forked from OSchip/llvm-project
Fixes a corner case bug whereby declaring and defining an extern variable in a
particular sequence causes its definition to not be generated in the object file. (fixes radar 8071804). llvm-svn: 106424
This commit is contained in:
parent
bbc29ea821
commit
cc99b3ca9e
|
@ -701,7 +701,15 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const {
|
||||||
// AST for 'extern "C" int foo;' is annotated with 'extern'.
|
// AST for 'extern "C" int foo;' is annotated with 'extern'.
|
||||||
if (hasExternalStorage())
|
if (hasExternalStorage())
|
||||||
return DeclarationOnly;
|
return DeclarationOnly;
|
||||||
|
|
||||||
|
if (getStorageClassAsWritten() == Extern ||
|
||||||
|
getStorageClassAsWritten() == PrivateExtern) {
|
||||||
|
for (const VarDecl *PrevVar = getPreviousDeclaration();
|
||||||
|
PrevVar; PrevVar = PrevVar->getPreviousDeclaration()) {
|
||||||
|
if (PrevVar->getLinkage() == InternalLinkage && PrevVar->hasInit())
|
||||||
|
return DeclarationOnly;
|
||||||
|
}
|
||||||
|
}
|
||||||
// C99 6.9.2p2:
|
// C99 6.9.2p2:
|
||||||
// A declaration of an object that has file scope without an initializer,
|
// A declaration of an object that has file scope without an initializer,
|
||||||
// and without a storage class specifier or the scs 'static', constitutes
|
// and without a storage class specifier or the scs 'static', constitutes
|
||||||
|
|
|
@ -1455,6 +1455,10 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (New->hasExternalStorage() &&
|
||||||
|
Old->getLinkage() == InternalLinkage)
|
||||||
|
New->setStorageClass(Old->getStorageClass());
|
||||||
|
|
||||||
// Keep a chain of previous declarations.
|
// Keep a chain of previous declarations.
|
||||||
New->setPreviousDeclaration(Old);
|
New->setPreviousDeclaration(Old);
|
||||||
|
|
||||||
|
|
|
@ -17,3 +17,40 @@ Anon anon1;
|
||||||
// CHECK: @anon2 = internal global
|
// CHECK: @anon2 = internal global
|
||||||
X<Anon> anon2;
|
X<Anon> anon2;
|
||||||
|
|
||||||
|
// rdar: // 8071804
|
||||||
|
char const * const xyzzy = "Hello, world!";
|
||||||
|
extern char const * const xyzzy;
|
||||||
|
|
||||||
|
char const * const *test1()
|
||||||
|
{
|
||||||
|
// CHECK: @_ZL5xyzzy = internal constant
|
||||||
|
return &xyzzy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char const * const static_xyzzy = "Hello, world!";
|
||||||
|
extern char const * const static_xyzzy;
|
||||||
|
|
||||||
|
char const * const *test2()
|
||||||
|
{
|
||||||
|
// CHECK: @_ZL12static_xyzzy = internal constant
|
||||||
|
return &static_xyzzy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char const * static_nonconst_xyzzy = "Hello, world!";
|
||||||
|
extern char const * static_nonconst_xyzzy;
|
||||||
|
|
||||||
|
char const * *test3()
|
||||||
|
{
|
||||||
|
// CHECK: @_ZL21static_nonconst_xyzzy = internal global
|
||||||
|
return &static_nonconst_xyzzy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char const * extern_nonconst_xyzzy = "Hello, world!";
|
||||||
|
extern char const * extern_nonconst_xyzzy;
|
||||||
|
|
||||||
|
char const * *test4()
|
||||||
|
{
|
||||||
|
// CHECK: @extern_nonconst_xyzzy = global
|
||||||
|
return &extern_nonconst_xyzzy;
|
||||||
|
}
|
||||||
|
|
|
@ -58,5 +58,5 @@ int *p=&g19; // expected-error{{use of undeclared identifier 'g19'}} \
|
||||||
|
|
||||||
// PR3645
|
// PR3645
|
||||||
static int a;
|
static int a;
|
||||||
extern int a;
|
extern int a; // expected-note {{previous definition is here}}
|
||||||
int a;
|
int a; // expected-error {{non-static declaration of 'a' follows static declaration}}
|
||||||
|
|
Loading…
Reference in New Issue