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 <j...@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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits