re PR c++/43831 ([C++0x] gcc-4.5.0 does not fail invalid lambda captures (against n3092 5.1.2/8))

PR c++/43831
	* parser.c (cp_parser_lambda_introducer): Complain about redundant
	captures.
	* semantics.c (add_capture): Likewise.
	(register_capture_members): Clear IDENTIFIER_MARKED.

From-SVN: r175211
This commit is contained in:
Jason Merrill 2011-06-20 10:39:44 -04:00 committed by Jason Merrill
parent c2954af926
commit 4b7d9ed4a8
5 changed files with 82 additions and 26 deletions

View file

@ -1,3 +1,11 @@
2011-06-20 Jason Merrill <jason@redhat.com>
PR c++/43831
* parser.c (cp_parser_lambda_introducer): Complain about redundant
captures.
* semantics.c (add_capture): Likewise.
(register_capture_members): Clear IDENTIFIER_MARKED.
2011-06-17 Jason Merrill <jason@redhat.com>
PR c++/49458

View file

@ -7485,6 +7485,10 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
/* Possibly capture `this'. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_THIS))
{
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_COPY)
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,
@ -7568,6 +7572,21 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
capture_init_expr
= unqualified_name_lookup_error (capture_init_expr);
if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE
&& !explicit_init_p)
{
if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_COPY
&& capture_kind == BY_COPY)
pedwarn (capture_token->location, 0, "explicit by-copy capture "
"of %qD redundant with by-copy capture default",
capture_id);
if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_REFERENCE
&& capture_kind == BY_REFERENCE)
pedwarn (capture_token->location, 0, "explicit by-reference "
"capture of %qD redundant with by-reference capture "
"default", capture_id);
}
add_capture (lambda_expr,
capture_id,
capture_init_expr,

View file

@ -8516,8 +8516,8 @@ tree
add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
bool explicit_init_p)
{
tree type;
tree member;
char *buf;
tree type, member, name;
type = lambda_capture_field_type (initializer);
if (by_reference_p)
@ -8527,18 +8527,31 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
error ("cannot capture %qE by reference", initializer);
}
/* Add __ to the beginning of the field name so that user code
won't find the field with name lookup. We can't just leave the name
unset because template instantiation uses the name to find
instantiated fields. */
buf = (char *) alloca (IDENTIFIER_LENGTH (id) + 3);
buf[1] = buf[0] = '_';
memcpy (buf + 2, IDENTIFIER_POINTER (id),
IDENTIFIER_LENGTH (id) + 1);
name = get_identifier (buf);
/* If TREE_TYPE isn't set, we're still in the introducer, so check
for duplicates. */
if (!TREE_TYPE (lambda))
{
if (IDENTIFIER_MARKED (name))
{
pedwarn (input_location, 0,
"already captured %qD in lambda expression", id);
return NULL_TREE;
}
IDENTIFIER_MARKED (name) = true;
}
/* Make member variable. */
{
/* Add __ to the beginning of the field name so that user code
won't find the field with name lookup. We can't just leave the name
unset because template instantiation uses the name to find
instantiated fields. */
char *buf = (char *) alloca (IDENTIFIER_LENGTH (id) + 3);
buf[1] = buf[0] = '_';
memcpy (buf + 2, IDENTIFIER_POINTER (id),
IDENTIFIER_LENGTH (id) + 1);
member = build_lang_decl (FIELD_DECL, get_identifier (buf), type);
}
member = build_lang_decl (FIELD_DECL, name, type);
if (!explicit_init_p)
/* Normal captures are invisible to name lookup but uses are replaced
@ -8548,6 +8561,9 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
always visible. */
DECL_NORMAL_CAPTURE_P (member) = true;
if (id == this_identifier)
LAMBDA_EXPR_THIS_CAPTURE (lambda) = member;
/* Add it to the appropriate closure class if we've started it. */
if (current_class_type && current_class_type == TREE_TYPE (lambda))
finish_member_declaration (member);
@ -8555,13 +8571,6 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
LAMBDA_EXPR_CAPTURE_LIST (lambda)
= tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
if (id == this_identifier)
{
if (LAMBDA_EXPR_CAPTURES_THIS_P (lambda))
error ("already captured %<this%> in lambda expression");
LAMBDA_EXPR_THIS_CAPTURE (lambda) = member;
}
if (TREE_TYPE (lambda))
return build_capture_proxy (member);
/* For explicit captures we haven't started the function yet, so we wait
@ -8572,13 +8581,16 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
/* Register all the capture members on the list CAPTURES, which is the
LAMBDA_EXPR_CAPTURE_LIST for the lambda after the introducer. */
void register_capture_members (tree captures)
void
register_capture_members (tree captures)
{
if (captures)
{
register_capture_members (TREE_CHAIN (captures));
finish_member_declaration (TREE_PURPOSE (captures));
}
if (captures == NULL_TREE)
return;
register_capture_members (TREE_CHAIN (captures));
/* We set this in add_capture to avoid duplicates. */
IDENTIFIER_MARKED (DECL_NAME (TREE_PURPOSE (captures))) = false;
finish_member_declaration (TREE_PURPOSE (captures));
}
/* Similar to add_capture, except this works on a stack of nested lambdas.

View file

@ -1,3 +1,8 @@
2011-06-20 Jason Merrill <jason@redhat.com>
PR c++/43831
* g++.dg/cpp0x/lambda/lambda-capture-reduncancy.C: New.
2011-06-20 Kai Tietz <ktietz@redhat.com>
* gcc.dg/binop-notand1.c: New test.

View file

@ -0,0 +1,12 @@
// FDIS 5.1.2/8
// { dg-options "-pedantic-errors -std=c++0x" }
struct S2 { void f(int i); };
void S2::f(int i) {
[&, i]{ }; // OK
[&, &i]{ }; // { dg-error "" } i preceded by & when & is the default
[=, i]{ }; // { dg-error "" } i not preceded by & when = is the default
[=, this]{ }; // { dg-error "" } this when = is the default
[i, i]{ }; // { dg-error "" } i repeated
[this, this]{ }; // { dg-error "" } i repeated
}