brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.5 KiB · 2b31460 Raw
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