112 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.ArrayDelete -std=c++11 -verify -analyzer-output=text %s2 3struct Base {4 virtual ~Base() = default;5};6 7struct Derived : public Base {};8 9struct DoubleDerived : public Derived {};10 11Derived *get();12 13Base *create() {14 Base *b = new Derived[3]; // expected-note{{Casting from 'Derived' to 'Base' here}}15 return b;16}17 18void sink(Base *b) {19 delete[] b; // expected-warning{{Deleting an array of 'Derived' objects as their base class 'Base' is undefined}}20 // expected-note@-1{{Deleting an array of 'Derived' objects as their base class 'Base' is undefined}}21}22 23void sink_cast(Base *b) {24 delete[] static_cast<Derived*>(b); // no-warning25}26 27void sink_derived(Derived *d) {28 delete[] d; // no-warning29}30 31void same_function() {32 Base *sd = new Derived[10]; // expected-note{{Casting from 'Derived' to 'Base' here}}33 delete[] sd; // expected-warning{{Deleting an array of 'Derived' objects as their base class 'Base' is undefined}}34 // expected-note@-1{{Deleting an array of 'Derived' objects as their base class 'Base' is undefined}}35 36 Base *dd = new DoubleDerived[10]; // expected-note{{Casting from 'DoubleDerived' to 'Base' here}}37 delete[] dd; // expected-warning{{Deleting an array of 'DoubleDerived' objects as their base class 'Base' is undefined}}38 // expected-note@-1{{Deleting an array of 'DoubleDerived' objects as their base class 'Base' is undefined}}39}40 41void different_function() {42 Base *assigned = get(); // expected-note{{Casting from 'Derived' to 'Base' here}}43 delete[] assigned; // expected-warning{{Deleting an array of 'Derived' objects as their base class 'Base' is undefined}}44 // expected-note@-1{{Deleting an array of 'Derived' objects as their base class 'Base' is undefined}}45 46 Base *indirect;47 indirect = get(); // expected-note{{Casting from 'Derived' to 'Base' here}}48 delete[] indirect; // expected-warning{{Deleting an array of 'Derived' objects as their base class 'Base' is undefined}}49 // expected-note@-1{{Deleting an array of 'Derived' objects as their base class 'Base' is undefined}}50 51 Base *created = create(); // expected-note{{Calling 'create'}}52 // expected-note@-1{{Returning from 'create'}}53 delete[] created; // expected-warning{{Deleting an array of 'Derived' objects as their base class 'Base' is undefined}}54 // expected-note@-1{{Deleting an array of 'Derived' objects as their base class 'Base' is undefined}}55 56 Base *sb = new Derived[10]; // expected-note{{Casting from 'Derived' to 'Base' here}}57 sink(sb); // expected-note{{Calling 'sink'}}58}59 60void safe_function() {61 Derived *d = new Derived[10];62 delete[] d; // no-warning63 64 Base *b = new Derived[10];65 delete[] static_cast<Derived*>(b); // no-warning66 67 Base *sb = new Derived[10];68 sink_cast(sb); // no-warning69 70 Derived *sd = new Derived[10];71 sink_derived(sd); // no-warning72}73 74void multiple_derived() {75 Base *b = new DoubleDerived[10]; // expected-note{{Casting from 'DoubleDerived' to 'Base' here}}76 delete[] b; // expected-warning{{Deleting an array of 'DoubleDerived' objects as their base class 'Base' is undefined}}77 // expected-note@-1{{Deleting an array of 'DoubleDerived' objects as their base class 'Base' is undefined}}78 79 Base *b2 = new DoubleDerived[10]; // expected-note{{Casting from 'DoubleDerived' to 'Base' here}}80 Derived *d2 = static_cast<Derived*>(b2); // expected-note{{Casting from 'Base' to 'Derived' here}}81 delete[] d2; // expected-warning{{Deleting an array of 'DoubleDerived' objects as their base class 'Derived' is undefined}}82 // expected-note@-1{{Deleting an array of 'DoubleDerived' objects as their base class 'Derived' is undefined}}83 84 Derived *d3 = new DoubleDerived[10]; // expected-note{{Casting from 'DoubleDerived' to 'Derived' here}}85 Base *b3 = d3; // expected-note{{Casting from 'Derived' to 'Base' here}}86 delete[] b3; // expected-warning{{Deleting an array of 'DoubleDerived' objects as their base class 'Base' is undefined}}87 // expected-note@-1{{Deleting an array of 'DoubleDerived' objects as their base class 'Base' is undefined}}88 89 Base *b4 = new DoubleDerived[10];90 Derived *d4 = static_cast<Derived*>(b4);91 DoubleDerived *dd4 = static_cast<DoubleDerived*>(d4);92 delete[] dd4; // no-warning93 94 Base *b5 = new DoubleDerived[10]; // expected-note{{Casting from 'DoubleDerived' to 'Base' here}}95 DoubleDerived *dd5 = static_cast<DoubleDerived*>(b5); // expected-note{{Casting from 'Base' to 'DoubleDerived' here}}96 Derived *d5 = dd5; // expected-note{{Casting from 'DoubleDerived' to 'Derived' here}}97 delete[] d5; // expected-warning{{Deleting an array of 'DoubleDerived' objects as their base class 'Derived' is undefined}}98 // expected-note@-1{{Deleting an array of 'DoubleDerived' objects as their base class 'Derived' is undefined}}99}100 101void unrelated_casts() {102 Base *b = new DoubleDerived[10]; // expected-note{{Casting from 'DoubleDerived' to 'Base' here}}103 Base &b2 = *b; // no-note: See the FIXME.104 105 // FIXME: Displaying casts of reference types is not supported.106 Derived &d2 = static_cast<Derived&>(b2); // no-note: See the FIXME.107 108 Derived *d = &d2; // no-note: See the FIXME.109 delete[] d; // expected-warning{{Deleting an array of 'DoubleDerived' objects as their base class 'Derived' is undefined}}110 // expected-note@-1{{Deleting an array of 'DoubleDerived' objects as their base class 'Derived' is undefined}}111}112