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