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