[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@junz.org>

 Differential Revision: https://reviews.llvm.org/D133088
This commit is contained in:
Jun Zhang 2022-09-12 22:21:17 +08:00
parent e4f4542517
commit 1d51bb824f
No known key found for this signature in database
GPG Key ID: E19904830B621534
7 changed files with 27 additions and 6 deletions

View File

@ -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
-------------------------------------------------

View File

@ -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<

View File

@ -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;

View File

@ -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}}

View File

@ -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]'}}

View File

@ -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}}
}

View File

@ -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;