1  /* { dg-do run } */
       2  /* { dg-options "-fsanitize=bounds -Wall -Wextra -Wno-unused -Wno-array-bounds" } */
       3  
       4  /* Test flexible array member-like arrays.  Normal flexible array members
       5     are tested in bounds-1.c.  Test non-strict mode.  */
       6  
       7  __attribute__ ((noinline, noclone))
       8  void
       9  fn1 (void)
      10  {
      11    volatile struct S { char a[1]; char b; } s;
      12    volatile int i;
      13    asm ("" : : "r" (&s.a) : "memory");
      14    i = s.a[0]; // OK
      15    asm ("" : : "r" (&s.a) : "memory");
      16    i = s.a[1]; // error
      17    volatile struct S *p = &s;
      18    asm ("" : : "r" (&p->a) : "memory");
      19    i = p->a[0]; // OK
      20    asm ("" : : "r" (&p->a) : "memory");
      21    i = p->a[1]; // error
      22  }
      23  
      24  __attribute__ ((noinline, noclone))
      25  void
      26  fn2 (void)
      27  {
      28    struct S { int c; char d[4]; };
      29    volatile struct T { int e; struct S f; int g; } t;
      30    volatile int i;
      31    asm ("" : : "r" (&t.f.d) : "memory");
      32    i = t.f.d[3]; // OK
      33    asm ("" : : "r" (&t.f.d) : "memory");
      34    i = t.f.d[4]; // error
      35    volatile struct T *p = &t;
      36    asm ("" : : "r" (&p->f.d) : "memory");
      37    i = p->f.d[3]; // OK
      38    asm ("" : : "r" (&p->f.d) : "memory");
      39    i = p->f.d[4]; // error
      40  }
      41  
      42  __attribute__ ((noinline, noclone))
      43  void
      44  fn3 (void)
      45  {
      46    volatile struct S { char b; char a[1]; } s;
      47    volatile int i;
      48    asm ("" : : "r" (&s.a) : "memory");
      49    i = s.a[0]; // OK
      50    asm ("" : : "r" (&s.a) : "memory");
      51    i = s.a[1]; // error
      52    volatile struct S *p = &s;
      53    asm ("" : : "r" (&p->a) : "memory");
      54    i = p->a[0]; // OK
      55    asm ("" : : "r" (&p->a) : "memory");
      56    i = p->a[1]; // error in strict mode
      57  }
      58  
      59  __attribute__ ((noinline, noclone))
      60  void
      61  fn4 (void)
      62  {
      63    volatile struct S { char b; char a[1]; } s;
      64    volatile struct T { struct S s; int i; } t;
      65    volatile int i;
      66    asm ("" : : "r" (&t.s.a) : "memory");
      67    i = t.s.a[0]; // OK
      68    asm ("" : : "r" (&t.s.a) : "memory");
      69    i = t.s.a[1]; // error
      70    volatile struct T *pt = &t;
      71    asm ("" : : "r" (&pt->s.a) : "memory");
      72    i = pt->s.a[0]; // OK
      73    asm ("" : : "r" (&pt->s.a) : "memory");
      74    i = pt->s.a[1]; // error
      75  }
      76  
      77  __attribute__ ((noinline, noclone))
      78  void
      79  fn5 (void)
      80  {
      81    volatile struct S { char b; char a[1]; } s;
      82    volatile struct U { int a; struct S s; } u;
      83    volatile int i;
      84    asm ("" : : "r" (&u.s.a) : "memory");
      85    i = u.s.a[0]; // OK
      86    asm ("" : : "r" (&u.s.a) : "memory");
      87    i = u.s.a[1]; // error
      88    volatile struct U *pu = &u;
      89    asm ("" : : "r" (&pu->s.a) : "memory");
      90    i = pu->s.a[0]; // OK
      91    asm ("" : : "r" (&pu->s.a) : "memory");
      92    i = pu->s.a[1]; // error in strict mode
      93  }
      94  
      95  int
      96  main (void)
      97  {
      98    fn1 ();
      99    fn2 ();
     100    fn3 ();
     101    fn4 ();
     102    fn5 ();
     103    return 0;
     104  }
     105  
     106  /* { dg-output "index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
     107  /* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
     108  /* { dg-output "\[^\n\r]*index 4 out of bounds for type 'char \\\[4\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
     109  /* { dg-output "\[^\n\r]*index 4 out of bounds for type 'char \\\[4\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
     110  /* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
     111  /* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
     112  /* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
     113  /* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'" } */