diff options
author | Jason Merrill <jason@redhat.com> | 2018-02-01 21:07:09 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2018-02-01 21:07:09 -0500 |
commit | fe23b12a23e357103a40fda08df33f3547f112e6 (patch) | |
tree | 1eeccbcc99f8325a3a6b6c4e7886433ffdff17e1 /gcc | |
parent | 60a57222fe2166519b54641766bccab92fa15606 (diff) | |
download | gcc-fe23b12a23e357103a40fda08df33f3547f112e6.zip gcc-fe23b12a23e357103a40fda08df33f3547f112e6.tar.gz gcc-fe23b12a23e357103a40fda08df33f3547f112e6.tar.bz2 |
PR c++/84160 - ICE with nested variadic capture.
* lambda.c (is_capture_proxy_with_ref): New.
(insert_capture_proxy): Don't set DECL_CAPTURED_VARIABLE from a
COMPONENT_REF.
* expr.c (mark_use): Use is_capture_proxy_with_ref.
* constexpr.c (potential_constant_expression_1): Likewise.
* semantics.c (process_outer_var_ref): Likewise.
From-SVN: r257325
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/expr.c | 4 | ||||
-rw-r--r-- | gcc/cp/lambda.c | 32 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic6.C | 12 |
7 files changed, 53 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5b6c75a..7285975 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2018-02-01 Jason Merrill <jason@redhat.com> + + PR c++/84160 - ICE with nested variadic capture. + * lambda.c (is_capture_proxy_with_ref): New. + (insert_capture_proxy): Don't set DECL_CAPTURED_VARIABLE from a + COMPONENT_REF. + * expr.c (mark_use): Use is_capture_proxy_with_ref. + * constexpr.c (potential_constant_expression_1): Likewise. + * semantics.c (process_outer_var_ref): Likewise. + 2018-02-01 Marek Polacek <polacek@redhat.com> PR c++/84125 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 1390405..171c389 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -5369,7 +5369,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case VAR_DECL: if (DECL_HAS_VALUE_EXPR_P (t)) { - if (now && is_normal_capture_proxy (t)) + if (now && is_capture_proxy_with_ref (t)) { /* -- in a lambda-expression, a reference to this or to a variable with automatic storage duration defined outside that diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5f14e51..a53f4fd 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6901,6 +6901,7 @@ extern void insert_capture_proxy (tree); extern void insert_pending_capture_proxies (void); extern bool is_capture_proxy (tree); extern bool is_normal_capture_proxy (tree); +extern bool is_capture_proxy_with_ref (tree); extern void register_capture_members (tree); extern tree lambda_expr_this_capture (tree, bool); extern void maybe_generic_this_capture (tree, tree); diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 2e67986..b2c8cfa 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -111,7 +111,7 @@ mark_use (tree expr, bool rvalue_p, bool read_p, { case VAR_DECL: case PARM_DECL: - if (rvalue_p && is_normal_capture_proxy (expr)) + if (rvalue_p && is_capture_proxy_with_ref (expr)) { /* Look through capture by copy. */ tree cap = DECL_CAPTURED_VARIABLE (expr); @@ -154,7 +154,7 @@ mark_use (tree expr, bool rvalue_p, bool read_p, { /* Try to look through the reference. */ tree ref = TREE_OPERAND (expr, 0); - if (rvalue_p && is_normal_capture_proxy (ref)) + if (rvalue_p && is_capture_proxy_with_ref (ref)) { /* Look through capture by reference. */ tree cap = DECL_CAPTURED_VARIABLE (ref); diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index e1caaef..ff8236a 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -290,13 +290,24 @@ is_normal_capture_proxy (tree decl) return DECL_NORMAL_CAPTURE_P (val); } +/* Returns true iff DECL is a capture proxy for which we can use + DECL_CAPTURED_VARIABLE. In effect, this is a normal proxy other than a + nested capture of a function parameter pack. */ + +bool +is_capture_proxy_with_ref (tree var) +{ + return (is_normal_capture_proxy (var) && DECL_LANG_SPECIFIC (var) + && DECL_CAPTURED_VARIABLE (var)); +} + /* VAR is a capture proxy created by build_capture_proxy; add it to the current function, which is the operator() for the appropriate lambda. */ void insert_capture_proxy (tree var) { - if (is_normal_capture_proxy (var)) + if (is_capture_proxy_with_ref (var)) { tree cap = DECL_CAPTURED_VARIABLE (var); if (CHECKING_P) @@ -443,11 +454,20 @@ build_capture_proxy (tree member, tree init) init = TREE_OPERAND (init, 0); STRIP_NOPS (init); } - gcc_assert (VAR_P (init) || TREE_CODE (init) == PARM_DECL); - while (is_normal_capture_proxy (init)) - init = DECL_CAPTURED_VARIABLE (init); - retrofit_lang_decl (var); - DECL_CAPTURED_VARIABLE (var) = init; + + if (TREE_CODE (init) == COMPONENT_REF) + /* We're capturing a capture of a function parameter pack, and have + lost track of the original variable. It's not important to have + DECL_CAPTURED_VARIABLE in this case, since a function parameter pack + isn't a constant variable, so don't bother trying to set it. */; + else + { + gcc_assert (VAR_P (init) || TREE_CODE (init) == PARM_DECL); + while (is_normal_capture_proxy (init)) + init = DECL_CAPTURED_VARIABLE (init); + retrofit_lang_decl (var); + DECL_CAPTURED_VARIABLE (var) = init; + } } if (name == this_identifier) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 7616034..ea92da3 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3321,7 +3321,7 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use) { /* Check whether we've already built a proxy. */ tree var = decl; - while (is_normal_capture_proxy (var)) + while (is_capture_proxy_with_ref (var)) var = DECL_CAPTURED_VARIABLE (var); tree d = retrieve_local_specialization (var); diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic6.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic6.C new file mode 100644 index 0000000..d9707d0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic6.C @@ -0,0 +1,12 @@ +// PR c++/84160 +// { dg-do compile { target c++11 } } + +template < typename ... T > void f (T ... a) +{ + [a ...] { [a ...] {}; }; +} + +void g () +{ + f < int > (0); +} |