Drew Dormann
Drew Dormann

Reputation: 63947

How does gcc compile C functions in a constexpr context?

Given that the C++ standard library doesn't (currently) provide constexpr versions of the cmath functions, consider the program below.

#include <cmath>
#include <cstring>

int main()
{
    constexpr auto a = std::pow(2, 10);
    constexpr auto b = std::strlen("ABC");
}

As expected, MSVC++ and clang++ fail to compile this, because constexpr variables are initialized from functions that are not declared constexpr.

g++, however, compiles this. The version of g++ doesn't seem to matter.

(See them all in compiler explorer)

How does g++ achieve this? Is this correct (allowed) compiler behavior?

Upvotes: 6

Views: 869

Answers (2)

Artyer
Artyer

Reputation: 40881

The resolution of LWG 2013 was that implementations are not allowed to declare non-constexpr functions as constexpr, so gcc is non-conformant by allowing these to be evaluated at compile time.

That said, GCC does not actually mark the needed functions as constexpr. What it instead does is replace those calls very early on with __builtin_pow and __builtin_strlen, which it can compute at compile time (the std:: versions call the libc versions, which can't). This is a compiler extension.

If you compile with -fno-builtin, it also fails to compile both std::pow and std::strlen, but you can make both clang and GCC compile this by explicitly writing out __builtin_pow(2, 10) and __builtin_strlen("ABC").

Upvotes: 8

Deev
Deev

Reputation: 481

As noted, the C++ standard library doesn't currently support constexpr evaluation of cmath functions. However, that doesn't prevent individual implementations from having non-standard code. GCC has a nonconforming extension that allows constexpr evaluation.

Upvotes: 6

Related Questions