Skip to content

Commit dae63e2

Browse files
committed
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.
1 parent f5ba3d0 commit dae63e2

File tree

3 files changed

+50
-6
lines changed

3 files changed

+50
-6
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ Bug Fixes in This Version
470470
- Fixed a crash when ``#embed`` appears as a part of a failed constant
471471
evaluation. The crashes were happening during diagnostics emission due to
472472
unimplemented statement printer. (#GH132641)
473+
- Fixed visibility calculation for template functions. (#GH103477)
473474

474475
Bug Fixes to Compiler Builtins
475476
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/AST/Decl.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,9 +400,9 @@ void LinkageComputer::mergeTemplateLV(
400400
FunctionTemplateDecl *temp = specInfo->getTemplate();
401401
// Merge information from the template declaration.
402402
LinkageInfo tempLV = getLVForDecl(temp, computation);
403-
// The linkage of the specialization should be consistent with the
404-
// template declaration.
405-
LV.setLinkage(tempLV.getLinkage());
403+
// The linkage and visibility of the specialization should be
404+
// consistent with the template declaration.
405+
LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
406406

407407
// Merge information from the template parameters.
408408
LinkageInfo paramsLV =
@@ -1051,6 +1051,13 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
10511051
if (const auto *redeclTemp = dyn_cast<RedeclarableTemplateDecl>(temp)) {
10521052
if (isExplicitMemberSpecialization(redeclTemp)) {
10531053
explicitSpecSuppressor = temp->getTemplatedDecl();
1054+
} else if (const RedeclarableTemplateDecl *from =
1055+
redeclTemp->getInstantiatedFromMemberTemplate()) {
1056+
// If no explicit visibility is specified yet, and this is an
1057+
// instantiated member of a template, look up visibility there
1058+
// as well.
1059+
LinkageInfo fromLV = from->getLinkageAndVisibility();
1060+
LV.mergeMaybeWithVisibility(fromLV, considerVisibility);
10541061
}
10551062
}
10561063
}

clang/test/CodeGenCXX/visibility.cpp

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,13 +1457,49 @@ namespace test71 {
14571457
// CHECK-LABEL: declare hidden noundef i32 @_ZN6test713fooIiE3zedEv(
14581458
// CHECK-LABEL: define linkonce_odr noundef i32 @_ZN6test713fooIiE3barIiEET_v(
14591459
// CHECK-LABEL: define linkonce_odr hidden noundef i64 @_ZN6test713fooIlE3zedEv(
1460-
// CHECK-LABEL: define linkonce_odr noundef i32 @_ZN6test713fooIlE3barIiEET_v(
1460+
// CHECK-LABEL: define linkonce_odr hidden noundef i32 @_ZN6test713fooIlE3barIiEET_v(
14611461
// CHECK-HIDDEN-LABEL: declare hidden noundef i32 @_ZN6test713fooIiE3zedEv(
14621462
// CHECK-HIDDEN-LABEL: define linkonce_odr noundef i32 @_ZN6test713fooIiE3barIiEET_v(
14631463
// CHECK-HIDDEN-LABEL: define linkonce_odr hidden noundef i64 @_ZN6test713fooIlE3zedEv(
14641464
// CHECK-HIDDEN-LABEL: define linkonce_odr hidden noundef i32 @_ZN6test713fooIlE3barIiEET_v(
14651465
}
14661466

1467+
// https://github.com/llvm/llvm-project/issues/103477
1468+
namespace test72 {
1469+
template <class a>
1470+
struct t {
1471+
template <int>
1472+
static HIDDEN void bar() {}
1473+
};
1474+
1475+
void test() {
1476+
t<char>::bar<1>();
1477+
}
1478+
// CHECK-LABEL: define linkonce_odr hidden void @_ZN6test721tIcE3barILi1EEEvv(
1479+
// CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test721tIcE3barILi1EEEvv(
1480+
}
1481+
1482+
// https://github.com/llvm/llvm-project/issues/31462
1483+
namespace test73 {
1484+
template <class T> struct s {
1485+
template <class U>
1486+
__attribute__((__visibility__("hidden"))) U should_not_be_exported();
1487+
};
1488+
1489+
template <class T> template <class U> U s<T>::should_not_be_exported() {
1490+
return U();
1491+
}
1492+
1493+
extern template struct __attribute__((__visibility__("default"))) s<int>;
1494+
1495+
int f() {
1496+
s<int> o;
1497+
return o.should_not_be_exported<int>();
1498+
}
1499+
// CHECK-LABEL: define linkonce_odr noundef i32 @_ZN6test731sIiE22should_not_be_exportedIiEET_v(
1500+
// CHECK-HIDDEN-LABEL: define linkonce_odr noundef i32 @_ZN6test731sIiE22should_not_be_exportedIiEET_v(
1501+
}
1502+
14671503
namespace test74 {
14681504
template <typename> struct T;
14691505
template <typename R>
@@ -1479,7 +1515,7 @@ namespace test74 {
14791515
void Fun() {
14801516
T<decltype(MM)>::Invoke(0);
14811517
}
1482-
// CHECK-LABEL: define linkonce_odr void @_ZN6test741TIMNS_1CEFvvEE6InvokeIiEEvT_(
1518+
// CHECK-LABEL: define linkonce_odr hidden void @_ZN6test741TIMNS_1CEFvvEE6InvokeIiEEvT_(
14831519
// CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test741TIMNS_1CEFvvEE6InvokeIiEEvT_(
14841520
}
14851521

@@ -1497,6 +1533,6 @@ namespace test75 {
14971533
void Fun() {
14981534
T<void (A::*)()>::Invoke(0);
14991535
}
1500-
// CHECK-LABEL: define linkonce_odr void @_ZN6test751TIMNS_1AEFvvEE6InvokeIiEEvT_(
1536+
// CHECK-LABEL: define linkonce_odr hidden void @_ZN6test751TIMNS_1AEFvvEE6InvokeIiEEvT_(
15011537
// CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test751TIMNS_1AEFvvEE6InvokeIiEEvT_(
15021538
}

0 commit comments

Comments
 (0)