aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2020-07-21 12:37:58 -0700
committerNathan Sidwell <nathan@acm.org>2020-07-21 12:42:09 -0700
commit4d6e94960aa199b2fe7bf5a66f98bd7691884c1d (patch)
treea9e4bce1eb8d4b9514d0baa8322d95d61fb1e0fa
parent28f2a080cc27531a8c78aec9f44aeff4961c2a4c (diff)
downloadgcc-4d6e94960aa199b2fe7bf5a66f98bd7691884c1d.zip
gcc-4d6e94960aa199b2fe7bf5a66f98bd7691884c1d.tar.gz
gcc-4d6e94960aa199b2fe7bf5a66f98bd7691884c1d.tar.bz2
c++: Fix scan forward over pragma [PR96257]
It turns out that the paren scanning code is used for speculatively searching to see if we're looking at a compound_literal. So we shouldn't always purge pragma tokens. gcc/cp/ * parser.c (cp_lexer_consume_token): Drop PRAGMA_EOL assert. (cp_parser_skip_to_closing_parenthesis_1): Only pass start token to pragma skipper if recovering. (cp_parser_skip_to_pragma_eol): Only purge and change pragma state when recovering. gcc/testsuite/ * g++.dg/parse/pr96257.C: New.
-rw-r--r--gcc/cp/parser.c17
-rw-r--r--gcc/testsuite/g++.dg/parse/pr96257.C18
2 files changed, 27 insertions, 8 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 11db024..5a2d73d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1121,8 +1121,6 @@ cp_lexer_consume_token (cp_lexer* lexer)
{
cp_token *token = lexer->next_token;
- gcc_assert (!lexer->in_pragma || token->type != CPP_PRAGMA_EOL);
-
do
{
gcc_assert (token->type != CPP_EOF);
@@ -3691,7 +3689,7 @@ cp_parser_skip_to_closing_parenthesis_1 (cp_parser *parser,
case CPP_PRAGMA:
/* We fell into a pragma. Skip it, and continue. */
- cp_parser_skip_to_pragma_eol (parser, token);
+ cp_parser_skip_to_pragma_eol (parser, recovering ? token : nullptr);
continue;
default:
@@ -3930,15 +3928,14 @@ cp_parser_skip_to_closing_brace (cp_parser *parser)
/* Consume tokens until we reach the end of the pragma. The PRAGMA_TOK
parameter is the PRAGMA token, allowing us to purge the entire pragma
- sequence. */
+ sequence. PRAGMA_TOK can be NULL, if we're speculatively scanning
+ forwards (not error recovery). */
static void
cp_parser_skip_to_pragma_eol (cp_parser* parser, cp_token *pragma_tok)
{
cp_token *token;
- parser->lexer->in_pragma = false;
-
do
{
/* The preprocessor makes sure that a PRAGMA_EOL token appears
@@ -3950,8 +3947,12 @@ cp_parser_skip_to_pragma_eol (cp_parser* parser, cp_token *pragma_tok)
}
while (token->type != CPP_PRAGMA_EOL);
- /* Ensure that the pragma is not parsed again. */
- cp_lexer_purge_tokens_after (parser->lexer, pragma_tok);
+ if (pragma_tok)
+ {
+ /* Ensure that the pragma is not parsed again. */
+ cp_lexer_purge_tokens_after (parser->lexer, pragma_tok);
+ parser->lexer->in_pragma = false;
+ }
}
/* Require pragma end of line, resyncing with it as necessary. The
diff --git a/gcc/testsuite/g++.dg/parse/pr96257.C b/gcc/testsuite/g++.dg/parse/pr96257.C
new file mode 100644
index 0000000..34b0208
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr96257.C
@@ -0,0 +1,18 @@
+// PR96257 we scan forwards checking for a compound literal. Do not
+// eat the tokens when doing that!
+/* { dg-require-effective-target fopenmp } */
+/* { dg-additional-options -fopenmp } */
+
+int
+f2 ()
+{
+ int s = (int // { dg-error "expected" }
+#pragma omp atomic capture
+ ){1};
+
+ int t = (int // { dg-error "expected" }
+#pragma omp atomic capture ){
+ {1};
+
+ return s + t;
+} // { dg-bogus "expected" }