-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Handle instantiated members to determine visibility #136128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang] Handle instantiated members to determine visibility #136128
Conversation
@llvm/pr-subscribers-clang Author: Andrew Savonichev (asavonic) ChangesAs reported in issue #103477, visibility of instantiated member functions used to be ignored when calculating visibility of a specialization. This patch modifies A similar issue was reported in #31462, but it seems that Both tests from #103477 and #31462 are added as LIT tests Full diff: https://github.com/llvm/llvm-project/pull/136128.diff 2 Files Affected:
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(
+}
|
Libcxx tests failed. I'll check them tomorrow.
|
IMO they fail now in all PRs, so this is likely unrelated. |
FYI the libc++ CI has been fixed so all you need to do is to rebase your branch |
As reported in issue llvm#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 llvm#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 llvm#103477 and llvm#31462 are added as LIT tests `test72` and `test73` respectively.
c08102a
to
79a70bb
Compare
This seems reasonable to me, but I'd like to see if @mizvekov has thoughts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! LGTM as well.
Thanks everyone for review! |
I was going to say we need a release note but you have merged it :) |
Sure, I'll post another patch to update release notes. |
I think this broke one of our bots: https://lab.llvm.org/buildbot/#/builders/10/builds/3726/steps/10/logs/stdio The bot was red for another issue at the time, but the stack trace includes methods that are touched in this PR.
I'd appreciate if someone more familiar with the matter can have a look at it. I'm happy to assist with info on build config etc. |
This is breaking builds when compiling chromium as well, bisected to this change. Example build: https://ci.chromium.org/ui/p/chromium/builders/ci/ToTLinux%20(dbg)/31974/overview. Compiler output can be seen by clicking |
Hmm... do either of you (@jplehr @DKLoehr ) have the ability to provide the author a reduced example they can work with? We can revert in the meantime, but without a reduction provided (or AT LEAST a pre-processed example), there isn't anything we can really do about these reports. Our crashes usually provide dumps (the location should be printed in the crash) which should provide the info needed to do so. |
I can try later today to get dumps/preprocessed source or maybe some better idea on how to reproduce the issue. |
Revert submitted here: #136317 When CI is ok with it, I'll merge it. |
I'm working on reducing my reproduction, but it's taking a while. |
…136317) Reverts #136128 See discussion here: #136128 (comment) and : #136128 (comment) @asavonic can re-submit once the examples provided by @jplehr and/or @DKLoehr are fixed.
…isibility" (#136317) Reverts llvm/llvm-project#136128 See discussion here: llvm/llvm-project#136128 (comment) and : llvm/llvm-project#136128 (comment) @asavonic can re-submit once the examples provided by @jplehr and/or @DKLoehr are fixed.
Here's what cvise gave me; unfortunately, I'm in a rush so I don't have time to clean it up any further. It crashes when run with repro.cc:
|
Thanks a lot @jplehr and @DKLoehr for helping with reproducers, and @erichkeane for taking care of the revert. The compiler trips on
I'll figure out what to do with this case and send a new patch. The following helps to bypass the error, but perhaps we need to do something else for function types here. diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 42e94d66d1a1..28a5fdc4c3a8 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -4746,8 +4746,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;
} |
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 llvm#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 llvm#136128.
…lvm#136128) As reported in issue llvm#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 llvm#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 llvm#103477 and llvm#31462 are added as LIT tests `test72` and `test73` respectively.
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 llvm#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 llvm#136128.
…lvm#136128) As reported in issue llvm#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 llvm#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 llvm#103477 and llvm#31462 are added as LIT tests `test72` and `test73` respectively.
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 llvm#136128 where the issue was reported. LIT tests 74 and 75 are reduced from Chromium and LLVM libc test harness as reported in llvm#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
…lvm#136128) As reported in issue llvm#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 llvm#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 llvm#103477 and llvm#31462 are added as LIT tests `test72` and `test73` respectively.
…6689) 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
…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.
…m#136689) 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 llvm#136128 where the issue was reported. LIT tests 74 and 75 are reduced from Chromium and LLVM libc test harness as reported in llvm#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
…lvm#136128) (llvm#136689) As reported in issue llvm#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 llvm#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 llvm#103477 and llvm#31462 are added as LIT tests `test72` and `test73` respectively.
) As reported in issue llvm#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 llvm#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 llvm#103477 and llvm#31462 are added as LIT tests `test72` and `test73` respectively.
…lvm#136317) Reverts llvm#136128 See discussion here: llvm#136128 (comment) and : llvm#136128 (comment) @asavonic can re-submit once the examples provided by @jplehr and/or @DKLoehr are fixed.
…m#136689) 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 llvm#136128 where the issue was reported. LIT tests 74 and 75 are reduced from Chromium and LLVM libc test harness as reported in llvm#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
…lvm#136128) (llvm#136689) As reported in issue llvm#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 llvm#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 llvm#103477 and llvm#31462 are added as LIT tests `test72` and `test73` respectively.
…lvm#136317) Reverts llvm#136128 See discussion here: llvm#136128 (comment) and : llvm#136128 (comment) @asavonic can re-submit once the examples provided by @jplehr and/or @DKLoehr are fixed.
…m#136689) 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 llvm#136128 where the issue was reported. LIT tests 74 and 75 are reduced from Chromium and LLVM libc test harness as reported in llvm#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
…lvm#136128) (llvm#136689) As reported in issue llvm#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 llvm#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 llvm#103477 and llvm#31462 are added as LIT tests `test72` and `test73` respectively.
) As reported in issue llvm#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 llvm#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 llvm#103477 and llvm#31462 are added as LIT tests `test72` and `test73` respectively.
…lvm#136317) Reverts llvm#136128 See discussion here: llvm#136128 (comment) and : llvm#136128 (comment) @asavonic can re-submit once the examples provided by @jplehr and/or @DKLoehr are fixed.
…m#136689) 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 llvm#136128 where the issue was reported. LIT tests 74 and 75 are reduced from Chromium and LLVM libc test harness as reported in llvm#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
…lvm#136128) (llvm#136689) As reported in issue llvm#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 llvm#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 llvm#103477 and llvm#31462 are added as LIT tests `test72` and `test73` respectively.
…m#136689) 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 llvm#136128 where the issue was reported. LIT tests 74 and 75 are reduced from Chromium and LLVM libc test harness as reported in llvm#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
…lvm#136128) (llvm#136689) As reported in issue llvm#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 llvm#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 llvm#103477 and llvm#31462 are added as LIT tests `test72` and `test73` respectively.
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 changesmergeTemplateLV
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
andtest73
respectively.