commit 276e736980d133f032633eeb69d9edb1be6070eb
Author: Jason Merrill <jason@redhat.com>
Date: Mon Mar 24 16:11:02 2014 -0400
PR c++/60375
* parser.c (cp_parser_lambda_expression): Don't parse the body of
a lambda in unevaluated context.
@@ -8718,14 +8718,17 @@ cp_parser_lambda_expression (cp_parser* parser)
{
tree lambda_expr = build_lambda_expr ();
tree type;
- bool ok;
+ bool ok = true;
LAMBDA_EXPR_LOCATION (lambda_expr)
= cp_lexer_peek_token (parser->lexer)->location;
if (cp_unevaluated_operand)
- error_at (LAMBDA_EXPR_LOCATION (lambda_expr),
- "lambda-expression in unevaluated context");
+ {
+ error_at (LAMBDA_EXPR_LOCATION (lambda_expr),
+ "lambda-expression in unevaluated context");
+ ok = false;
+ }
/* We may be in the middle of deferred access check. Disable
it now. */
@@ -8770,12 +8773,15 @@ 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. */
- ok = cp_parser_lambda_declarator_opt (parser, lambda_expr);
+ ok &= cp_parser_lambda_declarator_opt (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);
+ {
+ if (cp_parser_skip_to_closing_brace (parser))
+ cp_lexer_consume_token (parser->lexer);
+ }
/* The capture list was built up in reverse order; fix that now. */
LAMBDA_EXPR_CAPTURE_LIST (lambda_expr)
@@ -5,3 +5,5 @@ template <class T>
struct A { };
A<decltype([]{ return 1; }())> a; // { dg-error "lambda.*unevaluated context" }
+// { dg-prune-output "template argument" }
+// { dg-prune-output "invalid type" }
new file mode 100644
@@ -0,0 +1,7 @@
+// PR c++/60375
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ decltype( [](){ return this; }() ) x; // { dg-error "unevaluated" }
+};
commit d0dd16c1e91b1d394c659e608d86a93e82f24fb4
Author: Jason Merrill <jason@redhat.com>
Date: Mon Mar 24 16:11:02 2014 -0400
* parser.h (struct cp_token): Rename ambiguous_p to error_reported.
* parser.c: Adjust.
(cp_lexer_get_preprocessor_token): Always clear it.
(cp_parser_lambda_expression): Use it to avoid duplicate diagnostics.
@@ -762,6 +762,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
token->keyword = RID_MAX;
token->pragma_kind = PRAGMA_NONE;
token->purged_p = false;
+ token->error_reported = false;
/* On some systems, some header files are surrounded by an
implicit extern "C" block. Set a flag in the token if it
@@ -797,7 +798,6 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
C_SET_RID_CODE (token->u.value, RID_MAX);
}
- token->ambiguous_p = false;
token->keyword = RID_MAX;
}
}
@@ -3011,7 +3011,7 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
if (token->type == CPP_NESTED_NAME_SPECIFIER)
{
cp_token *next = cp_lexer_peek_nth_token (parser->lexer, 2);
- if (next->type == CPP_NAME && next->ambiguous_p)
+ if (next->type == CPP_NAME && next->error_reported)
goto out;
}
@@ -4535,7 +4535,7 @@ cp_parser_primary_expression (cp_parser *parser,
we've already issued an error message; there's no reason
to check again. */
if (id_expr_token->type == CPP_NAME
- && id_expr_token->ambiguous_p)
+ && id_expr_token->error_reported)
{
cp_parser_simulate_error (parser);
return error_mark_node;
@@ -5313,7 +5313,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
token = cp_lexer_consume_token (parser->lexer);
if (!error_p)
{
- if (!token->ambiguous_p)
+ if (!token->error_reported)
{
tree decl;
tree ambiguous_decls;
@@ -8719,14 +8719,18 @@ cp_parser_lambda_expression (cp_parser* parser)
tree lambda_expr = build_lambda_expr ();
tree type;
bool ok = true;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
- LAMBDA_EXPR_LOCATION (lambda_expr)
- = cp_lexer_peek_token (parser->lexer)->location;
+ LAMBDA_EXPR_LOCATION (lambda_expr) = token->location;
if (cp_unevaluated_operand)
{
- error_at (LAMBDA_EXPR_LOCATION (lambda_expr),
- "lambda-expression in unevaluated context");
+ if (!token->error_reported)
+ {
+ error_at (LAMBDA_EXPR_LOCATION (lambda_expr),
+ "lambda-expression in unevaluated context");
+ token->error_reported = true;
+ }
ok = false;
}
@@ -19122,7 +19126,7 @@ cp_parser_class_name (cp_parser *parser,
/* Look for the identifier. */
identifier_token = cp_lexer_peek_token (parser->lexer);
- ambiguous_p = identifier_token->ambiguous_p;
+ ambiguous_p = identifier_token->error_reported;
identifier = cp_parser_identifier (parser);
/* If the next token isn't an identifier, we are certainly not
looking at a class-name. */
@@ -51,10 +51,10 @@ typedef struct GTY (()) cp_token {
ENUM_BITFIELD (pragma_kind) pragma_kind : 6;
/* True if this token is from a context where it is implicitly extern "C" */
BOOL_BITFIELD implicit_extern_c : 1;
- /* True for a CPP_NAME token that is not a keyword (i.e., for which
- KEYWORD is RID_MAX) iff this name was looked up and found to be
- ambiguous. An error has already been reported. */
- BOOL_BITFIELD ambiguous_p : 1;
+ /* True if an error has already been reported for this token, such as a
+ CPP_NAME token that is not a keyword (i.e., for which KEYWORD is
+ RID_MAX) iff this name was looked up and found to be ambiguous. */
+ BOOL_BITFIELD error_reported : 1;
/* True for a token that has been purged. If a token is purged,
it is no longer a valid token and it should be considered
deleted. */