// 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 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 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 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 (45) != 45 || f10 (128LL) != 128LL #if __cpp_nontype_template_args >= 201911L || f10 (-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 () != 0) std::abort (); }