Break MSVC and Clang with this one weird trick

ibobev1 pts0 comments

Break MSVC and Clang with this one weird trick! | Braden++

A few weeks ago I came across some code that MSVC and Clang both rejected, but GCC accepted. The error messages are different in MSVC and Clang, so clearly I must have done something wrong, and GCC falsely accepts the code, right? I mostly minimized the code, and ended up with this. (Compiler Explorer link)

struct S{};

template<br>void foo(T) {<br>(void)[](U) consteval -> bool {<br>return requires { 0 * T{}; };<br>}(0);

void bar() {<br>foo(S{});

In this post I will explain how I got here, what I think is going on with all 3 of these compilers, and allude to what I’ll be talking about in the next article after this one.

Getting an expert opinion

I reached out to a compiler developer whose work I really respect, and who I always enjoy speaking with. Normally I wouldn’t do this, I would just file a bug with the relevant compiler and move on. But this one was too weird.

TODO: Add messages.

Alright, so it turns out GCC is actually the correct one here. This code should be accepted. MSVC rejects it for one reason, and Clang rejects it for another. That means that I’ll need to work around each of the compilers individually.

But first, this code looks too contrived. How did I get here?

The general backstory

I like writing compile-time code. For a few years I’ve been working on a compile-time parser generator library using expression templates. The challenge was to make all the parser types entirely empty, with no non-static data members. When I started, I knew significantly less C++ than I do now, and a lot of my learning came from writing the library. If you’re interested to take a look, it’s called tok3n

Because I have this parser generator library that I like very much, most of my effort has actually been focused on testing it. If you write compile-time code, you should also test that code as compile-time, so all of my tests check the compile-time behaviour of my library. This is something I care about deeply, and I’ve given 3 talks on it so far:

C++Now 2024 - Unit Testing an Expression Template Library in C++20

C++Now 2026 - Testing Everything in Constexpr (link TBD)

ACCU on Sea 2026 - Techniques of Compile-time Unit Testing in C++ (link TBD).

Between 2024 and 2026, I entirely changed my testing strategy, based on the amazing idea I encountered when writing my 2024 talk, from the Snitch library: You can store a compile-time condition, and only check the result at run-time. Instead of using static_assert throughout my tests, I want my tests to all compile successfully, even if there are compile-time conditions that fail. Then at run-time, I can have a nice user-defined error message and a nice test printout from the framework. This is nicer than a compiler-generated error message, especially because the printout is compiler-independent, and will look the same regardless.

I spun my testing framework off into its own repo separate from tok3n, and named it k3tchup. Then I started to add more features to it, in an effort to make it a generally usable testing library. This whole story for the past 2 years, with the technical details on many of the features I added, is the topic of my last 2 talks, at C++Now 2026 (link TBD) and ACCU on Sea 2026 (link TBD).

The specific backstory

After many various updates to the k3tchup framework, I updated the k3tchup submodule in tok3n, and encountered approximately 18 quintillion compiler errors, give or take. This was right after ACCU on Sea 2026, so a small amount of the code I showed in my slides is now outdated. Oops.

The short version is this. For any given parser p, you can add a bunch of modifiers onto it. For example, the complete modifier means that the parser will reject any input that has anything leftover after parsing.

constexpr auto p = "abc"_all;<br>constexpr auto p2 = p % complete; // Or `complete(p)`<br>static_assert(p.parse("abcd"));<br>static_assert(!p2.parse("abcd"));

Many of the errors were triggered inside a k3tchup “packet” (a nested callable) in tok3n’s tests, checking what happens when you add the modifiers. The library k3tchup itself doesn’t have any matchers, but tok3n’s tests build up a system of matchers.

For example, this is a simplified version of what happens.

EXPECT_THAT(the_parser | is_modifiable_by);

Which parser am I checking? Many of them. I have a long list of samples, and I want to check this condition for all of them. So I write something like this.

constexpr auto complete_modifier_tester =<br>[](P) {<br>EXPECT_THAT(the_parser | is_modifiable_by);<br>};

Then I loop over the list of samples with this tester lambda.

EXPECT_THAT(all_samples.satisfy(complete_modifier_tester));

The issue is happening inside the is_modifiable_by fragment, whose class is defined similar to this.

template<br>struct is_modifiable_by_fragment {<br>template<br>void operator()(P) const {

EXPECT_COMPILE_TIME(requires { M{}(P{}); });<br>EXPECT_COMPILE_TIME(requires { P{} % M{}; });

// etc...<br>};

I minimized the issue,...

time code compile library testing compiler

Related Articles