MaskRay created this revision. MaskRay added reviewers: clang, aaron.ballman, efriedma, rjmccall, smeenai. Herald added a project: All. MaskRay requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
In CodeGenCXX/visibility.cpp, Match GCC for part of test51: Change explicit instantiation of a function template to respect the instantiated-from template's VisibilityAttr. Match GCC for test71: For an implicit or explicit instantiation of a class template, change its member template instantiation to respect the instantiated-from member template's VisibilityAttr. Fix https://github.com/llvm/llvm-project/issues/31462 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D154774 Files: clang/lib/AST/Decl.cpp clang/test/CodeGenCXX/visibility.cpp Index: clang/test/CodeGenCXX/visibility.cpp =================================================================== --- clang/test/CodeGenCXX/visibility.cpp +++ clang/test/CodeGenCXX/visibility.cpp @@ -969,10 +969,6 @@ } namespace test51 { - // Test that we use the visibility of struct foo when instantiating the - // template. Note that is a case where we disagree with gcc, it produces - // a default symbol. - struct HIDDEN foo { }; DEFAULT foo x, y, z; @@ -980,8 +976,8 @@ void DEFAULT zed() { } template void zed<&x>(); - // CHECK-LABEL: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv - // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv + // CHECK-LABEL: define weak_odr void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv + // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv template void HIDDEN zed<&y>(); // CHECK-LABEL: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1yEEEEEvv( @@ -1373,6 +1369,7 @@ template <class T> template <class U> U foo<T>::bar() { return {}; } + /// foo<int>::{zed,bar} get the instantiated-from member's HIDDEN, overriding DEFAULT. extern template struct DEFAULT foo<int>; int use() { @@ -1380,13 +1377,12 @@ foo<long> p; return o.zed() + o.bar<int>() + p.zed() + p.bar<int>(); } - /// FIXME: foo<int>::bar is hidden in GCC w/ or w/o -fvisibility=hidden. // CHECK-LABEL: declare hidden noundef i32 @_ZN6test713fooIiE3zedEv( - // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN6test713fooIiE3barIiEET_v( + // CHECK-LABEL: define linkonce_odr hidden noundef i32 @_ZN6test713fooIiE3barIiEET_v( // CHECK-LABEL: define linkonce_odr hidden noundef i64 @_ZN6test713fooIlE3zedEv( - // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN6test713fooIlE3barIiEET_v( + // CHECK-LABEL: define linkonce_odr hidden noundef i32 @_ZN6test713fooIlE3barIiEET_v( // CHECK-HIDDEN-LABEL: declare hidden noundef i32 @_ZN6test713fooIiE3zedEv( - // CHECK-HIDDEN-LABEL: define linkonce_odr noundef i32 @_ZN6test713fooIiE3barIiEET_v( + // CHECK-HIDDEN-LABEL: define linkonce_odr hidden noundef i32 @_ZN6test713fooIiE3barIiEET_v( // CHECK-HIDDEN-LABEL: define linkonce_odr hidden noundef i64 @_ZN6test713fooIlE3zedEv( // CHECK-HIDDEN-LABEL: define linkonce_odr hidden noundef i32 @_ZN6test713fooIlE3barIiEET_v( } Index: clang/lib/AST/Decl.cpp =================================================================== --- clang/lib/AST/Decl.cpp +++ clang/lib/AST/Decl.cpp @@ -375,7 +375,9 @@ if (!specInfo->isExplicitInstantiationOrSpecialization()) return true; - return !fn->hasAttr<VisibilityAttr>(); + return !fn->hasAttr<VisibilityAttr>() && !specInfo->getTemplate() + ->getTemplatedDecl() + ->hasAttr<VisibilityAttr>(); } /// Merge in template-related linkage and visibility for the given @@ -1240,12 +1242,20 @@ } // Also handle function template specializations. if (const auto *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 specialization of a template, + if (FunctionTemplateSpecializationInfo *templateInfo = + fn->getTemplateSpecializationInfo()) { + // ... If the template has an explicit visibility attribute, use that. + if (auto Vis = getVisibilityOf( + templateInfo->getTemplate()->getTemplatedDecl(), kind)) + return Vis; + // ... If the template instantiates from a member template with an + // explicit visibility attribute, use that. + if (auto *A = + templateInfo->getTemplate()->getInstantiatedFromMemberTemplate()) + return getVisibilityOf(A->getTemplatedDecl(), kind); + return std::nullopt; + } // If the function is a member of a specialization of a class template // and the corresponding decl has explicit visibility, use that.
Index: clang/test/CodeGenCXX/visibility.cpp =================================================================== --- clang/test/CodeGenCXX/visibility.cpp +++ clang/test/CodeGenCXX/visibility.cpp @@ -969,10 +969,6 @@ } namespace test51 { - // Test that we use the visibility of struct foo when instantiating the - // template. Note that is a case where we disagree with gcc, it produces - // a default symbol. - struct HIDDEN foo { }; DEFAULT foo x, y, z; @@ -980,8 +976,8 @@ void DEFAULT zed() { } template void zed<&x>(); - // CHECK-LABEL: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv - // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv + // CHECK-LABEL: define weak_odr void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv + // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv template void HIDDEN zed<&y>(); // CHECK-LABEL: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1yEEEEEvv( @@ -1373,6 +1369,7 @@ template <class T> template <class U> U foo<T>::bar() { return {}; } + /// foo<int>::{zed,bar} get the instantiated-from member's HIDDEN, overriding DEFAULT. extern template struct DEFAULT foo<int>; int use() { @@ -1380,13 +1377,12 @@ foo<long> p; return o.zed() + o.bar<int>() + p.zed() + p.bar<int>(); } - /// FIXME: foo<int>::bar is hidden in GCC w/ or w/o -fvisibility=hidden. // CHECK-LABEL: declare hidden noundef i32 @_ZN6test713fooIiE3zedEv( - // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN6test713fooIiE3barIiEET_v( + // CHECK-LABEL: define linkonce_odr hidden noundef i32 @_ZN6test713fooIiE3barIiEET_v( // CHECK-LABEL: define linkonce_odr hidden noundef i64 @_ZN6test713fooIlE3zedEv( - // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN6test713fooIlE3barIiEET_v( + // CHECK-LABEL: define linkonce_odr hidden noundef i32 @_ZN6test713fooIlE3barIiEET_v( // CHECK-HIDDEN-LABEL: declare hidden noundef i32 @_ZN6test713fooIiE3zedEv( - // CHECK-HIDDEN-LABEL: define linkonce_odr noundef i32 @_ZN6test713fooIiE3barIiEET_v( + // CHECK-HIDDEN-LABEL: define linkonce_odr hidden noundef i32 @_ZN6test713fooIiE3barIiEET_v( // CHECK-HIDDEN-LABEL: define linkonce_odr hidden noundef i64 @_ZN6test713fooIlE3zedEv( // CHECK-HIDDEN-LABEL: define linkonce_odr hidden noundef i32 @_ZN6test713fooIlE3barIiEET_v( } Index: clang/lib/AST/Decl.cpp =================================================================== --- clang/lib/AST/Decl.cpp +++ clang/lib/AST/Decl.cpp @@ -375,7 +375,9 @@ if (!specInfo->isExplicitInstantiationOrSpecialization()) return true; - return !fn->hasAttr<VisibilityAttr>(); + return !fn->hasAttr<VisibilityAttr>() && !specInfo->getTemplate() + ->getTemplatedDecl() + ->hasAttr<VisibilityAttr>(); } /// Merge in template-related linkage and visibility for the given @@ -1240,12 +1242,20 @@ } // Also handle function template specializations. if (const auto *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 specialization of a template, + if (FunctionTemplateSpecializationInfo *templateInfo = + fn->getTemplateSpecializationInfo()) { + // ... If the template has an explicit visibility attribute, use that. + if (auto Vis = getVisibilityOf( + templateInfo->getTemplate()->getTemplatedDecl(), kind)) + return Vis; + // ... If the template instantiates from a member template with an + // explicit visibility attribute, use that. + if (auto *A = + templateInfo->getTemplate()->getInstantiatedFromMemberTemplate()) + return getVisibilityOf(A->getTemplatedDecl(), kind); + return std::nullopt; + } // If the function is a member of a specialization of a class template // and the corresponding decl has explicit visibility, use that.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits