aboutsummaryrefslogtreecommitdiff
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
commitaf8ca37a7fa45bff84831706c6d85f9e5b4e1d15 (patch)
tree107ceb05aed012ae20b7e5f587bee3c52f09ee9b
parentb5fb7e018c079c0a4bdec024b640ca03f2da1f26 (diff)
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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125268 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ASTContext.cpp4
-rw-r--r--lib/AST/Decl.cpp13
-rw-r--r--test/SemaCXX/linkage.cpp11
-rw-r--r--test/SemaCXX/warn-unused-filescoped.cpp10
4 files changed, 33 insertions, 5 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index d6c89c947c..6b26743258 100644
--- a/lib/AST/ASTContext.cpp
+++ b/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/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 11614df500..9aeb04fa44 100644
--- a/lib/AST/Decl.cpp
+++ b/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/test/SemaCXX/linkage.cpp b/test/SemaCXX/linkage.cpp
index fb21f94e92..ba56318fbd 100644
--- a/test/SemaCXX/linkage.cpp
+++ b/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/test/SemaCXX/warn-unused-filescoped.cpp b/test/SemaCXX/warn-unused-filescoped.cpp
index 628075ac04..c32acb0b48 100644
--- a/test/SemaCXX/warn-unused-filescoped.cpp
+++ b/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);
+}