[cfe-commits] r133958 - in /cfe/trunk: include/clang/AST/DeclTemplate.h lib/AST/Decl.cpp test/CodeGenCXX/visibility.cpp
John McCall
rjmccall at apple.com
Mon Jun 27 16:06:04 PDT 2011
Author: rjmccall
Date: Mon Jun 27 18:06:04 2011
New Revision: 133958
URL: http://llvm.org/viewvc/llvm-project?rev=133958&view=rev
Log:
Don't factor in visibility for templates and template arguments
for explicit specializations with their own explicit visibility.
Modified:
cfe/trunk/include/clang/AST/DeclTemplate.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/test/CodeGenCXX/visibility.cpp
Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=133958&r1=133957&r2=133958&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Mon Jun 27 18:06:04 2011
@@ -314,6 +314,10 @@
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 @@
return static_cast<TemplateSpecializationKind>(SpecializationKind);
}
+ bool isExplicitSpecialization() const {
+ return getSpecializationKind() == TSK_ExplicitSpecialization;
+ }
+
void setSpecializationKind(TemplateSpecializationKind TSK) {
SpecializationKind = TSK;
}
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=133958&r1=133957&r2=133958&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Mon Jun 27 18:06:04 2011
@@ -197,6 +197,16 @@
return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), F);
}
+static bool shouldConsiderTemplateLV(const FunctionDecl *fn,
+ const FunctionTemplateSpecializationInfo *spec) {
+ return !(spec->isExplicitSpecialization() &&
+ fn->hasAttr<VisibilityAttr>());
+}
+
+static bool shouldConsiderTemplateLV(const ClassTemplateSpecializationDecl *d) {
+ return !(d->isExplicitSpecialization() && d->hasAttr<VisibilityAttr>());
+}
+
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
"Not a name having namespace scope");
@@ -397,12 +407,16 @@
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 @@
// 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<ClassTemplateSpecializationDecl>(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 @@
// 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 @@
// *do* apply -fvisibility to method declarations.
} else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
- if (const ClassTemplateSpecializationDecl *Spec
+ if (const ClassTemplateSpecializationDecl *spec
= dyn_cast<ClassTemplateSpecializationDecl>(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.
Modified: cfe/trunk/test/CodeGenCXX/visibility.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/visibility.cpp?rev=133958&r1=133957&r2=133958&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/visibility.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/visibility.cpp Mon Jun 27 18:06:04 2011
@@ -422,3 +422,35 @@
// CHECK: define weak_odr void @_ZN6test211AILNS_2EnE0EE3fooEv(
template void A<en>::foo();
}
+
+// rdar://problem/9616154
+// Visibility on explicit specializations should take precedence.
+namespace test22 {
+ class A1 {};
+ class A2 {};
+
+ template <class T> struct B {};
+ template <> struct DEFAULT B<A1> {
+ static void foo();
+ static void bar() {}
+ };
+ template <> struct B<A2> {
+ static void foo();
+ static void bar() {}
+ };
+
+ void test() {
+ B<A1>::foo();
+ B<A1>::bar();
+ B<A2>::foo();
+ B<A2>::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()
+}
More information about the cfe-commits
mailing list