llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Andrew Savonichev (asavonic) <details> <summary>Changes</summary> This patchset includes #<!-- -->136128, and adds a fix for regressions that were reported by @<!-- -->jplehr and @<!-- -->DKLoehr: [clang] Fix computeTypeLinkageInfo for non-record member pointers MemberPointerType can point to records, functions, or types from template parameters. computeTypeLinkageInfo used to expect only records, and crash for anything else. It seems that the compiler never executed this code path before patch https://github.com/llvm/llvm-project/pull/136128 where the issue was reported. Function member (test74): MemberPointerType 'type-parameter-0-0 (type-parameter-0-1::*)(void)' dependent |-TemplateTypeParmType 'type-parameter-0-1' dependent depth 0 index 1 `-FunctionProtoType 'type-parameter-0-0 (void)' dependent cdecl `-TemplateTypeParmType 'type-parameter-0-0' dependent depth 0 index 0 Template parameter (test75): MemberPointerType 'type-parameter-0-1 type-parameter-0-0::*' dependent |-TemplateTypeParmType 'type-parameter-0-0' dependent depth 0 index 0 `-TemplateTypeParmType 'type-parameter-0-1' dependent depth 0 index 1 For non-record types, it should be enough to look at a pointee type to determine linkage and visibility. LIT tests 74 and 75 are reduced from Chromium and LLVM libc test harness as reported in https://github.com/llvm/llvm-project/pull/136128. --- Full diff: https://github.com/llvm/llvm-project/pull/136689.diff 4 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+1) - (modified) clang/lib/AST/Decl.cpp (+10-3) - (modified) clang/lib/AST/Type.cpp (+4-2) - (modified) clang/test/CodeGenCXX/visibility.cpp (+74-1) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 86d37f5616356..9ecd78c13d4e5 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -458,6 +458,7 @@ Bug Fixes in This Version - Fixed a crash when ``#embed`` appears as a part of a failed constant evaluation. The crashes were happening during diagnostics emission due to unimplemented statement printer. (#GH132641) +- Fixed visibility calculation for template functions. (#GH103477) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 1d9208f0e1c72..61d497999b669 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -400,9 +400,9 @@ void LinkageComputer::mergeTemplateLV( FunctionTemplateDecl *temp = specInfo->getTemplate(); // Merge information from the template declaration. LinkageInfo tempLV = getLVForDecl(temp, computation); - // The linkage of the specialization should be consistent with the - // template declaration. - LV.setLinkage(tempLV.getLinkage()); + // The linkage and visibility of the specialization should be + // consistent with the template declaration. + LV.mergeMaybeWithVisibility(tempLV, considerVisibility); // Merge information from the template parameters. LinkageInfo paramsLV = @@ -1051,6 +1051,13 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D, if (const auto *redeclTemp = dyn_cast<RedeclarableTemplateDecl>(temp)) { if (isExplicitMemberSpecialization(redeclTemp)) { explicitSpecSuppressor = temp->getTemplatedDecl(); + } else if (const RedeclarableTemplateDecl *from = + redeclTemp->getInstantiatedFromMemberTemplate()) { + // If no explicit visibility is specified yet, and this is an + // instantiated member of a template, look up visibility there + // as well. + LinkageInfo fromLV = from->getLinkageAndVisibility(); + LV.mergeMaybeWithVisibility(fromLV, considerVisibility); } } } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index fe1dc7e2fe786..5783f87012731 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -4787,8 +4787,10 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) { return computeTypeLinkageInfo(cast<ReferenceType>(T)->getPointeeType()); case Type::MemberPointer: { const auto *MPT = cast<MemberPointerType>(T); - LinkageInfo LV = - getDeclLinkageAndVisibility(MPT->getMostRecentCXXRecordDecl()); + LinkageInfo LV; + if (CXXRecordDecl *D = MPT->getMostRecentCXXRecordDecl()) { + LV.merge(getDeclLinkageAndVisibility(D)); + } LV.merge(computeTypeLinkageInfo(MPT->getPointeeType())); return LV; } diff --git a/clang/test/CodeGenCXX/visibility.cpp b/clang/test/CodeGenCXX/visibility.cpp index e1061f3dbd18f..442e2a5aaa2b3 100644 --- a/clang/test/CodeGenCXX/visibility.cpp +++ b/clang/test/CodeGenCXX/visibility.cpp @@ -1457,9 +1457,82 @@ namespace test71 { // CHECK-LABEL: declare hidden noundef i32 @_ZN6test713fooIiE3zedEv( // CHECK-LABEL: define linkonce_odr 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 i64 @_ZN6test713fooIlE3zedEv( // CHECK-HIDDEN-LABEL: define linkonce_odr hidden noundef i32 @_ZN6test713fooIlE3barIiEET_v( } + +// https://github.com/llvm/llvm-project/issues/103477 +namespace test72 { + template <class a> + struct t { + template <int> + static HIDDEN void bar() {} + }; + + void test() { + t<char>::bar<1>(); + } + // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test721tIcE3barILi1EEEvv( + // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test721tIcE3barILi1EEEvv( +} + +// https://github.com/llvm/llvm-project/issues/31462 +namespace test73 { + template <class T> struct s { + template <class U> + __attribute__((__visibility__("hidden"))) U should_not_be_exported(); + }; + + template <class T> template <class U> U s<T>::should_not_be_exported() { + return U(); + } + + extern template struct __attribute__((__visibility__("default"))) s<int>; + + int f() { + s<int> o; + return o.should_not_be_exported<int>(); + } + // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN6test731sIiE22should_not_be_exportedIiEET_v( + // CHECK-HIDDEN-LABEL: define linkonce_odr noundef i32 @_ZN6test731sIiE22should_not_be_exportedIiEET_v( +} + +namespace test74 { + template <typename> struct T; + template <typename R> + struct T<void (R::*)()> { + template <typename M> + static __attribute__((__visibility__("hidden"))) void Invoke(M) { + } + }; + + struct C; + void (C::*MM)(); + + void Fun() { + T<decltype(MM)>::Invoke(0); + } + // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test741TIMNS_1CEFvvEE6InvokeIiEEvT_( + // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test741TIMNS_1CEFvvEE6InvokeIiEEvT_( +} + +namespace test75 { + template <class> struct T; + template <class C, class Ret> + struct T<Ret C::*> { + template <class M> + static __attribute__((__visibility__("hidden"))) + void Invoke(M) { + } + }; + + struct A; + void Fun() { + T<void (A::*)()>::Invoke(0); + } + // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test751TIMNS_1AEFvvEE6InvokeIiEEvT_( + // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test751TIMNS_1AEFvvEE6InvokeIiEEvT_( +} `````````` </details> https://github.com/llvm/llvm-project/pull/136689 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits