diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 0170b08cd7ed..419856ff50e9 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -97,6 +97,12 @@ static Linkage getLinkageForTemplateArgumentList(const TemplateArgument *Args, return L; } +static Linkage +getLinkageForTemplateArgumentList(const TemplateArgumentList &TArgs) { + return getLinkageForTemplateArgumentList(TArgs.getFlatArgumentList(), + TArgs.flat_size()); +} + static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) { assert(D->getDeclContext()->getLookupContext()->isFileContext() && "Not a name having namespace scope"); @@ -219,10 +225,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) { = Function->getTemplateSpecializationInfo()) { Linkage L = SpecInfo->getTemplate()->getLinkage(); const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments; - L = minLinkage(L, - getLinkageForTemplateArgumentList( - TemplateArgs.getFlatArgumentList(), - TemplateArgs.flat_size())); + L = minLinkage(L, getLinkageForTemplateArgumentList(TemplateArgs)); return L; } @@ -245,9 +248,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) { if (const ClassTemplateSpecializationDecl *Spec = dyn_cast(Tag)) { const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - Linkage L = getLinkageForTemplateArgumentList( - TemplateArgs.getFlatArgumentList(), - TemplateArgs.flat_size()); + Linkage L = getLinkageForTemplateArgumentList(TemplateArgs); return minLinkage(L, Spec->getSpecializedTemplate()->getLinkage()); } @@ -279,6 +280,47 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) { return NoLinkage; } +static Linkage getLinkageForClassMember(const NamedDecl *D) { + if (!(isa(D) || + isa(D) || + (isa(D) && + (D->getDeclName() || cast(D)->getTypedefForAnonDecl())))) + return NoLinkage; + + // Class members only have linkage if their class has external linkage. + Linkage L = cast(D->getDeclContext())->getLinkage(); + if (!isExternalLinkage(L)) return NoLinkage; + + // If the class already has unique-external linkage, we can't improve. + if (L == UniqueExternalLinkage) return UniqueExternalLinkage; + + // If this is a method template specialization, use the linkage for + // the template parameters and arguments. + if (const CXXMethodDecl *MD = dyn_cast(D)) { + if (FunctionTemplateSpecializationInfo *SpecInfo + = MD->getTemplateSpecializationInfo()) { + Linkage ArgLinkage = + getLinkageForTemplateArgumentList(*SpecInfo->TemplateArguments); + Linkage ParamLinkage = + getLinkageForTemplateParameterList( + SpecInfo->getTemplate()->getTemplateParameters()); + return minLinkage(ArgLinkage, ParamLinkage); + } + + // Similarly for member class template specializations. + } else if (const ClassTemplateSpecializationDecl *Spec + = dyn_cast(D)) { + Linkage ArgLinkage = + getLinkageForTemplateArgumentList(Spec->getTemplateArgs()); + Linkage ParamLinkage = + getLinkageForTemplateParameterList( + Spec->getSpecializedTemplate()->getTemplateParameters()); + return minLinkage(ArgLinkage, ParamLinkage); + } + + return ExternalLinkage; +} + Linkage NamedDecl::getLinkage() const { // Objective-C: treat all Objective-C declarations as having external @@ -314,14 +356,8 @@ Linkage NamedDecl::getLinkage() const { // that the class or enumeration has the typedef name for linkage // purposes (7.1.3), has external linkage if the name of the class // has external linkage. - if (getDeclContext()->isRecord() && - (isa(this) || isa(this) || - (isa(this) && - (getDeclName() || cast(this)->getTypedefForAnonDecl())))) { - Linkage L = cast(getDeclContext())->getLinkage(); - if (isExternalLinkage(L)) - return L; - } + if (getDeclContext()->isRecord()) + return getLinkageForClassMember(this); // C++ [basic.link]p6: // The name of a function declared in block scope and the name of diff --git a/clang/test/CodeGenCXX/anonymous-namespaces.cpp b/clang/test/CodeGenCXX/anonymous-namespaces.cpp index fb3470ca9bee..3ec7032ee5f5 100644 --- a/clang/test/CodeGenCXX/anonymous-namespaces.cpp +++ b/clang/test/CodeGenCXX/anonymous-namespaces.cpp @@ -1,12 +1,14 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm %s -o - > %t +// RUN: FileCheck %s -check-prefix=1 < %t +// RUN: FileCheck %s -check-prefix=2 < %t int f(); namespace { - // CHECK: @_ZN12_GLOBAL__N_11bE = internal global i32 0 - // CHECK: @_ZN12_GLOBAL__N_1L1cE = internal global i32 0 - // CHECK: @_ZN12_GLOBAL__N_11D1dE = internal global i32 0 - // CHECK: @_ZN12_GLOBAL__N_11aE = internal global i32 0 + // CHECK-1: @_ZN12_GLOBAL__N_11bE = internal global i32 0 + // CHECK-1: @_ZN12_GLOBAL__N_1L1cE = internal global i32 0 + // CHECK-1: @_ZN12_GLOBAL__N_11D1dE = internal global i32 0 + // CHECK-1: @_ZN12_GLOBAL__N_11aE = internal global i32 0 int a = 0; int b = f(); @@ -20,18 +22,18 @@ namespace { int D::d = f(); // Check for generation of a VTT with internal linkage - // CHECK: @_ZTSN12_GLOBAL__N_11X1EE = internal constant + // CHECK-1: @_ZTSN12_GLOBAL__N_11X1EE = internal constant struct X { struct EBase { }; struct E : public virtual EBase { virtual ~E() {} }; }; - // CHECK: define internal i32 @_ZN12_GLOBAL__N_13fooEv() + // CHECK-1: define internal i32 @_ZN12_GLOBAL__N_13fooEv() int foo() { return 32; } - // CHECK: define internal i32 @_ZN12_GLOBAL__N_11A3fooEv() + // CHECK-1: define internal i32 @_ZN12_GLOBAL__N_11A3fooEv() namespace A { int foo() { return 45; @@ -44,3 +46,23 @@ int concrete() { } void test_XE() { throw X::E(); } + +// Miscompile on llvmc plugins. +namespace test2 { + struct A { + template struct B { + static void foo() {} + }; + }; + namespace { + struct C; + } + + // CHECK-2: define void @_ZN5test24testEv() + // CHECK-2: call void @_ZN5test21A1BINS_12_GLOBAL__N_11CEE3fooEv() + void test() { + A::B::foo(); + } + + // CHECK-2: define internal void @_ZN5test21A1BINS_12_GLOBAL__N_11CEE3fooEv() +}