1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\ 2 // RUN: -analyzer-checker cplusplus.Move,alpha.cplusplus.SmartPtr\ 3 // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\ 4 // RUN: -std=c++11 -verify %s 5 6 #include "Inputs/system-header-simulator-cxx.h" 7 8 void clang_analyzer_warnIfReached(); 9 void clang_analyzer_numTimesReached(); 10 11 void derefAfterMove(std::unique_ptr<int> P) { 12 std::unique_ptr<int> Q = std::move(P); 13 if (Q) 14 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} 15 *Q.get() = 1; // no-warning 16 if (P) 17 clang_analyzer_warnIfReached(); // no-warning 18 // TODO: Report a null dereference (instead). 19 *P.get() = 1; // expected-warning {{Method called on moved-from object 'P'}} 20 } 21 22 // Don't crash when attempting to model a call with unknown callee. 23 namespace testUnknownCallee { 24 struct S { 25 void foo(); 26 }; 27 void bar(S *s, void (S::*func)(void)) { 28 (s->*func)(); // no-crash 29 } 30 } // namespace testUnknownCallee 31 32 class A { 33 public: 34 A(){}; 35 void foo(); 36 }; 37 38 A *return_null() { 39 return nullptr; 40 } 41 42 void derefAfterValidCtr() { 43 std::unique_ptr<A> P(new A()); 44 P->foo(); // No warning. 45 } 46 47 void derefOfUnknown(std::unique_ptr<A> P) { 48 P->foo(); // No warning. 49 } 50 51 void derefAfterDefaultCtr() { 52 std::unique_ptr<A> P; 53 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 54 } 55 56 void derefAfterCtrWithNull() { 57 std::unique_ptr<A> P(nullptr); 58 *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 59 } 60 61 void derefAfterCtrWithNullVariable() { 62 A *InnerPtr = nullptr; 63 std::unique_ptr<A> P(InnerPtr); 64 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 65 } 66 67 void derefAfterRelease() { 68 std::unique_ptr<A> P(new A()); 69 P.release(); 70 clang_analyzer_numTimesReached(); // expected-warning {{1}} 71 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 72 } 73 74 void derefAfterReset() { 75 std::unique_ptr<A> P(new A()); 76 P.reset(); 77 clang_analyzer_numTimesReached(); // expected-warning {{1}} 78 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 79 } 80 81 void derefAfterResetWithNull() { 82 std::unique_ptr<A> P(new A()); 83 P.reset(nullptr); 84 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 85 } 86 87 void derefAfterResetWithNonNull() { 88 std::unique_ptr<A> P; 89 P.reset(new A()); 90 P->foo(); // No warning. 91 } 92 93 void derefAfterReleaseAndResetWithNonNull() { 94 std::unique_ptr<A> P(new A()); 95 P.release(); 96 P.reset(new A()); 97 P->foo(); // No warning. 98 } 99 100 void derefOnReleasedNullRawPtr() { 101 std::unique_ptr<A> P; 102 A *AP = P.release(); 103 AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 104 } 105 106 void derefOnReleasedValidRawPtr() { 107 std::unique_ptr<A> P(new A()); 108 A *AP = P.release(); 109 AP->foo(); // No warning. 110 } 111 112 void pass_smart_ptr_by_ref(std::unique_ptr<A> &a); 113 void pass_smart_ptr_by_const_ref(const std::unique_ptr<A> &a); 114 void pass_smart_ptr_by_rvalue_ref(std::unique_ptr<A> &&a); 115 void pass_smart_ptr_by_const_rvalue_ref(const std::unique_ptr<A> &&a); 116 void pass_smart_ptr_by_ptr(std::unique_ptr<A> *a); 117 void pass_smart_ptr_by_const_ptr(const std::unique_ptr<A> *a); 118 119 void regioninvalidationTest() { 120 { 121 std::unique_ptr<A> P; 122 pass_smart_ptr_by_ref(P); 123 P->foo(); // no-warning 124 } 125 { 126 std::unique_ptr<A> P; 127 pass_smart_ptr_by_const_ref(P); 128 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 129 } 130 { 131 std::unique_ptr<A> P; 132 pass_smart_ptr_by_rvalue_ref(std::move(P)); 133 P->foo(); // no-warning 134 } 135 { 136 std::unique_ptr<A> P; 137 pass_smart_ptr_by_const_rvalue_ref(std::move(P)); 138 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 139 } 140 { 141 std::unique_ptr<A> P; 142 pass_smart_ptr_by_ptr(&P); 143 P->foo(); 144 } 145 { 146 std::unique_ptr<A> P; 147 pass_smart_ptr_by_const_ptr(&P); 148 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 149 } 150 } 151 152 struct StructWithSmartPtr { 153 std::unique_ptr<A> P; 154 }; 155 156 void pass_struct_with_smart_ptr_by_ref(StructWithSmartPtr &a); 157 void pass_struct_with_smart_ptr_by_const_ref(const StructWithSmartPtr &a); 158 void pass_struct_with_smart_ptr_by_rvalue_ref(StructWithSmartPtr &&a); 159 void pass_struct_with_smart_ptr_by_const_rvalue_ref(const StructWithSmartPtr &&a); 160 void pass_struct_with_smart_ptr_by_ptr(StructWithSmartPtr *a); 161 void pass_struct_with_smart_ptr_by_const_ptr(const StructWithSmartPtr *a); 162 163 void regioninvalidationTestWithinStruct() { 164 { 165 StructWithSmartPtr S; 166 pass_struct_with_smart_ptr_by_ref(S); 167 S.P->foo(); // no-warning 168 } 169 { 170 StructWithSmartPtr S; 171 pass_struct_with_smart_ptr_by_const_ref(S); 172 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 173 } 174 { 175 StructWithSmartPtr S; 176 pass_struct_with_smart_ptr_by_rvalue_ref(std::move(S)); 177 S.P->foo(); // no-warning 178 } 179 { 180 StructWithSmartPtr S; 181 pass_struct_with_smart_ptr_by_const_rvalue_ref(std::move(S)); 182 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 183 } 184 { 185 StructWithSmartPtr S; 186 pass_struct_with_smart_ptr_by_ptr(&S); 187 S.P->foo(); 188 } 189 { 190 StructWithSmartPtr S; 191 pass_struct_with_smart_ptr_by_const_ptr(&S); 192 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 193 } 194 } 195 196 void derefAfterAssignment() { 197 { 198 std::unique_ptr<A> P(new A()); 199 std::unique_ptr<A> Q; 200 Q = std::move(P); 201 Q->foo(); // no-warning 202 } 203 { 204 std::unique_ptr<A> P; 205 std::unique_ptr<A> Q; 206 Q = std::move(P); 207 // TODO: Fix test with expecting warning after '=' operator overloading modeling. 208 Q->foo(); // no-warning 209 } 210 } 211 212 void derefOnSwappedNullPtr() { 213 std::unique_ptr<A> P(new A()); 214 std::unique_ptr<A> PNull; 215 P.swap(PNull); 216 PNull->foo(); // No warning. 217 (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 218 } 219 220 void derefOnStdSwappedNullPtr() { 221 std::unique_ptr<A> P; 222 std::unique_ptr<A> PNull; 223 std::swap(P, PNull); 224 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 225 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 226 } 227 228 void derefOnSwappedValidPtr() { 229 std::unique_ptr<A> P(new A()); 230 std::unique_ptr<A> PValid(new A()); 231 P.swap(PValid); 232 (*P).foo(); // No warning. 233 PValid->foo(); // No warning. 234 std::swap(P, PValid); 235 P->foo(); // No warning. 236 PValid->foo(); // No warning. 237 } 238