annotate libcxxabi/test/test_vector1.pass.cpp @ 192:d7606dcf6fce

Added tag llvm10 for changeset 0572611fdcc8
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 14 Dec 2020 18:01:34 +0900
parents 1d019706d866
children 2e18cbf3894f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===---------------------------- test_vector.cpp -------------------------===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8
anatofuz
parents:
diff changeset
9 #include "cxxabi.h"
anatofuz
parents:
diff changeset
10
anatofuz
parents:
diff changeset
11 #include <iostream>
anatofuz
parents:
diff changeset
12 #include <cstdlib>
anatofuz
parents:
diff changeset
13 #include <cassert>
anatofuz
parents:
diff changeset
14
anatofuz
parents:
diff changeset
15 // Wrapper routines
anatofuz
parents:
diff changeset
16 void *my_alloc2 ( size_t sz ) {
anatofuz
parents:
diff changeset
17 void *p = std::malloc ( sz );
anatofuz
parents:
diff changeset
18 // std::printf ( "Allocated %ld bytes at %lx\n", sz, (unsigned long) p );
anatofuz
parents:
diff changeset
19 return p;
anatofuz
parents:
diff changeset
20 }
anatofuz
parents:
diff changeset
21
anatofuz
parents:
diff changeset
22 void my_dealloc2 ( void *p ) {
anatofuz
parents:
diff changeset
23 // std::printf ( "Freeing %lx\n", (unsigned long) p );
anatofuz
parents:
diff changeset
24 std::free ( p );
anatofuz
parents:
diff changeset
25 }
anatofuz
parents:
diff changeset
26
anatofuz
parents:
diff changeset
27 void my_dealloc3 ( void *p, size_t ) {
anatofuz
parents:
diff changeset
28 // std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz );
anatofuz
parents:
diff changeset
29 std::free ( p );
anatofuz
parents:
diff changeset
30 }
anatofuz
parents:
diff changeset
31
anatofuz
parents:
diff changeset
32 void my_construct ( void * ) {
anatofuz
parents:
diff changeset
33 // std::printf ( "Constructing %lx\n", (unsigned long) p );
anatofuz
parents:
diff changeset
34 }
anatofuz
parents:
diff changeset
35
anatofuz
parents:
diff changeset
36 void my_destruct ( void * ) {
anatofuz
parents:
diff changeset
37 // std::printf ( "Destructing %lx\n", (unsigned long) p );
anatofuz
parents:
diff changeset
38 }
anatofuz
parents:
diff changeset
39
anatofuz
parents:
diff changeset
40 int gCounter;
anatofuz
parents:
diff changeset
41 void count_construct ( void * ) { ++gCounter; }
anatofuz
parents:
diff changeset
42 void count_destruct ( void * ) { --gCounter; }
anatofuz
parents:
diff changeset
43
anatofuz
parents:
diff changeset
44
anatofuz
parents:
diff changeset
45 int gConstructorCounter;
anatofuz
parents:
diff changeset
46 int gConstructorThrowTarget;
anatofuz
parents:
diff changeset
47 int gDestructorCounter;
anatofuz
parents:
diff changeset
48 int gDestructorThrowTarget;
anatofuz
parents:
diff changeset
49 void throw_construct ( void * ) {
anatofuz
parents:
diff changeset
50 #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
anatofuz
parents:
diff changeset
51 if ( gConstructorCounter == gConstructorThrowTarget )
anatofuz
parents:
diff changeset
52 throw 1;
anatofuz
parents:
diff changeset
53 ++gConstructorCounter;
anatofuz
parents:
diff changeset
54 #endif
anatofuz
parents:
diff changeset
55 }
anatofuz
parents:
diff changeset
56 void throw_destruct ( void * ) {
anatofuz
parents:
diff changeset
57 #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
anatofuz
parents:
diff changeset
58 if ( ++gDestructorCounter == gDestructorThrowTarget )
anatofuz
parents:
diff changeset
59 throw 2;
anatofuz
parents:
diff changeset
60 #endif
anatofuz
parents:
diff changeset
61 }
anatofuz
parents:
diff changeset
62
anatofuz
parents:
diff changeset
63 #if __cplusplus >= 201103L
anatofuz
parents:
diff changeset
64 # define CAN_THROW noexcept(false)
anatofuz
parents:
diff changeset
65 #else
anatofuz
parents:
diff changeset
66 # define CAN_THROW
anatofuz
parents:
diff changeset
67 #endif
anatofuz
parents:
diff changeset
68
anatofuz
parents:
diff changeset
69 struct vec_on_stack {
anatofuz
parents:
diff changeset
70 void *storage;
anatofuz
parents:
diff changeset
71 vec_on_stack () : storage ( __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct )) {}
anatofuz
parents:
diff changeset
72 ~vec_on_stack () CAN_THROW {__cxxabiv1::__cxa_vec_delete ( storage, 40, 8, throw_destruct ); }
anatofuz
parents:
diff changeset
73 };
anatofuz
parents:
diff changeset
74
anatofuz
parents:
diff changeset
75 // Test calls with empty constructors and destructors
anatofuz
parents:
diff changeset
76 int test_empty ( ) {
anatofuz
parents:
diff changeset
77 void *one, *two, *three;
anatofuz
parents:
diff changeset
78
anatofuz
parents:
diff changeset
79 // Try with no padding and no con/destructors
anatofuz
parents:
diff changeset
80 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, NULL, NULL );
anatofuz
parents:
diff changeset
81 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, NULL, NULL, my_alloc2, my_dealloc2 );
anatofuz
parents:
diff changeset
82 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, NULL, NULL, my_alloc2, my_dealloc3 );
anatofuz
parents:
diff changeset
83
anatofuz
parents:
diff changeset
84 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, NULL );
anatofuz
parents:
diff changeset
85 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, NULL, my_dealloc2 );
anatofuz
parents:
diff changeset
86 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, NULL, my_dealloc3 );
anatofuz
parents:
diff changeset
87
anatofuz
parents:
diff changeset
88 // Try with no padding
anatofuz
parents:
diff changeset
89 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, my_construct, my_destruct );
anatofuz
parents:
diff changeset
90 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc2 );
anatofuz
parents:
diff changeset
91 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc3 );
anatofuz
parents:
diff changeset
92
anatofuz
parents:
diff changeset
93 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, my_destruct );
anatofuz
parents:
diff changeset
94 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, my_destruct, my_dealloc2 );
anatofuz
parents:
diff changeset
95 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, my_destruct, my_dealloc3 );
anatofuz
parents:
diff changeset
96
anatofuz
parents:
diff changeset
97 // Padding and no con/destructors
anatofuz
parents:
diff changeset
98 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, NULL, NULL );
anatofuz
parents:
diff changeset
99 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc2 );
anatofuz
parents:
diff changeset
100 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc3 );
anatofuz
parents:
diff changeset
101
anatofuz
parents:
diff changeset
102 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, NULL );
anatofuz
parents:
diff changeset
103 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, NULL, my_dealloc2 );
anatofuz
parents:
diff changeset
104 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, NULL, my_dealloc3 );
anatofuz
parents:
diff changeset
105
anatofuz
parents:
diff changeset
106 // Padding with con/destructors
anatofuz
parents:
diff changeset
107 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, my_construct, my_destruct );
anatofuz
parents:
diff changeset
108 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc2 );
anatofuz
parents:
diff changeset
109 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc3 );
anatofuz
parents:
diff changeset
110
anatofuz
parents:
diff changeset
111 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, my_destruct );
anatofuz
parents:
diff changeset
112 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, my_destruct, my_dealloc2 );
anatofuz
parents:
diff changeset
113 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, my_destruct, my_dealloc3 );
anatofuz
parents:
diff changeset
114
anatofuz
parents:
diff changeset
115 return 0;
anatofuz
parents:
diff changeset
116 }
anatofuz
parents:
diff changeset
117
anatofuz
parents:
diff changeset
118 // Make sure the constructors and destructors are matched
anatofuz
parents:
diff changeset
119 int test_counted ( ) {
anatofuz
parents:
diff changeset
120 int retVal = 0;
anatofuz
parents:
diff changeset
121 void *one, *two, *three;
anatofuz
parents:
diff changeset
122
anatofuz
parents:
diff changeset
123 // Try with no padding
anatofuz
parents:
diff changeset
124 gCounter = 0;
anatofuz
parents:
diff changeset
125 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, count_construct, count_destruct );
anatofuz
parents:
diff changeset
126 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc2 );
anatofuz
parents:
diff changeset
127 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc3 );
anatofuz
parents:
diff changeset
128
anatofuz
parents:
diff changeset
129 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, count_destruct );
anatofuz
parents:
diff changeset
130 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, count_destruct, my_dealloc2 );
anatofuz
parents:
diff changeset
131 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, count_destruct, my_dealloc3 );
anatofuz
parents:
diff changeset
132
anatofuz
parents:
diff changeset
133 // Since there was no padding, the # of elements in the array are not stored
anatofuz
parents:
diff changeset
134 // and the destructors are not called.
anatofuz
parents:
diff changeset
135 if ( gCounter != 30 ) {
anatofuz
parents:
diff changeset
136 std::cerr << "Mismatched Constructor/Destructor calls (1)" << std::endl;
anatofuz
parents:
diff changeset
137 std::cerr << " Expected 30, got " << gCounter << std::endl;
anatofuz
parents:
diff changeset
138 retVal = 1;
anatofuz
parents:
diff changeset
139 }
anatofuz
parents:
diff changeset
140
anatofuz
parents:
diff changeset
141 gCounter = 0;
anatofuz
parents:
diff changeset
142 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, count_construct, count_destruct );
anatofuz
parents:
diff changeset
143 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc2 );
anatofuz
parents:
diff changeset
144 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc3 );
anatofuz
parents:
diff changeset
145
anatofuz
parents:
diff changeset
146 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, count_destruct );
anatofuz
parents:
diff changeset
147 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, count_destruct, my_dealloc2 );
anatofuz
parents:
diff changeset
148 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, count_destruct, my_dealloc3 );
anatofuz
parents:
diff changeset
149
anatofuz
parents:
diff changeset
150 if ( gCounter != 0 ) {
anatofuz
parents:
diff changeset
151 std::cerr << "Mismatched Constructor/Destructor calls (2)" << std::endl;
anatofuz
parents:
diff changeset
152 std::cerr << " Expected 0, got " << gCounter << std::endl;
anatofuz
parents:
diff changeset
153 retVal = 1;
anatofuz
parents:
diff changeset
154 }
anatofuz
parents:
diff changeset
155
anatofuz
parents:
diff changeset
156 return retVal;
anatofuz
parents:
diff changeset
157 }
anatofuz
parents:
diff changeset
158
anatofuz
parents:
diff changeset
159 #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
anatofuz
parents:
diff changeset
160 // Make sure the constructors and destructors are matched
anatofuz
parents:
diff changeset
161 int test_exception_in_constructor ( ) {
anatofuz
parents:
diff changeset
162 int retVal = 0;
anatofuz
parents:
diff changeset
163 void *one, *two, *three;
anatofuz
parents:
diff changeset
164
anatofuz
parents:
diff changeset
165 // Try with no padding
anatofuz
parents:
diff changeset
166 gConstructorCounter = gDestructorCounter = 0;
anatofuz
parents:
diff changeset
167 gConstructorThrowTarget = 15;
anatofuz
parents:
diff changeset
168 gDestructorThrowTarget = -1;
anatofuz
parents:
diff changeset
169 try {
anatofuz
parents:
diff changeset
170 one = two = three = NULL;
anatofuz
parents:
diff changeset
171 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, throw_construct, throw_destruct );
anatofuz
parents:
diff changeset
172 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
anatofuz
parents:
diff changeset
173 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );
anatofuz
parents:
diff changeset
174 }
anatofuz
parents:
diff changeset
175 catch ( int i ) {}
anatofuz
parents:
diff changeset
176
anatofuz
parents:
diff changeset
177 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, throw_destruct );
anatofuz
parents:
diff changeset
178 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, throw_destruct, my_dealloc2 );
anatofuz
parents:
diff changeset
179 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, throw_destruct, my_dealloc3 );
anatofuz
parents:
diff changeset
180
anatofuz
parents:
diff changeset
181 // Since there was no padding, the # of elements in the array are not stored
anatofuz
parents:
diff changeset
182 // and the destructors are not called.
anatofuz
parents:
diff changeset
183 // Since we threw after 15 calls to the constructor, we should see 5 calls to
anatofuz
parents:
diff changeset
184 // the destructor from the partially constructed array.
anatofuz
parents:
diff changeset
185 if ( gConstructorCounter - gDestructorCounter != 10 ) {
anatofuz
parents:
diff changeset
186 std::cerr << "Mismatched Constructor/Destructor calls (1C)" << std::endl;
anatofuz
parents:
diff changeset
187 std::cerr << gConstructorCounter << " constructors, but " <<
anatofuz
parents:
diff changeset
188 gDestructorCounter << " destructors" << std::endl;
anatofuz
parents:
diff changeset
189 retVal = 1;
anatofuz
parents:
diff changeset
190 }
anatofuz
parents:
diff changeset
191
anatofuz
parents:
diff changeset
192 gConstructorCounter = gDestructorCounter = 0;
anatofuz
parents:
diff changeset
193 gConstructorThrowTarget = 15;
anatofuz
parents:
diff changeset
194 gDestructorThrowTarget = -1;
anatofuz
parents:
diff changeset
195 try {
anatofuz
parents:
diff changeset
196 one = two = three = NULL;
anatofuz
parents:
diff changeset
197 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct );
anatofuz
parents:
diff changeset
198 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
anatofuz
parents:
diff changeset
199 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );
anatofuz
parents:
diff changeset
200 }
anatofuz
parents:
diff changeset
201 catch ( int i ) {}
anatofuz
parents:
diff changeset
202
anatofuz
parents:
diff changeset
203 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, throw_destruct );
anatofuz
parents:
diff changeset
204 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, throw_destruct, my_dealloc2 );
anatofuz
parents:
diff changeset
205 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, throw_destruct, my_dealloc3 );
anatofuz
parents:
diff changeset
206
anatofuz
parents:
diff changeset
207 if ( gConstructorCounter != gDestructorCounter ) {
anatofuz
parents:
diff changeset
208 std::cerr << "Mismatched Constructor/Destructor calls (2C)" << std::endl;
anatofuz
parents:
diff changeset
209 std::cerr << gConstructorCounter << " constructors, but " <<
anatofuz
parents:
diff changeset
210 gDestructorCounter << " destructors" << std::endl;
anatofuz
parents:
diff changeset
211 retVal = 1;
anatofuz
parents:
diff changeset
212 }
anatofuz
parents:
diff changeset
213
anatofuz
parents:
diff changeset
214 return retVal;
anatofuz
parents:
diff changeset
215 }
anatofuz
parents:
diff changeset
216 #endif
anatofuz
parents:
diff changeset
217
anatofuz
parents:
diff changeset
218 #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
anatofuz
parents:
diff changeset
219 // Make sure the constructors and destructors are matched
anatofuz
parents:
diff changeset
220 int test_exception_in_destructor ( ) {
anatofuz
parents:
diff changeset
221 int retVal = 0;
anatofuz
parents:
diff changeset
222 void *one, *two, *three;
anatofuz
parents:
diff changeset
223 one = two = three = NULL;
anatofuz
parents:
diff changeset
224
anatofuz
parents:
diff changeset
225 // Throw from within a destructor
anatofuz
parents:
diff changeset
226 gConstructorCounter = gDestructorCounter = 0;
anatofuz
parents:
diff changeset
227 gConstructorThrowTarget = -1;
anatofuz
parents:
diff changeset
228 gDestructorThrowTarget = 15;
anatofuz
parents:
diff changeset
229 try {
anatofuz
parents:
diff changeset
230 one = two = NULL;
anatofuz
parents:
diff changeset
231 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct );
anatofuz
parents:
diff changeset
232 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
anatofuz
parents:
diff changeset
233 }
anatofuz
parents:
diff changeset
234 catch ( int i ) {}
anatofuz
parents:
diff changeset
235
anatofuz
parents:
diff changeset
236 try {
anatofuz
parents:
diff changeset
237 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, throw_destruct );
anatofuz
parents:
diff changeset
238 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, throw_destruct, my_dealloc2 );
anatofuz
parents:
diff changeset
239 assert(false);
anatofuz
parents:
diff changeset
240 }
anatofuz
parents:
diff changeset
241 catch ( int i ) {}
anatofuz
parents:
diff changeset
242
anatofuz
parents:
diff changeset
243 // We should have thrown in the middle of cleaning up "two", which means that
anatofuz
parents:
diff changeset
244 // there should be 20 calls to the destructor and the try block should exit
anatofuz
parents:
diff changeset
245 // before the assertion.
anatofuz
parents:
diff changeset
246 if ( gConstructorCounter != 20 || gDestructorCounter != 20 ) {
anatofuz
parents:
diff changeset
247 std::cerr << "Unexpected Constructor/Destructor calls (1D)" << std::endl;
anatofuz
parents:
diff changeset
248 std::cerr << "Expected (20, 20), but got (" << gConstructorCounter << ", " <<
anatofuz
parents:
diff changeset
249 gDestructorCounter << ")" << std::endl;
anatofuz
parents:
diff changeset
250 retVal = 1;
anatofuz
parents:
diff changeset
251 }
anatofuz
parents:
diff changeset
252
anatofuz
parents:
diff changeset
253 // Try throwing from a destructor - should be fine.
anatofuz
parents:
diff changeset
254 gConstructorCounter = gDestructorCounter = 0;
anatofuz
parents:
diff changeset
255 gConstructorThrowTarget = -1;
anatofuz
parents:
diff changeset
256 gDestructorThrowTarget = 5;
anatofuz
parents:
diff changeset
257 try { vec_on_stack v; }
anatofuz
parents:
diff changeset
258 catch ( int i ) {}
anatofuz
parents:
diff changeset
259
anatofuz
parents:
diff changeset
260 if ( gConstructorCounter != gDestructorCounter ) {
anatofuz
parents:
diff changeset
261 std::cerr << "Mismatched Constructor/Destructor calls (2D)" << std::endl;
anatofuz
parents:
diff changeset
262 std::cerr << gConstructorCounter << " constructors, but " <<
anatofuz
parents:
diff changeset
263 gDestructorCounter << " destructors" << std::endl;
anatofuz
parents:
diff changeset
264 retVal = 1;
anatofuz
parents:
diff changeset
265 }
anatofuz
parents:
diff changeset
266
anatofuz
parents:
diff changeset
267 return retVal;
anatofuz
parents:
diff changeset
268 }
anatofuz
parents:
diff changeset
269 #endif
anatofuz
parents:
diff changeset
270
anatofuz
parents:
diff changeset
271 int main () {
anatofuz
parents:
diff changeset
272 int retVal = 0;
anatofuz
parents:
diff changeset
273 retVal += test_empty ();
anatofuz
parents:
diff changeset
274 retVal += test_counted ();
anatofuz
parents:
diff changeset
275 #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
anatofuz
parents:
diff changeset
276 retVal += test_exception_in_constructor ();
anatofuz
parents:
diff changeset
277 retVal += test_exception_in_destructor ();
anatofuz
parents:
diff changeset
278 #endif
anatofuz
parents:
diff changeset
279 return retVal;
anatofuz
parents:
diff changeset
280 }