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