aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/pt.c37
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-vla1.C16
3 files changed, 51 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3fc1b31..cfc9c62 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2020-01-21 Jason Merrill <jason@redhat.com>
+
+ 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 <iain@sandoe.co.uk>
Bin Cheng <bin.cheng@linux.alibaba.com>
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index cad9751..4520c99 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 0000000..c9025c7
--- /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<typename T>
+int foo(T t) {
+ char buf[SIZE] = { 24 };
+ return [&buf](auto x){ return buf[x]; }(t);
+}
+
+int main() {
+ if (foo(0) != 24)
+ __builtin_abort();
+}