Commit 0e81aa85 by Jason Merrill Committed by Jason Merrill

re PR c++/50437 ([C++0x] [4.7 regression] ICE for trivial use of lambda in template function)

	PR c++/50437
	* cp-tree.h (struct tree_lambda_expr): Add closure field.
	(LAMBDA_EXPR_CLOSURE): New.
	* pt.c (tsubst_copy_and_build) [LAMBDA_EXPR]: Likewise.
	* semantics.c (build_lambda_object): Use it instead of TREE_TYPE.
	(begin_lambda_type, lambda_function, add_capture): Likewise.
	(add_default_capture, lambda_expr_this_capture): Likewise.

From-SVN: r179944
parent f1c141a7
2011-10-13 Jason Merrill <jason@redhat.com>
PR c++/50437
* cp-tree.h (struct tree_lambda_expr): Add closure field.
(LAMBDA_EXPR_CLOSURE): New.
* pt.c (tsubst_copy_and_build) [LAMBDA_EXPR]: Likewise.
* semantics.c (build_lambda_object): Use it instead of TREE_TYPE.
(begin_lambda_type, lambda_function, add_capture): Likewise.
(add_default_capture, lambda_expr_this_capture): Likewise.
2011-10-13 Diego Novillo <dnovillo@google.com> 2011-10-13 Diego Novillo <dnovillo@google.com>
* cp-tree.h (struct language_function): Rename in_function_try_handler * cp-tree.h (struct language_function): Rename in_function_try_handler
......
...@@ -671,6 +671,12 @@ enum cp_lambda_default_capture_mode_type { ...@@ -671,6 +671,12 @@ enum cp_lambda_default_capture_mode_type {
#define LAMBDA_EXPR_PENDING_PROXIES(NODE) \ #define LAMBDA_EXPR_PENDING_PROXIES(NODE) \
(((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->pending_proxies) (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->pending_proxies)
/* The closure type of the lambda. Note that the TREE_TYPE of a
LAMBDA_EXPR is always NULL_TREE, because we need to instantiate the
LAMBDA_EXPR in order to instantiate the type. */
#define LAMBDA_EXPR_CLOSURE(NODE) \
(((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->closure)
struct GTY (()) tree_lambda_expr struct GTY (()) tree_lambda_expr
{ {
struct tree_typed typed; struct tree_typed typed;
...@@ -678,6 +684,7 @@ struct GTY (()) tree_lambda_expr ...@@ -678,6 +684,7 @@ struct GTY (()) tree_lambda_expr
tree this_capture; tree this_capture;
tree return_type; tree return_type;
tree extra_scope; tree extra_scope;
tree closure;
VEC(tree,gc)* pending_proxies; VEC(tree,gc)* pending_proxies;
location_t locus; location_t locus;
enum cp_lambda_default_capture_mode_type default_capture_mode; enum cp_lambda_default_capture_mode_type default_capture_mode;
......
...@@ -13937,8 +13937,8 @@ tsubst_copy_and_build (tree t, ...@@ -13937,8 +13937,8 @@ tsubst_copy_and_build (tree t,
{ {
tree r = build_lambda_expr (); tree r = build_lambda_expr ();
tree type = tsubst (TREE_TYPE (t), args, complain, NULL_TREE); tree type = tsubst (LAMBDA_EXPR_CLOSURE (t), args, complain, NULL_TREE);
TREE_TYPE (r) = type; LAMBDA_EXPR_CLOSURE (r) = type;
CLASSTYPE_LAMBDA_EXPR (type) = r; CLASSTYPE_LAMBDA_EXPR (type) = r;
LAMBDA_EXPR_LOCATION (r) LAMBDA_EXPR_LOCATION (r)
......
...@@ -8324,7 +8324,7 @@ build_lambda_object (tree lambda_expr) ...@@ -8324,7 +8324,7 @@ build_lambda_object (tree lambda_expr)
/* N2927: "[The closure] class type is not an aggregate." /* N2927: "[The closure] class type is not an aggregate."
But we briefly treat it as an aggregate to make this simpler. */ But we briefly treat it as an aggregate to make this simpler. */
type = TREE_TYPE (lambda_expr); type = LAMBDA_EXPR_CLOSURE (lambda_expr);
CLASSTYPE_NON_AGGREGATE (type) = 0; CLASSTYPE_NON_AGGREGATE (type) = 0;
expr = finish_compound_literal (type, expr, tf_warning_or_error); expr = finish_compound_literal (type, expr, tf_warning_or_error);
CLASSTYPE_NON_AGGREGATE (type) = 1; CLASSTYPE_NON_AGGREGATE (type) = 1;
...@@ -8365,7 +8365,7 @@ begin_lambda_type (tree lambda) ...@@ -8365,7 +8365,7 @@ begin_lambda_type (tree lambda)
type = begin_class_definition (type, /*attributes=*/NULL_TREE); type = begin_class_definition (type, /*attributes=*/NULL_TREE);
/* Cross-reference the expression and the type. */ /* Cross-reference the expression and the type. */
TREE_TYPE (lambda) = type; LAMBDA_EXPR_CLOSURE (lambda) = type;
CLASSTYPE_LAMBDA_EXPR (type) = lambda; CLASSTYPE_LAMBDA_EXPR (type) = lambda;
return type; return type;
...@@ -8399,7 +8399,7 @@ lambda_function (tree lambda) ...@@ -8399,7 +8399,7 @@ lambda_function (tree lambda)
{ {
tree type; tree type;
if (TREE_CODE (lambda) == LAMBDA_EXPR) if (TREE_CODE (lambda) == LAMBDA_EXPR)
type = TREE_TYPE (lambda); type = LAMBDA_EXPR_CLOSURE (lambda);
else else
type = lambda; type = lambda;
gcc_assert (LAMBDA_TYPE_P (type)); gcc_assert (LAMBDA_TYPE_P (type));
...@@ -8714,7 +8714,7 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, ...@@ -8714,7 +8714,7 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
/* If TREE_TYPE isn't set, we're still in the introducer, so check /* If TREE_TYPE isn't set, we're still in the introducer, so check
for duplicates. */ for duplicates. */
if (!TREE_TYPE (lambda)) if (!LAMBDA_EXPR_CLOSURE (lambda))
{ {
if (IDENTIFIER_MARKED (name)) if (IDENTIFIER_MARKED (name))
{ {
...@@ -8740,13 +8740,14 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, ...@@ -8740,13 +8740,14 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
LAMBDA_EXPR_THIS_CAPTURE (lambda) = member; LAMBDA_EXPR_THIS_CAPTURE (lambda) = member;
/* Add it to the appropriate closure class if we've started it. */ /* Add it to the appropriate closure class if we've started it. */
if (current_class_type && current_class_type == TREE_TYPE (lambda)) if (current_class_type
&& current_class_type == LAMBDA_EXPR_CLOSURE (lambda))
finish_member_declaration (member); finish_member_declaration (member);
LAMBDA_EXPR_CAPTURE_LIST (lambda) LAMBDA_EXPR_CAPTURE_LIST (lambda)
= tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda)); = tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
if (TREE_TYPE (lambda)) if (LAMBDA_EXPR_CLOSURE (lambda))
return build_capture_proxy (member); return build_capture_proxy (member);
/* For explicit captures we haven't started the function yet, so we wait /* For explicit captures we haven't started the function yet, so we wait
and build the proxy from cp_parser_lambda_body. */ and build the proxy from cp_parser_lambda_body. */
...@@ -8789,7 +8790,7 @@ add_default_capture (tree lambda_stack, tree id, tree initializer) ...@@ -8789,7 +8790,7 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
{ {
tree lambda = TREE_VALUE (node); tree lambda = TREE_VALUE (node);
current_class_type = TREE_TYPE (lambda); current_class_type = LAMBDA_EXPR_CLOSURE (lambda);
var = add_capture (lambda, var = add_capture (lambda,
id, id,
initializer, initializer,
...@@ -8820,7 +8821,7 @@ lambda_expr_this_capture (tree lambda) ...@@ -8820,7 +8821,7 @@ lambda_expr_this_capture (tree lambda)
if (!this_capture if (!this_capture
&& LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE) && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)
{ {
tree containing_function = TYPE_CONTEXT (TREE_TYPE (lambda)); tree containing_function = TYPE_CONTEXT (LAMBDA_EXPR_CLOSURE (lambda));
tree lambda_stack = tree_cons (NULL_TREE, lambda, NULL_TREE); tree lambda_stack = tree_cons (NULL_TREE, lambda, NULL_TREE);
tree init = NULL_TREE; tree init = NULL_TREE;
...@@ -8870,7 +8871,8 @@ lambda_expr_this_capture (tree lambda) ...@@ -8870,7 +8871,8 @@ lambda_expr_this_capture (tree lambda)
else else
{ {
/* To make sure that current_class_ref is for the lambda. */ /* To make sure that current_class_ref is for the lambda. */
gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) == TREE_TYPE (lambda)); gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref))
== LAMBDA_EXPR_CLOSURE (lambda));
result = this_capture; result = this_capture;
......
2011-10-13 Jason Merrill <jason@redhat.com> 2011-10-13 Jason Merrill <jason@redhat.com>
PR c++/50437
* g++.dg/cpp0x/lambda/lambda-auto1.C: New.
PR c++/50618 PR c++/50618
* g++.dg/init/vbase1.C: New. * g++.dg/init/vbase1.C: New.
......
// PR c++/50437
// { dg-options -std=c++0x }
template <typename T>
void f()
{
auto g = [](T t){ return t == 0; };
g(T());
}
int main()
{
f<int>();
}
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