1  /* { dg-skip-if "requires frame pointers" { *-*-* } "-fomit-frame-pointer" "" } */
       2  /* { dg-require-effective-target return_address } */
       3  
       4  extern void exit (int);
       5  extern void abort (void);
       6  extern void *alloca (__SIZE_TYPE__);
       7  char *dummy (void);
       8  
       9  #define NOINLINE __attribute__((noinline)) __attribute__ ((noclone))
      10  
      11  void *save_ret1[6];
      12  void *test4a (char *);
      13  void *test5a (char *);
      14  void *test6a (char *);
      15  
      16  void NOINLINE *test1 (void)
      17  {
      18    void * temp;
      19    temp = __builtin_return_address (0);
      20    return temp;
      21  }
      22  
      23  void NOINLINE *test2 (void)
      24  {
      25    void * temp;
      26    dummy ();
      27    temp = __builtin_return_address (0);
      28    return temp;
      29  }
      30  
      31  void NOINLINE *test3 (void)
      32  {
      33    void * temp;
      34    temp = __builtin_return_address (0);
      35    dummy ();
      36    return temp;
      37  }
      38  
      39  void NOINLINE *test4 (void)
      40  {
      41    char * save = (char*) alloca (4);
      42    
      43    return test4a (save);
      44  }
      45  
      46  void *NOINLINE test4a (char * p)
      47  {
      48    void * temp;
      49    temp = __builtin_return_address (1);
      50    return temp;
      51  }
      52  
      53  void NOINLINE *test5 (void)
      54  {
      55    char * save = (char*) alloca (4);
      56    
      57    return test5a (save);
      58  }
      59  
      60  void NOINLINE *test5a (char * p)
      61  {
      62    void * temp;
      63    dummy ();
      64    temp = __builtin_return_address (1);
      65    return temp;
      66  }
      67  
      68  void NOINLINE *test6 (void)
      69  {
      70    char * save = (char*) alloca (4);
      71    
      72    return test6a (save);
      73  }
      74  
      75  void NOINLINE *test6a (char * p)
      76  {
      77    void * temp;
      78    temp = __builtin_return_address (1);
      79    dummy ();
      80    return temp;
      81  }
      82  
      83  void *(*func1[6])(void) = { test1, test2, test3, test4, test5, test6 };
      84  
      85  char * NOINLINE call_func1 (int i)
      86  {
      87    save_ret1[i] = func1[i] ();
      88  }
      89  
      90  static void *ret_addr;
      91  void *save_ret2[6];
      92  void test10a (char *);
      93  void test11a (char *);
      94  void test12a (char *);
      95  
      96  void NOINLINE test7 (void)
      97  {
      98    ret_addr = __builtin_return_address (0);
      99    return;
     100  }
     101  
     102  void NOINLINE test8 (void)
     103  {
     104    dummy ();
     105    ret_addr = __builtin_return_address (0);
     106    return;
     107  }
     108  
     109  void NOINLINE test9 (void)
     110  {
     111    ret_addr = __builtin_return_address (0);
     112    dummy ();
     113    return;
     114  }
     115  
     116  void NOINLINE test10 (void)
     117  {
     118    char * save = (char*) alloca (4);
     119    
     120    test10a (save);
     121  }
     122  
     123  void NOINLINE test10a (char * p)
     124  {
     125    ret_addr = __builtin_return_address (1);
     126    return;
     127  }
     128  
     129  void NOINLINE test11 (void)
     130  {
     131    char * save = (char*) alloca (4);
     132    
     133    test11a (save);
     134  }
     135  
     136  void NOINLINE test11a (char * p)
     137  {
     138    dummy ();
     139    ret_addr = __builtin_return_address (1);
     140    return;
     141  }
     142  
     143  void NOINLINE test12 (void)
     144  {
     145    char * save = (char*) alloca (4);
     146    
     147    test12a (save);
     148  }
     149  
     150  void NOINLINE test12a (char * p)
     151  {
     152    ret_addr = __builtin_return_address (1);
     153    dummy ();
     154    return;
     155  }
     156  
     157  char * dummy (void)
     158  {
     159    char * save = (char*) alloca (4);
     160    
     161    return save;
     162  }
     163  
     164  void (*func2[6])(void) = { test7, test8, test9, test10, test11, test12 };
     165  
     166  void NOINLINE call_func2 (int i)
     167  {
     168    func2[i] ();
     169    save_ret2[i] = ret_addr;
     170  }
     171  
     172  int main (void)
     173  {
     174    int i;
     175  
     176    for (i = 0; i < 6; i++) {
     177      call_func1(i);
     178    }
     179  
     180    if (save_ret1[0] != save_ret1[1]
     181        || save_ret1[1] != save_ret1[2])
     182      abort ();
     183    if (save_ret1[3] != save_ret1[4]
     184        || save_ret1[4] != save_ret1[5])
     185      abort ();
     186    if (save_ret1[3] && save_ret1[0] != save_ret1[3])
     187      abort ();
     188  
     189  
     190    for (i = 0; i < 6; i++) {
     191      call_func2(i);
     192    }
     193  
     194    if (save_ret2[0] != save_ret2[1]
     195        || save_ret2[1] != save_ret2[2])
     196      abort ();
     197    if (save_ret2[3] != save_ret2[4]
     198        || save_ret2[4] != save_ret2[5])
     199      abort ();
     200    if (save_ret2[3] && save_ret2[0] != save_ret2[3])
     201      abort ();
     202  
     203    exit (0);
     204  }