summaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2.c
blob: 841b2bfa1229c47159265353d7ae0e98cae3b977 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* Test to verify that -Wzero-length-bounds and not -Warray-bounds is
   issued for accesses to interior zero-length array members that are
   within the bounds of the enclosing struct.
   { dg-do compile }
   { dg-options "-O2 -Wall" } */

void sink (void*);

struct A { int i; };
struct B { int j; struct A a[0]; };

struct C
{
  struct B b1;
  struct B b2;
};


void test_B_ref (struct B *p)
{
  // References with negative indices are always diagnosed by -Warray-bounds
  // even though they could be considered the same as past the end accesses
  // to trailing zero-length arrays.
  p->a[-1].i = 0;       // { dg-warning "\\\[-Warray-bounds" }
  p->a[ 0].i = 0;
  p->a[ 1].i = 0;
  sink (p);

  p[1].a[-1].i = 0;     // { dg-warning "\\\[-Warray-bounds" }
  p[1].a[ 0].i = 0;
  p[1].a[ 1].i = 0;
}


void test_C_ref (struct C *p)
{
  p->b1.a[-1].i = 0;     // { dg-warning "\\\[-Warray-bounds" }
  p->b1.a[ 0].i = 0;     // { dg-warning "\\\[-Wzero-length-bounds" }
  p->b1.a[ 1].i = 0;     // { dg-warning "\\\[-Wzero-length-bounds" }

  // Accesses to trailing zero-length arrays are not diagnosed (should
  // they be?)
  p->b2.a[ 0].i = 0;
  p->b2.a[ 9].i = 0;
}


void test_C_decl (void)
{
  struct C c, *p = &c;

  p->b1.a[-1].i = 0;     // { dg-warning "\\\[-Warray-bounds" }

  // c.b1.a[0].i overlaps c.b2.j.
  p->b1.a[ 0].i = 0;     // { dg-warning "\\\[-Wzero-length-bounds" }

  // c.b1.a[1].i is past the end of c...
  p->b1.a[ 1].i = 0;     // { dg-warning "\\\[-Warray-bounds" }
  sink (p);

  // ...and so are references to all elements of c.b2.a
  p->b2.a[ 0].i = 0;     // { dg-warning "\\\[-Warray-bounds" }
  p->b2.a[ 1].i = 0;     // { dg-warning "\\\[-Warray-bounds" }
  sink (p);
}


char cbuf1[1 * sizeof (struct C)];
char cbuf2[2 * sizeof (struct C)] = { };

void test_C_global_buf (void)
{
  struct C *p = (struct C*)&cbuf1;

  p->b1.a[-1].i = 0;     // { dg-warning "\\\[-Warray-bounds" }
  p->b1.a[ 0].i = 0;     // { dg-warning "\\\[-Wzero-length-bounds" }
  p->b1.a[ 1].i = 0;     // { dg-warning "\\\[-Warray-bounds" }
  sink (p);

  p->b2.a[ 0].i = 0;     // { dg-warning "\\\[-Warray-bounds" }
  p->b2.a[ 1].i = 0;     // { dg-warning "\\\[-Warray-bounds" }
  sink (p);

  p = (struct C*)&cbuf2;
  p->b1.a[-1].i = 0;     // { dg-warning "\\\[-Warray-bounds" }
  p->b1.a[ 0].i = 0;     // { dg-warning "\\\[-Wzero-length-bounds" }
  p->b1.a[ 1].i = 0;     // { dg-warning "\\\[-Wzero-length-bounds" }
  sink (p);

  p->b2.a[ 0].i = 0;
  p->b2.a[ 1].i = 0;
  p->b2.a[ 2].i = 0;     // { dg-warning "\\\[-Warray-bounds" }
  p->b2.a[ 3].i = 0;     // { dg-warning "\\\[-Warray-bounds" }
  sink (p);
}


void test_C_local_buf (void)
{
  char cbuf1[1 * sizeof (struct C)] = "";
  char cbuf2[2 * sizeof (struct C)] = { };

  struct C *p = (struct C*)&cbuf1;

  p->b1.a[-1].i = 1;     // { dg-warning "\\\[-Warray-bounds" }
  p->b1.a[ 0].i = 2;     // { dg-warning "\\\[-Wzero-length-bounds" }
  p->b1.a[ 1].i = 3;     // { dg-warning "\\\[-Warray-bounds" }
  sink (p);

  p->b2.a[ 0].i = 4;     // { dg-warning "\\\[-Warray-bounds" }
  p->b2.a[ 1].i = 5;     // { dg-warning "\\\[-Warray-bounds" }
  sink (p);

  p = (struct C*)&cbuf2;
  p->b1.a[-1].i = 6;     // { dg-warning "\\\[-Warray-bounds" }
  p->b1.a[ 0].i = 7;     // { dg-warning "\\\[-Wzero-length-bounds" }
  p->b1.a[ 1].i = 8;     // { dg-warning "\\\[-Wzero-length-bounds" }
  sink (p);

  p->b2.a[ 0].i = 9;
  p->b2.a[ 1].i = 10;
  p->b2.a[ 2].i = 11;    // { dg-warning "\\\[-Warray-bounds" }
  p->b2.a[ 3].i = 12;    // { dg-warning "\\\[-Warray-bounds" }
  sink (p);
}