aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2012-12-18 04:18:55 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2012-12-18 04:18:55 +0000
commita7a2f2a96dc9d2e66a5e6ee7ca50cb04931f4c98 (patch)
tree32e3e3e4d0db14c7fb503f4866fce4e5bb820339
parent853c37018bd4c6f1a2118568d5ac59525f2a3b51 (diff)
Merge storage classes even when contexts don't match.
This fixes the storage class of extern decls that are merged with file level statics. The patch also fixes the linkage computation so that they are considered internal. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@170406 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/Decl.cpp8
-rw-r--r--lib/Sema/SemaDecl.cpp3
-rw-r--r--test/Index/linkage.c8
3 files changed, 15 insertions, 4 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 4e4bc0ec80..a2c6da67f0 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -786,12 +786,16 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) {
}
if (const VarDecl *Var = dyn_cast<VarDecl>(D))
- if (Var->getStorageClass() == SC_Extern ||
- Var->getStorageClass() == SC_PrivateExtern) {
+ if (Var->getStorageClassAsWritten() == SC_Extern ||
+ Var->getStorageClassAsWritten() == SC_PrivateExtern) {
if (Var->isInAnonymousNamespace() &&
!Var->getDeclContext()->isExternCContext())
return LinkageInfo::uniqueExternal();
+ // This is an "extern int foo;" which got merged with a file static.
+ if (Var->getStorageClass() == SC_Static)
+ return LinkageInfo::internal();
+
LinkageInfo LV;
if (Var->getStorageClass() == SC_PrivateExtern)
LV.mergeVisibility(HiddenVisibility, true);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 4bccc1c987..7f98c3359c 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2616,8 +2616,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// specified at the prior declaration.
// FIXME. revisit this code.
if (New->hasExternalStorage() &&
- Old->getLinkage() == InternalLinkage &&
- New->getDeclContext() == Old->getDeclContext())
+ Old->getLinkage() == InternalLinkage)
New->setStorageClass(Old->getStorageClass());
// Merge "used" flag.
diff --git a/test/Index/linkage.c b/test/Index/linkage.c
index 41a1fbdd71..ab006590b6 100644
--- a/test/Index/linkage.c
+++ b/test/Index/linkage.c
@@ -13,6 +13,12 @@ static int wibble(int);
void ena(int (*dio)(int tria));
+static int test2;
+void f16(void) {
+ extern int test2;
+}
+
+
// CHECK: EnumDecl=Baz:3:6 (Definition)linkage=External
// CHECK: EnumConstantDecl=Qux:3:12 (Definition)linkage=External
// CHECK: VarDecl=x:4:5linkage=External
@@ -28,3 +34,5 @@ void ena(int (*dio)(int tria));
// CHECK: FunctionDecl=ena:14:6linkage=External
// CHECK: ParmDecl=dio:14:16 (Definition)linkage=NoLinkage
// CHECK: ParmDecl=tria:14:25 (Definition)linkage=NoLinkage
+// CHECK: VarDecl=test2{{.*}}linkage=Internal
+// CHECK: VarDecl=test2{{.*}}linkage=Internal