libcpp: Fix ICEs on __has_include syntax errors [PR93545]
authorJakub Jelinek <jakub@redhat.com>
Tue, 4 Feb 2020 12:38:16 +0000 (13:38 +0100)
committerJakub Jelinek <jakub@redhat.com>
Tue, 4 Feb 2020 12:38:16 +0000 (13:38 +0100)
Some of the following testcases ICE, because one of the cpp_get_token
calls in builtin_has_include reads the CPP_EOF token but the caller isn't
aware that CPP_EOF has been reached and will do another cpp_get_token.
get_token_no_padding is something that is use by the
has_attribute/has_builtin callbacks, which will first peek and will not
consume CPP_EOF (but will consume other tokens).  The !SEEN_EOL ()
check on the other side doesn't work anymore and isn't really needed,
as we don't consume the EOF.  The change adds one further error to the
pr88974.c testcase, if we wanted just one error per __has_include,
we could add some boolean whether we've emitted errors already and
only emit the first one we encounter (not implemented).

2020-02-04  Jakub Jelinek  <jakub@redhat.com>

PR preprocessor/93545
* macro.c (cpp_get_token_no_padding): New function.
(builtin_has_include): Use it instead of cpp_get_token.  Don't check
SEEN_EOL.

* c-c++-common/cpp/pr88974.c: Expect another diagnostics during error
recovery.
* c-c++-common/cpp/pr93545-1.c: New test.
* c-c++-common/cpp/pr93545-2.c: New test.
* c-c++-common/cpp/pr93545-3.c: New test.
* c-c++-common/cpp/pr93545-4.c: New test.

gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/cpp/pr88974.c
gcc/testsuite/c-c++-common/cpp/pr93545-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cpp/pr93545-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cpp/pr93545-3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cpp/pr93545-4.c [new file with mode: 0644]
libcpp/ChangeLog
libcpp/macro.c

index 8e245303974c43c634ac19b28edb141f19bc74ff..e46561a540cf598d3b1b58371a41d93c71f35553 100644 (file)
@@ -1,3 +1,13 @@
+2020-02-04  Jakub Jelinek  <jakub@redhat.com>
+
+       PR preprocessor/93545
+       * c-c++-common/cpp/pr88974.c: Expect another diagnostics during error
+       recovery.
+       * c-c++-common/cpp/pr93545-1.c: New test.
+       * c-c++-common/cpp/pr93545-2.c: New test.
+       * c-c++-common/cpp/pr93545-3.c: New test.
+       * c-c++-common/cpp/pr93545-4.c: New test.
+
 2020-02-04  Iain Sandoe  <iain@sandoe.co.uk>
 
        * g++.dg/coroutines/coro-missing-promise.C: New test.
index c375d83c75f1f4e2312785b5ad868fe35480d35a..d6c2414ea1f79e7ba8912455806a46a8420baf64 100644 (file)
@@ -3,4 +3,5 @@
 
 #if __has_include (<pr88974.h)
 /* { dg-error "missing terminating > character" "" { target *-*-* } .-1 } */
+/* { dg-error "missing '\\\)' after .__has_include. operand" "" { target *-*-* } .-2 } */
 #endif
diff --git a/gcc/testsuite/c-c++-common/cpp/pr93545-1.c b/gcc/testsuite/c-c++-common/cpp/pr93545-1.c
new file mode 100644 (file)
index 0000000..757277b
--- /dev/null
@@ -0,0 +1,4 @@
+/* PR preprocessor/93545 */
+/* { dg-do preprocess } */
+
+__has_include  /* { dg-error "" } */
diff --git a/gcc/testsuite/c-c++-common/cpp/pr93545-2.c b/gcc/testsuite/c-c++-common/cpp/pr93545-2.c
new file mode 100644 (file)
index 0000000..5ed2dab
--- /dev/null
@@ -0,0 +1,4 @@
+/* PR preprocessor/93545 */
+/* { dg-do preprocess } */
+
+__has_include (        /* { dg-error "" } */
diff --git a/gcc/testsuite/c-c++-common/cpp/pr93545-3.c b/gcc/testsuite/c-c++-common/cpp/pr93545-3.c
new file mode 100644 (file)
index 0000000..eae13bd
--- /dev/null
@@ -0,0 +1,4 @@
+/* PR preprocessor/93545 */
+/* { dg-do preprocess } */
+
+__has_include ("foobarbaz"     /* { dg-error "" } */
diff --git a/gcc/testsuite/c-c++-common/cpp/pr93545-4.c b/gcc/testsuite/c-c++-common/cpp/pr93545-4.c
new file mode 100644 (file)
index 0000000..977d210
--- /dev/null
@@ -0,0 +1,4 @@
+/* PR preprocessor/93545 */
+/* { dg-do preprocess } */
+
+__has_include ()       /* { dg-error "" } */
index e61700f7ee96cecd52becfe706d60843940aa866..11c0773adb6e979e49343180e2d3834f76eac49b 100644 (file)
@@ -1,3 +1,10 @@
+2020-02-04  Jakub Jelinek  <jakub@redhat.com>
+
+       PR preprocessor/93545
+       * macro.c (cpp_get_token_no_padding): New function.
+       (builtin_has_include): Use it instead of cpp_get_token.  Don't check
+       SEEN_EOL.
+
 2020-02-01  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * configure: Regenerate.
index ec3f8b7b73cb38fccfaaf987f72b6ec4a9263ca5..9f9f83134b4fea71c28f9c840c2faa16901634f6 100644 (file)
@@ -336,6 +336,22 @@ unsigned num_expanded_macros_counter = 0;
    from macro expansion.  */
 unsigned num_macro_tokens_counter = 0;
 
+/* Wrapper around cpp_get_token to skip CPP_PADDING tokens
+   and not consume CPP_EOF.  */
+static const cpp_token *
+cpp_get_token_no_padding (cpp_reader *pfile)
+{
+  for (;;)
+    {
+      const cpp_token *ret = cpp_peek_token (pfile, 0);
+      if (ret->type == CPP_EOF)
+       return ret;
+      ret = cpp_get_token (pfile);
+      if (ret->type != CPP_PADDING)
+       return ret;
+    }
+}
+
 /* Handle meeting "__has_include" builtin macro.  */
 
 static int
@@ -344,10 +360,10 @@ builtin_has_include (cpp_reader *pfile, cpp_hashnode *op, bool has_next)
   int result = 0;
 
   pfile->state.angled_headers = true;
-  const cpp_token *token = cpp_get_token (pfile);
+  const cpp_token *token = cpp_get_token_no_padding (pfile);
   bool paren = token->type == CPP_OPEN_PAREN;
   if (paren)
-    token = cpp_get_token (pfile);
+    token = cpp_get_token_no_padding (pfile);
   else
     cpp_error (pfile, CPP_DL_ERROR,
               "missing '(' before \"%s\" operand", NODE_NAME (op));
@@ -379,7 +395,8 @@ builtin_has_include (cpp_reader *pfile, cpp_hashnode *op, bool has_next)
       XDELETEVEC (fname);
     }
 
-  if (paren && !SEEN_EOL () && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN)
+  if (paren
+      && cpp_get_token_no_padding (pfile)->type != CPP_CLOSE_PAREN)
     cpp_error (pfile, CPP_DL_ERROR,
               "missing ')' after \"%s\" operand", NODE_NAME (op));