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

Reply via email to