forked from OSchip/llvm-project
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:
parent
6b657aed33
commit
f768aa7613
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue