From af8ca37a7fa45bff84831706c6d85f9e5b4e1d15 Mon Sep 17 00:00:00 2001 From: John McCall <rjmccall@apple.com> Date: Thu, 10 Feb 2011 06:50:24 +0000 Subject: [PATCH] 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 --- lib/AST/ASTContext.cpp | 4 ---- lib/AST/Decl.cpp | 13 +++++++++++++ test/SemaCXX/linkage.cpp | 11 +++++++++++ test/SemaCXX/warn-unused-filescoped.cpp | 10 +++++++++- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d6c89c947ce..6b267432586 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 11614df5003..9aeb04fa448 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 fb21f94e92e..ba56318fbd6 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 628075ac04d..c32acb0b48b 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); +} -- GitLab