441 lines · cpp
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 %s5 6//===----------------------------------------------------------------------===//7// Helper functions for tests.8//===----------------------------------------------------------------------===//9 10[[noreturn]] void halt();11 12void assert(int b) {13 if (!b)14 halt();15}16 17int rand();18 19//===----------------------------------------------------------------------===//20// Tests for fields properly guarded by asserts.21//===----------------------------------------------------------------------===//22 23class NoUnguardedFieldsTest {24public:25 enum Kind {26 V,27 A28 };29 30private:31 int Volume, Area;32 Kind K;33 34public: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 57void fNoUnguardedFieldsTest() {58 NoUnguardedFieldsTest T1(NoUnguardedFieldsTest::Kind::A);59 NoUnguardedFieldsTest T2(NoUnguardedFieldsTest::Kind::V);60}61 62class NoUngardedFieldsNoReturnFuncCalledTest {63public:64 enum Kind {65 V,66 A67 };68 69private:70 int Volume, Area;71 Kind K;72 73public: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 96void fNoUngardedFieldsNoReturnFuncCalledTest() {97 NoUngardedFieldsNoReturnFuncCalledTest98 T1(NoUngardedFieldsNoReturnFuncCalledTest::Kind::A);99 NoUngardedFieldsNoReturnFuncCalledTest100 T2(NoUngardedFieldsNoReturnFuncCalledTest::Kind::V);101}102 103class NoUnguardedFieldsWithUndefMethodTest {104public:105 enum Kind {106 V,107 A108 };109 110private:111 int Volume, Area;112 Kind K;113 114public: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 test137 // whether we handle methods without definitions.138 void methodWithoutDefinition();139};140 141void fNoUnguardedFieldsWithUndefMethodTest() {142 NoUnguardedFieldsWithUndefMethodTest143 T1(NoUnguardedFieldsWithUndefMethodTest::Kind::A);144 NoUnguardedFieldsWithUndefMethodTest145 T2(NoUnguardedFieldsWithUndefMethodTest::Kind::V);146}147 148class UnguardedFieldThroughMethodTest {149public:150 enum Kind {151 V,152 A153 };154 155private:156 int Volume, Area; // expected-note {{uninitialized field 'this->Volume'}}157 Kind K;158 159public: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 181void fUnguardedFieldThroughMethodTest() {182 UnguardedFieldThroughMethodTest T1(UnguardedFieldThroughMethodTest::Kind::A);183}184 185class UnguardedPublicFieldsTest {186public:187 enum Kind {188 V,189 A190 };191 192public:193 // Note that fields are public.194 int Volume, Area; // expected-note {{uninitialized field 'this->Volume'}}195 Kind K;196 197public: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 220void fUnguardedPublicFieldsTest() {221 UnguardedPublicFieldsTest T1(UnguardedPublicFieldsTest::Kind::A);222}223 224//===----------------------------------------------------------------------===//225// Highlights of some false negatives due to syntactic checking.226//===----------------------------------------------------------------------===//227 228class UnguardedFalseNegativeTest1 {229public:230 enum Kind {231 V,232 A233 };234 235private:236 int Volume, Area;237 Kind K;238 239public: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 264void fUnguardedFalseNegativeTest1() {265 UnguardedFalseNegativeTest1 T1(UnguardedFalseNegativeTest1::Kind::A);266}267 268class UnguardedFalseNegativeTest2 {269public:270 enum Kind {271 V,272 A273 };274 275private:276 int Volume, Area;277 Kind K;278 279public: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 302void fUnguardedFalseNegativeTest2() {303 UnguardedFalseNegativeTest2 T1(UnguardedFalseNegativeTest2::Kind::A);304}305 306//===----------------------------------------------------------------------===//307// Tests for other guards. These won't be as thorough, as other guards are308// matched the same way as asserts, so if they are recognized, they are expected309// to work as well as asserts do.310//311// None of these tests expect warnings, since the flag works correctly if these312// fields are regarded properly guarded.313//===----------------------------------------------------------------------===//314 315class IfGuardedFieldsTest {316public:317 enum Kind {318 V,319 A320 };321 322private:323 int Volume, Area;324 Kind K;325 326public: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 351void fIfGuardedFieldsTest() {352 IfGuardedFieldsTest T1(IfGuardedFieldsTest::Kind::A);353 IfGuardedFieldsTest T2(IfGuardedFieldsTest::Kind::V);354}355 356class SwitchGuardedFieldsTest {357public:358 enum Kind {359 V,360 A361 };362 363private:364 int Volume, Area;365 Kind K;366 367public: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 398void fSwitchGuardedFieldsTest() {399 SwitchGuardedFieldsTest T1(SwitchGuardedFieldsTest::Kind::A);400 SwitchGuardedFieldsTest T2(SwitchGuardedFieldsTest::Kind::V);401}402 403class ConditionalOperatorGuardedFieldsTest {404public:405 enum Kind {406 V,407 A408 };409 410private:411 int Volume, Area;412 Kind K;413 414public: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 435void fConditionalOperatorGuardedFieldsTest() {436 ConditionalOperatorGuardedFieldsTest437 T1(ConditionalOperatorGuardedFieldsTest::Kind::A);438 ConditionalOperatorGuardedFieldsTest439 T2(ConditionalOperatorGuardedFieldsTest::Kind::V);440}441