summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-02-10 06:50:24 +0000
committerJohn McCall <rjmccall@apple.com>2011-02-10 06:50:24 +0000
commitf768aa7613f0705bc32e226f12fe58be9fb5b0b7 (patch)
tree84ea1b7ad66bf5402dcc103a88c95205e6203124
parent6b657aed3365d6bf77b0eda4020eeea5661535e7 (diff)
downloadbcm5719-llvm-f768aa7613f0705bc32e226f12fe58be9fb5b0b7.tar.gz
bcm5719-llvm-f768aa7613f0705bc32e226f12fe58be9fb5b0b7.zip
Move the check that gives functions with unique-external types unique-external
linkage into Decl.cpp. Disable this logic for extern "C" functions, because the operative rule there is weaker. Fixes rdar://problem/8898466 llvm-svn: 125268
-rw-r--r--clang/lib/AST/ASTContext.cpp4
-rw-r--r--clang/lib/AST/Decl.cpp13
-rw-r--r--clang/test/SemaCXX/linkage.cpp11
-rw-r--r--clang/test/SemaCXX/warn-unused-filescoped.cpp10
4 files changed, 33 insertions, 5 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index d6c89c947ce..6b267432586 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -5859,10 +5859,6 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
GVALinkage External = GVA_StrongExternal;
Linkage L = FD->getLinkage();
- if (L == ExternalLinkage && getLangOptions().CPlusPlus &&
- FD->getType()->getLinkage() == UniqueExternalLinkage)
- L = UniqueExternalLinkage;
-
switch (L) {
case NoLinkage:
case InternalLinkage:
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 11614df5003..9aeb04fa448 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -392,6 +392,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
}
}
+ // In C++, then if the type of the function uses a type with
+ // unique-external linkage, it's not legally usable from outside
+ // this translation unit. However, we should use the C linkage
+ // rules instead for extern "C" declarations.
+ if (Context.getLangOptions().CPlusPlus && !Function->isExternC() &&
+ Function->getType()->getLinkage() == UniqueExternalLinkage)
+ return LinkageInfo::uniqueExternal();
+
if (FunctionTemplateSpecializationInfo *SpecInfo
= Function->getTemplateSpecializationInfo()) {
LV.merge(getLVForDecl(SpecInfo->getTemplate(),
@@ -512,6 +520,11 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
return LinkageInfo::uniqueExternal();
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ // If the type of the function uses a type with unique-external
+ // linkage, it's not legally usable from outside this translation unit.
+ if (MD->getType()->getLinkage() == UniqueExternalLinkage)
+ return LinkageInfo::uniqueExternal();
+
TemplateSpecializationKind TSK = TSK_Undeclared;
// If this is a method template specialization, use the linkage for
diff --git a/clang/test/SemaCXX/linkage.cpp b/clang/test/SemaCXX/linkage.cpp
index fb21f94e92e..ba56318fbd6 100644
--- a/clang/test/SemaCXX/linkage.cpp
+++ b/clang/test/SemaCXX/linkage.cpp
@@ -53,5 +53,16 @@ namespace test2 {
}
}
+namespace test3 {
+ namespace { struct A {}; }
+
+ // CHECK: define internal void @_ZN5test34testENS_12_GLOBAL__N_11AE(
+ void test(A a) {}
+ void force() { test(A()); }
+
+ // CHECK: define void @test3(
+ extern "C" void test3(A a) {}
+}
+
// CHECK: define linkonce_odr i8* @_ZN5test21A1BILj0EE3fooEv(
// CHECK: define linkonce_odr i8* @_ZN5test11A3fooILj0EEEPvv(
diff --git a/clang/test/SemaCXX/warn-unused-filescoped.cpp b/clang/test/SemaCXX/warn-unused-filescoped.cpp
index 628075ac04d..c32acb0b48b 100644
--- a/clang/test/SemaCXX/warn-unused-filescoped.cpp
+++ b/clang/test/SemaCXX/warn-unused-filescoped.cpp
@@ -66,7 +66,15 @@ namespace PR8841 {
template <typename T> void template_test(X<T> x) {
(void)(x == x);
}
- void test(X<int> x) {
+ void test() {
+ X<int> x;
template_test(x);
}
}
+
+namespace test4 {
+ namespace { struct A {}; }
+
+ void test(A a); // expected-warning {{unused function}}
+ extern "C" void test4(A a);
+}
OpenPOWER on IntegriCloud