1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.UninitializedObject \ 2 // RUN: -analyzer-config optin.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \ 3 // RUN: -analyzer-config optin.cplusplus.UninitializedObject:IgnoreGuardedFields=true \ 4 // RUN: -std=c++11 -verify %s 5 6 //===----------------------------------------------------------------------===// 7 // Helper functions for tests. 8 //===----------------------------------------------------------------------===// 9 10 [[noreturn]] void halt(); 11 12 void assert(int b) { 13 if (!b) 14 halt(); 15 } 16 17 int rand(); 18 19 //===----------------------------------------------------------------------===// 20 // Tests for fields properly guarded by asserts. 21 //===----------------------------------------------------------------------===// 22 23 class NoUnguardedFieldsTest { 24 public: 25 enum Kind { 26 V, 27 A 28 }; 29 30 private: 31 int Volume, Area; 32 Kind K; 33 34 public: 35 NoUnguardedFieldsTest(Kind K) : K(K) { 36 switch (K) { 37 case V: 38 Volume = 0; 39 break; 40 case A: 41 Area = 0; 42 break; 43 } 44 } 45 46 void operator-() { 47 assert(K == Kind::A); 48 (void)Area; 49 } 50 51 void operator+() { 52 assert(K == Kind::V); 53 (void)Volume; 54 } 55 }; 56 57 void fNoUnguardedFieldsTest() { 58 NoUnguardedFieldsTest T1(NoUnguardedFieldsTest::Kind::A); 59 NoUnguardedFieldsTest T2(NoUnguardedFieldsTest::Kind::V); 60 } 61 62 class NoUngardedFieldsNoReturnFuncCalledTest { 63 public: 64 enum Kind { 65 V, 66 A 67 }; 68 69 private: 70 int Volume, Area; 71 Kind K; 72 73 public: 74 NoUngardedFieldsNoReturnFuncCalledTest(Kind K) : K(K) { 75 switch (K) { 76 case V: 77 Volume = 0; 78 break; 79 case A: 80 Area = 0; 81 break; 82 } 83 } 84 85 void operator-() { 86 halt(); 87 (void)Area; 88 } 89 90 void operator+() { 91 halt(); 92 (void)Volume; 93 } 94 }; 95 96 void fNoUngardedFieldsNoReturnFuncCalledTest() { 97 NoUngardedFieldsNoReturnFuncCalledTest 98 T1(NoUngardedFieldsNoReturnFuncCalledTest::Kind::A); 99 NoUngardedFieldsNoReturnFuncCalledTest 100 T2(NoUngardedFieldsNoReturnFuncCalledTest::Kind::V); 101 } 102 103 class NoUnguardedFieldsWithUndefMethodTest { 104 public: 105 enum Kind { 106 V, 107 A 108 }; 109 110 private: 111 int Volume, Area; 112 Kind K; 113 114 public: 115 NoUnguardedFieldsWithUndefMethodTest(Kind K) : K(K) { 116 switch (K) { 117 case V: 118 Volume = 0; 119 break; 120 case A: 121 Area = 0; 122 break; 123 } 124 } 125 126 void operator-() { 127 assert(K == Kind::A); 128 (void)Area; 129 } 130 131 void operator+() { 132 assert(K == Kind::V); 133 (void)Volume; 134 } 135 136 // We're checking method definitions for guards, so this is a no-crash test 137 // whether we handle methods without definitions. 138 void methodWithoutDefinition(); 139 }; 140 141 void fNoUnguardedFieldsWithUndefMethodTest() { 142 NoUnguardedFieldsWithUndefMethodTest 143 T1(NoUnguardedFieldsWithUndefMethodTest::Kind::A); 144 NoUnguardedFieldsWithUndefMethodTest 145 T2(NoUnguardedFieldsWithUndefMethodTest::Kind::V); 146 } 147 148 class UnguardedFieldThroughMethodTest { 149 public: 150 enum Kind { 151 V, 152 A 153 }; 154 155 private: 156 int Volume, Area; // expected-note {{uninitialized field 'this->Volume'}} 157 Kind K; 158 159 public: 160 UnguardedFieldThroughMethodTest(Kind K) : K(K) { 161 switch (K) { 162 case V: 163 Volume = 0; 164 break; 165 case A: 166 Area = 0; 167 break; // expected-warning {{1 uninitialized field}} 168 } 169 } 170 171 void operator-() { 172 assert(K == Kind::A); 173 (void)Area; 174 } 175 176 void operator+() { 177 (void)Volume; 178 } 179 }; 180 181 void fUnguardedFieldThroughMethodTest() { 182 UnguardedFieldThroughMethodTest T1(UnguardedFieldThroughMethodTest::Kind::A); 183 } 184 185 class UnguardedPublicFieldsTest { 186 public: 187 enum Kind { 188 V, 189 A 190 }; 191 192 public: 193 // Note that fields are public. 194 int Volume, Area; // expected-note {{uninitialized field 'this->Volume'}} 195 Kind K; 196 197 public: 198 UnguardedPublicFieldsTest(Kind K) : K(K) { 199 switch (K) { 200 case V: 201 Volume = 0; 202 break; 203 case A: 204 Area = 0; 205 break; // expected-warning {{1 uninitialized field}} 206 } 207 } 208 209 void operator-() { 210 assert(K == Kind::A); 211 (void)Area; 212 } 213 214 void operator+() { 215 assert(K == Kind::V); 216 (void)Volume; 217 } 218 }; 219 220 void fUnguardedPublicFieldsTest() { 221 UnguardedPublicFieldsTest T1(UnguardedPublicFieldsTest::Kind::A); 222 } 223 224 //===----------------------------------------------------------------------===// 225 // Highlights of some false negatives due to syntactic checking. 226 //===----------------------------------------------------------------------===// 227 228 class UnguardedFalseNegativeTest1 { 229 public: 230 enum Kind { 231 V, 232 A 233 }; 234 235 private: 236 int Volume, Area; 237 Kind K; 238 239 public: 240 UnguardedFalseNegativeTest1(Kind K) : K(K) { 241 switch (K) { 242 case V: 243 Volume = 0; 244 break; 245 case A: 246 Area = 0; 247 break; 248 } 249 } 250 251 void operator-() { 252 if (rand()) 253 assert(K == Kind::A); 254 (void)Area; 255 } 256 257 void operator+() { 258 if (rand()) 259 assert(K == Kind::V); 260 (void)Volume; 261 } 262 }; 263 264 void fUnguardedFalseNegativeTest1() { 265 UnguardedFalseNegativeTest1 T1(UnguardedFalseNegativeTest1::Kind::A); 266 } 267 268 class UnguardedFalseNegativeTest2 { 269 public: 270 enum Kind { 271 V, 272 A 273 }; 274 275 private: 276 int Volume, Area; 277 Kind K; 278 279 public: 280 UnguardedFalseNegativeTest2(Kind K) : K(K) { 281 switch (K) { 282 case V: 283 Volume = 0; 284 break; 285 case A: 286 Area = 0; 287 break; 288 } 289 } 290 291 void operator-() { 292 assert(rand()); 293 (void)Area; 294 } 295 296 void operator+() { 297 assert(rand()); 298 (void)Volume; 299 } 300 }; 301 302 void fUnguardedFalseNegativeTest2() { 303 UnguardedFalseNegativeTest2 T1(UnguardedFalseNegativeTest2::Kind::A); 304 } 305 306 //===----------------------------------------------------------------------===// 307 // Tests for other guards. These won't be as thorough, as other guards are 308 // matched the same way as asserts, so if they are recognized, they are expected 309 // to work as well as asserts do. 310 // 311 // None of these tests expect warnings, since the flag works correctly if these 312 // fields are regarded properly guarded. 313 //===----------------------------------------------------------------------===// 314 315 class IfGuardedFieldsTest { 316 public: 317 enum Kind { 318 V, 319 A 320 }; 321 322 private: 323 int Volume, Area; 324 Kind K; 325 326 public: 327 IfGuardedFieldsTest(Kind K) : K(K) { 328 switch (K) { 329 case V: 330 Volume = 0; 331 break; 332 case A: 333 Area = 0; 334 break; 335 } 336 } 337 338 void operator-() { 339 if (K != Kind::A) 340 return; 341 (void)Area; 342 } 343 344 void operator+() { 345 if (K != Kind::V) 346 return; 347 (void)Volume; 348 } 349 }; 350 351 void fIfGuardedFieldsTest() { 352 IfGuardedFieldsTest T1(IfGuardedFieldsTest::Kind::A); 353 IfGuardedFieldsTest T2(IfGuardedFieldsTest::Kind::V); 354 } 355 356 class SwitchGuardedFieldsTest { 357 public: 358 enum Kind { 359 V, 360 A 361 }; 362 363 private: 364 int Volume, Area; 365 Kind K; 366 367 public: 368 SwitchGuardedFieldsTest(Kind K) : K(K) { 369 switch (K) { 370 case V: 371 Volume = 0; 372 break; 373 case A: 374 Area = 0; 375 break; 376 } 377 } 378 379 int operator-() { 380 switch (K) { 381 case Kind::A: 382 return Area; 383 case Kind::V: 384 return -1; 385 } 386 } 387 388 int operator+() { 389 switch (K) { 390 case Kind::A: 391 return Area; 392 case Kind::V: 393 return -1; 394 } 395 } 396 }; 397 398 void fSwitchGuardedFieldsTest() { 399 SwitchGuardedFieldsTest T1(SwitchGuardedFieldsTest::Kind::A); 400 SwitchGuardedFieldsTest T2(SwitchGuardedFieldsTest::Kind::V); 401 } 402 403 class ConditionalOperatorGuardedFieldsTest { 404 public: 405 enum Kind { 406 V, 407 A 408 }; 409 410 private: 411 int Volume, Area; 412 Kind K; 413 414 public: 415 ConditionalOperatorGuardedFieldsTest(Kind K) : K(K) { 416 switch (K) { 417 case V: 418 Volume = 0; 419 break; 420 case A: 421 Area = 0; 422 break; 423 } 424 } 425 426 int operator-() { 427 return K == Kind::A ? Area : -1; 428 } 429 430 int operator+() { 431 return K == Kind::V ? Volume : -1; 432 } 433 }; 434 435 void fConditionalOperatorGuardedFieldsTest() { 436 ConditionalOperatorGuardedFieldsTest 437 T1(ConditionalOperatorGuardedFieldsTest::Kind::A); 438 ConditionalOperatorGuardedFieldsTest 439 T2(ConditionalOperatorGuardedFieldsTest::Kind::V); 440 } 441