1 /* Test STT_GNU_IFUNC symbols:
2 
3    1. Direct function call.
4    2. Function pointer.
5    3. Visibility with override.
6  */
7 
8 #include <stdlib.h>
9 
10 int ret_foo;
11 int ret_foo_hidden;
12 int ret_foo_protected;
13 
14 extern int foo (void);
15 extern int foo_protected (void);
16 
17 #ifndef FOO_P
18 typedef int (*foo_p) (void);
19 #endif
20 
21 foo_p foo_ptr = foo;
22 foo_p foo_procted_ptr = foo_protected;
23 
24 extern foo_p get_foo_p (void);
25 extern foo_p get_foo_hidden_p (void);
26 extern foo_p get_foo_protected_p (void);
27 
28 int
29 __attribute__ ((noinline))
foo(void)30 foo (void)
31 {
32   return -30;
33 }
34 
35 int
36 __attribute__ ((noinline))
foo_hidden(void)37 foo_hidden (void)
38 {
39   return -20;
40 }
41 
42 int
43 __attribute__ ((noinline))
foo_protected(void)44 foo_protected (void)
45 {
46   return -40;
47 }
48 
49 int
main(void)50 main (void)
51 {
52   foo_p p;
53 
54   if (foo_ptr != foo)
55     abort ();
56   if ((*foo_ptr) () != -30)
57     abort ();
58 
59   if (foo_procted_ptr != foo_protected)
60     abort ();
61   if ((*foo_procted_ptr) () != -40)
62     abort ();
63 
64   p = get_foo_p ();
65   if (p != foo)
66     abort ();
67   if (foo () != -30)
68     abort ();
69   if (ret_foo != -30 || (*p) () != ret_foo)
70     abort ();
71 
72   p = get_foo_hidden_p ();
73   if (foo_hidden () != -20)
74     abort ();
75   if (ret_foo_hidden != 1 || (*p) () != ret_foo_hidden)
76     abort ();
77 
78   p = get_foo_protected_p ();
79   if (p == foo_protected)
80     abort ();
81   if (foo_protected () != -40)
82     abort ();
83   if (ret_foo_protected != 0 || (*p) () != ret_foo_protected)
84     abort ();
85 
86   return 0;
87 }
88