From: Jason Merrill Date: Thu, 13 Oct 2011 21:23:36 +0000 (-0400) Subject: re PR c++/50437 ([C++0x] [4.7 regression] ICE for trivial use of lambda in template... X-Git-Tag: releases/gcc-4.7.0~3137 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0e81aa85294d479dea3fb9b5a71e6f7242770af6;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 039b155810f2..0322103c9412 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2011-10-13 Jason Merrill + + 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 * cp-tree.h (struct language_function): Rename in_function_try_handler diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1b896b819870..bae6071ebcb7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -671,6 +671,12 @@ enum cp_lambda_default_capture_mode_type { #define LAMBDA_EXPR_PENDING_PROXIES(NODE) \ (((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 tree_typed typed; @@ -678,6 +684,7 @@ struct GTY (()) tree_lambda_expr tree this_capture; tree return_type; tree extra_scope; + tree closure; VEC(tree,gc)* pending_proxies; location_t locus; enum cp_lambda_default_capture_mode_type default_capture_mode; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index bfbd24443254..880f3d1510d5 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13937,8 +13937,8 @@ tsubst_copy_and_build (tree t, { tree r = build_lambda_expr (); - tree type = tsubst (TREE_TYPE (t), args, complain, NULL_TREE); - TREE_TYPE (r) = type; + tree type = tsubst (LAMBDA_EXPR_CLOSURE (t), args, complain, NULL_TREE); + LAMBDA_EXPR_CLOSURE (r) = type; CLASSTYPE_LAMBDA_EXPR (type) = r; LAMBDA_EXPR_LOCATION (r) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index eed38e62f7b8..7d37fa3e2c10 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -8324,7 +8324,7 @@ build_lambda_object (tree lambda_expr) /* N2927: "[The closure] class type is not an aggregate." 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; expr = finish_compound_literal (type, expr, tf_warning_or_error); CLASSTYPE_NON_AGGREGATE (type) = 1; @@ -8365,7 +8365,7 @@ begin_lambda_type (tree lambda) type = begin_class_definition (type, /*attributes=*/NULL_TREE); /* Cross-reference the expression and the type. */ - TREE_TYPE (lambda) = type; + LAMBDA_EXPR_CLOSURE (lambda) = type; CLASSTYPE_LAMBDA_EXPR (type) = lambda; return type; @@ -8399,7 +8399,7 @@ lambda_function (tree lambda) { tree type; if (TREE_CODE (lambda) == LAMBDA_EXPR) - type = TREE_TYPE (lambda); + type = LAMBDA_EXPR_CLOSURE (lambda); else type = lambda; gcc_assert (LAMBDA_TYPE_P (type)); @@ -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 for duplicates. */ - if (!TREE_TYPE (lambda)) + if (!LAMBDA_EXPR_CLOSURE (lambda)) { if (IDENTIFIER_MARKED (name)) { @@ -8740,13 +8740,14 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, LAMBDA_EXPR_THIS_CAPTURE (lambda) = member; /* 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); 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); /* For explicit captures we haven't started the function yet, so we wait and build the proxy from cp_parser_lambda_body. */ @@ -8789,7 +8790,7 @@ add_default_capture (tree lambda_stack, tree id, tree initializer) { tree lambda = TREE_VALUE (node); - current_class_type = TREE_TYPE (lambda); + current_class_type = LAMBDA_EXPR_CLOSURE (lambda); var = add_capture (lambda, id, initializer, @@ -8820,7 +8821,7 @@ lambda_expr_this_capture (tree lambda) if (!this_capture && 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 init = NULL_TREE; @@ -8870,7 +8871,8 @@ lambda_expr_this_capture (tree lambda) else { /* 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 283b699a36d1..3c15036747cc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2011-10-13 Jason Merrill + PR c++/50437 + * g++.dg/cpp0x/lambda/lambda-auto1.C: New. + PR c++/50618 * g++.dg/init/vbase1.C: New. diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-auto1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-auto1.C new file mode 100644 index 000000000000..b5ba06637544 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-auto1.C @@ -0,0 +1,14 @@ +// PR c++/50437 +// { dg-options -std=c++0x } + +template +void f() +{ + auto g = [](T t){ return t == 0; }; + g(T()); +} + +int main() +{ + f(); +}