A recent improvement to the vectorizer (r278334 if my bisection is right) can transform multiple stores to adjacent struct members into single vectorized assignments that write over all the members in a single MEM_REF. These are then flagged by -Wstringop-overflow thanks to its also recently enhanced past-the-end store detection. The warnings have been causing failures in some of Jeff's periodic builds (e.g., in cjdns-v20.4).
Reliably distinguishing these transformed, multi-member, MEM_REF stores from accidental bugs the warning is designed to detect will require annotating them somehow at the time they are introduced. Until that happens, the attached patch simply tweaks the logic that determines the size of the destination objects to punt on these vectorized MEM_REFs. Martin
PR middle-end/93200 - spurious -Wstringop-overflow due to assignment vectorization to multiple members gcc/testsuite/ChangeLog: PR middle-end/93200 * gcc.dg/Wstringop-overflow-30.c: New test. gcc/ChangeLog: PR middle-end/93200 * builtins.c (compute_objsize): Avoid handling MEM_REFs of vector type. Index: gcc/builtins.c =================================================================== --- gcc/builtins.c (revision 280012) +++ gcc/builtins.c (working copy) @@ -3966,6 +3966,18 @@ || TREE_CODE (dest) == MEM_REF) { tree ref = TREE_OPERAND (dest, 0); + tree reftype = TREE_TYPE (ref); + if (TREE_CODE (dest) == MEM_REF && TREE_CODE (reftype) == POINTER_TYPE) + { + /* Give up for MEM_REFs of vector types; those may be synthesized + from multiple assignments to consecutive data members. See PR + 93200. + FIXME: Deal with this more generally, e.g., by marking up such + MEM_REFs at the time they're created. */ + reftype = TREE_TYPE (reftype); + if (TREE_CODE (reftype) == VECTOR_TYPE) + return NULL_TREE; + } tree off = TREE_OPERAND (dest, 1); if (tree size = compute_objsize (ref, ostype, pdecl, poff)) { Index: gcc/testsuite/gcc.dg/Wstringop-overflow-30.c =================================================================== --- gcc/testsuite/gcc.dg/Wstringop-overflow-30.c (nonexistent) +++ gcc/testsuite/gcc.dg/Wstringop-overflow-30.c (working copy) @@ -0,0 +1,80 @@ +/* PR middle-end/93200 - spurious -Wstringop-overflow due to assignment + vectorization to multiple members + { dg-do compile } + { dg-options "-O3 -Wall" } */ + +typedef __INT8_TYPE__ int8_t; +typedef __INT16_TYPE__ int16_t; +typedef __INT32_TYPE__ int32_t; +typedef __INT64_TYPE__ int64_t; + +struct A { char b, c; }; +struct B1A { int8_t i8; struct A a; }; +struct B2A { int16_t i16; struct A a; }; +struct B3A { int16_t i16; int8_t i8; struct A a; }; +struct B4A { int64_t i64; struct A a; }; + +void ba1 (struct B1A *p) +{ + p->a.b = 0; p->a.c = 1; +} + +void b2a (struct B2A *p) +{ + /* This results in: + vector(2) char *vectp.14_6 = &p_2(D)->a.b; + MEM <vector(2) char> [(char *)vectp.14_6] = { 4, 5 }; */ + + p->a.b = 4; // { dg-bogus "-Wstringop-overflow" } + p->a.c = 5; +} + +void b3a (struct B3A *p) +{ + p->a.b = 4; p->a.c = 5; +} + +void b4a (struct B4A *p) +{ + /* This results in: + vector(2) char *vectp.22_6 = &p_2(D)->a.b; + MEM <vector(2) char> [(char *)vectp.22_6] = { 6, 7 }; */ + + p->a.b = 6; // { dg-bogus "-Wstringop-overflow" } + p->a.c = 7; +} + + +struct Aa { char a[2], b[2]; }; +struct B1Aa { int8_t i8; struct Aa a; }; +struct B2Aa { int16_t i16; struct Aa a; }; +struct B3Aa { int16_t i16; int8_t i8; struct Aa a; }; +struct B4Aa { int64_t i64; struct Aa a; }; + +void b1aa (struct B1Aa *p) +{ + p->a.a[0] = 0; p->a.a[1] = 1; + p->a.b[0] = 0; p->a.b[1] = 1; +} + +void b2aa (struct B2Aa *p) +{ + p->a.a[0] = 2; p->a.a[1] = 3; + p->a.b[0] = 2; p->a.b[1] = 3; +} + +void b3aa (struct B3Aa *p) +{ + p->a.a[0] = 4; p->a.a[1] = 5; + p->a.b[0] = 4; p->a.b[1] = 5; +} + +void b4aa (struct B4Aa *p) +{ + /* This results in: + vector(4) char *vectp.36_8 = &p_2(D)->a.a[0]; + MEM <vector(4) char> [(char *)vectp.36_8] = { 6, 7, 6, 7 }; */ + + p->a.a[0] = 6; p->a.a[1] = 7; + p->a.b[0] = 6; p->a.b[1] = 7; +}