diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc index 54f32051199..199d9f5d216 100644 --- a/gcc/gimple-array-bounds.cc +++ b/gcc/gimple-array-bounds.cc @@ -895,7 +895,7 @@ array_bounds_checker::check_addr_expr (location_t location, tree t) problems discussed in pr98266 and pr97595. */ static bool -inbounds_vbase_memaccess_p (tree t) +inbounds_memaccess_p (tree t) { if (TREE_CODE (t) != COMPONENT_REF) return false; @@ -928,10 +928,19 @@ inbounds_vbase_memaccess_p (tree t) object by adding its offset computed above to the MEM_REF offset. */ tree refoff = TREE_OPERAND (mref, 1); tree fldoff = int_const_binop (PLUS_EXPR, fldpos, refoff); + /* Return false if the member offset is greater or equal to the size + of the complete object. */ + if (!tree_int_cst_lt (fldoff, refsize)) + return false; - /* Return true if the member offset is less than the size of the complete - object. */ - return tree_int_cst_lt (fldoff, refsize); + tree fldsiz = DECL_SIZE_UNIT (fld); + if (!fldsiz || TREE_CODE (fldsiz) != INTEGER_CST) + return false; + + /* Return true if the offset just past the end of the member is less + than or equal to the size of the complete object. */ + tree fldend = int_const_binop (PLUS_EXPR, fldoff, fldsiz); + return tree_int_cst_le (fldend, refsize); } /* Callback for walk_tree to check a tree for out of bounds array @@ -965,7 +974,7 @@ array_bounds_checker::check_array_bounds (tree *tp, int *walk_subtree, checker->check_addr_expr (location, t); *walk_subtree = false; } - else if (inbounds_vbase_memaccess_p (t)) + else if (inbounds_memaccess_p (t)) /* Hack: Skip MEM_REF checks in accesses to a member of a base class at an offset that's within the bounds of the enclosing object. See pr98266 and pr97595. */ diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-22.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-22.C new file mode 100644 index 00000000000..77cdb5ebd43 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-22.C @@ -0,0 +1,105 @@ +/* PR middle-end/99502 - missing -Warray-bounds on partial out of bounds + access in C++ + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +typedef __INT8_TYPE__ int8_t; +typedef __INT16_TYPE__ int16_t; +typedef __INT32_TYPE__ int32_t; + +struct POD32 +{ + int32_t i32; +}; + +int8_t a16[2]; +int8_t apod32[sizeof (POD32)]; + +void nowarn_pod32_assign () +{ + POD32 *p = (POD32*)apod32; + *p = POD32 (); +} + +void nowarn_pod32_assign_member () +{ + POD32 *p = (POD32*)apod32; + p->i32 = __LINE__; +} + + +void warn_pod32_assign () +{ + POD32 *p = (POD32*)a16; + *p = POD32 (); // { dg-warning "-Warray-bounds" } +} + +void warn_pod32_assign_member () +{ + POD32 *p = (POD32*)a16; + p->i32 = __LINE__; // { dg-warning "-Warray-bounds" } +} + + +struct BV32 // { dg-warning "-Warray-bounds" "due to pr99525" } +{ + int32_t i32; + + virtual ~BV32 (); +}; + +int8_t abv32[sizeof (BV32)]; + +void nowarn_bv32_assign () +{ + BV32 *p = (BV32*)abv32; + *p = BV32 (); +} + +void nowarn_bv32_assign_member () +{ + BV32 *p = (BV32*)abv32; + p->i32 = __LINE__; +} + +void warn_bv32_assign () +{ + BV32 *p = (BV32*)a16; + *p = BV32 (); // { dg-warning "-Warray-bounds" "pr99525" { xfail *-*-* } } +} + +void warn_bv32_assign_member () +{ + BV32 *p = (BV32*)a16; + p->i32 = __LINE__; // { dg-warning "-Warray-bounds" } +} + + +struct DV32: virtual BV32 { }; + +int8_t adv32[sizeof (DV32)]; +int8_t adv32_m1[sizeof adv32 - 1]; + +void nowarn_dv32_assign () +{ + DV32 *p = (DV32*)adv32; + *p = DV32 (); +} + +void nowarn_dv32_assign_member () +{ + DV32 *p = (DV32*)adv32; + p->i32 = __LINE__; +} + +void warn_dv32_assign () +{ + DV32 *p = (DV32*)adv32_m1; + *p = DV32 (); // { dg-warning "-Warray-bounds" "pr?????" { xfail *-*-* } } +} + +void warn_dv32_assign_member () +{ + DV32 *p = (DV32*)adv32_m1; + p->i32 = __LINE__; // { dg-warning "-Warray-bounds" "pr?????" { xfail *-*-* } } +} diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-23.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-23.C new file mode 100644 index 00000000000..c43a7dea3ef --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-23.C @@ -0,0 +1,345 @@ +/* PR middle-end/99502 - missing -Warray-bounds on partial out of bounds + access in C++ + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +inline void* operator new (__SIZE_TYPE__, void *p) { return p; } + +struct B0 { int b0i; }; +struct B1: virtual B0 { int b1i; }; +struct B2: virtual B0 { int b2i; }; +struct D1: B1, B2 { int d1i; }; +struct D2: D1 { int d2i; }; +struct D3: D2 { long d3i, d3ax[]; }; + +void sink (void*); + + +void test_D1 () +{ + { + char *p = new char[sizeof (D1)]; + new (p) D1 (); + sink (p); + } + + { + char *p = new char[sizeof (D1) - 1]; + new (p) D1 (); // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D1_b0i () +{ + { + D1 *p = (D1*)new char[sizeof (D1)]; + p->b0i = __LINE__; + sink (p); + } + + { + D1 *p = (D1*)new char[3]; + p->b0i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D1_b1i () +{ + { + D1 *p = (D1*)new char[sizeof (D1)]; + p->b1i = __LINE__; + sink (p); + } + + { + D1 *p = (D1*)new char[3]; + p->b1i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D1_b2i () +{ + { + D1 *p = (D1*)new char[sizeof (D1)]; + p->b2i = __LINE__; + sink (p); + } + + { + D1 *p = (D1*)new char[3]; + p->b2i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D1_d1i () +{ + { + D1 *p = (D1*)new char[sizeof (D1)]; + p->d1i = __LINE__; + sink (p); + } + + { + D1 *p = (D1*)new char[3]; + p->d1i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + + +void test_D2 () +{ + { + char *p = new char[sizeof (D2)]; + new (p) D2 (); + sink (p); + } + + { + char *p = new char[sizeof (D2) - 1]; + new (p) D2 (); // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D2_b0i () +{ + { + D2 *p = (D2*)new char[sizeof (D2)]; + p->b0i = __LINE__; + sink (p); + } + + { + D2 *p = (D2*)new char[3]; + p->b0i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D2_b1i () +{ + { + D2 *p = (D2*)new char[sizeof (D2)]; + p->b1i = __LINE__; + sink (p); + } + + { + D2 *p = (D2*)new char[3]; + p->b1i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D2_b2i () +{ + { + D2 *p = (D2*)new char[sizeof (D2)]; + p->b2i = __LINE__; + sink (p); + } + + { + D2 *p = (D2*)new char[3]; + p->b2i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D2_d1i () +{ + { + D2 *p = (D2*)new char[sizeof (D2)]; + p->d1i = __LINE__; + sink (p); + } + + { + D2 *p = (D2*)new char[3]; + p->d1i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D2_d2i () +{ + { + D2 *p = (D2*)new char[sizeof (D2)]; + p->d2i = __LINE__; + sink (p); + } + + { + D2 *p = (D2*)new char[3]; + p->d2i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + + +void test_D3 () +{ + { + char *p = new char[sizeof (D3)]; + new (p) D3 (); + sink (p); + } + + { + char *p = new char[sizeof (D3) - 1]; + new (p) D3 (); // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_b0i () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + p->b0i = __LINE__; + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + p->b0i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_b1i () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + p->b1i = __LINE__; + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + p->b1i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_b2i () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + p->b2i = __LINE__; + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + p->b2i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_d1i () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + p->d1i = __LINE__; + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + p->d1i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_d2i () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + p->d2i = __LINE__; + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + p->d2i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_d3i () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + p->d3i = __LINE__; + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + p->d3i = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_d3ax () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + *p->d3ax = __LINE__; // { dg-warning "-Warray-bounds" "pr?????" { xfail *-*-* } } + p->d3ax[9] = __LINE__; // { dg-warning "-Warray-bounds" "pr?????" { xfail *-*-* } } + sink (p); + } + + { + D3 *p = (D3*)new char[sizeof (D3) + sizeof (D3::d3ax[0])]; + p->d3ax[0] = __LINE__; + p->d3ax[1] = __LINE__; // { dg-warning "-Warray-bounds" "pr?????" { xfail *-*-* } } + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + *p->d3ax = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +struct D4: D2 +{ + // D4:d4a0 overlaps with B0:b0i! + long d4i, d4a0[0]; +}; + +void test_D4_d3a0 () +{ + { + D4 *p = (D4*)new char[sizeof (D4)]; + *p->d4a0 = __LINE__; // { dg-warning "-Warray-bounds" } + p->d4a0[1] = __LINE__; // { dg-warning "-Warray-bounds" } + p->d4a0[9] = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D4 *p = (D4*)new char[sizeof (D4) + sizeof (D4::d4a0[0])]; + /* The access to d4a0[0] should get a -Wzero-length-bounds because + it's in bounds but overlaps p->b0i. */ + p->d4a0[0] = __LINE__; // { dg-warning "-Wzero-length-bounds" "pr99635" { xfail *-*-* } } + // { dg-warning "-Warray-bounds" "actual" { target *-*-* } .-1 } + p->d4a0[1] = __LINE__; // { dg-warning "-Warray-bounds" } + p->d4a0[9] = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D4 *p = (D4*)new char[3]; + *p->d4a0 = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-24.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-24.C new file mode 100644 index 00000000000..071453a485d --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-24.C @@ -0,0 +1,289 @@ +/* PR middle-end/99502 - missing -Warray-bounds on partial out of bounds + access in C++ + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +inline void* operator new (__SIZE_TYPE__, void *p) { return p; } + +struct B0 { int b0i, b0a[0]; }; +struct B1: virtual B0 { int b1i, b1a[0]; }; +struct B2: virtual B0 { int b2i, b2a[0]; }; +struct D1: B1, B2 { int d1i, d1a[0]; }; +struct D2: D1 { int d2i, d2a[0]; }; +struct D3: D2 { int d3i, d3a[0]; }; + +void sink (void*); + + +void test_D1 () +{ + { + char *p = new char[sizeof (D1)]; + new (p) D1 (); + sink (p); + } + + { + char *p = new char[sizeof (D1) - 1]; + new (p) D1 (); // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D1_b0a () +{ + { + D1 *p = (D1*)new char[sizeof (D1)]; + *p->b0a = __LINE__; // { dg-warning "-Warray-bounds" "pr99630" { xfail *-*-* } } + sink (p); + } + + { + D1 *p = (D1*)new char[3]; + *p->b0a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D1_b1a () +{ + { + D1 *p = (D1*)new char[sizeof (D1)]; + *p->b1a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D1 *p = (D1*)new char[3]; + *p->b1a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D1_b2a () +{ + { + D1 *p = (D1*)new char[sizeof (D1)]; + *p->b2a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D1 *p = (D1*)new char[3]; + *p->b2a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D1_d1a () +{ + { + D1 *p = (D1*)new char[sizeof (D1)]; + *p->d1a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D1 *p = (D1*)new char[3]; + *p->d1a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + + +void test_D2 () +{ + { + char *p = new char[sizeof (D2)]; + new (p) D2 (); + sink (p); + } + + { + char *p = new char[sizeof (D2) - 1]; + new (p) D2 (); // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D2_b0a () +{ + { + D2 *p = (D2*)new char[sizeof (D2)]; + *p->b0a = __LINE__; // { dg-warning "-Warray-bounds" "pr99630" { xfail *-*-* } } + sink (p); + } + + { + D2 *p = (D2*)new char[3]; + *p->b0a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D2_b1a () +{ + { + D2 *p = (D2*)new char[sizeof (D2)]; + *p->b1a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D2 *p = (D2*)new char[3]; + *p->b1a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D2_b2a () +{ + { + D2 *p = (D2*)new char[sizeof (D2)]; + *p->b2a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D2 *p = (D2*)new char[3]; + *p->b2a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D2_d1a () +{ + { + D2 *p = (D2*)new char[sizeof (D2)]; + *p->d1a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D2 *p = (D2*)new char[3]; + *p->d1a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D2_d2a () +{ + { + D2 *p = (D2*)new char[sizeof (D2)]; + *p->d2a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D2 *p = (D2*)new char[3]; + *p->d2a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + + +void test_D3 () +{ + { + char *p = new char[sizeof (D3)]; + new (p) D3 (); + sink (p); + } + + { + char *p = new char[sizeof (D3) - 1]; + new (p) D3 (); // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_b0a () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + *p->b0a = __LINE__; // { dg-warning "-Warray-bounds" "pr99630" { xfail *-*-* } } + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + *p->b0a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_b1a () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + *p->b1a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + *p->b1a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_b2a () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + *p->b2a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + *p->b2a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_d1a () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + *p->d1a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + *p->d1a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_d2a () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + *p->d2a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + *p->d2a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} + +void test_D3_d3a () +{ + { + D3 *p = (D3*)new char[sizeof (D3)]; + *p->d3a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } + + { + D3 *p = (D3*)new char[3]; + *p->d3a = __LINE__; // { dg-warning "-Warray-bounds" } + sink (p); + } +} +