1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config ipa=inlining -analyzer-config c++-allocator-inlining=true -verify %s 2 3 void clang_analyzer_eval(bool); 4 void clang_analyzer_checkInlined(bool); 5 6 typedef __typeof__(sizeof(int)) size_t; 7 extern "C" void *malloc(size_t); 8 9 // This is the standard placement new. 10 inline void* operator new(size_t, void* __p) throw() 11 { 12 clang_analyzer_checkInlined(true);// expected-warning{{TRUE}} 13 return __p; 14 } 15 16 17 class A { 18 public: 19 int getZero() { return 0; } 20 virtual int getNum() { return 0; } 21 }; 22 23 void test(A &a) { 24 clang_analyzer_eval(a.getZero() == 0); // expected-warning{{TRUE}} 25 clang_analyzer_eval(a.getNum() == 0); // expected-warning{{UNKNOWN}} 26 27 A copy(a); 28 clang_analyzer_eval(copy.getZero() == 0); // expected-warning{{TRUE}} 29 clang_analyzer_eval(copy.getNum() == 0); // expected-warning{{TRUE}} 30 } 31 32 33 class One : public A { 34 public: 35 virtual int getNum() { return 1; } 36 }; 37 38 void testPathSensitivity(int x) { 39 A a; 40 One b; 41 42 A *ptr; 43 switch (x) { 44 case 0: 45 ptr = &a; 46 break; 47 case 1: 48 ptr = &b; 49 break; 50 default: 51 return; 52 } 53 54 // This should be true on both branches. 55 clang_analyzer_eval(ptr->getNum() == x); // expected-warning {{TRUE}} 56 } 57 58 59 namespace PureVirtualParent { 60 class Parent { 61 public: 62 virtual int pureVirtual() const = 0; 63 int callVirtual() const { 64 return pureVirtual(); 65 } 66 }; 67 68 class Child : public Parent { 69 public: 70 virtual int pureVirtual() const { 71 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} 72 return 42; 73 } 74 }; 75 76 void testVirtual() { 77 Child x; 78 79 clang_analyzer_eval(x.pureVirtual() == 42); // expected-warning{{TRUE}} 80 clang_analyzer_eval(x.callVirtual() == 42); // expected-warning{{TRUE}} 81 } 82 } 83 84 85 namespace PR13569 { 86 class Parent { 87 protected: 88 int m_parent; 89 virtual int impl() const = 0; 90 91 Parent() : m_parent(0) {} 92 93 public: 94 int interface() const { 95 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} 96 return impl(); 97 } 98 }; 99 100 class Child : public Parent { 101 protected: 102 virtual int impl() const { 103 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} 104 return m_parent + m_child; 105 } 106 107 public: 108 Child() : m_child(0) {} 109 110 int m_child; 111 }; 112 113 void testVirtual() { 114 Child x; 115 x.m_child = 42; 116 117 // Don't crash when inlining and devirtualizing. 118 x.interface(); 119 } 120 121 122 class Grandchild : public Child {}; 123 124 void testDevirtualizeToMiddle() { 125 Grandchild x; 126 x.m_child = 42; 127 128 // Don't crash when inlining and devirtualizing. 129 x.interface(); 130 } 131 } 132 133 namespace PR13569_virtual { 134 class Parent { 135 protected: 136 int m_parent; 137 virtual int impl() const = 0; 138 139 Parent() : m_parent(0) {} 140 141 public: 142 int interface() const { 143 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} 144 return impl(); 145 } 146 }; 147 148 class Child : virtual public Parent { 149 protected: 150 virtual int impl() const { 151 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} 152 return m_parent + m_child; 153 } 154 155 public: 156 Child() : m_child(0) {} 157 158 int m_child; 159 }; 160 161 void testVirtual() { 162 Child x; 163 x.m_child = 42; 164 165 // Don't crash when inlining and devirtualizing. 166 x.interface(); 167 } 168 169 170 class Grandchild : virtual public Child {}; 171 172 void testDevirtualizeToMiddle() { 173 Grandchild x; 174 x.m_child = 42; 175 176 // Don't crash when inlining and devirtualizing. 177 x.interface(); 178 } 179 } 180 181 namespace Invalidation { 182 struct X { 183 void touch(int &x) const { 184 x = 0; 185 } 186 187 void touch2(int &x) const; 188 189 virtual void touchV(int &x) const { 190 x = 0; 191 } 192 193 virtual void touchV2(int &x) const; 194 195 int test() const { 196 // We were accidentally not invalidating under inlining 197 // at one point for virtual methods with visible definitions. 198 int a, b, c, d; 199 touch(a); 200 touch2(b); 201 touchV(c); 202 touchV2(d); 203 return a + b + c + d; // no-warning 204 } 205 }; 206 } 207 208 namespace DefaultArgs { 209 int takesDefaultArgs(int i = 42) { 210 return -i; 211 } 212 213 void testFunction() { 214 clang_analyzer_eval(takesDefaultArgs(1) == -1); // expected-warning{{TRUE}} 215 clang_analyzer_eval(takesDefaultArgs() == -42); // expected-warning{{TRUE}} 216 } 217 218 class Secret { 219 public: 220 static const int value = 40 + 2; 221 int get(int i = value) { 222 return i; 223 } 224 }; 225 226 void testMethod() { 227 Secret obj; 228 clang_analyzer_eval(obj.get(1) == 1); // expected-warning{{TRUE}} 229 clang_analyzer_eval(obj.get() == 42); // expected-warning{{TRUE}} 230 clang_analyzer_eval(Secret::value == 42); // expected-warning{{TRUE}} 231 } 232 233 enum ABC { 234 A = 0, 235 B = 1, 236 C = 2 237 }; 238 239 int enumUser(ABC input = B) { 240 return static_cast<int>(input); 241 } 242 243 void testEnum() { 244 clang_analyzer_eval(enumUser(C) == 2); // expected-warning{{TRUE}} 245 clang_analyzer_eval(enumUser() == 1); // expected-warning{{TRUE}} 246 } 247 248 249 int exprUser(int input = 2 * 4) { 250 return input; 251 } 252 253 int complicatedExprUser(int input = 2 * Secret::value) { 254 return input; 255 } 256 257 void testExprs() { 258 clang_analyzer_eval(exprUser(1) == 1); // expected-warning{{TRUE}} 259 clang_analyzer_eval(exprUser() == 8); // expected-warning{{TRUE}} 260 261 clang_analyzer_eval(complicatedExprUser(1) == 1); // expected-warning{{TRUE}} 262 clang_analyzer_eval(complicatedExprUser() == 84); // expected-warning{{TRUE}} 263 } 264 265 int defaultReference(const int &input = 42) { 266 return -input; 267 } 268 int defaultReferenceZero(const int &input = 0) { 269 return -input; 270 } 271 272 void testReference() { 273 clang_analyzer_eval(defaultReference(1) == -1); // expected-warning{{TRUE}} 274 clang_analyzer_eval(defaultReference() == -42); // expected-warning{{TRUE}} 275 276 clang_analyzer_eval(defaultReferenceZero(1) == -1); // expected-warning{{TRUE}} 277 clang_analyzer_eval(defaultReferenceZero() == 0); // expected-warning{{TRUE}} 278 } 279 280 double defaultFloatReference(const double &i = 42) { 281 return -i; 282 } 283 double defaultFloatReferenceZero(const double &i = 0) { 284 return -i; 285 } 286 287 void testFloatReference() { 288 clang_analyzer_eval(defaultFloatReference(1) == -1); // expected-warning{{UNKNOWN}} 289 clang_analyzer_eval(defaultFloatReference() == -42); // expected-warning{{UNKNOWN}} 290 291 clang_analyzer_eval(defaultFloatReferenceZero(1) == -1); // expected-warning{{UNKNOWN}} 292 clang_analyzer_eval(defaultFloatReferenceZero() == 0); // expected-warning{{UNKNOWN}} 293 } 294 295 char defaultString(const char *s = "abc") { 296 return s[1]; 297 } 298 299 void testString() { 300 clang_analyzer_eval(defaultString("xyz") == 'y'); // expected-warning{{TRUE}} 301 clang_analyzer_eval(defaultString() == 'b'); // expected-warning{{TRUE}} 302 } 303 304 const void * const void_string = "abc"; 305 306 void testBitcastedString() { 307 clang_analyzer_eval(0 != void_string); // expected-warning{{TRUE}} 308 clang_analyzer_eval('b' == ((char *)void_string)[1]); // expected-warning{{TRUE}} 309 } 310 } 311 312 namespace OperatorNew { 313 class IntWrapper { 314 public: 315 int value; 316 317 IntWrapper(int input) : value(input) { 318 // We don't want this constructor to be inlined unless we can actually 319 // use the proper region for operator new. 320 // See PR12014 and <rdar://problem/12180598>. 321 clang_analyzer_checkInlined(false); // no-warning 322 } 323 }; 324 325 void test() { 326 IntWrapper *obj = new IntWrapper(42); 327 // should be TRUE 328 clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}} 329 delete obj; 330 } 331 332 void testPlacement() { 333 IntWrapper *obj = static_cast<IntWrapper *>(malloc(sizeof(IntWrapper))); 334 IntWrapper *alias = new (obj) IntWrapper(42); 335 336 clang_analyzer_eval(alias == obj); // expected-warning{{TRUE}} 337 338 // should be TRUE 339 clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}} 340 } 341 } 342 343 344 namespace VirtualWithSisterCasts { 345 // This entire set of tests exercises casts from sister classes and 346 // from classes outside the hierarchy, which can very much confuse 347 // code that uses DynamicTypeInfo or needs to construct CXXBaseObjectRegions. 348 // These examples used to cause crashes in +Asserts builds. 349 struct Parent { 350 virtual int foo(); 351 int x; 352 }; 353 354 struct A : Parent { 355 virtual int foo() { return 42; } 356 }; 357 358 struct B : Parent { 359 virtual int foo(); 360 }; 361 362 struct Grandchild : public A {}; 363 364 struct Unrelated {}; 365 366 void testDowncast(Parent *b) { 367 A *a = (A *)(void *)b; 368 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}} 369 370 a->x = 42; 371 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}} 372 } 373 374 void testRelated(B *b) { 375 A *a = (A *)(void *)b; 376 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}} 377 378 a->x = 42; 379 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}} 380 } 381 382 void testUnrelated(Unrelated *b) { 383 A *a = (A *)(void *)b; 384 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}} 385 386 a->x = 42; 387 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}} 388 } 389 390 void testCastViaNew(B *b) { 391 Grandchild *g = new (b) Grandchild(); 392 clang_analyzer_eval(g->foo() == 42); // expected-warning{{TRUE}} 393 394 g->x = 42; 395 clang_analyzer_eval(g->x == 42); // expected-warning{{TRUE}} 396 } 397 } 398 399 400 namespace QualifiedCalls { 401 void test(One *object) { 402 // This uses the One class from the top of the file. 403 clang_analyzer_eval(object->getNum() == 1); // expected-warning{{UNKNOWN}} 404 clang_analyzer_eval(object->One::getNum() == 1); // expected-warning{{TRUE}} 405 clang_analyzer_eval(object->A::getNum() == 0); // expected-warning{{TRUE}} 406 407 // getZero is non-virtual. 408 clang_analyzer_eval(object->getZero() == 0); // expected-warning{{TRUE}} 409 clang_analyzer_eval(object->One::getZero() == 0); // expected-warning{{TRUE}} 410 clang_analyzer_eval(object->A::getZero() == 0); // expected-warning{{TRUE}} 411 } 412 } 413 414 415 namespace rdar12409977 { 416 struct Base { 417 int x; 418 }; 419 420 struct Parent : public Base { 421 virtual Parent *vGetThis(); 422 Parent *getThis() { return vGetThis(); } 423 }; 424 425 struct Child : public Parent { 426 virtual Child *vGetThis() { return this; } 427 }; 428 429 void test() { 430 Child obj; 431 obj.x = 42; 432 433 // Originally, calling a devirtualized method with a covariant return type 434 // caused a crash because the return value had the wrong type. When we then 435 // go to layer a CXXBaseObjectRegion on it, the base isn't a direct base of 436 // the object region and we get an assertion failure. 437 clang_analyzer_eval(obj.getThis()->x == 42); // expected-warning{{TRUE}} 438 } 439 } 440 441 namespace bug16307 { 442 void one_argument(int a) { } 443 void call_with_less() { 444 reinterpret_cast<void (*)()>(one_argument)(); // expected-warning{{Function taking 1 argument}} 445 } 446 } 447