1 /* PR tree-optimization/88372 - alloc_size attribute is ignored
2 on function pointers { dg-do compile }
3 { dg-options "-O2 -fdump-tree-optimized" } */
5 typedef __SIZE_TYPE__
size_t;
7 #define ATTR(...) __attribute__ ((__VA_ARGS__))
8 #define CONCAT(x, y) x ## y
9 #define CAT(x, y) CONCAT (x, y)
10 #define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
12 #define FAIL(name) do { \
13 extern void FAILNAME (name) (void); \
17 /* Macro to emit a call to function named
18 call_in_true_branch_not_eliminated_on_line_NNN()
19 for each call that's expected to be eliminated. The dg-final
20 scan-tree-dump-time directive at the bottom of the test verifies
21 that no such call appears in output. */
23 if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
27 #define T(alloc, n) do { \
30 ELIM (n == __builtin_object_size (p, 0)); \
31 ELIM (n == __builtin_object_size (p, 1)); \
32 ELIM (n == __builtin_object_size (p, 2)); \
33 ELIM (n == __builtin_object_size (p, 3)); \
37 ATTR (alloc_size (1)) void* (*alloc_1_x
)(size_t, size_t);
38 ATTR (alloc_size (2)) void* (*alloc_x_2
)(size_t, size_t);
40 /* Verify that things work when attribute alloc_size is applied
41 to a typedef that is then used to declared a pointer. */
42 typedef ATTR (alloc_size (1, 2)) void* (alloc_1_2_t
)(size_t, size_t);
44 void test_alloc_ptr (alloc_1_2_t
*alloc_1_2
)
46 T (alloc_1_x (0, 0), 0);
47 T (alloc_1_x (1, 0), 1);
48 T (alloc_1_x (3, 0), 3);
49 T (alloc_1_x (9, 5), 9);
51 T (alloc_x_2 (0, 0), 0);
52 T (alloc_x_2 (1, 0), 0);
53 T (alloc_x_2 (0, 1), 1);
54 T (alloc_x_2 (9, 5), 5);
56 T (alloc_1_2 (0, 0), 0);
57 T (alloc_1_2 (1, 0), 0);
58 T (alloc_1_2 (0, 1), 0);
59 T (alloc_1_2 (9, 5), 45);
62 /* Verify that object size is detected even in indirect calls via
63 function pointers to built-in allocation functions, even without
64 explicit use of attribute alloc_size on the pointers. */
66 typedef void *(allocfn_1
) (size_t);
67 typedef void *(allocfn_1_2
) (size_t, size_t);
70 call_alloc (allocfn_1
*fn1
, allocfn_1_2
*fn2
, size_t n1
, size_t n2
)
72 return fn1
? fn1 (n1
) : fn2 (n1
, n2
);
76 call_malloc (size_t n
)
78 return call_alloc (__builtin_malloc
, 0, n
, 0);
82 call_calloc (size_t n1
, size_t n2
)
84 return call_alloc (0, __builtin_calloc
, n1
, n2
);
87 void test_builtin_ptr (void)
89 T (call_malloc (0), 0);
90 T (call_malloc (1), 1);
91 T (call_malloc (9), 9);
93 T (call_calloc (0, 0), 0);
94 T (call_calloc (0, 1), 0);
95 T (call_calloc (1, 0), 0);
96 T (call_calloc (1, 1), 1);
97 T (call_calloc (1, 3), 3);
98 T (call_calloc (2, 3), 6);
101 /* { dg-final { scan-tree-dump-not "not_eliminated" "optimized" } } */