+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>
* cp-tree.h (struct language_function): Rename in_function_try_handler
#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;
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;
/* 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;
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;
{
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));
/* 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))
{
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. */
{
tree lambda = TREE_VALUE (node);
- current_class_type = TREE_TYPE (lambda);
+ current_class_type = LAMBDA_EXPR_CLOSURE (lambda);
var = add_capture (lambda,
id,
initializer,
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;
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;