1 | // RUN: %check_clang_tidy -std=c++11 -check-suffixes=ALL,CPP11 %s bugprone-multiple-new-in-one-expression %t -- -- -target x86_64-unknown-unknown |
2 | // RUN: %check_clang_tidy -std=c++17 -check-suffixes=ALL,CPP17 %s bugprone-multiple-new-in-one-expression %t -- -- -target x86_64-unknown-unknown |
3 | |
4 | namespace std { |
5 | typedef __typeof__(sizeof(0)) size_t; |
6 | enum class align_val_t : std::size_t {}; |
7 | class exception {}; |
8 | class bad_alloc : public exception {}; |
9 | struct nothrow_t {}; |
10 | extern const nothrow_t nothrow; |
11 | } // namespace std |
12 | |
13 | void *operator new(std::size_t, const std::nothrow_t &) noexcept; |
14 | void *operator new(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept; |
15 | void *operator new(std::size_t, void *) noexcept; |
16 | void *operator new(std::size_t, char); |
17 | |
18 | struct B; |
19 | |
20 | struct A { int VarI; int *PtrI; B *PtrB; }; |
21 | |
22 | struct B { int VarI; }; |
23 | |
24 | struct G { |
25 | G(A*, B*) {} |
26 | int operator+=(A *) { return 3; }; |
27 | }; |
28 | |
29 | struct H { |
30 | int *a; |
31 | int *b; |
32 | }; |
33 | |
34 | int f(int); |
35 | int f(A*); |
36 | int f(A*, B*); |
37 | int f(int, B*); |
38 | int f(G, G); |
39 | int f(B*); |
40 | int f(const H &); |
41 | void f1(void *, void *); |
42 | A *g(A *); |
43 | |
44 | G operator+(const G&, const G&); |
45 | |
46 | void test_function_parameter(A *XA, B *XB) { |
47 | (void)f(new A, new B); |
48 | try { |
49 | (void)f(new A, new B); |
50 | } |
51 | catch (A) {}; |
52 | try { |
53 | (void)f(new A, new B); |
54 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:13: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; order of these allocations is undefined [ |
55 | (void)f(f(new A, new B)); |
56 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
57 | int X = f(new A, new B); |
58 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
59 | X = f(new A, new B); |
60 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:11: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
61 | X = 1 + f(new A, new B); |
62 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
63 | |
64 | (void)f(g(new A), new B); |
65 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
66 | |
67 | (void)f(1 + f(new A), new B); |
68 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:19: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
69 | (void)f(XA = new A, new B); |
70 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:18: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
71 | (void)f(1 + f(new A), XB = new B); |
72 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:19: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
73 | } |
74 | catch (std::exception) {} |
75 | } |
76 | |
77 | void test_operator(G *G1) { |
78 | (void)(f(new A) + f(new B)); |
79 | try { |
80 | (void)(f(new A) + f(new B)); |
81 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:14: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
82 | (void)f(f(new A) + f(new B)); |
83 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
84 | int X = f(new A) + f(new B); |
85 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
86 | X = f(new A) + f(new B); |
87 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:11: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
88 | X = 1 + f(new A) + 1 + f(new B); |
89 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
90 | |
91 | (void)(f(g(new A)) + f(new B)); |
92 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:16: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
93 | |
94 | (void)(f(1 + f(new A)) + f(new B)); |
95 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:20: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
96 | (void)(f(1 + f(new A)) + f(1 + f(new B))); |
97 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:20: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
98 | |
99 | (void)((new A)->VarI + (new A)->VarI); |
100 | |
101 | (void)(f(new A) + ((*G1) += new A)); |
102 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:14: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
103 | } |
104 | catch (std::bad_alloc) {} |
105 | } |
106 | |
107 | void test_construct() { |
108 | (void)(G(new A, new B)); |
109 | try { |
110 | (void)(G(new A, new B)); |
111 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:14: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
112 | (void)(G(new A, nullptr) + G(nullptr, new B)); |
113 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:14: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
114 | f(G(new A, nullptr), G(new A, nullptr)); |
115 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:9: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
116 | |
117 | (void)new G(new A, nullptr); |
118 | // CHECK-MESSAGES-CPP11: :[[@LINE-1]]:11: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
119 | // CHECK-MESSAGES-CPP17: :[[@LINE-2]]:11: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception [ |
120 | (void)new G(nullptr, (new A)->PtrB); |
121 | G *Z = new G(new A, nullptr); |
122 | // CHECK-MESSAGES-CPP11: :[[@LINE-1]]:12: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
123 | // CHECK-MESSAGES-CPP17: :[[@LINE-2]]:12: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception [ |
124 | Z = new G(g(new A), nullptr); |
125 | // CHECK-MESSAGES-CPP11: :[[@LINE-1]]:9: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
126 | // CHECK-MESSAGES-CPP17: :[[@LINE-2]]:9: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception [ |
127 | G *Z1, *Z2 = new G(nullptr, (new A)->PtrB), *Z3; |
128 | // CHECK-MESSAGES-CPP11: :[[@LINE-1]]:18: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
129 | // CHECK-MESSAGES-CPP17: :[[@LINE-2]]:18: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception [ |
130 | } |
131 | catch (const std::bad_alloc &) {} |
132 | } |
133 | |
134 | void test_new_assign() { |
135 | A *X, *Y; |
136 | (X = new A)->VarI = (Y = new A)->VarI; |
137 | try { |
138 | (X = new A)->VarI = (Y = new A)->VarI; |
139 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
140 | (new A)->VarI = (Y = new A)->VarI; |
141 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:6: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
142 | (X = new A)->VarI = (new A)->VarI; |
143 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
144 | (new A)->VarI = (new A)->VarI; |
145 | (new A)->PtrI = new int; |
146 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:6: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
147 | (X = new A)->VarI += (new A)->VarI; |
148 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
149 | } |
150 | catch (...) {} |
151 | } |
152 | |
153 | void test_operator_fixed_order(unsigned int L) { |
154 | (void)(f((f(new A) || f(0)) + f(new B[L]))); |
155 | try { |
156 | (void)(f(new A) || f(new B)); |
157 | (void)(f(new A) && f(new B)); |
158 | (void)(f(new A) || f(new B) || f(new A)); |
159 | |
160 | (void)(f(new A), f(new B)); |
161 | |
162 | int Y = f(0, new B) ? f(new A) : f(new B); |
163 | Y = f(new A) ? 1 : f(new B); |
164 | Y = f(new A) ? f(new B) : 1; |
165 | |
166 | G g{new A, new B}; |
167 | H h{.a: new int, .b: new int}; |
168 | f({.a: new int, .b: new int}); |
169 | (void)f({new A, new B}, {nullptr, nullptr}); |
170 | (void)f({new A, new B}, {new A, nullptr}); |
171 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:14: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
172 | |
173 | (void)(f((f(new A) || f(0)) + f(new B[L]))); |
174 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:17: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
175 | } |
176 | catch (std::bad_alloc) {} |
177 | } |
178 | |
179 | void test_cast() { |
180 | try { |
181 | f1(static_cast<void *>(new A), new B); |
182 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:28: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
183 | } |
184 | catch (std::bad_alloc &) {} |
185 | } |
186 | |
187 | void test_nothrow(void *P) { |
188 | try { |
189 | (void)f(new(std::nothrow) A, new B); |
190 | (void)f(new A, new(std::nothrow) B); |
191 | (void)f(new(static_cast<std::align_val_t>(8), std::nothrow) A, new B); |
192 | (void)f(new(P) A, new B); |
193 | (void)f(new('a') A, new B); |
194 | // CHECK-MESSAGES-ALL: :[[@LINE-1]]:13: warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; |
195 | } |
196 | catch (std::exception) {} |
197 | } |
198 | |