Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC and Clang differ in static_assert related to __builtin_constant_p

I happen to find that GCC and Clang differ in the compilation of the following code:

struct Foo
{
    int mem = 42;
};

int main()
{
    constexpr Foo foo;
    static_assert(__builtin_constant_p(foo));
    return 0;
}

I compile with g++ -std=c++17 and clang++ -std=c++17.

In particular,

  • g++ g++-9 (Homebrew GCC 9.3.0_1) 9.3.0 compiles, whereas
  • clang++ Apple clang version 11.0.3 (clang-1103.0.32.62) fails to compile, complaining that
error: static_assert failed due to requirement '__builtin_constant_p(foo)'
    static_assert(__builtin_constant_p(foo));
    ^             ~~~~~~~~~~~~~~~~~~~~~~~~~

I didn't find any hint that there should be any difference regarding __builtin_constant_p.

For __builtin_constant_p

GCC says

You can use the built-in function __builtin_constant_p to determine if a value is known to be constant at compile time ...

Clang says

Clang supports a number of builtin library functions with the same syntax as GCC, including things like __builtin_nan, __builtin_constant_p, __builtin_choose_expr, __builtin_types_compatible_p, __builtin_assume_aligned, __sync_fetch_and_add, etc.

Question: While I know __builtin_constant_p is a compiler extension, which one should be the correct one?

like image 818
aafulei Avatar asked Nov 06 '22 06:11

aafulei


1 Answers

Both are poorly documented so I doubt there is a proper answer to your question.

If you need a workaround: it seems that clang gives up if the argument is not an int.

So this works:

struct Foo
{
    int mem = 42;
};

int main()
{
    constexpr Foo foo;
    static_assert(__builtin_constant_p(foo.mem));
    return 0;
}
like image 113
NoSenseEtAl Avatar answered Nov 13 '22 21:11

NoSenseEtAl