зеркало из https://github.com/microsoft/clang.git
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:
Родитель
a0b7d2ed23
Коммит
6ce51ee94b
|
@ -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(),
|
||||
if (shouldConsiderTemplateLV(Function, specInfo)) {
|
||||
LV.merge(getLVForDecl(specInfo->getTemplate(),
|
||||
F.onlyTemplateVisibility()));
|
||||
const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
|
||||
LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
|
||||
const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
|
||||
LV.merge(getLVForTemplateArgumentList(templateArgs, F));
|
||||
}
|
||||
}
|
||||
|
||||
// - a named class (Clause 9), or an unnamed class defined in a
|
||||
|
@ -418,16 +432,18 @@ 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)) {
|
||||
if (shouldConsiderTemplateLV(spec)) {
|
||||
// From the template.
|
||||
LV.merge(getLVForDecl(Spec->getSpecializedTemplate(),
|
||||
LV.merge(getLVForDecl(spec->getSpecializedTemplate(),
|
||||
F.onlyTemplateVisibility()));
|
||||
|
||||
// The arguments at which the template was instantiated.
|
||||
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
||||
const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs();
|
||||
LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
|
||||
}
|
||||
}
|
||||
|
||||
// Consider -fvisibility unless the type has C linkage.
|
||||
if (F.ConsiderGlobalVisibility)
|
||||
|
@ -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 (shouldConsiderTemplateLV(MD, spec)) {
|
||||
LV.merge(getLVForTemplateArgumentList(*spec->TemplateArguments, F));
|
||||
if (F.ConsiderTemplateParameterTypes)
|
||||
LV.merge(getLVForTemplateParameterList(
|
||||
Spec->getTemplate()->getTemplateParameters()));
|
||||
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)) {
|
||||
if (shouldConsiderTemplateLV(spec)) {
|
||||
// Merge template argument/parameter information for member
|
||||
// class template specializations.
|
||||
LV.merge(getLVForTemplateArgumentList(Spec->getTemplateArgs(), F));
|
||||
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()
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче