[clang-cl] Ignore /Wv and /Wv:17 flags
[llvm-project.git] / clang / test / Analysis / more-dtors-cfg-output.cpp
blob21824506c73c89a182314a9d952c89d076ff1dec
1 // RUN: rm -f %t.14 %t.2a
2 // RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -std=c++14 -DCXX2A=0 -fblocks -Wall -Wno-unused -Werror %s > %t.14 2>&1
3 // RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -std=c++2a -DCXX2A=1 -fblocks -Wall -Wno-unused -Werror %s > %t.2a 2>&1
4 // RUN: FileCheck --input-file=%t.14 -check-prefixes=CHECK,CXX14 -implicit-check-not=destructor %s
5 // RUN: FileCheck --input-file=%t.2a -check-prefixes=CHECK,CXX2A -implicit-check-not=destructor %s
7 int puts(const char *);
9 struct Foo {
10 Foo() = delete;
11 #if CXX2A
12 // Guarantee that the elided examples are actually elided by deleting the
13 // copy constructor.
14 Foo(const Foo &) = delete;
15 #else
16 // No elision support, so we need a copy constructor.
17 Foo(const Foo &);
18 #endif
19 ~Foo();
22 struct TwoFoos {
23 Foo foo1, foo2;
24 ~TwoFoos();
27 Foo get_foo();
29 struct Bar {
30 Bar();
31 Bar(const Bar &);
32 ~Bar();
33 Bar &operator=(const Bar &);
36 Bar get_bar();
38 struct TwoBars {
39 Bar foo1, foo2;
40 ~TwoBars();
43 // Start of tests:
45 void elided_assign() {
46 Foo x = get_foo();
48 // CHECK: void elided_assign()
49 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
50 // CXX14: ~Foo() (Temporary object destructor)
51 // CHECK: ~Foo() (Implicit destructor)
53 void nonelided_assign() {
54 Bar x = (const Bar &)get_bar();
56 // CHECK: void nonelided_assign()
57 // CHECK: (CXXConstructExpr{{.*}}, struct Bar)
58 // CHECK: ~Bar() (Temporary object destructor)
59 // CHECK: ~Bar() (Implicit destructor)
61 void elided_paren_init() {
62 Foo x(get_foo());
64 // CHECK: void elided_paren_init()
65 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
66 // CXX14: ~Foo() (Temporary object destructor)
67 // CHECK: ~Foo() (Implicit destructor)
69 void nonelided_paren_init() {
70 Bar x((const Bar &)get_bar());
72 // CHECK: void nonelided_paren_init()
73 // CHECK: (CXXConstructExpr{{.*}}, struct Bar)
74 // CHECK: ~Bar() (Temporary object destructor)
75 // CHECK: ~Bar() (Implicit destructor)
77 void elided_brace_init() {
78 Foo x{get_foo()};
80 // CHECK: void elided_brace_init()
81 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
82 // CXX14: ~Foo() (Temporary object destructor)
83 // CHECK: ~Foo() (Implicit destructor)
85 void nonelided_brace_init() {
86 Bar x{(const Bar &)get_bar()};
88 // CHECK: void nonelided_brace_init()
89 // CHECK: (CXXConstructExpr{{.*}}, struct Bar)
90 // CHECK: ~Bar() (Temporary object destructor)
91 // CHECK: ~Bar() (Implicit destructor)
93 void elided_lambda_capture_init() {
94 // The copy from get_foo() into the lambda should be elided. Should call
95 // the lambda's destructor, but not ~Foo() separately.
96 // (This syntax is C++14 'generalized lambda captures'.)
97 auto z = [x=get_foo()]() {};
99 // CHECK: void elided_lambda_capture_init()
100 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
101 // CXX14: ~(lambda at {{.*}})() (Temporary object destructor)
102 // CXX14: ~Foo() (Temporary object destructor)
103 // CHECK: ~(lambda at {{.*}})() (Implicit destructor)
105 void nonelided_lambda_capture_init() {
106 // Should call the lambda's destructor as well as ~Bar() for the temporary.
107 auto z = [x((const Bar &)get_bar())]() {};
109 // CHECK: void nonelided_lambda_capture_init()
110 // CHECK: (CXXConstructExpr{{.*}}, struct Bar)
111 // CXX14: ~(lambda at {{.*}})() (Temporary object destructor)
112 // CHECK: ~Bar() (Temporary object destructor)
113 // CHECK: ~(lambda at {{.*}})() (Implicit destructor)
115 Foo elided_return_stmt_expr() {
116 // Two copies, both elided in C++17.
117 return ({ get_foo(); });
119 // CHECK: Foo elided_return_stmt_expr()
120 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
121 // CXX14: ~Foo() (Temporary object destructor)
122 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
123 // CXX14: ~Foo() (Temporary object destructor)
125 void elided_stmt_expr() {
126 // One copy, elided in C++17.
127 ({ get_foo(); });
129 // CHECK: void elided_stmt_expr()
130 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
131 // CXX14: ~Foo() (Temporary object destructor)
132 // CHECK: ~Foo() (Temporary object destructor)
135 void elided_stmt_expr_multiple_stmts() {
136 // Make sure that only the value returned out of a statement expression is
137 // elided.
138 ({ get_bar(); get_foo(); });
140 // CHECK: void elided_stmt_expr_multiple_stmts()
141 // CHECK: ~Bar() (Temporary object destructor)
142 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
143 // CXX14: ~Foo() (Temporary object destructor)
144 // CHECK: ~Foo() (Temporary object destructor)
147 void unelided_stmt_expr() {
148 ({ (const Bar &)get_bar(); });
150 // CHECK: void unelided_stmt_expr()
151 // CHECK: (CXXConstructExpr{{.*}}, struct Bar)
152 // CHECK: ~Bar() (Temporary object destructor)
153 // CHECK: ~Bar() (Temporary object destructor)
155 void elided_aggregate_init() {
156 TwoFoos x{get_foo(), get_foo()};
158 // CHECK: void elided_aggregate_init()
159 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
160 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
161 // CXX14: ~Foo() (Temporary object destructor)
162 // CXX14: ~Foo() (Temporary object destructor)
163 // CHECK: ~TwoFoos() (Implicit destructor)
165 void nonelided_aggregate_init() {
166 TwoBars x{(const Bar &)get_bar(), (const Bar &)get_bar()};
168 // CHECK: void nonelided_aggregate_init()
169 // CHECK: (CXXConstructExpr{{.*}}, struct Bar)
170 // CHECK: (CXXConstructExpr{{.*}}, struct Bar)
171 // CHECK: ~Bar() (Temporary object destructor)
172 // CHECK: ~Bar() (Temporary object destructor)
173 // CHECK: ~TwoBars() (Implicit destructor)
175 TwoFoos return_aggregate_init() {
176 return TwoFoos{get_foo(), get_foo()};
178 // CHECK: TwoFoos return_aggregate_init()
179 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
180 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
181 // CXX14: ~TwoFoos() (Temporary object destructor)
182 // CXX14: ~Foo() (Temporary object destructor)
183 // CXX14: ~Foo() (Temporary object destructor)
185 void lifetime_extended() {
186 const Foo &x = (get_foo(), get_foo());
187 puts("one destroyed before, one destroyed after");
189 // CHECK: void lifetime_extended()
190 // CHECK: ~Foo() (Temporary object destructor)
191 // CHECK: one destroyed before, one destroyed after
192 // CHECK: ~Foo() (Implicit destructor)
194 void not_lifetime_extended() {
195 Foo x = (get_foo(), get_foo());
196 puts("one destroyed before, one destroyed after");
198 // CHECK: void not_lifetime_extended()
199 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
200 // CHECK: ~Foo() (Temporary object destructor)
201 // CXX14: ~Foo() (Temporary object destructor)
202 // CHECK: one destroyed before, one destroyed after
203 // CHECK: ~Foo() (Implicit destructor)
205 void compound_literal() {
206 (void)(Bar[]){{}, {}};
208 // CHECK: void compound_literal()
209 // CHECK: (CXXConstructExpr, struct Bar)
210 // CHECK: (CXXConstructExpr, struct Bar)
211 // CHECK: ~Bar[2]() (Temporary object destructor)
213 Foo elided_return() {
214 return get_foo();
216 // CHECK: Foo elided_return()
217 // CXX14: (CXXConstructExpr{{.*}}, struct Foo)
218 // CXX14: ~Foo() (Temporary object destructor)
220 auto elided_return_lambda() {
221 return [x=get_foo()]() {};
223 // CHECK: (lambda at {{.*}}) elided_return_lambda()
224 // CXX14: (CXXConstructExpr{{.*}}, class (lambda at {{.*}}))
225 // CXX14: ~(lambda at {{.*}})() (Temporary object destructor)
226 // CXX14: ~Foo() (Temporary object destructor)
228 void const_auto_obj() {
229 const Bar bar;
231 // CHECK: void const_auto_obj()
232 // CHECK: .~Bar() (Implicit destructor)
234 void has_default_arg(Foo foo = get_foo());
235 void test_default_arg() {
236 // FIXME: This emits a destructor but no constructor. Search CFG.cpp for
237 // 'PR13385' for details.
238 has_default_arg();
240 // CHECK: void test_default_arg()
241 // CXX14: ~Foo() (Temporary object destructor)
242 // CHECK: ~Foo() (Temporary object destructor)
244 struct DefaultArgInCtor {
245 DefaultArgInCtor(Foo foo = get_foo());
246 ~DefaultArgInCtor();
249 void default_ctor_with_default_arg() {
250 // FIXME: Default arguments are mishandled in two ways:
251 // - The constructor is not emitted at all (not specific to arrays; see fixme
252 // in CFG.cpp that mentions PR13385).
253 // - The destructor is emitted once, even though the default argument will be
254 // constructed and destructed once per array element.
255 // Ideally, the CFG would expand array constructions into a loop that
256 // constructs each array element, allowing default argument
257 // constructor/destructor calls to be correctly placed inside the loop.
258 DefaultArgInCtor qux[3];
260 // CHECK: void default_ctor_with_default_arg()
261 // CHECK: CXXConstructExpr, {{.*}}, struct DefaultArgInCtor[3]
262 // CXX14: ~Foo() (Temporary object destructor)
263 // CHECK: ~Foo() (Temporary object destructor)
264 // CHECK: .~DefaultArgInCtor[3]() (Implicit destructor)
266 void new_default_ctor_with_default_arg(long count) {
267 // Same problems as above.
268 new DefaultArgInCtor[count];
270 // CHECK: void new_default_ctor_with_default_arg(long count)
271 // CHECK: CXXConstructExpr, {{.*}}, struct DefaultArgInCtor[]
272 // CXX14: ~Foo() (Temporary object destructor)
273 // CHECK: ~Foo() (Temporary object destructor)
275 #if CXX2A
276 // Boilerplate needed to test co_return:
278 namespace std {
279 template <typename Promise>
280 struct coroutine_handle {
281 static coroutine_handle from_address(void *) noexcept;
283 } // namespace std
285 struct TestPromise {
286 TestPromise initial_suspend();
287 TestPromise final_suspend() noexcept;
288 bool await_ready() noexcept;
289 void await_suspend(const std::coroutine_handle<TestPromise> &) noexcept;
290 void await_resume() noexcept;
291 Foo return_value(const Bar &);
292 Bar get_return_object();
293 void unhandled_exception();
296 namespace std {
297 template <typename Ret, typename... Args>
298 struct coroutine_traits;
299 template <>
300 struct coroutine_traits<Bar> {
301 using promise_type = TestPromise;
303 } // namespace std
305 Bar coreturn() {
306 co_return get_bar();
307 // This expands to something like:
308 // promise.return_value(get_bar());
309 // get_bar() is passed by reference to return_value() and is then destroyed;
310 // there is no equivalent of RVO. TestPromise::return_value also returns a
311 // Foo, which should be immediately destroyed.
312 // FIXME: The generated CFG completely ignores get_return_object().
314 // CXX2A: Bar coreturn()
315 // CXX2A: ~Foo() (Temporary object destructor)
316 // CXX2A: ~Bar() (Temporary object destructor)
317 #endif