c: Fix pragma inside a pragma [PR97991}

Message ID 20250211002608.4157034-1-quic_apinski@quicinc.com
State New
Headers
Series c: Fix pragma inside a pragma [PR97991} |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed

Commit Message

Andrew Pinski Feb. 11, 2025, 12:26 a.m. UTC
  After r0-72806-gbc4071dd66fd4d, c_parser_consume_token will
assert if we get a pragma inside c_parser_consume_token but
pragma processing will call pragma_lex which then calls
c_parser_consume_token. In the case of pragma with expansion
(redefine_extname, message and sometimes pack [and some target
specific pragmas]) we get the expanded tokens that includes
CPP_PRAGMA. We should just allow it instead of doing an assert.
This follows what the C++ front-end does even and we no longer
have an ICE.

Bootstrapped and tested on x86_64-linux-gnu.

	PR c/97991

gcc/c/ChangeLog:

	* c-parser.cc (c_parser_consume_token): Allow
	CPP_PRAGMA if inside a pragma.

gcc/testsuite/ChangeLog:

	* c-c++-common/cpp/pr97991-1.c: New test.

Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
---
 gcc/c/c-parser.cc                          | 6 +++++-
 gcc/testsuite/c-c++-common/cpp/pr97991-1.c | 3 +++
 2 files changed, 8 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/c-c++-common/cpp/pr97991-1.c
  

Comments

Andrew Pinski March 6, 2026, 12:17 a.m. UTC | #1
On Mon, Feb 10, 2025 at 4:27 PM Andrew Pinski <quic_apinski@quicinc.com> wrote:
>
> After r0-72806-gbc4071dd66fd4d, c_parser_consume_token will
> assert if we get a pragma inside c_parser_consume_token but
> pragma processing will call pragma_lex which then calls
> c_parser_consume_token. In the case of pragma with expansion
> (redefine_extname, message and sometimes pack [and some target
> specific pragmas]) we get the expanded tokens that includes
> CPP_PRAGMA. We should just allow it instead of doing an assert.
> This follows what the C++ front-end does even and we no longer
> have an ICE.

Ping?

>
> Bootstrapped and tested on x86_64-linux-gnu.
>
>         PR c/97991
>
> gcc/c/ChangeLog:
>
>         * c-parser.cc (c_parser_consume_token): Allow
>         CPP_PRAGMA if inside a pragma.
>
> gcc/testsuite/ChangeLog:
>
>         * c-c++-common/cpp/pr97991-1.c: New test.
>
> Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
> ---
>  gcc/c/c-parser.cc                          | 6 +++++-
>  gcc/testsuite/c-c++-common/cpp/pr97991-1.c | 3 +++
>  2 files changed, 8 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/c-c++-common/cpp/pr97991-1.c
>
> diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
> index 106a5b48093..ff4a15aebce 100644
> --- a/gcc/c/c-parser.cc
> +++ b/gcc/c/c-parser.cc
> @@ -929,7 +929,11 @@ c_parser_consume_token (c_parser *parser)
>    gcc_assert (parser->tokens_avail >= 1);
>    gcc_assert (parser->tokens[0].type != CPP_EOF);
>    gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
> -  gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
> +  /* CPP_PRAGMA should not show up here except if there was an error or inside
> +     another pragma.  */
> +  gcc_assert (parser->in_pragma
> +             || parser->error
> +             || parser->tokens[0].type != CPP_PRAGMA);
>    parser->last_token_location = parser->tokens[0].location;
>    if (parser->tokens != &parser->tokens_buf[0])
>      parser->tokens++;
> diff --git a/gcc/testsuite/c-c++-common/cpp/pr97991-1.c b/gcc/testsuite/c-c++-common/cpp/pr97991-1.c
> new file mode 100644
> index 00000000000..afdfd8a51b2
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/cpp/pr97991-1.c
> @@ -0,0 +1,3 @@
> +/* { dg-do compile } */
> +/* Make sure malformed redefine_extname with a pragma inside does not cause an ICE. */
> +#pragma redefine_extname _Pragma ("pack(bar)") /* { dg-warning "" } */
> --
> 2.43.0
>
  
Joseph Myers March 6, 2026, 5:18 p.m. UTC | #2
On Thu, 5 Mar 2026, Andrew Pinski wrote:

> On Mon, Feb 10, 2025 at 4:27 PM Andrew Pinski <quic_apinski@quicinc.com> wrote:
> >
> > After r0-72806-gbc4071dd66fd4d, c_parser_consume_token will
> > assert if we get a pragma inside c_parser_consume_token but
> > pragma processing will call pragma_lex which then calls
> > c_parser_consume_token. In the case of pragma with expansion
> > (redefine_extname, message and sometimes pack [and some target
> > specific pragmas]) we get the expanded tokens that includes
> > CPP_PRAGMA. We should just allow it instead of doing an assert.
> > This follows what the C++ front-end does even and we no longer
> > have an ICE.
> 
> Ping?

OK.
  

Patch

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 106a5b48093..ff4a15aebce 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -929,7 +929,11 @@  c_parser_consume_token (c_parser *parser)
   gcc_assert (parser->tokens_avail >= 1);
   gcc_assert (parser->tokens[0].type != CPP_EOF);
   gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
-  gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
+  /* CPP_PRAGMA should not show up here except if there was an error or inside
+     another pragma.  */
+  gcc_assert (parser->in_pragma
+	      || parser->error
+	      || parser->tokens[0].type != CPP_PRAGMA);
   parser->last_token_location = parser->tokens[0].location;
   if (parser->tokens != &parser->tokens_buf[0])
     parser->tokens++;
diff --git a/gcc/testsuite/c-c++-common/cpp/pr97991-1.c b/gcc/testsuite/c-c++-common/cpp/pr97991-1.c
new file mode 100644
index 00000000000..afdfd8a51b2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/pr97991-1.c
@@ -0,0 +1,3 @@ 
+/* { dg-do compile } */
+/* Make sure malformed redefine_extname with a pragma inside does not cause an ICE. */
+#pragma redefine_extname _Pragma ("pack(bar)") /* { dg-warning "" } */