diff options
author | Jakub Jelinek <jakub@redhat.com> | 2016-09-27 21:10:38 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2016-09-27 21:10:38 +0200 |
commit | 8ca333471792082b70360b87c33a1219534b4ed1 (patch) | |
tree | 2ca31d880419a194ebf4e7a0fe6a924476ebc7ab /gcc/cp | |
parent | 459bcfb0bec5bb642685e0b54551995ab51fb156 (diff) | |
download | gcc-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/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/lambda.c | 23 | ||||
-rw-r--r-- | gcc/cp/parser.c | 20 |
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; |