On Thu, Jul 02, 2026 at 01:21:31PM -0400, Jason Merrill wrote:
> > if (tsubst_decomp_names (decl, pattern_decl, args,
> > complain, in_decl, decomp)
> > == error_mark_node)
> > - decomp = NULL;
> > + {
> > + decomp = NULL;
> > + if (TREE_STATIC (decl))
> > + {
> > + tree id = get_identifier ("<decomp>");
> > + SET_DECL_ASSEMBLER_NAME (decl, id);
>
> How about doing this in tsubst_decomp_names?
So like this? The patch is larger because tsubst_decomp_names
can return error_mark_node in 2 spots rather than just one, and
worse it overwrites the decl argument in that case to error_mark_node
so that we don't know what to check TREE_STATIC on and what to
SET_DECL_ASSEMBLER_NAME on.
2026-07-03 Jakub Jelinek <[email protected]>
PR c++/126057
* decl.cc (cp_finish_decomp): Set assembler name to
<decomp> during error recovery whenever TREE_STATIC
rather than just DECL_NAMESPACE_SCOPE_P.
* pt.cc (tsubst_decomp_names): When returning error_mark_node
and decl is TREE_STATIC, set assembler name to <decomp>.
* g++.dg/cpp2a/decomp11.C: New test.
--- gcc/cp/decl.cc.jj 2026-07-01 11:54:35.402958896 +0200
+++ gcc/cp/decl.cc 2026-07-01 19:19:33.763975576 +0200
@@ -10708,7 +10708,7 @@ cp_finish_decomp (tree decl, cp_decomp *
}
first = DECL_CHAIN (first);
}
- if (DECL_P (decl) && DECL_NAMESPACE_SCOPE_P (decl))
+ if (DECL_P (decl) && TREE_STATIC (decl))
SET_DECL_ASSEMBLER_NAME (decl, get_identifier ("<decomp>"));
return false;
}
--- gcc/cp/pt.cc.jj 2026-06-25 10:03:50.817436390 +0200
+++ gcc/cp/pt.cc 2026-07-02 23:20:13.328152342 +0200
@@ -19602,6 +19602,7 @@ tsubst_decomp_names (tree decl, tree pat
tsubst_flags_t complain, tree in_decl, cp_decomp *decomp)
{
tree decl2, decl3, prev = decl;
+ bool fail = false;
decomp->count = 0;
gcc_assert (DECL_NAME (decl) == NULL_TREE);
for (decl2 = DECL_CHAIN (pattern_decl);
@@ -19613,7 +19614,8 @@ tsubst_decomp_names (tree decl, tree pat
if (TREE_TYPE (decl2) == error_mark_node && decomp->count == 0)
{
gcc_assert (errorcount);
- return error_mark_node;
+ fail = true;
+ goto out;
}
decomp->count++;
gcc_assert (DECL_DECOMP_BASE (decl2) == pattern_decl);
@@ -19629,23 +19631,33 @@ tsubst_decomp_names (tree decl, tree pat
else
{
gcc_assert (errorcount);
- decl = error_mark_node;
+ fail = true;
continue;
}
maybe_push_decl (decl3);
if (error_operand_p (decl3))
- decl = error_mark_node;
- else if (decl != error_mark_node
+ fail = true;
+ else if (!fail
&& DECL_CHAIN (decl3) != prev
&& decl != prev)
{
gcc_assert (errorcount);
- decl = error_mark_node;
+ fail = true;
}
else
prev = decl3;
}
decomp->decl = prev;
+out:
+ if (fail)
+ {
+ if (TREE_STATIC (decl))
+ {
+ tree id = get_identifier ("<decomp>");
+ SET_DECL_ASSEMBLER_NAME (decl, id);
+ }
+ decl = error_mark_node;
+ }
return decl;
}
--- gcc/testsuite/g++.dg/cpp2a/decomp11.C.jj 2026-07-01 19:28:37.892148276
+0200
+++ gcc/testsuite/g++.dg/cpp2a/decomp11.C 2026-07-01 19:28:18.524391284
+0200
@@ -0,0 +1,12 @@
+// PR c++/126057
+// { dg-do compile { target c++20 } }
+
+template <typename T>
+int
+foo ()
+{
+ static auto [a] = 0; // { dg-error "cannot decompose non-array non-class
type 'int'" }
+ return 0;
+}
+
+int a = foo <int> ();
Jakub