xref: /llvm-project/clang/test/AST/ByteCode/floats.cpp (revision a07aba5d44204a7ca0d891a3da05af9960081e4c)
1 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
2 // RUN: %clang_cc1 -verify=ref %s
3 
4 
5 constexpr void assert(bool C) {
6   if (C)
7     return;
8   // Invalid in constexpr.
9   (void)(1 / 0); // expected-warning {{undefined}} \
10                  // ref-warning {{undefined}}
11 }
12 
13 constexpr int i = 2;
14 constexpr float f = 1.0f;
15 static_assert(f == 1.0f, "");
16 
17 constexpr float f2 = 1u * f;
18 static_assert(f2 == 1.0f, "");
19 
20 constexpr float f3 = 1.5;
21 constexpr int i3 = f3;
22 static_assert(i3 == 1, "");
23 
24 constexpr bool b3 = f3;
25 static_assert(b3, "");
26 
27 
28 static_assert(1.0f + 3u == 4, "");
29 static_assert(4.0f / 1.0f == 4, "");
30 static_assert(10.0f * false == 0, "");
31 
32 constexpr float floats[] = {1.0f, 2.0f, 3.0f, 4.0f};
33 
34 constexpr float m = 5.0f / 0.0f; // ref-error {{must be initialized by a constant expression}} \
35                                  // ref-note {{division by zero}} \
36                                  // expected-error {{must be initialized by a constant expression}} \
37                                  // expected-note {{division by zero}}
38 
39 static_assert(~2.0f == 3, ""); // ref-error {{invalid argument type 'float' to unary expression}} \
40                                // expected-error {{invalid argument type 'float' to unary expression}}
41 
42 
43 typedef int tdb[(long long)4e20]; //expected-error {{variable length}} \
44                                   //ref-error {{variable length}}
45 
46 /// Initialized by a double.
47 constexpr float df = 0.0;
48 /// The other way around.
49 constexpr double fd = 0.0f;
50 
51 static_assert(0.0f == -0.0f, "");
52 
53 const int k = 3 * (1.0f / 3.0f);
54 static_assert(k == 1, "");
55 
56 constexpr bool b = 1.0;
57 static_assert(b, "");
58 
59 constexpr double db = true;
60 static_assert(db == 1.0, "");
61 
62 constexpr float fa[] = {1.0f, 2.0, 1, false};
63 constexpr double da[] = {1.0f, 2.0, 1, false};
64 
65 constexpr float fm = __FLT_MAX__;
66 constexpr int someInt = fm; // ref-error {{must be initialized by a constant expression}} \
67                             // ref-note {{is outside the range of representable values}} \
68                             // expected-error {{must be initialized by a constant expression}} \
69                             // expected-note {{is outside the range of representable values}}
70 
71 namespace compound {
72   constexpr float f1() {
73     float f = 0;
74     f += 3.0;
75     f -= 3.0f;
76 
77     f += 1;
78     f /= 1;
79     f /= 1.0;
80     f *= f;
81 
82     f *= 2.0;
83     return f;
84   }
85   static_assert(f1() == 2, "");
86 
87   constexpr float f2() {
88     float f = __FLT_MAX__;
89     f += 1.0;
90     return f;
91   }
92   static_assert(f2() == __FLT_MAX__, "");
93 
94   constexpr float ff() {
95     float a[] = {1,2};
96     int i = 0;
97 
98     // RHS should be evaluated before LHS, so this should
99     // write to a[1];
100     a[i++] += ++i;
101 #if __cplusplus <= 201402L
102                   // expected-warning@-2 {{multiple unsequenced modifications}} \
103                   // ref-warning@-2 {{multiple unsequenced modifications}}
104 #endif
105 
106     return a[1];
107   }
108   static_assert(ff() == 3, "");
109 
110   constexpr float intPlusDouble() {
111    int a = 0;
112    a += 2.0;
113 
114    return a;
115   }
116   static_assert(intPlusDouble() == 2, "");
117 
118   constexpr double doublePlusInt() {
119    double a = 0.0;
120    a += 2;
121 
122    return a;
123   }
124   static_assert(doublePlusInt() == 2, "");
125 
126   constexpr float boolPlusDouble() {
127    bool a = 0;
128    a += 1.0;
129 
130    return a;
131   }
132   static_assert(boolPlusDouble(), "");
133 
134   constexpr bool doublePlusbool() {
135    double a = 0.0;
136    a += true;
137 
138    return a;
139   }
140   static_assert(doublePlusbool() == 1.0, "");
141 }
142 
143 namespace unary {
144   constexpr float a() {
145     float f = 0.0;
146     assert(++f == 1.0);
147     assert(f == 1.0);
148     ++f;
149     f++;
150     assert(f == 3.0);
151     --f;
152     f--;
153     assert(f == 1.0);
154     return 1.0;
155   }
156   static_assert(a() == 1.0, "");
157 
158   constexpr float b() {
159     float f = __FLT_MAX__;
160     f++;
161     return f;
162   }
163   static_assert(b() == __FLT_MAX__, "");
164 }
165 
166 
167 namespace ZeroInit {
168   template<typename FloatT>
169   struct A {
170     int a;
171     FloatT f;
172   };
173 
174   constexpr A<float> a{12};
175   static_assert(a.f == 0.0f, "");
176 
177   constexpr A<double> b{12};
178   static_assert(a.f == 0.0, "");
179 };
180 
181 namespace LongDouble {
182   constexpr long double ld = 3.1425926539;
183 
184   constexpr long double f() {
185     const long double L = __LDBL_MAX__;
186 
187     return L;
188   };
189   static_assert(f() == __LDBL_MAX__, "");
190 
191 #ifdef __FLOAT128__
192   constexpr __float128 f128() {
193     const __float128 L = __LDBL_MAX__;
194 
195     return L;
196   };
197   static_assert(f128() == __LDBL_MAX__, "");
198 #endif
199 }
200 
201 namespace Compare {
202   constexpr float nan = __builtin_nan("");
203   constexpr float inf = __builtin_inf();
204   static_assert(!(nan == nan), "");
205   static_assert(nan != nan, "");
206   static_assert(!(inf < nan), "");
207   static_assert(!(inf > nan), "");
208 }
209 
210 namespace nan {
211   constexpr double nan = __builtin_nan("");
212   static_assert(nan);
213 
214   constexpr double D1 = 1 + nan; // ref-error {{must be initialized by a constant expression}} \
215                                  // ref-note {{produces a NaN}} \
216                                  // expected-error {{must be initialized by a constant expression}} \
217                                  // expected-note {{produces a NaN}}
218 
219   constexpr double D2 = __builtin_inf() / __builtin_inf(); // ref-error {{must be initialized by a constant expression}} \
220                                                            // ref-note {{produces a NaN}} \
221                                                            // expected-error {{must be initialized by a constant expression}} \
222                                                            // expected-note {{produces a NaN}}
223 }
224