serge-sans-paille created this revision. serge-sans-paille added reviewers: aaron.ballman, rsmith. Herald added a subscriber: dexonsmith. serge-sans-paille requested review of this revision. Herald added a reviewer: jdoerfert. Herald added subscribers: cfe-commits, sstefan1. Herald added a project: clang.
According to https://eel.is/c++draft/over.literal > double operator""_Bq(long double); // OK: does not use the reserved > identifier _Bq ([lex.name]) > double operator"" _Bq(long double); // ill-formed, no diagnostic required: > uses the reserved identifier _Bq ([lex.name]) Obey that rule by keeping track of the operator literal name status wrt. leading whitespace. Fix: https://bugs.llvm.org/show_bug.cgi?id=50644 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D104299 Files: clang/include/clang/Basic/IdentifierTable.h clang/lib/Basic/IdentifierTable.cpp clang/lib/Parse/ParseExprCXX.cpp clang/test/Sema/reserved-identifier.cpp Index: clang/test/Sema/reserved-identifier.cpp =================================================================== --- clang/test/Sema/reserved-identifier.cpp +++ clang/test/Sema/reserved-identifier.cpp @@ -81,6 +81,11 @@ return 0.; } +long double operator""_SacreBleue(long double) // no-warning +{ + return 0.; +} + struct _BarbeRouge { // expected-warning {{identifier '_BarbeRouge' is reserved because it starts with '_' followed by a capital letter}} } p; struct _BarbeNoire { // expected-warning {{identifier '_BarbeNoire' is reserved because it starts with '_' followed by a capital letter}} Index: clang/lib/Parse/ParseExprCXX.cpp =================================================================== --- clang/lib/Parse/ParseExprCXX.cpp +++ clang/lib/Parse/ParseExprCXX.cpp @@ -2644,6 +2644,7 @@ Lexer::AdvanceToTokenCharacter(TokLocs[Literal.getUDSuffixToken()], Literal.getUDSuffixOffset(), PP.getSourceManager(), getLangOpts()); + II->setLiteralOperatorWithoutWhitespace(true); } else if (Tok.is(tok::identifier)) { II = Tok.getIdentifierInfo(); SuffixLoc = ConsumeToken(); Index: clang/lib/Basic/IdentifierTable.cpp =================================================================== --- clang/lib/Basic/IdentifierTable.cpp +++ clang/lib/Basic/IdentifierTable.cpp @@ -285,6 +285,11 @@ if (Name.size() <= 1) return ReservedIdentifierStatus::NotReserved; + // [over.literal] p8 + llvm::errs() << Name << " isLiteralOperatorWithoutWhitespace: " << isLiteralOperatorWithoutWhitespace() << "\n"; + if(isLiteralOperatorWithoutWhitespace()) + return ReservedIdentifierStatus::NotReserved; + // [lex.name] p3 if (Name[0] == '_') { Index: clang/include/clang/Basic/IdentifierTable.h =================================================================== --- clang/include/clang/Basic/IdentifierTable.h +++ clang/include/clang/Basic/IdentifierTable.h @@ -121,7 +121,10 @@ // True if this is a mangled OpenMP variant name. unsigned IsMangledOpenMPVariantName : 1; - // 28 bits left in a 64-bit word. + // True if this identifier is a literal operator without whitespace. + unsigned IsLiteralOperatorWithoutWhitespace : 1; + + // 27 bits left in a 64-bit word. // Managed by the language front-end. void *FETokenInfo = nullptr; @@ -134,7 +137,8 @@ IsPoisoned(false), IsCPPOperatorKeyword(false), NeedsHandleIdentifier(false), IsFromAST(false), ChangedAfterLoad(false), FEChangedAfterLoad(false), RevertedTokenID(false), OutOfDate(false), - IsModulesImport(false), IsMangledOpenMPVariantName(false) {} + IsModulesImport(false), IsMangledOpenMPVariantName(false), + IsLiteralOperatorWithoutWhitespace(false) {} public: IdentifierInfo(const IdentifierInfo &) = delete; @@ -378,6 +382,16 @@ /// Set whether this is the mangled name of an OpenMP variant. void setMangledOpenMPVariantName(bool I) { IsMangledOpenMPVariantName = I; } + /// Determine whether this is a literal operator without whitespace + bool isLiteralOperatorWithoutWhitespace() const { + return IsLiteralOperatorWithoutWhitespace; + } + + /// Set whether this is a literal operator without whitespace. + void setLiteralOperatorWithoutWhitespace(bool I) { + IsLiteralOperatorWithoutWhitespace = I; + } + /// Return true if this identifier is an editor placeholder. /// /// Editor placeholders are produced by the code-completion engine and are
Index: clang/test/Sema/reserved-identifier.cpp =================================================================== --- clang/test/Sema/reserved-identifier.cpp +++ clang/test/Sema/reserved-identifier.cpp @@ -81,6 +81,11 @@ return 0.; } +long double operator""_SacreBleue(long double) // no-warning +{ + return 0.; +} + struct _BarbeRouge { // expected-warning {{identifier '_BarbeRouge' is reserved because it starts with '_' followed by a capital letter}} } p; struct _BarbeNoire { // expected-warning {{identifier '_BarbeNoire' is reserved because it starts with '_' followed by a capital letter}} Index: clang/lib/Parse/ParseExprCXX.cpp =================================================================== --- clang/lib/Parse/ParseExprCXX.cpp +++ clang/lib/Parse/ParseExprCXX.cpp @@ -2644,6 +2644,7 @@ Lexer::AdvanceToTokenCharacter(TokLocs[Literal.getUDSuffixToken()], Literal.getUDSuffixOffset(), PP.getSourceManager(), getLangOpts()); + II->setLiteralOperatorWithoutWhitespace(true); } else if (Tok.is(tok::identifier)) { II = Tok.getIdentifierInfo(); SuffixLoc = ConsumeToken(); Index: clang/lib/Basic/IdentifierTable.cpp =================================================================== --- clang/lib/Basic/IdentifierTable.cpp +++ clang/lib/Basic/IdentifierTable.cpp @@ -285,6 +285,11 @@ if (Name.size() <= 1) return ReservedIdentifierStatus::NotReserved; + // [over.literal] p8 + llvm::errs() << Name << " isLiteralOperatorWithoutWhitespace: " << isLiteralOperatorWithoutWhitespace() << "\n"; + if(isLiteralOperatorWithoutWhitespace()) + return ReservedIdentifierStatus::NotReserved; + // [lex.name] p3 if (Name[0] == '_') { Index: clang/include/clang/Basic/IdentifierTable.h =================================================================== --- clang/include/clang/Basic/IdentifierTable.h +++ clang/include/clang/Basic/IdentifierTable.h @@ -121,7 +121,10 @@ // True if this is a mangled OpenMP variant name. unsigned IsMangledOpenMPVariantName : 1; - // 28 bits left in a 64-bit word. + // True if this identifier is a literal operator without whitespace. + unsigned IsLiteralOperatorWithoutWhitespace : 1; + + // 27 bits left in a 64-bit word. // Managed by the language front-end. void *FETokenInfo = nullptr; @@ -134,7 +137,8 @@ IsPoisoned(false), IsCPPOperatorKeyword(false), NeedsHandleIdentifier(false), IsFromAST(false), ChangedAfterLoad(false), FEChangedAfterLoad(false), RevertedTokenID(false), OutOfDate(false), - IsModulesImport(false), IsMangledOpenMPVariantName(false) {} + IsModulesImport(false), IsMangledOpenMPVariantName(false), + IsLiteralOperatorWithoutWhitespace(false) {} public: IdentifierInfo(const IdentifierInfo &) = delete; @@ -378,6 +382,16 @@ /// Set whether this is the mangled name of an OpenMP variant. void setMangledOpenMPVariantName(bool I) { IsMangledOpenMPVariantName = I; } + /// Determine whether this is a literal operator without whitespace + bool isLiteralOperatorWithoutWhitespace() const { + return IsLiteralOperatorWithoutWhitespace; + } + + /// Set whether this is a literal operator without whitespace. + void setLiteralOperatorWithoutWhitespace(bool I) { + IsLiteralOperatorWithoutWhitespace = I; + } + /// Return true if this identifier is an editor placeholder. /// /// Editor placeholders are produced by the code-completion engine and are
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits