1 // RUN: %clang_cc1 -analyze -analyzer-checker=cplusplus.ArrayDelete -std=c++11 -verify -analyzer-output=text %s
2
3 struct Base {
4 virtual ~Base() = default;
5 };
6
7 struct Derived : public Base {};
8
9 struct DoubleDerived : public Derived {};
10
11 Derived *get();
12
create()13 Base *create() {
14 Base *b = new Derived[3]; // expected-note{{Casting from 'Derived' to 'Base' here}}
15 return b;
16 }
17
sink(Base * b)18 void 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
sink_cast(Base * b)23 void sink_cast(Base *b) {
24 delete[] static_cast<Derived*>(b); // no-warning
25 }
26
sink_derived(Derived * d)27 void sink_derived(Derived *d) {
28 delete[] d; // no-warning
29 }
30
same_function()31 void 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
different_function()41 void 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
safe_function()60 void safe_function() {
61 Derived *d = new Derived[10];
62 delete[] d; // no-warning
63
64 Base *b = new Derived[10];
65 delete[] static_cast<Derived*>(b); // no-warning
66
67 Base *sb = new Derived[10];
68 sink_cast(sb); // no-warning
69
70 Derived *sd = new Derived[10];
71 sink_derived(sd); // no-warning
72 }
73
multiple_derived()74 void 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-warning
93
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
unrelated_casts()101 void 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