444 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config ipa=inlining -analyzer-config c++-allocator-inlining=true -verify -analyzer-config eagerly-assume=false %s2 3void clang_analyzer_eval(bool);4void clang_analyzer_checkInlined(bool);5 6typedef __typeof__(sizeof(int)) size_t;7extern "C" void *malloc(size_t);8 9// This is the standard placement new.10inline void* operator new(size_t, void* __p) throw()11{12 clang_analyzer_checkInlined(true);// expected-warning{{TRUE}}13 return __p;14}15 16 17class A {18public:19 int getZero() { return 0; }20 virtual int getNum() { return 0; }21};22 23void 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 33class One : public A {34public:35 virtual int getNum() { return 1; }36};37 38void 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 59namespace 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 85namespace 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 133namespace 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 181namespace 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 inlining197 // 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-warning204 }205 };206}207 208namespace 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 = 2237 };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 312namespace OperatorNew {313 class IntWrapper {314 public:315 int value;316 317 IntWrapper(int input) : value(input) {318 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}319 }320 };321 322 void test() {323 IntWrapper *obj = new IntWrapper(42);324 clang_analyzer_eval(obj->value == 42); // expected-warning{{TRUE}}325 delete obj;326 }327 328 void testPlacement() {329 IntWrapper *obj = static_cast<IntWrapper *>(malloc(sizeof(IntWrapper)));330 IntWrapper *alias = new (obj) IntWrapper(42);331 332 clang_analyzer_eval(alias == obj); // expected-warning{{TRUE}}333 334 clang_analyzer_eval(obj->value == 42); // expected-warning{{TRUE}}335 // Because malloc() was never free()d:336 // expected-warning@-2{{Potential leak of memory pointed to by 'alias'}}337 }338}339 340 341namespace VirtualWithSisterCasts {342 // This entire set of tests exercises casts from sister classes and343 // from classes outside the hierarchy, which can very much confuse344 // code that uses DynamicTypeInfo or needs to construct CXXBaseObjectRegions.345 // These examples used to cause crashes in +Asserts builds.346 struct Parent {347 virtual int foo();348 int x;349 };350 351 struct A : Parent {352 virtual int foo() { return 42; }353 };354 355 struct B : Parent {356 virtual int foo();357 };358 359 struct Grandchild : public A {};360 361 struct Unrelated {};362 363 void testDowncast(Parent *b) {364 A *a = (A *)(void *)b;365 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}366 367 a->x = 42;368 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}369 }370 371 void testRelated(B *b) {372 A *a = (A *)(void *)b;373 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}374 375 a->x = 42;376 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}377 }378 379 void testUnrelated(Unrelated *b) {380 A *a = (A *)(void *)b;381 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}382 383 a->x = 42;384 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}385 }386 387 void testCastViaNew(B *b) {388 Grandchild *g = new (b) Grandchild();389 clang_analyzer_eval(g->foo() == 42); // expected-warning{{TRUE}}390 391 g->x = 42;392 clang_analyzer_eval(g->x == 42); // expected-warning{{TRUE}}393 }394}395 396 397namespace QualifiedCalls {398 void test(One *object) {399 // This uses the One class from the top of the file.400 clang_analyzer_eval(object->getNum() == 1); // expected-warning{{UNKNOWN}}401 clang_analyzer_eval(object->One::getNum() == 1); // expected-warning{{TRUE}}402 clang_analyzer_eval(object->A::getNum() == 0); // expected-warning{{TRUE}}403 404 // getZero is non-virtual.405 clang_analyzer_eval(object->getZero() == 0); // expected-warning{{TRUE}}406 clang_analyzer_eval(object->One::getZero() == 0); // expected-warning{{TRUE}}407 clang_analyzer_eval(object->A::getZero() == 0); // expected-warning{{TRUE}}408}409}410 411 412namespace rdar12409977 {413 struct Base {414 int x;415 };416 417 struct Parent : public Base {418 virtual Parent *vGetThis();419 Parent *getThis() { return vGetThis(); }420 };421 422 struct Child : public Parent {423 virtual Child *vGetThis() { return this; }424 };425 426 void test() {427 Child obj;428 obj.x = 42;429 430 // Originally, calling a devirtualized method with a covariant return type431 // caused a crash because the return value had the wrong type. When we then432 // go to layer a CXXBaseObjectRegion on it, the base isn't a direct base of433 // the object region and we get an assertion failure.434 clang_analyzer_eval(obj.getThis()->x == 42); // expected-warning{{TRUE}}435 }436}437 438namespace bug16307 {439 void one_argument(int a) { }440 void call_with_less() {441 reinterpret_cast<void (*)()>(one_argument)(); // expected-warning{{Function taking 1 argument is called with fewer (0)}}442 }443}444