blob: 51a5c3ba6044ddd241618fe10bf50763b2f3a7fc [file] [log] [blame]
Martin Brænne9a5be6e2023-04-11 10:22:06 -07001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5// Tests for function calls.
6
Googler7f19b2b2023-05-01 09:44:57 -07007#include "nullability/test/check_diagnostics.h"
Martin Brænne9a5be6e2023-04-11 10:22:06 -07008#include "third_party/llvm/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h"
9
Sam McCall4f6be422023-06-27 02:51:22 -070010namespace clang::tidy::nullability {
Martin Brænne9a5be6e2023-04-11 10:22:06 -070011namespace {
12
13TEST(PointerNullabilityTest, CallExprWithPointerReturnType) {
14 // free function
15 EXPECT_TRUE(checkDiagnostics(R"cc(
16 int *_Nonnull makeNonnull();
17 int *_Nullable makeNullable();
18 int *makeUnannotated();
19 void target() {
20 *makeNonnull();
21 *makeNullable(); // [[unsafe]]
22 *makeUnannotated();
23 }
24 )cc"));
25
26 // member function
27 EXPECT_TRUE(checkDiagnostics(R"cc(
28 struct Foo {
29 int *_Nonnull makeNonnull();
30 int *_Nullable makeNullable();
31 int *makeUnannotated();
32 };
33 void target(Foo foo) {
34 *foo.makeNonnull();
35 *foo.makeNullable(); // [[unsafe]]
36 *foo.makeUnannotated();
37 }
38 )cc"));
39
Martin Brænne9a5be6e2023-04-11 10:22:06 -070040 // function pointer
41 EXPECT_TRUE(checkDiagnostics(R"cc(
Sam McCall7d9afee2023-06-27 01:43:24 -070042 void target(int *_Nonnull (*makeNonnull)(),
43 int *_Nullable (*makeNullable)(), int *(*makeUnannotated)()) {
Martin Brænne9a5be6e2023-04-11 10:22:06 -070044 *makeNonnull();
45 *makeNullable(); // [[unsafe]]
46 *makeUnannotated();
47 }
48 )cc"));
49
50 // pointer to function pointer
51 EXPECT_TRUE(checkDiagnostics(R"cc(
Sam McCall7d9afee2023-06-27 01:43:24 -070052 void target(int *_Nonnull (**makeNonnull)(),
53 int *_Nullable (**makeNullable)(), int *(**makeUnannotated)()) {
Martin Brænne9a5be6e2023-04-11 10:22:06 -070054 *(*makeNonnull)();
55 *(*makeNullable)(); // [[unsafe]]
56 *(*makeUnannotated)();
57 }
58 )cc"));
59
60 // function returning a function pointer which returns a pointer
61 EXPECT_TRUE(checkDiagnostics(R"cc(
Sam McCall7d9afee2023-06-27 01:43:24 -070062 typedef int *_Nonnull (*MakeNonnullT)();
63 typedef int *_Nullable (*MakeNullableT)();
64 typedef int *(*MakeUnannotatedT)();
Martin Brænne9a5be6e2023-04-11 10:22:06 -070065 void target(MakeNonnullT (*makeNonnull)(), MakeNullableT (*makeNullable)(),
66 MakeUnannotatedT (*makeUnannotated)()) {
67 *(*makeNonnull)()();
68 *(*makeNullable)()(); // [[unsafe]]
69 *(*makeUnannotated)()();
70 }
71 )cc"));
72
73 // free function returns reference to pointer
74 EXPECT_TRUE(checkDiagnostics(R"cc(
75 int *_Nonnull &makeNonnull();
76 int *_Nullable &makeNullable();
77 int *&makeUnannotated();
78 void target() {
79 *makeNonnull();
80 *makeNullable(); // [[unsafe]]
81 *makeUnannotated();
Martin Brænne0da58852023-05-23 06:43:57 -070082
83 // Check that we can take the address of the returned reference and still
84 // see the correct nullability "behind" the resulting pointer.
85 __assert_nullability<NK_nonnull, NK_nonnull>(&makeNonnull());
86 __assert_nullability<NK_nonnull, NK_nullable>(&makeNullable());
87 __assert_nullability<NK_nonnull, NK_unspecified>(&makeUnannotated());
Martin Brænne9a5be6e2023-04-11 10:22:06 -070088 }
89 )cc"));
90
91 // function called in loop
92 EXPECT_TRUE(checkDiagnostics(R"cc(
93 int *_Nullable makeNullable();
94 bool makeBool();
95 void target() {
96 bool first = true;
97 while (true) {
98 int *x = makeNullable();
99 if (first && x == nullptr) return;
100 first = false;
101 *x; // [[unsafe]]
102 }
103 }
104 )cc"));
105}
106
Googler2d6527a2023-09-06 17:19:14 -0700107TEST(PointerNullabilityTest, OutputParameterBasic) {
108 EXPECT_TRUE(checkDiagnostics(R"cc(
109 void maybeModifyPtr(int** p);
110 void target() {
111 int* p = nullptr;
112 maybeModifyPtr(&p);
113 *p;
114 }
115 )cc"));
116}
117
118TEST(PointerNullabilityTest, OutputParameterReference) {
119 EXPECT_TRUE(checkDiagnostics(R"cc(
120 void maybeModifyPtr(int*& r);
121 void target() {
122 int* p = nullptr;
123 maybeModifyPtr(p);
124 *p;
125 }
126 )cc"));
127}
128
129TEST(PointerNullabilityTest, OutputParameterReferenceConst) {
130 EXPECT_TRUE(checkDiagnostics(R"cc(
131 void pointerNotModified(int* const& r);
132 void target() {
133 int* p = nullptr;
134 pointerNotModified(p);
135 *p; // [[unsafe]]
136 }
137 )cc"));
138}
139
140TEST(PointerNullabilityTest, OutputParameterReferencePointerToPointer) {
141 EXPECT_TRUE(checkDiagnostics(R"cc(
142 void maybeModifyPtr(int**& r);
143 void target() {
144 int** pp = nullptr;
145 maybeModifyPtr(pp);
146 *pp;
147 **pp;
148 }
149 )cc"));
150}
151
152TEST(PointerNullabilityTest, OutputParameterConst) {
153 EXPECT_TRUE(checkDiagnostics(R"cc(
154 void pointerNotModified(int* const* p);
155 void target(int* _Nullable p) {
156 pointerNotModified(&p);
157 *p; // [[unsafe]]
158 }
159 )cc"));
160
161 // The only const qualifier that should be considered is on the inner
162 // pointer, otherwise this pattern should be considered safe.
163 EXPECT_TRUE(checkDiagnostics(R"cc(
164 void maybeModifyPtr(const int** const p);
165 void target() {
166 const int* p = nullptr;
167 maybeModifyPtr(&p);
168 *p;
169 }
170 )cc"));
171}
172
173TEST(PointerNullabilityTest, OutputParameterNonnull) {
174 EXPECT_TRUE(checkDiagnostics(R"cc(
175 void pointerNotModified(int* _Nonnull* p);
176 void target(int* _Nonnull p) {
177 pointerNotModified(&p);
178 *p;
179 }
180 )cc"));
181}
182
183TEST(PointerNullabilityTest, OutputParameterCheckedNullable) {
184 EXPECT_TRUE(checkDiagnostics(R"cc(
185 void maybeModify(int* _Nullable* p);
186 void target(int* _Nullable p) {
187 if (!p) return;
188 maybeModify(&p);
189 *p; // false negative: this dereference is actually unsafe!
190 }
191 )cc"));
192}
193
194TEST(PointerNullabilityTest, OutputParameterNullable) {
195 EXPECT_TRUE(checkDiagnostics(R"cc(
196 void maybeModifyPtr(int* _Nullable* p);
197 void target() {
198 int* p = nullptr;
199 maybeModifyPtr(&p);
200 *p; // [[unsafe]]
201 }
202 )cc"));
203}
204
205TEST(PointerNullabilityTest, OutputParameterConditional) {
206 // This tests that flow sensitivity is preserved, to catch for example if the
207 // underlying pointer was always set to Nonnull once it's passed as an
208 // output parameter.
209 EXPECT_TRUE(checkDiagnostics(R"cc(
210 void maybeModifyPtr(int** p);
211 void target(int* _Nullable j, bool b) {
212 if (b) {
213 maybeModifyPtr(&j);
214 }
215 if (b) {
216 *j;
217 }
218 if (!b) {
219 *j; // [[unsafe]]
220 }
221 }
222 )cc"));
223}
224
225TEST(PointerNullabilityTest, OutputParameterWithoutAmpersandOperator) {
226 // This tests that the call to maybeModifyPtr works as expected if the param
227 // passed in doesn't directly use the & operator
228 EXPECT_TRUE(checkDiagnostics(R"cc(
229 void maybeModifyPtr(int** p);
230 void target(int* _Nullable p) {
231 auto pp = &p;
232 maybeModifyPtr(pp);
233 *p;
234 }
235 )cc"));
236}
237
238TEST(PointerNullabilityTest, OutputParameterTemplate) {
239 EXPECT_TRUE(checkDiagnostics(R"cc(
240 template <typename T>
241 struct S {
242 void maybeModify(T& ref);
243 };
244 void target(S<int*> s, int* _Nullable p) {
245 s.maybeModify(p);
246 *p;
247 }
248 )cc"));
Dmitri Gribenko497e36b2023-09-08 10:21:28 -0700249
250 EXPECT_TRUE(checkDiagnostics(R"cc(
251 template <typename T>
252 struct S {
253 void maybeModify(T& ref);
254 };
255 void target(S<int* _Nullable> s, int* _Nullable p) {
256 s.maybeModify(p);
257 *p; // false negative
258 }
259 )cc"));
260
261 EXPECT_TRUE(checkDiagnostics(R"cc(
262 template <typename T>
263 struct S {
264 void maybeModify(T& ref);
265 };
266 void target(S<int* _Nonnull> s, int* _Nonnull p) {
267 s.maybeModify(p);
268 *p;
269 }
270 )cc"));
Googler2d6527a2023-09-06 17:19:14 -0700271}
272
Martin Brænnefc424b72023-04-12 00:28:31 -0700273TEST(PointerNullabilityTest, CallExprParamAssignment) {
274 // free function with single param
275 EXPECT_TRUE(checkDiagnostics(R"cc(
276 void takeNonnull(int *_Nonnull);
277 void takeNullable(int *_Nullable);
278 void takeUnannotated(int *);
279 void target(int *_Nonnull ptr_nonnull, int *_Nullable ptr_nullable,
280 int *ptr_unannotated) {
281 takeNonnull(nullptr); // [[unsafe]]
282 takeNonnull(ptr_nonnull);
283 takeNonnull(ptr_nullable); // [[unsafe]]
284 takeNonnull(ptr_unannotated);
285
286 takeNullable(nullptr);
287 takeNullable(ptr_nonnull);
288 takeNullable(ptr_nullable);
289 takeNullable(ptr_unannotated);
290
291 takeUnannotated(nullptr);
292 takeUnannotated(ptr_nonnull);
293 takeUnannotated(ptr_nullable);
294 takeUnannotated(ptr_unannotated);
295 }
296 )cc"));
297
Martin Brænnefc424b72023-04-12 00:28:31 -0700298 // free function with multiple params of mixed nullability
299 EXPECT_TRUE(checkDiagnostics(R"cc(
300 void takeMixed(int *, int *_Nullable, int *_Nonnull);
301 void target() {
302 takeMixed(nullptr, nullptr, nullptr); // [[unsafe]]
303 }
304 )cc"));
305
Martin Brænnefc424b72023-04-12 00:28:31 -0700306 // member function
307 EXPECT_TRUE(checkDiagnostics(R"cc(
308 struct Foo {
309 void takeNonnull(int *_Nonnull);
310 void takeNullable(int *_Nullable);
311 void takeUnannotated(int *);
312 };
313 void target(Foo foo) {
314 foo.takeNonnull(nullptr); // [[unsafe]]
315 foo.takeNullable(nullptr);
316 foo.takeUnannotated(nullptr);
317 }
318 )cc"));
319
320 // function pointer
321 EXPECT_TRUE(checkDiagnostics(R"cc(
322 void target(void (*takeNonnull)(int *_Nonnull),
323 void (*takeNullable)(int *_Nullable),
324 void (*takeUnannotated)(int *)) {
325 takeNonnull(nullptr); // [[unsafe]]
326 takeNullable(nullptr);
327 takeUnannotated(nullptr);
328 }
329 )cc"));
330
331 // pointer to function pointer
332 //
333 // TODO(b/233582219): Fix false negative. Implement support for retrieving
334 // parameter types from a pointer to function pointer.
335 EXPECT_TRUE(checkDiagnostics(R"cc(
336 void target(void (**takeNonnull)(int *_Nonnull),
337 void (**takeNullable)(int *_Nullable),
338 void (**takeUnannotated)(int *)) {
339 (*takeNonnull)(nullptr); // false-negative
340 (*takeNullable)(nullptr);
341 (*takeUnannotated)(nullptr);
342 }
343 )cc"));
344
345 // function returned from function
346 //
347 // TODO(b/233582219): Fix false negative. Implement support for retrieving
348 // parameter types for functions returned by another function.
349 EXPECT_TRUE(checkDiagnostics(R"cc(
350 typedef void (*takeNonnullF)(int *_Nonnull);
351 typedef void (*takeNullableF)(int *_Nullable);
352 typedef void (*takeUnannotatedF)(int *);
353 void target(takeNonnullF (*takeNonnull)(), takeNullableF (*takeNullable)(),
354 takeUnannotatedF (*takeUnannotated)()) {
355 (*takeNonnull)()(nullptr); // false-negative
356 (*takeNullable)()(nullptr);
357 (*takeUnannotated)()(nullptr);
358 }
359 )cc"));
360
361 // passing a reference to a nonnull pointer
362 //
363 // TODO(b/233582219): Fix false negative. When the nonnull pointer is passed
364 // by reference into the callee which takes a nullable parameter, its value
365 // may be changed to null, making it unsafe to dereference when we return from
366 // the function call. Some possible approaches for handling this case:
367 // (1) Disallow passing a nonnull pointer as a nullable reference - and warn
368 // at the function call.
369 // (2) Assume in worst case the nonnull pointer becomes nullable after the
370 // call - and warn at the dereference.
371 // (3) Sacrifice soundness for reduction in noise, and skip the warning.
372 EXPECT_TRUE(checkDiagnostics(R"cc(
373 void takeNonnullRef(int *_Nonnull &);
374 void takeNullableRef(int *_Nullable &);
375 void takeUnannotatedRef(int *&);
376 void target(int *_Nonnull ptr_nonnull) {
377 takeNonnullRef(ptr_nonnull);
378 *ptr_nonnull;
379
380 // false-negative
381 takeNullableRef(ptr_nonnull);
382 *ptr_nonnull;
383
384 takeUnannotatedRef(ptr_nonnull);
385 *ptr_nonnull;
386 }
387 )cc"));
388
389 // passing a reference to a nullable pointer
390 EXPECT_TRUE(checkDiagnostics(R"cc(
391 void takeNonnullRef(int *_Nonnull &);
392 void takeNullableRef(int *_Nullable &);
393 void takeUnannotatedRef(int *&);
394 void target(int *_Nullable ptr_nullable) {
395 takeNonnullRef(ptr_nullable); // [[unsafe]]
396 *ptr_nullable; // [[unsafe]]
397
398 takeNullableRef(ptr_nullable);
399 *ptr_nullable; // [[unsafe]]
400
401 takeUnannotatedRef(ptr_nullable);
Googler2d6527a2023-09-06 17:19:14 -0700402 *ptr_nullable;
Martin Brænnefc424b72023-04-12 00:28:31 -0700403 }
404 )cc"));
405
406 // passing a reference to an unannotated pointer
407 //
408 // TODO(b/233582219): Fix false negative. The unannotated pointer should be
409 // considered nullable if it has been used as a nullable pointer.
410 EXPECT_TRUE(checkDiagnostics(R"cc(
411 void takeNonnullRef(int *_Nonnull &);
412 void takeNullableRef(int *_Nullable &);
413 void takeUnannotatedRef(int *&);
414 void target(int *ptr_unannotated) {
415 takeNonnullRef(ptr_unannotated);
416 *ptr_unannotated;
417
418 takeNullableRef(ptr_unannotated);
419 *ptr_unannotated; // false-negative
420
421 takeUnannotatedRef(ptr_unannotated);
422 *ptr_unannotated;
423 }
424 )cc"));
425}
426
Googler3d9adbe2023-07-20 12:41:23 -0700427TEST(PointerNullabilityTest, CallExprMultiNonnullParams) {
428 EXPECT_TRUE(checkDiagnostics(R"cc(
429 void take(int *_Nonnull, int *_Nullable, int *_Nonnull);
430 void target() {
431 take(nullptr, // [[unsafe]]
432 nullptr,
433 nullptr); // [[unsafe]]
434 }
435 )cc"));
436}
437
Martin Brænnec307b1f2023-04-20 07:16:35 -0700438TEST(PointerNullabilityTest, CanOverwritePtrWithPtrCreatedFromRefReturnType) {
439 // Test that if we create a pointer from a function returning a reference, we
440 // can use that pointer to overwrite an existing nullable pointer and make it
441 // nonnull.
442
443 EXPECT_TRUE(checkDiagnostics(R"cc(
Sam McCall7d9afee2023-06-27 01:43:24 -0700444 int &get_int();
Martin Brænnec307b1f2023-04-20 07:16:35 -0700445
Sam McCall7d9afee2023-06-27 01:43:24 -0700446 void target(int *_Nullable i) {
Martin Brænnec307b1f2023-04-20 07:16:35 -0700447 i = &get_int();
448 *i;
449 }
450 )cc"));
451}
452
453TEST(PointerNullabilityTest, CanOverwritePtrWithPtrReturnedByFunction) {
454 EXPECT_TRUE(checkDiagnostics(R"cc(
Sam McCall7d9afee2023-06-27 01:43:24 -0700455 int *_Nonnull get_int();
Martin Brænnec307b1f2023-04-20 07:16:35 -0700456
Sam McCall7d9afee2023-06-27 01:43:24 -0700457 void target(int *_Nullable i) {
Martin Brænnec307b1f2023-04-20 07:16:35 -0700458 i = get_int();
459 *i;
460 }
461 )cc"));
462}
463
Martin Brænne55ac3242023-04-20 07:42:46 -0700464TEST(PointerNullabilityTest, CallVariadicFunction) {
465 EXPECT_TRUE(checkDiagnostics(R"cc(
Sam McCall7d9afee2023-06-27 01:43:24 -0700466 void variadic(int *_Nonnull, ...);
Martin Brænne55ac3242023-04-20 07:42:46 -0700467 void target() {
468 int i = 0;
469 variadic(&i, nullptr, &i);
470 variadic(nullptr, nullptr, &i); // [[unsafe]]
471 }
472 )cc"));
473}
474
Martin Brænne89959d52023-06-28 06:10:18 -0700475TEST(PointerNullabilityTest, CallVariadicConstructor) {
476 EXPECT_TRUE(checkDiagnostics(R"cc(
477 struct S {
478 S(int* _Nonnull, ...);
479 };
480 void target() {
481 int i = 0;
482 S(&i, nullptr, &i);
483 S(nullptr, nullptr, &i); // [[unsafe]]
484 }
485 )cc"));
486}
487
Martin Brænne56cefdf2023-04-24 21:52:01 -0700488TEST(PointerNullabilityTest, CallMemberOperatorNoParams) {
489 EXPECT_TRUE(checkDiagnostics(R"cc(
490 struct MakeNonnull {
491 int *_Nonnull operator()();
492 };
493 struct MakeNullable {
494 int *_Nullable operator()();
495 };
496 struct MakeUnannotated {
497 int *operator()();
498 };
499 void target() {
500 MakeNonnull makeNonnull;
501 *makeNonnull();
502
503 MakeNullable makeNullable;
504 *makeNullable(); // [[unsafe]]
505
506 MakeUnannotated makeUnannotated;
507 *makeUnannotated();
508 }
509 )cc"));
510}
511
512TEST(PointerNullabilityTest, CallMemberOperatorOneParam) {
513 // overloaded operator with single param
514 EXPECT_TRUE(checkDiagnostics(R"cc(
515 // map<int * _Nonnull, int>
516 struct MapWithNonnullKeys {
517 int &operator[](int *_Nonnull key);
518 };
519 // map<int * _Nullable, int>
520 struct MapWithNullableKeys {
521 int &operator[](int *_Nullable key);
522 };
523 // map<int *, int>
524 struct MapWithUnannotatedKeys {
525 int &operator[](int *key);
526 };
527 void target(int *_Nonnull ptr_nonnull, int *_Nullable ptr_nullable,
528 int *ptr_unannotated) {
529 MapWithNonnullKeys nonnull_keys;
530 nonnull_keys[nullptr] = 42; // [[unsafe]]
531 nonnull_keys[ptr_nonnull] = 42;
532 nonnull_keys[ptr_nullable] = 42; // [[unsafe]]
533 nonnull_keys[ptr_unannotated] = 42;
534
535 MapWithNullableKeys nullable_keys;
536 nullable_keys[nullptr] = 42;
537 nullable_keys[ptr_nonnull] = 42;
538 nullable_keys[ptr_nullable] = 42;
539 nullable_keys[ptr_unannotated] = 42;
540
541 MapWithUnannotatedKeys unannotated_keys;
542 unannotated_keys[nullptr] = 42;
543 unannotated_keys[ptr_nonnull] = 42;
544 unannotated_keys[ptr_nullable] = 42;
545 unannotated_keys[ptr_unannotated] = 42;
546 }
547 )cc"));
548}
549
550TEST(PointerNullabilityTest, CallMemberOperatorMultipleParams) {
551 EXPECT_TRUE(checkDiagnostics(R"cc(
552 struct TakeMixed {
553 void operator()(int *, int *_Nullable, int *_Nonnull);
554 };
555 void target() {
556 TakeMixed takeMixed;
557 takeMixed(nullptr, nullptr, nullptr); // [[unsafe]]
558 }
559 )cc"));
560}
561
Martin Brænne4ac05552023-04-24 21:56:06 -0700562TEST(PointerNullabilityTest, CallFreeOperator) {
563 // No nullability involved. This is just a regression test to make sure we can
564 // process a call to a free overloaded operator.
565 EXPECT_TRUE(checkDiagnostics(R"cc(
566 struct A {};
567 A operator+(A, A);
568 void target() {
569 A a;
570 a = a + a;
571 }
572 )cc"));
573}
574
Martin Brænnec4903062023-04-24 23:40:36 -0700575// Check that we distinguish between the nullability of the return type and
576// parameters.
577TEST(PointerNullabilityTest, DistinguishFunctionReturnTypeAndParams) {
578 EXPECT_TRUE(checkDiagnostics(R"cc(
579 int *_Nullable callee(int *_Nonnull);
580
581 void target() {
582 int i = 0;
583 __assert_nullability<NK_nullable>(callee(&i));
584 }
585 )cc"));
586}
587
588TEST(PointerNullabilityTest, DistinguishMethodReturnTypeAndParams) {
589 EXPECT_TRUE(checkDiagnostics(R"cc(
590 struct S {
591 int *_Nullable callee(int *_Nonnull);
592 };
593
594 void target(S s) {
595 int i = 0;
596 __assert_nullability<NK_nullable>(s.callee(&i));
597 }
598 )cc"));
599}
600
601TEST(PointerNullabilityTest,
602 ClassTemplate_DistinguishMethodReturnTypeAndParams) {
603 EXPECT_TRUE(checkDiagnostics(R"cc(
604 template <typename T0, typename T1>
605 struct S {
606 T0 callee(T1);
607 };
608
609 void target(S<int *_Nullable, int *_Nonnull> s) {
610 int i = 0;
611 __assert_nullability<NK_nullable>(s.callee(&i));
612 }
613 )cc"));
614}
615
Martin Brænne61d4e362023-04-27 01:07:59 -0700616TEST(PointerNullabilityTest,
Martin Brænne31dedf02023-04-27 06:04:39 -0700617 CallFunctionTemplate_TemplateArgInReturnTypeHasNullTypeSourceInfo) {
Martin Brænne61d4e362023-04-27 01:07:59 -0700618 // This test sets up a function call where we don't have a `TypeSourceInfo`
Martin Brænne31dedf02023-04-27 06:04:39 -0700619 // for the argument to a template parameter used in the return type.
620 // This is a regression test for a crash that we observed on real-world code.
Martin Brænne61d4e362023-04-27 01:07:59 -0700621 EXPECT_TRUE(checkDiagnostics(R"cc(
622 template <class T>
623 struct A {
624 using Type = T;
625 };
626 template <int, class T>
627 typename A<T>::Type f(T);
628 void target() { f<0>(1); }
629 )cc"));
630}
631
Martin Brænne8cdb0b12023-04-27 03:47:50 -0700632TEST(PointerNullabilityTest, CallFunctionTemplate_PartiallyDeduced) {
633 EXPECT_TRUE(checkDiagnostics(R"cc(
634 template <int, class T>
635 T f(T);
636 void target() { f<0>(1); }
637 )cc"));
638}
639
Martin Brænne381e2b92023-06-26 01:02:48 -0700640TEST(PointerNullabilityTest, CallBuiltinFunction) {
641 // Crash repro.
642 EXPECT_TRUE(checkDiagnostics(R"cc(
643 void target() { __builtin_operator_new(0); }
644 )cc"));
645}
646
Martin Brænne874fa802023-10-24 08:01:24 -0700647TEST(PointerNullabilityTest, CallNoreturnDestructor) {
648 // This test demonstrates that the check considers program execution to end
649 // when a `noreturn` destructor is called.
650 // Among other things, this is intended to demonstrate that Abseil's logging
651 // instruction `LOG(FATAL)` (which creates an object with a `noreturn`
652 // destructor) is correctly interpreted as terminating the program.
653 EXPECT_TRUE(checkDiagnostics(R"cc(
654 struct Fatal {
655 __attribute__((noreturn)) ~Fatal();
656 void method(int);
657 };
658 void target(int* _Nullable p) {
659 // Do warn here, as the `*p` dereference happens before the `Fatal` object
660 // is destroyed.
661 Fatal().method(*p); // [[unsafe]]
662 // Don't warn here: We know that this code never gets executed.
663 *p;
664 }
665 )cc"));
666}
667
Googlere9a51b52023-10-25 08:41:19 -0700668TEST(PointerNullabilityTest, ConstMethodNoParamsCheckFirst) {
669 EXPECT_TRUE(checkDiagnostics(R"cc(
670 struct C {
671 int *_Nullable property() const { return x; }
Martin Brænne3f5afef2023-10-26 07:11:26 -0700672 int *_Nullable x = nullptr;
Googlere9a51b52023-10-25 08:41:19 -0700673 };
674 void target() {
675 C obj;
Martin Brænne3f5afef2023-10-26 07:11:26 -0700676 if (obj.property() != nullptr) *obj.property();
Googlere9a51b52023-10-25 08:41:19 -0700677 }
678 )cc"));
679}
680
681TEST(PointerNullabilityTest, FieldUndefinedValue) {
682 EXPECT_TRUE(checkDiagnostics(R"cc(
683 struct C {
684 int *_Nullable property() const { return x; }
Martin Brænne3f5afef2023-10-26 07:11:26 -0700685 int *_Nullable x = nullptr;
Googlere9a51b52023-10-25 08:41:19 -0700686 };
687 C foo();
688 void target() {
689 C obj;
Martin Brænne3f5afef2023-10-26 07:11:26 -0700690 if (foo().x != nullptr) *foo().x; // [[unsafe]]
Googlere9a51b52023-10-25 08:41:19 -0700691 }
692 )cc"));
693}
694
Martin Brænne262ffc72023-10-26 07:18:40 -0700695TEST(PointerNullabilityTest, Accessor_BaseObjectReturnedByReference) {
696 // Crash repro:
697 // If the base object of the accessor call expression is a reference returned
698 // from a function call, we have a storage location for the object but no
699 // values for its fields. Check that we don't crash in this case.
700 EXPECT_TRUE(checkDiagnostics(R"cc(
701 struct C {
702 int *_Nullable property() const { return x; }
703 int *_Nullable x = nullptr;
704 };
705 C &foo();
706 void target() {
707 if (foo().property() != nullptr) int x = *foo().property(); // [[unsafe]]
708 }
709 )cc"));
710}
711
Googlere9a51b52023-10-25 08:41:19 -0700712TEST(PointerNullabilityTest, MethodNoParamsUndefinedValue) {
713 EXPECT_TRUE(checkDiagnostics(R"cc(
714 struct C {
715 int *_Nullable property() const { return x; }
716 int *_Nullable x = nullptr;
717 };
Googlere9a51b52023-10-25 08:41:19 -0700718 void target() {
719 int x = 0;
720 if (C().property() != nullptr) {
721 *C().property(); // [[unsafe]]
722 }
Martin Brænne3f5afef2023-10-26 07:11:26 -0700723 C obj;
Googlere9a51b52023-10-25 08:41:19 -0700724 if (obj.property() != nullptr) {
725 *obj.property();
726 }
727 }
728 )cc"));
729}
730
Martin Brænne9a5be6e2023-04-11 10:22:06 -0700731} // namespace
Sam McCall4f6be422023-06-27 02:51:22 -0700732} // namespace clang::tidy::nullability