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