brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.3 KiB · dfae209 Raw
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