aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Myers <jsm28@cam.ac.uk>2000-10-20 16:59:07 +0100
committerJoseph Myers <jsm28@gcc.gnu.org>2000-10-20 16:59:07 +0100
commit2f74f7e928e72c7382cc5a72a7440657175fc2d2 (patch)
treeff7e2b47546c45c64b35f3cf895f47da04cf520d
parent971774bbc15f4c0e411a921bace1fda1471433fc (diff)
downloadgcc-2f74f7e928e72c7382cc5a72a7440657175fc2d2.zip
gcc-2f74f7e928e72c7382cc5a72a7440657175fc2d2.tar.gz
gcc-2f74f7e928e72c7382cc5a72a7440657175fc2d2.tar.bz2
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
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/c-common.c27
-rw-r--r--gcc/c-typeck.c29
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/format-array-1.c39
5 files changed, 106 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b9f58c1..5a71796 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 086177f..e9ce259 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -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++;
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 0d2209e..e055e98 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 679b4ed..ebaa50f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/format-array-1.c b/gcc/testsuite/gcc.dg/format-array-1.c
new file mode 100644
index 0000000..8d632a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format-array-1.c
@@ -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" } */
+}