Author: Andrew Savonichev
Date: 2025-04-28T15:49:54+09:00
New Revision: dae63e2c0ff1b7d64e186fe72e06a80ef895402c

URL: 
https://github.com/llvm/llvm-project/commit/dae63e2c0ff1b7d64e186fe72e06a80ef895402c
DIFF: 
https://github.com/llvm/llvm-project/commit/dae63e2c0ff1b7d64e186fe72e06a80ef895402c.diff

LOG: Reland [clang] Handle instantiated members to determine visibility 
(#136128) (#136689)

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.

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/AST/Decl.cpp
    clang/test/CodeGenCXX/visibility.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index eb2e8f2b8a6c0..3105d8b481560 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -470,6 +470,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