PR50644: Do not warn on a declaration of `operator"" _foo`.
authorRichard Smith <richard@metafoo.co.uk>
Wed, 6 Oct 2021 21:11:32 +0000 (14:11 -0700)
committerRichard Smith <richard@metafoo.co.uk>
Wed, 6 Oct 2021 22:13:05 +0000 (15:13 -0700)
Also do not warn on `#define _foo` or `#undef _foo`.

Only global scope names starting with _[a-z] are reserved, not the use
of such an identifier in any other context.

clang/include/clang/Basic/IdentifierTable.h
clang/lib/AST/Decl.cpp
clang/lib/Lex/PPDirectives.cpp
clang/lib/Sema/SemaCodeComplete.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaStmt.cpp
clang/test/Sema/reserved-identifier.c
clang/test/SemaCXX/reserved-identifier.cpp [moved from clang/test/Sema/reserved-identifier.cpp with 93% similarity]

index d620138..803fec8 100644 (file)
@@ -48,6 +48,21 @@ enum class ReservedIdentifierStatus {
   ContainsDoubleUnderscore,
 };
 
+/// Determine whether an identifier is reserved for use as a name at global
+/// scope. Such identifiers might be implementation-specific global functions
+/// or variables.
+inline bool isReservedAtGlobalScope(ReservedIdentifierStatus Status) {
+  return Status != ReservedIdentifierStatus::NotReserved;
+}
+
+/// Determine whether an identifier is reserved in all contexts. Such
+/// identifiers might be implementation-specific keywords or macros, for
+/// example.
+inline bool isReservedInAllContexts(ReservedIdentifierStatus Status) {
+  return Status != ReservedIdentifierStatus::NotReserved &&
+         Status != ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope;
+}
+
 /// A simple pair of identifier info and location.
 using IdentifierLocPair = std::pair<IdentifierInfo *, SourceLocation>;
 
index 6788f21..57d84f2 100644 (file)
@@ -1088,7 +1088,7 @@ NamedDecl::isReserved(const LangOptions &LangOpts) const {
     return ReservedIdentifierStatus::NotReserved;
 
   ReservedIdentifierStatus Status = II->isReserved(LangOpts);
-  if (Status == ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope) {
+  if (isReservedAtGlobalScope(Status) && !isReservedInAllContexts(Status)) {
     // Check if we're at TU level or not.
     if (isa<ParmVarDecl>(this) || isTemplateParameter())
       return ReservedIdentifierStatus::NotReserved;
index b53ff12..e77b389 100644 (file)
@@ -129,7 +129,7 @@ static bool isForModuleBuilding(Module *M, StringRef CurrentModule,
 
 static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II) {
   const LangOptions &Lang = PP.getLangOpts();
-  if (II->isReserved(Lang) != ReservedIdentifierStatus::NotReserved) {
+  if (isReservedInAllContexts(II->isReserved(Lang))) {
     // list from:
     // - https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_macros.html
     // - https://docs.microsoft.com/en-us/cpp/c-runtime-library/security-features-in-the-crt?view=msvc-160
@@ -183,7 +183,7 @@ static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II) {
 static MacroDiag shouldWarnOnMacroUndef(Preprocessor &PP, IdentifierInfo *II) {
   const LangOptions &Lang = PP.getLangOpts();
   // Do not warn on keyword undef.  It is generally harmless and widely used.
-  if (II->isReserved(Lang) != ReservedIdentifierStatus::NotReserved)
+  if (isReservedInAllContexts(II->isReserved(Lang)))
     return MD_ReservedMacro;
   return MD_NoWarn;
 }
index 610c64d..2186eec 100644 (file)
@@ -743,9 +743,7 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
 static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
   ReservedIdentifierStatus Status = ND->isReserved(SemaRef.getLangOpts());
   // Ignore reserved names for compiler provided decls.
-  if ((Status != ReservedIdentifierStatus::NotReserved) &&
-      (Status != ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope) &&
-      ND->getLocation().isInvalid())
+  if (isReservedInAllContexts(Status) && ND->getLocation().isInvalid())
     return true;
 
   // For system headers ignore only double-underscore names.
index 1b4c49d..8e2a549 100644 (file)
@@ -494,7 +494,7 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
     IdentifierInfo *II = Name.Identifier;
     ReservedIdentifierStatus Status = II->isReserved(PP.getLangOpts());
     SourceLocation Loc = Name.getEndLoc();
-    if (Status != ReservedIdentifierStatus::NotReserved &&
+    if (isReservedInAllContexts(Status) &&
         !PP.getSourceManager().isInSystemHeader(Loc)) {
       Diag(Loc, diag::warn_reserved_extern_symbol)
           << II << static_cast<int>(Status)
index 529f814..c83ada8 100644 (file)
@@ -547,7 +547,7 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
   }
 
   ReservedIdentifierStatus Status = TheDecl->isReserved(getLangOpts());
-  if (Status != ReservedIdentifierStatus::NotReserved &&
+  if (isReservedInAllContexts(Status) &&
       !Context.getSourceManager().isInSystemHeader(IdentLoc))
     Diag(IdentLoc, diag::warn_reserved_extern_symbol)
         << TheDecl << static_cast<int>(Status);
index 2ee7fc6..746b477 100644 (file)
@@ -16,6 +16,8 @@ void foo(unsigned int _Reserved) { // expected-warning {{identifier '_Reserved'
   goto __reserved;                 // expected-warning {{identifier '__reserved' is reserved because it starts with '__'}}
 __reserved: // expected-warning {{identifier '__reserved' is reserved because it starts with '__'}}
             ;
+  goto _not_reserved;
+_not_reserved: ;
 }
 
 void foot(unsigned int _not_reserved) {} // no-warning
similarity index 93%
rename from clang/test/Sema/reserved-identifier.cpp
rename to clang/test/SemaCXX/reserved-identifier.cpp
index 1d3e0f9..56fa387 100644 (file)
@@ -89,6 +89,9 @@ long double operator""_SacreBleu(long double) // no-warning
 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
 
+void operator"" _lowercase(unsigned long long); // no-warning
+void operator""_lowercase(unsigned long long); // 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}}
@@ -97,3 +100,8 @@ struct _BarbeNoire { // expected-warning {{identifier '_BarbeNoire' is reserved
 struct Any {
   friend void _barbegrise(); // expected-warning {{identifier '_barbegrise' is reserved because it starts with '_' at global scope}}
 };
+
+#define _not_reserved
+#define _Reserved // expected-warning {{macro name is a reserved identifier}}
+#undef _not_reserved
+#undef _Reserved // expected-warning {{macro name is a reserved identifier}}