aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2016-09-27 21:10:38 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2016-09-27 21:10:38 +0200
commit8ca333471792082b70360b87c33a1219534b4ed1 (patch)
tree2ca31d880419a194ebf4e7a0fe6a924476ebc7ab /gcc/cp
parent459bcfb0bec5bb642685e0b54551995ab51fb156 (diff)
downloadgcc-8ca333471792082b70360b87c33a1219534b4ed1.zip
gcc-8ca333471792082b70360b87c33a1219534b4ed1.tar.gz
gcc-8ca333471792082b70360b87c33a1219534b4ed1.tar.bz2
Implement P0018R3, C++17 lambda capture of *this by value as [=,*this]
Implement P0018R3, C++17 lambda capture of *this by value as [=,*this] * parser.c (cp_parser_lambda_introducer): Formatting fix. Pass true instead of false as by_reference_p to add_capture for 'this'. Parse '*this' simple-capture. * lambda.c (build_capture_proxy): Handle '*this' capture by value. (add_capture): Adjust function comment. For id == this_identifier, treat by_reference_p as capturing '*this' by reference, i.e. 'this' by value, and !by_reference_p as capturing '*this' by value. (add_default_capture): For implicit 'this' capture, always pass by_reference_p true rather than false. * g++.dg/cpp1z/lambda-this1.C: New test. * g++.dg/cpp1z/lambda-this2.C: New test. From-SVN: r240556
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/lambda.c23
-rw-r--r--gcc/cp/parser.c20
3 files changed, 49 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 75c9d36..1a1f186 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,16 @@
2016-09-27 Jakub Jelinek <jakub@redhat.com>
+ Implement P0018R3, C++17 lambda capture of *this by value as [=,*this]
+ * parser.c (cp_parser_lambda_introducer): Formatting fix. Pass
+ true instead of false as by_reference_p to add_capture for 'this'.
+ Parse '*this' simple-capture.
+ * lambda.c (build_capture_proxy): Handle '*this' capture by value.
+ (add_capture): Adjust function comment. For id == this_identifier,
+ treat by_reference_p as capturing '*this' by reference, i.e. 'this'
+ by value, and !by_reference_p as capturing '*this' by value.
+ (add_default_capture): For implicit 'this' capture, always pass
+ by_reference_p true rather than false.
+
PR c++/77722
* cp-gimplify.c (cp_ubsan_maybe_instrument_return): Instrument also
functions that have just a STATEMENT_LIST instead of BIND_EXPR, or
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index d511185..cd32226 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -380,6 +380,13 @@ build_capture_proxy (tree member)
type = lambda_proxy_type (object);
+ if (name == this_identifier && !POINTER_TYPE_P (type))
+ {
+ 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))
{
/* Rebuild the VLA type from the pointer and maxindex. */
@@ -440,7 +447,8 @@ vla_capture_type (tree array_type)
/* From an ID and INITIALIZER, create a capture (by reference if
BY_REFERENCE_P is true), add it to the capture-list for LAMBDA,
- and return it. */
+ and return it. If ID is `this', BY_REFERENCE_P says whether
+ `*this' is captured by reference. */
tree
add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
@@ -499,7 +507,14 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
type = lambda_capture_field_type (initializer, explicit_init_p);
if (type == error_mark_node)
return error_mark_node;
- if (by_reference_p)
+ if (id == this_identifier && !by_reference_p)
+ {
+ gcc_assert (POINTER_TYPE_P (type));
+ type = TREE_TYPE (type);
+ initializer = cp_build_indirect_ref (initializer, RO_NULL,
+ tf_warning_or_error);
+ }
+ if (id != this_identifier && by_reference_p)
{
type = build_reference_type (type);
if (!dependent_type_p (type) && !lvalue_p (initializer))
@@ -628,8 +643,8 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
id,
initializer,
/*by_reference_p=*/
- (!this_capture_p
- && (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda)
+ (this_capture_p
+ || (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda)
== CPLD_REFERENCE)),
/*explicit_init_p=*/false);
initializer = convert_from_reference (var);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 5ec8b1b..f672b8d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -9899,7 +9899,25 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
cp_lexer_consume_token (parser->lexer);
add_capture (lambda_expr,
/*id=*/this_identifier,
- /*initializer=*/finish_this_expr(),
+ /*initializer=*/finish_this_expr (),
+ /*by_reference_p=*/true,
+ explicit_init_p);
+ continue;
+ }
+
+ /* Possibly capture `*this'. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_MULT)
+ && cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_THIS))
+ {
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ if (cxx_dialect < cxx1z)
+ pedwarn (loc, 0, "%<*this%> capture only available with "
+ "-std=c++1z or -std=gnu++1z");
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ add_capture (lambda_expr,
+ /*id=*/this_identifier,
+ /*initializer=*/finish_this_expr (),
/*by_reference_p=*/false,
explicit_init_p);
continue;