blob: 1d79930cd58c202c3dc9199c7738e54f9fbfea35 [file] [log] [blame]
/* PR middle-end/91458 - inconsistent warning for writing past the end
of an array member
{ dg-do compile }
{ dg-options "-O2 -Wall -Wno-array-bounds -fno-ipa-icf" } */
void sink (void*);
// Exercise flexible array members.
struct Ax
{
char n;
char a[]; // { dg-message "destination object" "note" }
};
// Verify warning for a definition with no initializer.
struct Ax ax_;
void gax_ (void)
{
ax_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
ax_.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
ax_.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
}
// Verify warning for access to a definition with an initializer that doesn't
// initialize the flexible array member.
struct Ax ax0 = { 0 };
void gax0 (void)
{
ax0.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
ax0.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
ax0.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
}
// Verify warning for access to a definition with an initializer that
// initializes the flexible array member to empty.
struct Ax ax0_ = { 0, { } };
void gax0_ (void)
{
ax0_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
ax0_.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
ax0_.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
}
// Verify warning for out-of-bounds accesses to a definition with
// an initializer.
struct Ax ax1 = { 1, { 0 } };
void gax1 (void)
{
ax1.a[0] = 0;
ax1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
ax1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
}
struct Ax ax2 = { 2, { 1, 0 } };
void gax2 (void)
{
ax2.a[0] = 0;
ax2.a[1] = 1;
ax2.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
}
// Verify no warning for an unknown struct object.
void gaxp (struct Ax *p)
{
p->a[0] = 0;
p->a[3] = 3;
p->a[9] = 9;
}
// Verify no warning for an extern struct object whose array may be
// initialized to any number of elements.
extern struct Ax axx;
void gaxx (void)
{
axx.a[0] = 0;
axx.a[3] = 3;
axx.a[9] = 9;
}
// Exercise zero-length array members.
struct A0
{
char n;
char a[0]; // { dg-message "destination object" "note" }
};
// Verify warning for a definition with no initializer.
struct A0 a0_;
void ga0_ (void)
{
a0_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
a0_.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a0_.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
}
// Verify warning for access to a definition with an initializer that doesn't
// initialize the flexible array member.
struct A0 a00 = { 0 };
void ga00 (void)
{
a00.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
a00.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a00.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
}
// Verify warning for access to a definition with an initializer that
// initializes the flexible array member to empty.
struct A0 a00_ = { 0, { } };
void ga00_ (void)
{
a00_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
a00_.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a00_.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
}
// The following are rejected with
// error: too many initializers for 'char [0]'
// A0 a01 = { 1, { 0 } };
// A0 a02 = { 2, { 1, 0 } };
// Verify no warning for an unknown struct object.
void ga0p (struct A0 *p)
{
p->a[0] = 0;
p->a[3] = 3;
p->a[9] = 9;
}
// Verify warning for an extern struct object which (unlike a true
// flexible array member) may not be initialized.
extern struct A0 a0x;
void ga0x (void)
{
a0x.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
a0x.a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
a0x.a[9] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
}
// Exercise trailing one-element array members.
struct A1
{
char n;
char a[1]; // { dg-message "destination object" "note" }
};
// Verify warning for a definition with no initializer.
struct A1 a1_;
void ga1_ (void)
{
a1_.a[0] = 0;
a1_.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a1_.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
struct A1 a;
a.a[0] = 0;
a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
sink (&a);
}
// Verify warning for access to a definition with an initializer that doesn't
// initialize the one-element array member.
struct A1 a1__ = { 0 };
void ga1__ (void)
{
a1__.a[0] = 0;
a1__.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a1__.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
struct A1 a = { 1 };
a.a[0] = 0;
a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
sink (&a);
}
// Verify warning for access to a definition with an initializer that
// initializes the one-element array member to empty.
struct A1 a1_0 = { 0, { } };
void ga1_0_ (void)
{
a1_0.a[0] = 0;
a1_0.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a1_0.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
struct A1 a = { 1, { } };
a.a[0] = 0;
a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
sink (&a);
}
// Verify warning for access to a definition with an initializer that
// initializes the one-element array member.
struct A1 a1_1 = { 0, { 1 } };
void ga1_1 (void)
{
a1_1.a[0] = 0;
a1_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a1_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
struct A1 a = { 0, { 1 } };
a.a[0] = 0;
a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
sink (&a);
}
// Verify no warning for an unknown struct object.
void ga1p (struct A1 *p)
{
p->a[0] = 0;
p->a[3] = 3;
p->a[9] = 9;
}
// Verify warning for an extern struct object. Similar to the zero-length
// array case, a one-element trailing array can be initialized to at most
// a single element.
extern struct A1 a1x;
void ga1x (void)
{
a1x.a[0] = 0;
a1x.a[3] = 3; // { dg-warning "\\\[-Wstringop-overflow" }
a1x.a[9] = 9; // { dg-warning "\\\[-Wstringop-overflow" }
}
// Exercise interior one-element array members (verify they're not
// treated as trailing.
struct A1i
{
char n;
char a[1]; // { dg-message "destination object" }
char x;
};
// Verify warning for a definition with no initializer.
struct A1i a1i_;
void ga1i_ (void)
{
a1i_.a[0] = 0;
a1i_.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a1i_.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
struct A1i a;
a.a[0] = 1;
a.a[1] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
a.a[2] = 3; // { dg-warning "\\\[-Wstringop-overflow" }
sink (&a);
}
// Verify warning for access to a definition with an initializer that doesn't
// initialize the one-element array member.
struct A1i a1i__ = { 0 };
void ga1i__ (void)
{
a1i__.a[0] = 0;
a1i__.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a1i__.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
struct A1i a = { 0 };
a.a[0] = 0;
a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
sink (&a);
}
// Verify warning for access to a definition with an initializer that
// initializes the one-element array member to empty.
struct A1 a1i_0 = { 0, { } };
void ga1i_0_ (void)
{
a1i_0.a[0] = 0;
a1i_0.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a1i_0.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
struct A1 a = { 0, { } };
a.a[0] = 0;
a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
sink (&a);
}
// Verify warning for access to a definition with an initializer that
// initializes the one-element array member.
struct A1 a1i_1 = { 0, { 1 } };
void ga1i_1 (void)
{
a1i_1.a[0] = 0;
a1i_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" }
a1i_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
struct A1 a = { 0, { 1 } };
a.a[0] = 1;
a.a[1] = 2; // { dg-warning "\\\[-Wstringop-overflow" }
a.a[2] = 3; // { dg-warning "\\\[-Wstringop-overflow" }
sink (&a);
}
// Verify no warning for an unknown struct object.
void ga1ip (struct A1i *p)
{
p->a[0] = 0;
p->a[3] = 3; // { dg-warning "\\\[-Wstringop-overflow" }
p->a[9] = 9; // { dg-warning "\\\[-Wstringop-overflow" }
}
// Verify no warning for an extern struct object.
extern struct A1i a1ix;
void ga1ix (void)
{
a1ix.a[0] = 0;
a1ix.a[3] = 3; // { dg-warning "\\\[-Wstringop-overflow" }
a1ix.a[9] = 9; // { dg-warning "\\\[-Wstringop-overflow" }
}