[clang] [clang] Handle instantiated members to determine visibility (PR #136128)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 17 04:41:47 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Andrew Savonichev (asavonic)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/136128.diff
2 Files Affected:
- (modified) clang/lib/AST/Decl.cpp (+10-3)
- (modified) clang/test/CodeGenCXX/visibility.cpp (+37-1)
``````````diff
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index ad1cb01592e9b..b59619892979a 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 e1061f3dbd18f..b69278a71d48e 100644
--- a/clang/test/CodeGenCXX/visibility.cpp
+++ b/clang/test/CodeGenCXX/visibility.cpp
@@ -1457,9 +1457,45 @@ 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(
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/136128
More information about the cfe-commits
mailing list