diff options
author | Patrick Palka <ppalka@redhat.com> | 2021-11-19 08:54:25 -0500 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2021-11-19 08:54:25 -0500 |
commit | fd740165e54151ea794fca34904f5c2e2ea1dcda (patch) | |
tree | c0481c3654f63b5d76040b0ac7fe6214a18d8923 /gcc/cp/lambda.c | |
parent | f316727e5f6a4c58b63bdee9ad6be785f97f5ee7 (diff) | |
download | gcc-fd740165e54151ea794fca34904f5c2e2ea1dcda.zip gcc-fd740165e54151ea794fca34904f5c2e2ea1dcda.tar.gz gcc-fd740165e54151ea794fca34904f5c2e2ea1dcda.tar.bz2 |
c++: nested lambda capturing a capture proxy [PR94376]
Here when determining the type of the FIELD_DECL for the by-value capture
of 'i' in the inner lambda, we incorrectly give it the type const int
instead of int since the effective initializer is the proxy for the outer
capture, and this proxy is const since the outer lambda is non-mutable.
This patch fixes this by making lambda_capture_field_type handle
by-value capturing of capture proxies specially, namely we instead
consider the type of their FIELD_DECL which unlike the proxy has the
true cv-quals of the captured entity.
PR c++/94376
gcc/cp/ChangeLog:
* lambda.c (lambda_capture_field_type): Simplify by handling the
is_this case first. When capturing by-value a capture proxy,
consider the type of the corresponding field instead.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/lambda/lambda-nested9.C: New test.
Diffstat (limited to 'gcc/cp/lambda.c')
-rw-r--r-- | gcc/cp/lambda.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index f68c68c..c39a2bc 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -195,7 +195,9 @@ 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 && explicit_init_p) + if (is_this) + type = TREE_TYPE (expr); + else if (explicit_init_p) { tree auto_node = make_auto (); @@ -209,7 +211,7 @@ lambda_capture_field_type (tree expr, bool explicit_init_p, else type = do_auto_deduction (type, expr, auto_node); } - else if (!is_this && type_dependent_expression_p (expr)) + else if (type_dependent_expression_p (expr)) { type = cxx_make_type (DECLTYPE_TYPE); DECLTYPE_TYPE_EXPR (type) = expr; @@ -219,10 +221,19 @@ lambda_capture_field_type (tree expr, bool explicit_init_p, } else { + if (!by_reference_p && is_capture_proxy (expr)) + { + /* When capturing by-value another capture proxy from an enclosing + lambda, consider the type of the corresponding field instead, + as the proxy may be additionally const-qualifed if the enclosing + lambda is non-mutable (PR94376). */ + gcc_assert (TREE_CODE (DECL_VALUE_EXPR (expr)) == COMPONENT_REF); + expr = TREE_OPERAND (DECL_VALUE_EXPR (expr), 1); + } + type = non_reference (unlowered_expr_type (expr)); - if (!is_this - && (by_reference_p || TREE_CODE (type) == FUNCTION_TYPE)) + if (by_reference_p || TREE_CODE (type) == FUNCTION_TYPE) type = build_reference_type (type); } |