/* Build expressions with type checking for C compiler.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GCC.
static int require_constant_value;
static int require_constant_elements;
+static bool null_pointer_constant_p (tree);
static tree qualify_type (tree, tree);
static int tagged_types_tu_compatible_p (tree, tree);
static int comp_target_types (tree, tree);
static int lvalue_p (tree);
static void record_maybe_used_decl (tree);
static int comptypes_internal (tree, tree);
+\f
+/* Return true if EXP is a null pointer constant, false otherwise. */
+
+static bool
+null_pointer_constant_p (tree expr)
+{
+ /* This should really operate on c_expr structures, but they aren't
+ yet available everywhere required. */
+ tree type = TREE_TYPE (expr);
+ return (TREE_CODE (expr) == INTEGER_CST
+ && !TREE_CONSTANT_OVERFLOW (expr)
+ && integer_zerop (expr)
+ && (INTEGRAL_TYPE_P (type)
+ || (TREE_CODE (type) == POINTER_TYPE
+ && VOID_TYPE_P (TREE_TYPE (type))
+ && TYPE_QUALS (TREE_TYPE (type)) == TYPE_UNQUALIFIED)));
+}
\f/* This is a cache to hold if two types are compatible or not. */
struct tagged_tu_seen_cache {
if (code2 == REAL_TYPE && code1 != REAL_TYPE)
return t2;
+ /* If both are real and either are decimal floating point types, use
+ the decimal floating point type with the greater precision. */
+
+ if (code1 == REAL_TYPE && code2 == REAL_TYPE)
+ {
+ if (TYPE_MAIN_VARIANT (t1) == dfloat128_type_node
+ || TYPE_MAIN_VARIANT (t2) == dfloat128_type_node)
+ return dfloat128_type_node;
+ else if (TYPE_MAIN_VARIANT (t1) == dfloat64_type_node
+ || TYPE_MAIN_VARIANT (t2) == dfloat64_type_node)
+ return dfloat64_type_node;
+ else if (TYPE_MAIN_VARIANT (t1) == dfloat32_type_node
+ || TYPE_MAIN_VARIANT (t2) == dfloat32_type_node)
+ return dfloat32_type_node;
+ }
+
/* Both real or both integers; use the one with greater precision. */
if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
static struct tagged_tu_seen_cache *
alloc_tagged_tu_seen_cache (tree t1, tree t2)
{
- struct tagged_tu_seen_cache *tu = xmalloc (sizeof (struct tagged_tu_seen_cache));
+ struct tagged_tu_seen_cache *tu = XNEW (struct tagged_tu_seen_cache);
tu->next = tagged_tu_seen_base;
tu->t1 = t1;
tu->t2 = t2;
{
/* Warn if any argument is passed as `float',
since without a prototype it would be `double'. */
- if (formal_prec == TYPE_PRECISION (float_type_node))
+ if (formal_prec == TYPE_PRECISION (float_type_node)
+ && type != dfloat32_type_node)
warning (0, "passing argument %d of %qE as %<float%> "
"rather than %<double%> due to prototype",
argnum, rname);
+
+ /* Warn if mismatch between argument and prototype
+ for decimal float types. Warn of conversions with
+ binary float types and of precision narrowing due to
+ prototype. */
+ else if (type != TREE_TYPE (val)
+ && (type == dfloat32_type_node
+ || type == dfloat64_type_node
+ || type == dfloat128_type_node
+ || TREE_TYPE (val) == dfloat32_type_node
+ || TREE_TYPE (val) == dfloat64_type_node
+ || TREE_TYPE (val) == dfloat128_type_node)
+ && (formal_prec
+ <= TYPE_PRECISION (TREE_TYPE (val))
+ || (type == dfloat128_type_node
+ && (TREE_TYPE (val)
+ != dfloat64_type_node
+ && (TREE_TYPE (val)
+ != dfloat32_type_node)))
+ || (type == dfloat64_type_node
+ && (TREE_TYPE (val)
+ != dfloat32_type_node))))
+ warning (0, "passing argument %d of %qE as %qT "
+ "rather than %qT due to prototype",
+ argnum, rname, type, TREE_TYPE (val));
+
}
/* Detect integer changing in width or signedness.
These warnings are only activated with
}
else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (val))
- < TYPE_PRECISION (double_type_node)))
+ < TYPE_PRECISION (double_type_node))
+ && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val))))
/* Convert `float' to `double'. */
result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
else if ((invalid_func_diag =
{
if (comp_target_types (type1, type2))
result_type = common_pointer_type (type1, type2);
- else if (integer_zerop (orig_op1) && TREE_TYPE (type1) == void_type_node)
+ else if (null_pointer_constant_p (orig_op1))
result_type = qualify_type (type2, type1);
- else if (integer_zerop (orig_op2) && TREE_TYPE (type2) == void_type_node)
+ else if (null_pointer_constant_p (orig_op2))
result_type = qualify_type (type1, type2);
else if (VOID_TYPE_P (TREE_TYPE (type1)))
{
}
else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
{
- if (!integer_zerop (op2))
+ if (!null_pointer_constant_p (orig_op2))
pedwarn ("pointer/integer type mismatch in conditional expression");
else
{
}
else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
- if (!integer_zerop (op1))
+ if (!null_pointer_constant_p (orig_op1))
pedwarn ("pointer/integer type mismatch in conditional expression");
else
{
if (TREE_CODE (type) == INTEGER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE
- && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
- && !TREE_CONSTANT (value))
+ && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
+ /* Unlike conversion of integers to pointers, where the
+ warning is disabled for converting constants because
+ of cases such as SIG_*, warn about converting constant
+ pointers to integers. In some cases it may cause unwanted
+ sign extension, and a warning is appropriate. */
warning (OPT_Wpointer_to_int_cast,
"cast from pointer to integer of different size");
&& TREE_CODE (otype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
- && !(integer_zerop (value) && TREE_TYPE (otype) == void_type_node))
+ && !null_pointer_constant_p (value))
pedwarn ("ISO C forbids conversion of object pointer to function pointer type");
ovalue = value;
}
/* Can convert integer zero to any pointer type. */
- if (integer_zerop (rhs))
+ if (null_pointer_constant_p (rhs))
{
rhs = null_pointer_node;
break;
&& ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
||
(VOID_TYPE_P (ttr)
- && !integer_zerop (rhs)
+ && !null_pointer_constant_p (rhs)
&& TREE_CODE (ttl) == FUNCTION_TYPE)))
WARN_FOR_ASSIGNMENT (G_("ISO C forbids passing argument %d of "
"%qE between function pointer "
/* An explicit constant 0 can convert to a pointer,
or one that results from arithmetic, even including
a cast to integer type. */
- if (!integer_zerop (rhs))
+ if (!null_pointer_constant_p (rhs))
WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes "
"pointer from integer without a cast"),
G_("assignment makes pointer from integer "
start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
{
const char *locus;
- struct initializer_stack *p = xmalloc (sizeof (struct initializer_stack));
+ struct initializer_stack *p = XNEW (struct initializer_stack);
p->decl = constructor_decl;
p->require_constant_value = require_constant_value;
{
/* op0 != orig_op0 detects the case of something
whose value is 0 but which isn't a valid null ptr const. */
- if (pedantic && (!integer_zerop (op0) || op0 != orig_op0)
+ if (pedantic && !null_pointer_constant_p (orig_op0)
&& TREE_CODE (tt1) == FUNCTION_TYPE)
pedwarn ("ISO C forbids comparison of %<void *%>"
" with function pointer");
}
else if (VOID_TYPE_P (tt1))
{
- if (pedantic && (!integer_zerop (op1) || op1 != orig_op1)
+ if (pedantic && !null_pointer_constant_p (orig_op1)
&& TREE_CODE (tt0) == FUNCTION_TYPE)
pedwarn ("ISO C forbids comparison of %<void *%>"
" with function pointer");
if (result_type == NULL_TREE)
result_type = ptr_type_node;
}
- else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
- && integer_zerop (op1))
- result_type = type0;
- else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
- && integer_zerop (op0))
- result_type = type1;
+ else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
+ {
+ if (TREE_CODE (op0) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (op0, 0))
+ && !DECL_WEAK (TREE_OPERAND (op0, 0)))
+ warning (OPT_Walways_true, "the address of %qD will never be NULL",
+ TREE_OPERAND (op0, 0));
+ result_type = type0;
+ }
+ else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
+ {
+ if (TREE_CODE (op1) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (op1, 0))
+ && !DECL_WEAK (TREE_OPERAND (op1, 0)))
+ warning (OPT_Walways_true, "the address of %qD will never be NULL",
+ TREE_OPERAND (op1, 0));
+ result_type = type1;
+ }
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
pedwarn ("comparison of distinct pointer types lacks a cast");
}
}
- else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
- && integer_zerop (op1))
+ else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
{
result_type = type0;
if (pedantic || extra_warnings)
pedwarn ("ordered comparison of pointer with integer zero");
}
- else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
- && integer_zerop (op0))
+ else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
{
result_type = type1;
if (pedantic)