Commit f7d86b5c by Martin Sebor Committed by Martin Sebor

builtins.c (compute_objsize): Add an argument and set it to offset into destination.


gcc/ChangeLog:

	* builtins.c (compute_objsize): Add an argument and set it to offset
	into destination.
	* builtins.h (compute_objsize): Add an argument.
	* tree-object-size.c (addr_object_size): Add an argument and set it
	to offset into destination.
	(compute_builtin_object_size): Same.
	* tree-object-size.h (compute_builtin_object_size): Add an argument.
	* tree-ssa-strlen.c (get_addr_stridx): Add an argument and set it
	to offset into destination.
	(maybe_warn_overflow): New function.
	(handle_store): Call maybe_warn_overflow to issue warnings.

gcc/testsuite/ChangeLog:

	* c-c++-common/Wstringop-overflow-2.c: Adjust text of expected messages.
	* g++.dg/warn/Wstringop-overflow-3.C: Same.
	* gcc.dg/Wstringop-overflow-17.c: Same.

From-SVN: r279248
parent c7f5b4ed
2019-12-11 Martin Sebor <msebor@redhat.com>
* builtins.c (compute_objsize): Add an argument and set it to offset
into destination.
* builtins.h (compute_objsize): Add an argument.
* tree-object-size.c (addr_object_size): Add an argument and set it
to offset into destination.
(compute_builtin_object_size): Same.
* tree-object-size.h (compute_builtin_object_size): Add an argument.
* tree-ssa-strlen.c (get_addr_stridx): Add an argument and set it
to offset into destination.
(maybe_warn_overflow): New function.
(handle_store): Call maybe_warn_overflow to issue warnings.
2019-12-11 Jozef Lawrynowicz <jozef.l@mittosystems.com>
* config/msp430/msp430.h (STARTFILE_SPEC) [!fexceptions]: Use
......@@ -3817,7 +3817,7 @@ compute_objsize (tree dest, int ostype, tree *pdecl /* = NULL */,
/* Only the two least significant bits are meaningful. */
ostype &= 3;
if (compute_builtin_object_size (dest, ostype, &size, pdecl))
if (compute_builtin_object_size (dest, ostype, &size, pdecl, poff))
return build_int_cst (sizetype, size);
if (TREE_CODE (dest) == SSA_NAME)
......@@ -3924,7 +3924,7 @@ compute_objsize (tree dest, int ostype, tree *pdecl /* = NULL */,
if (integer_zerop (size)
&& *pdecl && DECL_P (*pdecl)
&& *poff && integer_zerop (*poff))
return integer_zero_node;
return size_zero_node;
/* A valid offset into a declared object cannot be negative. */
if (tree_int_cst_sgn (*poff) < 0)
......
......@@ -22,6 +22,12 @@
2019-12-11 Martin Sebor <msebor@redhat.com>
* c-c++-common/Wstringop-overflow-2.c: Adjust text of expected messages.
* g++.dg/warn/Wstringop-overflow-3.C: Same.
* gcc.dg/Wstringop-overflow-17.c: Same.
2019-12-11 Martin Sebor <msebor@redhat.com>
PR middle-end/79221
* gcc.dg/Wstringop-overflow-26.c: New test.
......
......@@ -10,7 +10,7 @@ void sink (void*);
struct Ax
{
char n;
char a[]; // { dg-message "destination object declared here" }
char a[]; // { dg-message "declared here" }
};
// Verify warning for a definition with no initializer.
......@@ -91,7 +91,7 @@ void gaxx (void)
struct A0
{
char n;
char a[0]; // { dg-message "destination object declared here" }
char a[0]; // { dg-message "declared here" }
};
// Verify warning for a definition with no initializer.
......@@ -158,7 +158,7 @@ void ga0x (void)
struct A1
{
char n;
char a[1]; // { dg-message "destination object declared here" }
char a[1]; // { dg-message "declared here" }
};
// Verify warning for a definition with no initializer.
......@@ -256,7 +256,7 @@ void ga1x (void)
struct A1i
{
char n;
char a[1]; // { dg-message "destination object declared here" }
char a[1]; // { dg-message "declared here" }
char x;
};
......
......@@ -3,6 +3,8 @@
{ dg-do compile }
{ dg-options "-O2 -Wall -Wno-array-bounds" } */
#define NOIPA __attribute__ ((noipa))
void sink (void*);
// Exercise flexible array members.
......@@ -10,13 +12,13 @@ void sink (void*);
struct Ax
{
char n;
char a[]; // { dg-message "destination object declared here" }
char a[]; // { dg-message "at offset \[0-2\] to object 'Ax::a' declared here" }
};
// Verify warning for a definition with no initializer.
Ax ax_;
void gax_ ()
NOIPA void gax_ ()
{
ax_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
ax_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -27,7 +29,7 @@ void gax_ ()
// initialize the flexible array member.
Ax ax0 = { 0 };
void gax0 ()
NOIPA void gax0 ()
{
ax0.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
ax0.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -38,7 +40,7 @@ void gax0 ()
// initializes the flexible array member to empty.
Ax ax0_ = { 0, { } };
void gax0_ ()
NOIPA void gax0_ ()
{
ax0_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
ax0_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -49,7 +51,7 @@ void gax0_ ()
// an initializer.
Ax ax1 = { 1, { 0 } };
void gax1 ()
NOIPA void gax1 ()
{
ax1.a[0] = 0;
ax1.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -58,7 +60,7 @@ void gax1 ()
Ax ax2 = { 2, { 1, 0 } };
void gax2 ()
NOIPA void gax2 ()
{
ax2.a[0] = 0;
ax2.a[1] = 0;
......@@ -67,7 +69,7 @@ void gax2 ()
// Verify no warning for an unknown struct object.
void gaxp (Ax *p)
NOIPA void gaxp (Ax *p)
{
p->a[0] = 0;
p->a[3] = 0;
......@@ -79,7 +81,7 @@ void gaxp (Ax *p)
// initialized to any number of elements.
extern Ax axx;
void gaxx ()
NOIPA void gaxx ()
{
axx.a[0] = 0;
axx.a[3] = 0;
......@@ -91,13 +93,13 @@ void gaxx ()
struct A0
{
char n;
char a[0]; // { dg-message "destination object declared here" }
char a[0]; // { dg-message "at offset \[0-2\] to object 'A0::a' with size 0 declared here" }
};
// Verify warning for a definition with no initializer.
A0 a0_;
void ga0_ ()
NOIPA void ga0_ ()
{
a0_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
a0_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -108,7 +110,7 @@ void ga0_ ()
// initialize the flexible array member.
A0 a00 = { 0 };
void ga00 ()
NOIPA void ga00 ()
{
a00.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
a00.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -119,7 +121,7 @@ void ga00 ()
// initializes the flexible array member to empty.
A0 a00_ = { 0, { } };
void ga00_ ()
NOIPA void ga00_ ()
{
a00_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
a00_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -133,7 +135,7 @@ void ga00_ ()
// Verify no warning for an unknown struct object.
void ga0p (A0 *p)
NOIPA void ga0p (A0 *p)
{
p->a[0] = 0;
p->a[3] = 0;
......@@ -145,7 +147,7 @@ void ga0p (A0 *p)
// flexible array member) may not be initialized.
extern A0 a0x;
void ga0x ()
NOIPA void ga0x ()
{
a0x.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
a0x.a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -158,13 +160,13 @@ void ga0x ()
struct A1
{
char n;
char a[1]; // { dg-message "destination object declared here" }
char a[1]; // { dg-message "at offset \[1-9\] to object 'A1::a' with size 1 declared here" }
};
// Verify warning for a definition with no initializer.
A1 a1_;
void ga1_ ()
NOIPA void ga1_ ()
{
a1_.a[0] = 0;
a1_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -175,7 +177,7 @@ void ga1_ ()
// initialize the one-element array member.
A1 a1__ = { 0 };
void ga1__ ()
NOIPA void ga1__ ()
{
a1__.a[0] = 0;
a1__.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -186,7 +188,7 @@ void ga1__ ()
// initializes the one-element array member to empty.
A1 a1_0 = { 0, { } };
void ga1_0_ ()
NOIPA void ga1_0_ ()
{
a1_0.a[0] = 0;
a1_0.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -197,7 +199,7 @@ void ga1_0_ ()
// initializes the one-element array member.
A1 a1_1 = { 0, { 1 } };
void ga1_1 ()
NOIPA void ga1_1 ()
{
a1_1.a[0] = 0;
a1_1.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -206,7 +208,7 @@ void ga1_1 ()
// Verify no warning for an unknown struct object.
void ga1p (A1 *p)
NOIPA void ga1p (A1 *p)
{
p->a[0] = 0;
p->a[3] = 0;
......@@ -219,7 +221,7 @@ void ga1p (A1 *p)
// a single element.
extern A1 a1x;
void ga1x ()
NOIPA void ga1x ()
{
a1x.a[0] = 0;
a1x.a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -232,14 +234,14 @@ void ga1x ()
struct A1i
{
char n;
char a[1]; // { dg-message "destination object declared here" }
char a[1]; // { dg-message "at offset \[1-9\] to object 'A1i::a' with size 1 declared here" }
char x;
};
// Verify warning for a definition with no initializer.
A1i a1i_;
void ga1i_ ()
NOIPA void ga1i_ ()
{
a1i_.a[0] = 0;
a1i_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -250,7 +252,7 @@ void ga1i_ ()
// initialize the one-element array member.
A1i a1i__ = { 0 };
void ga1i__ ()
NOIPA void ga1i__ ()
{
a1i__.a[0] = 0;
a1i__.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -261,7 +263,7 @@ void ga1i__ ()
// initializes the one-element array member to empty.
A1 a1i_0 = { 0, { } };
void ga1i_0_ ()
NOIPA void ga1i_0_ ()
{
a1i_0.a[0] = 0;
a1i_0.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -272,7 +274,7 @@ void ga1i_0_ ()
// initializes the one-element array member.
A1 a1i_1 = { 0, { 1 } };
void ga1i_1 ()
NOIPA void ga1i_1 ()
{
a1i_1.a[0] = 0;
a1i_1.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -281,7 +283,7 @@ void ga1i_1 ()
// Verify no warning for an unknown struct object.
void ga1ip (A1i *p)
NOIPA void ga1ip (A1i *p)
{
p->a[0] = 0;
p->a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -292,7 +294,7 @@ void ga1ip (A1i *p)
// Verify no warning for an extern struct object.
extern A1i a1ix;
void ga1ix ()
NOIPA void ga1ix ()
{
a1ix.a[0] = 0;
a1ix.a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -305,7 +307,7 @@ void ga1ix ()
struct Bx
{
char n;
char a[]; // { dg-message "destination object declared here" }
char a[]; // { dg-message "at offset 0 to object 'Bx::a' declared here" }
// Verify the warning for a constant.
Bx () { a[0] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
......@@ -315,13 +317,13 @@ struct Bx
Bx (int i) { a[i] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
};
void gbx (void)
NOIPA void gbx (void)
{
struct Bx bx;
sink (&bx);
}
void gbxi (int i)
NOIPA void gbxi (int i)
{
struct Bx bxi (i);
sink (&bxi);
......@@ -330,13 +332,13 @@ void gbxi (int i)
struct B0
{
char n;
char a[0]; // { dg-message "destination object declared here" }
char a[0]; // { dg-message "at offset 0 to object 'B0::a' with size 0 declared here" }
B0 () { a[0] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
};
void gb0 (void)
NOIPA void gb0 (void)
{
struct B0 b0;
sink (&b0);
......@@ -346,12 +348,12 @@ void gb0 (void)
struct B1
{
char n;
char a[1]; // { dg-message "destination object declared here" }
char a[1]; // { dg-message "at offset 1 to object 'B1::a' with size 1 declared here" }
B1 () { a[1] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
};
void gb1 (void)
NOIPA void gb1 (void)
{
struct B1 b1;
sink (&b1);
......@@ -360,12 +362,12 @@ void gb1 (void)
struct B123
{
char a[123]; // { dg-message "destination object declared here" }
char a[123]; // { dg-message "at offset 123 to object 'B123::a' with size 123 declared here" }
B123 () { a[123] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
};
void gb123 (void)
NOIPA void gb123 (void)
{
struct B123 b123;
sink (&b123);
......@@ -374,12 +376,12 @@ void gb123 (void)
struct B234
{
char a[234]; // { dg-message "destination object declared here" }
char a[234]; // { dg-message "at offset 234 to object 'B234::a' with size 234 declared here" }
B234 (int i) { a[i] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
};
void g234 (void)
NOIPA void g234 (void)
{
struct B234 b234 (234);
sink (&b234);
......
......@@ -13,7 +13,7 @@ void sink (void*);
void call_copy_n (const char *s)
{
char a[3]; // { dg-message "destination object declared here" }
char a[3]; // { dg-message "declared here" }
copy_n (a, "1234567", 7);
sink (a);
}
......@@ -55,7 +55,7 @@ static const unsigned HOST_WIDE_INT unknown[4] = {
static tree compute_object_offset (const_tree, const_tree);
static bool addr_object_size (struct object_size_info *,
const_tree, int, unsigned HOST_WIDE_INT *,
tree * = NULL);
tree * = NULL, tree * = NULL);
static unsigned HOST_WIDE_INT alloc_object_size (const gcall *, int);
static tree pass_through_call (const gcall *);
static void collect_object_sizes_for (struct object_size_info *, tree);
......@@ -174,13 +174,15 @@ compute_object_offset (const_tree expr, const_tree var)
static bool
addr_object_size (struct object_size_info *osi, const_tree ptr,
int object_size_type, unsigned HOST_WIDE_INT *psize,
tree *pdecl /* = NULL */)
tree *pdecl /* = NULL */, tree *poff /* = NULL */)
{
tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
tree dummy;
tree dummy_decl, dummy_off = size_zero_node;
if (!pdecl)
pdecl = &dummy;
pdecl = &dummy_decl;
if (!poff)
poff = &dummy_off;
gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
......@@ -201,7 +203,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
|| TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME)
{
compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
object_size_type & ~1, &sz, pdecl);
object_size_type & ~1, &sz, pdecl, poff);
}
else
{
......@@ -376,6 +378,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
bytes = size_zero_node;
else
bytes = size_binop (MINUS_EXPR, var_size, bytes);
*poff = bytes;
}
if (var != pt_var
&& pt_var_size
......@@ -390,6 +393,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
bytes2 = size_zero_node;
else
bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2);
*poff = size_binop (PLUS_EXPR, *poff, bytes2);
bytes = size_binop (MIN_EXPR, bytes, bytes2);
}
}
......@@ -496,10 +500,16 @@ pass_through_call (const gcall *call)
bool
compute_builtin_object_size (tree ptr, int object_size_type,
unsigned HOST_WIDE_INT *psize,
tree *pdecl /* = NULL */)
tree *pdecl /* = NULL */, tree *poff /* = NULL */)
{
gcc_assert (object_size_type >= 0 && object_size_type <= 3);
tree dummy_decl, dummy_off = size_zero_node;
if (!pdecl)
pdecl = &dummy_decl;
if (!poff)
poff = &dummy_off;
/* Set to unknown and overwrite just before returning if the size
could be determined. */
*psize = unknown[object_size_type];
......@@ -508,7 +518,7 @@ compute_builtin_object_size (tree ptr, int object_size_type,
init_offset_limit ();
if (TREE_CODE (ptr) == ADDR_EXPR)
return addr_object_size (NULL, ptr, object_size_type, psize, pdecl);
return addr_object_size (NULL, ptr, object_size_type, psize, pdecl, poff);
if (TREE_CODE (ptr) != SSA_NAME
|| !POINTER_TYPE_P (TREE_TYPE (ptr)))
......@@ -533,11 +543,12 @@ compute_builtin_object_size (tree ptr, int object_size_type,
if (tree_fits_shwi_p (offset)
&& compute_builtin_object_size (ptr, object_size_type,
psize, pdecl))
psize, pdecl, poff))
{
/* Return zero when the offset is out of bounds. */
unsigned HOST_WIDE_INT off = tree_to_shwi (offset);
*psize = off < *psize ? *psize - off : 0;
*poff = offset;
return true;
}
}
......
......@@ -23,6 +23,6 @@ along with GCC; see the file COPYING3. If not see
extern void init_object_sizes (void);
extern void fini_object_sizes (void);
extern bool compute_builtin_object_size (tree, int, unsigned HOST_WIDE_INT *,
tree * = NULL);
tree * = NULL, tree * = NULL);
#endif // GCC_TREE_OBJECT_SIZE_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment