Hi,
for this testcase:
int main()
{
auto a = []() { return true; };
auto b = []() { return a(); }; // { dg-error "'a' is not captured" }
int c, d;
while (b() && c < d)
{
}
}
we produce meaningless diagnostics for the while loop (stemming from b()
but the caret is also in the wrong place, a separate issue):
error: invalid operands of types ‘void’ and ‘int’ to binary ‘operator!=’
because nothing notices in cp_parser_lambda_body that
cp_parser_expression went wrong, thus finish_return_stmt (expr) is
called on expr == error_mark_node. The way I'm handling the problem is
by returning false to the caller, cp_parser_lambda_expression, which is
already equipped to smoothly handle errors and return back error_mark_node.
Tested x86_64-linux.
Thanks,
Paolo.
///////////////////////
/cp
2012-05-07 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/53158
* parser.c (cp_parser_lambda_body): Return a boolean, false if
cp_parser_expression returns error_mark_node;
(cp_parser_lambda_expression): Check the latter.
/testsuite
2012-05-07 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/53158
* g++.dg/cpp0x/lambda/lambda-err2.C: New.
Index: testsuite/g++.dg/cpp0x/lambda/lambda-err2.C
===================================================================
--- testsuite/g++.dg/cpp0x/lambda/lambda-err2.C (revision 0)
+++ testsuite/g++.dg/cpp0x/lambda/lambda-err2.C (revision 0)
@@ -0,0 +1,12 @@
+// PR c++/53158
+// { dg-do compile { target c++11 } }
+
+int main()
+{
+ auto a = []() { return true; };
+ auto b = []() { return a(); }; // { dg-error "'a' is not captured" }
+ int c, d;
+ while (b() && c < d)
+ {
+ }
+}
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 187249)
+++ cp/parser.c (working copy)
@@ -1848,7 +1848,7 @@ static void cp_parser_lambda_introducer
(cp_parser *, tree);
static bool cp_parser_lambda_declarator_opt
(cp_parser *, tree);
-static void cp_parser_lambda_body
+static bool cp_parser_lambda_body
(cp_parser *, tree);
/* Statements [gram.stmt.stmt] */
@@ -8101,7 +8101,7 @@ cp_parser_lambda_expression (cp_parser* parser)
ok = cp_parser_lambda_declarator_opt (parser, lambda_expr);
if (ok)
- cp_parser_lambda_body (parser, lambda_expr);
+ 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);
@@ -8466,11 +8466,13 @@ cp_parser_lambda_declarator_opt (cp_parser* parser
but which requires special handling.
LAMBDA_EXPR is the current representation of the lambda expression. */
-static void
+static bool
cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
{
bool nested = (current_function_decl != NULL_TREE);
bool local_variables_forbidden_p = parser->local_variables_forbidden_p;
+ bool ok = true;
+
if (nested)
push_function_context ();
else
@@ -8540,6 +8542,8 @@ cp_parser_lambda_body (cp_parser* parser, tree lam
cp_parser_require_keyword (parser, RID_RETURN, RT_RETURN);
expr = cp_parser_expression (parser, /*cast_p=*/false, &idk);
+ if (expr == error_mark_node)
+ ok = false;
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
@@ -8579,6 +8583,8 @@ cp_parser_lambda_body (cp_parser* parser, tree lam
pop_function_context();
else
--function_depth;
+
+ return ok;
}
/* Statements [gram.stmt.stmt] */