https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118513
Bug ID: 118513 Summary: ICE with modules and structured binding using std::tuple* Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: jakub at gcc dot gnu.org Target Milestone: --- --- gcc/testsuite/g++.dg/modules/decomp-3_a.H.jj 2025-01-16 13:43:36.492879734 +0100 +++ gcc/testsuite/g++.dg/modules/decomp-3_a.H 2025-01-16 13:43:11.314224231 +0100 @@ -0,0 +1,19 @@ +// { dg-additional-options -fmodule-header } +// { dg-module-cmi {} } + +namespace std { + template<typename T> struct tuple_size; + template<int, typename> struct tuple_element; +} + +struct A { + int a, b; + template <int I> int &get () { if (I == 0) return a; else return b; } +}; + +template <> struct std::tuple_size <A> { static const int value = 2; }; +template <int I> struct std::tuple_element <I, A> { using type = int; }; + +namespace { +auto [x, y] = A { 42, 43 }; +} --- gcc/testsuite/g++.dg/modules/decomp-3_b.C.jj 2025-01-16 13:43:41.782807354 +0100 +++ gcc/testsuite/g++.dg/modules/decomp-3_b.C 2025-01-16 13:41:49.256346946 +0100 @@ -0,0 +1,11 @@ +// { dg-do run } +// { dg-additional-options "-fmodules-ts" } + +import "decomp-3_a.H"; + +int +main () +{ + if (x != 42 || y != 43) + __builtin_abort (); +} testcase ICEs with FAIL: g++.dg/modules/decomp-3_b.C -std=c++17 (internal compiler error: in import_export_decl, at cp/decl2.cc:3442) FAIL: g++.dg/modules/decomp-3_b.C -std=c++17 (test for excess errors) FAIL: g++.dg/modules/decomp-3_b.C -std=c++2a (internal compiler error: in import_export_decl, at cp/decl2.cc:3442) FAIL: g++.dg/modules/decomp-3_b.C -std=c++2a (test for excess errors) FAIL: g++.dg/modules/decomp-3_b.C -std=c++2b (internal compiler error: in import_export_decl, at cp/decl2.cc:3442) FAIL: g++.dg/modules/decomp-3_b.C -std=c++2b (test for excess errors) If I use #include "decomp-3_a.H" instead of import "decomp-3_a.H"; then the x and y VAR_DECLs, initially TREE_PUBLIC, first go through (in cp_finish_decomp) through layout_decl (v[i], 0);, then copy_linkage (v[i], decl); which among other things clears TREE_PUBLIC and then cp_finish_decl (v[i], init, /*constexpr*/false, /*asm*/NULL_TREE, LOOKUP_NORMAL); which among other things calls 9291 make_rtl_for_nonlocal_decl (decl, init, asmspec); and so var_finalized_p is since then true, so write_out_vars does nothing for it. Now, when reading the module header, the VAR_DECLs are streamed in with proper !TREE_PUBLIC flag, but var_finalized_p is not true, and as the var doesn't have DECL_INTERFACE_KNOWN, we ICE in import_export_decl. I'm afraid I have no idea what should be done in the module case, whether the vars need to be finalized somewhere during the streaming in (just namespace scope structured bindings, something else?) or whether something should arrange for DECL_INTERFACE_KNOWN to be set for those.