Author: serge-sans-paille Date: 2021-06-23T15:38:42+02:00 New Revision: a0d05ed848990c06c6dcdfc2e37bc8f13f7fe470
URL: https://github.com/llvm/llvm-project/commit/a0d05ed848990c06c6dcdfc2e37bc8f13f7fe470 DIFF: https://github.com/llvm/llvm-project/commit/a0d05ed848990c06c6dcdfc2e37bc8f13f7fe470.diff LOG: Handle interactions between reserved identifier and user-defined suffixes 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 Differential Revision: https://reviews.llvm.org/D104299 Added: Modified: clang/include/clang/Sema/Sema.h clang/lib/AST/Decl.cpp clang/lib/Parse/ParseExprCXX.cpp clang/lib/Sema/SemaExprCXX.cpp clang/test/Sema/reserved-identifier.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index db389922ae3a1..5a9ed8519e765 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4122,7 +4122,8 @@ class Sema final { bool RValueThis, unsigned ThisQuals); CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); - bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id); + bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id, + bool IsUDSuffix); LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys, bool AllowRaw, bool AllowTemplate, diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 0fbe8ec161910..5047dc19b0c6f 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1081,10 +1081,9 @@ bool NamedDecl::isLinkageValid() const { ReservedIdentifierStatus NamedDecl::isReserved(const LangOptions &LangOpts) const { const IdentifierInfo *II = getIdentifier(); - if (!II) - if (const auto *FD = dyn_cast<FunctionDecl>(this)) - II = FD->getLiteralIdentifier(); + // This triggers at least for CXXLiteralIdentifiers, which we already checked + // at lexing time. if (!II) return ReservedIdentifierStatus::NotReserved; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 93f578edc09e6..f3d10b4a08895 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -9,7 +9,6 @@ // This file implements the Expression parsing implementation for C++. // //===----------------------------------------------------------------------===// -#include "clang/Parse/Parser.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" @@ -17,6 +16,7 @@ #include "clang/Basic/PrettyStackTrace.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" @@ -2636,9 +2636,10 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // Grab the literal operator's suffix, which will be either the next token // or a ud-suffix from the string literal. + bool IsUDSuffix = !Literal.getUDSuffix().empty(); IdentifierInfo *II = nullptr; SourceLocation SuffixLoc; - if (!Literal.getUDSuffix().empty()) { + if (IsUDSuffix) { II = &PP.getIdentifierTable().get(Literal.getUDSuffix()); SuffixLoc = Lexer::AdvanceToTokenCharacter(TokLocs[Literal.getUDSuffixToken()], @@ -2675,7 +2676,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, Result.setLiteralOperatorId(II, KeywordLoc, SuffixLoc); - return Actions.checkLiteralOperatorId(SS, Result); + return Actions.checkLiteralOperatorId(SS, Result, IsUDSuffix); } // Parse a conversion-function-id. diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index a57c5ad198e1b..b0b6b3dca5f6a 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -484,8 +484,25 @@ ParsedType Sema::getDestructorTypeForDecltype(const DeclSpec &DS, } bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, - const UnqualifiedId &Name) { + const UnqualifiedId &Name, bool IsUDSuffix) { assert(Name.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId); + if (!IsUDSuffix) { + // [over.literal] p8 + // + // double operator""_Bq(long double); // OK: not a reserved identifier + // double operator"" _Bq(long double); // ill-formed, no diagnostic required + IdentifierInfo *II = Name.Identifier; + ReservedIdentifierStatus Status = II->isReserved(PP.getLangOpts()); + SourceLocation Loc = Name.getEndLoc(); + if (Status != ReservedIdentifierStatus::NotReserved && + !PP.getSourceManager().isInSystemHeader(Loc)) { + Diag(Loc, diag::warn_reserved_extern_symbol) + << II << static_cast<int>(Status) + << FixItHint::CreateReplacement( + Name.getSourceRange(), + (StringRef("operator\"\"") + II->getName()).str()); + } + } if (!SS.isValid()) return false; diff --git a/clang/test/Sema/reserved-identifier.cpp b/clang/test/Sema/reserved-identifier.cpp index 1992f6976c38f..1d3e0f9f0043f 100644 --- a/clang/test/Sema/reserved-identifier.cpp +++ b/clang/test/Sema/reserved-identifier.cpp @@ -76,11 +76,19 @@ namespace { int _barbatruc; // no-warning } -long double operator"" _BarbeBleue(long double) // expected-warning {{identifier 'operator""_BarbeBleue' is reserved because it starts with '_' followed by a capital letter}} +long double operator"" _BarbeBleue(long double) // expected-warning {{identifier '_BarbeBleue' is reserved because it starts with '_' followed by a capital letter}} { return 0.; } +long double operator""_SacreBleu(long double) // no-warning +{ + return 0.; +} + +long double sacrebleu = operator"" _SacreBleu(1.2); // expected-warning {{identifier '_SacreBleu' is reserved because it starts with '_' followed by a capital letter}} +long double sangbleu = operator""_SacreBleu(1.2); // no-warning + 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}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits