From: Patrick Palka Date: Thu, 21 Dec 2023 18:53:43 +0000 (-0500) Subject: c++: visibility wrt template and ptrmem targs [PR70413] X-Git-Tag: basepoints/gcc-15~3350 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7226f825db049517b64442a40a6387513febb8f9;p=thirdparty%2Fgcc.git c++: visibility wrt template and ptrmem targs [PR70413] When constraining the visibility of an instantiation, we weren't properly considering the visibility of PTRMEM_CST and TEMPLATE_DECL template arguments. This patch fixes this. It turns out we don't maintain the relevant visibility flags for alias templates (e.g. TREE_PUBLIC is never set), so continue to ignore alias template template arguments for now. PR c++/70413 PR c++/107906 gcc/cp/ChangeLog: * decl2.cc (min_vis_expr_r): Handle PTRMEM_CST and TEMPLATE_DECL other than those for alias templates. gcc/testsuite/ChangeLog: * g++.dg/template/linkage2.C: New test. * g++.dg/template/linkage3.C: New test. * g++.dg/template/linkage4.C: New test. * g++.dg/template/linkage4a.C: New test. --- diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index 0850d3f5bce5..4777ceb8af7a 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -2655,7 +2655,10 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void *data) int *vis_p = (int *)data; int tpvis = VISIBILITY_DEFAULT; - switch (TREE_CODE (*tp)) + tree t = *tp; + if (TREE_CODE (t) == PTRMEM_CST) + t = PTRMEM_CST_MEMBER (t); + switch (TREE_CODE (t)) { case CAST_EXPR: case IMPLICIT_CONV_EXPR: @@ -2666,15 +2669,26 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void *data) case NEW_EXPR: case CONSTRUCTOR: case LAMBDA_EXPR: - tpvis = type_visibility (TREE_TYPE (*tp)); + tpvis = type_visibility (TREE_TYPE (t)); break; + case TEMPLATE_DECL: + if (DECL_ALIAS_TEMPLATE_P (t)) + /* FIXME: We don't maintain TREE_PUBLIC / DECL_VISIBILITY for + alias templates so we can't trust it here (PR107906). */ + break; + t = DECL_TEMPLATE_RESULT (t); + /* Fall through. */ case VAR_DECL: case FUNCTION_DECL: - if (! TREE_PUBLIC (*tp)) + if (! TREE_PUBLIC (t)) tpvis = VISIBILITY_ANON; else - tpvis = DECL_VISIBILITY (*tp); + tpvis = DECL_VISIBILITY (t); + break; + + case FIELD_DECL: + tpvis = type_visibility (DECL_CONTEXT (t)); break; default: diff --git a/gcc/testsuite/g++.dg/template/linkage2.C b/gcc/testsuite/g++.dg/template/linkage2.C new file mode 100644 index 000000000000..08fb6930262c --- /dev/null +++ b/gcc/testsuite/g++.dg/template/linkage2.C @@ -0,0 +1,13 @@ +// PR c++/70413 +// { dg-do compile { target c++11 } } +// { dg-final { scan-assembler-not "(weak|glob)\[^\n\]*_Z" } } + +namespace { + template struct A; +} + +template class Q> void f() { } + +int main() { + f(); +} diff --git a/gcc/testsuite/g++.dg/template/linkage3.C b/gcc/testsuite/g++.dg/template/linkage3.C new file mode 100644 index 000000000000..257aab33b382 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/linkage3.C @@ -0,0 +1,17 @@ +// PR c++/70413 +// { dg-final { scan-assembler-not "(weak|glob)\[^\n\]*_Z" } } + +namespace { + struct A { + void f(); + int m; + }; +} + +template void g() { } +template void h() { } + +int main() { + g<&A::f>(); + h<&A::m>(); +} diff --git a/gcc/testsuite/g++.dg/template/linkage4.C b/gcc/testsuite/g++.dg/template/linkage4.C new file mode 100644 index 000000000000..03630eebd3d7 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/linkage4.C @@ -0,0 +1,16 @@ +// PR c++/107906 +// { dg-do compile { target c++11 } } +// { dg-final { scan-assembler-not "(weak|glob)\[^\n\]*_Z" { xfail *-*-* } } } + +namespace { + template using X = int; + struct A { + template using X = int; + }; +} +template class Q> void f() { } + +int main() { + f(); + f(); +} diff --git a/gcc/testsuite/g++.dg/template/linkage4a.C b/gcc/testsuite/g++.dg/template/linkage4a.C new file mode 100644 index 000000000000..f1934fd65573 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/linkage4a.C @@ -0,0 +1,14 @@ +// { dg-do compile { target c++11 } } +// { dg-final { scan-assembler "(weak|glob)\[^\n\]*_Z1fI1XEvv" } } +// { dg-final { scan-assembler "(weak|glob)\[^\n\]*_Z1fIN1A1XEEvv" } } + +template using X = int; +struct A { + template using X = int; +}; +template class Q> void f() { } + +int main() { + f(); + f(); +}