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