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 305 namespace OperatorNew { 306 class IntWrapper { 307 public: 308 int value; 309 310 IntWrapper(int input) : value(input) { 311 // We don't want this constructor to be inlined unless we can actually 312 // use the proper region for operator new. 313 // See PR12014 and <rdar://problem/12180598>. 314 clang_analyzer_checkInlined(false); // no-warning 315 } 316 }; 317 318 void test() { 319 IntWrapper *obj = new IntWrapper(42); 320 // should be TRUE 321 clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}} 322 delete obj; 323 } 324 325 void testPlacement() { 326 IntWrapper *obj = static_cast<IntWrapper *>(malloc(sizeof(IntWrapper))); 327 IntWrapper *alias = new (obj) IntWrapper(42); 328 329 clang_analyzer_eval(alias == obj); // expected-warning{{TRUE}} 330 331 // should be TRUE 332 clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}} 333 } 334 } 335 336 337 namespace VirtualWithSisterCasts { 338 // This entire set of tests exercises casts from sister classes and 339 // from classes outside the hierarchy, which can very much confuse 340 // code that uses DynamicTypeInfo or needs to construct CXXBaseObjectRegions. 341 // These examples used to cause crashes in +Asserts builds. 342 struct Parent { 343 virtual int foo(); 344 int x; 345 }; 346 347 struct A : Parent { 348 virtual int foo() { return 42; } 349 }; 350 351 struct B : Parent { 352 virtual int foo(); 353 }; 354 355 struct Grandchild : public A {}; 356 357 struct Unrelated {}; 358 359 void testDowncast(Parent *b) { 360 A *a = (A *)(void *)b; 361 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}} 362 363 a->x = 42; 364 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}} 365 } 366 367 void testRelated(B *b) { 368 A *a = (A *)(void *)b; 369 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}} 370 371 a->x = 42; 372 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}} 373 } 374 375 void testUnrelated(Unrelated *b) { 376 A *a = (A *)(void *)b; 377 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}} 378 379 a->x = 42; 380 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}} 381 } 382 383 void testCastViaNew(B *b) { 384 Grandchild *g = new (b) Grandchild(); 385 clang_analyzer_eval(g->foo() == 42); // expected-warning{{TRUE}} 386 387 g->x = 42; 388 clang_analyzer_eval(g->x == 42); // expected-warning{{TRUE}} 389 } 390 } 391 392 393 namespace QualifiedCalls { 394 void test(One *object) { 395 // This uses the One class from the top of the file. 396 clang_analyzer_eval(object->getNum() == 1); // expected-warning{{UNKNOWN}} 397 clang_analyzer_eval(object->One::getNum() == 1); // expected-warning{{TRUE}} 398 clang_analyzer_eval(object->A::getNum() == 0); // expected-warning{{TRUE}} 399 400 // getZero is non-virtual. 401 clang_analyzer_eval(object->getZero() == 0); // expected-warning{{TRUE}} 402 clang_analyzer_eval(object->One::getZero() == 0); // expected-warning{{TRUE}} 403 clang_analyzer_eval(object->A::getZero() == 0); // expected-warning{{TRUE}} 404 } 405 } 406 407 408 namespace rdar12409977 { 409 struct Base { 410 int x; 411 }; 412 413 struct Parent : public Base { 414 virtual Parent *vGetThis(); 415 Parent *getThis() { return vGetThis(); } 416 }; 417 418 struct Child : public Parent { 419 virtual Child *vGetThis() { return this; } 420 }; 421 422 void test() { 423 Child obj; 424 obj.x = 42; 425 426 // Originally, calling a devirtualized method with a covariant return type 427 // caused a crash because the return value had the wrong type. When we then 428 // go to layer a CXXBaseObjectRegion on it, the base isn't a direct base of 429 // the object region and we get an assertion failure. 430 clang_analyzer_eval(obj.getThis()->x == 42); // expected-warning{{TRUE}} 431 } 432 } 433 434 namespace bug16307 { 435 void one_argument(int a) { } 436 void call_with_less() { 437 reinterpret_cast<void (*)()>(one_argument)(); // expected-warning{{Function taking 1 argument}} 438 } 439 } 440