hp
toc

Crashing GCC with 63 Bytes

2020-10-15, post № 235

C++, error, #GCC, #g++, #internal compiler error

Enthusiastically following C++20’s new compile-time capabilities as well as awaiting more powerful ones being promised in upcoming standards, yet being stuck on C++17 [1], I try to take full advantage of the limited C++17-constexpr features. However, without static storage promotion, a constexpr std::string is all but a pipe dream, thereby necessitating the use of a wrapped static pointer; std::string_view.

One does not program against one’s compiler; one programs against the abstract machine defined by the standard.

As such, whilst I was refactoring away under the comforting veil of passing tests, a tear announced itself in form of an email containing an erroneous make compilation output [2]. Excerpt (slightly formatted):

error: 'constexpr InstructionDefinitionsUtil::InstructionDefinitionsArray
        InstructionDefinitionsUtil::build()' called in constant expression

As unintuitive it may seem, I did indeed intend to call a constexpr builder inside a constant context, since I wanted to force compile-time computation of a lookup table. Alas, without C++20’s consteval specifier, a constexpr routine is only able to be evaluated at compile time, yet also leads to a dynamically accessible manifestation of its body.
Although I do not fully understand why, copying a std::string_view in a constexpr context seems to be the culprit. A culprit which is only detected by some GCC versions.

It turns out that there were two different compilers at play: I only tested my implementation using g++ 9.3.0 and clang 10.0.0, not g++ 10.2.0, as was the aforementioned email’s author.
Thus, to ensure compilability even with newer versions of GCC, I updated my compiler to g++ 10.2.0 and began to correct my implementation. Unsuspectingly typing away at my keyboard, I was shocked to receive a compilation error of a type which I have never encountered before:

crashing-gcc-with-63-bytes_first-crash.jpg
internal compiler error [3]

Curious about the root cause, I set out to distill a minimal (non-)working example. After all, I encountered an internal compiler error in a project spanning multiple thousand lines of code [4].

A few hours later, I managed to write a 63 byte long C++ source file which crashes g++ 10.2.0 when compiling using the C++17 standard:

int main(){[](){enum E{F};struct{E e{F};}p[1]{};return p->e;};}

Since the example is only a single short line, one can write a zsh one-liner to demonstrate GCC crashing:

% g++ -xc++ -std=c++17 =(printf 'int main(){[](){enum E{F};struct{E e{F};}p[1]{};return p->e;};}')

As my compiler asked kindly to file a report regarding its crash, I set out to create a Bugzilla account and filed a bug report: Bug 97430.

Hopefully this compiler bug soon gets fixed [5] and C++20 is adopted swiftly, since being ping-ponged between unexpected constexpr compiler inabilities and seemingly arbitrary compiler crashes made for a rather unpleasant coding experience.

Footnotes

  1. See https://github.com/jfrech/joy-assembler.
  2. See Joy-Assember@fee15a4/Types.hpp#L118 for the full source code context.
  3. internal compiler error: in verify_ctor_sanity, at cp/constexpr.c:3884
  4. To browse the repository at this point in time, see Joy-Assembler@e0bf0f1.
  5. [2020-10-28] My bug report has been marked to be a duplicate of Bug 96241, which in turn alledgedly has been fixed.
Jonathan Frech's blog; built 2024/12/19 23:13:08 CET