From patchwork Sat May 28 21:54:58 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: C++ PATCH for c++/46124 (lambda error-recovery) Date: Sat, 28 May 2011 11:54:58 -0000 From: Jason Merrill X-Patchwork-Id: 97823 Message-Id: <4DE16F32.4040301@redhat.com> To: gcc-patches List The lambda parsing code hasn't dealt very well with erroneous constructs. In this example there are two problems: first, the return type is invalid, and then there's no body. Tested x86_64-pc-linux-gnu, applying to trunk. commit 22a693118203160af613df0e89dbb2723a9fa146 Author: Jason Merrill Date: Fri May 27 23:44:06 2011 -0400 PR c++/46124 * parser.c (cp_parser_lambda_expression): Improve error recovery. (cp_parser_lambda_declarator_opt): Likewise. Return bool. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 75ad3f8..a410082 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1580,7 +1580,7 @@ static tree cp_parser_lambda_expression (cp_parser *); static void cp_parser_lambda_introducer (cp_parser *, tree); -static void cp_parser_lambda_declarator_opt +static bool cp_parser_lambda_declarator_opt (cp_parser *, tree); static void cp_parser_lambda_body (cp_parser *, tree); @@ -7347,6 +7347,7 @@ cp_parser_lambda_expression (cp_parser* parser) { tree lambda_expr = build_lambda_expr (); tree type; + bool ok; LAMBDA_EXPR_LOCATION (lambda_expr) = cp_lexer_peek_token (parser->lexer)->location; @@ -7382,9 +7383,12 @@ cp_parser_lambda_expression (cp_parser* parser) /* By virtue of defining a local class, a lambda expression has access to the private variables of enclosing classes. */ - cp_parser_lambda_declarator_opt (parser, lambda_expr); + ok = cp_parser_lambda_declarator_opt (parser, lambda_expr); - cp_parser_lambda_body (parser, lambda_expr); + if (ok) + cp_parser_lambda_body (parser, lambda_expr); + else if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) + cp_parser_skip_to_end_of_block_or_statement (parser); /* The capture list was built up in reverse order; fix that now. */ { @@ -7418,7 +7422,8 @@ cp_parser_lambda_expression (cp_parser* parser) LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) = newlist; } - maybe_add_lambda_conv_op (type); + if (ok) + maybe_add_lambda_conv_op (type); type = finish_struct (type, /*attributes=*/NULL_TREE); @@ -7427,7 +7432,10 @@ cp_parser_lambda_expression (cp_parser* parser) pop_deferring_access_checks (); - return build_lambda_object (lambda_expr); + if (ok) + return build_lambda_object (lambda_expr); + else + return error_mark_node; } /* Parse the beginning of a lambda expression. @@ -7592,7 +7600,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) LAMBDA_EXPR is the current representation of the lambda expression. */ -static void +static bool cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) { /* 5.1.1.4 of the standard says: @@ -7688,12 +7696,17 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) fco = grokmethod (&return_type_specs, declarator, attributes); - DECL_INITIALIZED_IN_CLASS_P (fco) = 1; - DECL_ARTIFICIAL (fco) = 1; + if (fco != error_mark_node) + { + DECL_INITIALIZED_IN_CLASS_P (fco) = 1; + DECL_ARTIFICIAL (fco) = 1; + } finish_member_declaration (fco); obstack_free (&declarator_obstack, p); + + return (fco != error_mark_node); } } diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-syntax1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-syntax1.C new file mode 100644 index 0000000..f350133 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-syntax1.C @@ -0,0 +1,5 @@ +// PR c++/46124 +// { dg-options -std=c++0x } + +void foo() { [] () -> void (); } // { dg-error "returning a function" } +// { dg-error "expected .\{" "" { target *-*-* } 4 }