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
4namespace std {
5typedef __typeof__(sizeof(0)) size_t;
6enum class align_val_t : std::size_t {};
7class exception {};
8class bad_alloc : public exception {};
9struct nothrow_t {};
10extern const nothrow_t nothrow;
11} // namespace std
12
13void *operator new(std::size_t, const std::nothrow_t &) noexcept;
14void *operator new(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept;
15void *operator new(std::size_t, void *) noexcept;
16void *operator new(std::size_t, char);
17
18struct B;
19
20struct A { int VarI; int *PtrI; B *PtrB; };
21
22struct B { int VarI; };
23
24struct G {
25 G(A*, B*) {}
26 int operator+=(A *) { return 3; };
27};
28
29struct H {
30 int *a;
31 int *b;
32};
33
34int f(int);
35int f(A*);
36int f(A*, B*);
37int f(int, B*);
38int f(G, G);
39int f(B*);
40int f(const H &);
41void f1(void *, void *);
42A *g(A *);
43
44G operator+(const G&, const G&);
45
46void 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
77void 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
107void 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
134void 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
153void 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
179void 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
187void 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

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/multiple-new-in-one-expression.cpp