summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2014-06-30 18:30:50 +0000
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2014-06-30 18:30:50 +0000
commit2c18ecc52764107851561a5425b4d9f556f0ba74 (patch)
tree0d0e586063aba446bedd32780b1491e8f843acd2 /gcc
parent9d4eeb529c2363388ae75168fcb371fceb4d7681 (diff)
downloadgcc-2c18ecc52764107851561a5425b4d9f556f0ba74.tar.gz
/cp
2014-06-30 Paolo Carlini <paolo.carlini@oracle.com> PR c++/54891 * parser.c (cp_parser_tokens_start_cast_expression): In C++11 a '[' can also start a primary-expression. (cp_parser_cast_expression): Parse a cast-expression only tentatively when cp_parser_tokens_start_cast_expression returns -1. /testsuite 2014-06-30 Paolo Carlini <paolo.carlini@oracle.com> PR c++/54891 * g++.dg/cpp0x/lambda/lambda-cast1.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@212162 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/parser.c82
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-cast1.C7
4 files changed, 72 insertions, 30 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f1212369d2f..bfe4da64af5 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2014-06-30 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/54891
+ * parser.c (cp_parser_tokens_start_cast_expression): In C++11
+ a '[' can also start a primary-expression.
+ (cp_parser_cast_expression): Parse a cast-expression only tentatively
+ when cp_parser_tokens_start_cast_expression returns -1.
+
2014-06-30 Jason Merrill <jason@redhat.com>
PR c++/61539
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 057b6ca14cc..013fc6ecd08 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4109,6 +4109,7 @@ complain_flags (bool decltype_p)
this
( expression )
id-expression
+ lambda-expression (C++11)
GNU Extensions:
@@ -7621,10 +7622,10 @@ cp_parser_delete_expression (cp_parser* parser)
tf_warning_or_error);
}
-/* Returns true if TOKEN may start a cast-expression and false
- otherwise. */
+/* Returns 1 if TOKEN may start a cast-expression and, in C++11,
+ isn't '[', -1 if TOKEN is '[' in C++11, 0 otherwise. */
-static bool
+static int
cp_parser_tokens_start_cast_expression (cp_parser *parser)
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
@@ -7667,7 +7668,7 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser)
case CPP_OR:
case CPP_OR_OR:
case CPP_EOF:
- return false;
+ return 0;
case CPP_OPEN_PAREN:
/* In ((type ()) () the last () isn't a valid cast-expression,
@@ -7675,12 +7676,15 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser)
return cp_lexer_peek_nth_token (parser->lexer, 2)->type
!= CPP_CLOSE_PAREN;
- /* '[' may start a primary-expression in obj-c++. */
+ /* '[' may start a primary-expression in obj-c++ and in C++11,
+ as a lambda-expression, eg, '(void)[]{}'. */
case CPP_OPEN_SQUARE:
+ if (cxx_dialect >= cxx11)
+ return -1;
return c_dialect_objc ();
default:
- return true;
+ return 1;
}
}
@@ -7705,7 +7709,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
{
tree type = NULL_TREE;
tree expr = NULL_TREE;
- bool cast_expression_p;
+ int cast_expression = 0;
const char *saved_message;
/* There's no way to know yet whether or not this is a cast.
@@ -7728,6 +7732,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
will commit to the parse at that point, because we cannot
undo the action that is done when creating a new class. So,
then we cannot back up and do a postfix-expression.
+
Another tricky case is the following (c++/29234):
struct S { void operator () (); };
@@ -7746,20 +7751,30 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
we are dealing with an unary-expression, a postfix-expression
or something else.
+ Yet another tricky case, in C++11, is the following (c++/54891):
+
+ (void)[]{};
+
+ The issue is that usually, besides the case of lambda-expressions,
+ the parenthesized type-id cannot be followed by '[', and, eg, we
+ want to parse '(C ())[2];' in parse/pr26997.C as unary-expression.
+ Thus, if cp_parser_tokens_start_cast_expression returns -1, below
+ we don't commit, we try a cast-expression, then an unary-expression.
+
Save tokens so that we can put them back. */
cp_lexer_save_tokens (parser->lexer);
/* We may be looking at a cast-expression. */
- cast_expression_p
- = (cp_parser_skip_to_closing_parenthesis (parser, false, false,
- /*consume_paren=*/true)
- && cp_parser_tokens_start_cast_expression (parser));
+ if (cp_parser_skip_to_closing_parenthesis (parser, false, false,
+ /*consume_paren=*/true))
+ cast_expression
+ = cp_parser_tokens_start_cast_expression (parser);
/* Roll back the tokens we skipped. */
cp_lexer_rollback_tokens (parser->lexer);
/* If we aren't looking at a cast-expression, simulate an error so
- that the call to cp_parser_parse_definitely below will fail. */
- if (!cast_expression_p)
+ that the call to cp_parser_error_occurred below returns true. */
+ if (!cast_expression)
cp_parser_simulate_error (parser);
else
{
@@ -7780,30 +7795,37 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
function returning T. */
if (!cp_parser_error_occurred (parser))
{
- cp_parser_parse_definitely (parser);
+ /* Only commit if the cast-expression doesn't start with '[' in
+ C++11, which may or may not start a lambda-expression. */
+ if (cast_expression > 0)
+ cp_parser_commit_to_topmost_tentative_parse (parser);
+
expr = cp_parser_cast_expression (parser,
/*address_p=*/false,
/*cast_p=*/true,
/*decltype_p=*/false,
pidk);
- /* Warn about old-style casts, if so requested. */
- if (warn_old_style_cast
- && !in_system_header_at (input_location)
- && !VOID_TYPE_P (type)
- && current_lang_name != lang_name_c)
- warning (OPT_Wold_style_cast, "use of old-style cast");
-
- /* Only type conversions to integral or enumeration types
- can be used in constant-expressions. */
- if (!cast_valid_in_integral_constant_expression_p (type)
- && cp_parser_non_integral_constant_expression (parser,
- NIC_CAST))
- return error_mark_node;
+ if (cp_parser_parse_definitely (parser))
+ {
+ /* Warn about old-style casts, if so requested. */
+ if (warn_old_style_cast
+ && !in_system_header_at (input_location)
+ && !VOID_TYPE_P (type)
+ && current_lang_name != lang_name_c)
+ warning (OPT_Wold_style_cast, "use of old-style cast");
+
+ /* Only type conversions to integral or enumeration types
+ can be used in constant-expressions. */
+ if (!cast_valid_in_integral_constant_expression_p (type)
+ && cp_parser_non_integral_constant_expression (parser,
+ NIC_CAST))
+ return error_mark_node;
- /* Perform the cast. */
- expr = build_c_cast (input_location, type, expr);
- return expr;
+ /* Perform the cast. */
+ expr = build_c_cast (input_location, type, expr);
+ return expr;
+ }
}
else
cp_parser_abort_tentative_parse (parser);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 930d60b7338..abfe4812a6d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2014-06-30 Paolo Carlini <paolo.carlini@oracle.com>
+ PR c++/54891
+ * g++.dg/cpp0x/lambda/lambda-cast1.C: New.
+
+2014-06-30 Paolo Carlini <paolo.carlini@oracle.com>
+
PR c++/51400
* g++.dg/cpp0x/constexpr-attribute3.C: New.
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-cast1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-cast1.C
new file mode 100644
index 00000000000..e5d49ca43e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-cast1.C
@@ -0,0 +1,7 @@
+// PR c++/54891
+// { dg-do compile { target c++11 } }
+
+int main()
+{
+ (void)[]{};
+}