mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-02 08:40:26 +08:00
builtins.h (c_srlen): Add argument.
* builtins.h (c_srlen): Add argument. * builtins.c (warn_string_no_nul): New function. (c_strlen): Add argument and use it. Update recursive calls. Pass DECL argument to string_constant to get info on non terminated strings. Update *NONSTR as needed. (fold_builtin_strlen): Add argument to calls to c_strlen. Warn for unterminated arrays. (warn_string_no_null): Add prototype. * expr.c (string_constant): Update arguments. Update recursive calls appropriately. Detect missing NUL terminator and outermost declaration its missing in. Improve checks for arrays with nonzero lower bound or elements that are not a single byte. Simplify offset computation. Simplify checks for non-NUL terminated strings. * gimple-fold.c (get_range_strlen): Add argument to c_strlen call. * gimple-ssa-sprintf.c (get_string_length): Remove unnecessary code. * gcc.dg/warn-strlen-no-nul.c: New test. Co-Authored-By: Bernd Edlinger <bernd.edlinger@hotmail.de> Co-Authored-By: Jeff Law <law@redhat.com> From-SVN: r264302
This commit is contained in:
parent
d01b568a78
commit
6ab24ea809
@ -1,3 +1,23 @@
|
||||
2018-09-13 Martin Sebor <msebor@redhat.com>
|
||||
Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* builtins.h (c_srlen): Add argument.
|
||||
* builtins.c (warn_string_no_nul): New function.
|
||||
(c_strlen): Add argument and use it. Update recursive calls.
|
||||
Pass DECL argument to string_constant to get info on non
|
||||
terminated strings. Update *NONSTR as needed.
|
||||
(fold_builtin_strlen): Add argument to calls to c_strlen.
|
||||
Warn for unterminated arrays.
|
||||
(warn_string_no_null): Add prototype.
|
||||
* expr.c (string_constant): Update arguments. Update recursive
|
||||
calls appropriately. Detect missing NUL terminator and outermost
|
||||
declaration its missing in.
|
||||
Improve checks for arrays with nonzero lower bound or elements
|
||||
that are not a single byte. Simplify offset computation.
|
||||
Simplify checks for non-NUL terminated strings.
|
||||
* gimple-fold.c (get_range_strlen): Add argument to c_strlen call.
|
||||
* gimple-ssa-sprintf.c (get_string_length): Remove unnecessary code.
|
||||
|
||||
2018-09-13 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* builtins.c (c_strlen): Handle not zero terminated STRING_CSTs
|
||||
|
@ -542,6 +542,27 @@ string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
|
||||
return n;
|
||||
}
|
||||
|
||||
/* For a call at LOC to a function FN that expects a string in the argument
|
||||
ARG, issue a diagnostic due to it being a called with an argument
|
||||
declared at NONSTR that is a character array with no terminating NUL. */
|
||||
|
||||
void
|
||||
warn_string_no_nul (location_t loc, const char *fn, tree arg, tree decl)
|
||||
{
|
||||
if (TREE_NO_WARNING (arg))
|
||||
return;
|
||||
|
||||
loc = expansion_point_location_if_in_system_header (loc);
|
||||
|
||||
if (warning_at (loc, OPT_Wstringop_overflow_,
|
||||
"%qs argument missing terminating nul", fn))
|
||||
{
|
||||
inform (DECL_SOURCE_LOCATION (decl),
|
||||
"referenced argument declared here");
|
||||
TREE_NO_WARNING (arg) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute the length of a null-terminated character string or wide
|
||||
character string handling character sizes of 1, 2, and 4 bytes.
|
||||
TREE_STRING_LENGTH is not the right way because it evaluates to
|
||||
@ -559,13 +580,18 @@ string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
|
||||
accesses. Note that this implies the result is not going to be emitted
|
||||
into the instruction stream.
|
||||
|
||||
If a not zero-terminated string value is encountered and NONSTR is
|
||||
non-zero, the declaration of the string value is assigned to *NONSTR.
|
||||
*NONSTR is accumulating, thus not cleared on success, therefore it has
|
||||
to be initialized to NULL_TREE by the caller.
|
||||
|
||||
ELTSIZE is 1 for normal single byte character strings, and 2 or
|
||||
4 for wide characer strings. ELTSIZE is by default 1.
|
||||
|
||||
The value returned is of type `ssizetype'. */
|
||||
|
||||
tree
|
||||
c_strlen (tree src, int only_value, unsigned eltsize)
|
||||
c_strlen (tree src, int only_value, tree *nonstr, unsigned eltsize)
|
||||
{
|
||||
gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
|
||||
STRIP_NOPS (src);
|
||||
@ -574,22 +600,23 @@ c_strlen (tree src, int only_value, unsigned eltsize)
|
||||
{
|
||||
tree len1, len2;
|
||||
|
||||
len1 = c_strlen (TREE_OPERAND (src, 1), only_value, eltsize);
|
||||
len2 = c_strlen (TREE_OPERAND (src, 2), only_value, eltsize);
|
||||
len1 = c_strlen (TREE_OPERAND (src, 1), only_value, nonstr, eltsize);
|
||||
len2 = c_strlen (TREE_OPERAND (src, 2), only_value, nonstr, eltsize);
|
||||
if (tree_int_cst_equal (len1, len2))
|
||||
return len1;
|
||||
}
|
||||
|
||||
if (TREE_CODE (src) == COMPOUND_EXPR
|
||||
&& (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
|
||||
return c_strlen (TREE_OPERAND (src, 1), only_value, eltsize);
|
||||
return c_strlen (TREE_OPERAND (src, 1), only_value, nonstr, eltsize);
|
||||
|
||||
location_t loc = EXPR_LOC_OR_LOC (src, input_location);
|
||||
|
||||
/* Offset from the beginning of the string in bytes. */
|
||||
tree byteoff;
|
||||
tree memsize;
|
||||
src = string_constant (src, &byteoff, &memsize, NULL);
|
||||
tree decl;
|
||||
src = string_constant (src, &byteoff, &memsize, &decl);
|
||||
if (src == 0)
|
||||
return NULL_TREE;
|
||||
|
||||
@ -628,8 +655,14 @@ c_strlen (tree src, int only_value, unsigned eltsize)
|
||||
unsigned len = string_length (ptr, eltsize, strelts);
|
||||
|
||||
/* Return when an embedded null character is found or none at all. */
|
||||
if (len + 1 < strelts || len >= maxelts)
|
||||
if (len + 1 < strelts)
|
||||
return NULL_TREE;
|
||||
else if (len >= maxelts)
|
||||
{
|
||||
if (nonstr && decl)
|
||||
*nonstr = decl;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* For empty strings the result should be zero. */
|
||||
if (len == 0)
|
||||
@ -694,7 +727,11 @@ c_strlen (tree src, int only_value, unsigned eltsize)
|
||||
/* Don't know what to return if there was no zero termination.
|
||||
Ideally this would turn into a gcc_checking_assert over time. */
|
||||
if (len >= maxelts - eltoff)
|
||||
return NULL_TREE;
|
||||
{
|
||||
if (nonstr && decl)
|
||||
*nonstr = decl;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
return ssize_int (len);
|
||||
}
|
||||
@ -8373,11 +8410,24 @@ fold_builtin_strlen (location_t loc, tree type, tree arg)
|
||||
return NULL_TREE;
|
||||
else
|
||||
{
|
||||
tree len = c_strlen (arg, 0);
|
||||
tree nonstr = NULL_TREE;
|
||||
tree len = c_strlen (arg, 0, &nonstr);
|
||||
|
||||
if (len)
|
||||
return fold_convert_loc (loc, type, len);
|
||||
|
||||
if (!nonstr)
|
||||
c_strlen (arg, 1, &nonstr); /* TODO: add test coverage here. */
|
||||
|
||||
if (nonstr)
|
||||
{
|
||||
if (EXPR_HAS_LOCATION (arg))
|
||||
loc = EXPR_LOCATION (arg);
|
||||
else if (loc == UNKNOWN_LOCATION)
|
||||
loc = input_location;
|
||||
warn_string_no_nul (loc, "strlen", arg, nonstr);
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ extern bool get_pointer_alignment_1 (tree, unsigned int *,
|
||||
unsigned HOST_WIDE_INT *);
|
||||
extern unsigned int get_pointer_alignment (tree);
|
||||
extern unsigned string_length (const void*, unsigned, unsigned);
|
||||
extern tree c_strlen (tree, int, unsigned = 1);
|
||||
extern tree c_strlen (tree, int, tree * = NULL, unsigned = 1);
|
||||
extern void expand_builtin_setjmp_setup (rtx, rtx);
|
||||
extern void expand_builtin_setjmp_receiver (rtx);
|
||||
extern void expand_builtin_update_setjmp_buf (rtx);
|
||||
@ -103,6 +103,7 @@ extern bool target_char_cst_p (tree t, char *p);
|
||||
extern internal_fn associated_internal_fn (tree);
|
||||
extern internal_fn replacement_internal_fn (gcall *);
|
||||
|
||||
extern void warn_string_no_nul (location_t, const char *, tree, tree);
|
||||
extern tree max_object_size ();
|
||||
|
||||
#endif /* GCC_BUILTINS_H */
|
||||
|
47
gcc/expr.c
47
gcc/expr.c
@ -11303,16 +11303,11 @@ is_aligning_offset (const_tree offset, const_tree exp)
|
||||
/* Return the tree node if an ARG corresponds to a string constant or zero
|
||||
if it doesn't. If we return nonzero, set *PTR_OFFSET to the (possibly
|
||||
non-constant) offset in bytes within the string that ARG is accessing.
|
||||
If NONSTR is non-null, consider valid even sequences of characters that
|
||||
aren't nul-terminated strings. In that case, if ARG refers to such
|
||||
a sequence set *NONSTR to its declaration and clear it otherwise.
|
||||
The type of the offset is sizetype. If MEM_SIZE is non-zero the storage
|
||||
size of the memory is returned. The returned STRING_CST object is
|
||||
valid up to TREE_STRING_LENGTH. Bytes between TREE_STRING_LENGTH
|
||||
and MEM_SIZE are zero. MEM_SIZE is at least TREE_STRING_LENGTH. */
|
||||
If MEM_SIZE is non-zero the storage size of the memory is returned.
|
||||
If DECL is non-zero the constant declaration is returned if available. */
|
||||
|
||||
tree
|
||||
string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *nonstr)
|
||||
string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *decl)
|
||||
{
|
||||
tree array;
|
||||
STRIP_NOPS (arg);
|
||||
@ -11341,6 +11336,12 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *nonstr)
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE)
|
||||
return NULL_TREE;
|
||||
|
||||
if (!integer_zerop (array_ref_low_bound (arg)))
|
||||
return NULL_TREE;
|
||||
|
||||
if (!integer_onep (array_ref_element_size (arg)))
|
||||
return NULL_TREE;
|
||||
}
|
||||
}
|
||||
array = get_addr_base_and_unit_offset (ref, &base_off);
|
||||
@ -11366,7 +11367,7 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *nonstr)
|
||||
return NULL_TREE;
|
||||
|
||||
tree offset;
|
||||
if (tree str = string_constant (arg0, &offset, mem_size, nonstr))
|
||||
if (tree str = string_constant (arg0, &offset, mem_size, decl))
|
||||
{
|
||||
/* Avoid pointers to arrays (see bug 86622). */
|
||||
if (POINTER_TYPE_P (TREE_TYPE (arg))
|
||||
@ -11396,11 +11397,7 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *nonstr)
|
||||
if (TREE_CODE (chartype) != INTEGER_TYPE)
|
||||
return NULL;
|
||||
|
||||
tree charsize = array_ref_element_size (arg);
|
||||
/* Set the non-constant offset to the non-constant index scaled
|
||||
by the size of the character type. */
|
||||
offset = fold_build2 (MULT_EXPR, TREE_TYPE (offset),
|
||||
fold_convert (sizetype, varidx), charsize);
|
||||
offset = fold_convert (sizetype, varidx);
|
||||
}
|
||||
|
||||
if (TREE_CODE (array) == STRING_CST)
|
||||
@ -11408,9 +11405,8 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *nonstr)
|
||||
*ptr_offset = fold_convert (sizetype, offset);
|
||||
if (mem_size)
|
||||
*mem_size = TYPE_SIZE_UNIT (TREE_TYPE (array));
|
||||
/* This is not strictly correct. FIXME in follow-up patch. */
|
||||
if (nonstr)
|
||||
*nonstr = NULL_TREE;
|
||||
if (decl)
|
||||
*decl = NULL_TREE;
|
||||
gcc_checking_assert (tree_to_shwi (TYPE_SIZE_UNIT (TREE_TYPE (array)))
|
||||
>= TREE_STRING_LENGTH (array));
|
||||
return array;
|
||||
@ -11455,23 +11451,10 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *nonstr)
|
||||
if (!init || TREE_CODE (init) != STRING_CST)
|
||||
return NULL_TREE;
|
||||
|
||||
/* Compute the lower bound number of elements (not bytes) in the array
|
||||
that the string is used to initialize. The actual size of the array
|
||||
may be greater if the string is shorter, but the the important
|
||||
data point is whether the literal, inlcuding the terminating nul,
|
||||
fits the array. */
|
||||
unsigned HOST_WIDE_INT charsize
|
||||
= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (init))));
|
||||
unsigned HOST_WIDE_INT array_elts
|
||||
= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (init))) / charsize;
|
||||
|
||||
/* Compute the string length in (wide) characters. */
|
||||
unsigned HOST_WIDE_INT length = TREE_STRING_LENGTH (init);
|
||||
|
||||
if (mem_size)
|
||||
*mem_size = TYPE_SIZE_UNIT (TREE_TYPE (init));
|
||||
if (nonstr)
|
||||
*nonstr = array_elts > length ? NULL_TREE : array;
|
||||
if (decl)
|
||||
*decl = array;
|
||||
|
||||
gcc_checking_assert (tree_to_shwi (TYPE_SIZE_UNIT (TREE_TYPE (init)))
|
||||
>= TREE_STRING_LENGTH (init));
|
||||
|
@ -14595,6 +14595,10 @@ c_getstr (tree src, unsigned HOST_WIDE_INT *strlen /* = NULL */)
|
||||
unsigned HOST_WIDE_INT string_length = TREE_STRING_LENGTH (src);
|
||||
unsigned HOST_WIDE_INT string_size = tree_to_uhwi (mem_size);
|
||||
|
||||
/* Ideally this would turn into a gcc_checking_assert over time. */
|
||||
if (string_length > string_size)
|
||||
string_length = string_size;
|
||||
|
||||
const char *string = TREE_STRING_POINTER (src);
|
||||
|
||||
/* Ideally this would turn into a gcc_checking_assert over time. */
|
||||
|
@ -1335,7 +1335,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|
||||
return false;
|
||||
}
|
||||
else
|
||||
val = c_strlen (arg, 1, eltsize);
|
||||
val = c_strlen (arg, 1, NULL, eltsize);
|
||||
|
||||
if (!val && fuzzy)
|
||||
{
|
||||
|
@ -1999,13 +1999,6 @@ get_string_length (tree str, unsigned eltsize)
|
||||
if (!str)
|
||||
return fmtresult ();
|
||||
|
||||
if (tree slen = c_strlen (str, 1, eltsize))
|
||||
{
|
||||
/* Simply return the length of the string. */
|
||||
fmtresult res (tree_to_shwi (slen));
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Determine the length of the shortest and longest string referenced
|
||||
by STR. Strings of unknown lengths are bounded by the sizes of
|
||||
arrays that subexpressions of STR may refer to. Pointers that
|
||||
|
@ -1,3 +1,8 @@
|
||||
2018-09-13 Martin Sebor <msebor@redhat.com>
|
||||
Jeff Law <law@redhat.com>
|
||||
|
||||
* gcc.dg/warn-strlen-no-nul.c: New test.
|
||||
|
||||
2018-09-13 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/87263
|
||||
|
301
gcc/testsuite/gcc.dg/warn-strlen-no-nul.c
Normal file
301
gcc/testsuite/gcc.dg/warn-strlen-no-nul.c
Normal file
@ -0,0 +1,301 @@
|
||||
/* PR tree-optimization/86552 - missing warning for reading past the end
|
||||
of non-string arrays
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
|
||||
|
||||
extern __SIZE_TYPE__ strlen (const char*);
|
||||
|
||||
const char a[5] = "12345"; /* { dg-message "declared here" } */
|
||||
|
||||
int v0 = 0;
|
||||
int v1 = 1;
|
||||
|
||||
void sink (int, ...);
|
||||
|
||||
#define CONCAT(a, b) a ## b
|
||||
#define CAT(a, b) CONCAT(a, b)
|
||||
|
||||
#define T(str) \
|
||||
__attribute__ ((noipa)) \
|
||||
void CAT (test_, __LINE__) (void) { \
|
||||
int i0 = 0, i1 = i0 + 1, i2 = i1 + 1, i3 = i2 + 1; \
|
||||
sink (strlen (str), i0, i1, i2, i3); \
|
||||
} typedef void dummy_type
|
||||
|
||||
T (a); /* { dg-warning "argument missing terminating nul" } */
|
||||
T (&a[0]); /* { dg-warning "nul" } */
|
||||
T (&a[0] + 1); /* { dg-warning "nul" } */
|
||||
T (&a[1]); /* { dg-warning "nul" } */
|
||||
T (&a[v0]); /* { dg-warning "nul" } */
|
||||
T (&a[v0] + 1); /* { dg-warning "nul" } */
|
||||
|
||||
|
||||
const char b[][5] = { /* { dg-message "declared here" } */
|
||||
"12", "123", "1234", "54321"
|
||||
};
|
||||
|
||||
T (b[0]);
|
||||
T (b[1]);
|
||||
T (b[2]);
|
||||
T (b[3]); /* { dg-warning "nul" } */
|
||||
|
||||
T (b[i0]);
|
||||
T (b[i1]);
|
||||
T (b[i2]);
|
||||
T (b[i3]); /* { dg-warning "nul" } */
|
||||
|
||||
T (b[v0]);
|
||||
|
||||
T (&b[i2][i1]);
|
||||
T (&b[i2][i1] + i1);
|
||||
T (&b[i2][v0]);
|
||||
T (&b[i2][i1] + v0);
|
||||
|
||||
T (&b[2][1]);
|
||||
T (&b[2][1] + i1);
|
||||
T (&b[2][i0]);
|
||||
T (&b[2][1] + i0);
|
||||
|
||||
T (&b[2][1]);
|
||||
T (&b[2][1] + v0);
|
||||
T (&b[2][v0]);
|
||||
|
||||
T (&b[3][1]); /* { dg-warning "nul" } */
|
||||
T (&b[3][1] + 1); /* { dg-warning "nul" } */
|
||||
T (&b[3][1] + i1); /* { dg-warning "nul" } */
|
||||
T (&b[3][v0]); /* { dg-warning "nul" } */
|
||||
T (&b[3][1] + v0); /* { dg-warning "nul" } */
|
||||
T (&b[3][v0] + v1); /* { dg-warning "nul" } */
|
||||
|
||||
T (&b[i3][i1]); /* { dg-warning "nul" } */
|
||||
T (&b[i3][i1] + 1); /* { dg-warning "nul" } */
|
||||
T (&b[i3][i1] + i1); /* { dg-warning "nul" } */
|
||||
T (&b[i3][v0]); /* { dg-warning "nul" "pr86919" { xfail *-*-* } } */
|
||||
T (&b[i3][i1] + v0); /* { dg-warning "nul" "pr86919" { xfail *-*-* } } */
|
||||
T (&b[i3][v0] + v1); /* { dg-warning "nul" "pr86919" { xfail *-*-* } } */
|
||||
|
||||
T (v0 ? "" : b[0]);
|
||||
T (v0 ? "" : b[1]);
|
||||
T (v0 ? "" : b[2]);
|
||||
T (v0 ? "" : b[3]); /* { dg-warning "nul" } */
|
||||
T (v0 ? b[0] : "");
|
||||
T (v0 ? b[1] : "");
|
||||
T (v0 ? b[2] : "");
|
||||
T (v0 ? b[3] : ""); /* { dg-warning "nul" } */
|
||||
|
||||
T (v0 ? "" : b[i0]);
|
||||
T (v0 ? "" : b[i1]);
|
||||
T (v0 ? "" : b[i2]);
|
||||
/* The following is diagnosed but the warning location is wrong
|
||||
(the PRE pass loses it). */
|
||||
T (v0 ? "" : b[i3]); /* { dg-warning "nul" } */
|
||||
T (v0 ? b[i0] : "");
|
||||
T (v0 ? b[i1] : "");
|
||||
T (v0 ? b[i2] : "");
|
||||
T (v0 ? b[i3] : ""); /* { dg-warning "nul" } */
|
||||
|
||||
T (v0 ? "1234" : b[3]); /* { dg-warning "nul" } */
|
||||
T (v0 ? "1234" : b[i3]); /* { dg-warning "nul" } */
|
||||
T (v0 ? b[3] : "1234"); /* { dg-warning "nul" } */
|
||||
T (v0 ? b[i3] : "1234"); /* { dg-warning "nul" } */
|
||||
|
||||
T (v0 ? a : b[3]); /* { dg-warning "nul" } */
|
||||
T (v0 ? b[0] : b[2]);
|
||||
T (v0 ? b[2] : b[3]); /* { dg-warning "nul" } */
|
||||
T (v0 ? b[3] : b[2]); /* { dg-warning "nul" } */
|
||||
|
||||
T (v0 ? a : b[i3]); /* { dg-warning "nul" } */
|
||||
T (v0 ? b[i0] : b[i2]);
|
||||
T (v0 ? b[i2] : b[i3]); /* { dg-warning "nul" } */
|
||||
T (v0 ? b[i3] : b[i2]); /* { dg-warning "nul" } */
|
||||
|
||||
T (v0 ? b[0] : &b[3][0] + 1); /* { dg-warning "nul" } */
|
||||
T (v0 ? b[0] : &b[3][0] + i1); /* { dg-warning "nul" } */
|
||||
T (v0 ? b[1] : &b[3][1] + v0); /* { dg-warning "nul" } */
|
||||
|
||||
T (v0 ? b[i0] : &b[i3][i0] + i1); /* { dg-warning "nul" } */
|
||||
T (v0 ? b[i0] : &b[i3][i0] + i1); /* { dg-warning "nul" } */
|
||||
T (v0 ? b[i1] : &b[i3][i1] + v0); /* { dg-warning "nul" } */
|
||||
|
||||
/* It's possible to detect the missing nul in the following two
|
||||
expressions but GCC doesn't do it yet. */
|
||||
T (v0 ? &b[3][1] + v0 : b[2]); /* { dg-warning "nul" "bug" } */
|
||||
T (v0 ? &b[3][v0] : &b[3][v1]); /* { dg-warning "nul" "bug" } */
|
||||
|
||||
|
||||
struct A { char a[5], b[5]; };
|
||||
|
||||
const struct A s = { "1234", "12345" };
|
||||
|
||||
T (s.a);
|
||||
T (&s.a[0]);
|
||||
T (&s.a[0] + 1);
|
||||
T (&s.a[0] + v0);
|
||||
T (&s.a[1]);
|
||||
T (&s.a[1] + 1);
|
||||
T (&s.a[1] + v0);
|
||||
|
||||
T (&s.a[i0]);
|
||||
T (&s.a[i0] + i1);
|
||||
T (&s.a[i0] + v0);
|
||||
T (&s.a[i1]);
|
||||
T (&s.a[i1] + i1);
|
||||
T (&s.a[i1] + v0);
|
||||
|
||||
T (s.b); /* { dg-warning "nul" } */
|
||||
T (&s.b[0]); /* { dg-warning "nul" } */
|
||||
T (&s.b[0] + 1); /* { dg-warning "nul" } */
|
||||
T (&s.b[0] + v0); /* { dg-warning "nul" } */
|
||||
T (&s.b[1]); /* { dg-warning "nul" } */
|
||||
T (&s.b[1] + 1); /* { dg-warning "nul" } */
|
||||
T (&s.b[1] + i0); /* { dg-warning "nul" } */
|
||||
T (&s.b[1] + v0); /* { dg-warning "nul" } */
|
||||
|
||||
T (&s.b[i0]); /* { dg-warning "nul" } */
|
||||
T (&s.b[i0] + i1); /* { dg-warning "nul" } */
|
||||
T (&s.b[i0] + v0); /* { dg-warning "nul" "pr86919" { xfail *-*-* } } */
|
||||
T (&s.b[i1]); /* { dg-warning "nul" } */
|
||||
T (&s.b[i1] + i1); /* { dg-warning "nul" } */
|
||||
T (&s.b[i1] + v0); /* { dg-warning "nul" "pr86919" { xfail *-*-* } } */
|
||||
|
||||
struct B { struct A a[2]; };
|
||||
|
||||
const struct B ba[] = {
|
||||
{ { { "123", "12345" }, { "12345", "123" } } },
|
||||
{ { { "12345", "123" }, { "123", "12345" } } },
|
||||
{ { { "1", "12" }, { "123", "1234" } } },
|
||||
{ { { "123", "1234" }, { "12345", "12" } } }
|
||||
};
|
||||
|
||||
T (ba[0].a[0].a);
|
||||
T (&ba[0].a[0].a[0]);
|
||||
T (&ba[0].a[0].a[0] + 1);
|
||||
T (&ba[0].a[0].a[0] + v0);
|
||||
T (&ba[0].a[0].a[1]);
|
||||
T (&ba[0].a[0].a[1] + 1);
|
||||
T (&ba[0].a[0].a[1] + v0);
|
||||
|
||||
T (ba[0].a[0].b); /* { dg-warning "nul" } */
|
||||
T (&ba[0].a[0].b[0]); /* { dg-warning "nul" } */
|
||||
T (&ba[0].a[0].b[0] + 1); /* { dg-warning "nul" } */
|
||||
T (&ba[0].a[0].b[0] + v0); /* { dg-warning "nul" } */
|
||||
T (&ba[0].a[0].b[1]); /* { dg-warning "nul" } */
|
||||
T (&ba[0].a[0].b[1] + 1); /* { dg-warning "nul" } */
|
||||
T (&ba[0].a[0].b[1] + v0); /* { dg-warning "nul" } */
|
||||
|
||||
T (ba[0].a[1].a); /* { dg-warning "nul" } */
|
||||
T (&ba[0].a[1].a[0]); /* { dg-warning "nul" } */
|
||||
T (&ba[0].a[1].a[0] + 1); /* { dg-warning "nul" } */
|
||||
T (&ba[0].a[1].a[0] + v0); /* { dg-warning "nul" } */
|
||||
T (&ba[0].a[1].a[1]); /* { dg-warning "nul" } */
|
||||
T (&ba[0].a[1].a[1] + 1); /* { dg-warning "nul" } */
|
||||
T (&ba[0].a[1].a[1] + v0); /* { dg-warning "nul" } */
|
||||
|
||||
T (ba[0].a[1].b);
|
||||
T (&ba[0].a[1].b[0]);
|
||||
T (&ba[0].a[1].b[0] + 1);
|
||||
T (&ba[0].a[1].b[0] + v0);
|
||||
T (&ba[0].a[1].b[1]);
|
||||
T (&ba[0].a[1].b[1] + 1);
|
||||
T (&ba[0].a[1].b[1] + v0);
|
||||
|
||||
|
||||
T (ba[1].a[0].a); /* { dg-warning "nul" } */
|
||||
T (&ba[1].a[0].a[0]); /* { dg-warning "nul" } */
|
||||
T (&ba[1].a[0].a[0] + 1); /* { dg-warning "nul" } */
|
||||
T (&ba[1].a[0].a[0] + v0); /* { dg-warning "nul" } */
|
||||
T (&ba[1].a[0].a[1]); /* { dg-warning "nul" } */
|
||||
T (&ba[1].a[0].a[1] + 1); /* { dg-warning "nul" } */
|
||||
T (&ba[1].a[0].a[1] + v0); /* { dg-warning "nul" } */
|
||||
|
||||
T (ba[1].a[0].b);
|
||||
T (&ba[1].a[0].b[0]);
|
||||
T (&ba[1].a[0].b[0] + 1);
|
||||
T (&ba[1].a[0].b[0] + v0);
|
||||
T (&ba[1].a[0].b[1]);
|
||||
T (&ba[1].a[0].b[1] + 1);
|
||||
T (&ba[1].a[0].b[1] + v0);
|
||||
|
||||
T (ba[1].a[1].a);
|
||||
T (&ba[1].a[1].a[0]);
|
||||
T (&ba[1].a[1].a[0] + 1);
|
||||
T (&ba[1].a[1].a[0] + v0);
|
||||
T (&ba[1].a[1].a[1]);
|
||||
T (&ba[1].a[1].a[1] + 1);
|
||||
T (&ba[1].a[1].a[1] + v0);
|
||||
|
||||
T (ba[1].a[1].b); /* { dg-warning "nul" } */
|
||||
T (&ba[1].a[1].b[0]); /* { dg-warning "nul" } */
|
||||
T (&ba[1].a[1].b[0] + 1); /* { dg-warning "nul" } */
|
||||
T (&ba[1].a[1].b[0] + v0); /* { dg-warning "nul" } */
|
||||
T (&ba[1].a[1].b[1]); /* { dg-warning "nul" } */
|
||||
T (&ba[1].a[1].b[1] + 1); /* { dg-warning "nul" } */
|
||||
T (&ba[1].a[1].b[1] + v0); /* { dg-warning "nul" } */
|
||||
|
||||
|
||||
T (ba[2].a[0].a);
|
||||
T (&ba[2].a[0].a[0]);
|
||||
T (&ba[2].a[0].a[0] + 1);
|
||||
T (&ba[2].a[0].a[0] + v0);
|
||||
T (&ba[2].a[0].a[1]);
|
||||
T (&ba[2].a[0].a[1] + 1);
|
||||
T (&ba[2].a[0].a[1] + v0);
|
||||
|
||||
T (ba[2].a[0].b);
|
||||
T (&ba[2].a[0].b[0]);
|
||||
T (&ba[2].a[0].b[0] + 1);
|
||||
T (&ba[2].a[0].b[0] + v0);
|
||||
T (&ba[2].a[0].b[1]);
|
||||
T (&ba[2].a[0].b[1] + 1);
|
||||
T (&ba[2].a[0].b[1] + v0);
|
||||
|
||||
T (ba[2].a[1].a);
|
||||
T (&ba[2].a[1].a[0]);
|
||||
T (&ba[2].a[1].a[0] + 1);
|
||||
T (&ba[2].a[1].a[0] + v0);
|
||||
T (&ba[2].a[1].a[1]);
|
||||
T (&ba[2].a[1].a[1] + 1);
|
||||
T (&ba[2].a[1].a[1] + v0);
|
||||
|
||||
|
||||
T (ba[3].a[0].a);
|
||||
T (&ba[3].a[0].a[0]);
|
||||
T (&ba[3].a[0].a[0] + 1);
|
||||
T (&ba[3].a[0].a[0] + v0);
|
||||
T (&ba[3].a[0].a[1]);
|
||||
T (&ba[3].a[0].a[1] + 1);
|
||||
T (&ba[3].a[0].a[1] + v0);
|
||||
|
||||
T (ba[3].a[0].b);
|
||||
T (&ba[3].a[0].b[0]);
|
||||
T (&ba[3].a[0].b[0] + 1);
|
||||
T (&ba[3].a[0].b[0] + v0);
|
||||
T (&ba[3].a[0].b[1]);
|
||||
T (&ba[3].a[0].b[1] + 1);
|
||||
T (&ba[3].a[0].b[1] + v0);
|
||||
|
||||
T (ba[3].a[1].a); /* { dg-warning "nul" } */
|
||||
T (&ba[3].a[1].a[0]); /* { dg-warning "nul" } */
|
||||
T (&ba[3].a[1].a[0] + 1); /* { dg-warning "nul" } */
|
||||
T (&ba[3].a[1].a[0] + v0); /* { dg-warning "nul" } */
|
||||
T (&ba[3].a[1].a[1]); /* { dg-warning "nul" } */
|
||||
T (&ba[3].a[1].a[1] + 1); /* { dg-warning "nul" } */
|
||||
T (&ba[3].a[1].a[1] + v0); /* { dg-warning "nul" } */
|
||||
|
||||
T (ba[3].a[1].b);
|
||||
T (&ba[3].a[1].b[0]);
|
||||
T (&ba[3].a[1].b[0] + 1);
|
||||
T (&ba[3].a[1].b[0] + v0);
|
||||
T (&ba[3].a[1].b[1]);
|
||||
T (&ba[3].a[1].b[1] + 1);
|
||||
T (&ba[3].a[1].b[1] + v0);
|
||||
|
||||
|
||||
T (v0 ? ba[0].a[0].a : ba[0].a[0].b); /* { dg-warning "nul" } */
|
||||
T (v0 ? ba[0].a[0].a : ba[0].a[0].b); /* { dg-warning "nul" } */
|
||||
|
||||
T (v0 ? &ba[0].a[0].a[0] : &ba[3].a[1].a[0]); /* { dg-warning "nul" } */
|
||||
T (v0 ? &ba[3].a[1].a[1] : ba[0].a[0].a); /* { dg-warning "nul" } */
|
||||
|
||||
T (v0 ? ba[0].a[0].a : ba[0].a[1].b);
|
||||
T (v0 ? ba[0].a[1].b : ba[0].a[0].a);
|
@ -291,8 +291,6 @@ get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out)
|
||||
static int
|
||||
get_stridx (tree exp)
|
||||
{
|
||||
tree s, o;
|
||||
|
||||
if (TREE_CODE (exp) == SSA_NAME)
|
||||
{
|
||||
if (ssa_ver_to_stridx[SSA_NAME_VERSION (exp)])
|
||||
@ -336,18 +334,10 @@ get_stridx (tree exp)
|
||||
return idx;
|
||||
}
|
||||
|
||||
s = string_constant (exp, &o, NULL, NULL);
|
||||
if (s != NULL_TREE
|
||||
&& (o == NULL_TREE || tree_fits_shwi_p (o))
|
||||
&& TREE_STRING_LENGTH (s) > 0)
|
||||
{
|
||||
HOST_WIDE_INT offset = o ? tree_to_shwi (o) : 0;
|
||||
const char *p = TREE_STRING_POINTER (s);
|
||||
int max = TREE_STRING_LENGTH (s) - 1;
|
||||
const char *p = c_getstr (exp);
|
||||
if (p)
|
||||
return ~(int) strlen (p);
|
||||
|
||||
if (p[max] == '\0' && offset >= 0 && offset <= max)
|
||||
return ~(int) strlen (p + offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user