448 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//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 if13// * The handler is of type cv T or cv T& and E and T are the same type14// (ignoring the top-level cv-qualifiers), or15// * the handler is of type cv T or cv T& and T is an unambiguous base16// class of E, or17// > * 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 is23// std::nullptr_t24//25//===----------------------------------------------------------------------===//26 27// UNSUPPORTED: no-exceptions28 29#include <exception>30#include <stdlib.h>31#include <assert.h>32#include <stdio.h>33 34struct Base {};35struct Derived : Base {};36struct Derived2 : Base {};37struct Ambiguous : Derived, Derived2 {};38struct Private : private Base {};39struct Protected : protected Base {};40 41template <typename T // Handler type42 ,typename E // Thrown exception type43 ,typename O // Object type44 >45void assert_catches()46{47 try48 {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 69template <typename T // Handler type70 ,typename E // Thrown exception type71 ,typename O // Object type72 >73void assert_cannot_catch()74{75 try76 {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 97void f1()98{99 // Test that every combination of handler of type:100 // cv1 Base * cv2101 // 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 121void f2()122{123 // Test that every combination of handler of type:124 // cv1 Base * cv2125 // 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 145void f3()146{147 // Test that every combination of handler of type:148 // cv1 Derived * cv2149 // 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 169void f4()170{171 // Test that every combination of handler of type:172 // cv1 Derived * cv2173 // 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 193void 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 217void 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 242void 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 266void 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.html270 // 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 that275 // can be converted to the type of the handler by either or both of:276 // * a standard pointer conversion (4.10) not involving conversions277 // to pointers to private or protected or ambiguous classes278 // Notice that the handlers of type "cv1 T*cv2&" are not allowed such279 // freedom to find a base class. The ABI error is that we treat handlers280 // of reference type exactly the same as the corresponding hander of281 // non-reference type. Elsewhere in the exception handling this makes no282 // 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#388285 //286 // TL;DR: it is an unresolved C++ ABI defect that these do catch287 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 310void f9()311{312 // Test that every combination of handler of type:313 // cv1 Base * cv2314 // 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 334void f10()335{336 // Test that every combination of handler of type:337 // cv1 Base * cv2338 // 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 358void f11()359{360 // Test that every combination of handler of type:361 // cv1 Base * cv2362 // 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 382void 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 406void 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 430int main(int, char**)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 return 0;447}448