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