mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 14:06:07 +00:00
224 lines
5.4 KiB
C++
224 lines
5.4 KiB
C++
// 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<typename FloatT>
|
|
struct A {
|
|
int a;
|
|
FloatT f;
|
|
};
|
|
|
|
constexpr A<float> a{12};
|
|
static_assert(a.f == 0.0f, "");
|
|
|
|
constexpr A<double> 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}}
|
|
}
|