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:
parent
c2954af926
commit
4b7d9ed4a8
5 changed files with 82 additions and 26 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Add table
Reference in a new issue