preprocessor: Further fix for EOF in macro args [PR97471]
authorNathan Sidwell <nathan@acm.org>
Tue, 20 Oct 2020 14:51:40 +0000 (07:51 -0700)
committerNathan Sidwell <nathan@acm.org>
Tue, 20 Oct 2020 15:01:34 +0000 (08:01 -0700)
My previous attempt at fixing this was incorrect.  The problem occurs
earlier in that _cpp_lex_direct processes the unwinding EOF needs in
collect_args mode.  This patch changes it not to do that, in the same
way as directive parsing works.  Also collect_args shouldn't push_back
such fake EOFs, and neither should funlike_invocation_p.

libcpp/
* lex.c (_cpp_lex_direct): Do not complete EOF processing when
parsing_args.
* macro.c (collect_args): Do not unwind fake EOF.
(funlike_invocation_p): Do not unwind fake EOF.
(cpp_context): Replace abort with gcc_assert.
gcc/testsuite/
* gcc.dg/cpp/endif.c: Move to ...
* c-c++-common/cpp/endif.c: ... here.
* gcc.dg/cpp/endif.h: Move to ...
* c-c++-common/cpp/endif.h: ... here.
* c-c++-common/cpp/eof-2.c: Adjust diagnostic.
* c-c++-common/cpp/eof-3.c: Adjust diagnostic.

gcc/testsuite/c-c++-common/cpp/endif.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cpp/endif.h [new file with mode: 0644]
gcc/testsuite/c-c++-common/cpp/eof-2.c
gcc/testsuite/c-c++-common/cpp/eof-3.c
gcc/testsuite/gcc.dg/cpp/endif.c [deleted file]
gcc/testsuite/gcc.dg/cpp/endif.h [deleted file]
libcpp/lex.c
libcpp/macro.c

diff --git a/gcc/testsuite/c-c++-common/cpp/endif.c b/gcc/testsuite/c-c++-common/cpp/endif.c
new file mode 100644 (file)
index 0000000..efea52c
--- /dev/null
@@ -0,0 +1,14 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.  */
+
+/* { dg-do preprocess } */
+
+/* Test case for PR preprocessor/6386 by Andreas Schwab.  We'd back up
+   over the CPP_EOF token (indicating not a funlike macro invocation)
+   in the header file, which would then be passed through as a real
+   EOF, leading to an early exit (and therefore bogus complaint about
+   unterminated #if).  */
+
+#define S(x)
+#if 1
+#include "endif.h"
+#endif
diff --git a/gcc/testsuite/c-c++-common/cpp/endif.h b/gcc/testsuite/c-c++-common/cpp/endif.h
new file mode 100644 (file)
index 0000000..3762249
--- /dev/null
@@ -0,0 +1 @@
+S
index 3a4af7f685002797c037da33dc87b79ae62f4f13..9cc4fed65646268c3c14560677a6f025a8724d15 100644 (file)
@@ -5,4 +5,4 @@
 #define f(x) x
 
 #include "eof-2.h"
- /* { dg-regexp {[^\n]*eof-2.h:4: error: unterminated argument list invoking macro "f"\n} } */
+ /* { dg-regexp {[^\n]*eof-2.h:4:21: error: unterminated argument list invoking macro "f"\n} } */
index 316918e3a6cb74dde45ec104f1581434bcc033f3..e309a548c0c0f00956d8b5e30f57ba6da0277e88 100644 (file)
@@ -3,6 +3,6 @@
 /* { dg-do preprocess } */
 /* { dg-additional-options "-include $srcdir/c-c++-common/cpp/eof-2.h" } */
 
- /* { dg-regexp {[^\n]*eof-2.h:4: error: unterminated argument list invoking macro "f"\n} } */
+ /* { dg-regexp {[^\n]*eof-2.h:4:21: error: unterminated argument list invoking macro "f"\n} } */
 
 token )
diff --git a/gcc/testsuite/gcc.dg/cpp/endif.c b/gcc/testsuite/gcc.dg/cpp/endif.c
deleted file mode 100644 (file)
index efea52c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.  */
-
-/* { dg-do preprocess } */
-
-/* Test case for PR preprocessor/6386 by Andreas Schwab.  We'd back up
-   over the CPP_EOF token (indicating not a funlike macro invocation)
-   in the header file, which would then be passed through as a real
-   EOF, leading to an early exit (and therefore bogus complaint about
-   unterminated #if).  */
-
-#define S(x)
-#if 1
-#include "endif.h"
-#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/endif.h b/gcc/testsuite/gcc.dg/cpp/endif.h
deleted file mode 100644 (file)
index 3762249..0000000
+++ /dev/null
@@ -1 +0,0 @@
-S
index 2fe77d162a2abf62be50f26376adcdf1879bf7c8..fb222924c8c69fdbae2331df14f2f9b63a46b6ce 100644 (file)
@@ -2768,7 +2768,10 @@ _cpp_lex_direct (cpp_reader *pfile)
       if (!_cpp_get_fresh_line (pfile))
        {
          result->type = CPP_EOF;
-         if (!pfile->state.in_directive)
+         /* Not a real EOF in a directive or arg parsing -- we refuse
+            to advance to the next file now, and will once we're out
+            of those modes.  */
+         if (!pfile->state.in_directive && !pfile->state.parsing_args)
            {
              /* Tell the compiler the line number of the EOF token.  */
              result->src_loc = pfile->line_table->highest_line;
index 9cb3b10a9a0f3e785ca6d964e0c9aa56ac02041c..0874028b2116da107ca0c342e7c5a68250f64455 100644 (file)
@@ -1259,13 +1259,10 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
 
   if (token->type == CPP_EOF)
     {
-      /* We still need the CPP_EOF to end directives, to end
-        pre-expansion of a macro argument, and at the end of the main
-        file.  We do not want it at the end of a -include'd (forced)
-        header file.  */
-      if (pfile->state.in_directive
-         || !pfile->line_table->depth
-         || pfile->context->prev)
+      /* Unless the EOF is marking the end of an argument, it's a fake
+        one from the end of a file that _cpp_clean_line will not have
+        advanced past.  */
+      if (token == &pfile->endarg)
        _cpp_backup_tokens (pfile, 1);
       cpp_error (pfile, CPP_DL_ERROR,
                 "unterminated argument list invoking macro \"%s\"",
@@ -1328,13 +1325,19 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node,
       pfile->state.parsing_args = 2;
       return collect_args (pfile, node, pragma_buff, num_args);
     }
-
-  /* Back up.  We may have skipped padding, in which case backing
-     up more than one token when expanding macros is in general
-     too difficult.  We re-insert it in its own context.  */
-  _cpp_backup_tokens (pfile, 1);
-  if (padding)
-    _cpp_push_token_context (pfile, NULL, padding, 1);
+  
+  /* Back up.  A CPP_EOF is either an EOF from an argument we're
+     expanding, or a fake one from lex_direct.  We want to backup the
+     former, but not the latter.  We may have skipped padding, in
+     which case backing up more than one token when expanding macros
+     is in general too difficult.  We re-insert it in its own
+     context.  */
+  if (token->type != CPP_EOF || token == &pfile->endarg)
+    {
+      _cpp_backup_tokens (pfile, 1);
+      if (padding)
+       _cpp_push_token_context (pfile, NULL, padding, 1);
+    }
 
   return NULL;
 }
@@ -2638,8 +2641,7 @@ _cpp_pop_context (cpp_reader *pfile)
   cpp_context *context = pfile->context;
 
   /* We should not be popping the base context.  */
-  if (context == &pfile->base_context)
-    abort ();
+  gcc_assert (context != &pfile->base_context);
 
   if (context->c.macro)
     {