1  /* { dg-require-effective-target return_address } */
       2  /* { dg-options "-finstrument-functions" } */
       3  /* { dg-xfail-run-if "" { powerpc-ibm-aix* } } */
       4  
       5  extern void abort (void);
       6  
       7  #define ASSERT(X)	if (!(X)) abort ();
       8  #define NOCHK __attribute__ ((no_instrument_function))
       9  
      10  int entry_calls, exit_calls;
      11  void (*last_fn_entered)();
      12  void (*last_fn_exited)();
      13  
      14  __attribute__ ((noinline))
      15  int main () NOCHK;
      16  
      17  __attribute__ ((noinline))
      18  void foo ()
      19  {
      20    ASSERT (last_fn_entered == foo);
      21  }
      22  
      23  __attribute__ ((noinline))
      24  static void foo2 ()
      25  {
      26    ASSERT (entry_calls == 1 && exit_calls == 0);
      27    ASSERT (last_fn_entered == foo2);
      28    foo ();
      29    ASSERT (entry_calls == 2 && exit_calls == 1);
      30    ASSERT (last_fn_entered == foo);
      31    ASSERT (last_fn_exited == foo);
      32  }
      33  
      34  __attribute__ ((noinline))
      35  void nfoo (void) NOCHK;
      36  void nfoo ()
      37  {
      38    ASSERT (entry_calls == 2 && exit_calls == 2);
      39    ASSERT (last_fn_entered == foo);
      40    ASSERT (last_fn_exited == foo2);
      41    foo ();
      42    ASSERT (entry_calls == 3 && exit_calls == 3);
      43    ASSERT (last_fn_entered == foo);
      44    ASSERT (last_fn_exited == foo);
      45  }
      46  
      47  int main ()
      48  {
      49    ASSERT (entry_calls == 0 && exit_calls == 0);
      50  
      51    foo2 ();
      52  
      53    ASSERT (entry_calls == 2 && exit_calls == 2);
      54    ASSERT (last_fn_entered == foo);
      55    ASSERT (last_fn_exited == foo2);
      56  
      57    nfoo ();
      58  
      59    ASSERT (entry_calls == 3 && exit_calls == 3);
      60    ASSERT (last_fn_entered == foo);
      61  
      62    return 0;
      63  }
      64  
      65  void __cyg_profile_func_enter (void*, void*) NOCHK;
      66  void __cyg_profile_func_exit (void*, void*) NOCHK;
      67  
      68  __attribute__ ((noinline))
      69  void __cyg_profile_func_enter (void *fn, void *parent)
      70  {
      71    entry_calls++;
      72    last_fn_entered = (void (*)())fn;
      73  }
      74  __attribute__ ((noinline))
      75  void __cyg_profile_func_exit (void *fn, void *parent)
      76  {
      77    exit_calls++;
      78    last_fn_exited = (void (*)())fn;
      79  }