Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / tests / Compiler_Features_10_Test.cpp
blob4621bc62f5eeeb0f9d64155d583f5c52945a1239
1 /**
2 * @file
4 * This program checks if the compiler / platform supports exceptions,
5 * in particular, if raising exceptions in constructors work. The
6 * motivation for this test was a discussion on the development
7 * mailing list, and the documentation was captured in:
9 * http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=3715
12 #include "test_config.h"
14 // The first part of the test is to compile this line. If the program
15 // does not compile the platform is just too broken.
16 #include <memory>
18 // ... using exceptions with C++ also implies using the standard
19 // exceptions ...
20 #include <stdexcept>
22 // For extra challenge, we use the anonymous namespace
23 namespace
25 int constructors = 0;
26 int destructors = 0;
27 int allocs = 0;
28 int deallocs = 0;
29 bool had_failure = false;
31 void check_constructor_count(int expected,
32 char const * filename,
33 int lineno);
34 void check_destructor_count(int expected,
35 char const * filename,
36 int lineno);
37 void check_alloc_count(int expected,
38 char const * filename,
39 int lineno);
40 void reset_counts();
41 void never_reached(char const * filename,
42 int lineno);
43 int status();
45 /**
46 * @class Base
48 class Base
50 public:
51 Base()
53 ++constructors;
55 Base(Base const & )
57 ++constructors;
59 ~Base()
61 ++destructors;
64 void * operator new(size_t n)
66 ++allocs;
67 return ::operator new(n);
69 void operator delete(void * x)
71 ++deallocs;
72 return ::operator delete(x);
76 /**
77 * @class May_Pop
79 * Create a class that can raise exceptions in its constructor
82 class May_Pop : public Base
84 public:
85 explicit May_Pop(bool do_raise)
86 // Even if an exception is raised, the base object is fully
87 // constructed and must be fully destructed ...
88 : Base()
90 if (do_raise)
92 throw std::runtime_error("requested exception");
94 // ... if an exception is raised this object is never
95 // initialized and no constructor / destructor calls should take
96 // place ...
97 Base tmp;
102 * @class Aggregate
104 class Aggregate : public Base
106 private:
107 May_Pop m1;
108 May_Pop m2;
109 May_Pop m3;
111 public:
113 * Constructor. Element m1 is fully initialized, its constructors
114 * and destructors should run, m2 is partially initialized, its
115 * destructor never runs, m3 is never initialized, neither its
116 * constructor nor destructor runs.
118 Aggregate()
119 : Base()
120 , m1(false)
121 , m2(true)
122 , m3(false)
129 run_main (int, ACE_TCHAR *[])
131 ACE_START_TEST (ACE_TEXT("Compiler_Features_10_Test"));
134 // ... start the test fresh ...
135 reset_counts();
136 // Let's try to build a simple object and destroy it, without any
137 // exceptions raised ...
138 May_Pop m1(false);
139 // ... two instances of the base class should be created ...
140 check_constructor_count(2, __FILE__, __LINE__);
141 // ... but only one instance is destroyed at this point ...
142 check_destructor_count(1, __FILE__, __LINE__);
144 catch (...)
146 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Error: Unexpected exception caught\n")));
148 // ... now both instances are gone ...
149 check_destructor_count(2, __FILE__, __LINE__);
153 // ... start the test fresh ...
154 reset_counts();
155 // ... now raise an exception ...
156 May_Pop m1(true);
157 never_reached(__FILE__, __LINE__);
159 catch(...)
161 // ... only one instance gets created ...
162 check_constructor_count(1, __FILE__, __LINE__);
163 // ... and it is gone ...
164 check_destructor_count(1, __FILE__, __LINE__);
169 // ... start the test fresh ...
170 reset_counts();
171 // ... now build a complex object with a failure in the middle ...
172 Aggregate a;
173 never_reached(__FILE__, __LINE__);
175 catch(...)
177 // ... check the expectations ...
178 check_constructor_count(4, __FILE__, __LINE__);
179 check_destructor_count(4, __FILE__, __LINE__);
184 // ... start the test fresh ...
185 reset_counts();
186 std::unique_ptr<Aggregate> b(new Aggregate);
187 never_reached(__FILE__, __LINE__);
189 catch(...)
191 // ... check the expectations ...
192 check_constructor_count(4, __FILE__, __LINE__);
193 check_destructor_count(4, __FILE__, __LINE__);
194 check_alloc_count(1, __FILE__, __LINE__);
197 ACE_END_TEST;
198 return status();
201 namespace
203 void
204 check_constructor_count(int expected,
205 char const * filename,
206 int lineno)
208 if (constructors == expected)
210 return;
212 had_failure = true;
213 ACE_ERROR ((LM_ERROR,
214 ACE_TEXT("Expected %d constructor calls, had %d -- (%s:%d)\n"),
215 expected, constructors, filename, lineno));
218 void
219 check_destructor_count(int expected,
220 char const * filename,
221 int lineno)
223 if (destructors == expected)
225 return;
227 had_failure = true;
228 ACE_ERROR ((LM_ERROR,
229 ACE_TEXT("Expected %d destructor calls, had %d -- (%s:%d)\n"),
230 expected, destructors, filename, lineno));
233 void
234 check_alloc_count(int expected,
235 char const * filename,
236 int lineno)
238 if (allocs == expected && deallocs == expected)
240 return;
242 had_failure = true;
243 if (allocs != expected)
245 ACE_ERROR ((LM_ERROR,
246 ACE_TEXT("Expected %d alloc calls, had %d -- (%s:%d)\n"),
247 expected, allocs, filename, lineno));
249 if (deallocs != expected)
251 ACE_ERROR ((LM_ERROR,
252 ACE_TEXT("Expected %d dealloc calls, had %d -- (%s:%d)\n"),
253 expected, deallocs, filename, lineno));
257 void
258 never_reached(char const * filename,
259 int lineno)
261 had_failure = true;
262 ACE_ERROR ((LM_ERROR,
263 ACE_TEXT("Code should not have reached (%s:%d)\n"),
264 filename, lineno));
267 void
268 reset_counts()
270 constructors = 0;
271 destructors = 0;
272 allocs = 0;
273 deallocs = 0;
277 status()
279 if (had_failure)
281 return 1;
283 return 0;