1 // Copyright (c) Microsoft. All rights reserved.
2 // Licensed under the MIT license. See LICENSE file in the project root for
3 // full license information.
4 
5 #include <stdlib.h>
6 #include <stdio.h>
7 
8 #define FALSE 0
9 #define TRUE 1
10 #define NO_CTOR_THROW 1
11 #define NO_DTOR_THROW 2
12 
13 #define TEST_DTOR
14 
15 #define MAX_OBJECTS 500
16 
17 #define NOEXCEPT(_x)
18 
19 int Object[MAX_OBJECTS];
20 int CurrentObjectNumber, ThrowCount, MaxObjectCount = 1;
21 int Fail;
22 
23 void FAIL(int i) {
24   printf("FAILED on %d\n", i);
25   Fail++;
26 }
27 
28 void dealloc(int i, int no_throw) {
29   /* Make sure i is valid, and object exists */
30   if (i < 0 || i >= MaxObjectCount || !Object[i])
31     FAIL(i);
32 
33   Object[i] = 0;
34 
35 /* Try throw in this dtor.. */
36 #ifdef TEST_DTOR
37   if (i + MaxObjectCount == ThrowCount && !no_throw) {
38     printf("Throwing\n");
39     throw(1);
40   }
41 #endif
42 }
43 
44 void alloc(int i, int no_throw) {
45   if (CurrentObjectNumber > MaxObjectCount)
46     MaxObjectCount = CurrentObjectNumber;
47 
48   /* Object already exists? */
49   if (Object[i])
50     FAIL(i);
51 
52   /* Try throw in this ctor.. */
53   if (i == ThrowCount && !no_throw) {
54     printf("Throwing\n");
55     throw(1);
56   }
57 
58   if (i >= MAX_OBJECTS) {
59     printf("\n*** Number of objects exceeded.  Increase MAX_OBJECTS ***\n\n");
60     FAIL(i);
61     i = 0;
62   }
63 
64   Object[i] = 1;
65 }
66 
67 class B {
68 public:
69   int i;
70   int flag;
71   B();
72   B(int);
73   ~B() NOEXCEPT(false);
74 };
75 
76 B::B() {
77   i = CurrentObjectNumber++;
78   printf("B ctor.  i = %d\n", i);
79   alloc(i, FALSE);
80 }
81 
82 B::B(int f) {
83   i = CurrentObjectNumber++;
84   flag = f;
85   printf("B ctor.  i = %d\n", i);
86   alloc(i, flag == NO_CTOR_THROW);
87 }
88 
89 B::~B() NOEXCEPT(false) {
90   printf("B dtor.  i = %d\n", i);
91   dealloc(i, flag == NO_DTOR_THROW);
92 }
93 
94 class A {
95 public:
96   int i;
97   A();
98   A(int) {
99     i = CurrentObjectNumber++;
100     printf("A(int) ctor.  i = %d\n", i);
101     alloc(i, FALSE);
102   }
103   A operator+(A a);
104   A(const A &a) {
105     /* Try objects in ctor */
106     B b1 = NO_DTOR_THROW, b2 = NO_DTOR_THROW;
107 
108     i = CurrentObjectNumber++;
109     printf("A copy ctor.  i = %d\n", i);
110     alloc(i, FALSE);
111   }
112 
113   ~A() NOEXCEPT(false) {
114     /* Try objects in dtor */
115     B b1 = NO_CTOR_THROW, b2 = NO_CTOR_THROW;
116 
117     printf("A dtor.  i = %d\n", i);
118     dealloc(i, FALSE);
119   };
120 };
121 
122 A::A() {
123   i = CurrentObjectNumber++;
124   printf("A ctor.  i = %d\n", i);
125   alloc(i, FALSE);
126 }
127 
128 A A::operator+(A a) {
129   printf("A%d + A%d\n", i, a.i);
130   return A();
131 }
132 
133 A foo(A a1, A a2) { return a1 + a2; };
134 
135 int bar() {
136   A a;
137 
138   return 666;
139 }
140 
141 void foo2(int i, A a1, A a2, A a3) {
142   if (i != 666)
143     FAIL(666);
144   foo(a1, a3);
145 }
146 
147 A test() {
148   puts("Try simple ctor");
149   A a1;
150 
151   puts("Try question op ctor");
152   A a2 = (ThrowCount & 1) ? A() : ThrowCount;
153 
154   puts("Try a more complex question op ctor");
155   A a3 = (ThrowCount & 1) ? A() + a1 + A() + a2 : a2 + A() + A() + ThrowCount;
156 
157   puts("Try mbarg copy ctors, and return UDT");
158   A a4 = foo(a1, a2);
159 
160   puts("Try a more complex mbarg copy ctors, and a function call");
161   foo2(bar(), a1 + a2, a2 + A() + a3 + a4, a3);
162 
163   puts("Try temporary expressions, and return UDT");
164   return a1 + A() + a2 + A() + a3 + a4;
165 }
166 
167 int main() {
168   int i;
169 
170   /* Call test(), with a different ctor/dtor throwing each time */
171   for (ThrowCount = 0; ThrowCount < MaxObjectCount * 2; ThrowCount++) {
172     printf("ThrowCount = %d   MaxObjectCount = %d\n", ThrowCount,
173            MaxObjectCount);
174 
175     CurrentObjectNumber = 0;
176 
177     try {
178       test();
179     } catch (int) {
180       printf("In catch\n");
181     }
182 
183     /* Any objects which didn't get dtor'd? */
184     for (i = 0; i < MaxObjectCount; i++) {
185       if (Object[i]) {
186         FAIL(i);
187         Object[i] = 0;
188       }
189     }
190 
191     printf("\n");
192   }
193 
194   printf("\n");
195   if (Fail)
196     printf("FAILED %d tests\n", Fail);
197   else
198     printf("Passed\n");
199 }
200