| 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 | |