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 // Eventually these should be TRUE as well, but right now
144 // we can't handle array constructors.
145 clang_analyzer_eval(arr
[0].x
== 0); // expected-warning{{UNKNOWN}}
146 clang_analyzer_eval(arr
[1].x
== 0); // expected-warning{{UNKNOWN}}
150 clang_analyzer_eval(*arr
[0].x
== 42); // expected-warning{{TRUE}}
151 clang_analyzer_eval(*arr
[1].x
== 42); // expected-warning{{TRUE}}
154 // The destructors should have invalidated i and j.
155 clang_analyzer_eval(i
== 42); // expected-warning{{UNKNOWN}}
156 clang_analyzer_eval(j
== 42); // expected-warning{{UNKNOWN}}
161 // Don't crash on a default argument inside an initializer.
163 DefaultArg(int x
= 0) {}
167 struct InheritsDefaultArg
: DefaultArg
{
168 InheritsDefaultArg() {}
169 virtual ~InheritsDefaultArg();
172 void testDefaultArg() {
173 InheritsDefaultArg a
;
174 // Force a bug to be emitted.
175 *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
179 namespace DestructorVirtualCalls
{
182 int *out1
, *out2
, *out3
;
184 virtual int get() { return 1; }
193 virtual int get() { return 2; }
202 virtual int get() { return 3; }
212 // New scope for the C object.
215 clang_analyzer_eval(obj
.get() == 3); // expected-warning{{TRUE}}
217 // Correctness check for devirtualization.
219 clang_analyzer_eval(base
->get() == 3); // expected-warning{{TRUE}}
226 clang_analyzer_eval(a
== 1); // expected-warning{{TRUE}}
227 clang_analyzer_eval(b
== 2); // expected-warning{{TRUE}}
228 clang_analyzer_eval(c
== 3); // expected-warning{{TRUE}}
233 namespace DestructorsShouldNotAffectReturnValues
{
237 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
243 return malloc(4); // no-warning
247 // At one point we had an issue where the statements inside an
248 // inlined destructor kept us from finding the return statement,
249 // leading the analyzer to believe that the malloc'd memory had leaked.
250 void *p
= allocate();
251 free(p
); // no-warning
255 namespace MultipleInheritanceVirtualDtors
{
258 virtual ~VirtualDtor() {
259 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
263 class NonVirtualDtor
{
266 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
270 class SubclassA
: public VirtualDtor
, public NonVirtualDtor
{
272 virtual ~SubclassA() {}
274 class SubclassB
: public NonVirtualDtor
, public VirtualDtor
{
276 virtual ~SubclassB() {}
285 namespace ExplicitDestructorCall
{
288 virtual ~VirtualDtor() {
289 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
293 class Subclass
: public VirtualDtor
{
295 virtual ~Subclass() {
296 clang_analyzer_checkInlined(false); // no-warning
300 void destroy(Subclass
*obj
) {
301 obj
->VirtualDtor::~VirtualDtor();
306 namespace MultidimensionalArrays
{
307 void testArrayInvalidation() {
312 IntWrapper arr
[2][2];
314 // There should be no undefined value warnings here.
315 // Eventually these should be TRUE as well, but right now
316 // we can't handle array constructors.
317 clang_analyzer_eval(arr
[0][0].x
== 0); // expected-warning{{UNKNOWN}}
318 clang_analyzer_eval(arr
[1][1].x
== 0); // expected-warning{{UNKNOWN}}
322 clang_analyzer_eval(*arr
[0][0].x
== 42); // expected-warning{{TRUE}}
323 clang_analyzer_eval(*arr
[1][1].x
== 42); // expected-warning{{TRUE}}
326 // The destructors should have invalidated i and j.
327 clang_analyzer_eval(i
== 42); // expected-warning{{UNKNOWN}}
328 clang_analyzer_eval(j
== 42); // expected-warning{{UNKNOWN}}
332 namespace LifetimeExtension
{
335 IntWrapper(int y
) : x(y
) {}
337 extern void use(int);
338 use(x
); // no-warning
342 struct DerivedWrapper
: public IntWrapper
{
343 DerivedWrapper(int y
) : IntWrapper(y
) {}
346 DerivedWrapper
get() {
347 return DerivedWrapper(1);
351 const DerivedWrapper
&d
= get(); // lifetime extended here
355 class SaveOnDestruct
{
357 static int lastOutput
;
368 const SaveOnDestruct
&obj
= SaveOnDestruct();
371 // destructor called here
374 clang_analyzer_eval(SaveOnDestruct::lastOutput
== 42); // expected-warning{{TRUE}}
379 NRCheck():bool_(true) {}
380 ~NRCheck() __attribute__((noreturn
));
381 operator bool() const { return bool_
; }
384 struct CheckAutoDestructor
{
386 CheckAutoDestructor():bool_(true) {}
387 operator bool() const { return bool_
; }
390 struct CheckCustomDestructor
{
392 CheckCustomDestructor():bool_(true) {}
393 ~CheckCustomDestructor();
394 operator bool() const { return bool_
; }
397 bool testUnnamedNR() {
404 if (NRCheck c
= NRCheck())
409 bool testUnnamedAutoDestructor() {
410 if (CheckAutoDestructor())
415 bool testNamedAutoDestructor() {
416 if (CheckAutoDestructor c
= CheckAutoDestructor())
421 bool testUnnamedCustomDestructor() {
422 if (CheckCustomDestructor())
427 // This case used to cause an unexpected "Undefined or garbage value returned
428 // to caller" warning
429 bool testNamedCustomDestructor() {
430 if (CheckCustomDestructor c
= CheckCustomDestructor())
435 bool testMultipleTemporariesCustomDestructor() {
436 if (CheckCustomDestructor c
= (CheckCustomDestructor(), CheckCustomDestructor()))
441 class VirtualDtorBase
{
444 virtual ~VirtualDtorBase() {}
447 class SaveOnVirtualDestruct
: public VirtualDtorBase
{
449 static int lastOutput
;
451 SaveOnVirtualDestruct();
452 virtual ~SaveOnVirtualDestruct() {
459 const VirtualDtorBase
&obj
= SaveOnVirtualDestruct();
462 // destructor called here
465 clang_analyzer_eval(SaveOnVirtualDestruct::lastOutput
== 42); // expected-warning{{TRUE}}
471 ~NR() __attribute__((noreturn
));
481 *x
= 47; // no warning
486 *x
= 47; // no warning
490 namespace PseudoDtor
{
491 template <typename T
>
492 void destroy(T
&obj
) {
493 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
500 clang_analyzer_eval(true); // expected-warning{{TRUE}}
504 namespace Incomplete
{
505 class Foo
; // expected-note{{forward declaration}}
506 void f(Foo
*foo
) { delete foo
; } // expected-warning{{deleting pointer to incomplete type}}
509 namespace TypeTraitExpr
{
510 template <bool IsSimple
, typename T
>
512 static void do_copy(T
*dest
, const T
*src
, unsigned count
);
514 template <typename T
, typename U
>
515 void do_copy(T
*dest
, const U
*src
, unsigned count
) {
516 const bool IsSimple
= __is_trivial(T
) && __is_same(T
, U
);
517 copier
<IsSimple
, T
>::do_copy(dest
, src
, count
);
521 NonTrivial() : p(new int[1]) { p
[0] = 0; }
522 NonTrivial(const NonTrivial
&other
) {
524 do_copy(p
, other
.p
, 1);
526 NonTrivial
&operator=(const NonTrivial
&other
) {
531 delete[] p
; // expected-warning {{free released memory}}
539 clang_analyzer_eval(__is_trivial(NonTrivial
)); // expected-warning{{FALSE}}
540 clang_analyzer_eval(__alignof(NonTrivial
) > 0); // expected-warning{{TRUE}}
544 namespace dtor_over_loc_concrete_int
{
568 void testAutoDtor() {
569 const A
&a
= *(A
*)-1;
572 } // namespace dtor_over_loc_concrete_int