1 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx2a %s -fcxx-exceptions -triple=x86_64-linux-gnu -Wno-c++23-extensions 2 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx23 %s -fcxx-exceptions -triple=x86_64-linux-gnu -Wpre-c++23-compat 3 4 struct NonLiteral { // cxx2a-note {{'NonLiteral' is not literal}} \ 5 // cxx23-note 2{{'NonLiteral' is not literal}} 6 NonLiteral() {} // cxx23-note 2{{declared here}} 7 }; 8 9 struct Constexpr{}; 10 11 #if __cplusplus > 202002L 12 13 constexpr int f(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} 14 static const int m = n; // cxx2a-note {{control flows through the definition of a static variable}} \ 15 // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} 16 return m; 17 } 18 constexpr int g(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} 19 thread_local const int m = n; // cxx2a-note {{control flows through the definition of a thread_local variable}} \ 20 // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}} 21 return m; 22 } 23 24 constexpr int c_thread_local(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} 25 static _Thread_local int m = 0; // cxx2a-note {{control flows through the definition of a thread_local variable}} \ 26 // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} 27 return m; 28 } 29 30 constexpr int gnu_thread_local(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} 31 static __thread int m = 0; // cxx2a-note {{control flows through the definition of a thread_local variable}} \ 32 // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} 33 return m; 34 } 35 36 constexpr int h(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} 37 static const int m = n; // cxx2a-note {{control flows through the definition of a static variable}} \ 38 // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} 39 return &m - &m; 40 } 41 constexpr int i(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} 42 thread_local const int m = n; // cxx2a-note {{control flows through the definition of a thread_local variable}} \ 43 // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}} 44 return &m - &m; 45 } 46 47 constexpr int j(int n) { 48 if (!n) 49 return 0; 50 static const int m = n; // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} 51 return m; 52 } 53 constexpr int j0 = j(0); 54 55 constexpr int k(int n) { 56 if (!n) 57 return 0; 58 thread_local const int m = n; // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}} 59 60 return m; 61 } 62 constexpr int k0 = k(0); 63 64 constexpr int j_evaluated(int n) { 65 if (!n) 66 return 0; 67 static const int m = n; // expected-note {{control flows through the definition of a static variable}} \ 68 // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} 69 return m; 70 } 71 72 constexpr int je = j_evaluated(1); // expected-error {{constexpr variable 'je' must be initialized by a constant expression}} \ 73 // expected-note {{in call}} 74 75 constexpr int k_evaluated(int n) { 76 if (!n) 77 return 0; 78 thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \ 79 // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}} 80 81 return m; 82 } 83 84 constexpr int ke = k_evaluated(1); // expected-error {{constexpr variable 'ke' must be initialized by a constant expression}} \ 85 // expected-note {{in call}} 86 87 constexpr int static_constexpr() { 88 static constexpr int m = 42; // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} 89 static constexpr Constexpr foo; // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} 90 return m; 91 } 92 93 constexpr int thread_local_constexpr() { 94 thread_local constexpr int m = 42; // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}} 95 thread_local constexpr Constexpr foo; // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}} 96 return m; 97 } 98 99 constexpr int non_literal(bool b) { 100 if (!b) 101 return 0; 102 NonLiteral n; // cxx23-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++23}} 103 } 104 105 constexpr int non_literal_1 = non_literal(false); 106 107 namespace eval_goto { 108 109 constexpr int f(int x) { 110 if (x) { 111 return 0; 112 } else { 113 goto test; // expected-note {{subexpression not valid in a constant expression}} \ 114 // cxx23-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}} 115 } 116 test: 117 return 0; 118 } 119 120 int a = f(0); 121 constexpr int b = f(0); // expected-error {{must be initialized by a constant expression}} \ 122 // expected-note {{in call to 'f(0)'}} 123 constexpr int c = f(1); 124 125 constexpr int label() { 126 127 test: // cxx23-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}} 128 return 0; 129 } 130 131 constexpr int d = label(); 132 133 } // namespace eval_goto 134 135 #endif 136 137 // Test that explicitly constexpr lambdas behave correctly, 138 // This is to be contrasted with the test for implicitly constexpr lambdas below. 139 int test_in_lambdas() { 140 auto a = []() constexpr { 141 static const int m = 32; // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} 142 return m; 143 }; 144 145 auto b = [](int n) constexpr { 146 if (!n) 147 return 0; 148 static const int m = n; // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} 149 return m; 150 } 151 (1); 152 153 auto c = [](int n) constexpr { 154 if (!n) 155 return 0; 156 else 157 goto test; // expected-note {{subexpression not valid in a constant expression}} \ 158 // cxx23-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}} 159 test: 160 return 1; 161 }; 162 c(0); 163 constexpr auto c_error = c(1); // expected-error {{constexpr variable 'c_error' must be initialized by a constant expression}} \ 164 // expected-note {{in call to}} 165 166 auto non_literal = [](bool b) constexpr { 167 if (!b) 168 NonLiteral n; // cxx2a-error {{variable of non-literal type 'NonLiteral' cannot be defined in a constexpr function before C++23}} \ 169 // cxx23-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++23}} \ 170 // cxx23-note {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}} 171 return 0; 172 }; 173 174 #if __cplusplus > 202002L 175 constexpr auto non_literal_ko = non_literal(false); // cxx23-error {{constexpr variable 'non_literal_ko' must be initialized by a constant expression}} \ 176 // cxx23-note {{in call}} 177 178 constexpr auto non_literal_ok = non_literal(true); 179 #endif 180 } 181 182 // Test whether lambdas are correctly treated as implicitly constexpr under the 183 // relaxed C++23 rules (and similarly as not implicitly constexpr under the 184 // C++20 rules). 185 int test_lambdas_implicitly_constexpr() { 186 187 auto b = [](int n) { // cxx2a-note 2{{declared here}} 188 if (!n) 189 return 0; 190 static const int m = n; // cxx23-note {{control flows through the definition of a static variable}} 191 return m; 192 }; 193 194 auto b1 = b(1); 195 constexpr auto b2 = b(0); // cxx2a-error {{must be initialized by a constant expression}} \ 196 // cxx2a-note {{non-constexpr function}} 197 198 constexpr auto b3 = b(1); // expected-error{{constexpr variable 'b3' must be initialized by a constant expression}} \ 199 // cxx2a-note {{non-constexpr function}} \ 200 // cxx23-note {{in call}} 201 202 auto c = [](int n) { // cxx2a-note 2{{declared here}} 203 if (!n) 204 return 0; 205 else 206 goto test; // cxx23-note {{subexpression not valid in a constant expression}} 207 test: 208 return 1; 209 }; 210 c(0); 211 constexpr auto c_ok = c(0); // cxx2a-error {{must be initialized by a constant expression}} \ 212 // cxx2a-note {{non-constexpr function}} 213 214 constexpr auto c_error = c(1); // expected-error {{constexpr variable 'c_error' must be initialized by a constant expression}} \ 215 // cxx2a-note {{non-constexpr function}} \ 216 // cxx23-note {{in call to}} 217 218 auto non_literal = [](bool b) { // cxx2a-note 2{{declared here}} 219 if (b) 220 NonLiteral n; // cxx23-note {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}} 221 return 0; 222 }; 223 224 constexpr auto non_literal_ko = non_literal(true); // expected-error {{constexpr variable 'non_literal_ko' must be initialized by a constant expression}} \ 225 // cxx2a-note {{non-constexpr function}} \ 226 // cxx23-note {{in call}} 227 228 constexpr auto non_literal_ok = non_literal(false); // cxx2a-error {{must be initialized by a constant expression}} \ 229 // cxx2a-note {{non-constexpr function}} 230 } 231 232 template <typename T> 233 constexpr auto dependent_var_def_lambda() { 234 return [](bool b) { // cxx2a-note {{declared here}} 235 if (!b) 236 T t; 237 return 0; 238 }; 239 } 240 241 constexpr auto non_literal_valid_in_cxx23 = dependent_var_def_lambda<NonLiteral>()(true); // \ 242 // cxx2a-error {{constexpr variable 'non_literal_valid_in_cxx23' must be initialized by a constant expression}} \ 243 // cxx2a-note {{non-constexpr function}} 244 245 246 constexpr double evaluate_static_constexpr() { 247 struct Constexpr{ 248 constexpr double f() const { 249 return 42; 250 } 251 }; 252 thread_local constexpr Constexpr t; // cxx23-warning {{before C++23}} 253 static constexpr Constexpr s; // cxx23-warning {{before C++23}} 254 return t.f() + s.f(); 255 } 256 static_assert(evaluate_static_constexpr() == 84); 257