loladiro created this revision.
loladiro added reviewers: aaron.ballman, rsmith, rnk.
loladiro added a subscriber: cfe-commits.
loladiro set the repository for this revision to rL LLVM.
When we were looking at a template instantiation, that itself was a template
instantiation
(say a templated member of a templated class), we weren't looking back far
enough along
the chain of instantiations to find a VisibilityAttr (which we don't copy when
instantiating
templates). This patch attempts to address that as well as adding a few test
cases for these
situations.
Repository:
rL LLVM
http://reviews.llvm.org/D13419
Files:
lib/AST/Decl.cpp
lib/AST/DeclCXX.cpp
test/CodeGenCXX/visibility.cpp
Index: test/CodeGenCXX/visibility.cpp
===================================================================
--- test/CodeGenCXX/visibility.cpp
+++ test/CodeGenCXX/visibility.cpp
@@ -1314,3 +1314,57 @@
// CHECK-LABEL: define void @_ZN6test693foo1fEv
// CHECK-HIDDEN-LABEL: define hidden void @_ZN6test693foo1fEv
}
+
+namespace test70 {
+ template < typename T > class foo {
+ public:
+ T x;
+ template < typename S >
+ HIDDEN S AddS(S);
+ template < typename S > class HIDDEN barS {
+ public:
+ static S AddS2(foo<T> x, S);
+ };
+ template < typename S > class HIDDEN barZ {
+ public:
+ template < typename Z >
+ static S AddSZ(foo<T> x, S, Z);
+ };
+ };
+
+ // CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4AddSIxEET_S3_
+ // CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4AddSIxEET_S3_
+ template < typename T >
+ template < typename S >
+ HIDDEN S foo<T>::AddS(S y) {
+ return ((S) x) + y;
+ }
+
+ // CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4barSIxE5AddS2ES1_x
+ // CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4barSIxE5AddS2ES1_x
+ template < typename T >
+ template < typename S >
+ HIDDEN S foo<T>::barS<S>::AddS2(foo<T> x, S y) {
+ return ((S) x.x) + y;
+ }
+
+ // CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4barZIxE5AddSZIcEExS1_xT_
+ // CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4barZIxE5AddSZIcEExS1_xT_
+ template < typename T >
+ template < typename S >
+ template < typename Z >
+ HIDDEN S foo<T>::barZ<S>::AddSZ(foo<T> x, S y, Z z) {
+ return ((S) x.x) + y + ((S) z);
+ }
+
+ extern template struct foo<int>;
+ template struct foo<int>;
+
+ void f() {
+ auto var = foo<int>{5};
+ auto bar = var.AddS((long long)3);
+ auto bar2 = decltype(var)::barS<long long>::AddS2(var,3);
+ auto bar3 = decltype(var)::barZ<long long>::AddSZ(var,3,(char)0);
+ }
+}
+
Index: lib/AST/DeclCXX.cpp
===================================================================
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -1261,20 +1261,22 @@
if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
auto From = TD->getInstantiatedFrom();
if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) {
- while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
+ auto *NewCTD = CTD;
+ do {
+ CTD = NewCTD;
if (NewCTD->isMemberSpecialization())
break;
- CTD = NewCTD;
- }
+ } while ((NewCTD = CTD->getInstantiatedFromMemberTemplate()));
return CTD->getTemplatedDecl()->getDefinition();
}
if (auto *CTPSD =
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
- while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
+ auto *NewCTPSD = CTPSD;
+ do {
+ CTPSD = NewCTPSD;
if (NewCTPSD->isMemberSpecialization())
break;
- CTPSD = NewCTPSD;
- }
+ } while ((NewCTPSD = CTPSD->getInstantiatedFromMember()));
return CTPSD->getDefinition();
}
}
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -1049,7 +1049,9 @@
// 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>(ND)) {
- CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
+ const CXXRecordDecl *InstantiatedFrom = RD->getTemplateInstantiationPattern();
+ if (!InstantiatedFrom)
+ InstantiatedFrom = RD->getInstantiatedFromMemberClass();
if (InstantiatedFrom)
return getVisibilityOf(InstantiatedFrom, kind);
}
@@ -1084,16 +1086,11 @@
}
// Also handle function template specializations.
if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(ND)) {
- // If the function is a specialization of a template with an
- // explicit visibility attribute, use that.
- if (FunctionTemplateSpecializationInfo *templateInfo
- = fn->getTemplateSpecializationInfo())
- return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(),
- kind);
-
- // If the function is a member of a specialization of a class template
+ // If the function is a member of a specialization of a some template
// and the corresponding decl has explicit visibility, use that.
- FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
+ FunctionDecl *InstantiatedFrom = fn->getTemplateInstantiationPattern();
+ if (!InstantiatedFrom)
+ InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
if (InstantiatedFrom)
return getVisibilityOf(InstantiatedFrom, kind);
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits