// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s // RUN: %clang_cc1 -verify=ref %s constexpr void assert(bool C) { if (C) return; // Invalid in constexpr. (void)(1 / 0); // expected-warning {{undefined}} \ // ref-warning {{undefined}} } constexpr int i = 2; constexpr float f = 1.0f; static_assert(f == 1.0f, ""); constexpr float f2 = 1u * f; static_assert(f2 == 1.0f, ""); constexpr float f3 = 1.5; constexpr int i3 = f3; static_assert(i3 == 1, ""); constexpr bool b3 = f3; static_assert(b3, ""); static_assert(1.0f + 3u == 4, ""); static_assert(4.0f / 1.0f == 4, ""); static_assert(10.0f * false == 0, ""); constexpr float floats[] = {1.0f, 2.0f, 3.0f, 4.0f}; constexpr float m = 5.0f / 0.0f; // ref-error {{must be initialized by a constant expression}} \ // ref-note {{division by zero}} \ // expected-error {{must be initialized by a constant expression}} \ // expected-note {{division by zero}} static_assert(~2.0f == 3, ""); // ref-error {{invalid argument type 'float' to unary expression}} \ // expected-error {{invalid argument type 'float' to unary expression}} typedef int tdb[(long long)4e20]; //expected-error {{variable length}} \ //ref-error {{variable length}} /// Initialized by a double. constexpr float df = 0.0; /// The other way around. constexpr double fd = 0.0f; static_assert(0.0f == -0.0f, ""); const int k = 3 * (1.0f / 3.0f); static_assert(k == 1, ""); constexpr bool b = 1.0; static_assert(b, ""); constexpr double db = true; static_assert(db == 1.0, ""); constexpr float fa[] = {1.0f, 2.0, 1, false}; constexpr double da[] = {1.0f, 2.0, 1, false}; constexpr float fm = __FLT_MAX__; constexpr int someInt = fm; // ref-error {{must be initialized by a constant expression}} \ // ref-note {{is outside the range of representable values}} \ // expected-error {{must be initialized by a constant expression}} \ // expected-note {{is outside the range of representable values}} namespace compound { constexpr float f1() { float f = 0; f += 3.0; f -= 3.0f; f += 1; f /= 1; f /= 1.0; f *= f; f *= 2.0; return f; } static_assert(f1() == 2, ""); constexpr float f2() { float f = __FLT_MAX__; f += 1.0; return f; } static_assert(f2() == __FLT_MAX__, ""); constexpr float ff() { float a[] = {1,2}; int i = 0; // RHS should be evaluated before LHS, so this should // write to a[1]; a[i++] += ++i; #if __cplusplus <= 201402L // expected-warning@-2 {{multiple unsequenced modifications}} \ // ref-warning@-2 {{multiple unsequenced modifications}} #endif return a[1]; } static_assert(ff() == 3, ""); constexpr float intPlusDouble() { int a = 0; a += 2.0; return a; } static_assert(intPlusDouble() == 2, ""); constexpr double doublePlusInt() { double a = 0.0; a += 2; return a; } static_assert(doublePlusInt() == 2, ""); constexpr float boolPlusDouble() { bool a = 0; a += 1.0; return a; } static_assert(boolPlusDouble(), ""); constexpr bool doublePlusbool() { double a = 0.0; a += true; return a; } static_assert(doublePlusbool() == 1.0, ""); } namespace unary { constexpr float a() { float f = 0.0; assert(++f == 1.0); assert(f == 1.0); ++f; f++; assert(f == 3.0); --f; f--; assert(f == 1.0); return 1.0; } static_assert(a() == 1.0, ""); constexpr float b() { float f = __FLT_MAX__; f++; return f; } static_assert(b() == __FLT_MAX__, ""); } namespace ZeroInit { template struct A { int a; FloatT f; }; constexpr A a{12}; static_assert(a.f == 0.0f, ""); constexpr A b{12}; static_assert(a.f == 0.0, ""); }; namespace LongDouble { constexpr long double ld = 3.1425926539; constexpr long double f() { const long double L = __LDBL_MAX__; return L; }; static_assert(f() == __LDBL_MAX__, ""); #ifdef __FLOAT128__ constexpr __float128 f128() { const __float128 L = __LDBL_MAX__; return L; }; static_assert(f128() == __LDBL_MAX__, ""); #endif } namespace Compare { constexpr float nan = __builtin_nan(""); constexpr float inf = __builtin_inf(); static_assert(!(nan == nan), ""); static_assert(nan != nan, ""); static_assert(!(inf < nan), ""); static_assert(!(inf > nan), ""); } namespace nan { constexpr double nan = __builtin_nan(""); static_assert(nan); constexpr double D1 = 1 + nan; // ref-error {{must be initialized by a constant expression}} \ // ref-note {{produces a NaN}} \ // expected-error {{must be initialized by a constant expression}} \ // expected-note {{produces a NaN}} constexpr double D2 = __builtin_inf() / __builtin_inf(); // ref-error {{must be initialized by a constant expression}} \ // ref-note {{produces a NaN}} \ // expected-error {{must be initialized by a constant expression}} \ // expected-note {{produces a NaN}} }