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