From 276265195a4e7362b34ac512f3bc0ad5a974dcff Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 21 Jan 2020 13:22:35 -0500 Subject: [PATCH] PR c++/90732 - ICE with VLA capture and generic lambda. We were failing to handle VLA capture in tsubst_lambda_expr; initially building a DECLTYPE_TYPE for the capture and then tsubsting it doesn't give the special VLA handling. So with this patch we call add_capture again for VLAs. * pt.c (tsubst_lambda_expr): Repeat add_capture for VLAs. --- gcc/cp/ChangeLog | 5 ++++ gcc/cp/pt.c | 37 +++++++++++++++++++----- gcc/testsuite/g++.dg/cpp1y/lambda-vla1.C | 16 ++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-vla1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3fc1b31e5cd..cfc9c62371f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2020-01-21 Jason Merrill + + PR c++/90732 - ICE with VLA capture and generic lambda. + * pt.c (tsubst_lambda_expr): Repeat add_capture for VLAs. + 2020-01-21 Iain Sandoe Bin Cheng diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index cad97514cdc..4520c995028 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18751,6 +18751,36 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) cap = TREE_CHAIN (cap)) { tree ofield = TREE_PURPOSE (cap); + tree init = TREE_VALUE (cap); + if (PACK_EXPANSION_P (init)) + init = tsubst_pack_expansion (init, args, complain, in_decl); + else + init = tsubst_copy_and_build (init, args, complain, in_decl, + /*fn*/false, /*constexpr*/false); + + if (init == error_mark_node) + return error_mark_node; + + if (init && TREE_CODE (init) == TREE_LIST) + init = build_x_compound_expr_from_list (init, ELK_INIT, complain); + + if (!processing_template_decl + && init && TREE_CODE (init) != TREE_VEC + && variably_modified_type_p (TREE_TYPE (init), NULL_TREE)) + { + /* For a VLA, simply tsubsting the field type won't work, we need to + go through add_capture again. XXX do we want to do this for all + captures? */ + tree name = (get_identifier + (IDENTIFIER_POINTER (DECL_NAME (ofield)) + 2)); + tree ftype = TREE_TYPE (ofield); + bool by_ref = (TYPE_REF_P (ftype) + || (TREE_CODE (ftype) == DECLTYPE_TYPE + && DECLTYPE_FOR_REF_CAPTURE (ftype))); + add_capture (r, name, init, by_ref, !DECL_NORMAL_CAPTURE_P (ofield)); + continue; + } + if (PACK_EXPANSION_P (ofield)) ofield = PACK_EXPANSION_PATTERN (ofield); tree field = tsubst_decl (ofield, args, complain); @@ -18765,13 +18795,6 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (field == error_mark_node) return error_mark_node; - tree init = TREE_VALUE (cap); - if (PACK_EXPANSION_P (init)) - init = tsubst_pack_expansion (init, args, complain, in_decl); - else - init = tsubst_copy_and_build (init, args, complain, in_decl, - /*fn*/false, /*constexpr*/false); - if (TREE_CODE (field) == TREE_VEC) { int len = TREE_VEC_LENGTH (field); diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-vla1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-vla1.C new file mode 100644 index 00000000000..c9025c79aa7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-vla1.C @@ -0,0 +1,16 @@ +// PR c++/90732 +// { dg-do compile { target c++14 } } +// { dg-additional-options "-Wno-vla" } + +/*const*/ int SIZE = 100; + +template +int foo(T t) { + char buf[SIZE] = { 24 }; + return [&buf](auto x){ return buf[x]; }(t); +} + +int main() { + if (foo(0) != 24) + __builtin_abort(); +} -- 2.30.2