Skip to content

Commit 3a52c44

Browse files
committed
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>; llvm-svn: 176112
1 parent 58f546c commit 3a52c44

File tree

2 files changed

+59
-29
lines changed

2 files changed

+59
-29
lines changed

clang/lib/AST/Decl.cpp

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -970,11 +970,32 @@ void NamedDecl::verifyLinkage() const {
970970

971971
Optional<Visibility>
972972
NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
973-
// Use the most recent declaration of a variable.
974-
if (const VarDecl *Var = dyn_cast<VarDecl>(this)) {
975-
if (Optional<Visibility> V = getVisibilityOf(Var, kind))
976-
return V;
973+
// Check the declaration itself first.
974+
if (Optional<Visibility> V = getVisibilityOf(this, kind))
975+
return V;
976+
977+
// If this is a member class of a specialization of a class template
978+
// and the corresponding decl has explicit visibility, use that.
979+
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) {
980+
CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
981+
if (InstantiatedFrom)
982+
return getVisibilityOf(InstantiatedFrom, kind);
983+
}
977984

985+
// If there wasn't explicit visibility there, and this is a
986+
// specialization of a class template, check for visibility
987+
// on the pattern.
988+
if (const ClassTemplateSpecializationDecl *spec
989+
= dyn_cast<ClassTemplateSpecializationDecl>(this))
990+
return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(),
991+
kind);
992+
993+
// Use the most recent declaration.
994+
const NamedDecl *MostRecent = cast<NamedDecl>(this->getMostRecentDecl());
995+
if (MostRecent != this)
996+
return MostRecent->getExplicitVisibility(kind);
997+
998+
if (const VarDecl *Var = dyn_cast<VarDecl>(this)) {
978999
if (Var->isStaticDataMember()) {
9791000
VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember();
9801001
if (InstantiatedFrom)
@@ -983,12 +1004,8 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
9831004

9841005
return None;
9851006
}
986-
// Use the most recent declaration of a function, and also handle
987-
// function template specializations.
1007+
// Also handle function template specializations.
9881008
if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(this)) {
989-
if (Optional<Visibility> V = getVisibilityOf(fn, kind))
990-
return V;
991-
9921009
// If the function is a specialization of a template with an
9931010
// explicit visibility attribute, use that.
9941011
if (FunctionTemplateSpecializationInfo *templateInfo
@@ -1005,30 +1022,10 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
10051022
return None;
10061023
}
10071024

1008-
// Otherwise, just check the declaration itself first.
1009-
if (Optional<Visibility> V = getVisibilityOf(this, kind))
1010-
return V;
1011-
10121025
// The visibility of a template is stored in the templated decl.
10131026
if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(this))
10141027
return getVisibilityOf(TD->getTemplatedDecl(), kind);
10151028

1016-
// If there wasn't explicit visibility there, and this is a
1017-
// specialization of a class template, check for visibility
1018-
// on the pattern.
1019-
if (const ClassTemplateSpecializationDecl *spec
1020-
= dyn_cast<ClassTemplateSpecializationDecl>(this))
1021-
return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(),
1022-
kind);
1023-
1024-
// If this is a member class of a specialization of a class template
1025-
// and the corresponding decl has explicit visibility, use that.
1026-
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) {
1027-
CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
1028-
if (InstantiatedFrom)
1029-
return getVisibilityOf(InstantiatedFrom, kind);
1030-
}
1031-
10321029
return None;
10331030
}
10341031

clang/test/CodeGenCXX/visibility.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,3 +1227,36 @@ namespace test65 {
12271227

12281228
template class C<B<A>::InnerT>;
12291229
}
1230+
1231+
namespace test66 {
1232+
template <typename T>
1233+
struct __attribute__((visibility("default"))) barT {
1234+
static void zed() {}
1235+
};
1236+
class foo;
1237+
class __attribute__((visibility("default"))) foo;
1238+
template struct barT<foo>;
1239+
// CHECK: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
1240+
// CHECK-HIDDEN: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
1241+
1242+
template <int* I>
1243+
struct __attribute__((visibility("default"))) barI {
1244+
static void zed() {}
1245+
};
1246+
extern int I;
1247+
extern int I __attribute__((visibility("default")));
1248+
template struct barI<&I>;
1249+
// CHECK: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
1250+
// CHECK-HIDDEN: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
1251+
1252+
typedef void (*fType)(void);
1253+
template<fType F>
1254+
struct __attribute__((visibility("default"))) barF {
1255+
static void zed() {}
1256+
};
1257+
void F();
1258+
void F() __attribute__((visibility("default")));;
1259+
template struct barF<F>;
1260+
// CHECK: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
1261+
// CHECK-HIDDEN: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
1262+
}

0 commit comments

Comments
 (0)