From: John McCall Date: Mon, 27 Jun 2011 23:06:04 +0000 (+0000) Subject: Don't factor in visibility for templates and template arguments X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6ce51ee94bd300c5f30930d96436fd53e4ea89a7;p=clang Don't factor in visibility for templates and template arguments for explicit specializations with their own explicit visibility. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133958 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index dc50d614bf..d2b1d3990c 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -314,6 +314,10 @@ public: return (TemplateSpecializationKind)(Template.getInt() + 1); } + bool isExplicitSpecialization() const { + return getTemplateSpecializationKind() == TSK_ExplicitSpecialization; + } + /// \brief Set the template specialization kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK) { assert(TSK != TSK_Undeclared && @@ -1398,6 +1402,10 @@ public: return static_cast(SpecializationKind); } + bool isExplicitSpecialization() const { + return getSpecializationKind() == TSK_ExplicitSpecialization; + } + void setSpecializationKind(TemplateSpecializationKind TSK) { SpecializationKind = TSK; } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 7ca936abc9..9b507cfc5e 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -197,6 +197,16 @@ getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), F); } +static bool shouldConsiderTemplateLV(const FunctionDecl *fn, + const FunctionTemplateSpecializationInfo *spec) { + return !(spec->isExplicitSpecialization() && + fn->hasAttr()); +} + +static bool shouldConsiderTemplateLV(const ClassTemplateSpecializationDecl *d) { + return !(d->isExplicitSpecialization() && d->hasAttr()); +} + static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { assert(D->getDeclContext()->getRedeclContext()->isFileContext() && "Not a name having namespace scope"); @@ -397,12 +407,16 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { Function->getType()->getLinkage() == UniqueExternalLinkage) return LinkageInfo::uniqueExternal(); - if (FunctionTemplateSpecializationInfo *SpecInfo + // Consider LV from the template and the template arguments unless + // this is an explicit specialization with a visibility attribute. + if (FunctionTemplateSpecializationInfo *specInfo = Function->getTemplateSpecializationInfo()) { - LV.merge(getLVForDecl(SpecInfo->getTemplate(), - F.onlyTemplateVisibility())); - const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments; - LV.merge(getLVForTemplateArgumentList(TemplateArgs, F)); + if (shouldConsiderTemplateLV(Function, specInfo)) { + LV.merge(getLVForDecl(specInfo->getTemplate(), + F.onlyTemplateVisibility())); + const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; + LV.merge(getLVForTemplateArgumentList(templateArgs, F)); + } } // - a named class (Clause 9), or an unnamed class defined in a @@ -418,15 +432,17 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // If this is a class template specialization, consider the // linkage of the template and template arguments. - if (const ClassTemplateSpecializationDecl *Spec + if (const ClassTemplateSpecializationDecl *spec = dyn_cast(Tag)) { - // From the template. - LV.merge(getLVForDecl(Spec->getSpecializedTemplate(), - F.onlyTemplateVisibility())); - - // The arguments at which the template was instantiated. - const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - LV.merge(getLVForTemplateArgumentList(TemplateArgs, F)); + if (shouldConsiderTemplateLV(spec)) { + // From the template. + LV.merge(getLVForDecl(spec->getSpecializedTemplate(), + F.onlyTemplateVisibility())); + + // The arguments at which the template was instantiated. + const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs(); + LV.merge(getLVForTemplateArgumentList(TemplateArgs, F)); + } } // Consider -fvisibility unless the type has C linkage. @@ -527,14 +543,16 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { // If this is a method template specialization, use the linkage for // the template parameters and arguments. - if (FunctionTemplateSpecializationInfo *Spec + if (FunctionTemplateSpecializationInfo *spec = MD->getTemplateSpecializationInfo()) { - LV.merge(getLVForTemplateArgumentList(*Spec->TemplateArguments, F)); - if (F.ConsiderTemplateParameterTypes) - LV.merge(getLVForTemplateParameterList( - Spec->getTemplate()->getTemplateParameters())); + if (shouldConsiderTemplateLV(MD, spec)) { + LV.merge(getLVForTemplateArgumentList(*spec->TemplateArguments, F)); + if (F.ConsiderTemplateParameterTypes) + LV.merge(getLVForTemplateParameterList( + spec->getTemplate()->getTemplateParameters())); + } - TSK = Spec->getTemplateSpecializationKind(); + TSK = spec->getTemplateSpecializationKind(); } else if (MemberSpecializationInfo *MSI = MD->getMemberSpecializationInfo()) { TSK = MSI->getTemplateSpecializationKind(); @@ -561,14 +579,16 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { // *do* apply -fvisibility to method declarations. } else if (const CXXRecordDecl *RD = dyn_cast(D)) { - if (const ClassTemplateSpecializationDecl *Spec + if (const ClassTemplateSpecializationDecl *spec = dyn_cast(RD)) { - // Merge template argument/parameter information for member - // class template specializations. - LV.merge(getLVForTemplateArgumentList(Spec->getTemplateArgs(), F)); + if (shouldConsiderTemplateLV(spec)) { + // Merge template argument/parameter information for member + // class template specializations. + LV.merge(getLVForTemplateArgumentList(spec->getTemplateArgs(), F)); if (F.ConsiderTemplateParameterTypes) LV.merge(getLVForTemplateParameterList( - Spec->getSpecializedTemplate()->getTemplateParameters())); + spec->getSpecializedTemplate()->getTemplateParameters())); + } } // Static data members. diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp index 7644e47ff7..fdccd46045 100644 --- a/test/CodeGenCXX/visibility.cpp +++ b/test/CodeGenCXX/visibility.cpp @@ -422,3 +422,35 @@ namespace test21 { // CHECK: define weak_odr void @_ZN6test211AILNS_2EnE0EE3fooEv( template void A::foo(); } + +// rdar://problem/9616154 +// Visibility on explicit specializations should take precedence. +namespace test22 { + class A1 {}; + class A2 {}; + + template struct B {}; + template <> struct DEFAULT B { + static void foo(); + static void bar() {} + }; + template <> struct B { + static void foo(); + static void bar() {} + }; + + void test() { + B::foo(); + B::bar(); + B::foo(); + B::bar(); + } + // CHECK: declare void @_ZN6test221BINS_2A1EE3fooEv() + // CHECK: define linkonce_odr void @_ZN6test221BINS_2A1EE3barEv() + // CHECK: declare void @_ZN6test221BINS_2A2EE3fooEv() + // CHECK: define linkonce_odr void @_ZN6test221BINS_2A2EE3barEv() + // CHECK-HIDDEN: declare void @_ZN6test221BINS_2A1EE3fooEv() + // CHECK-HIDDEN: define linkonce_odr void @_ZN6test221BINS_2A1EE3barEv() + // CHECK-HIDDEN: declare void @_ZN6test221BINS_2A2EE3fooEv() + // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test221BINS_2A2EE3barEv() +}