/ test / catch_class_04.pass.cpp
catch_class_04.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  void f1()
 82  {
 83      assert(A::count == 0);
 84      assert(C1::count == 0);
 85      assert(C2::count == 0);
 86      assert(B::count == 0);
 87      A a(5);
 88      assert(A::count == 1);
 89      assert(C1::count == 1);
 90      assert(C2::count == 1);
 91      assert(B::count == 1);
 92  
 93      assert(a.id_ == 5);
 94      assert(static_cast<C1&>(a).id_ == 4);
 95      assert(static_cast<C2&>(a).id_ == 3);
 96      assert(static_cast<B&>(a).id_ == 8);
 97      throw a;
 98      assert(false);
 99  }
100  
101  void f2()
102  {
103      try
104      {
105          assert(A::count == 0);
106          assert(C1::count == 0);
107          assert(C2::count == 0);
108          assert(B::count == 0);
109          f1();
110          assert(false);
111      }
112      catch (const A& a)  // can catch A
113      {
114          assert(a.id_ == 5);
115          assert(static_cast<const C1&>(a).id_ == 4);
116          assert(static_cast<const C2&>(a).id_ == 3);
117          assert(static_cast<const B&>(a).id_ == 8);
118          throw;
119      }
120      catch (const C1&)
121      {
122          assert(false);
123      }
124      catch (const C2&)
125      {
126          assert(false);
127      }
128      catch (const B&)
129      {
130          assert(false);
131      }
132  }
133  
134  void f3()
135  {
136      try
137      {
138          assert(A::count == 0);
139          assert(C1::count == 0);
140          assert(C2::count == 0);
141          assert(B::count == 0);
142          f2();
143          assert(false);
144      }
145      catch (const B& a)  // can catch B
146      {
147          assert(static_cast<const B&>(a).id_ == 8);
148          throw;
149      }
150      catch (const C1& c1)
151      {
152          assert(false);
153      }
154      catch (const C2&)
155      {
156          assert(false);
157      }
158  }
159  
160  void f4()
161  {
162      try
163      {
164          assert(A::count == 0);
165          assert(C1::count == 0);
166          assert(C2::count == 0);
167          assert(B::count == 0);
168          f3();
169          assert(false);
170      }
171      catch (const C2& c2)  // can catch C2
172      {
173          assert(c2.id_ == 3);
174          throw;
175      }
176      catch (const B& a)  // can not catch B (ambiguous base)
177      {
178          assert(false);
179      }
180      catch (const C1&)
181      {
182          assert(false);
183      }
184  }
185  
186  void f5()
187  {
188      try
189      {
190          assert(A::count == 0);
191          assert(C1::count == 0);
192          assert(C2::count == 0);
193          assert(B::count == 0);
194          f4();
195          assert(false);
196      }
197      catch (const C1& c1)  // can catch C1
198      {
199          assert(c1.id_ == 4);
200          assert(static_cast<const B&>(c1).id_ == 8);
201          throw;
202      }
203      catch (const B& a)
204      {
205          assert(false);
206      }
207      catch (const C2&)
208      {
209          assert(false);
210      }
211  }
212  
213  int main(int, char**)
214  {
215      try
216      {
217          f5();
218          assert(false);
219      }
220      catch (...)
221      {
222      }
223      assert(A::count == 0);
224      assert(C1::count == 0);
225      assert(C2::count == 0);
226      assert(B::count == 0);
227  
228      return 0;
229  }