forked from OSchip/llvm-project
[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:
parent
e4f4542517
commit
1d51bb824f
|
@ -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
|
||||
-------------------------------------------------
|
||||
|
|
|
@ -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<
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}}
|
||||
|
||||
|
|
|
@ -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]'}}
|
||||
|
|
|
@ -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}}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue