1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection,cplusplus -analyzer-config c++-inlining=destructors -Wno-null-dereference -Wno-inaccessible-base -verify -analyzer-config eagerly-assume=false %s
3 void clang_analyzer_eval(bool);
4 void clang_analyzer_checkInlined(bool);
10 *x
= 3; // expected-warning{{Dereference of null pointer}}
19 typedef __typeof(sizeof(int)) size_t;
26 SmartPointer(void *x
) : X(x
) {}
32 void testSmartPointer() {
33 char *mem
= (char*)malloc(4);
35 SmartPointer
Deleter(mem
);
36 // destructor called here
38 *mem
= 0; // expected-warning{{Use of memory after it is freed}}
43 void testSmartPointer2() {
44 char *mem
= (char*)malloc(4);
46 SmartPointer
Deleter(mem
);
47 // Remove dead bindings...
49 // destructor called here
51 *mem
= 0; // expected-warning{{Use of memory after it is freed}}
55 class Subclass
: public SmartPointer
{
57 Subclass(void *x
) : SmartPointer(x
) {}
60 void testSubclassSmartPointer() {
61 char *mem
= (char*)malloc(4);
63 Subclass
Deleter(mem
);
64 // Remove dead bindings...
66 // destructor called here
68 *mem
= 0; // expected-warning{{Use of memory after it is freed}}
72 class MultipleInheritance
: public Subclass
, public SmartPointer
{
74 MultipleInheritance(void *a
, void *b
) : Subclass(a
), SmartPointer(b
) {}
77 void testMultipleInheritance1() {
78 char *mem
= (char*)malloc(4);
80 MultipleInheritance
Deleter(mem
, 0);
81 // Remove dead bindings...
83 // destructor called here
85 *mem
= 0; // expected-warning{{Use of memory after it is freed}}
88 void testMultipleInheritance2() {
89 char *mem
= (char*)malloc(4);
91 MultipleInheritance
Deleter(0, mem
);
92 // Remove dead bindings...
94 // destructor called here
96 *mem
= 0; // expected-warning{{Use of memory after it is freed}}
99 void testMultipleInheritance3() {
100 char *mem
= (char*)malloc(4);
102 MultipleInheritance
Deleter(mem
, mem
);
103 // Remove dead bindings...
105 // destructor called here
106 // expected-warning@28 {{Attempt to free released memory}}
111 class SmartPointerMember
{
114 SmartPointerMember(void *x
) : P(x
) {}
117 void testSmartPointerMember() {
118 char *mem
= (char*)malloc(4);
120 SmartPointerMember
Deleter(mem
);
121 // Remove dead bindings...
123 // destructor called here
125 *mem
= 0; // expected-warning{{Use of memory after it is freed}}
130 IntWrapper() : x(0) {}
135 void testArrayInvalidation() {
142 // There should be no undefined value warnings here.
143 clang_analyzer_eval(arr
[0].x
== 0); // expected-warning{{TRUE}}
144 clang_analyzer_eval(arr
[1].x
== 0); // expected-warning{{TRUE}}
148 clang_analyzer_eval(*arr
[0].x
== 42); // expected-warning{{TRUE}}
149 clang_analyzer_eval(*arr
[1].x
== 42); // expected-warning{{TRUE}}
152 // The destructors should have invalidated i and j.
153 clang_analyzer_eval(i
== 42); // expected-warning{{UNKNOWN}}
154 clang_analyzer_eval(j
== 42); // expected-warning{{UNKNOWN}}
159 // Don't crash on a default argument inside an initializer.
161 DefaultArg(int x
= 0) {}
165 struct InheritsDefaultArg
: DefaultArg
{
166 InheritsDefaultArg() {}
167 virtual ~InheritsDefaultArg();
170 void testDefaultArg() {
171 InheritsDefaultArg a
;
172 // Force a bug to be emitted.
173 *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
177 namespace DestructorVirtualCalls
{
180 int *out1
, *out2
, *out3
;
182 virtual int get() { return 1; }
191 virtual int get() { return 2; }
200 virtual int get() { return 3; }
210 // New scope for the C object.
213 clang_analyzer_eval(obj
.get() == 3); // expected-warning{{TRUE}}
215 // Correctness check for devirtualization.
217 clang_analyzer_eval(base
->get() == 3); // expected-warning{{TRUE}}
224 clang_analyzer_eval(a
== 1); // expected-warning{{TRUE}}
225 clang_analyzer_eval(b
== 2); // expected-warning{{TRUE}}
226 clang_analyzer_eval(c
== 3); // expected-warning{{TRUE}}
231 namespace DestructorsShouldNotAffectReturnValues
{
235 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
241 return malloc(4); // no-warning
245 // At one point we had an issue where the statements inside an
246 // inlined destructor kept us from finding the return statement,
247 // leading the analyzer to believe that the malloc'd memory had leaked.
248 void *p
= allocate();
249 free(p
); // no-warning
253 namespace MultipleInheritanceVirtualDtors
{
256 virtual ~VirtualDtor() {
257 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
261 class NonVirtualDtor
{
264 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
268 class SubclassA
: public VirtualDtor
, public NonVirtualDtor
{
270 virtual ~SubclassA() {}
272 class SubclassB
: public NonVirtualDtor
, public VirtualDtor
{
274 virtual ~SubclassB() {}
283 namespace ExplicitDestructorCall
{
286 virtual ~VirtualDtor() {
287 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
291 class Subclass
: public VirtualDtor
{
293 virtual ~Subclass() {
294 clang_analyzer_checkInlined(false); // no-warning
298 void destroy(Subclass
*obj
) {
299 obj
->VirtualDtor::~VirtualDtor();
304 namespace MultidimensionalArrays
{
305 void testArrayInvalidation() {
310 IntWrapper arr
[2][2];
312 // There should be no undefined value warnings here.
313 clang_analyzer_eval(arr
[0][0].x
== 0); // expected-warning{{TRUE}}
314 clang_analyzer_eval(arr
[1][1].x
== 0); // expected-warning{{TRUE}}
318 clang_analyzer_eval(*arr
[0][0].x
== 42); // expected-warning{{TRUE}}
319 clang_analyzer_eval(*arr
[1][1].x
== 42); // expected-warning{{TRUE}}
322 // The destructors should have invalidated i and j.
323 clang_analyzer_eval(i
== 42); // expected-warning{{UNKNOWN}}
324 clang_analyzer_eval(j
== 42); // expected-warning{{UNKNOWN}}
328 namespace LifetimeExtension
{
331 IntWrapper(int y
) : x(y
) {}
333 extern void use(int);
334 use(x
); // no-warning
338 struct DerivedWrapper
: public IntWrapper
{
339 DerivedWrapper(int y
) : IntWrapper(y
) {}
342 DerivedWrapper
get() {
343 return DerivedWrapper(1);
347 const DerivedWrapper
&d
= get(); // lifetime extended here
351 class SaveOnDestruct
{
353 static int lastOutput
;
364 const SaveOnDestruct
&obj
= SaveOnDestruct();
367 // destructor called here
370 clang_analyzer_eval(SaveOnDestruct::lastOutput
== 42); // expected-warning{{TRUE}}
375 NRCheck():bool_(true) {}
376 ~NRCheck() __attribute__((noreturn
));
377 operator bool() const { return bool_
; }
380 struct CheckAutoDestructor
{
382 CheckAutoDestructor():bool_(true) {}
383 operator bool() const { return bool_
; }
386 struct CheckCustomDestructor
{
388 CheckCustomDestructor():bool_(true) {}
389 ~CheckCustomDestructor();
390 operator bool() const { return bool_
; }
393 bool testUnnamedNR() {
400 if (NRCheck c
= NRCheck())
405 bool testUnnamedAutoDestructor() {
406 if (CheckAutoDestructor())
411 bool testNamedAutoDestructor() {
412 if (CheckAutoDestructor c
= CheckAutoDestructor())
417 bool testUnnamedCustomDestructor() {
418 if (CheckCustomDestructor())
423 // This case used to cause an unexpected "Undefined or garbage value returned
424 // to caller" warning
425 bool testNamedCustomDestructor() {
426 if (CheckCustomDestructor c
= CheckCustomDestructor())
431 bool testMultipleTemporariesCustomDestructor() {
432 if (CheckCustomDestructor c
= (CheckCustomDestructor(), CheckCustomDestructor()))
437 class VirtualDtorBase
{
440 virtual ~VirtualDtorBase() {}
443 class SaveOnVirtualDestruct
: public VirtualDtorBase
{
445 static int lastOutput
;
447 SaveOnVirtualDestruct();
448 virtual ~SaveOnVirtualDestruct() {
455 const VirtualDtorBase
&obj
= SaveOnVirtualDestruct();
458 // destructor called here
461 clang_analyzer_eval(SaveOnVirtualDestruct::lastOutput
== 42); // expected-warning{{TRUE}}
467 ~NR() __attribute__((noreturn
));
477 *x
= 47; // no warning
482 *x
= 47; // no warning
486 namespace PseudoDtor
{
487 template <typename T
>
488 void destroy(T
&obj
) {
489 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
496 clang_analyzer_eval(true); // expected-warning{{TRUE}}
500 namespace Incomplete
{
501 class Foo
; // expected-note{{forward declaration}}
502 void f(Foo
*foo
) { delete foo
; } // expected-warning{{deleting pointer to incomplete type}}
505 namespace TypeTraitExpr
{
506 template <bool IsSimple
, typename T
>
508 static void do_copy(T
*dest
, const T
*src
, unsigned count
);
510 template <typename T
, typename U
>
511 void do_copy(T
*dest
, const U
*src
, unsigned count
) {
512 const bool IsSimple
= __is_trivial(T
) && __is_same(T
, U
);
513 copier
<IsSimple
, T
>::do_copy(dest
, src
, count
);
517 NonTrivial() : p(new int[1]) { p
[0] = 0; }
518 NonTrivial(const NonTrivial
&other
) {
520 do_copy(p
, other
.p
, 1);
522 NonTrivial
&operator=(const NonTrivial
&other
) {
527 delete[] p
; // expected-warning {{free released memory}}
535 clang_analyzer_eval(__is_trivial(NonTrivial
)); // expected-warning{{FALSE}}
536 clang_analyzer_eval(__alignof(NonTrivial
) > 0); // expected-warning{{TRUE}}
540 namespace dtor_over_loc_concrete_int
{
564 void testAutoDtor() {
565 const A
&a
= *(A
*)-1;
568 } // namespace dtor_over_loc_concrete_int
570 // Test overriden new/delete operators
571 struct CustomOperators
{
572 void *operator new(size_t count
) {
573 return malloc(count
);
576 void operator delete(void *addr
) {
585 auto *a
= new CustomOperators();
589 void overrideLeak() {
590 auto *a
= new CustomOperators();
591 } // expected-warning{{Potential leak of memory pointed to by 'a'}}
593 void overrideDoubleDelete() {
594 auto *a
= new CustomOperators();
596 delete a
; // expected-warning@577 {{Attempt to free released memory}}