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
This commit is contained in:
John McCall 2011-06-27 23:06:04 +00:00
Родитель a0b7d2ed23
Коммит 6ce51ee94b
3 изменённых файлов: 83 добавлений и 23 удалений

Просмотреть файл

@ -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<TemplateSpecializationKind>(SpecializationKind);
}
bool isExplicitSpecialization() const {
return getSpecializationKind() == TSK_ExplicitSpecialization;
}
void setSpecializationKind(TemplateSpecializationKind TSK) {
SpecializationKind = TSK;
}

Просмотреть файл

@ -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<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 @@ 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<ClassTemplateSpecializationDecl>(Tag)) {
// From the template.
LV.merge(getLVForDecl(Spec->getSpecializedTemplate(),
F.onlyTemplateVisibility()));
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));
// 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<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.

Просмотреть файл

@ -422,3 +422,35 @@ namespace test21 {
// 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()
}