public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug preprocessor/106767] New: Failure to detect recursive macro calls due to _Pragma(pop_macro)
@ 2022-08-28 21:58 izbyshev at ispras dot ru
  2022-08-28 22:01 ` [Bug preprocessor/106767] " pinskia at gcc dot gnu.org
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: izbyshev at ispras dot ru @ 2022-08-28 21:58 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106767

            Bug ID: 106767
           Summary: Failure to detect recursive macro calls due to
                    _Pragma(pop_macro)
           Product: gcc
           Version: 13.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: preprocessor
          Assignee: unassigned at gcc dot gnu.org
          Reporter: izbyshev at ispras dot ru
                CC: amonakov at gcc dot gnu.org
  Target Milestone: ---

GCC preprocessor appears to behave as if each _Pragma(pop_macro("m")) creates a
new definition of "m", so, for example, the following code results in infinite
recursion:

#define P(x) _Pragma(#x)
#define f() P(push_macro("f")) P(pop_macro("f")) f()
f()

Naturally, this makes the preprocessor Turing-complete, e.g. it can add
numbers:

#define P(x) _Pragma(#x)
#define PUSH(x) P(push_macro(#x))
#define POP(x) P(pop_macro(#x))
#define R(f) PUSH(f) POP(f)
#define C(x, y) x ## y
#define ADD0(...) __VA_ARGS__
#define ADD1(...) 1, R(ADD) ADD(__VA_ARGS__)
#define ADD(x, ...) C(ADD, x)(__VA_ARGS__)

// 1 + 2 (zero-terminated unary numbers)
ADD(1, 0, 1, 1, 0)
// Outputs 1, 1, 1, 0 with "gcc -E -P"

The earliest GCC with this behavior on https://godbolt.org is 4.4.7.

Clang detects recursion correctly.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug preprocessor/106767] Failure to detect recursive macro calls due to _Pragma(pop_macro)
  2022-08-28 21:58 [Bug preprocessor/106767] New: Failure to detect recursive macro calls due to _Pragma(pop_macro) izbyshev at ispras dot ru
@ 2022-08-28 22:01 ` pinskia at gcc dot gnu.org
  2022-08-28 22:27 ` izbyshev at ispras dot ru
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: pinskia at gcc dot gnu.org @ 2022-08-28 22:01 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106767

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
How does msvc handle this? Since gcc is trying to be compatible with msvc here.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug preprocessor/106767] Failure to detect recursive macro calls due to _Pragma(pop_macro)
  2022-08-28 21:58 [Bug preprocessor/106767] New: Failure to detect recursive macro calls due to _Pragma(pop_macro) izbyshev at ispras dot ru
  2022-08-28 22:01 ` [Bug preprocessor/106767] " pinskia at gcc dot gnu.org
@ 2022-08-28 22:27 ` izbyshev at ispras dot ru
  2022-08-28 23:39 ` izbyshev at ispras dot ru
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: izbyshev at ispras dot ru @ 2022-08-28 22:27 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106767

--- Comment #2 from Alexey Izbyshev <izbyshev at ispras dot ru> ---
Old MSVC doesn't support _Pragma, and I can make newer one recognize _Pragma
only by unquoting the string literal, so the first test case becomes:

// Removed stringizing in _Pragma
#define P(x) _Pragma(x)
#define f() P(push_macro("f")) P(pop_macro("f")) f()
f()

Recursion is detected properly:

> cl /E test.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29910 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
#line 1 "test.c"

  f()

The second test case modified in the same way also works:

Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29910 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

add.c
#line 1 "add.c"

1,   ADD(0, 1, 1, 0)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug preprocessor/106767] Failure to detect recursive macro calls due to _Pragma(pop_macro)
  2022-08-28 21:58 [Bug preprocessor/106767] New: Failure to detect recursive macro calls due to _Pragma(pop_macro) izbyshev at ispras dot ru
  2022-08-28 22:01 ` [Bug preprocessor/106767] " pinskia at gcc dot gnu.org
  2022-08-28 22:27 ` izbyshev at ispras dot ru
@ 2022-08-28 23:39 ` izbyshev at ispras dot ru
  2022-08-29  8:44 ` rguenth at gcc dot gnu.org
  2022-08-29  9:44 ` izbyshev at ispras dot ru
  4 siblings, 0 replies; 6+ messages in thread
From: izbyshev at ispras dot ru @ 2022-08-28 23:39 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106767

--- Comment #3 from Alexey Izbyshev <izbyshev at ispras dot ru> ---
> I can make newer one recognize _Pragma only by unquoting the string literal
I've investigated this strange behavior because MSVC docs do claim that C99
_Pragma is properly supported[1].

It turned out that /E (preprocess) MSVC option is semi-broken and its output
can't be trusted. When it's specified, ill-formed _Pragma with arguments that
are tokens instead of a string literal appears to behave like simple #pragma:

> type test.c
#define X 1
_Pragma(push_macro("X"))
#undef X
#define X 2
_Pragma(pop_macro("X"))
int x = X;

> cl /E /std:c11 test.c

Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29910 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
#line 1 "test.c"

int x = 1 ;

And correct _Pragma with a string literal is only expanded to MSVC-internal
__pragma, without actually "executing" it, so X is expanded incorrectly below:

> type test.c
#define X 1
_Pragma("push_macro(\"X\")")
#undef X
#define X 2
_Pragma("pop_macro(\"X\")")
int x = X;

> cl /E /std:c11 test.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29910 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
#line 1 "test.c"

__pragma(push_macro("X"))


__pragma(pop_macro("X"))
int x = 2 ;

However, without /E it works as expected: ill-formed _Pragma is a syntax error,
and proper _Pragma is processed, e.g. with the previous example X is expanded
to 1:

>cl /c /Facon /std:c11 test.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29910 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
; Listing generated by Microsoft (R) Optimizing Compiler Version 19.28.29910.0

include listing.inc

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC  x
_DATA   SEGMENT
x       DD      01H
_DATA   ENDS
END

Nothing of the above changes the fact that macro recursion is detected properly
by MSVC, so Clang and MSVC behave the same way in this regard.

[1]
https://docs.microsoft.com/en-us/cpp/preprocessor/pragma-directives-and-the-pragma-keyword?view=msvc-170

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug preprocessor/106767] Failure to detect recursive macro calls due to _Pragma(pop_macro)
  2022-08-28 21:58 [Bug preprocessor/106767] New: Failure to detect recursive macro calls due to _Pragma(pop_macro) izbyshev at ispras dot ru
                   ` (2 preceding siblings ...)
  2022-08-28 23:39 ` izbyshev at ispras dot ru
@ 2022-08-29  8:44 ` rguenth at gcc dot gnu.org
  2022-08-29  9:44 ` izbyshev at ispras dot ru
  4 siblings, 0 replies; 6+ messages in thread
From: rguenth at gcc dot gnu.org @ 2022-08-29  8:44 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106767

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jsm28 at gcc dot gnu.org,
                   |                            |ktietz at gcc dot gnu.org
     Ever confirmed|0                           |1
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2022-08-29

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
Not sure if Kai is still active but he contributed push/pop_macro support.

Is there a public specification of the Microsoft extension and how it is
supposed to behave with recursion or is the recursion behavior specified
by the C standard?

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug preprocessor/106767] Failure to detect recursive macro calls due to _Pragma(pop_macro)
  2022-08-28 21:58 [Bug preprocessor/106767] New: Failure to detect recursive macro calls due to _Pragma(pop_macro) izbyshev at ispras dot ru
                   ` (3 preceding siblings ...)
  2022-08-29  8:44 ` rguenth at gcc dot gnu.org
@ 2022-08-29  9:44 ` izbyshev at ispras dot ru
  4 siblings, 0 replies; 6+ messages in thread
From: izbyshev at ispras dot ru @ 2022-08-29  9:44 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106767

--- Comment #5 from Alexey Izbyshev <izbyshev at ispras dot ru> ---
(In reply to Richard Biener from comment #4)
> Is there a public specification of the Microsoft extension and how it is
> supposed to behave with recursion or is the recursion behavior specified
> by the C standard?

I would be surprised if anything that could be called "a public specification"
exists. The Clang patch[1] from 2010 cites only the rudimentary MSDN
documentation[2].

I've modified the first test case to be compilable to assembler to avoid
relying on broken /E:

#define P(x) _Pragma(#x)
#define f() P(push_macro("f")) P(pop_macro("f")) f()
int f() {
    return 42;
}

and have checked that:

* All x64 MSVC versions supporting C99 _Pragma and available at godbolt
(19.25-19.33/latest) successfully compile it (with and without /Zc:preprocessor
option which enables standard-conforming preprocessor, where it's supported).
The only exception is 19.26 with /Zc:preprocessor: it emits strange syntax
errors, but that's likely a bug in the new preprocessor (19.26 is the first
version supporting it).

* All x64 MSVC versions available at godbolt (19.0, 19.10, 19.14-19.33/latest)
successfully compile the same test case with _Pragma(#x) replaced with
MSVC-specific __pragma(x) equivalent (again, with and without /Zc:preprocessor
where supported).

This suggests that push/pop_macro isn't supposed to interfere with recursion
detection.

[1]
https://github.com/llvm/llvm-project/commit/c0a585d63c6cf700ea01f1fe30c9f4cd51c1e97b
[2] https://docs.microsoft.com/en-us/cpp/preprocessor/push-macro

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-08-29  9:44 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-28 21:58 [Bug preprocessor/106767] New: Failure to detect recursive macro calls due to _Pragma(pop_macro) izbyshev at ispras dot ru
2022-08-28 22:01 ` [Bug preprocessor/106767] " pinskia at gcc dot gnu.org
2022-08-28 22:27 ` izbyshev at ispras dot ru
2022-08-28 23:39 ` izbyshev at ispras dot ru
2022-08-29  8:44 ` rguenth at gcc dot gnu.org
2022-08-29  9:44 ` izbyshev at ispras dot ru

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).