| // RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -verify=expected,both %s |
| // RUN: %clang_cc1 -std=c++20 -verify=ref,both %s |
| |
| using intptr_t = __INTPTR_TYPE__; |
| |
| static_assert(__builtin_constant_p(12), ""); |
| static_assert(__builtin_constant_p(1.0), ""); |
| |
| constexpr int I = 100; |
| static_assert(__builtin_constant_p(I), ""); |
| static_assert(__builtin_constant_p(I + 10), ""); |
| static_assert(__builtin_constant_p(I + 10.0), ""); |
| static_assert(__builtin_constant_p(nullptr), ""); |
| static_assert(__builtin_constant_p(&I), ""); // both-error {{failed due to requirement}} |
| static_assert(__builtin_constant_p((void)I), ""); // both-error {{failed due to requirement}} |
| |
| extern int z; |
| constexpr int foo(int &a) { |
| return __builtin_constant_p(a); |
| } |
| static_assert(!foo(z)); |
| |
| static_assert(__builtin_constant_p(__builtin_constant_p(1))); |
| |
| constexpr bool nested(int& a) { |
| return __builtin_constant_p(__builtin_constant_p(a)); |
| } |
| static_assert(nested(z)); |
| |
| constexpr bool Local() { |
| int z = 10; |
| return __builtin_constant_p(z); |
| } |
| static_assert(Local()); |
| |
| constexpr bool Local2() { |
| int z = 10; |
| return __builtin_constant_p(&z); |
| } |
| static_assert(!Local2()); |
| |
| constexpr bool Parameter(int a) { |
| return __builtin_constant_p(a); |
| } |
| static_assert(Parameter(10)); |
| |
| constexpr bool InvalidLocal() { |
| int *z; |
| { |
| int b = 10; |
| z = &b; |
| } |
| return __builtin_constant_p(z); |
| } |
| static_assert(!InvalidLocal()); |
| |
| template<typename T> constexpr bool bcp(T t) { |
| return __builtin_constant_p(t); |
| } |
| |
| constexpr intptr_t ptr_to_int(const void *p) { |
| return __builtin_constant_p(1) ? (intptr_t)p : (intptr_t)p; |
| } |
| |
| static_assert(bcp(ptr_to_int("foo"))); |
| |
| constexpr bool AndFold(const int &a, const int &b) { |
| return __builtin_constant_p(a && b); |
| } |
| |
| static_assert(AndFold(10, 20)); |
| static_assert(!AndFold(z, 10)); |
| static_assert(!AndFold(10, z)); |
| |
| |
| struct F { |
| int a; |
| }; |
| |
| constexpr F f{12}; |
| static_assert(__builtin_constant_p(f.a)); |
| |
| constexpr bool Member() { |
| F f; |
| return __builtin_constant_p(f.a); |
| } |
| static_assert(!Member()); |
| |
| constexpr bool Discard() { |
| (void)__builtin_constant_p(10); |
| return true; |
| } |
| static_assert(Discard()); |
| |
| static_assert(__builtin_constant_p((int*)123)); |
| |
| constexpr void func() {} |
| static_assert(!__builtin_constant_p(func)); |
| |
| /// This is from SemaCXX/builtin-constant-p and GCC agrees with the bytecode interpreter. |
| constexpr int mutate1() { |
| int n = 1; |
| int m = __builtin_constant_p(++n); |
| return n * 10 + m; |
| } |
| static_assert(mutate1() == 21); // ref-error {{static assertion failed}} \ |
| // ref-note {{evaluates to '10 == 21'}} |
| |
| /// Similar for this. GCC agrees with the bytecode interpreter. |
| constexpr int mutate_param(bool mutate, int ¶m) { |
| mutate = mutate; // Mutation of internal state is OK |
| if (mutate) |
| ++param; |
| return param; |
| } |
| constexpr int mutate6(bool mutate) { |
| int n = 1; |
| int m = __builtin_constant_p(mutate_param(mutate, n)); |
| return n * 10 + m; |
| } |
| static_assert(mutate6(false) == 11); |
| static_assert(mutate6(true) == 21); // ref-error {{static assertion failed}} \ |
| // ref-note {{evaluates to '10 == 21'}} |