view gcc/testsuite/gcc.dg/Warray-bounds-48.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
line wrap: on
line source

/* PR middle-end/91647 - missing -Warray-bounds accessing a zero-length array
   of a declared object
   { dg-do "compile" }
   { dg-options "-O2 -Wall" } */

typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;

void sink (void*);

/* Exercise a true flexible member.  */

struct AX
{
  int32_t n;
  int16_t ax[];     // { dg-message "while referencing 'ax'" "member" }
};

static void warn_ax_local (struct AX *p)
{
  p->ax[0] = 0;     // { dg-warning "\\\[-Warray-bounds" }
  p->ax[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
}

static void nowarn_ax_extern (struct AX *p)
{
  p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
}

static void warn_ax_local_buf (struct AX *p)
{
  p->ax[0] = 4; p->ax[1] = 5;

  p->ax[2] = 6;     // { dg-warning "\\\[-Warray-bounds" }
  p->ax[3] = 7;     // { dg-warning "\\\[-Warray-bounds" }
  p->ax[4] = 8;     // { dg-warning "\\\[-Warray-bounds" }
}

static void warn_ax_extern_buf (struct AX *p)
{
  p->ax[0] = 9; p->ax[1] = 10; p->ax[2] = 11;

  p->ax[3] = 12;    // { dg-warning "\\\[-Warray-bounds" }
  p->ax[4] = 13;    // { dg-warning "\\\[-Warray-bounds" }
  p->ax[5] = 14;    // { dg-warning "\\\[-Warray-bounds" }
}

static void nowarn_ax_extern_bufx (struct AX *p)
{
  p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
}

static void nowarn_ax_ref (struct AX *p)
{
  p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
}

void test_ax (struct AX *p, unsigned n)
{
  {
    struct AX sax;  // { dg-message "defined here" "struct definition" }
    warn_ax_local (&sax);
    sink (&sax);
  }

  {
    extern
      struct AX xsax;
    nowarn_ax_extern (&xsax);
    sink (&xsax);
  }

  {
    /* Verify out-of-bounds access to the local BUF is diagnosed.  */
    char ax_buf_p2[sizeof (struct AX) + 2 * sizeof (int16_t)];
    warn_ax_local_buf ((struct AX*) ax_buf_p2);
    sink (ax_buf_p2);
  }

  {
    /* Verify out-of-bounds access to the extern BUF with a known
       bound is diagnosed.  */
    extern char ax_buf_p3[sizeof (struct AX) + 3 * sizeof (int16_t)];
    warn_ax_extern_buf ((struct AX*) ax_buf_p3);
    sink (ax_buf_p3);
  }

  {
    /* Verify that accesses to BUFX with an unknown bound are not
       diagnosed.  */
    extern char bufx[];
    nowarn_ax_extern_bufx ((struct AX*) bufx);
    sink (bufx);
  }

  {
    /* Verify that accesses to BUFN with a runtime bound are not
       diagnosed.  */
    char bufn[n];
    nowarn_ax_extern_bufx ((struct AX*) bufn);
    sink (bufn);
  }

  nowarn_ax_ref (p);
}


/* Exercise a zero-length trailing member array.  It's the same as above
   except that extern declarations with no definitions are considered to
   have zero elements (they can't be initialized to have any).  */

struct A0
{
  int32_t n;
  int16_t a0[0];    // { dg-message "while referencing 'a0'" "member" }
};

static void warn_a0_local (struct A0 *p)
{
  p->a0[0] = 0;     // { dg-warning "\\\[-Warray-bounds" }
  p->a0[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
}

static void warn_a0_extern (struct A0 *p)
{
  p->a0[0] = 2;     // { dg-warning "\\\[-Warray-bounds" }
  p->a0[1] = 3;     // { dg-warning "\\\[-Warray-bounds" }
}

static void warn_a0_local_buf (struct A0 *p)
{
  p->a0[0] = 4; p->a0[1] = 5;

  p->a0[2] = 6;     // { dg-warning "\\\[-Warray-bounds" }
  p->a0[3] = 7;     // { dg-warning "\\\[-Warray-bounds" }
  p->a0[4] = 8;     // { dg-warning "\\\[-Warray-bounds" }
}

static void warn_a0_extern_buf (struct A0 *p)
{
  p->a0[0] = 9; p->a0[1] = 10; p->a0[2] = 11;

  p->a0[3] = 12;    // { dg-warning "\\\[-Warray-bounds" }
  p->a0[4] = 13;    // { dg-warning "\\\[-Warray-bounds" }
  p->a0[5] = 14;    // { dg-warning "\\\[-Warray-bounds" }
}

static void nowarn_a0_extern_bufx (struct A0 *p)
{
  p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999;
}

static void nowarn_a0_ref (struct A0 *p)
{
  p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999;
}

void test_a0 (struct A0 *p, unsigned n)
{
  {
    struct A0 sa0;  // { dg-message "defined here" "struct definition" }
    warn_a0_local (&sa0);
    sink (&sa0);
  }

  {
    extern
      struct A0 xsa0;  // { dg-message "defined here" "struct definition" }
    warn_a0_extern (&xsa0);
    sink (&xsa0);
  }

  {
    /* Verify out-of-bounds access to the local BUF is diagnosed.  */
    char a0_buf_p2[sizeof (struct A0) + 2 * sizeof (int16_t)];
    warn_a0_local_buf ((struct A0*) a0_buf_p2);
    sink (a0_buf_p2);
  }

  {
    /* Verify out-of-bounds access to the extern BUF with a known
       bound is diagnosed.  */
    extern char a0_buf_p3[sizeof (struct A0) + 3 * sizeof (int16_t)];
    warn_a0_extern_buf ((struct A0*) a0_buf_p3);
    sink (a0_buf_p3);
  }

  {
    /* Verify that accesses to BUFX with an unknown bound are not
       diagnosed.  */
    extern char bufx[];
    nowarn_a0_extern_bufx ((struct A0*) bufx);
    sink (bufx);
  }

  {
    /* Verify that accesses to BUFN with a runtime bound are not
       diagnosed.  */
    char bufn[n];
    nowarn_a0_extern_bufx ((struct A0*) bufn);
    sink (bufn);
  }

  nowarn_a0_ref (p);
}


/* Exercise a one-element trailing member array.  It's the same as above
   except that it has exactly one element.  */

struct A1
{
  int32_t n;
  int16_t a1[1];    // { dg-message "while referencing 'a1'" }
};

static void warn_a1_local_noinit (struct A1 *p)
{
  p->a1[0] = 0;
  p->a1[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
  p->a1[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
}

static void warn_a1_extern (struct A1 *p)
{
  p->a1[0] = 0;
  p->a1[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
  p->a1[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
}

static void warn_a1_init (struct A1 *p)
{
  p->a1[0] = 0;
  p->a1[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
  p->a1[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
}

static void warn_a1_local_buf (struct A1 *p)
{
  p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3;

  p->a1[4] = 4;     // { dg-warning "\\\[-Warray-bounds" }
}

static void warn_a1_extern_buf (struct A1 *p)
{
  p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3; p->a1[4] = 4;

  p->a1[5] = 5;     // { dg-warning "\\\[-Warray-bounds" }
}

static void nowarn_a1_extern_bufx (struct A1 *p)
{
  p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999;
}

static void nowarn_a1_ref (struct A1 *p)
{
  p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999;
}

void test_a1 (struct A1 *p, unsigned n)
{
  {
    struct A1 a1;
    warn_a1_local_noinit (&a1);
    sink (&a1);
  }

  {
    extern struct A1 a1x;
    warn_a1_extern (&a1x);
    sink (&a1x);
}
  {
    struct A1 a1 = { 0, { 1 } };
    warn_a1_init (&a1);
    sink (&a1);
  }

  {
    /* Verify out-of-bounds access to the local BUF is diagnosed.  */
    char buf_p2[sizeof (struct A1) + 2 * sizeof (int16_t)];
    warn_a1_local_buf ((struct A1*) buf_p2);
    sink (buf_p2);
  }

  {
    /* Verify out-of-bounds access to the extern BUF with a known
       bound is diagnosed.  */
    extern char a1_buf_p3[sizeof (struct A1) + 3 * sizeof (int16_t)];
    warn_a1_extern_buf ((struct A1*) a1_buf_p3);
    sink (a1_buf_p3);
  }

  {
    /* Verify that accesses to BUFX with an unknown bound are not
       diagnosed.  */
    extern char bufx[];
    nowarn_a1_extern_bufx ((struct A1*) bufx);
    sink (bufx);
  }

  {
    /* Verify that accesses to BUFN with a runtime bound are not
       diagnosed.  */
    char bufn[n];
    nowarn_a1_extern_bufx ((struct A1*) bufn);
    sink (bufn);
  }

  nowarn_a1_ref (p);
}


/* Exercise a two-element trailing member array.  It's treated
   the same as an interior array member.  */

struct A2
{
  int32_t n;
  int16_t a2[2];    // { dg-message "while referencing 'a2'" }
};

static void warn_a2_noinit (struct A2 *p)
{
  p->a2[0] = 0; p->a2[1] = 1;

  p->a2[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
}

static void warn_a2_init (struct A2 *p)
{
  p->a2[0] = 0; p->a2[1] = 1;

  p->a2[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
  p->a2[9] = 9;     // { dg-warning "\\\[-Warray-bounds" }
}

static void warn_a2_ref (struct A2 *p)
{
  p->a2[0] = 0; p->a2[1] = 1;

  p->a2[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
  p->a2[9] = 9;     // { dg-warning "\\\[-Warray-bounds" }
}

void test_a2 (struct A2 *p)
{
  {
    struct A2 a2;
    warn_a2_noinit (&a2);
    sink (&a2);
  }

  {
    struct A2 a2 = { 0, { 1, 2 } };
    warn_a2_init (&a2);
    sink (&a2);
  }

  warn_a2_ref (p);
}