c-common.c (check_format_info_recurse): Extract string constant initializers from non-volatile constant arrays and...
* c-common.c (check_format_info_recurse): Extract string constant initializers from non-volatile constant arrays and check them as formats. * c-typeck.c (decl_constant_value): Don't check pedantic or check for DECL_MODE (decl) != BLKmode. (decl_constant_value_for_broken_optimization): New function which includes these checks. (default_conversion, convert_for_assignment, digest_init): Use decl_constant_value_for_broken_optimization instead of decl_constant_value. testsuite: * gcc.dg/format-array-1.c: New test. From-SVN: r36965
This commit is contained in:
parent
971774bbc1
commit
2f74f7e928
|
@ -1,3 +1,16 @@
|
|||
2000-10-20 Joseph S. Myers <jsm28@cam.ac.uk>
|
||||
|
||||
* c-common.c (check_format_info_recurse): Extract string constant
|
||||
initializers from non-volatile constant arrays and check them as
|
||||
formats.
|
||||
* c-typeck.c (decl_constant_value): Don't check pedantic or check
|
||||
for DECL_MODE (decl) != BLKmode.
|
||||
(decl_constant_value_for_broken_optimization): New function which
|
||||
includes these checks.
|
||||
(default_conversion, convert_for_assignment, digest_init): Use
|
||||
decl_constant_value_for_broken_optimization instead of
|
||||
decl_constant_value.
|
||||
|
||||
2000-10-20 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* tree.h (DECL_ALIGN_UNIT): New macro.
|
||||
|
|
|
@ -2344,6 +2344,8 @@ check_format_info_recurse (status, res, info, format_tree, params, arg_num)
|
|||
{
|
||||
int format_length;
|
||||
const char *format_chars;
|
||||
tree array_size = 0;
|
||||
tree array_init;
|
||||
|
||||
if (TREE_CODE (format_tree) == NOP_EXPR)
|
||||
{
|
||||
|
@ -2436,6 +2438,17 @@ check_format_info_recurse (status, res, info, format_tree, params, arg_num)
|
|||
return;
|
||||
}
|
||||
format_tree = TREE_OPERAND (format_tree, 0);
|
||||
if (TREE_CODE (format_tree) == VAR_DECL
|
||||
&& TREE_CODE (TREE_TYPE (format_tree)) == ARRAY_TYPE
|
||||
&& (array_init = decl_constant_value (format_tree)) != format_tree
|
||||
&& TREE_CODE (array_init) == STRING_CST)
|
||||
{
|
||||
/* Extract the string constant initializer. Note that this may include
|
||||
a trailing NUL character that is not in the array (e.g.
|
||||
const char a[3] = "foo";). */
|
||||
array_size = DECL_SIZE_UNIT (format_tree);
|
||||
format_tree = array_init;
|
||||
}
|
||||
if (TREE_CODE (format_tree) != STRING_CST)
|
||||
{
|
||||
res->number_non_literal++;
|
||||
|
@ -2448,6 +2461,20 @@ check_format_info_recurse (status, res, info, format_tree, params, arg_num)
|
|||
}
|
||||
format_chars = TREE_STRING_POINTER (format_tree);
|
||||
format_length = TREE_STRING_LENGTH (format_tree);
|
||||
if (array_size != 0)
|
||||
{
|
||||
/* Variable length arrays can't be initialized. */
|
||||
if (TREE_CODE (array_size) != INTEGER_CST)
|
||||
abort ();
|
||||
if (host_integerp (array_size, 0))
|
||||
{
|
||||
HOST_WIDE_INT array_size_value = TREE_INT_CST_LOW (array_size);
|
||||
if (array_size_value > 0
|
||||
&& array_size_value == (int) array_size_value
|
||||
&& format_length > array_size_value)
|
||||
format_length = array_size_value;
|
||||
}
|
||||
}
|
||||
if (format_length < 1)
|
||||
{
|
||||
res->number_unterminated++;
|
||||
|
|
|
@ -54,6 +54,7 @@ static tree qualify_type PARAMS ((tree, tree));
|
|||
static int comp_target_types PARAMS ((tree, tree));
|
||||
static int function_types_compatible_p PARAMS ((tree, tree));
|
||||
static int type_lists_compatible_p PARAMS ((tree, tree));
|
||||
static tree decl_constant_value_for_broken_optimization PARAMS ((tree));
|
||||
static tree lookup_field PARAMS ((tree, tree, tree *));
|
||||
static tree convert_arguments PARAMS ((tree, tree, tree, tree));
|
||||
static tree pointer_int_sum PARAMS ((enum tree_code, tree, tree));
|
||||
|
@ -844,7 +845,6 @@ decl_constant_value (decl)
|
|||
if (/* Don't change a variable array bound or initial value to a constant
|
||||
in a place where a variable is invalid. */
|
||||
current_function_decl != 0
|
||||
&& ! pedantic
|
||||
&& ! TREE_THIS_VOLATILE (decl)
|
||||
&& TREE_READONLY (decl)
|
||||
&& DECL_INITIAL (decl) != 0
|
||||
|
@ -854,12 +854,29 @@ decl_constant_value (decl)
|
|||
or a variable, then re-evaluating it could give different results. */
|
||||
&& TREE_CONSTANT (DECL_INITIAL (decl))
|
||||
/* Check for cases where this is sub-optimal, even though valid. */
|
||||
&& TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
|
||||
&& DECL_MODE (decl) != BLKmode)
|
||||
&& TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
|
||||
return DECL_INITIAL (decl);
|
||||
return decl;
|
||||
}
|
||||
|
||||
/* Return either DECL or its known constant value (if it has one), but
|
||||
return DECL if pedantic or DECL has mode BLKmode. This is for
|
||||
bug-compatibility with the old behavior of decl_constant_value
|
||||
(before GCC 3.0); every use of this function is a bug and it should
|
||||
be removed before GCC 3.1. It is not appropriate to use pedantic
|
||||
in a way that affects optimization, and BLKmode is probably not the
|
||||
right test for avoiding misoptimizations either. */
|
||||
|
||||
static tree
|
||||
decl_constant_value_for_broken_optimization (decl)
|
||||
tree decl;
|
||||
{
|
||||
if (pedantic || DECL_MODE (decl) == BLKmode)
|
||||
return decl;
|
||||
else
|
||||
return decl_constant_value (decl);
|
||||
}
|
||||
|
||||
/* Perform default promotions for C data used in expressions.
|
||||
Arrays and functions are converted to pointers;
|
||||
enumeral types or short or char, to int.
|
||||
|
@ -881,7 +898,7 @@ default_conversion (exp)
|
|||
address of the array produces consistent results. */
|
||||
else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE)
|
||||
{
|
||||
exp = decl_constant_value (exp);
|
||||
exp = decl_constant_value_for_broken_optimization (exp);
|
||||
type = TREE_TYPE (exp);
|
||||
}
|
||||
|
||||
|
@ -4019,7 +4036,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
|
|||
|| TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE)
|
||||
rhs = default_conversion (rhs);
|
||||
else if (optimize && TREE_CODE (rhs) == VAR_DECL)
|
||||
rhs = decl_constant_value (rhs);
|
||||
rhs = decl_constant_value_for_broken_optimization (rhs);
|
||||
|
||||
rhstype = TREE_TYPE (rhs);
|
||||
coder = TREE_CODE (rhstype);
|
||||
|
@ -4695,7 +4712,7 @@ digest_init (type, init, require_constant, constructor_constant)
|
|||
}
|
||||
|
||||
if (optimize && TREE_CODE (inside_init) == VAR_DECL)
|
||||
inside_init = decl_constant_value (inside_init);
|
||||
inside_init = decl_constant_value_for_broken_optimization (inside_init);
|
||||
|
||||
/* Compound expressions can only occur here if -pedantic or
|
||||
-pedantic-errors is specified. In the later case, we always want
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2000-10-20 Joseph S. Myers <jsm28@cam.ac.uk>
|
||||
|
||||
* gcc.dg/format-array-1.c: New test.
|
||||
|
||||
2000-10-18 Joseph S. Myers <jsm28@cam.ac.uk>
|
||||
|
||||
* gcc.dg/c90-printf-1.c, gcc.dg/c90-scanf-1.c: Add tests for
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/* Test for format checking of constant arrays. */
|
||||
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-std=gnu99 -Wformat=2" } */
|
||||
|
||||
extern int printf (const char *, ...);
|
||||
|
||||
const char a1[] = "foo";
|
||||
const char a2[] = "foo%d";
|
||||
const char b[3] = "foo";
|
||||
static const char c1[] = "foo";
|
||||
static const char c2[] = "foo%d";
|
||||
char d[] = "foo";
|
||||
volatile const char e[] = "foo";
|
||||
|
||||
void
|
||||
foo (int i, long l)
|
||||
{
|
||||
const char p1[] = "bar";
|
||||
const char p2[] = "bar%d";
|
||||
static const char q1[] = "bar";
|
||||
static const char q2[] = "bar%d";
|
||||
printf (a1);
|
||||
printf (a2, i);
|
||||
printf (a2, l); /* { dg-warning "format" "wrong type with array" } */
|
||||
printf (b); /* { dg-warning "unterminated" "unterminated array" } */
|
||||
printf (c1);
|
||||
printf (c2, i);
|
||||
printf (c2, l); /* { dg-warning "format" "wrong type with array" } */
|
||||
printf (p1);
|
||||
printf (p2, i);
|
||||
printf (p2, l); /* { dg-warning "format" "wrong type with array" } */
|
||||
printf (q1);
|
||||
printf (q2, i);
|
||||
printf (q2, l); /* { dg-warning "format" "wrong type with array" } */
|
||||
/* Volatile or non-constant arrays must not be checked. */
|
||||
printf (d); /* { dg-warning "not a string literal" "non-const" } */
|
||||
printf ((const char *)e); /* { dg-warning "not a string literal" "volatile" } */
|
||||
}
|
Loading…
Reference in New Issue