blob: 0be28c7ac8333a404db8596af5cef589dff5283d [file] [log] [blame]
// P1774R8 - Portable assumptions
// { dg-do run { target c++11 } }
namespace std
{
constexpr bool
isfinite (float x)
{ return __builtin_isfinite (x); }
constexpr bool
isfinite (double x)
{ return __builtin_isfinite (x); }
constexpr bool
isfinite (long double x)
{ return __builtin_isfinite (x); }
constexpr float
sqrt (float x)
{ return __builtin_sqrtf (x); }
constexpr double
sqrt (double x)
{ return __builtin_sqrt (x); }
constexpr long double
sqrt (long double x)
{ return __builtin_sqrtl (x); }
extern "C" void
abort ();
}
constexpr int
f1 (int i)
{
#if __cpp_constexpr >= 201603L
auto f = [=] { [[__assume__ (i == 0)]]; };
return sizeof (f);
#else
return sizeof (int);
#endif
}
void
f2 ()
{
static_assert (f1 (0) >= sizeof (int), "");
}
int
f3 (int i)
{
[[gnu::assume (i == 42)]];
return i;
}
int
f4 (int i)
{
__attribute__ ((assume (++i == 44)));
return i;
}
int a;
int *volatile c;
bool
f5 ()
{
++a;
return true;
}
constexpr int
f6 ()
{
#if __cpp_constexpr >= 201304L
[[__assume__ (f5 ())]];
#endif
return 1;
}
template <int ...args>
bool
f7 ()
{
#if __cpp_fold_expressions >= 201411L
[[__gnu__::__assume__ (((args >= 0) && ...))]];
return ((args >= 0) && ...);
#else
return true;
#endif
}
bool
f8 (double x)
{
[[gnu::assume (std::isfinite (x) && x >= 0.0)]];
return std::isfinite (std::sqrt (x));
}
double
f9 (double x)
{
__attribute__((assume (std::isfinite (std::sqrt (x)))));
return std::sqrt (x);
}
template <typename T, T N>
T
f10 (T x)
{
[[__assume__ (x == N)]];
return x;
}
int
f11 (int x)
{
[[gnu::assume (x == 93 ? true : throw 1)]];
return x;
}
constexpr int
f12 (int x)
{
#if __cpp_constexpr >= 201304L
__attribute__((assume (++x == 43)));
#endif
return x;
}
static_assert (f12 (42) == 42, "");
struct S
{
operator bool () { return true; }
};
int
f13 ()
{
S s;
[[__gnu__::__assume__ (s)]];
return 0;
}
template <typename T>
int
f14 ()
{
T t;
__attribute__((assume (t)));
return 0;
}
int
main ()
{
int b = 42;
double d = 42.0, e = 43.0;
c = &b;
[[__assume__ (f5 ())]];
if (a)
std::abort ();
[[gnu::assume (++b == 43)]];
if (b != 42 || *c != 42)
std::abort ();
static_assert (f6 () == 1, "");
if (f6 () != 1)
std::abort ();
if (a)
std::abort ();
if (!f7 <0> () || !f7 <1, 2, 3, 4> ())
std::abort ();
__attribute__((assume (d < e)));
if (f10 <int, 45> (45) != 45
|| f10 <long long, 128LL> (128LL) != 128LL
#if __cpp_nontype_template_args >= 201911L
|| f10 <long double, -42.0L> (-42.0L) != -42.0L
#endif
|| false)
std::abort ();
int i = 90, j = 91, k = 92;
[[__assume__ (i == 90), gnu::assume (j <= 91)]]
#if __cplusplus >= 201703L
[[using gnu:assume (k >= 92)]]
#else
[[gnu::assume (k >= 92)]]
#endif
;
__attribute__((__assume__ (i == 90), assume (j <= 91))) __attribute__((assume (k >= 92)));
if (f11 (93) != 93)
std::abort ();
if (f14 <S> () != 0)
std::abort ();
}