c-common.c (braced_list_to_string): Remove eval parameter.
* c-common.c (braced_list_to_string): Remove eval parameter. Add some more checks. Always create zero-terminated STRING_CST. * c-common.h (braced_list_to_string): Adjust prototype. * c-decl.c (finish_decl): Call braced_list_to_string here ... * c-parser.c (c_parser_declaration_or_fndef): ... instead of here. * decl.c (eval_check_narrowing): Remove. (check_initializer): Move call to braced_list_to_string from here ... * typeck2.c (store_init_value): ... to here. (digest_init_r): Remove handing of signed/unsigned char strings. * c-c++-common/array-init.c: New test. * g++.dg/init/string2.C: Remove xfail. From-SVN: r264042
This commit is contained in:
parent
b101633fa6
commit
b5764229c1
12 changed files with 72 additions and 86 deletions
|
@ -1,3 +1,9 @@
|
|||
2018-09-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* c-common.c (braced_list_to_string): Remove eval parameter.
|
||||
Add some more checks. Always create zero-terminated STRING_CST.
|
||||
* c-common.h (braced_list_to_string): Adjust prototype.
|
||||
|
||||
2018-08-27 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR 87091
|
||||
|
|
|
@ -8542,39 +8542,28 @@ maybe_add_include_fixit (rich_location *richloc, const char *header,
|
|||
}
|
||||
|
||||
/* Attempt to convert a braced array initializer list CTOR for array
|
||||
TYPE into a STRING_CST for convenience and efficiency. When non-null,
|
||||
use EVAL to attempt to evalue constants (used by C++). Return
|
||||
the converted string on success or null on failure. */
|
||||
TYPE into a STRING_CST for convenience and efficiency. Return
|
||||
the converted string on success or the original ctor on failure. */
|
||||
|
||||
tree
|
||||
braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree))
|
||||
braced_list_to_string (tree type, tree ctor)
|
||||
{
|
||||
unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
|
||||
if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
|
||||
return ctor;
|
||||
|
||||
/* If the array has an explicit bound, use it to constrain the size
|
||||
of the string. If it doesn't, be sure to create a string that's
|
||||
as long as implied by the index of the last zero specified via
|
||||
a designator, as in:
|
||||
const char a[] = { [7] = 0 }; */
|
||||
unsigned HOST_WIDE_INT maxelts = HOST_WIDE_INT_M1U;
|
||||
if (tree size = TYPE_SIZE_UNIT (type))
|
||||
{
|
||||
if (tree_fits_uhwi_p (size))
|
||||
{
|
||||
maxelts = tree_to_uhwi (size);
|
||||
maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
|
||||
unsigned HOST_WIDE_INT maxelts = tree_to_uhwi (TYPE_SIZE_UNIT (type));
|
||||
maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
|
||||
|
||||
/* Avoid converting initializers for zero-length arrays. */
|
||||
if (!maxelts)
|
||||
return NULL_TREE;
|
||||
}
|
||||
}
|
||||
else if (!nelts)
|
||||
/* Avoid handling the undefined/erroneous case of an empty
|
||||
initializer for an arrays with unspecified bound. */
|
||||
return NULL_TREE;
|
||||
/* Avoid converting initializers for zero-length arrays. */
|
||||
if (!maxelts)
|
||||
return ctor;
|
||||
|
||||
tree eltype = TREE_TYPE (type);
|
||||
unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
|
||||
|
||||
auto_vec<char> str;
|
||||
str.reserve (nelts + 1);
|
||||
|
@ -8584,19 +8573,21 @@ braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree))
|
|||
|
||||
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value)
|
||||
{
|
||||
unsigned HOST_WIDE_INT idx = index ? tree_to_uhwi (index) : i;
|
||||
unsigned HOST_WIDE_INT idx = i;
|
||||
if (index)
|
||||
{
|
||||
if (!tree_fits_uhwi_p (index))
|
||||
return ctor;
|
||||
idx = tree_to_uhwi (index);
|
||||
}
|
||||
|
||||
/* auto_vec is limited to UINT_MAX elements. */
|
||||
if (idx > UINT_MAX)
|
||||
return NULL_TREE;
|
||||
return ctor;
|
||||
|
||||
/* Attempt to evaluate constants. */
|
||||
if (eval)
|
||||
value = eval (eltype, value);
|
||||
|
||||
/* Avoid non-constant initializers. */
|
||||
/* Avoid non-constant initializers. */
|
||||
if (!tree_fits_shwi_p (value))
|
||||
return NULL_TREE;
|
||||
return ctor;
|
||||
|
||||
/* Skip over embedded nuls except the last one (initializer
|
||||
elements are in ascending order of indices). */
|
||||
|
@ -8604,11 +8595,14 @@ braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree))
|
|||
if (!val && i + 1 < nelts)
|
||||
continue;
|
||||
|
||||
if (idx < str.length())
|
||||
return ctor;
|
||||
|
||||
/* Bail if the CTOR has a block of more than 256 embedded nuls
|
||||
due to implicitly initialized elements. */
|
||||
unsigned nchars = (idx - str.length ()) + 1;
|
||||
if (nchars > 256)
|
||||
return NULL_TREE;
|
||||
return ctor;
|
||||
|
||||
if (nchars > 1)
|
||||
{
|
||||
|
@ -8616,18 +8610,17 @@ braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree))
|
|||
str.quick_grow_cleared (idx);
|
||||
}
|
||||
|
||||
if (idx > maxelts)
|
||||
return NULL_TREE;
|
||||
if (idx >= maxelts)
|
||||
return ctor;
|
||||
|
||||
str.safe_insert (idx, val);
|
||||
}
|
||||
|
||||
if (!nelts)
|
||||
/* Append a nul for the empty initializer { }. */
|
||||
/* Append a nul string termination. */
|
||||
if (str.length () < maxelts)
|
||||
str.safe_push (0);
|
||||
|
||||
/* Build a STRING_CST with the same type as the array, which
|
||||
may be an array of unknown bound. */
|
||||
/* Build a STRING_CST with the same type as the array. */
|
||||
tree res = build_string (str.length (), str.begin ());
|
||||
TREE_TYPE (res) = type;
|
||||
return res;
|
||||
|
|
|
@ -1331,7 +1331,7 @@ 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, tree (*)(tree, tree) = NULL);
|
||||
extern tree braced_list_to_string (tree, tree);
|
||||
|
||||
#if CHECKING_P
|
||||
namespace selftest {
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2018-09-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* c-decl.c (finish_decl): Call braced_list_to_string here ...
|
||||
* c-parser.c (c_parser_declaration_or_fndef): ... instead of here.
|
||||
|
||||
2018-08-30 Alexander Monakov <amonakov@ispras.ru>
|
||||
|
||||
* gimple-parser.c (c_parser_gimple_binary_expression): Accept infix
|
||||
|
|
|
@ -5031,6 +5031,12 @@ 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));
|
||||
|
||||
if (VAR_P (decl))
|
||||
{
|
||||
if (init && TREE_CODE (init) == CONSTRUCTOR)
|
||||
|
|
|
@ -2127,15 +2127,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|
|||
if (d != error_mark_node)
|
||||
{
|
||||
maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
|
||||
|
||||
/* Try to convert a string CONSTRUCTOR into a STRING_CST. */
|
||||
tree valtype = TREE_TYPE (init.value);
|
||||
if (TREE_CODE (init.value) == CONSTRUCTOR
|
||||
&& TREE_CODE (valtype) == ARRAY_TYPE
|
||||
&& TYPE_STRING_FLAG (TREE_TYPE (valtype)))
|
||||
if (tree str = braced_list_to_string (valtype, init.value))
|
||||
init.value = str;
|
||||
|
||||
finish_decl (d, init_loc, init.value,
|
||||
init.original_type, asm_name);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2018-09-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* decl.c (eval_check_narrowing): Remove.
|
||||
(check_initializer): Move call to braced_list_to_string from here ...
|
||||
* typeck2.c (store_init_value): ... to here.
|
||||
(digest_init_r): Remove handing of signed/unsigned char strings.
|
||||
|
||||
2018-08-31 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
PR c++/87155
|
||||
|
|
|
@ -6283,30 +6283,6 @@ build_aggr_init_full_exprs (tree decl, tree init, int flags)
|
|||
return build_aggr_init (decl, init, flags, tf_warning_or_error);
|
||||
}
|
||||
|
||||
/* Attempt to determine the constant VALUE of integral type and convert
|
||||
it to TYPE, issuing narrowing warnings/errors as necessary. Return
|
||||
the constant result or null on failure. Callback for
|
||||
braced_list_to_string. */
|
||||
|
||||
static tree
|
||||
eval_check_narrowing (tree type, tree value)
|
||||
{
|
||||
if (tree valtype = TREE_TYPE (value))
|
||||
{
|
||||
if (TREE_CODE (valtype) != INTEGER_TYPE)
|
||||
return NULL_TREE;
|
||||
}
|
||||
else
|
||||
return NULL_TREE;
|
||||
|
||||
value = scalar_constant_value (value);
|
||||
if (!value)
|
||||
return NULL_TREE;
|
||||
|
||||
check_narrowing (type, value, tf_warning_or_error);
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Verify INIT (the initializer for DECL), and record the
|
||||
initialization in DECL_INITIAL, if appropriate. CLEANUP is as for
|
||||
grok_reference_init.
|
||||
|
@ -6422,17 +6398,7 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Try to convert a string CONSTRUCTOR into a STRING_CST. */
|
||||
tree valtype = TREE_TYPE (decl);
|
||||
if (TREE_CODE (valtype) == ARRAY_TYPE
|
||||
&& TYPE_STRING_FLAG (TREE_TYPE (valtype))
|
||||
&& BRACE_ENCLOSED_INITIALIZER_P (init))
|
||||
if (tree str = braced_list_to_string (valtype, init,
|
||||
eval_check_narrowing))
|
||||
init = str;
|
||||
|
||||
if (TREE_CODE (init) != STRING_CST)
|
||||
init = reshape_init (type, init, tf_warning_or_error);
|
||||
init = reshape_init (type, init, tf_warning_or_error);
|
||||
flags |= LOOKUP_NO_NARROWING;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -807,6 +807,11 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
|
|||
/* Digest the specified initializer into an expression. */
|
||||
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);
|
||||
|
||||
value = extend_ref_init_temps (decl, value, cleanups);
|
||||
|
||||
/* In C++11 constant expression is a semantic, not syntactic, property.
|
||||
|
@ -1058,9 +1063,7 @@ digest_init_r (tree type, tree init, int nested, int flags,
|
|||
|
||||
if (TYPE_PRECISION (typ1) == BITS_PER_UNIT)
|
||||
{
|
||||
if (char_type != char_type_node
|
||||
&& char_type != signed_char_type_node
|
||||
&& char_type != unsigned_char_type_node)
|
||||
if (char_type != char_type_node)
|
||||
{
|
||||
if (complain & tf_error)
|
||||
error_at (loc, "char-array initialized from wide string");
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2018-09-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* c-c++-common/array-init.c: New test.
|
||||
* g++.dg/init/string2.C: Remove selector.
|
||||
|
||||
2018-09-01 Michael Matz <matz@suse.de>
|
||||
|
||||
PR tree-optimization/87074
|
||||
|
|
4
gcc/testsuite/c-c++-common/array-init.c
Normal file
4
gcc/testsuite/c-c++-common/array-init.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-prune-output "sorry, unimplemented: non-trivial designated initializers not supported" } */
|
||||
|
||||
char x[] = { [-1] = 1, 2, 3 }; /* { dg-error "array index in initializer exceeds array bounds" "" { target c } } */
|
|
@ -54,7 +54,7 @@ template <class T>
|
|||
int tmplen ()
|
||||
{
|
||||
static const T
|
||||
a[] = { 1, 2, 333, 0 }; // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
|
||||
a[] = { 1, 2, 333, 0 }; // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" }
|
||||
return __builtin_strlen (a);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue