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 clang_analyzer_numTimesReached(); // expected-warning {{1}} 45 P->foo(); // No warning. 46 } 47 48 void derefOfUnknown(std::unique_ptr<A> P) { 49 P->foo(); // No warning. 50 } 51 52 void derefAfterDefaultCtr() { 53 std::unique_ptr<A> P; 54 clang_analyzer_numTimesReached(); // expected-warning {{1}} 55 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 56 } 57 58 void derefAfterCtrWithNull() { 59 std::unique_ptr<A> P(nullptr); 60 clang_analyzer_numTimesReached(); // expected-warning {{1}} 61 *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 62 } 63 64 void derefAfterCtrWithNullVariable() { 65 A *InnerPtr = nullptr; 66 std::unique_ptr<A> P(InnerPtr); 67 clang_analyzer_numTimesReached(); // expected-warning {{1}} 68 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 69 } 70 71 void derefAfterRelease() { 72 std::unique_ptr<A> P(new A()); 73 P.release(); 74 clang_analyzer_numTimesReached(); // expected-warning {{1}} 75 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 76 } 77 78 void derefAfterReset() { 79 std::unique_ptr<A> P(new A()); 80 P.reset(); 81 clang_analyzer_numTimesReached(); // expected-warning {{1}} 82 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 83 } 84 85 void derefAfterResetWithNull() { 86 std::unique_ptr<A> P(new A()); 87 P.reset(nullptr); 88 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 89 } 90 91 void derefAfterResetWithNonNull() { 92 std::unique_ptr<A> P; 93 P.reset(new A()); 94 clang_analyzer_numTimesReached(); // expected-warning {{1}} 95 P->foo(); // No warning. 96 } 97 98 void derefAfterReleaseAndResetWithNonNull() { 99 std::unique_ptr<A> P(new A()); 100 P.release(); 101 P.reset(new A()); 102 P->foo(); // No warning. 103 } 104 105 void derefOnReleasedNullRawPtr() { 106 std::unique_ptr<A> P; 107 A *AP = P.release(); 108 AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 109 } 110 111 void derefOnReleasedValidRawPtr() { 112 std::unique_ptr<A> P(new A()); 113 A *AP = P.release(); 114 AP->foo(); // No warning. 115 } 116 117 void pass_smart_ptr_by_ref(std::unique_ptr<A> &a); 118 void pass_smart_ptr_by_const_ref(const std::unique_ptr<A> &a); 119 void pass_smart_ptr_by_rvalue_ref(std::unique_ptr<A> &&a); 120 void pass_smart_ptr_by_const_rvalue_ref(const std::unique_ptr<A> &&a); 121 void pass_smart_ptr_by_ptr(std::unique_ptr<A> *a); 122 void pass_smart_ptr_by_const_ptr(const std::unique_ptr<A> *a); 123 124 void regioninvalidationWithPassByRef() { 125 std::unique_ptr<A> P; 126 pass_smart_ptr_by_ref(P); 127 P->foo(); // no-warning 128 } 129 130 void regioninvalidationWithPassByCostRef() { 131 std::unique_ptr<A> P; 132 pass_smart_ptr_by_const_ref(P); 133 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 134 } 135 136 void regioninvalidationWithPassByRValueRef() { 137 std::unique_ptr<A> P; 138 pass_smart_ptr_by_rvalue_ref(std::move(P)); 139 P->foo(); // no-warning 140 } 141 142 void regioninvalidationWithPassByConstRValueRef() { 143 std::unique_ptr<A> P; 144 pass_smart_ptr_by_const_rvalue_ref(std::move(P)); 145 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 146 } 147 148 void regioninvalidationWithPassByPtr() { 149 std::unique_ptr<A> P; 150 pass_smart_ptr_by_ptr(&P); 151 P->foo(); 152 } 153 154 void regioninvalidationWithPassByConstPtr() { 155 std::unique_ptr<A> P; 156 pass_smart_ptr_by_const_ptr(&P); 157 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 158 } 159 160 struct StructWithSmartPtr { 161 std::unique_ptr<A> P; 162 }; 163 164 void pass_struct_with_smart_ptr_by_ref(StructWithSmartPtr &a); 165 void pass_struct_with_smart_ptr_by_const_ref(const StructWithSmartPtr &a); 166 void pass_struct_with_smart_ptr_by_rvalue_ref(StructWithSmartPtr &&a); 167 void pass_struct_with_smart_ptr_by_const_rvalue_ref(const StructWithSmartPtr &&a); 168 void pass_struct_with_smart_ptr_by_ptr(StructWithSmartPtr *a); 169 void pass_struct_with_smart_ptr_by_const_ptr(const StructWithSmartPtr *a); 170 171 void regioninvalidationWithinStructPassByRef() { 172 StructWithSmartPtr S; 173 pass_struct_with_smart_ptr_by_ref(S); 174 S.P->foo(); // no-warning 175 } 176 177 void regioninvalidationWithinStructPassByConstRef() { 178 StructWithSmartPtr S; 179 pass_struct_with_smart_ptr_by_const_ref(S); 180 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 181 } 182 183 void regioninvalidationWithinStructPassByRValueRef() { 184 StructWithSmartPtr S; 185 pass_struct_with_smart_ptr_by_rvalue_ref(std::move(S)); 186 S.P->foo(); // no-warning 187 } 188 189 void regioninvalidationWithinStructPassByConstRValueRef() { 190 StructWithSmartPtr S; 191 pass_struct_with_smart_ptr_by_const_rvalue_ref(std::move(S)); 192 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 193 } 194 195 void regioninvalidationWithinStructPassByPtr() { 196 StructWithSmartPtr S; 197 pass_struct_with_smart_ptr_by_ptr(&S); 198 S.P->foo(); // no-warning 199 } 200 201 void regioninvalidationWithinStructPassByConstPtr() { 202 StructWithSmartPtr S; 203 pass_struct_with_smart_ptr_by_const_ptr(&S); 204 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 205 } 206 207 void derefAfterAssignment() { 208 { 209 std::unique_ptr<A> P(new A()); 210 std::unique_ptr<A> Q; 211 Q = std::move(P); 212 Q->foo(); // no-warning 213 } 214 { 215 std::unique_ptr<A> P; 216 std::unique_ptr<A> Q; 217 Q = std::move(P); 218 // TODO: Fix test with expecting warning after '=' operator overloading modeling. 219 Q->foo(); // no-warning 220 } 221 } 222 223 void derefOnSwappedNullPtr() { 224 std::unique_ptr<A> P(new A()); 225 std::unique_ptr<A> PNull; 226 P.swap(PNull); 227 PNull->foo(); // No warning. 228 (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 229 } 230 231 void derefOnFirstStdSwappedNullPtr() { 232 std::unique_ptr<A> P; 233 std::unique_ptr<A> PNull; 234 std::swap(P, PNull); 235 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 236 } 237 238 void derefOnSecondStdSwappedNullPtr() { 239 std::unique_ptr<A> P; 240 std::unique_ptr<A> PNull; 241 std::swap(P, PNull); 242 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 243 } 244 245 void derefOnSwappedValidPtr() { 246 std::unique_ptr<A> P(new A()); 247 std::unique_ptr<A> PValid(new A()); 248 P.swap(PValid); 249 (*P).foo(); // No warning. 250 PValid->foo(); // No warning. 251 std::swap(P, PValid); 252 P->foo(); // No warning. 253 PValid->foo(); // No warning. 254 } 255