257 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx2a %s -fcxx-exceptions -triple=x86_64-linux-gnu -Wno-c++23-extensions2// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx23 %s -fcxx-exceptions -triple=x86_64-linux-gnu -Wpre-c++23-compat3 4struct NonLiteral { // cxx2a-note {{'NonLiteral' is not literal}} \5 // cxx23-note 2{{'NonLiteral' is not literal}}6 NonLiteral() {} // cxx23-note 2{{declared here}}7};8 9struct Constexpr{};10 11#if __cplusplus > 202002L12 13constexpr 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}18constexpr 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 24constexpr 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 30constexpr 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 36constexpr 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}41constexpr 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 47constexpr 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}53constexpr int j0 = j(0);54 55constexpr 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}62constexpr int k0 = k(0);63 64constexpr 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 72constexpr int je = j_evaluated(1); // expected-error {{constexpr variable 'je' must be initialized by a constant expression}} \73 // expected-note {{in call}}74 75constexpr 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 84constexpr int ke = k_evaluated(1); // expected-error {{constexpr variable 'ke' must be initialized by a constant expression}} \85 // expected-note {{in call}}86 87constexpr 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 93constexpr 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 99constexpr 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 105constexpr int non_literal_1 = non_literal(false);106 107namespace eval_goto {108 109constexpr 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 }116test:117 return 0;118}119 120int a = f(0);121constexpr int b = f(0); // expected-error {{must be initialized by a constant expression}} \122 // expected-note {{in call to 'f(0)'}}123constexpr int c = f(1);124 125constexpr int label() {126 127test: // cxx23-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}}128 return 0;129}130 131constexpr int d = label();132 133} // namespace eval_goto134 135#endif136 137// Test that explicitly constexpr lambdas behave correctly,138// This is to be contrasted with the test for implicitly constexpr lambdas below.139int 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 else157 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 > 202002L175 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#endif180}181 182// Test whether lambdas are correctly treated as implicitly constexpr under the183// relaxed C++23 rules (and similarly as not implicitly constexpr under the184// C++20 rules).185int 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 else206 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 232template <typename T>233constexpr 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 241constexpr 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 246constexpr 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}256static_assert(evaluate_static_constexpr() == 84);257