aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2013-01-16 23:11:15 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2013-01-16 23:11:15 +0000
commit2a5bb509e2d33a0f7aa4bb0ba53c73b5dfdd6bb4 (patch)
tree7c6012abbb1658a5d441bb07d58a7502fc6f7805
parent4f918aed75d4927e88365541c7200f0b5fe5014b (diff)
Check for internal weak decls after merging.
This fixes pr14946. The problem was that the linkage computation was done too early, so things like "extern int a;" would be given external linkage, even if a previous declaration was static. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172667 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDecl.cpp13
-rw-r--r--lib/Sema/SemaDeclAttr.cpp6
-rw-r--r--test/Sema/attr-weak.c6
-rw-r--r--test/SemaCXX/attr-weak.cpp7
4 files changed, 26 insertions, 6 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 994b212613..0316654660 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4312,6 +4312,15 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
return false;
}
+static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
+ // 'weak' only applies to declarations with external linkage.
+ WeakAttr *WA = ND.getAttr<WeakAttr>();
+ if (WA && ND.getLinkage() != ExternalLinkage) {
+ S.Diag(WA->getLocation(), diag::err_attribute_weak_static);
+ ND.dropAttr<WeakAttr>();
+ }
+}
+
NamedDecl*
Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo, LookupResult &Previous,
@@ -4590,6 +4599,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->setInvalidDecl();
}
+ checkAttributesAfterMerging(*this, *NewVD);
+
// If this is a locally-scoped extern C variable, update the map of
// such variables.
if (CurContext->isFunctionOrMethod() && NewVD->isExternC() &&
@@ -6056,6 +6067,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
+ checkAttributesAfterMerging(*this, *NewFD);
+
AddKnownFunctionAttributes(NewFD);
if (NewFD->hasAttr<OverloadableAttr>() &&
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 85f48ecff3..efeafa697f 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -2511,12 +2511,6 @@ static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) {
NamedDecl *nd = cast<NamedDecl>(D);
- // 'weak' only applies to declarations with external linkage.
- if (hasEffectivelyInternalLinkage(nd)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_weak_static);
- return;
- }
-
nd->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context));
}
diff --git a/test/Sema/attr-weak.c b/test/Sema/attr-weak.c
index adedf1231f..df74554487 100644
--- a/test/Sema/attr-weak.c
+++ b/test/Sema/attr-weak.c
@@ -16,3 +16,9 @@ static int x __attribute__((weak)); // expected-error {{weak declaration cannot
// rdar://9538608
int C; // expected-note {{previous definition is here}}
extern int C __attribute__((weak_import)); // expected-warning {{an already-declared variable is made a weak_import declaration}}
+
+static int pr14946_x;
+extern int pr14946_x __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}}
+
+static void pr14946_f();
+void pr14946_f() __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}}
diff --git a/test/SemaCXX/attr-weak.cpp b/test/SemaCXX/attr-weak.cpp
index b6a9e0aa84..8939a28d75 100644
--- a/test/SemaCXX/attr-weak.cpp
+++ b/test/SemaCXX/attr-weak.cpp
@@ -21,9 +21,16 @@ namespace {
};
}
+// GCC rejects the instantiation with the internal type, but some existing
+// code expects it. It is also not that different from giving hidden visibility
+// to parts of a template that have explicit default visibility, so we accept
+// this.
template <class T> struct Test7 {
void test7() __attribute__((weak)) {}
+ static int var __attribute__((weak));
};
+template <class T>
+int Test7<T>::var;
namespace { class Internal; }
template struct Test7<Internal>;
template struct Test7<int>;