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 {
GG25   G(A*, B*) {}
operator +=G26   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 
test_function_parameter(A * XA,B * XB)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 
test_operator(G * G1)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 
test_construct()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 
test_new_assign()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 
test_operator_fixed_order(unsigned int L)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{new int, new int};
168     f({new int, 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 
test_cast()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 
test_nothrow(void * P)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