1 // { dg-do run }
2 //
3 // Purpose: Check the lifetime of the temporaries.
4 //
5 // Lifetime of temporaries:
6 // egcs 2.92 performs cleanup for temporaries inside new expressions
7 // after the new is complete, not at the end of the full expression.
8 //
9 // In GCC, the operands are computed first. If no exception is raised, then
10 // the result should be "ctor, new, func, dtor". If the new operator throws
11 // the exception, then the result should be "ctor, new, dtor". If the
12 // constructor of the temporary throws the exception, then the result should
13 // be "ctor".
14 //
15 // In Clang, the new operator is called first. If no exception is raised,
16 // then the result should be "new, ctor, func, dtor". If the new operator
17 // throws the exception, then the result should be "new". If the constructor
18 // of the temporary throws the exception, then the result should be
19 // "new, ctor, delete".
20 //
21 // Both of them are allowed by the C++ language specification, so we are using
22 // #ifdef for different compilers.
23
24 #include <new>
25 #include <cstdlib>
26 #include <cstdio>
27
28 bool new_throws;
29 bool ctor_throws;
30
31 int new_done;
32 int ctor_done;
33 int func_done;
34 int dtor_done;
35 int delete_done;
36
37 int count;
38
init()39 void init()
40 {
41 new_throws = ctor_throws = false;
42 new_done = ctor_done = func_done = dtor_done = delete_done = count = 0;
43 }
44
45 struct line_error{
46 int line;
line_errorline_error47 line_error(int i):line(i){}
48 };
49
50 #define CHECK(cond) if(!(cond))throw line_error(__LINE__);
51
52 struct A{
AA53 A(int){
54 ctor_done = ++count;
55 if(ctor_throws)
56 throw 1;
57 }
AA58 A(const A&){
59 CHECK(false); //no copy constructors in this code
60 }
~AA61 ~A(){
62 dtor_done = ++count;
63 }
addrA64 A* addr(){return this;}
65 };
66
67 struct B{
BB68 B(A*){}
operator newB69 void* operator new(size_t s){
70 new_done = ++count;
71 if(new_throws)
72 throw 1;
73 return malloc(s);
74 }
operator deleteB75 void operator delete(void *){
76 delete_done = ++count;
77 }
78 };
79
func(B *)80 void func(B* )
81 {
82 func_done = ++count;
83 }
84
test1()85 void test1()
86 {
87 init();
88 try{
89 func(new B(A(10).addr()));
90 }catch(int){
91 }
92 #if defined(__clang__)
93 CHECK(new_done==1);
94 CHECK(ctor_done==2);
95 CHECK(func_done==3);
96 CHECK(dtor_done==4);
97 CHECK(delete_done==0);
98 #elif defined(__GNUC__)
99 CHECK(ctor_done==1);
100 CHECK(new_done==2);
101 CHECK(func_done==3);
102 CHECK(dtor_done==4);
103 CHECK(delete_done==0);
104 #else
105 #error "Unknown compiler"
106 #endif
107 }
108
test2()109 void test2()
110 {
111 init();
112 new_throws = true;
113 try{
114 func(new B(A(10).addr()));
115 }catch(int){
116 }
117 #if defined(__clang__)
118 CHECK(new_done==1);
119 CHECK(ctor_done==0);
120 CHECK(func_done==0);
121 CHECK(dtor_done==0);
122 CHECK(delete_done==0);
123 #elif defined(__GNUC__)
124 CHECK(ctor_done==1);
125 CHECK(new_done==2);
126 CHECK(func_done==0);
127 CHECK(dtor_done==3);
128 CHECK(delete_done==0);
129 #else
130 #error "Unknown compiler"
131 #endif
132 }
133
test3()134 void test3()
135 {
136 init();
137 ctor_throws = true;
138 try{
139 func(new B(A(10).addr()));
140 }catch(int){
141 }
142 #if defined(__clang__)
143 CHECK(new_done==1);
144 CHECK(ctor_done==2);
145 CHECK(func_done==0);
146 CHECK(dtor_done==0);
147 CHECK(delete_done==3);
148 #elif defined(__GNUC__)
149 CHECK(new_done==0);
150 CHECK(ctor_done==1);
151 CHECK(func_done==0);
152 CHECK(dtor_done==0);
153 CHECK(delete_done==0);
154 #else
155 #error "Unknown compiler"
156 #endif
157 }
158
main()159 int main()
160 {
161 try{
162 test1();
163 test2();
164 test3();
165 }catch(line_error e){
166 printf("Got error in line %d\n",e.line);
167 return 1;
168 }
169 return 0;
170 }
171