151 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -verify=expected,both %s -fexperimental-new-constant-interpreter2// RUN: %clang_cc1 -std=c++20 -verify=ref,both %s3 4using intptr_t = __INTPTR_TYPE__;5 6static_assert(__builtin_constant_p(12), "");7static_assert(__builtin_constant_p(1.0), "");8 9constexpr int I = 100;10static_assert(__builtin_constant_p(I), "");11static_assert(__builtin_constant_p(I + 10), "");12static_assert(__builtin_constant_p(I + 10.0), "");13static_assert(__builtin_constant_p(nullptr), "");14static_assert(__builtin_constant_p(&I), ""); // both-error {{failed due to requirement}}15static_assert(__builtin_constant_p((void)I), ""); // both-error {{failed due to requirement}}16 17extern int z;18constexpr int foo(int &a) {19 return __builtin_constant_p(a);20}21static_assert(!foo(z));22 23static_assert(__builtin_constant_p(__builtin_constant_p(1)));24 25constexpr bool nested(int& a) {26 return __builtin_constant_p(__builtin_constant_p(a));27}28static_assert(nested(z));29 30constexpr bool Local() {31 int z = 10;32 return __builtin_constant_p(z);33}34static_assert(Local());35 36constexpr bool Local2() {37 int z = 10;38 return __builtin_constant_p(&z);39}40static_assert(!Local2());41 42constexpr bool Parameter(int a) {43 return __builtin_constant_p(a);44}45static_assert(Parameter(10));46 47constexpr bool InvalidLocal() {48 int *z;49 {50 int b = 10;51 z = &b;52 }53 return __builtin_constant_p(z);54}55static_assert(!InvalidLocal());56 57template<typename T> constexpr bool bcp(T t) {58 return __builtin_constant_p(t);59}60 61constexpr intptr_t ptr_to_int(const void *p) {62 return __builtin_constant_p(1) ? (intptr_t)p : (intptr_t)p;63}64 65static_assert(bcp(ptr_to_int("foo")));66 67constexpr bool AndFold(const int &a, const int &b) {68 return __builtin_constant_p(a && b);69}70 71static_assert(AndFold(10, 20));72static_assert(!AndFold(z, 10));73static_assert(!AndFold(10, z));74 75 76struct F {77 int a;78};79 80constexpr F f{12};81static_assert(__builtin_constant_p(f.a));82 83constexpr bool Member() {84 F f;85 return __builtin_constant_p(f.a);86}87static_assert(!Member());88 89constexpr bool Discard() {90 (void)__builtin_constant_p(10);91 return true;92}93static_assert(Discard());94 95static_assert(__builtin_constant_p((int*)123));96 97constexpr void func() {}98static_assert(!__builtin_constant_p(func));99 100/// This is from SemaCXX/builtin-constant-p and GCC agrees with the bytecode interpreter.101constexpr int mutate1() {102 int n = 1;103 int m = __builtin_constant_p(++n);104 return n * 10 + m;105}106static_assert(mutate1() == 21); // ref-error {{static assertion failed}} \107 // ref-note {{evaluates to '10 == 21'}}108 109/// Similar for this. GCC agrees with the bytecode interpreter.110constexpr int mutate_param(bool mutate, int ¶m) {111 mutate = mutate; // Mutation of internal state is OK112 if (mutate)113 ++param;114 return param;115}116constexpr int mutate6(bool mutate) {117 int n = 1;118 int m = __builtin_constant_p(mutate_param(mutate, n));119 return n * 10 + m;120}121static_assert(mutate6(false) == 11);122static_assert(mutate6(true) == 21); // ref-error {{static assertion failed}} \123 // ref-note {{evaluates to '10 == 21'}}124 125#define fold(x) (__builtin_constant_p(x) ? (x) : (x))126void g() {127 /// f will be revisited when evaluating the static_assert, since it's128 /// a local variable. But it should be visited in a non-constant context.129 const float f = __builtin_is_constant_evaluated();130 static_assert(fold(f == 0.0f));131}132 133void test17(void) {134#define ASSERT(...) { enum { folded = (__VA_ARGS__) }; int arr[folded ? 1 : -1]; }135#define T(...) ASSERT(__builtin_constant_p(__VA_ARGS__))136#define F(...) ASSERT(!__builtin_constant_p(__VA_ARGS__))137 138 T(3i + 5);139 T("string literal");140 F("string literal" + 1); // both-warning {{adding}} \141 // both-note {{use array indexing}}142}143 144/// FIXME145static void foo(int i) __attribute__((__diagnose_if__(!__builtin_constant_p(i), "not constant", "error"))) // expected-note {{from}}146{147}148static void bar(int i) {149 foo(15); // expected-error {{not constant}}150}151