PR tree-optimization/89688 - -Wstringop-overflow confused by const 2D array of char
gcc/c/ChangeLog: PR tree-optimization/89688 * c-decl.c (finish_decl): Call braced_lists_to_string for more kinds of initializers. gcc/c-family/ChangeLog: PR tree-optimization/89688 * c-common.c (braced_list_to_string): Make static. (braced_lists_to_strings): Define new function. * c-common.h (braced_list_to_string): Remove. (braced_lists_to_strings): Declare. gcc/cp/ChangeLog: PR tree-optimization/89688 * typeck2.c (store_init_value): Call braced_lists_to_string for more kinds of initializers. gcc/testsuite/ChangeLog: PR tree-optimization/89688 * gcc.dg/strlenopt-61.c: New test. * g++.dg/warn/Wstringop-overflow-2.C: New test. From-SVN: r269814
This commit is contained in:
parent
026216a753
commit
bec1da64ae
|
@ -1,3 +1,11 @@
|
|||
2019-03-19 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/89688
|
||||
* c-common.c (braced_list_to_string): Make static.
|
||||
(braced_lists_to_strings): Define new function.
|
||||
* c-common.h (braced_list_to_string): Remove.
|
||||
(braced_lists_to_strings): Declare.
|
||||
|
||||
2019-03-12 Martin Liska <mliska@suse.cz>
|
||||
|
||||
* c-opts.c (c_common_handle_option): Wrap option with %< and %>.
|
||||
|
|
|
@ -8814,7 +8814,7 @@ maybe_add_include_fixit (rich_location *richloc, const char *header,
|
|||
TYPE into a STRING_CST for convenience and efficiency. Return
|
||||
the converted string on success or the original ctor on failure. */
|
||||
|
||||
tree
|
||||
static tree
|
||||
braced_list_to_string (tree type, tree ctor)
|
||||
{
|
||||
if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
|
||||
|
@ -8895,4 +8895,52 @@ braced_list_to_string (tree type, tree ctor)
|
|||
return res;
|
||||
}
|
||||
|
||||
/* Attempt to convert a CTOR containing braced array initializer lists
|
||||
for array TYPE into one containing STRING_CSTs, for convenience and
|
||||
efficiency. Recurse for arrays of arrays and member initializers.
|
||||
Return the converted CTOR or STRING_CST on success or the original
|
||||
CTOR otherwise. */
|
||||
|
||||
tree
|
||||
braced_lists_to_strings (tree type, tree ctor)
|
||||
{
|
||||
if (TREE_CODE (ctor) != CONSTRUCTOR)
|
||||
return ctor;
|
||||
|
||||
tree_code code = TREE_CODE (type);
|
||||
|
||||
tree ttp;
|
||||
if (code == ARRAY_TYPE)
|
||||
ttp = TREE_TYPE (type);
|
||||
else if (code == RECORD_TYPE)
|
||||
{
|
||||
ttp = TREE_TYPE (ctor);
|
||||
if (TREE_CODE (ttp) == ARRAY_TYPE)
|
||||
{
|
||||
type = ttp;
|
||||
ttp = TREE_TYPE (ttp);
|
||||
}
|
||||
}
|
||||
else
|
||||
return ctor;
|
||||
|
||||
if (TYPE_STRING_FLAG (ttp))
|
||||
return braced_list_to_string (type, ctor);
|
||||
|
||||
code = TREE_CODE (ttp);
|
||||
if (code == ARRAY_TYPE || code == RECORD_TYPE)
|
||||
{
|
||||
/* Handle array of arrays or struct member initializers. */
|
||||
tree val;
|
||||
unsigned HOST_WIDE_INT idx;
|
||||
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), idx, val)
|
||||
{
|
||||
val = braced_lists_to_strings (ttp, val);
|
||||
CONSTRUCTOR_ELT (ctor, idx)->value = val;
|
||||
}
|
||||
}
|
||||
|
||||
return ctor;
|
||||
}
|
||||
|
||||
#include "gt-c-family-c-common.h"
|
||||
|
|
|
@ -1372,7 +1372,8 @@ extern void maybe_add_include_fixit (rich_location *, const char *, bool);
|
|||
extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
|
||||
enum cpp_ttype token_type,
|
||||
location_t prev_token_loc);
|
||||
extern tree braced_list_to_string (tree, tree);
|
||||
extern tree braced_lists_to_strings (tree, tree);
|
||||
|
||||
extern bool has_attribute (location_t, tree, tree, tree (*)(tree));
|
||||
|
||||
#if CHECKING_P
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2019-03-19 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/89688
|
||||
* c-decl.c (finish_decl): Call braced_lists_to_string for more
|
||||
kinds of initializers.
|
||||
|
||||
2019-03-19 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c/89734
|
||||
|
|
|
@ -5165,11 +5165,10 @@ finish_decl (tree decl, location_t init_loc, tree init,
|
|||
relayout_decl (decl);
|
||||
}
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_TYPE
|
||||
&& TYPE_STRING_FLAG (TREE_TYPE (type))
|
||||
&& DECL_INITIAL (decl)
|
||||
&& TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR)
|
||||
DECL_INITIAL (decl) = braced_list_to_string (type, DECL_INITIAL (decl));
|
||||
/* Look for braced array initializers for character arrays and
|
||||
recursively convert them into STRING_CSTs. */
|
||||
if (tree init = DECL_INITIAL (decl))
|
||||
DECL_INITIAL (decl) = braced_lists_to_strings (type, init);
|
||||
|
||||
if (VAR_P (decl))
|
||||
{
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2019-03-19 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/89688
|
||||
* typeck2.c (store_init_value): Call braced_lists_to_string for more
|
||||
kinds of initializers.
|
||||
|
||||
2019-03-18 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/89630 - ICE with dependent using-decl as template arg.
|
||||
|
|
|
@ -824,10 +824,9 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
|
|||
value = digest_init_flags (type, init, flags, tf_warning_or_error);
|
||||
}
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_TYPE
|
||||
&& TYPE_STRING_FLAG (TREE_TYPE (type))
|
||||
&& TREE_CODE (value) == CONSTRUCTOR)
|
||||
value = braced_list_to_string (type, value);
|
||||
/* Look for braced array initializers for character arrays and
|
||||
recursively convert them into STRING_CSTs. */
|
||||
value = braced_lists_to_strings (type, value);
|
||||
|
||||
current_ref_temp_count = 0;
|
||||
value = extend_ref_init_temps (decl, value, cleanups);
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2019-03-19 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/89688
|
||||
* gcc.dg/strlenopt-61.c: New test.
|
||||
* g++.dg/warn/Wstringop-overflow-2.C: New test.
|
||||
|
||||
2019-03-19 Jim Wilson <jimw@sifive.com>
|
||||
|
||||
PR target/89411
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/* PR tree-optimization/89688 - -Wstringop-overflow confused by const 2D
|
||||
array of char
|
||||
{ dg-do compile }
|
||||
{ dg-options "-Wall -fdump-tree-gimple -fdump-tree-optimized" } */
|
||||
|
||||
extern "C" __SIZE_TYPE__ strlen (const char*);
|
||||
|
||||
const char a2[2] = { '1' };
|
||||
|
||||
void a2_len ()
|
||||
{
|
||||
if (strlen (a2) != 1)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
const char a2_2[2][3] = { { '1' }, { '1', '2' } };
|
||||
|
||||
void a2_2_len ()
|
||||
{
|
||||
if (strlen (a2_2[0]) != 1) // { dg-bogus "-Wstringop-overflow" }
|
||||
__builtin_abort ();
|
||||
|
||||
if (strlen (a2_2[1]) != 2) // { dg-bogus "-Wstringop-overflow" }
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "abort" "optimized" } }
|
||||
{ dg-final { scan-tree-dump-not "strlen" "gimple" } } */
|
|
@ -0,0 +1,218 @@
|
|||
/* PR tree-optimization/89688 - -Wstringop-overflow confused by const
|
||||
2D array of char
|
||||
{ dg-do compile }
|
||||
{ dg-options "-Wall -fdump-tree-gimple -fdump-tree-optimized" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
size_t strlen (const char*);
|
||||
#define CAT(x, y) x ## y
|
||||
#define CONCAT(x, y) CAT (x, y)
|
||||
#define FAILNAME(name) CONCAT (call_ ## name ##_on_line_, __LINE__)
|
||||
|
||||
#define FAIL(name) do { \
|
||||
extern __attribute__ ((noreturn)) void FAILNAME (name) (void); \
|
||||
FAILNAME (name)(); \
|
||||
} while (0)
|
||||
|
||||
#define A(ref, len) \
|
||||
if (strlen (ref) != len) FAIL (failure); else (void)0
|
||||
|
||||
const char a3_4[3][4] = { { 1 }, { 1, 2 }, { 1, 2, 3 } };
|
||||
|
||||
void test_a4_4 (void)
|
||||
{
|
||||
A (a3_4[0], 1);
|
||||
A (a3_4[1], 2);
|
||||
A (a3_4[2], 3);
|
||||
|
||||
A (&a3_4[0][0], 1);
|
||||
A (&a3_4[0][1], 0);
|
||||
A (&a3_4[0][2], 0);
|
||||
A (&a3_4[0][3], 0);
|
||||
|
||||
A (&a3_4[1][0], 2);
|
||||
A (&a3_4[1][1], 1);
|
||||
A (&a3_4[1][2], 0);
|
||||
A (&a3_4[1][3], 0);
|
||||
|
||||
A (&a3_4[2][0], 3);
|
||||
A (&a3_4[2][1], 2);
|
||||
A (&a3_4[2][2], 1);
|
||||
A (&a3_4[2][3], 0);
|
||||
}
|
||||
|
||||
|
||||
const char a3_4_5[3][4][5] =
|
||||
{
|
||||
{ { 1 }, { 1, 2 }, { 1, 2, 3 }, { 1, 2, 3, 4 } },
|
||||
{ { 1, 2 }, { 1, 2, 3 }, { 1, 2, 3, 4 }, { 1 } },
|
||||
{ { 1, 2, 3 }, { 1, 2, 3, 4 }, { 1 }, { 1, 2 } },
|
||||
};
|
||||
|
||||
void test_a3_4_5 (void)
|
||||
{
|
||||
A (a3_4_5[0][0], 1);
|
||||
A (a3_4_5[0][1], 2);
|
||||
A (a3_4_5[0][2], 3);
|
||||
A (a3_4_5[0][3], 4);
|
||||
|
||||
A (a3_4_5[1][0], 2);
|
||||
A (a3_4_5[1][1], 3);
|
||||
A (a3_4_5[1][2], 4);
|
||||
A (a3_4_5[1][3], 1);
|
||||
|
||||
A (a3_4_5[2][0], 3);
|
||||
A (a3_4_5[2][1], 4);
|
||||
A (a3_4_5[2][2], 1);
|
||||
A (a3_4_5[2][3], 2);
|
||||
}
|
||||
|
||||
|
||||
struct S
|
||||
{
|
||||
char a3[3];
|
||||
char a4_5[4][5];
|
||||
};
|
||||
|
||||
const struct S sa4[4] =
|
||||
{
|
||||
{ .a3 = { 0 },
|
||||
.a4_5 =
|
||||
{
|
||||
{ 1 }, { 1, 2 }, { 1, 2, 3 }, { 1, 2, 3, 4 }
|
||||
}
|
||||
},
|
||||
{ .a3 = { 1 },
|
||||
.a4_5 =
|
||||
{
|
||||
{ 1, 2 }, { 1, 2, 3 }, { 1, 2, 3, 4 }, { 1 }
|
||||
}
|
||||
},
|
||||
{ .a3 = { 1, 2 },
|
||||
.a4_5 =
|
||||
{
|
||||
{ 1, 2, 3 }, { 1, 2, 3, 4 }, { 1 }, { 1, 2 }
|
||||
}
|
||||
},
|
||||
{ .a3 = { 1 },
|
||||
.a4_5 =
|
||||
{
|
||||
{ 1, 2, 3, 4 }, "1", { 1, 2 }, "123"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void test_sa4 (void)
|
||||
{
|
||||
A (sa4[0].a3, 0);
|
||||
A (sa4[0].a4_5[0], 1);
|
||||
A (sa4[0].a4_5[1], 2);
|
||||
A (sa4[0].a4_5[2], 3);
|
||||
A (sa4[0].a4_5[3], 4);
|
||||
|
||||
A (sa4[1].a3, 1);
|
||||
A (sa4[1].a4_5[0], 2);
|
||||
A (sa4[1].a4_5[1], 3);
|
||||
A (sa4[1].a4_5[2], 4);
|
||||
A (sa4[1].a4_5[3], 1);
|
||||
|
||||
A (sa4[2].a3, 2);
|
||||
A (sa4[2].a4_5[0], 3);
|
||||
A (sa4[2].a4_5[1], 4);
|
||||
A (sa4[2].a4_5[2], 1);
|
||||
A (sa4[2].a4_5[3], 2);
|
||||
|
||||
A (sa4[3].a3, 1);
|
||||
A (sa4[3].a4_5[0], 4);
|
||||
A (sa4[3].a4_5[1], 1);
|
||||
A (sa4[3].a4_5[2], 2);
|
||||
A (sa4[3].a4_5[3], 3);
|
||||
}
|
||||
|
||||
|
||||
struct T
|
||||
{
|
||||
struct S sa2[2];
|
||||
char a4[4];
|
||||
};
|
||||
|
||||
const struct T ta2[2] =
|
||||
{
|
||||
[0] =
|
||||
{
|
||||
.sa2 =
|
||||
{
|
||||
[0] =
|
||||
{ .a3 = { 0 },
|
||||
.a4_5 =
|
||||
{
|
||||
{ 1 }, { 1, 2 }, { 1, 2, 3 }, { 1, 2, 3, 4 }
|
||||
}
|
||||
},
|
||||
[1] =
|
||||
{ .a3 = { 1 },
|
||||
.a4_5 =
|
||||
{
|
||||
{ 1, 2 }, { 1, 2, 3 }, { 1, 2, 3, 4 }, { 1 }
|
||||
}
|
||||
},
|
||||
},
|
||||
.a4 = "12"
|
||||
},
|
||||
|
||||
[1] =
|
||||
{
|
||||
.sa2 =
|
||||
{
|
||||
[0] =
|
||||
{ .a3 = { 1, 2 },
|
||||
.a4_5 =
|
||||
{
|
||||
{ 1, 2, 3 }, { 1, 2, 3, 4 }, { 1 }, { 1, 2 }
|
||||
}
|
||||
},
|
||||
{ .a3 = { 1 },
|
||||
.a4_5 =
|
||||
{
|
||||
{ 1, 2, 3, 4 }, "1", { 1, 2 }, "123"
|
||||
}
|
||||
}
|
||||
},
|
||||
.a4 = "123"
|
||||
}
|
||||
};
|
||||
|
||||
void test_ta2 (void)
|
||||
{
|
||||
A (ta2[0].sa2[0].a3, 0);
|
||||
A (ta2[0].sa2[0].a4_5[0], 1);
|
||||
A (ta2[0].sa2[0].a4_5[1], 2);
|
||||
A (ta2[0].sa2[0].a4_5[2], 3);
|
||||
A (ta2[0].sa2[0].a4_5[3], 4);
|
||||
|
||||
A (ta2[0].sa2[1].a3, 1);
|
||||
A (ta2[0].sa2[1].a4_5[0], 2);
|
||||
A (ta2[0].sa2[1].a4_5[1], 3);
|
||||
A (ta2[0].sa2[1].a4_5[2], 4);
|
||||
A (ta2[0].sa2[1].a4_5[3], 1);
|
||||
|
||||
A (ta2[0].a4, 2);
|
||||
|
||||
A (ta2[1].sa2[0].a3, 2);
|
||||
A (ta2[1].sa2[0].a4_5[0], 3);
|
||||
A (ta2[1].sa2[0].a4_5[1], 4);
|
||||
A (ta2[1].sa2[0].a4_5[2], 1);
|
||||
A (ta2[1].sa2[0].a4_5[3], 2);
|
||||
|
||||
A (ta2[1].sa2[1].a3, 1);
|
||||
A (ta2[1].sa2[1].a4_5[0], 4);
|
||||
A (ta2[1].sa2[1].a4_5[1], 1);
|
||||
A (ta2[1].sa2[1].a4_5[2], 2);
|
||||
A (ta2[1].sa2[1].a4_5[3], 3);
|
||||
|
||||
A (ta2[1].a4, 3);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "failure" "optimized" } }
|
||||
{ dg-final { scan-tree-dump-not "strlen" "gimple" } } */
|
Loading…
Reference in New Issue