1 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
2 // RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter -verify %s
3 // RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -verify %s
4 // RUN: %clang_cc1 -verify=ref %s
5 // RUN: %clang_cc1 -std=c++14 -verify=ref %s
6 // RUN: %clang_cc1 -std=c++20 -verify=ref %s
8 constexpr void doNothing() {}
9 constexpr int gimme5() {
13 static_assert(gimme5() == 5, "");
16 template<typename T
> constexpr T
identity(T t
) {
17 static_assert(true, "");
20 static_assert(identity(true), "");
21 static_assert(identity(true), ""); /// Compiled bytecode should be cached
22 static_assert(!identity(false), "");
24 template<typename A
, typename B
>
25 constexpr bool sameSize() {
26 static_assert(sizeof(A
) == sizeof(B
), ""); // expected-error {{static assertion failed}} \
27 // ref-error {{static assertion failed}} \
28 // expected-note {{evaluates to}} \
29 // ref-note {{evaluates to}}
32 static_assert(sameSize
<int, int>(), "");
33 static_assert(sameSize
<unsigned int, int>(), "");
34 static_assert(sameSize
<char, long>(), ""); // expected-note {{in instantiation of function template specialization}} \
35 // ref-note {{in instantiation of function template specialization}}
38 constexpr auto add(int a
, int b
) -> int {
39 return identity(a
) + identity(b
);
42 constexpr int sub(int a
, int b
) {
45 static_assert(sub(5, 2) == 3, "");
46 static_assert(sub(0, 5) == -5, "");
48 constexpr int norm(int n
) {
54 static_assert(norm(5) == norm(-5), "");
56 constexpr int square(int n
) {
57 return norm(n
) * norm(n
);
59 static_assert(square(2) == 4, "");
61 constexpr int add_second(int a
, int b
, bool doAdd
= true) {
66 static_assert(add_second(10, 3, true) == 13, "");
67 static_assert(add_second(10, 3) == 13, "");
68 static_assert(add_second(300, -20, false) == 300, "");
71 constexpr int sub(int a
, int b
, int c
) {
74 static_assert(sub(10, 8, 2) == 0, "");
77 constexpr int recursion(int i
) {
85 static_assert(recursion(10) == 0, "");
88 constexpr decltype(N
) getNum() {
91 static_assert(getNum
<-2>() == -2, "");
92 static_assert(getNum
<10>() == 10, "");
93 static_assert(getNum() == 5, "");
95 constexpr int f(); // expected-note {{declared here}} \
96 // ref-note {{declared here}}
97 static_assert(f() == 5, ""); // expected-error {{not an integral constant expression}} \
98 // expected-note {{undefined function 'f'}} \
99 // ref-error {{not an integral constant expression}} \
100 // ref-note {{undefined function 'f'}}
107 static_assert(a() == 5, "");
109 constexpr int invalid() {
110 // Invalid expression in visit().
111 while(huh
) {} // expected-error {{use of undeclared identifier}} \
112 // ref-error {{use of undeclared identifier}}
117 constexpr void invalid2() {
119 // Invalid expression in discard().
120 huh(); // expected-error {{use of undeclared identifier}} \
121 // ref-error {{use of undeclared identifier}}
124 namespace FunctionPointers
{
125 constexpr int add(int a
, int b
) {
134 constexpr int applyBinOp(int a
, int b
, int (*op
)(int, int)) {
137 static_assert(applyBinOp(1, 2, add
) == 3, "");
139 constexpr int ignoreReturnValue() {
140 int (*foo
)(int, int) = add
;
145 static_assert(ignoreReturnValue() == 1, "");
147 constexpr int createS(S (*gimme
)()) {
148 gimme(); // Ignored return value
151 static_assert(createS(getS
) == 12, "");
153 namespace FunctionReturnType
{
154 typedef int (*ptr
)(int*);
157 constexpr int fun1(int* y
) {
160 constexpr ptr
fun() {
163 static_assert(fun() == nullptr, ""); // expected-error {{static assertion failed}} \
164 // ref-error {{static assertion failed}}
166 constexpr int foo() {
167 int (*f
)(int *) = fun();
174 static_assert(foo() == 10, "");
182 static_assert(s
.fp
== nullptr, ""); // zero-initialized function pointer.
184 constexpr int (*op
)(int, int) = add
;
185 constexpr bool b
= op
;
186 static_assert(op
, "");
187 static_assert(!!op
, "");
188 constexpr int (*op2
)(int, int) = nullptr;
189 static_assert(!op2
, "");
192 namespace Comparison
{
194 constexpr void (*pf
)() = &f
, (*pg
)() = &g
;
196 constexpr bool u13
= pf
< pg
; // ref-warning {{ordered comparison of function pointers}} \
197 // ref-error {{must be initialized by a constant expression}} \
198 // ref-note {{comparison between '&f' and '&g' has unspecified value}} \
199 // expected-warning {{ordered comparison of function pointers}} \
200 // expected-error {{must be initialized by a constant expression}} \
201 // expected-note {{comparison between '&f' and '&g' has unspecified value}}
203 constexpr bool u14
= pf
< (void(*)())nullptr; // ref-warning {{ordered comparison of function pointers}} \
204 // ref-error {{must be initialized by a constant expression}} \
205 // ref-note {{comparison between '&f' and 'nullptr' has unspecified value}} \
206 // expected-warning {{ordered comparison of function pointers}} \
207 // expected-error {{must be initialized by a constant expression}} \
208 // expected-note {{comparison between '&f' and 'nullptr' has unspecified value}}
212 static_assert(pf
!= pg
, "");
213 static_assert(pf
== &f
, "");
214 static_assert(pg
== &g
, "");
220 constexpr bool ok() const {
223 constexpr bool okRecurse() const {
228 struct BodylessMemberFunction
{
229 constexpr int first() const {
232 constexpr int second() const {
237 constexpr int nyd(int m
);
238 constexpr int doit() { return nyd(10); }
239 constexpr int nyd(int m
) { return m
; }
240 static_assert(doit() == 10, "");
242 namespace InvalidCall
{
244 constexpr int a() const { // expected-error {{never produces a constant expression}} \
245 // ref-error {{never produces a constant expression}}
246 return 1 / 0; // expected-note 2{{division by zero}} \
247 // expected-warning {{is undefined}} \
248 // ref-note 2{{division by zero}} \
249 // ref-warning {{is undefined}}
253 static_assert(s
.a() == 1, ""); // expected-error {{not an integral constant expression}} \
254 // expected-note {{in call to}} \
255 // ref-error {{not an integral constant expression}} \
256 // ref-note {{in call to}}
258 /// This used to cause an assertion failure in the new constant interpreter.
259 constexpr void func(); // expected-note {{declared here}} \
260 // ref-note {{declared here}}
262 constexpr SS() { func(); } // expected-note {{undefined function }} \
263 // ref-note {{undefined function}}
265 constexpr SS ss
; // expected-error {{must be initialized by a constant expression}} \
266 // expected-note {{in call to 'SS()'}} \
267 // ref-error {{must be initialized by a constant expression}} \
268 // ref-note {{in call to 'SS()'}}
272 namespace CallWithArgs
{
273 /// This used to call problems during checkPotentialConstantExpression() runs.
274 constexpr void g(int a
) {}
280 namespace ReturnLocalPtr
{
283 return &a
; // ref-warning {{address of stack memory}} \
284 // expected-warning {{address of stack memory}}
287 /// GCC rejects the expression below, just like the new interpreter. The current interpreter
288 /// however accepts it and only warns about the function above returning an address to stack
289 /// memory. If we change the condition to 'p() != nullptr', it even succeeds.
290 static_assert(p() == nullptr, ""); // ref-error {{static assertion failed}} \
291 // expected-error {{not an integral constant expression}}
293 /// FIXME: The current interpreter emits diagnostics in the reference case below, but the
294 /// new one does not.
295 constexpr const int &p2() {
296 int a
= 12; // ref-note {{declared here}}
297 return a
; // ref-warning {{reference to stack memory associated with local variable}} \
298 // expected-warning {{reference to stack memory associated with local variable}}
301 static_assert(p2() == 12, ""); // ref-error {{not an integral constant expression}} \
302 // ref-note {{read of variable whose lifetime has ended}} \
303 // expected-error {{not an integral constant expression}}
306 namespace VoidReturn
{
307 /// ReturnStmt with an expression in a void function used to cause problems.
308 constexpr void bar() {}
309 constexpr void foo() {
312 static_assert((foo(),1) == 1, "");
315 namespace InvalidReclRefs
{
316 void param(bool b
) { // ref-note {{declared here}} \
317 // expected-note {{declared here}}
318 static_assert(b
, ""); // ref-error {{not an integral constant expression}} \
319 // ref-note {{function parameter 'b' with unknown value}} \
320 // expected-error {{not an integral constant expression}} \
321 // expected-note {{function parameter 'b' with unknown value}}
322 static_assert(true ? true : b
, "");
325 #if __cplusplus >= 202002L
326 consteval
void param2(bool b
) { // ref-note {{declared here}} \
327 // expected-note {{declared here}}
328 static_assert(b
, ""); // ref-error {{not an integral constant expression}} \
329 // ref-note {{function parameter 'b' with unknown value}} \
330 // expected-error {{not an integral constant expression}} \
331 // expected-note {{function parameter 'b' with unknown value}}
336 namespace TemplateUndefined
{
337 template<typename T
> constexpr int consume(T
);
338 // ok, not a constant expression.
339 const int k
= consume(0);
341 template<typename T
> constexpr int consume(T
) { return 0; }
342 // ok, constant expression.
343 constexpr int l
= consume(0);
344 static_assert(l
== 0, "");
347 namespace PtrReturn
{
348 constexpr void *a() {
351 static_assert(a() == nullptr, "");
355 struct S
{ int a
; bool b
; };
357 constexpr void variadic_function(int a
, ...) {}
359 variadic_function(1, S
{'a', false});
362 static_assert(f1() == 1, "");
364 constexpr int variadic_function2(...) {
367 static_assert(variadic_function2() == 12, "");
368 static_assert(variadic_function2(1, 2, 3, 4, 5) == 12, "");
369 static_assert(variadic_function2(1, variadic_function2()) == 12, "");
371 constexpr int (*VFP
)(...) = variadic_function2
;
372 static_assert(VFP() == 12, "");