1 //===---------------------- catch_pointer_referece.cpp --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This test case checks specifically the cases under bullet 3.1 & 3.2: 10 // 11 // C++ ABI 15.3: 12 // A handler is a match for an exception object of type E if 13 // * The handler is of type cv T or cv T& and E and T are the same type 14 // (ignoring the top-level cv-qualifiers), or 15 // * the handler is of type cv T or cv T& and T is an unambiguous base 16 // class of E, or 17 // / * the handler is of type cv1 T* cv2 and E is a pointer type that can \ 18 // | be converted to the type of the handler by either or both of | 19 // | o a standard pointer conversion (4.10 [conv.ptr]) not involving | 20 // | conversions to private or protected or ambiguous classes | 21 // \ o a qualification conversion / 22 // * the handler is a pointer or pointer to member type and E is 23 // std::nullptr_t 24 // 25 //===----------------------------------------------------------------------===// 26 27 // UNSUPPORTED: libcxxabi-no-exceptions 28 29 #include <exception> 30 #include <stdlib.h> 31 #include <assert.h> 32 #include <stdio.h> 33 34 struct Base {}; 35 struct Derived : Base {}; 36 struct Derived2 : Base {}; 37 struct Ambiguous : Derived, Derived2 {}; 38 struct Private : private Base {}; 39 struct Protected : protected Base {}; 40 41 template <typename T // Handler type 42 ,typename E // Thrown exception type 43 ,typename O // Object type 44 > 45 void assert_catches() 46 { 47 try 48 { 49 O o; 50 throw static_cast<E>(&o); 51 printf("%s\n", __PRETTY_FUNCTION__); 52 assert(false && "Statements after throw must be unreachable"); 53 } 54 catch (T t) 55 { 56 assert(true); 57 return; 58 } 59 catch (...) 60 { 61 printf("%s\n", __PRETTY_FUNCTION__); 62 assert(false && "Should not have entered catch-all"); 63 } 64 65 printf("%s\n", __PRETTY_FUNCTION__); 66 assert(false && "The catch should have returned"); 67 } 68 69 template <typename T // Handler type 70 ,typename E // Thrown exception type 71 ,typename O // Object type 72 > 73 void assert_cannot_catch() 74 { 75 try 76 { 77 O o; 78 throw static_cast<E>(&o); 79 printf("%s\n", __PRETTY_FUNCTION__); 80 assert(false && "Statements after throw must be unreachable"); 81 } 82 catch (T t) 83 { 84 printf("%s\n", __PRETTY_FUNCTION__); 85 assert(false && "Should not have entered the catch"); 86 } 87 catch (...) 88 { 89 assert(true); 90 return; 91 } 92 93 printf("%s\n", __PRETTY_FUNCTION__); 94 assert(false && "The catch-all should have returned"); 95 } 96 97 void f1() 98 { 99 // Test that every combination of handler of type: 100 // cv1 Base * cv2 101 // catches an exception of type: 102 // Derived * 103 assert_catches< Base * , Derived *, Derived>(); 104 assert_catches<const Base * , Derived *, Derived>(); 105 assert_catches< volatile Base * , Derived *, Derived>(); 106 assert_catches<const volatile Base * , Derived *, Derived>(); 107 assert_catches< Base * const , Derived *, Derived>(); 108 assert_catches<const Base * const , Derived *, Derived>(); 109 assert_catches< volatile Base * const , Derived *, Derived>(); 110 assert_catches<const volatile Base * const , Derived *, Derived>(); 111 assert_catches< Base * volatile, Derived *, Derived>(); 112 assert_catches<const Base * volatile, Derived *, Derived>(); 113 assert_catches< volatile Base * volatile, Derived *, Derived>(); 114 assert_catches<const volatile Base * volatile, Derived *, Derived>(); 115 assert_catches< Base * const volatile, Derived *, Derived>(); 116 assert_catches<const Base * const volatile, Derived *, Derived>(); 117 assert_catches< volatile Base * const volatile, Derived *, Derived>(); 118 assert_catches<const volatile Base * const volatile, Derived *, Derived>(); 119 } 120 121 void f2() 122 { 123 // Test that every combination of handler of type: 124 // cv1 Base * cv2 125 // catches an exception of type: 126 // Base * 127 assert_catches< Base * , Base *, Derived>(); 128 assert_catches<const Base * , Base *, Derived>(); 129 assert_catches< volatile Base * , Base *, Derived>(); 130 assert_catches<const volatile Base * , Base *, Derived>(); 131 assert_catches< Base * const , Base *, Derived>(); 132 assert_catches<const Base * const , Base *, Derived>(); 133 assert_catches< volatile Base * const , Base *, Derived>(); 134 assert_catches<const volatile Base * const , Base *, Derived>(); 135 assert_catches< Base * volatile, Base *, Derived>(); 136 assert_catches<const Base * volatile, Base *, Derived>(); 137 assert_catches< volatile Base * volatile, Base *, Derived>(); 138 assert_catches<const volatile Base * volatile, Base *, Derived>(); 139 assert_catches< Base * const volatile, Base *, Derived>(); 140 assert_catches<const Base * const volatile, Base *, Derived>(); 141 assert_catches< volatile Base * const volatile, Base *, Derived>(); 142 assert_catches<const volatile Base * const volatile, Base *, Derived>(); 143 } 144 145 void f3() 146 { 147 // Test that every combination of handler of type: 148 // cv1 Derived * cv2 149 // catches an exception of type: 150 // Derived * 151 assert_catches< Derived * , Derived *, Derived>(); 152 assert_catches<const Derived * , Derived *, Derived>(); 153 assert_catches< volatile Derived * , Derived *, Derived>(); 154 assert_catches<const volatile Derived * , Derived *, Derived>(); 155 assert_catches< Derived * const , Derived *, Derived>(); 156 assert_catches<const Derived * const , Derived *, Derived>(); 157 assert_catches< volatile Derived * const , Derived *, Derived>(); 158 assert_catches<const volatile Derived * const , Derived *, Derived>(); 159 assert_catches< Derived * volatile, Derived *, Derived>(); 160 assert_catches<const Derived * volatile, Derived *, Derived>(); 161 assert_catches< volatile Derived * volatile, Derived *, Derived>(); 162 assert_catches<const volatile Derived * volatile, Derived *, Derived>(); 163 assert_catches< Derived * const volatile, Derived *, Derived>(); 164 assert_catches<const Derived * const volatile, Derived *, Derived>(); 165 assert_catches< volatile Derived * const volatile, Derived *, Derived>(); 166 assert_catches<const volatile Derived * const volatile, Derived *, Derived>(); 167 } 168 169 void f4() 170 { 171 // Test that every combination of handler of type: 172 // cv1 Derived * cv2 173 // cannot catch an exception of type: 174 // Base * 175 assert_cannot_catch< Derived * , Base *, Derived>(); 176 assert_cannot_catch<const Derived * , Base *, Derived>(); 177 assert_cannot_catch< volatile Derived * , Base *, Derived>(); 178 assert_cannot_catch<const volatile Derived * , Base *, Derived>(); 179 assert_cannot_catch< Derived * const , Base *, Derived>(); 180 assert_cannot_catch<const Derived * const , Base *, Derived>(); 181 assert_cannot_catch< volatile Derived * const , Base *, Derived>(); 182 assert_cannot_catch<const volatile Derived * const , Base *, Derived>(); 183 assert_cannot_catch< Derived * volatile, Base *, Derived>(); 184 assert_cannot_catch<const Derived * volatile, Base *, Derived>(); 185 assert_cannot_catch< volatile Derived * volatile, Base *, Derived>(); 186 assert_cannot_catch<const volatile Derived * volatile, Base *, Derived>(); 187 assert_cannot_catch< Derived * const volatile, Base *, Derived>(); 188 assert_cannot_catch<const Derived * const volatile, Base *, Derived>(); 189 assert_cannot_catch< volatile Derived * const volatile, Base *, Derived>(); 190 assert_cannot_catch<const volatile Derived * const volatile, Base *, Derived>(); 191 } 192 193 void f5() 194 { 195 // Test that every combination of handler of type: 196 // cv1 Derived * cv2 & 197 // catches an exception of type: 198 // Derived * 199 assert_catches< Derived * &, Derived *, Derived>(); 200 assert_catches<const Derived * &, Derived *, Derived>(); 201 assert_catches< volatile Derived * &, Derived *, Derived>(); 202 assert_catches<const volatile Derived * &, Derived *, Derived>(); 203 assert_catches< Derived * const &, Derived *, Derived>(); 204 assert_catches<const Derived * const &, Derived *, Derived>(); 205 assert_catches< volatile Derived * const &, Derived *, Derived>(); 206 assert_catches<const volatile Derived * const &, Derived *, Derived>(); 207 assert_catches< Derived * volatile &, Derived *, Derived>(); 208 assert_catches<const Derived * volatile &, Derived *, Derived>(); 209 assert_catches< volatile Derived * volatile &, Derived *, Derived>(); 210 assert_catches<const volatile Derived * volatile &, Derived *, Derived>(); 211 assert_catches< Derived * const volatile &, Derived *, Derived>(); 212 assert_catches<const Derived * const volatile &, Derived *, Derived>(); 213 assert_catches< volatile Derived * const volatile &, Derived *, Derived>(); 214 assert_catches<const volatile Derived * const volatile &, Derived *, Derived>(); 215 } 216 217 void f6() 218 { 219 // Test that every combination of handler of type: 220 // cv1 Base * cv2 & 221 // catches an exception of type: 222 // Base * 223 assert_catches< Base * &, Base *, Derived>(); 224 assert_catches<const Base * &, Base *, Derived>(); 225 assert_catches< volatile Base * &, Base *, Derived>(); 226 assert_catches<const volatile Base * &, Base *, Derived>(); 227 assert_catches< Base * const &, Base *, Derived>(); 228 assert_catches<const Base * const &, Base *, Derived>(); 229 assert_catches< volatile Base * const &, Base *, Derived>(); 230 assert_catches<const volatile Base * const &, Base *, Derived>(); 231 assert_catches< Base * volatile &, Base *, Derived>(); 232 assert_catches<const Base * volatile &, Base *, Derived>(); 233 assert_catches< volatile Base * volatile &, Base *, Derived>(); 234 assert_catches<const volatile Base * volatile &, Base *, Derived>(); 235 assert_catches< Base * const volatile &, Base *, Derived>(); 236 assert_catches<const Base * const volatile &, Base *, Derived>(); 237 assert_catches< volatile Base * const volatile &, Base *, Derived>(); 238 assert_catches<const volatile Base * const volatile &, Base *, Derived>(); 239 240 } 241 242 void f7() 243 { 244 // Test that every combination of handler of type: 245 // cv1 Derived * cv2 & 246 // cannot catch an exception of type: 247 // Base * 248 assert_cannot_catch< Derived * &, Base *, Derived>(); 249 assert_cannot_catch<const Derived * &, Base *, Derived>(); 250 assert_cannot_catch< volatile Derived * &, Base *, Derived>(); 251 assert_cannot_catch<const volatile Derived * &, Base *, Derived>(); 252 assert_cannot_catch< Derived * const &, Base *, Derived>(); 253 assert_cannot_catch<const Derived * const &, Base *, Derived>(); 254 assert_cannot_catch< volatile Derived * const &, Base *, Derived>(); 255 assert_cannot_catch<const volatile Derived * const &, Base *, Derived>(); 256 assert_cannot_catch< Derived * volatile &, Base *, Derived>(); 257 assert_cannot_catch<const Derived * volatile &, Base *, Derived>(); 258 assert_cannot_catch< volatile Derived * volatile &, Base *, Derived>(); 259 assert_cannot_catch<const volatile Derived * volatile &, Base *, Derived>(); 260 assert_cannot_catch< Derived * const volatile &, Base *, Derived>(); 261 assert_cannot_catch<const Derived * const volatile &, Base *, Derived>(); 262 assert_cannot_catch< volatile Derived * const volatile &, Base *, Derived>(); 263 assert_cannot_catch<const volatile Derived * const volatile &, Base *, Derived>(); 264 } 265 266 void f8() 267 { 268 // This test case has a caveat noted in the discussion here: 269 // https://gcc.gnu.org/ml/gcc-patches/2009-08/msg00264.html 270 // Specifically: 271 // This [test exposes a] corner case of the ARM C++ ABI. The generic C++ 272 // ABI also gets this wrong, because I failed to notice the subtlety here. 273 // The issue is that 15.3/3 3rd bullet says: 274 // The handler is of type cv1 T* cv2 and E is a pointer type that 275 // can be converted to the type of the handler by either or both of: 276 // * a standard pointer conversion (4.10) not involving conversions 277 // to pointers to private or protected or ambiguous classes 278 // Notice that the handlers of type "cv1 T*cv2&" are not allowed such 279 // freedom to find a base class. The ABI error is that we treat handlers 280 // of reference type exactly the same as the corresponding hander of 281 // non-reference type. Elsewhere in the exception handling this makes no 282 // difference (for instance bullet 1 explicitly says 'cv T or cv T&'). 283 // 284 // See also: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#388 285 // 286 // TL;DR: it is an unresolved C++ ABI defect that these do catch 287 288 // Test that every combination of handler of type: 289 // cv1 Base * cv2 & 290 // catches an exception of type: 291 // Derived * 292 assert_catches< Base * &, Derived *, Derived>(); 293 assert_catches<const Base * &, Derived *, Derived>(); 294 assert_catches< volatile Base * &, Derived *, Derived>(); 295 assert_catches<const volatile Base * &, Derived *, Derived>(); 296 assert_catches< Base * const &, Derived *, Derived>(); 297 assert_catches<const Base * const &, Derived *, Derived>(); 298 assert_catches< volatile Base * const &, Derived *, Derived>(); 299 assert_catches<const volatile Base * const &, Derived *, Derived>(); 300 assert_catches< Base * volatile &, Derived *, Derived>(); 301 assert_catches<const Base * volatile &, Derived *, Derived>(); 302 assert_catches< volatile Base * volatile &, Derived *, Derived>(); 303 assert_catches<const volatile Base * volatile &, Derived *, Derived>(); 304 assert_catches< Base * const volatile &, Derived *, Derived>(); 305 assert_catches<const Base * const volatile &, Derived *, Derived>(); 306 assert_catches< volatile Base * const volatile &, Derived *, Derived>(); 307 assert_catches<const volatile Base * const volatile &, Derived *, Derived>(); 308 } 309 310 void f9() 311 { 312 // Test that every combination of handler of type: 313 // cv1 Base * cv2 314 // cannot catch an exception of type: 315 // Ambiguous * 316 assert_cannot_catch< Base * , Ambiguous *, Ambiguous>(); 317 assert_cannot_catch<const Base * , Ambiguous *, Ambiguous>(); 318 assert_cannot_catch< volatile Base * , Ambiguous *, Ambiguous>(); 319 assert_cannot_catch<const volatile Base * , Ambiguous *, Ambiguous>(); 320 assert_cannot_catch< Base * const , Ambiguous *, Ambiguous>(); 321 assert_cannot_catch<const Base * const , Ambiguous *, Ambiguous>(); 322 assert_cannot_catch< volatile Base * const , Ambiguous *, Ambiguous>(); 323 assert_cannot_catch<const volatile Base * const , Ambiguous *, Ambiguous>(); 324 assert_cannot_catch< Base * volatile, Ambiguous *, Ambiguous>(); 325 assert_cannot_catch<const Base * volatile, Ambiguous *, Ambiguous>(); 326 assert_cannot_catch< volatile Base * volatile, Ambiguous *, Ambiguous>(); 327 assert_cannot_catch<const volatile Base * volatile, Ambiguous *, Ambiguous>(); 328 assert_cannot_catch< Base * const volatile, Ambiguous *, Ambiguous>(); 329 assert_cannot_catch<const Base * const volatile, Ambiguous *, Ambiguous>(); 330 assert_cannot_catch< volatile Base * const volatile, Ambiguous *, Ambiguous>(); 331 assert_cannot_catch<const volatile Base * const volatile, Ambiguous *, Ambiguous>(); 332 } 333 334 void f10() 335 { 336 // Test that every combination of handler of type: 337 // cv1 Base * cv2 338 // cannot catch an exception of type: 339 // Private * 340 assert_cannot_catch< Base * , Private *, Private>(); 341 assert_cannot_catch<const Base * , Private *, Private>(); 342 assert_cannot_catch< volatile Base * , Private *, Private>(); 343 assert_cannot_catch<const volatile Base * , Private *, Private>(); 344 assert_cannot_catch< Base * const , Private *, Private>(); 345 assert_cannot_catch<const Base * const , Private *, Private>(); 346 assert_cannot_catch< volatile Base * const , Private *, Private>(); 347 assert_cannot_catch<const volatile Base * const , Private *, Private>(); 348 assert_cannot_catch< Base * volatile, Private *, Private>(); 349 assert_cannot_catch<const Base * volatile, Private *, Private>(); 350 assert_cannot_catch< volatile Base * volatile, Private *, Private>(); 351 assert_cannot_catch<const volatile Base * volatile, Private *, Private>(); 352 assert_cannot_catch< Base * const volatile, Private *, Private>(); 353 assert_cannot_catch<const Base * const volatile, Private *, Private>(); 354 assert_cannot_catch< volatile Base * const volatile, Private *, Private>(); 355 assert_cannot_catch<const volatile Base * const volatile, Private *, Private>(); 356 } 357 358 void f11() 359 { 360 // Test that every combination of handler of type: 361 // cv1 Base * cv2 362 // cannot catch an exception of type: 363 // Protected * 364 assert_cannot_catch< Base * , Protected *, Protected>(); 365 assert_cannot_catch<const Base * , Protected *, Protected>(); 366 assert_cannot_catch< volatile Base * , Protected *, Protected>(); 367 assert_cannot_catch<const volatile Base * , Protected *, Protected>(); 368 assert_cannot_catch< Base * const , Protected *, Protected>(); 369 assert_cannot_catch<const Base * const , Protected *, Protected>(); 370 assert_cannot_catch< volatile Base * const , Protected *, Protected>(); 371 assert_cannot_catch<const volatile Base * const , Protected *, Protected>(); 372 assert_cannot_catch< Base * volatile, Protected *, Protected>(); 373 assert_cannot_catch<const Base * volatile, Protected *, Protected>(); 374 assert_cannot_catch< volatile Base * volatile, Protected *, Protected>(); 375 assert_cannot_catch<const volatile Base * volatile, Protected *, Protected>(); 376 assert_cannot_catch< Base * const volatile, Protected *, Protected>(); 377 assert_cannot_catch<const Base * const volatile, Protected *, Protected>(); 378 assert_cannot_catch< volatile Base * const volatile, Protected *, Protected>(); 379 assert_cannot_catch<const volatile Base * const volatile, Protected *, Protected>(); 380 } 381 382 void f12() 383 { 384 // Test that every combination of handler of type: 385 // cv1 Base * cv2 & 386 // cannot catch an exception of type: 387 // Private * 388 assert_cannot_catch< Base * &, Private *, Private>(); 389 assert_cannot_catch<const Base * &, Private *, Private>(); 390 assert_cannot_catch< volatile Base * &, Private *, Private>(); 391 assert_cannot_catch<const volatile Base * &, Private *, Private>(); 392 assert_cannot_catch< Base * const &, Private *, Private>(); 393 assert_cannot_catch<const Base * const &, Private *, Private>(); 394 assert_cannot_catch< volatile Base * const &, Private *, Private>(); 395 assert_cannot_catch<const volatile Base * const &, Private *, Private>(); 396 assert_cannot_catch< Base * volatile &, Private *, Private>(); 397 assert_cannot_catch<const Base * volatile &, Private *, Private>(); 398 assert_cannot_catch< volatile Base * volatile &, Private *, Private>(); 399 assert_cannot_catch<const volatile Base * volatile &, Private *, Private>(); 400 assert_cannot_catch< Base * const volatile &, Private *, Private>(); 401 assert_cannot_catch<const Base * const volatile &, Private *, Private>(); 402 assert_cannot_catch< volatile Base * const volatile &, Private *, Private>(); 403 assert_cannot_catch<const volatile Base * const volatile &, Private *, Private>(); 404 } 405 406 void f13() 407 { 408 // Test that every combination of handler of type: 409 // cv1 Base * cv2 & 410 // cannot catch an exception of type: 411 // Protected * 412 assert_cannot_catch< Base * &, Protected *, Protected>(); 413 assert_cannot_catch<const Base * &, Protected *, Protected>(); 414 assert_cannot_catch< volatile Base * &, Protected *, Protected>(); 415 assert_cannot_catch<const volatile Base * &, Protected *, Protected>(); 416 assert_cannot_catch< Base * const &, Protected *, Protected>(); 417 assert_cannot_catch<const Base * const &, Protected *, Protected>(); 418 assert_cannot_catch< volatile Base * const &, Protected *, Protected>(); 419 assert_cannot_catch<const volatile Base * const &, Protected *, Protected>(); 420 assert_cannot_catch< Base * volatile &, Protected *, Protected>(); 421 assert_cannot_catch<const Base * volatile &, Protected *, Protected>(); 422 assert_cannot_catch< volatile Base * volatile &, Protected *, Protected>(); 423 assert_cannot_catch<const volatile Base * volatile &, Protected *, Protected>(); 424 assert_cannot_catch< Base * const volatile &, Protected *, Protected>(); 425 assert_cannot_catch<const Base * const volatile &, Protected *, Protected>(); 426 assert_cannot_catch< volatile Base * const volatile &, Protected *, Protected>(); 427 assert_cannot_catch<const volatile Base * const volatile &, Protected *, Protected>(); 428 } 429 430 int main() 431 { 432 f1(); 433 f2(); 434 f3(); 435 f4(); 436 f5(); 437 f6(); 438 f7(); 439 f8(); 440 f9(); 441 f10(); 442 f11(); 443 f12(); 444 f13(); 445 } 446