206 lines · cpp
1// RUN: %clang_cc1 -std=c++23 -x c++ %s -verify2// RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected3// RUN: %clang_cc1 -std=c++23 -x c++ %s -verify -fexperimental-new-constant-interpreter4// RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected -fexperimental-new-constant-interpreter5// RUN: %clang_cc1 -std=c++26 -x c++ %s -verify6// RUN: %clang_cc1 -std=c++26 -x c++ %s -verify -fexperimental-new-constant-interpreter7 8struct A{};9struct B{ explicit operator bool() { return true; } };10 11// This should be the first test case of this file.12void IsActOnFinishFullExprCalled() {13 // Do not add other test cases to this function.14 // Make sure `ActOnFinishFullExpr` is called and creates `ExprWithCleanups`15 // to avoid assertion failure.16 [[assume(B{})]]; // expected-warning {{assumption is ignored because it contains (potential) side-effects}} // ext-warning {{C++23 extension}}17}18 19template <bool cond>20void f() {21 [[assume(cond)]]; // ext-warning {{C++23 extension}}22}23 24template <bool cond>25struct S {26 void f() {27 [[assume(cond)]]; // ext-warning {{C++23 extension}}28 }29 30 template <typename T>31 constexpr bool g() {32 [[assume(cond == sizeof(T))]]; // expected-note {{assumption evaluated to false}} ext-warning {{C++23 extension}}33 return true;34 }35};36 37bool f2();38 39template <typename T>40constexpr void f3() {41 [[assume(T{})]]; // expected-error {{not contextually convertible to 'bool'}} expected-warning {{assumption is ignored because it contains (potential) side-effects}} ext-warning {{C++23 extension}}42}43 44void g(int x) {45 f<true>();46 f<false>();47 S<true>{}.f();48 S<false>{}.f();49 S<true>{}.g<char>();50 S<true>{}.g<int>();51 [[assume(f2())]]; // expected-warning {{assumption is ignored because it contains (potential) side-effects}} ext-warning {{C++23 extension}}52 53 [[assume((x = 3))]]; // expected-warning {{assumption is ignored because it contains (potential) side-effects}} // ext-warning {{C++23 extension}}54 [[assume(x++)]]; // expected-warning {{assumption is ignored because it contains (potential) side-effects}} // ext-warning {{C++23 extension}}55 [[assume(++x)]]; // expected-warning {{assumption is ignored because it contains (potential) side-effects}} // ext-warning {{C++23 extension}}56 [[assume([]{ return true; }())]]; // expected-warning {{assumption is ignored because it contains (potential) side-effects}} // ext-warning {{C++23 extension}}57 [[assume(B{})]]; // expected-warning {{assumption is ignored because it contains (potential) side-effects}} // ext-warning {{C++23 extension}}58 [[assume((1, 2))]]; // expected-warning {{has no effect}} // ext-warning {{C++23 extension}}59 60 f3<A>(); // expected-note {{in instantiation of}}61 f3<B>(); // expected-note {{in instantiation of}}62 [[assume]]; // expected-error {{takes one argument}}63 [[assume(z)]]; // expected-error {{undeclared identifier}}64 [[assume(A{})]]; // expected-error {{not contextually convertible to 'bool'}}65 [[assume(true)]] if (true) {} // expected-error {{only applies to empty statements}}66 [[assume(true)]] {} // expected-error {{only applies to empty statements}}67 [[assume(true)]] for (;false;) {} // expected-error {{only applies to empty statements}}68 [[assume(true)]] while (false) {} // expected-error {{only applies to empty statements}}69 [[assume(true)]] label:; // expected-error {{cannot be applied to a declaration}}70 [[assume(true)]] goto label; // expected-error {{only applies to empty statements}}71 72 // Also check variant spellings.73 __attribute__((__assume__(true))); // Should not issue a warning because it doesn't use the [[]] spelling.74 __attribute__((assume(true))) {}; // expected-error {{only applies to empty statements}}75 [[clang::assume(true)]] {}; // expected-error {{only applies to empty statements}}76}77 78// Check that 'x' is ODR-used here.79constexpr int h(int x) { return sizeof([=] { [[assume(x)]]; }); } // ext-warning {{C++23 extension}}80static_assert(h(4) == sizeof(int));81 82static_assert(__has_cpp_attribute(assume) == 202207L);83static_assert(__has_attribute(assume));84 85constexpr bool i() { // ext-error {{never produces a constant expression}}86 [[assume(false)]]; // ext-note {{assumption evaluated to false}} expected-note {{assumption evaluated to false}} ext-warning {{C++23 extension}}87 return true;88}89 90constexpr bool j(bool b) {91 [[assume(b)]]; // expected-note {{assumption evaluated to false}} ext-warning {{C++23 extension}}92 return true;93}94 95static_assert(i()); // expected-error {{not an integral constant expression}} expected-note {{in call to}}96static_assert(j(true));97static_assert(j(false)); // expected-error {{not an integral constant expression}} expected-note {{in call to}}98static_assert(S<true>{}.g<char>());99static_assert(S<false>{}.g<A>()); // expected-error {{not an integral constant expression}} expected-note {{in call to}}100 101 102template <typename T>103constexpr bool f4() {104 [[assume(!T{})]]; // expected-error {{invalid argument type 'D'}} // expected-warning 2 {{assumption is ignored because it contains (potential) side-effects}} ext-warning {{C++23 extension}}105 return sizeof(T) == sizeof(int);106}107 108template <typename T>109concept C = f4<T>(); // expected-note 3 {{in instantiation of}}110 // expected-note@-1 3 {{while substituting}}111 // expected-error@-2 {{resulted in a non-constant expression}}112 // expected-note@-3 {{because substituted constraint expression is ill-formed: substitution into constraint expression resulted in a non-constant expression}}113 114struct D {115 int x;116};117 118struct E {119 int x;120 constexpr explicit operator bool() { return false; }121};122 123struct F {124 int x;125 int y;126 constexpr explicit operator bool() { return false; }127};128 129template <typename T>130constexpr int f5() requires C<T> { return 1; } // expected-note {{while checking the satisfaction}}131 // expected-note@-1 {{candidate template ignored}}132 133template <typename T>134constexpr int f5() requires (!C<T>) { return 2; } // expected-note 3 {{while checking the satisfaction}} \135 // expected-note 3 {{while substituting template arguments}} \136 // expected-note {{candidate template ignored}}137 138static_assert(f5<int>() == 1);139static_assert(f5<D>() == 1); // expected-note 2 {{while checking constraint satisfaction}}140 // expected-note@-1 2 {{while substituting deduced template arguments}}141 // expected-error@-2 {{no matching function for call}}142 143static_assert(f5<double>() == 2);144static_assert(f5<E>() == 1); // expected-note {{while checking constraint satisfaction}} expected-note {{while substituting deduced template arguments}}145static_assert(f5<F>() == 2); // expected-note {{while checking constraint satisfaction}} expected-note {{while substituting deduced template arguments}}146 147// Do not validate assumptions whose evaluation would have side-effects.148constexpr int foo() {149 int a = 0;150 [[assume(a++)]] [[assume(++a)]]; // expected-warning 2 {{assumption is ignored because it contains (potential) side-effects}} ext-warning 2 {{C++23 extension}}151 [[assume((a+=1))]]; // expected-warning {{assumption is ignored because it contains (potential) side-effects}} ext-warning {{C++23 extension}}152 return a;153}154 155static_assert(foo() == 0);156 157template <bool ...val>158void f() {159 [[assume(val)]]; // expected-error {{expression contains unexpanded parameter pack}}160}161 162namespace gh71858 {163int164foo (int x, int y)165{166 __attribute__((assume(x == 42)));167 __attribute__((assume(++y == 43))); // expected-warning {{assumption is ignored because it contains (potential) side-effects}}168 return x + y;169}170}171 172// Do not crash when assumptions are unreachable.173namespace gh106898 {174int foo () {175 while(1);176 int a = 0, b = 1;177 __attribute__((assume (a < b)));178}179}180 181namespace GH114787 {182 183// FIXME: Correct the C++26 value184#if __cplusplus >= 202400L185 186constexpr int test(auto... xs) {187 // FIXME: Investigate why addresses of PackIndexingExprs are printed for the next188 // 'in call to' note.189 return [&]<int I>() { // expected-note {{in call to}}190 [[assume(191 xs...[I] == 2192 )]];193 [[assume(194 xs...[I + 1] == 0 // expected-note {{assumption evaluated to false}}195 )]];196 return xs...[I];197 }.template operator()<1>();198}199 200static_assert(test(1, 2, 3, 5, 6) == 2); // expected-error {{not an integral constant expression}} \201 // expected-note {{in call to}}202 203#endif204 205} // namespace GH114787206