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 28bool new_throws; 29bool ctor_throws; 30 31int new_done; 32int ctor_done; 33int func_done; 34int dtor_done; 35int delete_done; 36 37int count; 38 39void init() 40{ 41 new_throws = ctor_throws = false; 42 new_done = ctor_done = func_done = dtor_done = delete_done = count = 0; 43} 44 45struct line_error{ 46 int line; 47 line_error(int i):line(i){} 48}; 49 50#define CHECK(cond) if(!(cond))throw line_error(__LINE__); 51 52struct A{ 53 A(int){ 54 ctor_done = ++count; 55 if(ctor_throws) 56 throw 1; 57 } 58 A(const A&){ 59 CHECK(false); //no copy constructors in this code 60 } 61 ~A(){ 62 dtor_done = ++count; 63 } 64 A* addr(){return this;} 65}; 66 67struct B{ 68 B(A*){} 69 void* operator new(size_t s){ 70 new_done = ++count; 71 if(new_throws) 72 throw 1; 73 return malloc(s); 74 } 75 void operator delete(void *){ 76 delete_done = ++count; 77 } 78}; 79 80void func(B* ) 81{ 82 func_done = ++count; 83} 84 85void 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 109void 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 134void 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 159int 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