aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/lambda.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/lambda.cc')
-rw-r--r--gcc/cp/lambda.cc69
1 files changed, 46 insertions, 23 deletions
diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index a2bed9f..c798967 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -150,7 +150,7 @@ begin_lambda_type (tree lambda)
/* Cross-reference the expression and the type. */
LAMBDA_EXPR_CLOSURE (lambda) = type;
- CLASSTYPE_LAMBDA_EXPR (type) = lambda;
+ SET_CLASSTYPE_LAMBDA_EXPR (type, lambda);
/* In C++17, assume the closure is literal; we'll clear the flag later if
necessary. */
@@ -218,9 +218,7 @@ lambda_capture_field_type (tree expr, bool explicit_init_p,
tree type;
bool is_this = is_this_parameter (tree_strip_nop_conversions (expr));
- if (is_this)
- type = TREE_TYPE (expr);
- else if (explicit_init_p)
+ if (explicit_init_p)
{
tree auto_node = make_auto ();
@@ -259,7 +257,7 @@ lambda_capture_field_type (tree expr, bool explicit_init_p,
type = non_reference (unlowered_expr_type (expr));
- if (by_reference_p || TREE_CODE (type) == FUNCTION_TYPE)
+ if ((by_reference_p && !is_this) || TREE_CODE (type) == FUNCTION_TYPE)
type = build_reference_type (type);
}
@@ -440,13 +438,21 @@ build_capture_proxy (tree member, tree init)
else
name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2);
- type = lambda_proxy_type (object);
-
- if (name == this_identifier && !INDIRECT_TYPE_P (type))
+ if (name == this_identifier && TYPE_PTR_P (TREE_TYPE (member)))
+ /* Avoid DECLTYPE_TYPE for by-ref 'this' capture in an xobj lambda; the
+ constness of the closure doesn't matter just like it doesn't matter to
+ other by-ref capture. It's simpler to handle this special case here
+ than in lambda_proxy_type. */
+ type = TREE_TYPE (member);
+ else
{
- type = build_pointer_type (type);
- type = cp_build_qualified_type (type, TYPE_QUAL_CONST);
- object = build_fold_addr_expr_with_type (object, type);
+ type = lambda_proxy_type (object);
+ if (name == this_identifier)
+ {
+ type = build_pointer_type (type);
+ type = cp_build_qualified_type (type, TYPE_QUAL_CONST);
+ object = build_fold_addr_expr_with_type (object, type);
+ }
}
if (DECL_VLA_CAPTURE_P (member))
@@ -817,6 +823,14 @@ lambda_expr_this_capture (tree lambda, int add_capture_p)
if (cp_unevaluated_operand)
add_capture_p = false;
+ /* If we captured 'this' but don't have a capture proxy yet, look up the
+ captured 'this' again. */
+ if (this_capture && TREE_CODE (this_capture) == FIELD_DECL)
+ {
+ gcc_assert (!add_capture_p);
+ this_capture = NULL_TREE;
+ }
+
/* Try to default capture 'this' if we can. */
if (!this_capture)
{
@@ -921,8 +935,9 @@ lambda_expr_this_capture (tree lambda, int add_capture_p)
else
{
/* To make sure that current_class_ref is for the lambda. */
- gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref))
- == LAMBDA_EXPR_CLOSURE (lambda));
+ gcc_assert (!current_class_ref
+ || (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref))
+ == LAMBDA_EXPR_CLOSURE (lambda)));
result = this_capture;
@@ -933,6 +948,9 @@ lambda_expr_this_capture (tree lambda, int add_capture_p)
result = rvalue (result);
}
+ gcc_checking_assert (!result || result == error_mark_node
+ || TYPE_PTR_P (TREE_TYPE (result)));
+
return result;
}
@@ -1020,13 +1038,19 @@ maybe_generic_this_capture (tree object, tree fns)
}
}
-/* Returns the innermost non-lambda function. */
+/* Returns the innermost non-lambda function. If ONLY_SKIP_CONSTEVAL_BLOCK_P,
+ we only skip lambda functions that represent consteval blocks. */
tree
-current_nonlambda_function (void)
+current_nonlambda_function (bool only_skip_consteval_block_p/*=false*/)
{
tree fn = current_function_decl;
- while (fn && LAMBDA_FUNCTION_P (fn))
+ tree lam;
+ while (fn && LAMBDA_FUNCTION_P (fn)
+ && (!only_skip_consteval_block_p
+ /* Only keep going if FN represents a consteval block. */
+ || ((lam = CLASSTYPE_LAMBDA_EXPR (CP_DECL_CONTEXT (fn)))
+ && LAMBDA_EXPR_CONSTEVAL_BLOCK_P (lam))))
fn = decl_function_context (fn);
return fn;
}
@@ -1037,12 +1061,9 @@ current_nonlambda_function (void)
tree
nonlambda_method_basetype (void)
{
- if (!current_class_ref)
- return NULL_TREE;
-
tree type = current_class_type;
if (!type || !LAMBDA_TYPE_P (type))
- return type;
+ return current_class_ref ? type : NULL_TREE;
while (true)
{
@@ -1054,7 +1075,7 @@ nonlambda_method_basetype (void)
tree fn = TYPE_CONTEXT (type);
if (!fn || TREE_CODE (fn) != FUNCTION_DECL
- || !DECL_IOBJ_MEMBER_FUNCTION_P (fn))
+ || !DECL_OBJECT_MEMBER_FUNCTION_P (fn))
/* No enclosing non-lambda method. */
return NULL_TREE;
if (!LAMBDA_FUNCTION_P (fn))
@@ -1128,7 +1149,9 @@ maybe_add_lambda_conv_op (tree type)
tree lam = CLASSTYPE_LAMBDA_EXPR (type);
if (LAMBDA_EXPR_CAPTURE_LIST (lam) != NULL_TREE
- || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) != CPLD_NONE)
+ || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) != CPLD_NONE
+ /* CWG2561 ...and no explicit object parameter. */
+ || DECL_XOBJ_MEMBER_FUNCTION_P (callop))
return;
if (processing_template_decl)
@@ -1935,7 +1958,7 @@ finish_lambda_function (tree body)
{
finish_function_body (body);
- prune_lambda_captures (body);
+ prune_lambda_captures (cur_stmt_list);
/* Finish the function and generate code for it if necessary. */
tree fn = finish_function (/*inline_p=*/true);