[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323 --- Comment #10 from GCC Commits --- The trunk branch has been updated by Marek Polacek : https://gcc.gnu.org/g:081f8937cb82da311c224da04b0c6cbd57a8fb5d commit r14-9596-g081f8937cb82da311c224da04b0c6cbd57a8fb5d Author: Marek Polacek Date: Thu Mar 7 20:41:23 2024 -0500 c++: explicit inst of template method not generated [PR110323] Consider constexpr int VAL = 1; struct foo { template void bar(typename std::conditional::type arg) { } }; template void foo::bar<1>(int arg); where we since r11-291 fail to emit the code for the explicit instantiation. That's because cp_walk_subtrees/TYPENAME_TYPE now walks TYPE_CONTEXT ('conditional' here) as well, and in a template finds the B==VAL template argument. VAL is constexpr, which implies const, which in the global scope implies static. constrain_visibility_for_template then makes "struct conditional<(B == VAL), int, float>" non-TREE_PUBLIC. Then symtab_node::needed_p checks TREE_PUBLIC, sees it's 0, and we don't emit any code. I thought the fix would be some ODR-esque check to not consider constexpr variables/fns that are used just for their value. But it turned out to be tricky. For instance, we can't skip determine_visibility in a template; we can't even skip it for value-dep expressions. For example, no-linkage-expr1.C has using P = struct {}*; template void f(int(*)[((P)0, N)]) {} where ((P)0, N) is value-dep, but N is not relevant here: we have to ferret out the anonymous type. When instantiating, it's already gone. This patch uses decl_constant_var_p. This is to implement (an approximation) [basic.def.odr]#14.5.1 and [basic.def.odr]#5.2. PR c++/110323 gcc/cp/ChangeLog: * decl2.cc (min_vis_expr_r) : Do nothing for decl_constant_var_p VAR_DECLs. gcc/testsuite/ChangeLog: * g++.dg/template/explicit-instantiation6.C: New test. * g++.dg/template/explicit-instantiation7.C: New test.
[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323 --- Comment #9 from Marek Polacek --- Oh and I meant to say it's the DECL_DECLARED_INLINE_P check that makes the difference.
[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323 --- Comment #8 from Marek Polacek --- (In reply to Patrick Palka from comment #7) > I noticed we emit the function if we turn it into a non-member: > > #include > > constexpr int VAL = 1; > > template > void bar(typename std::conditional::type arg) { > } > > template void bar<1>(int arg); > > I wonder why this bug seems specific to member functions? Good question. It's because in this case bar is marked as force_output here: /* When not optimizing, also output the static functions. (see PR24561), but don't do so for always_inline functions, functions declared inline and nested functions. These were optimized out in the original implementation and it is unclear whether we want to change the behavior here. */ if (((!opt_for_fn (decl, optimize) || flag_keep_static_functions || node->no_reorder) && !node->cpp_implicit_alias && !DECL_DISREGARD_INLINE_LIMITS (decl) && !DECL_DECLARED_INLINE_P (decl) && !(DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) node->force_output = 1; and when deciding if we ought to emit the fn in symtab_node::needed_p we do: /* If the user told us it is used, then it must be so. */ if (force_output) return true; With -O the fn isn't emitted.
[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323 Patrick Palka changed: What|Removed |Added CC||ppalka at gcc dot gnu.org --- Comment #7 from Patrick Palka --- I noticed we emit the function if we turn it into a non-member: #include constexpr int VAL = 1; template void bar(typename std::conditional::type arg) { } template void bar<1>(int arg); I wonder why this bug seems specific to member functions?
[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323 --- Comment #6 from Marek Polacek --- Extended test. I think all 4 should be emitted. ``` // PR c++/110323 template struct conditional { using type = T; }; template struct conditional { using type = F; }; constexpr int VAL = 1; static constexpr int getval () { return 1; } template constexpr int TVAL = 1; static struct S { constexpr operator bool() { return true; } } s; struct foo { template void bar(typename conditional::type arg) { } template void baz(typename conditional::type arg) { } template void qux(typename conditional, int, float>::type arg) { } template void lox(typename conditional::type arg) { } }; template void foo::bar<1>(int arg); template void foo::baz<1>(int arg); template void foo::qux<1>(int arg); template void foo::lox<1>(int arg); ```
[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323 Marek Polacek changed: What|Removed |Added Status|NEW |ASSIGNED Assignee|unassigned at gcc dot gnu.org |mpolacek at gcc dot gnu.org
[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323 --- Comment #5 from Marek Polacek --- VAL is constexpr, which implies const, which in the global scope implies static. Then constrain_visibility_for_template makes "struct conditional<(B == VAL), int, float>" non-TREE_PUBLIC. So with extern constexpr int VAL = 1; the test works again.
[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323 --- Comment #4 from Marek Polacek --- Ah -- if we walk into TYPE_CONTEXT (t) (here: struct conditional), then in min_vis_r we determine the visibility as VISIBILITY_ANON. Without it, it remains VISIBILITY_DEFAULT.
[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323 --- Comment #3 from Marek Polacek --- This makes a difference for some reason: --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -5542,7 +5542,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, break; case TYPENAME_TYPE: - WALK_SUBTREE (TYPE_CONTEXT (t)); + //WALK_SUBTREE (TYPE_CONTEXT (t)); WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (t)); *walk_subtrees_p = 0; break;
[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323 Marek Polacek changed: What|Removed |Added Priority|P3 |P2 CC||mpolacek at gcc dot gnu.org --- Comment #2 from Marek Polacek --- Started with r11-291-g0f50f6daa14018: commit 0f50f6daa140186a048cbf33f54f4591eabf5f12 Author: Jason Merrill Date: Mon May 11 15:46:59 2020 -0400 c++: tree walk into TYPENAME_TYPE. ``` template struct conditional { using type = T; }; template struct conditional { using type = F; }; constexpr int VAL = 1; struct foo { template void bar(typename conditional::type arg) { } }; template void foo::bar<1>(int arg); ```
[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323 Andrew Pinski changed: What|Removed |Added Keywords||wrong-code Target Milestone|--- |11.5 Summary|Code for explicit |[11/12/13/14 Regression] |instantiation of template |Code for explicit |method of template class|instantiation of template |not generated |method of template class ||not generated Ever confirmed|0 |1 Last reconfirmed||2023-06-20 Status|UNCONFIRMED |NEW URL|https://godbolt.org/z/x4ao4 | |dxdx| Known to work|10.4.0 |10.1.0, 9.1.0 --- Comment #1 from Andrew Pinski --- Confirmed.