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
This commit is contained in:
John McCall 2011-02-10 06:50:24 +00:00
parent 6b657aed33
commit f768aa7613
4 changed files with 33 additions and 5 deletions

View File

@ -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:

View File

@ -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

View File

@ -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(

View File

@ -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);
}