c++: Fix scan forward over pragma [PR96257]
authorNathan Sidwell <nathan@acm.org>
Tue, 21 Jul 2020 19:37:58 +0000 (12:37 -0700)
committerNathan Sidwell <nathan@acm.org>
Tue, 21 Jul 2020 19:42:09 +0000 (12:42 -0700)
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.

gcc/cp/parser.c
gcc/testsuite/g++.dg/parse/pr96257.C [new file with mode: 0644]

index 11db02418bc9722ceff2c34a9fbd9b0c50d1d7df..5a2d73d1ab04a5d5f80118332b43b6a2147a3c4d 100644 (file)
@@ -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 (file)
index 0000000..34b0208
--- /dev/null
@@ -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" }