blob: 0d00c7451e24c944172390ca44be701aece27008 [file] [log] [blame]
Howard Hinnant372e2f42012-01-31 23:52:20 +00001//===---------------------- catch_class_03.cpp ----------------------------===//
2//
Chandler Carruth57b08b02019-01-19 10:56:40 +00003// 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
Howard Hinnant372e2f42012-01-31 23:52:20 +00006//
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.
13*/
14
Louis Dionne8c611142020-04-17 10:29:15 -040015// UNSUPPORTED: no-exceptions
Asiri Rathnayake57e446d2016-05-31 12:01:32 +000016
Louis Dionne8d313922020-10-30 17:33:02 -040017// 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
Howard Hinnant372e2f42012-01-31 23:52:20 +000023#include <exception>
24#include <stdlib.h>
25#include <assert.h>
26
Eric Fiselierf5ff11c2016-06-15 19:07:19 +000027// 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
Howard Hinnant372e2f42012-01-31 23:52:20 +000034struct 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
43int B::count = 0;
44
45struct C1
46 : 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
55int C1::count = 0;
56
57struct C2
58 : 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
67int C2::count = 0;
68
69struct A
70 : C1, C2
71{
72 static int count;
73 int id_;
74 explicit A(int id) : C1(id-1), C2(id-2), id_(id) {count++;}
75 A(const A& a) : C1(a.id_-1), C2(a.id_-2), id_(a.id_) {count++;}
76 ~A() {count--;}
77};
78
79int A::count = 0;
80
81void 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 == 2);
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&>(static_cast<C1&>(a)).id_ == 2);
97 assert(static_cast<B&>(static_cast<C2&>(a)).id_ == 1);
98 throw a;
99 assert(false);
100}
101
102void f2()
103{
104 try
105 {
106 assert(A::count == 0);
107 assert(C1::count == 0);
108 assert(C2::count == 0);
109 assert(B::count == 0);
110 f1();
111 assert(false);
112 }
113 catch (const A& a) // can catch A
114 {
115 assert(a.id_ == 5);
116 assert(static_cast<const C1&>(a).id_ == 4);
117 assert(static_cast<const C2&>(a).id_ == 3);
118 assert(static_cast<const B&>(static_cast<const C1&>(a)).id_ == 2);
119 assert(static_cast<const B&>(static_cast<const C2&>(a)).id_ == 1);
120 throw;
121 }
122 catch (const C1&)
123 {
124 assert(false);
125 }
126 catch (const C2&)
127 {
128 assert(false);
129 }
130 catch (const B&)
131 {
132 assert(false);
133 }
134}
135
136void f3()
137{
138 try
139 {
140 assert(A::count == 0);
141 assert(C1::count == 0);
142 assert(C2::count == 0);
143 assert(B::count == 0);
144 f2();
145 assert(false);
146 }
147 catch (const B& a) // can not catch B (ambiguous base)
148 {
149 assert(false);
150 }
151 catch (const C1& c1) // can catch C1
152 {
153 assert(c1.id_ == 4);
154 assert(static_cast<const B&>(c1).id_ == 2);
155 throw;
156 }
157 catch (const C2&)
158 {
159 assert(false);
160 }
161}
162
163void f4()
164{
165 try
166 {
167 assert(A::count == 0);
168 assert(C1::count == 0);
169 assert(C2::count == 0);
170 assert(B::count == 0);
171 f3();
172 assert(false);
173 }
174 catch (const B& a) // can not catch B (ambiguous base)
175 {
176 assert(false);
177 }
178 catch (const C2& c2) // can catch C2
179 {
180 assert(c2.id_ == 3);
181 assert(static_cast<const B&>(c2).id_ == 1);
182 throw;
183 }
184 catch (const C1&)
185 {
186 assert(false);
187 }
188}
189
Louis Dionne504bc072020-10-08 13:36:33 -0400190int main(int, char**)
Howard Hinnant372e2f42012-01-31 23:52:20 +0000191{
192 try
193 {
194 f4();
195 assert(false);
196 }
197 catch (...)
198 {
199 }
200 assert(A::count == 0);
201 assert(C1::count == 0);
202 assert(C2::count == 0);
203 assert(B::count == 0);
Louis Dionne504bc072020-10-08 13:36:33 -0400204
205 return 0;
Howard Hinnant372e2f42012-01-31 23:52:20 +0000206}