зеркало из https://github.com/microsoft/clang-1.git
Use the most recent decl in getExplicitVisibility.
Now that implicitly hidden template arguments can make an instantiation hidden, it is important to look at more than just the canonical decl of the argument in order to see if an attribute is available in a more recent decl. This has the disadvantage of exposing when getExplicitVisibility is called, but lets us handle cases like template <typename T> struct __attribute__((visibility("default"))) barT { static void zed() {} }; class foo; class __attribute__((visibility("default"))) foo; template struct barT<foo>; git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176112 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
d7a60ad800
Коммит
d3b2f0ac1c
|
@ -970,11 +970,32 @@ void NamedDecl::verifyLinkage() const {
|
|||
|
||||
Optional<Visibility>
|
||||
NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
|
||||
// Use the most recent declaration of a variable.
|
||||
if (const VarDecl *Var = dyn_cast<VarDecl>(this)) {
|
||||
if (Optional<Visibility> V = getVisibilityOf(Var, kind))
|
||||
return V;
|
||||
// Check the declaration itself first.
|
||||
if (Optional<Visibility> V = getVisibilityOf(this, kind))
|
||||
return V;
|
||||
|
||||
// If this is a member class of a specialization of a class template
|
||||
// and the corresponding decl has explicit visibility, use that.
|
||||
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) {
|
||||
CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
|
||||
if (InstantiatedFrom)
|
||||
return getVisibilityOf(InstantiatedFrom, kind);
|
||||
}
|
||||
|
||||
// If there wasn't explicit visibility there, and this is a
|
||||
// specialization of a class template, check for visibility
|
||||
// on the pattern.
|
||||
if (const ClassTemplateSpecializationDecl *spec
|
||||
= dyn_cast<ClassTemplateSpecializationDecl>(this))
|
||||
return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(),
|
||||
kind);
|
||||
|
||||
// Use the most recent declaration.
|
||||
const NamedDecl *MostRecent = cast<NamedDecl>(this->getMostRecentDecl());
|
||||
if (MostRecent != this)
|
||||
return MostRecent->getExplicitVisibility(kind);
|
||||
|
||||
if (const VarDecl *Var = dyn_cast<VarDecl>(this)) {
|
||||
if (Var->isStaticDataMember()) {
|
||||
VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember();
|
||||
if (InstantiatedFrom)
|
||||
|
@ -983,12 +1004,8 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
|
|||
|
||||
return None;
|
||||
}
|
||||
// Use the most recent declaration of a function, and also handle
|
||||
// function template specializations.
|
||||
// Also handle function template specializations.
|
||||
if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(this)) {
|
||||
if (Optional<Visibility> V = getVisibilityOf(fn, kind))
|
||||
return V;
|
||||
|
||||
// If the function is a specialization of a template with an
|
||||
// explicit visibility attribute, use that.
|
||||
if (FunctionTemplateSpecializationInfo *templateInfo
|
||||
|
@ -1005,30 +1022,10 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
|
|||
return None;
|
||||
}
|
||||
|
||||
// Otherwise, just check the declaration itself first.
|
||||
if (Optional<Visibility> V = getVisibilityOf(this, kind))
|
||||
return V;
|
||||
|
||||
// The visibility of a template is stored in the templated decl.
|
||||
if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(this))
|
||||
return getVisibilityOf(TD->getTemplatedDecl(), kind);
|
||||
|
||||
// If there wasn't explicit visibility there, and this is a
|
||||
// specialization of a class template, check for visibility
|
||||
// on the pattern.
|
||||
if (const ClassTemplateSpecializationDecl *spec
|
||||
= dyn_cast<ClassTemplateSpecializationDecl>(this))
|
||||
return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(),
|
||||
kind);
|
||||
|
||||
// If this is a member class of a specialization of a class template
|
||||
// and the corresponding decl has explicit visibility, use that.
|
||||
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) {
|
||||
CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
|
||||
if (InstantiatedFrom)
|
||||
return getVisibilityOf(InstantiatedFrom, kind);
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
@ -1227,3 +1227,36 @@ namespace test65 {
|
|||
|
||||
template class C<B<A>::InnerT>;
|
||||
}
|
||||
|
||||
namespace test66 {
|
||||
template <typename T>
|
||||
struct __attribute__((visibility("default"))) barT {
|
||||
static void zed() {}
|
||||
};
|
||||
class foo;
|
||||
class __attribute__((visibility("default"))) foo;
|
||||
template struct barT<foo>;
|
||||
// CHECK: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
|
||||
// CHECK-HIDDEN: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
|
||||
|
||||
template <int* I>
|
||||
struct __attribute__((visibility("default"))) barI {
|
||||
static void zed() {}
|
||||
};
|
||||
extern int I;
|
||||
extern int I __attribute__((visibility("default")));
|
||||
template struct barI<&I>;
|
||||
// CHECK: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
|
||||
// CHECK-HIDDEN: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
|
||||
|
||||
typedef void (*fType)(void);
|
||||
template<fType F>
|
||||
struct __attribute__((visibility("default"))) barF {
|
||||
static void zed() {}
|
||||
};
|
||||
void F();
|
||||
void F() __attribute__((visibility("default")));;
|
||||
template struct barF<F>;
|
||||
// CHECK: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
|
||||
// CHECK-HIDDEN: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче