aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-03-21 23:01:02 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2019-03-21 23:01:02 +0100
commit152d47df7f625885ae972386c759330cea6b169e (patch)
treedf1fa2daab768303053a87f6d65572c918d887e9 /gcc/cp/parser.c
parent36a3a7a3726c8b65eeceb6eb4a8946e0cd5650a9 (diff)
downloadgcc-152d47df7f625885ae972386c759330cea6b169e.zip
gcc-152d47df7f625885ae972386c759330cea6b169e.tar.gz
gcc-152d47df7f625885ae972386c759330cea6b169e.tar.bz2
re PR c++/89767 (ICE with tuple and optimization)
PR c++/89767 * parser.c (cp_parser_lambda_introducer): Add ids and first_capture_id variables, check for duplicates in this function. * lambda.c (add_capture): Don't check for duplicates nor use IDENTIFIER_MARKED. (register_capture_members): Don't clear IDENTIFIER_MARKED here. * g++.dg/cpp1y/lambda-init18.C: New test. * g++.dg/cpp1y/lambda-init19.C: New test. * g++.dg/cpp1y/pr89767.C: New test. From-SVN: r269860
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c55
1 files changed, 40 insertions, 15 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 81aff35..c669e49 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10547,6 +10547,8 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
error ("non-local lambda expression cannot have a capture-default");
}
+ hash_set<tree, true> ids;
+ tree first_capture_id = NULL_TREE;
while (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_SQUARE))
{
cp_token* capture_token;
@@ -10582,11 +10584,14 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
pedwarn (loc, 0, "explicit by-copy capture of %<this%> redundant "
"with by-copy capture default");
cp_lexer_consume_token (parser->lexer);
- add_capture (lambda_expr,
- /*id=*/this_identifier,
- /*initializer=*/finish_this_expr (),
- /*by_reference_p=*/true,
- explicit_init_p);
+ if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr))
+ pedwarn (input_location, 0,
+ "already captured %qD in lambda expression",
+ this_identifier);
+ else
+ add_capture (lambda_expr, /*id=*/this_identifier,
+ /*initializer=*/finish_this_expr (),
+ /*by_reference_p=*/true, explicit_init_p);
continue;
}
@@ -10600,11 +10605,14 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
"%<-std=c++17%> or %<-std=gnu++17%>");
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);
+ if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr))
+ pedwarn (input_location, 0,
+ "already captured %qD in lambda expression",
+ this_identifier);
+ else
+ add_capture (lambda_expr, /*id=*/this_identifier,
+ /*initializer=*/finish_this_expr (),
+ /*by_reference_p=*/false, explicit_init_p);
continue;
}
@@ -10753,11 +10761,28 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
"default", capture_id);
}
- add_capture (lambda_expr,
- capture_id,
- capture_init_expr,
- /*by_reference_p=*/capture_kind == BY_REFERENCE,
- explicit_init_p);
+ /* Check for duplicates.
+ Optimize for the zero or one explicit captures cases and only create
+ the hash_set after adding second capture. */
+ bool found = false;
+ if (ids.elements ())
+ found = ids.add (capture_id);
+ else if (first_capture_id == NULL_TREE)
+ first_capture_id = capture_id;
+ else if (capture_id == first_capture_id)
+ found = true;
+ else
+ {
+ ids.add (first_capture_id);
+ ids.add (capture_id);
+ }
+ if (found)
+ pedwarn (input_location, 0,
+ "already captured %qD in lambda expression", capture_id);
+ else
+ add_capture (lambda_expr, capture_id, capture_init_expr,
+ /*by_reference_p=*/capture_kind == BY_REFERENCE,
+ explicit_init_p);
/* If there is any qualification still in effect, clear it
now; we will be starting fresh with the next capture. */