xref: /llvm-project/clang/test/AST/ByteCode/functions.cpp (revision fd6baa477fa13a4b893aeeba7fce92eb6a1f4962)
1 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -pedantic -verify=expected,both %s
2 // RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter -pedantic -verify=expected,both %s
3 // RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -pedantic -verify=expected,both %s
4 // RUN: %clang_cc1 -pedantic -verify=ref,both %s
5 // RUN: %clang_cc1 -pedantic -std=c++14 -verify=ref,both %s
6 // RUN: %clang_cc1 -pedantic -std=c++20 -verify=ref,both %s
7 
8 constexpr void doNothing() {}
9 constexpr int gimme5() {
10   doNothing();
11   return 5;
12 }
13 static_assert(gimme5() == 5, "");
14 
15 
16 template<typename T> constexpr T identity(T t) {
17   static_assert(true, "");
18   return t;
19 }
20 static_assert(identity(true), "");
21 static_assert(identity(true), ""); /// Compiled bytecode should be cached
22 static_assert(!identity(false), "");
23 
24 template<typename A, typename B>
25 constexpr bool sameSize() {
26   static_assert(sizeof(A) == sizeof(B), ""); // both-error {{static assertion failed}} \
27                                              // both-note {{evaluates to}}
28   return true;
29 }
30 static_assert(sameSize<int, int>(), "");
31 static_assert(sameSize<unsigned int, int>(), "");
32 static_assert(sameSize<char, long>(), ""); // both-note {{in instantiation of function template specialization}}
33 
34 
35 constexpr auto add(int a, int b) -> int {
36   return identity(a) + identity(b);
37 }
38 
39 constexpr int sub(int a, int b) {
40   return a - b;
41 }
42 static_assert(sub(5, 2) == 3, "");
43 static_assert(sub(0, 5) == -5, "");
44 
45 constexpr int norm(int n) {
46   if (n >= 0) {
47     return identity(n);
48   }
49   return -identity(n);
50 }
51 static_assert(norm(5) == norm(-5), "");
52 
53 constexpr int square(int n) {
54   return norm(n) * norm(n);
55 }
56 static_assert(square(2) == 4, "");
57 
58 constexpr int add_second(int a, int b, bool doAdd = true) {
59   if (doAdd)
60     return a + b;
61   return a;
62 }
63 static_assert(add_second(10, 3, true) == 13, "");
64 static_assert(add_second(10, 3) == 13, "");
65 static_assert(add_second(300, -20, false) == 300, "");
66 
67 
68 constexpr int sub(int a, int b, int c) {
69   return a - b - c;
70 }
71 static_assert(sub(10, 8, 2) == 0, "");
72 
73 
74 constexpr int recursion(int i) {
75   doNothing();
76   i = i - 1;
77   if (i == 0)
78     return identity(0);
79 
80   return recursion(i);
81 }
82 static_assert(recursion(10) == 0, "");
83 
84 template<int N = 5>
85 constexpr decltype(N) getNum() {
86   return N;
87 }
88 static_assert(getNum<-2>() == -2, "");
89 static_assert(getNum<10>() == 10, "");
90 static_assert(getNum() == 5, "");
91 
92 constexpr int f(); // both-note {{declared here}}
93 static_assert(f() == 5, ""); // both-error {{not an integral constant expression}} \
94                              // both-note {{undefined function 'f'}}
95 constexpr int a() {
96   return f();
97 }
98 constexpr int f() {
99   return 5;
100 }
101 static_assert(a() == 5, "");
102 
103 constexpr int invalid() {
104   // Invalid expression in visit().
105   while(huh) {} // both-error {{use of undeclared identifier}}
106   return 0;
107 }
108 
109 constexpr void invalid2() {
110   int i = 0;
111   // Invalid expression in discard().
112   huh(); // both-error {{use of undeclared identifier}}
113 }
114 
115 namespace FunctionPointers {
116   constexpr int add(int a, int b) {
117     return a + b;
118   }
119 
120   struct S { int a; };
121   constexpr S getS() {
122     return S{12};
123   }
124 
125   constexpr int applyBinOp(int a, int b, int (*op)(int, int)) {
126     return op(a, b); // both-note {{evaluates to a null function pointer}}
127   }
128   static_assert(applyBinOp(1, 2, add) == 3, "");
129   static_assert(applyBinOp(1, 2, nullptr) == 3, ""); // both-error {{not an integral constant expression}} \
130                                                      // both-note {{in call to}}
131 
132 
133   constexpr int ignoreReturnValue() {
134     int (*foo)(int, int) = add;
135 
136     foo(1, 2);
137     return 1;
138   }
139   static_assert(ignoreReturnValue() == 1, "");
140 
141   constexpr int createS(S (*gimme)()) {
142     gimme(); // Ignored return value
143     return gimme().a;
144   }
145   static_assert(createS(getS) == 12, "");
146 
147 namespace FunctionReturnType {
148   typedef int (*ptr)(int*);
149   typedef ptr (*pm)();
150 
151   constexpr int fun1(int* y) {
152       return *y + 10;
153   }
154   constexpr ptr fun() {
155       return &fun1;
156   }
157   static_assert(fun() == nullptr, ""); // both-error {{static assertion failed}}
158 
159   constexpr int foo() {
160     int (*f)(int *) = fun();
161     int m = 0;
162 
163     m = f(&m);
164 
165     return m;
166   }
167   static_assert(foo() == 10, "");
168 
169   struct S {
170     int i;
171     void (*fp)();
172   };
173 
174   constexpr S s{ 12 };
175   static_assert(s.fp == nullptr, ""); // zero-initialized function pointer.
176 
177   constexpr int (*op)(int, int) = add;
178   constexpr bool b = op;
179   static_assert(op, "");
180   static_assert(!!op, "");
181   constexpr int (*op2)(int, int) = nullptr;
182   static_assert(!op2, "");
183 
184   int m() { return 5;} // both-note {{declared here}}
185   constexpr int (*invalidFnPtr)() = m;
186   static_assert(invalidFnPtr() == 5, ""); // both-error {{not an integral constant expression}} \
187                                           // both-note {{non-constexpr function 'm'}}
188 
189 
190 namespace ToBool {
191   void mismatched(int x) {}
192   typedef void (*callback_t)(int);
193   void foo() {
194     callback_t callback = (callback_t)mismatched; // warns
195     /// Casts a function pointer to a boolean and then back to a function pointer.
196     /// This is extracted from test/Sema/callingconv-cast.c
197     callback = (callback_t)!mismatched; // both-warning {{address of function 'mismatched' will always evaluate to 'true'}} \
198                                         // both-note {{prefix with the address-of operator to silence this warning}}
199   }
200 }
201 
202 
203 }
204 
205 namespace Comparison {
206   void f(), g();
207   constexpr void (*pf)() = &f, (*pg)() = &g;
208 
209   constexpr bool u13 = pf < pg; // both-warning {{ordered comparison of function pointers}} \
210                                 // both-error {{must be initialized by a constant expression}} \
211                                 // both-note {{comparison between pointers to unrelated objects '&f' and '&g' has unspecified value}}
212 
213   constexpr bool u14 = pf < (void(*)())nullptr; // both-warning {{ordered comparison of function pointers}} \
214                                                 // both-error {{must be initialized by a constant expression}} \
215                                                 // both-note {{comparison between pointers to unrelated objects '&f' and 'nullptr' has unspecified value}}
216 
217 
218 
219   static_assert(pf != pg, "");
220   static_assert(pf == &f, "");
221   static_assert(pg == &g, "");
222 }
223 
224   constexpr int Double(int n) { return 2 * n; }
225   constexpr int Triple(int n) { return 3 * n; }
226   constexpr int Twice(int (*F)(int), int n) { return F(F(n)); }
227   constexpr int Quadruple(int n) { return Twice(Double, n); }
228   constexpr auto Select(int n) -> int (*)(int) {
229     return n == 2 ? &Double : n == 3 ? &Triple : n == 4 ? &Quadruple : 0;
230   }
231   constexpr int Apply(int (*F)(int), int n) { return F(n); } // both-note {{'F' evaluates to a null function pointer}}
232 
233   constexpr int Invalid = Apply(Select(0), 0); // both-error {{must be initialized by a constant expression}} \
234                                                // both-note {{in call to 'Apply(nullptr, 0)'}}
235 }
236 
237 struct F {
238   constexpr bool ok() const {
239     return okRecurse();
240   }
241   constexpr bool okRecurse() const {
242     return true;
243   }
244 };
245 
246 struct BodylessMemberFunction {
247   constexpr int first() const {
248     return second();
249   }
250   constexpr int second() const {
251     return 1;
252   }
253 };
254 
255 constexpr int nyd(int m);
256 constexpr int doit() { return nyd(10); }
257 constexpr int nyd(int m) { return m; }
258 static_assert(doit() == 10, "");
259 
260 namespace InvalidCall {
261   struct S {
262     constexpr int a() const { // both-error {{never produces a constant expression}}
263       return 1 / 0; // both-note 2{{division by zero}} \
264                     // both-warning {{is undefined}}
265     }
266   };
267   constexpr S s;
268   static_assert(s.a() == 1, ""); // both-error {{not an integral constant expression}} \
269                                  // both-note {{in call to}}
270 
271   /// This used to cause an assertion failure in the new constant interpreter.
272   constexpr void func(); // both-note {{declared here}}
273   struct SS {
274     constexpr SS() { func(); } // both-note {{undefined function }}
275   };
276   constexpr SS ss; // both-error {{must be initialized by a constant expression}} \
277                    // both-note {{in call to 'SS()'}}
278 
279 
280   /// This should not emit a diagnostic.
281   constexpr int f();
282   constexpr int a() {
283     return f();
284   }
285   constexpr int f() {
286     return 5;
287   }
288   static_assert(a() == 5, "");
289 
290 }
291 
292 namespace CallWithArgs {
293   /// This used to call problems during checkPotentialConstantExpression() runs.
294   constexpr void g(int a) {}
295   constexpr void f() {
296     g(0);
297   }
298 }
299 
300 namespace ReturnLocalPtr {
301   constexpr int *p() {
302     int a = 12;
303     return &a; // both-warning {{address of stack memory}}
304   }
305 
306   /// FIXME: Both interpreters should diagnose this. We're returning a pointer to a local
307   /// variable.
308   static_assert(p() == nullptr, ""); // both-error {{static assertion failed}}
309 
310   constexpr const int &p2() {
311     int a = 12; // both-note {{declared here}}
312     return a; // both-warning {{reference to stack memory associated with local variable}}
313   }
314 
315   static_assert(p2() == 12, ""); // both-error {{not an integral constant expression}} \
316                                  // both-note {{read of variable whose lifetime has ended}}
317 }
318 
319 namespace VoidReturn {
320   /// ReturnStmt with an expression in a void function used to cause problems.
321   constexpr void bar() {}
322   constexpr void foo() {
323     return bar();
324   }
325   static_assert((foo(),1) == 1, "");
326 }
327 
328 namespace InvalidReclRefs {
329   void param(bool b) { // both-note {{declared here}}
330     static_assert(b, ""); // both-error {{not an integral constant expression}} \
331                           // both-note {{function parameter 'b' with unknown value}}
332     static_assert(true ? true : b, "");
333   }
334 
335 #if __cplusplus >= 202002L
336   consteval void param2(bool b) { // both-note {{declared here}}
337     static_assert(b, ""); // both-error {{not an integral constant expression}} \
338                           // both-note {{function parameter 'b' with unknown value}}
339   }
340 #endif
341 }
342 
343 namespace TemplateUndefined {
344   template<typename T> constexpr int consume(T);
345   // ok, not a constant expression.
346   const int k = consume(0);
347 
348   template<typename T> constexpr int consume(T) { return 0; }
349   // ok, constant expression.
350   constexpr int l = consume(0);
351   static_assert(l == 0, "");
352 }
353 
354 namespace PtrReturn {
355   constexpr void *a() {
356     return nullptr;
357   }
358   static_assert(a() == nullptr, "");
359 }
360 
361 namespace Variadic {
362   struct S { int a; bool b; };
363 
364   constexpr void variadic_function(int a, ...) {}
365   constexpr int f1() {
366     variadic_function(1, S{'a', false});
367     return 1;
368   }
369   static_assert(f1() == 1, "");
370 
371   constexpr int variadic_function2(...) {
372     return 12;
373   }
374   static_assert(variadic_function2() == 12, "");
375   static_assert(variadic_function2(1, 2, 3, 4, 5) == 12, "");
376   static_assert(variadic_function2(1, variadic_function2()) == 12, "");
377 
378   constexpr int (*VFP)(...) = variadic_function2;
379   static_assert(VFP() == 12, "");
380 
381   /// Member functions
382   struct Foo {
383     int a = 0;
384     constexpr void bla(...) {}
385     constexpr S bla2(...) {
386       return S{12, true};
387     }
388     constexpr Foo(...) : a(1337) {}
389     constexpr Foo(void *c, bool b, void*p, ...) : a('a' + b) {}
390     constexpr Foo(int a, const S* s, ...) : a(a) {}
391   };
392 
393   constexpr int foo2() {
394     Foo f(1, nullptr);
395     auto s = f.bla2(1, 2, S{1, false});
396     return s.a + s.b;
397   }
398   static_assert(foo2() == 13, "");
399 
400   constexpr Foo _f = 123;
401   static_assert(_f.a == 1337, "");
402 
403   constexpr Foo __f(nullptr, false, nullptr, nullptr, 'a', Foo());
404   static_assert(__f.a ==  'a', "");
405 
406 
407 #if __cplusplus >= 202002L
408 namespace VariadicVirtual {
409   class A {
410   public:
411     constexpr virtual void foo(int &a, ...) {
412       a = 1;
413     }
414   };
415 
416   class B : public A {
417   public:
418     constexpr void foo(int &a, ...) override {
419       a = 2;
420     }
421   };
422 
423   constexpr int foo() {
424     B b;
425     int a;
426     b.foo(a, 1,2,nullptr);
427     return a;
428   }
429   static_assert(foo() == 2, "");
430 } // VariadicVirtual
431 
432 namespace VariadicQualified {
433   class A {
434       public:
435       constexpr virtual int foo(...) const {
436           return 5;
437       }
438   };
439   class B : public A {};
440   class C : public B {
441       public:
442       constexpr int foo(...) const override {
443           return B::foo(1,2,3); // B doesn't have a foo(), so this should call A::foo().
444       }
445       constexpr int foo2() const {
446         return this->A::foo(1,2,3,this);
447       }
448   };
449   constexpr C c;
450   static_assert(c.foo() == 5);
451   static_assert(c.foo2() == 5);
452 } // VariadicQualified
453 #endif
454 
455 }
456 
457 namespace Packs {
458   template<typename...T>
459   constexpr int foo() { return sizeof...(T); }
460   static_assert(foo<int, char>() == 2, "");
461   static_assert(foo<>() == 0, "");
462 }
463 
464 namespace AddressOf {
465   struct S {} s;
466   static_assert(__builtin_addressof(s) == &s, "");
467 
468   struct T { constexpr T *operator&() const { return nullptr; } int n; } t;
469   constexpr T *pt = __builtin_addressof(t);
470   static_assert(&pt->n == &t.n, "");
471 
472   struct U { int n : 5; } u;
473   int *pbf = __builtin_addressof(u.n); // both-error {{address of bit-field requested}}
474 
475   S *ptmp = __builtin_addressof(S{}); // both-error {{taking the address of a temporary}} \
476                                       // both-warning {{temporary whose address is used as value of local variable 'ptmp' will be destroyed at the end of the full-expression}}
477 
478   constexpr int foo() {return 1;}
479   static_assert(__builtin_addressof(foo) == foo, "");
480 
481   constexpr _Complex float F = {3, 4}; // both-warning {{'_Complex' is a C99 extension}}
482   static_assert(__builtin_addressof(F) == &F, "");
483 
484   void testAddressof(int x) {
485     static_assert(&x == __builtin_addressof(x), "");
486   }
487 }
488 
489 namespace std {
490 template <typename T> struct remove_reference { using type = T; };
491 template <typename T> struct remove_reference<T &> { using type = T; };
492 template <typename T> struct remove_reference<T &&> { using type = T; };
493 template <typename T>
494 constexpr typename std::remove_reference<T>::type&& move(T &&t) noexcept {
495   return static_cast<typename std::remove_reference<T>::type &&>(t);
496 }
497 }
498 /// The std::move declaration above gets translated to a builtin function.
499 namespace Move {
500 #if __cplusplus >= 202002L
501   consteval int f_eval() { // both-note 12{{declared here}}
502     return 0;
503   }
504 
505   /// From test/SemaCXX/cxx2a-consteval.
506   struct Copy {
507     int(*ptr)();
508     constexpr Copy(int(*p)() = nullptr) : ptr(p) {}
509     consteval Copy(const Copy&) = default;
510   };
511 
512   constexpr const Copy &to_lvalue_ref(const Copy &&a) {
513     return a;
514   }
515 
516   void test() {
517     constexpr const Copy C;
518     // there is no the copy constructor call when its argument is a prvalue because of garanteed copy elision.
519     // so we need to test with both prvalue and xvalues.
520     { Copy c(C); }
521     { Copy c((Copy(&f_eval))); } // both-error {{cannot take address of consteval}}
522     { Copy c(std::move(C)); }
523     { Copy c(std::move(Copy(&f_eval))); } // both-error {{is not a constant expression}} \
524                                           // both-note {{to a consteval}}
525     { Copy c(to_lvalue_ref((Copy(&f_eval)))); } // both-error {{is not a constant expression}} \
526                                                 // both-note {{to a consteval}}
527     { Copy c(to_lvalue_ref(std::move(C))); }
528     { Copy c(to_lvalue_ref(std::move(Copy(&f_eval)))); } // both-error {{is not a constant expression}} \
529                                                          // both-note {{to a consteval}}
530     { Copy c = Copy(C); }
531     { Copy c = Copy(Copy(&f_eval)); } // both-error {{cannot take address of consteval}}
532     { Copy c = Copy(std::move(C)); }
533     { Copy c = Copy(std::move(Copy(&f_eval))); } // both-error {{is not a constant expression}} \
534                                                  // both-note {{to a consteval}}
535     { Copy c = Copy(to_lvalue_ref(Copy(&f_eval))); } // both-error {{is not a constant expression}} \
536                                                      // both-note {{to a consteval}}
537     { Copy c = Copy(to_lvalue_ref(std::move(C))); }
538     { Copy c = Copy(to_lvalue_ref(std::move(Copy(&f_eval)))); } // both-error {{is not a constant expression}} \
539                                                                 // both-note {{to a consteval}}
540     { Copy c; c = Copy(C); }
541     { Copy c; c = Copy(Copy(&f_eval)); } // both-error {{cannot take address of consteval}}
542     { Copy c; c = Copy(std::move(C)); }
543     { Copy c; c = Copy(std::move(Copy(&f_eval))); } // both-error {{is not a constant expression}} \
544                                                     // both-note {{to a consteval}}
545     { Copy c; c = Copy(to_lvalue_ref(Copy(&f_eval))); } // both-error {{is not a constant expression}} \
546                                                         // both-note {{to a consteval}}
547     { Copy c; c = Copy(to_lvalue_ref(std::move(C))); }
548     { Copy c; c = Copy(to_lvalue_ref(std::move(Copy(&f_eval)))); } // both-error {{is not a constant expression}} \
549                                                                    // both-note {{to a consteval}}
550   }
551 #endif
552   constexpr int A = std::move(5);
553   static_assert(A == 5, "");
554 }
555 
556 namespace StaticLocals {
557   void test() {
558     static int j; // both-note {{declared here}}
559     static_assert(&j != nullptr, ""); // both-warning {{always true}}
560 
561     static_assert(j == 0, ""); // both-error {{not an integral constant expression}} \
562                                // both-note {{read of non-const variable 'j'}}
563 
564     static int k = 0; // both-note {{declared here}}
565     static_assert(k == 0, ""); // both-error {{not an integral constant expression}} \
566                                // both-note {{read of non-const variable 'k'}}
567 
568     static const int l = 12;
569     static_assert(l == 12, "");
570 
571     static const int m; // both-error {{default initialization}}
572     static_assert(m == 0, "");
573   }
574 }
575 
576 namespace Local {
577   /// We used to run into infinite recursin here because we were
578   /// trying to evaluate t's initializer while evaluating t's initializer.
579   int a() {
580     const int t=t;
581     return t;
582   }
583 }
584 
585 namespace VariadicOperator {
586   struct Callable {
587     float& operator()(...);
588   };
589 
590   void test_callable(Callable c) {
591     float &fr = c(10);
592   }
593 }
594 
595 namespace WeakCompare {
596   [[gnu::weak]]void weak_method();
597   static_assert(weak_method != nullptr, ""); // both-error {{not an integral constant expression}} \
598                                              // both-note {{comparison against address of weak declaration '&weak_method' can only be performed at runtim}}
599 
600   constexpr auto A = &weak_method;
601   static_assert(A != nullptr, ""); // both-error {{not an integral constant expression}} \
602                                    // both-note {{comparison against address of weak declaration '&weak_method' can only be performed at runtim}}
603 }
604 
605 namespace FromIntegral {
606 #if __cplusplus >= 202002L
607   typedef double (*DoubleFn)();
608   int a[(int)DoubleFn((void*)-1)()]; // both-error {{not allowed at file scope}} \
609                                     // both-warning {{variable length arrays}}
610   int b[(int)DoubleFn((void*)(-1 + 1))()]; // both-error {{not allowed at file scope}} \
611                                            // expected-note {{evaluates to a null function pointer}} \
612                                            // both-warning {{variable length arrays}}
613 #endif
614 }
615 
616 namespace {
617   template <typename T> using id = T;
618   template <typename T>
619   constexpr void g() {
620     constexpr id<void (T)> f;
621   }
622 
623   static_assert((g<int>(), true), "");
624 }
625 
626 namespace {
627   /// The InitListExpr here is of void type.
628   void bir [[clang::annotate("B", {1, 2, 3, 4})]] (); // both-error {{'annotate' attribute requires parameter 1 to be a constant expression}} \
629                                                       // both-note {{subexpression not valid in a constant expression}}
630 }
631 
632 namespace FuncPtrParam {
633   void foo(int(&a)()) {
634     *a; // both-warning {{expression result unused}}
635   }
636 }
637 
638 namespace {
639   void f() noexcept;
640   void (&r)() = f;
641   void (&cond3)() = r;
642 }
643 
644 namespace FunctionCast {
645   // When folding, we allow functions to be cast to different types. Such
646   // cast functions cannot be called, even if they're constexpr.
647   constexpr int f() { return 1; }
648   typedef double (*DoubleFn)();
649   typedef int (*IntFn)();
650   int a[(int)DoubleFn(f)()]; // both-error {{variable length array}} \
651                              // both-warning {{are a Clang extension}}
652   int b[(int)IntFn(f)()];    // ok
653 }
654 
655 #if __cplusplus >= 202002L
656 namespace StableAddress {
657   template<unsigned N> struct str {
658     char arr[N];
659   };
660   // FIXME: Deduction guide not needed with P1816R0.
661   template<unsigned N> str(const char (&)[N]) -> str<N>;
662 
663   template<str s> constexpr int sum() {
664     int n = 0;
665     for (char c : s.arr)
666       n += c;
667     return n;
668   }
669   static_assert(sum<str{"$hello $world."}>() == 1234, "");
670 }
671 #endif
672