aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-07-30 17:44:38 +0200
committerJakub Jelinek <jakub@redhat.com>2021-07-30 17:44:38 +0200
commit0ba2003cf306aa98b6ec91c9d849ab9bafcf17c2 (patch)
tree41ff2dc33aad41fbda41722670e552777510dd80
parent59ffdb9849be033540ad680836cd4cc592098ca4 (diff)
downloadgcc-0ba2003cf306aa98b6ec91c9d849ab9bafcf17c2.zip
gcc-0ba2003cf306aa98b6ec91c9d849ab9bafcf17c2.tar.gz
gcc-0ba2003cf306aa98b6ec91c9d849ab9bafcf17c2.tar.bz2
c++: Fix up attribute rollbacks in cp_parser_statement
During the OpenMP directives using C++ attribute syntax work, I've noticed that cp_parser_statement when parsing various block declarations that do not allow attribute-specifier-seq at the start rolls back the attributes only if std_attrs is non-NULL (i.e. some attributes have been parsed), but doesn't roll back if some tokens were parsed as attribute-specifier-seq, but didn't yield any attributes (e.g. [[]][[]][[]][[]]), which means we accept those empty attributes even in places where they don't appear in the grammar. The following patch fixes that by instead checking if there are any tokens to roll back. This makes the parsing handle the first function the same as the second one (where some attribute appears). The testcase contains two xfails, using namespace ... apparently allows attributes at the start and the attributes shall appeartain to using in that case. To be fixed incrementally. 2021-07-30 Jakub Jelinek <jakub@redhat.com> * parser.c (cp_parser_statement): Rollback attributes not just when std_attrs is non-NULL, but whenever cp_parser_std_attribute_spec_seq parsed any tokens. * g++.dg/cpp0x/gen-attrs-76.C: New test.
-rw-r--r--gcc/cp/parser.c11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C31
2 files changed, 38 insertions, 4 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d960d38..97078f9 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11904,6 +11904,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
cp_token *token;
location_t statement_location, attrs_loc;
bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
+ bool has_std_attrs;
restart:
if (if_p != NULL)
@@ -11912,7 +11913,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
statement = NULL_TREE;
saved_token_sentinel saved_tokens (parser->lexer);
- attrs_loc = cp_lexer_peek_token (parser->lexer)->location;
+ token = cp_lexer_peek_token (parser->lexer);
+ attrs_loc = token->location;
if (c_dialect_objc ())
/* In obj-c++, seeing '[[' might be the either the beginning of
c++11 attributes, or a nested objc-message-expression. So
@@ -11926,6 +11928,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
if (!cp_parser_parse_definitely (parser))
std_attrs = NULL_TREE;
}
+ has_std_attrs = cp_lexer_peek_token (parser->lexer) != token;
if (std_attrs && (flag_openmp || flag_openmp_simd))
std_attrs = cp_parser_handle_statement_omp_attributes (parser, std_attrs);
@@ -11994,7 +11997,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
case RID_NAMESPACE:
/* This must be a namespace alias definition. */
- if (std_attrs != NULL_TREE)
+ if (has_std_attrs)
{
/* Attributes should be parsed as part of the
declaration, so let's un-parse them. */
@@ -12099,7 +12102,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
{
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
{
- if (std_attrs != NULL_TREE)
+ if (has_std_attrs)
/* Attributes should be parsed as part of the declaration,
so let's un-parse them. */
saved_tokens.rollback();
@@ -12111,7 +12114,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
if (cp_parser_parse_definitely (parser))
return;
/* It didn't work, restore the post-attribute position. */
- if (std_attrs)
+ if (has_std_attrs)
cp_lexer_set_token_position (parser->lexer, statement_token);
}
/* All preceding labels have been parsed at this point. */
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C
new file mode 100644
index 0000000..cbda8de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C
@@ -0,0 +1,31 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wno-attributes" }
+
+namespace N {}
+namespace O { typedef int T; };
+
+void
+foo ()
+{
+ [[]] asm (""); // { dg-error "expected" }
+ [[]] __extension__ asm (""); // { dg-error "expected" }
+ __extension__ [[]] asm (""); // { dg-error "expected" }
+ [[]] namespace M = ::N; // { dg-error "expected" }
+ [[]] using namespace N; // { dg-bogus "expected" "" { xfail *-*-* } }
+ [[]] using O::T; // { dg-error "expected" }
+ [[]] __label__ foo; // { dg-error "expected" }
+ [[]] static_assert (true, ""); // { dg-error "expected" }
+}
+
+void
+bar ()
+{
+ [[gnu::unused]] asm (""); // { dg-error "expected" }
+ [[gnu::unused]] __extension__ asm (""); // { dg-error "expected" }
+ __extension__ [[gnu::unused]] asm (""); // { dg-error "expected" }
+ [[gnu::unused]] namespace M = ::N; // { dg-error "expected" }
+ [[gnu::unused]] using namespace N; // { dg-bogus "expected" "" { xfail *-*-* } }
+ [[gnu::unused]] using O::T; // { dg-error "expected" }
+ [[gnu::unused]] __label__ foo; // { dg-error "expected" }
+ [[gnu::unused]] static_assert (true, ""); // { dg-error "expected" }
+}