Hi, On 20 Dec 2024, at 20:56, Simon Martin wrote:
> Hi, > > On 20 Dec 2024, at 20:37, Simon Martin wrote: > >> We currently fail due to "infinite recursion" on the following invalid >> code with -std=c++20 and above >> >> === cut here === >> template <class T> struct S { struct U { const S s; } u; }; >> S t{2}; >> === cut here === >> >> The problem is that reshape_init_class for S calls reshape_init_r for >> its field S::u, that calls reshape_init_class for S::U, that calls >> reshape_init_r for field S::U::s that calls reshape_init_class for its >> type S, etc. >> >> This patch fixes the issue by erroring out in reshape_init_class if we >> detect that we're about to call reshape_init_r for a type that's part >> of >> our "TYPE_CONTEXT chain". >> >> An alternative was to change the check in grokdeclarator that rejects >> fields with an incomplete type to check for the field type's >> TYPE_BEING_DECLARED (which sounds like the right thing to do), however >> erroring for the definition of U::s breaks a bunch of existing test >> cases, and it would also make us diverge from clang and MSVC (but >> behave >> like EDG) - see https://godbolt.org/z/hT8d1GWa3. It feels to me like >> we >> don't want that (I'm happy to revisit if people think it's OK). >> >> Successfully tested on x86_64-pc-linux-gnu. Ping. Thanks! Simon >> >> PR c++/118078 >> >> gcc/cp/ChangeLog: >> >> * decl.cc (reshape_init_class): Don't trigger infinite recursion >> for invalid "recursive types". >> >> gcc/testsuite/ChangeLog: >> >> * g++.dg/cpp1z/class-deduction118.C: New test. >> * g++.dg/cpp2a/class-deduction-aggr16.C: New test. >> >> --- >> gcc/cp/decl.cc | 21 >> ++++++++++++++++--- >> .../g++.dg/cpp1z/class-deduction118.C | 8 +++++++ >> .../g++.dg/cpp2a/class-deduction-aggr16.C | 7 +++++++ >> 3 files changed, 33 insertions(+), 3 deletions(-) >> create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction118.C >> create mode 100644 >> gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr16.C >> >> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc >> index 42e83f880f9..ea55ea4c0e5 100644 >> --- a/gcc/cp/decl.cc >> +++ b/gcc/cp/decl.cc >> @@ -7315,9 +7315,24 @@ reshape_init_class (tree type, reshape_iter *d, >> bool first_initializer_p, >> d->cur++; >> } >> else >> - field_init = reshape_init_r (TREE_TYPE (field), d, >> - /*first_initializer_p=*/NULL_TREE, >> - complain); >> + { >> + /* Make sure that we won't be calling ourselves recursively, which >> + could happen with "recursive template types" (PR c++/118078). >> */ >> + tree ctx = TYPE_CONTEXT (type); >> + while (ctx && CLASS_TYPE_P (ctx)) >> + { >> + if (ctx == TYPE_MAIN_VARIANT (TREE_TYPE (field))) { > Of course this should be same_type_p (cxx, TYPE_MAIN_VARIANT (TREE_TYPE > (field)))... > > I’m running an extra round of testing with this. Ok assuming the > testing comes back green? > >> + if (complain & tf_error) >> + error ("field %qD has incomplete type %qT", field, >> + TREE_TYPE (field)); >> + return error_mark_node; >> + } >> + ctx = TYPE_CONTEXT (ctx); >> + } >> + field_init = reshape_init_r (TREE_TYPE (field), d, >> + /*first_initializer_p=*/NULL_TREE, >> + complain); >> + } >> >> if (field_init == error_mark_node) >> return error_mark_node; >> diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction118.C >> b/gcc/testsuite/g++.dg/cpp1z/class-deduction118.C >> new file mode 100644 >> index 00000000000..b14d62df793 >> --- /dev/null >> +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction118.C >> @@ -0,0 +1,8 @@ >> +// PR c++/118078 >> +// { dg-do "compile" { target c++11 } } >> + >> +template <class T> >> +struct S { struct U { const S s; } u; }; >> +S t{2}; // { dg-error "invalid use of template-name 'S' without an >> argument list" "" { target c++14_down } } >> + // { dg-error "class template argument deduction failed" "" { >> target c++17 } .-1 } >> + // { dg-error "no matching function for call to 'S\\\(int\\\)'" "" >> { target c++17 } .-2 } >> diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr16.C >> b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr16.C >> new file mode 100644 >> index 00000000000..feab11927c1 >> --- /dev/null >> +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr16.C >> @@ -0,0 +1,7 @@ >> +// PR c++/118078 >> +// { dg-do "compile" { target c++20 } } >> + >> +template <class T> >> +struct S { const struct U { struct V { volatile S s; } v; } u; }; >> +S t{2}; // { dg-error "class template argument deduction failed" } >> + // { dg-error "no matching function for call to 'S\\\(int\\\)'" "" >> { target *-*-* } .-1 } >> -- >> 2.44.0