Author: Richard Smith
Date: 2021-10-06T15:13:06-07:00
New Revision: 141df744564822b8d8250fe1bcec15cdbd5f213e

URL: 
https://github.com/llvm/llvm-project/commit/141df744564822b8d8250fe1bcec15cdbd5f213e
DIFF: 
https://github.com/llvm/llvm-project/commit/141df744564822b8d8250fe1bcec15cdbd5f213e.diff

LOG: Add missing diagnostic for use of _reserved name in extern "C"
declaration.

Names starting with an underscore are reserved at the global scope, so
cannot be used as the name of an extern "C" symbol in any scope because
such usages conflict with a name at global scope.

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Basic/IdentifierTable.h
    clang/lib/AST/Decl.cpp
    clang/test/SemaCXX/reserved-identifier.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 778ff67ce174..128ad047072e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -391,6 +391,7 @@ def warn_reserved_extern_symbol: Warning<
   "identifier %0 is reserved because %select{"
   "<ERROR>|" // ReservedIdentifierStatus::NotReserved
   "it starts with '_' at global scope|"
+  "it starts with '_' and has C language linkage|"
   "it starts with '__'|"
   "it starts with '_' followed by a capital letter|"
   "it contains '__'}1">,

diff  --git a/clang/include/clang/Basic/IdentifierTable.h 
b/clang/include/clang/Basic/IdentifierTable.h
index 803fec8df30c..19c967efcc42 100644
--- a/clang/include/clang/Basic/IdentifierTable.h
+++ b/clang/include/clang/Basic/IdentifierTable.h
@@ -43,6 +43,7 @@ class SourceLocation;
 enum class ReservedIdentifierStatus {
   NotReserved = 0,
   StartsWithUnderscoreAtGlobalScope,
+  StartsWithUnderscoreAndIsExternC,
   StartsWithDoubleUnderscore,
   StartsWithUnderscoreFollowedByCapitalLetter,
   ContainsDoubleUnderscore,
@@ -60,7 +61,8 @@ inline bool isReservedAtGlobalScope(ReservedIdentifierStatus 
Status) {
 /// example.
 inline bool isReservedInAllContexts(ReservedIdentifierStatus Status) {
   return Status != ReservedIdentifierStatus::NotReserved &&
-         Status != ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope;
+         Status != ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope 
&&
+         Status != ReservedIdentifierStatus::StartsWithUnderscoreAndIsExternC;
 }
 
 /// A simple pair of identifier info and location.

diff  --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 57d84f2c3439..acc0839dba75 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1089,12 +1089,28 @@ NamedDecl::isReserved(const LangOptions &LangOpts) 
const {
 
   ReservedIdentifierStatus Status = II->isReserved(LangOpts);
   if (isReservedAtGlobalScope(Status) && !isReservedInAllContexts(Status)) {
-    // Check if we're at TU level or not.
+    // This name is only reserved at global scope. Check if this declaration
+    // conflicts with a global scope declaration.
     if (isa<ParmVarDecl>(this) || isTemplateParameter())
       return ReservedIdentifierStatus::NotReserved;
+
+    // C++ [dcl.link]/7:
+    //   Two declarations [conflict] if [...] one declares a function or
+    //   variable with C language linkage, and the other declares [...] a
+    //   variable that belongs to the global scope.
+    //
+    // Therefore names that are reserved at global scope are also reserved as
+    // names of variables and functions with C language linkage.
     const DeclContext *DC = getDeclContext()->getRedeclContext();
-    if (!DC->isTranslationUnit())
-      return ReservedIdentifierStatus::NotReserved;
+    if (DC->isTranslationUnit())
+      return Status;
+    if (auto *VD = dyn_cast<VarDecl>(this))
+      if (VD->isExternC())
+        return ReservedIdentifierStatus::StartsWithUnderscoreAndIsExternC;
+    if (auto *FD = dyn_cast<FunctionDecl>(this))
+      if (FD->isExternC())
+        return ReservedIdentifierStatus::StartsWithUnderscoreAndIsExternC;
+    return ReservedIdentifierStatus::NotReserved;
   }
 
   return Status;

diff  --git a/clang/test/SemaCXX/reserved-identifier.cpp 
b/clang/test/SemaCXX/reserved-identifier.cpp
index 56fa3873359b..eaa5fe833033 100644
--- a/clang/test/SemaCXX/reserved-identifier.cpp
+++ b/clang/test/SemaCXX/reserved-identifier.cpp
@@ -105,3 +105,10 @@ struct Any {
 #define _Reserved // expected-warning {{macro name is a reserved identifier}}
 #undef _not_reserved
 #undef _Reserved // expected-warning {{macro name is a reserved identifier}}
+
+namespace N {
+  int _namespace_a;
+  extern "C" int _namespace_b; // expected-warning {{identifier '_namespace_b' 
is reserved because it starts with '_' and has C language linkage}}
+  void _namespace_c();
+  extern "C" void _namespace_d(); // expected-warning {{identifier 
'_namespace_d' is reserved because it starts with '_' and has C language 
linkage}}
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to