xref: /llvm-project/clang/test/Analysis/ArrayDelete.cpp (revision 37785fedabd8fa752129ef5bac3462311af91c35)
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