From c52255b0d89be25f833523ddce527a12270d5da7 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 10 Apr 2026 08:46:16 +0200 Subject: [PATCH] c++: Unshare expr in get_template_parm_object [PR124792] The following testcase is miscompiled due to incorrect CONSTRUCTOR sharing. For reflect_constant_array elts which aren't integral we call convert_reflect_constant_arg (but reflect_constant etc. do the same) and that eventually indirectly calls get_template_parm_object which creates the TPO VAR_DECL with DECL_INITIAL. Unfortunately, some CONSTRUCTORs in that DECL_INITIAL can be shared with whatever we use during constant expression evaluation later on, so when we evaluate ~vector, we modify those and with that modify also the CONSTRUCTORs inside of TPO DECL_INITIAL CONSTRUCTOR. So we need to unshare it somewhere. This patch unshares in get_template_parm_object, i.e. the lowest level, and only when not reusing previously created TPO. 2026-04-10 Jakub Jelinek PR c++/124792 * pt.cc (get_template_parm_object): Call unshare_expr_without_location on expr if check_init. * g++.dg/reflect/pr124792.C: New test. Reviewed-by: Jason Merrill --- gcc/cp/pt.cc | 2 ++ gcc/testsuite/g++.dg/reflect/pr124792.C | 11 +++++++++++ 2 files changed, 13 insertions(+) create mode 100644 gcc/testsuite/g++.dg/reflect/pr124792.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 18aec7ebb56..38e784517a5 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -7551,6 +7551,8 @@ get_template_parm_object (tree expr, tree name, bool check_init/*=true*/) DECL_NAME (decl) = name; SET_DECL_ASSEMBLER_NAME (decl, name); comdat_linkage (decl); + if (check_init) + expr = unshare_expr_without_location (expr); if (!zero_init_p (type)) { diff --git a/gcc/testsuite/g++.dg/reflect/pr124792.C b/gcc/testsuite/g++.dg/reflect/pr124792.C new file mode 100644 index 00000000000..8089dc13097 --- /dev/null +++ b/gcc/testsuite/g++.dg/reflect/pr124792.C @@ -0,0 +1,11 @@ +// PR c++/124792 +// { dg-do compile { target c++26 } } +// { dg-additional-options "-freflection" } + +#include + +struct S { const char *name = nullptr; }; + +constexpr auto a = std::define_static_array (std::vector { S { std::define_static_string ("foo") } }); +constexpr auto b = std::define_static_array (std::vector { S { std::define_static_string ("foo") }, + S { std::define_static_string ("bar") } }); -- 2.47.3