Commit 43b781fa by Jason Merrill Committed by Jason Merrill

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
parent 62da5a07
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> 2014-05-02 Marek Polacek <polacek@redhat.com>
* typeck.c (maybe_warn_about_returning_address_of_local): Separate * typeck.c (maybe_warn_about_returning_address_of_local): Separate
......
...@@ -5773,6 +5773,7 @@ extern bool is_sub_constant_expr (tree); ...@@ -5773,6 +5773,7 @@ extern bool is_sub_constant_expr (tree);
extern bool reduced_constant_expression_p (tree); extern bool reduced_constant_expression_p (tree);
extern void explain_invalid_constexpr_fn (tree); extern void explain_invalid_constexpr_fn (tree);
extern vec<tree> cx_error_context (void); extern vec<tree> cx_error_context (void);
extern bool is_this_parameter (tree);
enum { enum {
BCS_NO_SCOPE = 1, BCS_NO_SCOPE = 1,
......
...@@ -216,8 +216,8 @@ lambda_capture_field_type (tree expr, bool explicit_init_p) ...@@ -216,8 +216,8 @@ lambda_capture_field_type (tree expr, bool explicit_init_p)
} }
else else
type = non_reference (unlowered_expr_type (expr)); type = non_reference (unlowered_expr_type (expr));
if (!type || WILDCARD_TYPE_P (type) || type_uses_auto (type) if (type_dependent_expression_p (expr)
|| DECL_PACK_P (expr)) && !is_this_parameter (tree_strip_nop_conversions (expr)))
{ {
type = cxx_make_type (DECLTYPE_TYPE); type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = expr; DECLTYPE_TYPE_EXPR (type) = expr;
...@@ -455,7 +455,7 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p, ...@@ -455,7 +455,7 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
if (TREE_CODE (initializer) == TREE_LIST) if (TREE_CODE (initializer) == TREE_LIST)
initializer = build_x_compound_expr_from_list (initializer, ELK_INIT, initializer = build_x_compound_expr_from_list (initializer, ELK_INIT,
tf_warning_or_error); tf_warning_or_error);
type = lambda_capture_field_type (initializer, explicit_init_p); type = TREE_TYPE (initializer);
if (array_of_runtime_bound_p (type)) if (array_of_runtime_bound_p (type))
{ {
vla = true; vla = true;
...@@ -482,7 +482,10 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p, ...@@ -482,7 +482,10 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
"variable size", TREE_TYPE (type)); "variable size", TREE_TYPE (type));
type = error_mark_node; type = error_mark_node;
} }
else if (by_reference_p) else
{
type = lambda_capture_field_type (initializer, explicit_init_p);
if (by_reference_p)
{ {
type = build_reference_type (type); type = build_reference_type (type);
if (!real_lvalue_p (initializer)) if (!real_lvalue_p (initializer))
...@@ -491,6 +494,7 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p, ...@@ -491,6 +494,7 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
else else
/* Capture by copy requires a complete type. */ /* Capture by copy requires a complete type. */
type = complete_type (type); type = complete_type (type);
}
/* Add __ to the beginning of the field name so that user code /* 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 won't find the field with name lookup. We can't just leave the name
......
...@@ -12629,13 +12629,17 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -12629,13 +12629,17 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
} }
else else
{ {
/* This can happen for a variable used in a late-specified /* This can happen for a variable used in a
return type of a local lambda. Just make a dummy decl late-specified return type of a local lambda, or for a
since it's only used for its type. */ local static or constant. Building a new VAR_DECL
if (cp_unevaluated_operand) should be OK in all those cases. */
return tsubst_decl (t, args, complain); r = tsubst_decl (t, args, complain);
gcc_assert (errorcount || sorrycount); if (decl_constant_var_p (r))
return error_mark_node; /* 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;
} }
} }
} }
......
...@@ -8155,10 +8155,11 @@ maybe_initialize_constexpr_call_table (void) ...@@ -8155,10 +8155,11 @@ maybe_initialize_constexpr_call_table (void)
/* Return true if T designates the implied `this' parameter. */ /* Return true if T designates the implied `this' parameter. */
static inline bool bool
is_this_parameter (tree t) 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 /* We have an expression tree T that represents a call, either CALL_EXPR
......
// 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment