Commit bec1da64 by Martin Sebor Committed by Martin Sebor

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
parent 026216a7
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> 2019-03-12 Martin Liska <mliska@suse.cz>
* c-opts.c (c_common_handle_option): Wrap option with %< and %>. * 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, ...@@ -8814,7 +8814,7 @@ maybe_add_include_fixit (rich_location *richloc, const char *header,
TYPE into a STRING_CST for convenience and efficiency. Return TYPE into a STRING_CST for convenience and efficiency. Return
the converted string on success or the original ctor on failure. */ the converted string on success or the original ctor on failure. */
tree static tree
braced_list_to_string (tree type, tree ctor) braced_list_to_string (tree type, tree ctor)
{ {
if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))) if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
...@@ -8895,4 +8895,52 @@ braced_list_to_string (tree type, tree ctor) ...@@ -8895,4 +8895,52 @@ braced_list_to_string (tree type, tree ctor)
return res; 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" #include "gt-c-family-c-common.h"
...@@ -1372,7 +1372,8 @@ extern void maybe_add_include_fixit (rich_location *, const char *, bool); ...@@ -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, extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
enum cpp_ttype token_type, enum cpp_ttype token_type,
location_t prev_token_loc); 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)); extern bool has_attribute (location_t, tree, tree, tree (*)(tree));
#if CHECKING_P #if CHECKING_P
......
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> 2019-03-19 Jakub Jelinek <jakub@redhat.com>
PR c/89734 PR c/89734
......
...@@ -5165,11 +5165,10 @@ finish_decl (tree decl, location_t init_loc, tree init, ...@@ -5165,11 +5165,10 @@ finish_decl (tree decl, location_t init_loc, tree init,
relayout_decl (decl); relayout_decl (decl);
} }
if (TREE_CODE (type) == ARRAY_TYPE /* Look for braced array initializers for character arrays and
&& TYPE_STRING_FLAG (TREE_TYPE (type)) recursively convert them into STRING_CSTs. */
&& DECL_INITIAL (decl) if (tree init = DECL_INITIAL (decl))
&& TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR) DECL_INITIAL (decl) = braced_lists_to_strings (type, init);
DECL_INITIAL (decl) = braced_list_to_string (type, DECL_INITIAL (decl));
if (VAR_P (decl)) if (VAR_P (decl))
{ {
......
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> 2019-03-18 Jason Merrill <jason@redhat.com>
PR c++/89630 - ICE with dependent using-decl as template arg. 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) ...@@ -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); value = digest_init_flags (type, init, flags, tf_warning_or_error);
} }
if (TREE_CODE (type) == ARRAY_TYPE /* Look for braced array initializers for character arrays and
&& TYPE_STRING_FLAG (TREE_TYPE (type)) recursively convert them into STRING_CSTs. */
&& TREE_CODE (value) == CONSTRUCTOR) value = braced_lists_to_strings (type, value);
value = braced_list_to_string (type, value);
current_ref_temp_count = 0; current_ref_temp_count = 0;
value = extend_ref_init_temps (decl, value, cleanups); value = extend_ref_init_temps (decl, value, cleanups);
......
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> 2019-03-19 Jim Wilson <jimw@sifive.com>
PR target/89411 PR target/89411
......
/* 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" } } */
/* 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" } } */
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