/ test / catch_ptr.pass.cpp
catch_ptr.pass.cpp
  1  //===---------------------- catch_class_04.cpp ----------------------------===//
  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-exception
  6  //
  7  //===----------------------------------------------------------------------===//
  8  
  9  /*
 10      This test checks that adjustedPtr is correct as there exist offsets in this
 11      object for the various subobjects, all of which have a unique id_ to
 12      check against.  It also checks that virtual bases work properly
 13  */
 14  
 15  // UNSUPPORTED: no-exceptions
 16  
 17  // FIXME: GCC doesn't allow turning off the warning for exceptions being caught
 18  //        by earlier handlers, which this test is exercising. We have to disable
 19  //        warnings altogether to remove the error.
 20  //        See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97675.
 21  // ADDITIONAL_COMPILE_FLAGS: -Wno-error
 22  
 23  #include <exception>
 24  #include <stdlib.h>
 25  #include <assert.h>
 26  
 27  // Clang emits  warnings about exceptions of type 'Child' being caught by
 28  // an earlier handler of type 'Base'. Congrats clang, you've just
 29  // diagnosed the behavior under test.
 30  #if defined(__clang__)
 31  #pragma clang diagnostic ignored "-Wexceptions"
 32  #endif
 33  
 34  struct B
 35  {
 36      static int count;
 37      int id_;
 38      explicit B(int id) : id_(id) {count++;}
 39      B(const B& a) : id_(a.id_) {count++;}
 40      ~B() {count--;}
 41  };
 42  
 43  int B::count = 0;
 44  
 45  struct C1
 46      : virtual B
 47  {
 48      static int count;
 49      int id_;
 50      explicit C1(int id) : B(id-2), id_(id) {count++;}
 51      C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;}
 52      ~C1() {count--;}
 53  };
 54  
 55  int C1::count = 0;
 56  
 57  struct C2
 58      : virtual private B
 59  {
 60      static int count;
 61      int id_;
 62      explicit C2(int id) : B(id-2), id_(id) {count++;}
 63      C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;}
 64      ~C2() {count--;}
 65  };
 66  
 67  int C2::count = 0;
 68  
 69  struct A
 70      : C1, C2
 71  {
 72      static int count;
 73      int id_;
 74      explicit A(int id) : B(id+3), C1(id-1), C2(id-2), id_(id) {count++;}
 75      A(const A& a) : B(a.id_+3), C1(a.id_-1), C2(a.id_-2),  id_(a.id_) {count++;}
 76      ~A() {count--;}
 77  };
 78  
 79  int A::count = 0;
 80  
 81  A global_a(5);
 82  
 83  void f1()
 84  {
 85      throw &global_a;
 86      assert(false);
 87  }
 88  
 89  void f2()
 90  {
 91      try
 92      {
 93          f1();
 94          assert(false);
 95      }
 96      catch (const A* a)  // can catch A
 97      {
 98          assert(a->id_ == 5);
 99          assert(static_cast<const C1*>(a)->id_ == 4);
100          assert(static_cast<const C2*>(a)->id_ == 3);
101          assert(static_cast<const B*>(a)->id_ == 8);
102          throw;
103      }
104      catch (const C1*)
105      {
106          assert(false);
107      }
108      catch (const C2*)
109      {
110          assert(false);
111      }
112      catch (const B*)
113      {
114          assert(false);
115      }
116  }
117  
118  void f3()
119  {
120      try
121      {
122          f2();
123          assert(false);
124      }
125      catch (const B* a)  // can catch B
126      {
127          assert(static_cast<const B*>(a)->id_ == 8);
128          throw;
129      }
130      catch (const C1* c1)
131      {
132          assert(false);
133      }
134      catch (const C2*)
135      {
136          assert(false);
137      }
138  }
139  
140  void f4()
141  {
142      try
143      {
144          f3();
145          assert(false);
146      }
147      catch (const C2* c2)  // can catch C2
148      {
149          assert(c2->id_ == 3);
150          throw;
151      }
152      catch (const B* a)
153      {
154          assert(false);
155      }
156      catch (const C1*)
157      {
158          assert(false);
159      }
160  }
161  
162  void f5()
163  {
164      try
165      {
166          f4();
167          assert(false);
168      }
169      catch (const C1* c1)  // can catch C1
170      {
171          assert(c1->id_ == 4);
172          assert(static_cast<const B*>(c1)->id_ == 8);
173          throw;
174      }
175      catch (const B* a)
176      {
177          assert(false);
178      }
179      catch (const C2*)
180      {
181          assert(false);
182      }
183  }
184  
185  int main(int, char**)
186  {
187      try
188      {
189          f5();
190          assert(false);
191      }
192      catch (...)
193      {
194      }
195  
196      return 0;
197  }