diff options
author | Jason Merrill <jason@redhat.com> | 2014-05-02 15:47:40 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2014-05-02 15:47:40 -0400 |
commit | 43b781fac7673ac9f11105048ccc2a75c8a9f0c3 (patch) | |
tree | 5f8a43ce0d7d633ca950be8f18dfbaf9acef0cbf | |
parent | 62da5a07b2f56f860e70c9bb66791ac665bf14d8 (diff) | |
download | gcc-43b781fac7673ac9f11105048ccc2a75c8a9f0c3.zip gcc-43b781fac7673ac9f11105048ccc2a75c8a9f0c3.tar.gz gcc-43b781fac7673ac9f11105048ccc2a75c8a9f0c3.tar.bz2 |
re PR c++/60992 (ICE in tsubst_copy, at cp/pt.c:12637)
PR c++/60992
* lambda.c (lambda_capture_field_type): Wrap anything dependent
other than 'this'.
(add_capture): Check for VLA before calling it.
* semantics.c (is_this_parameter): Accept any 'this' parameter, not
just the current one. Make non-static.
* cp-tree.h: Declare it.
* pt.c (tsubst_copy) [VAR_DECL]: Also build a new VAR_DECL if
the operand was static or constant.
From-SVN: r210017
-rw-r--r-- | gcc/cp/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/lambda.c | 24 | ||||
-rw-r--r-- | gcc/cp/pt.c | 18 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const3.C | 38 |
6 files changed, 79 insertions, 19 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7729cb9..422e98c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2014-05-02 Jason Merrill <jason@redhat.com> + + PR c++/60992 + * lambda.c (lambda_capture_field_type): Wrap anything dependent + other than 'this'. + (add_capture): Check for VLA before calling it. + * semantics.c (is_this_parameter): Accept any 'this' parameter, not + just the current one. Make non-static. + * cp-tree.h: Declare it. + * pt.c (tsubst_copy) [VAR_DECL]: Also build a new VAR_DECL if + the operand was static or constant. + 2014-05-02 Marek Polacek <polacek@redhat.com> * typeck.c (maybe_warn_about_returning_address_of_local): Separate diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 55ecc4e..34d3d20 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5773,6 +5773,7 @@ extern bool is_sub_constant_expr (tree); extern bool reduced_constant_expression_p (tree); extern void explain_invalid_constexpr_fn (tree); extern vec<tree> cx_error_context (void); +extern bool is_this_parameter (tree); enum { BCS_NO_SCOPE = 1, diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 0b8b46a..5ba6f14 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -216,8 +216,8 @@ lambda_capture_field_type (tree expr, bool explicit_init_p) } else type = non_reference (unlowered_expr_type (expr)); - if (!type || WILDCARD_TYPE_P (type) || type_uses_auto (type) - || DECL_PACK_P (expr)) + if (type_dependent_expression_p (expr) + && !is_this_parameter (tree_strip_nop_conversions (expr))) { type = cxx_make_type (DECLTYPE_TYPE); DECLTYPE_TYPE_EXPR (type) = expr; @@ -455,7 +455,7 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p, if (TREE_CODE (initializer) == TREE_LIST) initializer = build_x_compound_expr_from_list (initializer, ELK_INIT, tf_warning_or_error); - type = lambda_capture_field_type (initializer, explicit_init_p); + type = TREE_TYPE (initializer); if (array_of_runtime_bound_p (type)) { vla = true; @@ -482,15 +482,19 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p, "variable size", TREE_TYPE (type)); type = error_mark_node; } - else if (by_reference_p) + else { - type = build_reference_type (type); - if (!real_lvalue_p (initializer)) - error ("cannot capture %qE by reference", initializer); + type = lambda_capture_field_type (initializer, explicit_init_p); + if (by_reference_p) + { + type = build_reference_type (type); + if (!real_lvalue_p (initializer)) + error ("cannot capture %qE by reference", initializer); + } + else + /* Capture by copy requires a complete type. */ + type = complete_type (type); } - else - /* Capture by copy requires a complete type. */ - type = complete_type (type); /* Add __ to the beginning of the field name so that user code won't find the field with name lookup. We can't just leave the name diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 48cc2a9..1584eb9 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12629,13 +12629,17 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) } else { - /* This can happen for a variable used in a late-specified - return type of a local lambda. Just make a dummy decl - since it's only used for its type. */ - if (cp_unevaluated_operand) - return tsubst_decl (t, args, complain); - gcc_assert (errorcount || sorrycount); - return error_mark_node; + /* This can happen for a variable used in a + late-specified return type of a local lambda, or for a + local static or constant. Building a new VAR_DECL + should be OK in all those cases. */ + r = tsubst_decl (t, args, complain); + if (decl_constant_var_p (r)) + /* A use of a local constant must decay to its value. */ + return integral_constant_value (r); + gcc_assert (cp_unevaluated_operand || TREE_STATIC (r) + || errorcount || sorrycount); + return r; } } } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 3f8ca44..4afb821 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -8155,10 +8155,11 @@ maybe_initialize_constexpr_call_table (void) /* Return true if T designates the implied `this' parameter. */ -static inline bool +bool is_this_parameter (tree t) { - return t == current_class_ptr; + return (TREE_CODE (t) == PARM_DECL + && DECL_NAME (t) == this_identifier); } /* We have an expression tree T that represents a call, either CALL_EXPR diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const3.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const3.C new file mode 100644 index 0000000..a1ffadd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const3.C @@ -0,0 +1,38 @@ +// PR c++/60992 +// { dg-do compile { target c++11 } } + +struct ScopeGuardGenerator { }; + +struct FF +{ + template < class F, class ... Ts > + void + operator () (F & ...) + { + const int n = sizeof ... (Ts) + 1; + void *mutexes[n]; + auto _on_scope_exit_var_0 = + ScopeGuardGenerator () + [&mutexes] { }; + } +}; + +template < class F > +int operator+ (ScopeGuardGenerator, F) { return 1; } + +struct D +{ + template < class T0, class T1, class T2, class ... T > + void + operator () (T0, T1, const T2 & t2, T & ... t) + { + base (t2, t ...); + } + FF base; +}; + +D run_with_locks; + +void Fn () +{ + run_with_locks ([] { }, 0, 0); +} |