[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / AST / ByteCode / cxx23.cpp
blob1803fb8ab2e9a40b82b396e3ec109e2da67572b2
1 // UNSUPPORTED: target={{.*}}-zos{{.*}}
2 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref,ref20,all,all20 %s
3 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=ref,ref23,all,all23 %s
4 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all,all20 %s -fexperimental-new-constant-interpreter
5 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=expected23,all,all23 %s -fexperimental-new-constant-interpreter
7 constexpr int f(int n) { // all20-error {{constexpr function never produces a constant expression}}
8 static const int m = n; // all-note {{control flows through the definition of a static variable}} \
9 // all20-note {{control flows through the definition of a static variable}} \
10 // all20-warning {{is a C++23 extension}}
12 return m;
14 static_assert(f(0) == 0, ""); // all-error {{not an integral constant expression}} \
15 // all-note {{in call to}}
17 constexpr int g(int n) { // all20-error {{constexpr function never produces a constant expression}}
18 thread_local const int m = n; // all-note {{control flows through the definition of a thread_local variable}} \
19 // all20-note {{control flows through the definition of a thread_local variable}} \
20 // all20-warning {{is a C++23 extension}}
21 return m;
23 static_assert(g(0) == 0, ""); // all-error {{not an integral constant expression}} \
24 // all-note {{in call to}}
26 constexpr int c_thread_local(int n) { // all20-error {{constexpr function never produces a constant expression}}
27 static _Thread_local int m = 0; // all20-note 2{{control flows through the definition of a thread_local variable}} \
28 // all23-note {{control flows through the definition of a thread_local variable}} \
29 // all20-warning {{is a C++23 extension}}
30 return m;
32 static_assert(c_thread_local(0) == 0, ""); // all-error {{not an integral constant expression}} \
33 // all-note {{in call to}}
36 constexpr int gnu_thread_local(int n) { // all20-error {{constexpr function never produces a constant expression}}
37 static __thread int m = 0; // all20-note 2{{control flows through the definition of a thread_local variable}} \
38 // all23-note {{control flows through the definition of a thread_local variable}} \
39 // all20-warning {{is a C++23 extension}}
40 return m;
42 static_assert(gnu_thread_local(0) == 0, ""); // all-error {{not an integral constant expression}} \
43 // all-note {{in call to}}
45 constexpr int h(int n) { // all20-error {{constexpr function never produces a constant expression}}
46 static const int m = n; // all20-note {{control flows through the definition of a static variable}} \
47 // all20-warning {{is a C++23 extension}}
48 return &m - &m;
51 constexpr int i(int n) { // all20-error {{constexpr function never produces a constant expression}}
52 thread_local const int m = n; // all20-note {{control flows through the definition of a thread_local variable}} \
53 // all20-warning {{is a C++23 extension}}
54 return &m - &m;
57 constexpr int j(int n) {
58 if (!n)
59 return 0;
60 static const int m = n; // ref20-warning {{is a C++23 extension}} \
61 // expected20-warning {{is a C++23 extension}}
62 return m;
64 constexpr int j0 = j(0);
66 constexpr int k(int n) {
67 if (!n)
68 return 0;
69 thread_local const int m = n; // ref20-warning {{is a C++23 extension}} \
70 // expected20-warning {{is a C++23 extension}}
72 return m;
74 constexpr int k0 = k(0);
76 namespace StaticLambdas {
77 constexpr auto static_capture_constexpr() {
78 char n = 'n';
79 return [n] static { return n; }(); // expected23-error {{a static lambda cannot have any captures}} \
80 // expected20-error {{a static lambda cannot have any captures}} \
81 // expected20-warning {{are a C++23 extension}} \
82 // expected20-warning {{is a C++23 extension}} \
83 // ref23-error {{a static lambda cannot have any captures}} \
84 // ref20-error {{a static lambda cannot have any captures}} \
85 // ref20-warning {{are a C++23 extension}} \
86 // ref20-warning {{is a C++23 extension}}
88 static_assert(static_capture_constexpr()); // expected23-error {{static assertion expression is not an integral constant expression}} \
89 // expected20-error {{static assertion expression is not an integral constant expression}} \
90 // ref23-error {{static assertion expression is not an integral constant expression}} \
91 // ref20-error {{static assertion expression is not an integral constant expression}}
93 constexpr auto capture_constexpr() {
94 char n = 'n';
95 return [n] { return n; }();
97 static_assert(capture_constexpr());
100 namespace StaticOperators {
101 auto lstatic = []() static { return 3; }; // ref20-warning {{C++23 extension}} \
102 // expected20-warning {{C++23 extension}}
103 static_assert(lstatic() == 3, "");
104 constexpr int (*f2)(void) = lstatic;
105 static_assert(f2() == 3);
107 struct S1 {
108 constexpr S1() { // all20-error {{never produces a constant expression}}
109 throw; // all-note {{not valid in a constant expression}} \
110 // all20-note {{not valid in a constant expression}}
112 static constexpr int operator()() { return 3; } // ref20-warning {{C++23 extension}} \
113 // expected20-warning {{C++23 extension}}
115 static_assert(S1{}() == 3, ""); // all-error {{not an integral constant expression}} \
116 // all-note {{in call to}}
122 int test_in_lambdas() {
123 auto c = [](int n) constexpr {
124 if (n == 0)
125 return 0;
126 else
127 goto test; // all-note {{subexpression not valid in a constant expression}} \
128 // all20-warning {{use of this statement in a constexpr function is a C++23 extension}}
129 test:
130 return 1;
132 c(0);
133 constexpr auto A = c(1); // all-error {{must be initialized by a constant expression}} \
134 // all-note {{in call to}}
135 return 0;
138 /// PackIndexExpr.
139 template <auto... p>
140 struct check_ice {
141 enum e {
142 x = p...[0] // all-warning {{is a C++2c extension}}
145 static_assert(check_ice<42>::x == 42);
148 namespace VirtualBases {
149 namespace One {
150 struct U { int n; };
151 struct V : U { int n; };
152 struct A : virtual V { int n; };
153 struct Aa { int n; };
154 struct B : virtual A, Aa {};
155 struct C : virtual A, Aa {};
156 struct D : B, C {};
158 /// Calls the constructor of D.
159 D d;
162 #if __cplusplus >= 202302L
163 struct VBase {};
164 struct HasVBase : virtual VBase {}; // all23-note 1{{virtual base class declared here}}
165 struct Derived : HasVBase {
166 constexpr Derived() {} // all23-error {{constexpr constructor not allowed in struct with virtual base class}}
168 template<typename T> struct DerivedFromVBase : T {
169 constexpr DerivedFromVBase();
171 constexpr int f(DerivedFromVBase<HasVBase>) {}
172 template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {}
173 constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // all23-error {{constant expression}} \
174 // all23-note {{cannot construct object of type 'DerivedFromVBase<VirtualBases::HasVBase>' with virtual base class in a constant expression}}
175 #endif
178 namespace LabelGoto {
179 constexpr int foo() { // all20-error {{never produces a constant expression}}
180 a: // all20-warning {{use of this statement in a constexpr function is a C++23 extension}}
181 goto a; // all20-note 2{{subexpression not valid in a constant expression}} \
182 // ref23-note {{subexpression not valid in a constant expression}} \
183 // expected23-note {{subexpression not valid in a constant expression}}
185 return 1;
187 static_assert(foo() == 1, ""); // all-error {{not an integral constant expression}} \
188 // all-note {{in call to}}
191 namespace ExplicitLambdaThis {
192 constexpr auto f = [x = 3]<typename Self>(this Self self) { // all20-error {{explicit object parameters are incompatible with C++ standards before C++2b}}
193 return x;
195 static_assert(f());
198 namespace std {
199 struct strong_ordering {
200 int n;
201 constexpr operator int() const { return n; }
202 static const strong_ordering less, equal, greater;
204 constexpr strong_ordering strong_ordering::less = {-1};
205 constexpr strong_ordering strong_ordering::equal = {0};
206 constexpr strong_ordering strong_ordering::greater = {1};
209 namespace UndefinedThreeWay {
210 struct A {
211 friend constexpr std::strong_ordering operator<=>(const A&, const A&) = default; // all-note {{declared here}}
214 constexpr std::strong_ordering operator<=>(const A&, const A&) noexcept;
215 constexpr std::strong_ordering (*test_a_threeway)(const A&, const A&) = &operator<=>;
216 static_assert(!(*test_a_threeway)(A(), A())); // all-error {{static assertion expression is not an integral constant expression}} \
217 // all-note {{undefined function 'operator<=>' cannot be used in a constant expression}}
220 /// FIXME: The new interpreter is missing the "initializer of q is not a constant expression" diagnostics.a
221 /// That's because the cast from void* to int* is considered fine, but diagnosed. So we don't consider
222 /// q to be uninitialized.
223 namespace VoidCast {
224 constexpr void* p = nullptr;
225 constexpr int* q = static_cast<int*>(p); // all-error {{must be initialized by a constant expression}} \
226 // all-note {{cast from 'void *' is not allowed in a constant expression}} \
227 // ref-note {{declared here}}
228 static_assert(q == nullptr); // ref-error {{not an integral constant expression}} \
229 // ref-note {{initializer of 'q' is not a constant expression}}
232 namespace ExplicitLambdaInstancePointer {
233 struct C {
234 constexpr C(auto) { }
236 void foo() {
237 constexpr auto b = [](this C) { return 1; }; // all20-error {{explicit object parameters are incompatible with C++ standards before C++2b}}
238 constexpr int (*fp)(C) = b;
239 static_assert(fp(1) == 1, "");
243 namespace TwosComplementShifts {
244 using uint32 = __UINT32_TYPE__;
245 using int32 = __INT32_TYPE__;
246 static_assert(uint32(int32(0x1234) << 16) == 0x12340000);
247 static_assert(uint32(int32(0x1234) << 19) == 0x91a00000);
248 static_assert(uint32(int32(0x1234) << 20) == 0x23400000);
249 static_assert(uint32(int32(0x1234) << 24) == 0x34000000);
250 static_assert(uint32(int32(-1) << 31) == 0x80000000);
252 static_assert(-2 >> 1 == -1);
253 static_assert(-3 >> 1 == -2);
254 static_assert(-7 >> 1 == -4);
257 namespace AnonUnionDtor {
258 struct A {
259 A ();
260 ~A();
263 template <class T>
264 struct opt
266 union { // all20-note {{is not literal}}
267 char c;
268 T data;
271 constexpr opt() {}
273 constexpr ~opt() {
274 if (engaged)
275 data.~T();
278 bool engaged = false;
281 consteval void foo() {
282 opt<A> a; // all20-error {{variable of non-literal type}}
285 void bar() { foo(); }
288 /// FIXME: The two interpreters disagree about there to diagnose the non-constexpr destructor call.
289 namespace NonLiteralDtorInParam {
290 class NonLiteral { // all20-note {{is not an aggregate and has no constexpr constructors other than copy or move constructors}}
291 public:
292 NonLiteral() {}
293 ~NonLiteral() {} // all23-note {{declared here}}
295 constexpr int F2(NonLiteral N) { // all20-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} \
296 // ref23-note {{non-constexpr function '~NonLiteral' cannot be used in a constant expression}}
297 return 8;
301 void test() {
302 NonLiteral L;
303 constexpr auto D = F2(L); // all23-error {{must be initialized by a constant expression}} \
304 // expected23-note {{non-constexpr function '~NonLiteral' cannot be used in a constant expression}}