From: Nathan Sidwell Date: Tue, 20 Oct 2020 14:51:40 +0000 (-0700) Subject: preprocessor: Further fix for EOF in macro args [PR97471] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=dbcc6b1577bedd2bf5879393c862b6c461787503;p=gcc.git preprocessor: Further fix for EOF in macro args [PR97471] 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. --- diff --git a/gcc/testsuite/c-c++-common/cpp/endif.c b/gcc/testsuite/c-c++-common/cpp/endif.c new file mode 100644 index 00000000000..efea52c46c2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/endif.c @@ -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 index 00000000000..37622491df3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/endif.h @@ -0,0 +1 @@ +S diff --git a/gcc/testsuite/c-c++-common/cpp/eof-2.c b/gcc/testsuite/c-c++-common/cpp/eof-2.c index 3a4af7f6850..9cc4fed6564 100644 --- a/gcc/testsuite/c-c++-common/cpp/eof-2.c +++ b/gcc/testsuite/c-c++-common/cpp/eof-2.c @@ -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} } */ diff --git a/gcc/testsuite/c-c++-common/cpp/eof-3.c b/gcc/testsuite/c-c++-common/cpp/eof-3.c index 316918e3a6c..e309a548c0c 100644 --- a/gcc/testsuite/c-c++-common/cpp/eof-3.c +++ b/gcc/testsuite/c-c++-common/cpp/eof-3.c @@ -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 index efea52c46c2..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/endif.c +++ /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 index 37622491df3..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/endif.h +++ /dev/null @@ -1 +0,0 @@ -S diff --git a/libcpp/lex.c b/libcpp/lex.c index 2fe77d162a2..fb222924c8c 100644 --- a/libcpp/lex.c +++ b/libcpp/lex.c @@ -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; diff --git a/libcpp/macro.c b/libcpp/macro.c index 9cb3b10a9a0..0874028b211 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -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) {