1 // RUN: %clang_analyze_cc1\
2 // RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr\
3 // RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
4 // RUN:  -analyzer-output=text -std=c++11 %s -verify=expected
5 
6 #include "Inputs/system-header-simulator-cxx.h"
7 
8 class A {
9 public:
10   A(){};
11   void foo();
12 };
13 
14 A *return_null() {
15   return nullptr;
16 }
17 
18 void derefAfterDefaultCtr() {
19   std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}}
20   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
21   // expected-note@-1{{Dereference of null smart pointer 'P'}}
22 }
23 
24 void derefAfterCtrWithNull() {
25   A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}}
26   std::unique_ptr<A> P(NullInnerPtr); // expected-note {{Smart pointer 'P' is constructed using a null value}}
27   *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
28   // expected-note@-1{{Dereference of null smart pointer 'P'}}
29 }
30 
31 void derefAfterCtrWithNullVariable() {
32   A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}}
33   std::unique_ptr<A> P(NullInnerPtr); // expected-note {{Smart pointer 'P' is constructed using a null value}}
34   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
35   // expected-note@-1{{Dereference of null smart pointer 'P'}}
36 }
37 
38 void derefAfterRelease() {
39   std::unique_ptr<A> P(new A());
40   P.release(); // expected-note {{Smart pointer 'P' is released and set to null}}
41   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
42   // expected-note@-1{{Dereference of null smart pointer 'P'}}
43 }
44 
45 void derefAfterReset() {
46   std::unique_ptr<A> P(new A());
47   P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
48   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
49   // expected-note@-1{{Dereference of null smart pointer 'P'}}
50 }
51 
52 void derefAfterResetWithNull() {
53   A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}}
54   std::unique_ptr<A> P(new A());
55   P.reset(NullInnerPtr); // expected-note {{Smart pointer 'P' reset using a null value}}
56   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
57   // expected-note@-1{{Dereference of null smart pointer 'P'}}
58 }
59 
60 // FIXME: Fix this test when support is added for tracking raw pointer
61 // and mark the smart pointer as interesting based on that and add tags.
62 void derefOnReleasedNullRawPtr() {
63   std::unique_ptr<A> P; // FIXME: add note "Default constructed smart pointer 'P' is null"
64   A *AP = P.release(); // expected-note {{'AP' initialized to a null pointer value}}
65   AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
66   // expected-note@-1{{Called C++ object pointer is null}}
67 }
68 
69 void derefOnSwappedNullPtr() {
70   std::unique_ptr<A> P(new A());
71   std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
72   P.swap(PNull); // expected-note {{Swapped null smart pointer 'PNull' with smart pointer 'P'}}
73   PNull->foo(); // No warning.
74   (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
75   // expected-note@-1{{Dereference of null smart pointer 'P'}}
76 }
77 
78 // FIXME: Fix this test when "std::swap" is modeled seperately.
79 void derefOnStdSwappedNullPtr() {
80   std::unique_ptr<A> P;
81   std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
82   std::swap(P, PNull); // expected-note@Inputs/system-header-simulator-cxx.h:978 {{Swapped null smart pointer 'PNull' with smart pointer 'P'}}
83   // expected-note@-1 {{Calling 'swap<A>'}}
84   // expected-note@-2 {{Returning from 'swap<A>'}}
85   PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
86   // expected-note@-1{{Dereference of null smart pointer 'PNull'}}
87   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
88   // expected-note@-1{{Dereference of null smart pointer 'P'}}
89 }
90 
91 struct StructWithSmartPtr { // expected-note {{Default constructed smart pointer 'S.P' is null}}
92   std::unique_ptr<A> P;
93 };
94 
95 void derefAfterDefaultCtrInsideStruct() {
96   StructWithSmartPtr S; // expected-note {{Calling implicit default constructor for 'StructWithSmartPtr'}}
97   // expected-note@-1 {{Returning from default constructor for 'StructWithSmartPtr'}}
98   S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}
99   // expected-note@-1{{Dereference of null smart pointer 'S.P'}}
100 }
101 
102 void noNoteTagsForNonInterestingRegion() {
103   std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}}
104   std::unique_ptr<A> P1; // No note.
105   std::unique_ptr<A> P2; // No note.
106   P1.release(); // No note.
107   P1.reset(); // No note.
108   P1.swap(P2); // No note.
109   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
110   // expected-note@-1{{Dereference of null smart pointer 'P'}}
111 }
112 
113 void noNoteTagsForNonMatchingBugType() {
114   std::unique_ptr<A> P; // No note.
115   std::unique_ptr<A> P1; // No note.
116   P1 = std::move(P); // expected-note {{Smart pointer 'P' of type 'std::unique_ptr' is reset to null when moved from}}
117   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' of type 'std::unique_ptr' [cplusplus.Move]}}
118   // expected-note@-1 {{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}}
119 }
120