On Sat, Feb 10, 2024 at 7:55 PM Nathaniel Shead <nathanielosh...@gmail.com> wrote: > > Bootstrapped and regtested (so far just modules.exp and dg.exp) on > x86_64-pc-linux-gnu, OK for trunk if full regtest succeeds? > > (Also I noticed I forgot to add the PR to the changelog in my last > patch, I've fixed that locally.) > > -- >8 -- > > After fixing PR111710, I noticed that we currently ICE when declaring a > type that derives from 'decltype([]{})'. As far as I can tell this > should be legal code, since by [basic.link] p15.2 a lambda defined in a > class-specifier should not be TU-local. > > This patch also adds a bunch of tests for unevaluated lambdas in other > contexts, which generally seem to work now.
There are many unevaluated lambdas (non-modules related) bugs report (all linked to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107430). Do you know if this fixes any of the non-module related ones too? Thanks, Andrew Pinski > > One interesting case is 'E::f' in the attached testcase: it appears to > get a merge kind of 'MK_field', rather than 'MK_keyed' as most other > lambdas do. I'm not entirely sure if this will cause issues in the > future, but I haven't been able to construct a testcase that causes > problems with this, and conversely wrapping the class body in > 'start_lambda_scope' causes issues with symbol duplication in COMDAT > groups, so I've left it as-is for now. > > gcc/cp/ChangeLog: > > * module.cc (trees_out::key_mergeable): Also support TYPE_DECLs. > (maybe_key_decl): Likewise. > * parser.cc (cp_parser_class_head): Start a lambda scope when > parsing base classes. > > gcc/testsuite/ChangeLog: > > * g++.dg/modules/lambda-7_a.C: > * g++.dg/modules/lambda-7_b.C: > > Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> > --- > gcc/cp/module.cc | 8 +++++--- > gcc/cp/parser.cc | 10 ++++++++-- > gcc/testsuite/g++.dg/modules/lambda-7_a.C | 19 +++++++++++++++++++ > gcc/testsuite/g++.dg/modules/lambda-7_b.C | 23 +++++++++++++++++++++++ > 4 files changed, 55 insertions(+), 5 deletions(-) > > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc > index 9742bca922c..cceec79b26b 100644 > --- a/gcc/cp/module.cc > +++ b/gcc/cp/module.cc > @@ -10784,7 +10784,8 @@ trees_out::key_mergeable (int tag, merge_kind mk, > tree decl, tree inner, > (TREE_TYPE (inner))); > gcc_checking_assert (TREE_CODE (scope) == VAR_DECL > || TREE_CODE (scope) == FIELD_DECL > - || TREE_CODE (scope) == PARM_DECL); > + || TREE_CODE (scope) == PARM_DECL > + || TREE_CODE (scope) == TYPE_DECL); > auto *root = keyed_table->get (scope); > unsigned ix = root->length (); > /* If we don't find it, we'll write a really big number > @@ -18980,10 +18981,11 @@ maybe_key_decl (tree ctx, tree decl) > return; > > /* We only need to deal with lambdas attached to var, field, > - or parm decls. */ > + parm, or type decls. */ > if (TREE_CODE (ctx) != VAR_DECL > && TREE_CODE (ctx) != FIELD_DECL > - && TREE_CODE (ctx) != PARM_DECL) > + && TREE_CODE (ctx) != PARM_DECL > + && TREE_CODE (ctx) != TYPE_DECL) > return; > > if (!keyed_table) > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > index 09ecfa23b5d..151e724ed66 100644 > --- a/gcc/cp/parser.cc > +++ b/gcc/cp/parser.cc > @@ -27663,10 +27663,16 @@ cp_parser_class_head (cp_parser* parser, > if (cp_lexer_next_token_is (parser->lexer, CPP_COLON)) > { > if (type) > - pushclass (type); > + { > + pushclass (type); > + start_lambda_scope (TYPE_NAME (type)); > + } > bases = cp_parser_base_clause (parser); > if (type) > - popclass (); > + { > + finish_lambda_scope (); > + popclass (); > + } > } > else > bases = NULL_TREE; > diff --git a/gcc/testsuite/g++.dg/modules/lambda-7_a.C > b/gcc/testsuite/g++.dg/modules/lambda-7_a.C > index 289285cd926..9a23827a280 100644 > --- a/gcc/testsuite/g++.dg/modules/lambda-7_a.C > +++ b/gcc/testsuite/g++.dg/modules/lambda-7_a.C > @@ -18,3 +18,22 @@ export struct S { > export inline int d(int x, int (*f)(int) = [](int x) { return x * 5; }) { > return f(x); > } > + > +// unevaluated lambdas > +#if __cplusplus >= 202002L > +export struct E : decltype([](int x) { return x * 6; }) { > + decltype([](int x) { return x * 7; }) f; > +}; > + > +export template <typename T> > +struct G : decltype([](int x) { return x * 8; }) { > + decltype([](int x) { return x * 9; }) h; > +}; > + > +template <> > +struct G<double> : decltype([](int x) { return x * 10; }) { > + decltype([](int x) { return x * 11; }) i; > +}; > + > +export decltype([](int x) { return x * 12; }) j; > +#endif > diff --git a/gcc/testsuite/g++.dg/modules/lambda-7_b.C > b/gcc/testsuite/g++.dg/modules/lambda-7_b.C > index a8762399ee1..59a82e05cbf 100644 > --- a/gcc/testsuite/g++.dg/modules/lambda-7_b.C > +++ b/gcc/testsuite/g++.dg/modules/lambda-7_b.C > @@ -13,4 +13,27 @@ int main() { > __builtin_abort(); > if (d(10) != 50) > __builtin_abort(); > + > +#if __cplusplus >= 202002L > + E e; > + if (e(10) != 60) > + __builtin_abort(); > + if (e.f(10) != 70) > + __builtin_abort(); > + > + G<int> g1; > + if (g1(10) != 80) > + __builtin_abort(); > + if (g1.h(10) != 90) > + __builtin_abort(); > + > + G<double> g2; > + if (g2(10) != 100) > + __builtin_abort(); > + if (g2.i(10) != 110) > + __builtin_abort(); > + > + if (j(10) != 120) > + __builtin_abort(); > +#endif > } > -- > 2.43.0 >