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 cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits