https://github.com/asavonic updated 
https://github.com/llvm/llvm-project/pull/136689

>From 348c94f4ef9b3fda5538813251360ccd8f6ffc44 Mon Sep 17 00:00:00 2001
From: Andrew Savonichev <andrew.savonic...@gmail.com>
Date: Mon, 21 Apr 2025 19:45:05 +0900
Subject: [PATCH 1/2] [clang] Fix computeTypeLinkageInfo for dependent member
 pointers

MemberPointerType may refer to a dependent class (qualifier), for
which getMostRecentCXXRecordDecl returns NULL. It seems that the
compiler never executed this code path before patch #136128 where the
issue was reported.

LIT tests 74 and 75 are reduced from Chromium and LLVM libc test
harness as reported in #136128.

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
---
 clang/lib/AST/Type.cpp               |  8 ++++--
 clang/test/CodeGenCXX/visibility.cpp | 37 ++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index fe1dc7e2fe786..871b0e00f3970 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -4787,8 +4787,12 @@ 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 (auto *D = MPT->getMostRecentCXXRecordDecl()) {
+      LV.merge(getDeclLinkageAndVisibility(D));
+    } else if (auto *Ty = MPT->getQualifier()->getAsType()) {
+      LV.merge(computeTypeLinkageInfo(Ty));
+    }
     LV.merge(computeTypeLinkageInfo(MPT->getPointeeType()));
     return LV;
   }
diff --git a/clang/test/CodeGenCXX/visibility.cpp 
b/clang/test/CodeGenCXX/visibility.cpp
index e1061f3dbd18f..b4c6fdcbcdf33 100644
--- a/clang/test/CodeGenCXX/visibility.cpp
+++ b/clang/test/CodeGenCXX/visibility.cpp
@@ -1463,3 +1463,40 @@ namespace test71 {
   // CHECK-HIDDEN-LABEL: define linkonce_odr hidden noundef i64 
@_ZN6test713fooIlE3zedEv(
   // CHECK-HIDDEN-LABEL: define linkonce_odr hidden noundef i32 
@_ZN6test713fooIlE3barIiEET_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 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 void 
@_ZN6test751TIMNS_1AEFvvEE6InvokeIiEEvT_(
+  // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void 
@_ZN6test751TIMNS_1AEFvvEE6InvokeIiEEvT_(
+}

>From b58ab38fa54eb28da87ce719f57ff12de4f40d54 Mon Sep 17 00:00:00 2001
From: Andrew Savonichev <andrew.savonic...@gmail.com>
Date: Thu, 17 Apr 2025 20:18:52 +0900
Subject: [PATCH 2/2] Reland [clang] Handle instantiated members to determine
 visibility (#136128)

As reported in issue #103477, visibility of instantiated member
functions used to be ignored when calculating visibility of a
specialization.

This patch modifies `getLVForClassMember` to look up for a source
template for an instantiated member, and changes `mergeTemplateLV` to
apply it.

A similar issue was reported in #31462, but it seems that `extern`
declaration with visibility prevents the function from being emitted
as hidden. This behavior seems correct, even though GCC emits it as
with default visibility instead.

Both tests from #103477 and #31462 are added as LIT tests `test72` and
`test73` respectively.
---
 clang/docs/ReleaseNotes.rst          |  1 +
 clang/lib/AST/Decl.cpp               | 13 +++++++--
 clang/test/CodeGenCXX/visibility.cpp | 42 ++++++++++++++++++++++++++--
 3 files changed, 50 insertions(+), 6 deletions(-)

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/test/CodeGenCXX/visibility.cpp 
b/clang/test/CodeGenCXX/visibility.cpp
index b4c6fdcbcdf33..442e2a5aaa2b3 100644
--- a/clang/test/CodeGenCXX/visibility.cpp
+++ b/clang/test/CodeGenCXX/visibility.cpp
@@ -1457,13 +1457,49 @@ 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>
@@ -1479,7 +1515,7 @@ namespace test74 {
   void Fun() {
     T<decltype(MM)>::Invoke(0);
   }
-  // CHECK-LABEL: define linkonce_odr void 
@_ZN6test741TIMNS_1CEFvvEE6InvokeIiEEvT_(
+  // CHECK-LABEL: define linkonce_odr hidden void 
@_ZN6test741TIMNS_1CEFvvEE6InvokeIiEEvT_(
   // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void 
@_ZN6test741TIMNS_1CEFvvEE6InvokeIiEEvT_(
 }
 
@@ -1497,6 +1533,6 @@ namespace test75 {
   void Fun() {
     T<void (A::*)()>::Invoke(0);
   }
-  // CHECK-LABEL: define linkonce_odr void 
@_ZN6test751TIMNS_1AEFvvEE6InvokeIiEEvT_(
+  // CHECK-LABEL: define linkonce_odr hidden void 
@_ZN6test751TIMNS_1AEFvvEE6InvokeIiEEvT_(
   // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void 
@_ZN6test751TIMNS_1AEFvvEE6InvokeIiEEvT_(
 }

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to