Message ID | 4FA7F554.90003@oracle.com |
---|---|
State | New |
Headers | show |
I don't think the diagnostic is meaningless; since a() is ill-formed, b() has type void. But we ought to give a more helpful message when an expression used as a truth value has an unsuitable type. Jason
On 05/07/2012 07:16 PM, Jason Merrill wrote: > I don't think the diagnostic is meaningless; since a() is ill-formed, > b() has type void. Sure we do understand it ;) > But we ought to give a more helpful message when an expression used > as a truth value has an unsuitable type. Thus something much more general than the lambda context of the PR. Ok, I can see what I can do. Thanks! Paolo.
On 05/07/2012 07:18 PM, Paolo Carlini wrote: > On 05/07/2012 07:16 PM, Jason Merrill wrote: >> I don't think the diagnostic is meaningless; since a() is ill-formed, >> b() has type void. > Sure we do understand it ;) >> But we ought to give a more helpful message when an expression used >> as a truth value has an unsuitable type. > Thus something much more general than the lambda context of the PR. > Ok, I can see what I can do. I think this is the minimal testcase we are looking for: void foo(); void bar(int a, int b) { if (foo() && a < b) ; } the error message is the same we see in PR 53158, thus: a.cc:5:20: error: invalid operands of types ‘void’ and ‘int’ to binary ‘operator!=’ if (foo() && a < b) If I take out the 'a < b' subexpression, we get: a.cc:5:12: error: could not convert ‘foo()’ from ‘void’ to ‘bool’ if (foo()) Is this the error message we want to see for the former testcase, or we want something slightly different? Thanks! Paolo.
On 7 May 2012 19:40, Paolo Carlini <paolo.carlini@oracle.com> wrote: > On 05/07/2012 07:18 PM, Paolo Carlini wrote: > > a.cc:5:12: error: could not convert ‘foo()’ from ‘void’ to ‘bool’ > if (foo()) > > Is this the error message we want to see for the former testcase, or we want > something slightly different? If "foo()" is printed with %qE, and now that we have caret diagnostics, I would expect the message to be: error: could not convert expression from 'void' to 'bool' For comparison, this is what Clang gives: /tmp/webcompile/_8320_0.cc:7:6: error: value of type 'void' is not contextually convertible to 'bool' if (foo() && a < b) ^~~~~ /tmp/webcompile/_8320_0.cc:7:12: error: invalid operands to binary expression ('void' and 'bool') if (foo() && a < b) ~~~~~ ^ ~~~~~ 2 errors generated. G++ could do better in this case, foo() is likely to be some kind of FUNCTION_DECL, so g++ could be smarter and say something like: error: could not convert return type of 'foo' from 'void' to 'bool' note: 'foo' declared here Just a suggestion. Cheers, Manuel.
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] */