Home | History | Annotate | Download | only in jni
      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 
     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;
     47   line_error(int i):line(i){}
     48 };
     49 
     50 #define CHECK(cond)  if(!(cond))throw line_error(__LINE__);
     51 
     52 struct 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 
     67 struct 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 
     80 void func(B* )
     81 {
     82   func_done = ++count;
     83 }
     84 
     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 
    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 
    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 
    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