1  /* PR 71831 - __builtin_object_size poor results with no optimization
       2     Verify that even without optimization __builtin_object_size result
       3     is folded into a constant and dead code that depends on it is
       4     eliminated.  */
       5  /* { dg-do compile } */
       6  /* { dg-options "-O0 -fdump-tree-ssa" } */
       7  
       8  #define concat(a, b)   a ## b
       9  #define CAT(a, b)      concat (a, b)
      10  
      11  /* Create a symbol name unique to each tes and object size type.  */
      12  #define SYM(type)      CAT (CAT (CAT (failure_on_line_, __LINE__), _type_), type)
      13  
      14  /* References to the following undefined symbol which is unique for each
      15     test case are expected to be eliminated.  */
      16  #define TEST_FAILURE(type)			\
      17    do {						\
      18      extern void SYM (type)(void);		\
      19      SYM (type)();				\
      20    } while (0)
      21  
      22  #define bos(obj, type) __builtin_object_size (obj, type)
      23  #define size(obj, n) ((size_t)n == X ? sizeof *obj : (size_t)n)
      24  
      25  #define test(expect, type, obj)			\
      26    do {						\
      27      if (bos (obj, type)	!= size (obj, expect))	\
      28        TEST_FAILURE (type);			\
      29    } while (0)
      30  
      31  #define FOLD_ALL(r0, r1, r2, r3, obj)		\
      32    do {						\
      33      test (r0, 0, obj);				\
      34      test (r1, 1, obj);				\
      35      test (r2, 2, obj);				\
      36      test (r3, 3, obj);				\
      37    } while (0)
      38  
      39  #define FOLD_0_2(r0, r1, r2, r3, obj)		\
      40    do {						\
      41      test (r0, 0, obj);				\
      42      test (r2, 2, obj);				\
      43    } while (0)
      44  
      45  /* For convenience.  Substitute for 'sizeof object' in test cases where
      46     the size can vary from target to target.  */
      47  #define X  (size_t)0xdeadbeef
      48  
      49  typedef __SIZE_TYPE__ size_t;
      50  
      51  extern char ax[];
      52  #ifndef __builtin_object_size
      53  char ax2[];               /* { dg-warning "assumed to have one element" } */
      54  #endif
      55  
      56  extern char a0[0];
      57  static char a1[1];
      58  static char a2[2];
      59  static char a9[9];
      60  
      61  #if __SIZEOF_SHORT__ == 4
      62  extern short ia0[0];
      63  static short ia1[1];
      64  static short ia9[9];
      65  #elif __SIZEOF_INT__ == 4
      66  extern int ia0[0];
      67  static int ia1[1];
      68  static int ia9[9];
      69  #elif __SIZEOF_LONG__ == 4
      70  extern long ia0[0];
      71  static long ia1[1];
      72  static long ia9[9];
      73  #endif
      74  
      75  static char a2x2[2][2];
      76  static char a3x5[3][5];
      77  
      78  struct Sx { char n, a[]; } sx;
      79  struct S0 { char n, a[0]; } s0;
      80  struct S1 { char n, a[1]; } s1;
      81  struct S2 { char n, a[2]; } s2;
      82  struct S9 { char n, a[9]; } s9;
      83  
      84  struct S2x2 { char n, a[2][2]; } s2x2;
      85  struct S3x5 { char n, a[3][5]; } s3x5;
      86  
      87  static __attribute__ ((noclone, noinline)) void
      88  test_arrays ()
      89  {
      90    FOLD_ALL (     1,       1,       1,       1,   ax2);
      91  
      92    FOLD_ALL (     1,       1,       1,       1,   a1);
      93    FOLD_ALL (     2,       2,       2,       2,   a2);
      94    FOLD_ALL (     9,       9,       9,       9,   a9);
      95  
      96    FOLD_ALL (     0,       0,       0,       0,   a0);
      97    FOLD_ALL (     1,       1,       1,       1,   ax2);
      98  
      99    FOLD_ALL (     0,       0,       0,       0,   ia0);
     100    FOLD_ALL (     4,       4,       4,       4,   ia1);
     101    FOLD_ALL (    36,      36,      36,      36,   ia9);
     102  
     103    /* Not all results for multidimensional arrays make sense (see
     104       bug 77293).  The expected results below simply reflect those
     105       obtained at -O2 (modulo the known limitations at -O1).  */
     106    FOLD_ALL (     4,       4,       4,       4,   a2x2);
     107    FOLD_ALL (     4,       4,       4,       4,   &a2x2[0]);
     108    FOLD_ALL (     4,       2,       4,       2,   &a2x2[0][0]);
     109    FOLD_0_2 (     0,  F1  (0),      0,       0,   &a2x2 + 1);
     110    FOLD_0_2 (     2,  F1 ( 2),      2,  F3 ( 2),  &a2x2[0] + 1);
     111    FOLD_0_2 (     3,  F1 ( 1),      3,  F3 ( 3),  &a2x2[0][0] + 1);
     112  
     113    FOLD_ALL (    15,      15,      15,      15,   a3x5);
     114    FOLD_ALL (    15,       5,      15,       5,   &a3x5[0][0] + 0);
     115    FOLD_0_2 (    14,  F1 ( 4),     14,  F3 (14),  &a3x5[0][0] + 1);
     116  
     117    FOLD_ALL (     1,       1,       1,       1,   a1 + 0);
     118    FOLD_0_2 (     0,  F1 ( 0),      0,       0,   &a1 + 1);
     119    FOLD_ALL (     2,       2,       2,       2,   a2 + 0);
     120    FOLD_0_2 (     1,  F1 ( 1),      1, F3 ( 1),   a2 + 1);
     121    FOLD_0_2 (     0,  F1 ( 0),      0,       0,   a2 + 2);
     122  }
     123  
     124  static __attribute__ ((noclone, noinline)) void
     125  test_structs (void)
     126  {
     127    /* The expected size of a declared object with a flexible array member
     128       is sizeof sx in all __builtin_object_size types.  */
     129    FOLD_ALL (     X,       X,       X,       X,   &sx);
     130  
     131    /* The expected size of a flexible array member of a declared object
     132       is zero.  */
     133    FOLD_ALL (     0,       0,       0,       0,   sx.a);
     134  
     135    /* The expected size of a declared object with a zero-length array member
     136       is sizeof sx in all __builtin_object_size types.  */
     137    FOLD_ALL (     X,       X,       X,       X,   &s0);
     138  
     139    /* The expected size of a zero-length array member of a declared object
     140       is zero.  */
     141    FOLD_ALL (     0,       0,       0,       0,   s0.a);
     142  
     143    FOLD_ALL (     X,       X,       X,       X,   &s1);
     144    FOLD_ALL (     1,       1,       1,       1,   s1.a);
     145    FOLD_0_2 (     0,  F1 (0),       0,       0,   s1.a + 1);
     146  
     147    FOLD_ALL (     X,       X,       X,       X,   &s9);
     148    FOLD_ALL (     9,       9,       9,       9,   s9.a);
     149    FOLD_ALL (     9,       9,       9,       9,   s9.a + 0);
     150    FOLD_0_2 (     8,  F1 ( 8),      8, F3 (  8),  s9.a + 1);
     151    FOLD_0_2 (     7,  F1 ( 7),      7, F3 (  7),  s9.a + 2);
     152    FOLD_0_2 (     0,  F1 ( 0),      0, F3 (  0),  s9.a + 9);
     153  }
     154  
     155  int
     156  main()
     157  {
     158    test_arrays ();
     159    test_structs ();
     160  
     161    return 0;
     162  }
     163  
     164  /* { dg-final { scan-tree-dump-not "failure_on_line" "ssa" } } */