Message ID | 65c844ee.170a0220.88382.a8fa@mx.google.com |
---|---|
State | New |
Headers | show |
Series | c++: Support lambdas attached to FIELD_DECLs in modules [PR111710] | expand |
On Sat, Feb 10, 2024 at 7:55 PM Nathaniel Shead <nathanieloshead@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 <nathanieloshead@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 >
On Sat, Feb 10, 2024 at 08:01:46PM -0800, Andrew Pinski wrote: > On Sat, Feb 10, 2024 at 7:55 PM Nathaniel Shead > <nathanieloshead@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 > I took a quick look at the issues linked to the above. I tried a few and they don't seem to be fixed with these patches; in general I would only expect changes in modules or potentially with lambdas being used in base class specifiers, neither of which seem particularly relevant to those issues. Nathaniel > > > > 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 <nathanieloshead@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 > >
On Sun, Feb 11, 2024 at 02:54:18PM +1100, Nathaniel Shead 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. > > 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. Hi Nathaniel, > 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: sorry to be pointing out nits, but this CL entry is missing a description. No need to repost the patch because of that, of couse. Marek
On 2/10/24 22:54, Nathaniel Shead 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. > > 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. You mean the lambda in the type of E::f? That happens because when we see a class in the body of another class, we treat it as a member even if it's a closure. This ought to work fine. It also works with the suggested direction for https://github.com/itanium-cxx-abi/cxx-abi/issues/165 So, the patch is OK with the missing ChangeLog bits filled in. Do we also need to key lambdas to concepts? template <class T> concept L = requires { []{ T(); }; }; > 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 <nathanieloshead@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 > }
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 }
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. 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 <nathanieloshead@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(-)