[Bug c++/107360] ICE on sizeof(*f(x)) when f's (deduced) return type is a pointer to VLA
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107360 --- Comment #4 from Alexey Izbyshev --- (In reply to Martin Uecker from comment #3) > I think there there are cases were variably modified > return types are allowed in ISO C: > > void f(int n, double (*(bar(void)))[n]) > { > double (*p)[n] = bar(); > } Yes, I should have been more precise. Per C11 6.7.6.2: > If an identifier is declared as having a variably modified type, it shall be > an ordinary identifier (as defined in 6.2.3), have no linkage, and have > either block scope or function prototype scope. So, since my original example is in C++ and involves return type deduction, what I really wanted to say is that it's not allowed to *define* a function with a variably modified return type in ISO C (hence it seems fine to not support it in GCC's VLA extension for C++ too and consider such code invalid). GCC does allow to define a nested function with a variably modified return type though, and, perhaps surprisingly, a test case similar to my original C++ one is compiled successfully: extern int n; int f() { int a[n]; int (*g())[n] { return &a; }; return sizeof *g(); } But what would seem to be a C++ equivalent crashes GCC: extern int n; int f() { int a[n]; auto g = [&]() { return &a; }; return sizeof *g(); } during RTL pass: expand : In function 'int f()': :6:13: internal compiler error: in expand_expr_real_1, at expr.cc:10586 6 | return &a; | ^ ... And for this one it's less clear to me whether GCC wants to consider it invalid. But without return type deduction GCC refuses to compile: extern int n; int f() { typedef int t[n]; t a; auto g = [&]() -> t* { return &a; }; return sizeof *g(); } : In function 'int f()': :6:12: error: data member may not have variably modified type 'int (*())[n]' 6 | auto g = [&]() -> t* { |^ :6:12: error: declaration of 'operator()' as non-function Compiler returned: 1
[Bug c++/107360] ICE on sizeof(*f(x)) when f's (deduced) return type is a pointer to VLA
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107360 --- Comment #2 from Alexey Izbyshev --- (In reply to Andrew Pinski from comment #1) > Maybe this should be invalid code ... Yes, I think it should be invalid. VLAs are not allowed in function return types in C. VLAs in C++ are a GCC extension, but it's unclear to me why (and how) GCC should allow them in return types, even when they don't depend on function parameters. Currently, GCC crashes even in the latter case, e.g.: extern int n; auto f() { int (*a)[n] = 0; return a; } int g() { return sizeof *f(); }
[Bug c++/107360] New: ICE on sizeof(*f(x)) when f's (deduced) return type is a pointer to VLA
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107360 Bug ID: 107360 Summary: ICE on sizeof(*f(x)) when f's (deduced) return type is a pointer to VLA Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: izbyshev at ispras dot ru Target Milestone: --- auto f(int n) { int (*a)[n] = 0; return a; } int g() { return sizeof *f(1); } Output of GCC 12.2: during RTL pass: expand : In function 'int g()': :7:23: internal compiler error: in expand_expr_real_1, at expr.cc:10586 7 | return sizeof *f(1); | ^ 0x1bb069e internal_error(char const*, ...) ???:0 0x6ff396 fancy_abort(char const*, int, char const*) ???:0 0xab97bd expand_expr_real_2(separate_ops*, rtx_def*, machine_mode, expand_modifier) ???:0 0xaab144 expand_expr_real_1(tree_node*, rtx_def*, machine_mode, expand_modifier, rtx_def**, bool) ???:0 0xab97bd expand_expr_real_2(separate_ops*, rtx_def*, machine_mode, expand_modifier) ???:0 0xaab144 expand_expr_real_1(tree_node*, rtx_def*, machine_mode, expand_modifier, rtx_def**, bool) ???:0 0xab38c4 expand_operands(tree_node*, tree_node*, rtx_def*, rtx_def**, rtx_def**, expand_modifier) ???:0 0xaba7ac expand_expr_real_2(separate_ops*, rtx_def*, machine_mode, expand_modifier) ???:0 0xaab144 expand_expr_real_1(tree_node*, rtx_def*, machine_mode, expand_modifier, rtx_def**, bool) ???:0 0xabb2c9 expand_expr_real_2(separate_ops*, rtx_def*, machine_mode, expand_modifier) ???:0 0xaab144 expand_expr_real_1(tree_node*, rtx_def*, machine_mode, expand_modifier, rtx_def**, bool) ???:0 All versions supporting C++14 return type deduction (i.e. since 4.8) produce ICE, except 4.9, which generates wrong code for g() instead (it returns 1 regardless of f's argument).
[Bug preprocessor/106767] Failure to detect recursive macro calls due to _Pragma(pop_macro)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106767 --- Comment #5 from Alexey Izbyshev --- (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
[Bug preprocessor/106767] Failure to detect recursive macro calls due to _Pragma(pop_macro)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106767 --- Comment #3 from Alexey Izbyshev --- > 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
[Bug preprocessor/106767] Failure to detect recursive macro calls due to _Pragma(pop_macro)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106767 --- Comment #2 from Alexey Izbyshev --- 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)
[Bug preprocessor/106767] New: Failure to detect recursive macro calls due to _Pragma(pop_macro)
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.
[Bug target/105355] -msmall-data-limit= unexpectedly accepts a separate argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105355 --- Comment #3 from Alexey Izbyshev --- (In reply to Martin Liška from comment #2) Yes, "gcc test.h -o test.pch" uses the separate spelling of "--output-pch=" in cc1 command line (but, curiously, "gcc test.h" uses the joined spelling).
[Bug driver/105355] New: -msmall-data-limit= unexpectedly accepts a separate argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105355 Bug ID: 105355 Summary: -msmall-data-limit= unexpectedly accepts a separate argument Product: gcc Version: 10.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: driver Assignee: unassigned at gcc dot gnu.org Reporter: izbyshev at ispras dot ru Target Milestone: --- Target: riscv64-linux-gnu "msmall-data-limit=" is marked as both Joined and Separate at https://gcc.gnu.org/git?p=gcc.git;a=blob;f=gcc/config/riscv/riscv.opt;h=492aad1232404c2711811c3d04f2e02902d1b740;hb=7964ab6c364c410c34efe7ca2eba797d36525349#l95. This is inconsistent with other "-m" options (which permit only joined spelling) and allows strange commands like "riscv64-linux-gnu-gcc -msmall-data-limit= 0 test.c". Note that even if joined spelling is used by the user, GCC driver splits it for the frontend: riscv64-linux-gnu-gcc -msmall-data-limit=0 test.c -### [...] /usr/lib/gcc-cross/riscv64-linux-gnu/10/cc1 -quiet -imultilib . -imultiarch riscv64-linux-gnu test.c -quiet -dumpbase test.c "-mno-small-data-limit=" 0 "-march=rv64imafdc" "-mabi=lp64d" -auxbase test -fstack-protector-strong -Wformat -Wformat-security -o /tmp/ccIJvDDO.s [...] This inconsistency unnecessarily complicates life of tools that parse compiler commands (e.g. for static analysis).
[Bug other/99903] 32-bit x86 frontends randomly crash while reporting timing on Windows
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99903 --- Comment #3 from Alexey Izbyshev --- Crashes eventually occurred with both one- and two-processor affinity masks, so pinning GCC to a single core doesn't help. But I've tracked the reason down. When `get_time()` from `gcc/timevar.c` gets inlined into its callers (which happens with -O2), it "returns" the result on a x87 FPU register. Then `timevar_accumulate()` computes the difference between this 80-bit number and a 64-bit double stored in the timer structure. So when `clock()` returns 15 at both start and end measurements, this code basically subtracts 15 * (1.0 / 1000) stored with 64-bit precision from itself computed with 80-bit precision, and the difference is 8.673617379884035472e-19. When `clock()` returns 15 for all measurements during a single cc1 run, the total time and each phase time are equal to this same constant, and the sum of phase times is twice the total time: Timing error: total of phase timers exceeds total time. user1.734723475976807094e-18 > 8.673617379884035472e-19 Maybe GCC should round such ridiculously small intervals to zero?
[Bug other/99903] 32-bit x86 frontends randomly crash while reporting timing on Windows
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99903 --- Comment #2 from Alexey Izbyshev --- > Is there a way to bind GCC to a specific core and test again? Yes, `repro.py` can be run via `start /affinity MASK`. I've started two experiments, with one- and two-processor masks. They haven't crashed after several minutes, but I'll wait longer and then report the result. Anyway, it seems that crashing in `gcc_unreachable()` due to NULL `context->printer` is still kind-of-a-bug, since it makes it difficult to understand what went wrong in the first place.
[Bug other/99903] New: 32-bit x86 frontends randomly crash while reporting timing on Windows
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99903 Bug ID: 99903 Summary: 32-bit x86 frontends randomly crash while reporting timing on Windows Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: other Assignee: unassigned at gcc dot gnu.org Reporter: izbyshev at ispras dot ru Target Milestone: --- Host: i686-w64-mingw32 Target: i686-w64-mingw32 Build: i686-w64-mingw32 Created attachment 50503 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=50503&action=edit A reproducer Running cc1 from i686-w64-mingw32-gcc[1] with timing report enabled (e.g. without `-quiet` or with `-ftime-report`) may randomly crash on Windows. A reproducer script is attached (tested on two Windows 10 1909 x64 machines). The time to reproduce varied from seconds to half an hour. Running multiple cc1 to increase load appears to help, but is not required; just running a single cc1 in a loop is enough too. The crash manifests as silent exit with code 3221225477 (0xc005; EXCEPTION_ACCESS_VIOLATION). Debugging showed the following. The eventual crash is actually a nested one. It happens at [2] while reporting an ICE because `context->printer` is NULL (which, by itself, looks like a separate bug). The initial crash is triggered by `gcc_unreachable()` in `timer::validate_phases()`[3]. #0 0x0125be91 in pp_format(pretty_printer*, text_info*) () #1 0x0125146b in diagnostic_report_diagnostic(diagnostic_context*, diagnostic_info*) () #2 0x01251bd7 in diagnostic_impl(rich_location*, diagnostic_metadata const*, int, char const*, char**, diagnostic_t) () #3 0x012521b8 in internal_error(char const*, ...) () #4 0x01528a96 in fancy_abort(char const*, int, char const*) () #5 0x014f9e9c in timer::validate_phases(_iobuf*) const [clone .cold] () #6 0x009400d3 in timer::print(_iobuf*) () #7 0x00942422 in toplev::~toplev() () #8 0x01526003 in main () And `gcc_unreachable()` is reached because `phase_user > total->user * tolerance` is true. GCC doesn't print anything when run from `repro.py` because of output buffering, but I extracted one message from memory: Timing error: total of phase timers exceeds total time. user1.734723475976807094e-18 > 8.673617379884035472e-19 I couldn't reproduce this with 64-bit x86 GCC. [1] https://github.com/msys2/MINGW-packages/tree/5d82e17a56a3216a54dbb5924b92c96284ae5c97/mingw-w64-gcc [2] https://gcc.gnu.org/git?p=gcc.git;a=blob;f=gcc/diagnostic.c;h=ed52bc03d17afa2d7ac3419beb73e8f59b6f392b;hb=releases/gcc-10.2.0#l1077 [3] https://gcc.gnu.org/git?p=gcc.git;a=blob;f=gcc/timevar.c;h=a3a882d32040db6503260ab51ee4bf338c4aa2b5;hb=releases/gcc-10.2.0#l628