Hi, thanks for the patch! On Fri, 15 Aug 2025, seha-bot wrote:
> From: Nedim Šehić <nedimsehi...@gmail.com> > > Regtested on x86_64-pc-linux-gnu. > > This patch fixes deduction for member array types from parenthesized > initializers which use braces and string literals. > > PR c++/121518 > > gcc/cp/ChangeLog: > > * pt.cc (maybe_aggr_guide): Add deduction for brace and string > literal initializer cases. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp2a/class-deduction-aggr17.C: New test. > > Co-Authored-By: Nathaniel Shead <nathanielosh...@gmail.com> > Signed-off-by: Nedim Šehić <nedimsehi...@gmail.com> > --- > gcc/cp/pt.cc | 22 +++-- > .../g++.dg/cpp2a/class-deduction-aggr17.C | 88 +++++++++++++++++++ > 2 files changed, 105 insertions(+), 5 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr17.C > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index b6b13edd03f..35c3ce517e8 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -31116,22 +31116,34 @@ maybe_aggr_guide (tree tmpl, tree init, > vec<tree,va_gc> *args) > } > else if (TREE_CODE (init) == TREE_LIST) > { > - int len = list_length (init); > + tree elt = init; > for (tree binfo : BINFO_BASE_BINFOS (TYPE_BINFO (template_type))) > { > - if (!len) > + if (!elt) > break; > parms = tree_cons (NULL_TREE, BINFO_TYPE (binfo), parms); > - --len; > + elt = TREE_CHAIN (elt); > } > for (tree field = TYPE_FIELDS (template_type); > - len; > - --len, field = DECL_CHAIN (field)) > + elt; > + elt = TREE_CHAIN (elt), field = DECL_CHAIN (field)) The identation seems off in this hunk. > { > field = next_aggregate_field (field); > if (!field) > return NULL_TREE; > tree ftype = finish_decltype_type (field, true, complain); > + tree arg = tree_strip_any_location_wrapper (TREE_VALUE (elt)); > + if (TREE_CODE (ftype) == ARRAY_TYPE) > + { > + if (BRACE_ENCLOSED_INITIALIZER_P (arg)) > + ftype = cp_build_reference_type (ftype, true); > + else if (TREE_CODE (arg) == STRING_CST) > + { > + ftype = cp_build_qualified_type > + (ftype, cp_type_quals (ftype) | TYPE_QUAL_CONST); > + ftype = cp_build_reference_type (ftype, false); > + } > + } Indentation seems off here too. And I think we could sink the variable 'arg' into the if. Besides that, LGTM, we have similar logic in collect_ctor_idx_types (for aggregate CTAD from {} rather than ()). I guess duplicating it isn't ideal but I don't mind too much. Jason, what do you think? > parms = tree_cons (NULL_TREE, ftype, parms); > } > } > diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr17.C > b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr17.C > new file mode 100644 > index 00000000000..9fa63369426 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr17.C > @@ -0,0 +1,88 @@ > +// PR c++/121518 > +// { dg-do compile { target c++20 } } > + > +#include <cstddef> > +#include <utility> > + > +template <std::size_t N> > +struct Str { > + char x[N]{}; > +}; > + > +struct MovableType { > + MovableType() = default; > + MovableType(MovableType const&) = delete; > + MovableType(MovableType&&) = default; > +}; > + > +struct ImmovableType { > + ImmovableType() = default; > + ImmovableType(ImmovableType&&) = delete; > +}; > + > +template <typename T, std::size_t N> > +struct Deduct { > + T x[N]{}; > +}; > + > +template<class, class> struct same; > +template<class T> struct same<T, T> {}; > + > +Str s0("a"); > +same<decltype(s0), Str<2>> c0; > +Str s1{"a"}; > +same<decltype(s1), Str<2>> c1; > +Str s2 = {"a"}; > +same<decltype(s2), Str<2>> c2; > + > +Str s3({'a', '\0'}); > +same<decltype(s3), Str<2>> c3; > +Str s4{{'a', '\0'}}; > +same<decltype(s4), Str<2>> c4; > +Str s5 = {{'a', '\0'}}; > +same<decltype(s5), Str<2>> c5; > + > +Deduct ds0("a"); > +same<decltype(ds0), Deduct<char, 2>> c15; > +Deduct ds1{"a"}; > +same<decltype(ds1), Deduct<char, 2>> c16; > +Deduct ds2 = {"a"}; > +same<decltype(ds2), Deduct<char, 2>> c17; > + > +Deduct ds3({'a', '\0'}); > +same<decltype(ds3), Deduct<char, 2>> c18; > +Deduct ds4{{'a', '\0'}}; > +same<decltype(ds4), Deduct<char, 2>> c19; > +Deduct ds5 = {{'a', '\0'}}; > +same<decltype(ds5), Deduct<char, 2>> c20; > + > +MovableType mt; > +Deduct dm0({MovableType{}}); > +same<decltype(dm0), Deduct<MovableType, 1>> c21; > +Deduct dm1({MovableType{}, std::move(mt)}); > +same<decltype(dm1), Deduct<MovableType, 2>> c22; > + > +Deduct dm2{{MovableType{}}}; > +same<decltype(dm2), Deduct<MovableType, 1>> c23; > +Deduct dm3{{MovableType{}, std::move(mt)}}; > +same<decltype(dm3), Deduct<MovableType, 2>> c24; > + > +Deduct dm4 = {{MovableType{}}}; > +same<decltype(dm4), Deduct<MovableType, 1>> c25; > +Deduct dm5 = {{MovableType{}, std::move(mt)}}; > +same<decltype(dm5), Deduct<MovableType, 2>> c26; > + > +Deduct dm6({MovableType{}, mt}); // { dg-error "use of deleted function" } > + > +ImmovableType it; > +Deduct di0({ImmovableType{}}); > +same<decltype(di0), Deduct<ImmovableType, 1>> c27; > +Deduct di1({ImmovableType{}, std::move(it)}); // { dg-error "use of deleted > function" } > + > +Deduct di2{{ImmovableType{}}}; > +same<decltype(di2), Deduct<ImmovableType, 1>> c28; > +Deduct di3{{ImmovableType{}, std::move(it)}}; // { dg-error "use of deleted > function" } > + > +Deduct di4 = {{ImmovableType{}}}; > +same<decltype(di4), Deduct<ImmovableType, 1>> c29; > +Deduct di5 = {{ImmovableType{}, std::move(it)}}; // { dg-error "use of > deleted function" } > -- > 2.50.1 > >