diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -136,6 +136,10 @@ - no_sanitize("...") on a global variable for known but not relevant sanitizers is now just a warning. It now says that this will be ignored instead of incorrectly saying no_sanitize only applies to functions and methods. +- Clang will now give a new more accurate diagnostic for declaration of block + scope identifiers that have external/internal linkage that has an initializer. + Fixes `Issue 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 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5901,7 +5901,7 @@ : 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>; def err_variable_object_no_init : Error< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12773,8 +12773,11 @@ 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 --- a/clang/test/Parser/cxx1z-decomposition.cpp +++ b/clang/test/Parser/cxx1z-decomposition.cpp @@ -69,7 +69,7 @@ // 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 --- a/clang/test/Sema/array-init.c +++ b/clang/test/Sema/array-init.c @@ -48,7 +48,7 @@ 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 --- /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 --- a/clang/test/Sema/private-extern.c +++ b/clang/test/Sema/private-extern.c @@ -69,9 +69,9 @@ 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;