1 // RUN: %check_clang_tidy %s performance-noexcept-destructor %t -- -- -fexceptions 2 3 struct Empty 4 {}; 5 6 struct IntWrapper { 7 int value; 8 }; 9 10 template <typename T> 11 struct FalseT { 12 static constexpr bool value = false; 13 }; 14 15 template <typename T> 16 struct TrueT { 17 static constexpr bool value = true; 18 }; 19 20 struct ThrowOnAnything { 21 ThrowOnAnything() noexcept(false); 22 ThrowOnAnything(ThrowOnAnything&&) noexcept(false); 23 ThrowOnAnything& operator=(ThrowOnAnything &&) noexcept(false); 24 ~ThrowOnAnything() noexcept(false); 25 }; 26 27 struct B { 28 static constexpr bool kFalse = false; 29 ~B() noexcept(kFalse); 30 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' [performance-noexcept-destructor] 31 }; 32 33 struct D { 34 static constexpr bool kFalse = false; 35 ~D() noexcept(kFalse) = default; 36 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' [performance-noexcept-destructor] 37 }; 38 39 template <typename> 40 struct E { 41 static constexpr bool kFalse = false; 42 ~E() noexcept(kFalse); 43 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' 44 }; 45 46 template <typename> 47 struct F { 48 static constexpr bool kFalse = false; 49 ~F() noexcept(kFalse) = default; 50 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' [performance-noexcept-destructor] 51 }; 52 53 struct G { 54 ~G() = default; 55 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: destructors should be marked noexcept [performance-noexcept-destructor] 56 // CHECK-FIXES: ~G() noexcept = default; 57 58 ThrowOnAnything field; 59 }; 60 throwing_function()61void throwing_function() noexcept(false) {} 62 63 struct H { 64 ~H() noexcept(noexcept(throwing_function())); 65 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' [performance-noexcept-destructor] 66 }; 67 68 template <typename> 69 struct I { 70 ~I() noexcept(noexcept(throwing_function())); 71 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' [performance-noexcept-destructor] 72 }; 73 74 template <typename T> struct TemplatedType { fTemplatedType75 static void f() {} 76 }; 77 78 template <> struct TemplatedType<int> { fTemplatedType79 static void f() noexcept {} 80 }; 81 82 struct J { 83 ~J() noexcept(noexcept(TemplatedType<double>::f())); 84 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' [performance-noexcept-destructor] 85 }; 86 87 struct K : public ThrowOnAnything { 88 ~K() = default; 89 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: destructors should be marked noexcept [performance-noexcept-destructor] 90 // CHECK-FIXES: ~K() noexcept = default; 91 }; 92 93 struct InheritFromThrowOnAnything : public ThrowOnAnything 94 {}; 95 96 struct L { 97 ~L() = default; 98 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: destructors should be marked noexcept [performance-noexcept-destructor] 99 // CHECK-FIXES: ~L() noexcept = default; 100 101 InheritFromThrowOnAnything IFF; 102 }; 103 104 struct M : public InheritFromThrowOnAnything { 105 ~M() = default; 106 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: destructors should be marked noexcept [performance-noexcept-destructor] 107 // CHECK-FIXES: ~M() noexcept = default; 108 }; 109 110 struct N : public IntWrapper, ThrowOnAnything { 111 ~N() = default; 112 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: destructors should be marked noexcept [performance-noexcept-destructor] 113 // CHECK-FIXES: ~N() noexcept = default; 114 }; 115 116 struct O : virtual IntWrapper, ThrowOnAnything { 117 ~O() = default; 118 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: destructors should be marked noexcept [performance-noexcept-destructor] 119 // CHECK-FIXES: ~O() noexcept = default; 120 }; 121 122 class OK {}; 123 124 struct OK1 { 125 ~OK1() noexcept; 126 }; 127 128 struct OK2 { 129 static constexpr bool kTrue = true; 130 ~OK2OK2131 ~OK2() noexcept(true) {} 132 }; 133 134 struct OK4 { ~OK4OK4135 ~OK4() noexcept(false) {} 136 }; 137 138 struct OK3 { 139 ~OK3() = default; 140 }; 141 142 struct OK5 { 143 ~OK5() noexcept(true) = default; 144 }; 145 146 struct OK6 { 147 ~OK6() = default; 148 }; 149 150 template <typename> 151 struct OK7 { 152 ~OK7() = default; 153 }; 154 155 template <typename> 156 struct OK8 { 157 ~OK8() noexcept = default; 158 }; 159 160 template <typename> 161 struct OK9 { 162 ~OK9() noexcept(true) = default; 163 }; 164 165 template <typename> 166 struct OK10 { 167 ~OK10() noexcept(false) = default; 168 }; 169 170 template <typename> 171 struct OK11 { 172 ~OK11() = delete; 173 }; 174 noexcept_function()175void noexcept_function() noexcept {} 176 177 struct OK12 { 178 ~OK12() noexcept(noexcept(noexcept_function())); 179 }; 180 181 struct OK13 { 182 ~OK13() noexcept(noexcept(noexcept_function())) = default; 183 }; 184 185 template <typename> 186 struct OK14 { 187 ~OK14() noexcept(noexcept(TemplatedType<int>::f())); 188 }; 189 190 struct OK15 { 191 ~OK15() = default; 192 193 int member; 194 }; 195 196 template <typename> 197 struct OK16 { 198 ~OK16() = default; 199 200 int member; 201 }; 202 203 struct OK17 { 204 ~OK17() = default; 205 206 OK empty_field; 207 }; 208 209 template <typename> 210 struct OK18 { 211 ~OK18() = default; 212 213 OK empty_field; 214 }; 215 216 struct OK19 : public OK { 217 ~OK19() = default; 218 }; 219 220 struct OK20 : virtual OK { 221 ~OK20() = default; 222 }; 223 224 template <typename T> 225 struct OK21 : public T { 226 ~OK21() = default; 227 }; 228 229 template <typename T> 230 struct OK22 : virtual T { 231 ~OK22() = default; 232 }; 233 234 template <typename T> 235 struct OK23 { 236 ~OK23() = default; 237 238 T member; 239 }; 240 testTemplates()241void testTemplates() { 242 OK21<Empty> value(OK21<Empty>{}); 243 value = OK21<Empty>{}; 244 245 OK22<Empty> value2{OK22<Empty>{}}; 246 value2 = OK22<Empty>{}; 247 248 OK23<Empty> value3{OK23<Empty>{}}; 249 value3 =OK23<Empty>{}; 250 } 251 252 struct OK24 : public Empty, OK1 { 253 ~OK24() = default; 254 }; 255 256 struct OK25 : virtual Empty, OK1 { 257 ~OK25() = default; 258 }; 259 260 struct OK26 : public Empty, IntWrapper { 261 ~OK26() = default; 262 }; 263 264 template <typename T> 265 struct OK27 : public T { 266 ~OK27() = default; 267 }; 268 269 template <typename T> 270 struct OK28 : virtual T { 271 ~OK28() = default; 272 }; 273 274 template <typename T> 275 struct OK29 { 276 ~OK29() = default; 277 278 T member; 279 }; 280 281 struct OK30 { 282 ~OK30() noexcept(TrueT<OK30>::value) = default; 283 }; 284 285 template <typename> 286 struct OK31 { 287 ~OK31() noexcept(TrueT<int>::value) = default; 288 }; 289 290 struct OK32 { 291 ~OK32(); 292 }; 293 294 template <typename> 295 struct OK33 { 296 ~OK33(); 297 }; 298 299 struct OK34 { ~OK34OK34300 ~OK34() {} 301 }; 302 303 template <typename> 304 struct OK35 { ~OK35OK35305 ~OK35() {} 306 }; 307