(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
builtin-object-size-19.c
       1  /* PR tree-optimization/88372 - alloc_size attribute is ignored
       2     on function pointers { dg-do compile }
       3     { dg-options "-O2 -fdump-tree-optimized" } */
       4  
       5  typedef __SIZE_TYPE__ size_t;
       6  
       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__)
      11  
      12  #define FAIL(name) do {				\
      13      extern void FAILNAME (name) (void);		\
      14      FAILNAME (name)();				\
      15    } while (0)
      16  
      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.  */
      22  #define ELIM(expr)							\
      23    if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
      24  
      25  void sink (void*);
      26  
      27  #define T(alloc, n) do {			\
      28      void *p = alloc;				\
      29      sink (p);					\
      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));	\
      34    } while (0)
      35  
      36  
      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);
      39  
      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);
      43  
      44  void test_alloc_ptr (alloc_1_2_t *alloc_1_2)
      45  {
      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);
      50  
      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);
      55  
      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);
      60  }
      61  
      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.  */
      65  
      66  typedef void *(allocfn_1) (size_t);
      67  typedef void *(allocfn_1_2) (size_t, size_t);
      68  
      69  static inline void *
      70  call_alloc (allocfn_1 *fn1, allocfn_1_2 *fn2, size_t n1, size_t n2)
      71  {
      72    return fn1 ? fn1 (n1) : fn2 (n1, n2);
      73  }
      74  
      75  static inline void *
      76  call_malloc (size_t n)
      77  {
      78    return call_alloc (__builtin_malloc, 0, n, 0);
      79  }
      80  
      81  static inline void *
      82  call_calloc (size_t n1, size_t n2)
      83  {
      84    return call_alloc (0, __builtin_calloc, n1, n2);
      85  }
      86  
      87  void test_builtin_ptr (void)
      88  {
      89    T (call_malloc (0), 0);
      90    T (call_malloc (1), 1);
      91    T (call_malloc (9), 9);
      92  
      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);
      99  }
     100  
     101  /* { dg-final { scan-tree-dump-not "not_eliminated" "optimized" } } */