[clang] 1d51bb8 - [Clang] Reword diagnostic for scope identifier with linkage

Jun Zhang via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 12 07:41:44 PDT 2022


Author: Jun Zhang
Date: 2022-09-12T22:40:54+08:00
New Revision: 1d51bb824f25140a5b1aa783f6860ac3e7f7d16d

URL: https://github.com/llvm/llvm-project/commit/1d51bb824f25140a5b1aa783f6860ac3e7f7d16d
DIFF: https://github.com/llvm/llvm-project/commit/1d51bb824f25140a5b1aa783f6860ac3e7f7d16d.diff

LOG: [Clang] Reword diagnostic for scope identifier with linkage

If the declaration of an identifier has block scope, and the identifier has
external or internal linkage, the declaration shall have no initializer for
the identifier.

Clang now gives a more suitable diagnosis for this case.
Fixes https://github.com/llvm/llvm-project/issues/57478

Signed-off-by: Jun Zhang <jun at junz.org>

 Differential Revision: https://reviews.llvm.org/D133088

Added: 
    clang/test/Sema/err-decl-block-extern-no-init.c

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaDecl.cpp
    clang/test/Parser/cxx1z-decomposition.cpp
    clang/test/Sema/array-init.c
    clang/test/Sema/private-extern.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 75a57c5d18d8b..30402411178d4 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -138,6 +138,9 @@ Improvements to Clang's diagnostics
   incorrectly saying no_sanitize only applies to functions and methods.
 - No longer mention ``reinterpet_cast`` in the invalid constant expression
   diagnostic note when in C mode.
+- Clang will now give a more suitale diagnostic for declaration of block
+  scope identifiers that have external/internal linkage that has an initializer.
+  Fixes `Issue 57478: <https://github.com/llvm/llvm-project/issues/57478>`_.
 
 Non-comprehensive list of changes in this release
 -------------------------------------------------

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 76e18c9deff46..016affb1b3236 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5901,7 +5901,7 @@ def err_loader_uninitialized_extern_decl
     : Error<"variable %0 cannot be declared both 'extern' and with the "
             "'loader_uninitialized' attribute">;
 def err_block_extern_cant_init : Error<
-  "'extern' variable cannot have an initializer">;
+  "declaration of block scope identifier with linkage cannot have an initializer">;
 def warn_extern_init : Warning<"'extern' variable has an initializer">,
   InGroup<DiagGroup<"extern-initializer">>;
 def err_variable_object_no_init : Error<

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 2ad6edc121ae9..6e94da4a115eb 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12773,8 +12773,11 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
     return;
   }
 
+  // C99 6.7.8p5. If the declaration of an identifier has block scope, and
+  // the identifier has external or internal linkage, the declaration shall
+  // have no initializer for the identifier.
+  // C++14 [dcl.init]p5 is the same restriction for C++.
   if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) {
-    // C99 6.7.8p5. C++ has no such restriction, but that is a defect.
     Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
     VDecl->setInvalidDecl();
     return;

diff  --git a/clang/test/Parser/cxx1z-decomposition.cpp b/clang/test/Parser/cxx1z-decomposition.cpp
index 7abf1f9cdac56..10ef464bda50c 100644
--- a/clang/test/Parser/cxx1z-decomposition.cpp
+++ b/clang/test/Parser/cxx1z-decomposition.cpp
@@ -69,7 +69,7 @@ namespace BadSpecifiers {
     // storage-class-specifiers
     static auto &[a] = n; // expected-warning {{declared 'static' is a C++20 extension}}
     thread_local auto &[b] = n; // expected-warning {{declared 'thread_local' is a C++20 extension}}
-    extern auto &[c] = n; // expected-error {{cannot be declared 'extern'}} expected-error {{cannot have an initializer}}
+    extern auto &[c] = n; // expected-error {{cannot be declared 'extern'}} expected-error {{declaration of block scope identifier with linkage cannot have an initializer}}
     struct S {
       mutable auto &[d] = n; // expected-error {{not permitted in this context}}
 

diff  --git a/clang/test/Sema/array-init.c b/clang/test/Sema/array-init.c
index ae3ce73ccc7a3..fcc3c13bc91da 100644
--- a/clang/test/Sema/array-init.c
+++ b/clang/test/Sema/array-init.c
@@ -48,7 +48,7 @@ void func(void) {
 
   struct threeElements *p = 7; // expected-error{{incompatible integer to pointer conversion initializing 'struct threeElements *' with an expression of type 'int'}}
 
-  extern int blockScopeExtern[3] = { 1, 3, 5 }; // expected-error{{'extern' variable cannot have an initializer}}
+  extern int blockScopeExtern[3] = { 1, 3, 5 }; // expected-error{{declaration of block scope identifier with linkage cannot have an initializer}}
 
   static long x2[3] = { 1.0,
                         "abc", // expected-error{{incompatible pointer to integer conversion initializing 'long' with an expression of type 'char[4]'}}

diff  --git a/clang/test/Sema/err-decl-block-extern-no-init.c b/clang/test/Sema/err-decl-block-extern-no-init.c
new file mode 100644
index 0000000000000..78a8befd0ca78
--- /dev/null
+++ b/clang/test/Sema/err-decl-block-extern-no-init.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s
+static int x;
+
+void foo(void)
+{
+    extern int x = 1; // expected-error {{declaration of block scope identifier with linkage cannot have an initializer}}
+}
+
+int y;
+
+void bar(void)
+{
+    extern int y = 1; // expected-error {{declaration of block scope identifier with linkage cannot have an initializer}}
+
+}

diff  --git a/clang/test/Sema/private-extern.c b/clang/test/Sema/private-extern.c
index 8c7fd18f36fd8..7e7fb27416aa8 100644
--- a/clang/test/Sema/private-extern.c
+++ b/clang/test/Sema/private-extern.c
@@ -69,9 +69,9 @@ void f8(void) {
 struct s0 { int x; };
 
 void f9(void) {
-  extern int g15 = 0; // expected-error{{'extern' variable cannot have an initializer}}
+  extern int g15 = 0; // expected-error{{declaration of block scope identifier with linkage cannot have an initializer}}
   // FIXME: linkage specifier in warning.
-  __private_extern__ int g16 = 0; // expected-error{{'extern' variable cannot have an initializer}}
+  __private_extern__ int g16 = 0; // expected-error{{declaration of block scope identifier with linkage cannot have an initializer}}
 }
 
 extern int g17;


        


More information about the cfe-commits mailing list