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 33struct Base {}; 34struct Derived : Base {}; 35struct Derived2 : Base {}; 36struct Ambiguous : Derived, Derived2 {}; 37struct Private : private Base {}; 38struct Protected : protected Base {}; 39 40template <typename T // Handler type 41 ,typename E // Thrown exception type 42 ,typename O // Object type 43 > 44void 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 68template <typename T // Handler type 69 ,typename E // Thrown exception type 70 ,typename O // Object type 71 > 72void 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 96void 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 120void 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 144void 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 168void 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 192void 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 216void 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 241void 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 265void 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 309void 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 333void 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 357void 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 381void 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 405void 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 429int 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