1 // P0595R1
2 // { dg-do run { target c++14 } }
3 
4 template<int N> struct X { int v = N; };
5 X<__builtin_is_constant_evaluated ()> x; // type X<true>
6 int y = 4;
7 int a = __builtin_is_constant_evaluated () ? y : 1; // initializes a to 1
8 int b = __builtin_is_constant_evaluated () ? 2 : y; // initializes b to 2
9 int c = y + (__builtin_is_constant_evaluated () ? 2 : y); // initializes c to 2*y
10 int d = __builtin_is_constant_evaluated (); // initializes d to 1
11 int e = d + __builtin_is_constant_evaluated (); // initializes e to 1 + 0
12 
13 struct false_type { static constexpr bool value = false; };
14 struct true_type { static constexpr bool value = true; };
15 template<class T, class U>
16 struct is_same : false_type {};
17 template<class T>
18 struct is_same<T, T> : true_type {};
19 
20 constexpr int
21 foo (int x)
22 {
23   const int n = __builtin_is_constant_evaluated () ? 13 : 17; // n == 13
24   int m = __builtin_is_constant_evaluated () ? 13 : 17; // m might be 13 or 17 (see below)
25   char arr[n] = {}; // char[13]
26   return m + sizeof (arr) + x;
27 }
28 
29 constexpr int
30 bar ()
31 {
32   const int n = __builtin_is_constant_evaluated() ? 13 : 17;
33   X<n> x1;
34   X<__builtin_is_constant_evaluated() ? 13 : 17> x2;
35   static_assert (is_same<decltype (x1), decltype (x2)>::value, "x1/x2's type");
36   return x1.v + x2.v;
37 }
38 
39 int p = foo (0); // m == 13; initialized to 26
40 int q = p + foo (0); // m == 17 for this call; initialized to 56
41 static_assert (bar () == 26, "bar");
42 
43 struct S { int a, b; };
44 
45 S s = { __builtin_is_constant_evaluated () ? 2 : 3, y };
46 S t = { __builtin_is_constant_evaluated () ? 2 : 3, 4 };
47 
48 static_assert (is_same<decltype (x), X<true> >::value, "x's type");
49 
50 int
51 main ()
52 {
53   if (a != 1 || b != 2 || c != 8 || d != 1 || e != 1 || p != 26 || q != 56)
54     __builtin_abort ();
55   if (s.a != 3 || s.b != 4 || t.a != 2 || t.b != 4)
56     __builtin_abort ();
57   if (foo (y) != 34)
58     __builtin_abort ();
59 #if __cplusplus >= 201703L
60   if constexpr (foo (0) != 26)
61     __builtin_abort ();
62 #endif
63   constexpr int w = foo (0);
64   if (w != 26)
65     __builtin_abort ();
66 }
67