brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.3 KiB · 4aca1d8 Raw
117 lines · cpp
1// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify -analyzer-config eagerly-assume=false %s2 3void clang_analyzer_eval(bool);4void clang_analyzer_dump(int);5 6typedef __typeof__(sizeof(int)) size_t;7 8void *conjure();9void exit(int);10 11struct S;12 13S *global_s;14 15// Recursive operator kinda placement new.16void *operator new(size_t size, S *place);17 18enum class ConstructionKind : char {19  Garbage,20  Recursive21};22 23struct S {24public:25  int x;26  S(): x(1) {}27  S(int y): x(y) {}28 29  S(ConstructionKind k) {30    switch (k) {31    case ConstructionKind::Recursive: { // Call one more operator new 'r'ecursively.32      S *s = new (nullptr) S(5);33      x = s->x + 1;34      global_s = s;35      return;36    }37    case ConstructionKind::Garbage: {38      // Leaves garbage in 'x'.39    }40    }41  }42  ~S() {}43};44 45// Do not try this at home!46void *operator new(size_t size, S *place) {47  if (!place)48    return new S();49  return place;50}51 52void testThatCharConstructorIndeedYieldsGarbage() {53  S *s = new S(ConstructionKind::Garbage);54  clang_analyzer_eval(s->x == 0); // expected-warning{{The left operand of '==' is a garbage value [core.UndefinedBinaryOperatorResult]}}55  clang_analyzer_eval(s->x == 1);56  s->x += 1;57  delete s;58}59 60 61void testChainedOperatorNew() {62  S *s;63  // * Evaluate standard new.64  // * Evaluate constructor S(3).65  // * Bind value for standard new.66  // * Evaluate our custom new.67  // * Evaluate constructor S(Garbage).68  // * Bind value for our custom new.69  s = new (new S(3)) S(ConstructionKind::Garbage);70  clang_analyzer_eval(s->x == 3); // expected-warning{{TRUE}}71  // expected-warning@+9{{Potential leak of memory pointed to by 's'}}72 73  // * Evaluate standard new.74  // * Evaluate constructor S(Garbage).75  // * Bind value for standard new.76  // * Evaluate our custom new.77  // * Evaluate constructor S(4).78  // * Bind value for our custom new.79  s = new (new S(ConstructionKind::Garbage)) S(4);80  clang_analyzer_eval(s->x == 4); // expected-warning{{TRUE}}81  delete s;82 83  // -> Enter our custom new (nullptr).84  //   * Evaluate standard new.85  //   * Inline constructor S().86  //   * Bind value for standard new.87  // <- Exit our custom new (nullptr).88  // * Evaluate constructor S(Garbage).89  // * Bind value for our custom new.90  s = new (nullptr) S(ConstructionKind::Garbage);91  clang_analyzer_eval(s->x == 1); // expected-warning{{TRUE}}92  delete s;93 94  // -> Enter our custom new (nullptr).95  //   * Evaluate standard new.96  //   * Inline constructor S().97  //   * Bind value for standard new.98  // <- Exit our custom new (nullptr).99  // -> Enter constructor S(Recursive).100  //   -> Enter our custom new (nullptr).101  //     * Evaluate standard new.102  //     * Inline constructor S().103  //     * Bind value for standard new.104  //   <- Exit our custom new (nullptr).105  //   * Evaluate constructor S(5).106  //   * Bind value for our custom new (nullptr).107  //   * Assign that value to global_s.108  // <- Exit constructor S(Recursive).109  // * Bind value for our custom new (nullptr).110  global_s = nullptr;111  s = new (nullptr) S(ConstructionKind::Recursive);112  clang_analyzer_eval(global_s); // expected-warning{{TRUE}}113  clang_analyzer_eval(global_s->x == 5); // expected-warning{{TRUE}}114  clang_analyzer_eval(s->x == 6); // expected-warning{{TRUE}}115  delete s;116}117