/* 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, 2006, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "rtl.h"
#include "tree.h"
#include "langhooks.h"
#include "c-tree.h"
#include "c-lang.h"
-#include "tm_p.h"
#include "flags.h"
#include "output.h"
#include "expr.h"
#include "toplev.h"
#include "intl.h"
-#include "ggc.h"
#include "target.h"
#include "tree-iterator.h"
-#include "gimple.h"
#include "tree-flow.h"
/* Possible cases of implicit bad conversions. Used to select
static char *print_spelling (char *);
static void warning_init (int, const char *);
static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
-static void output_init_element (tree, tree, bool, tree, tree, int, bool);
-static void output_pending_init_elements (int);
-static int set_designator (int);
-static void push_range_stack (tree);
-static void add_pending_init (tree, tree, tree, bool);
-static void set_nonincremental_init (void);
-static void set_nonincremental_init_from_string (tree);
-static tree find_init_member (tree);
+static void output_init_element (tree, tree, bool, tree, tree, int, bool,
+ struct obstack *);
+static void output_pending_init_elements (int, struct obstack *);
+static int set_designator (int, struct obstack *);
+static void push_range_stack (tree, struct obstack *);
+static void add_pending_init (tree, tree, tree, bool, struct obstack *);
+static void set_nonincremental_init (struct obstack *);
+static void set_nonincremental_init_from_string (tree, struct obstack *);
+static tree find_init_member (tree, struct obstack *);
static void readonly_error (tree, enum lvalue_use);
static void readonly_warning (tree, enum lvalue_use);
static int lvalue_or_else (const_tree, enum lvalue_use);
and wait (union wait *) to be compatible. */
if (TREE_CODE (a1) == UNION_TYPE
&& (TYPE_NAME (a1) == 0
- || TYPE_TRANSPARENT_UNION (a1))
+ || TYPE_TRANSPARENT_AGGR (a1))
&& TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST
&& tree_int_cst_equal (TYPE_SIZE (a1),
TYPE_SIZE (a2)))
}
else if (TREE_CODE (a2) == UNION_TYPE
&& (TYPE_NAME (a2) == 0
- || TYPE_TRANSPARENT_UNION (a2))
+ || TYPE_TRANSPARENT_AGGR (a2))
&& TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST
&& tree_int_cst_equal (TYPE_SIZE (a2),
TYPE_SIZE (a1)))
return build_unary_op (loc, ADDR_EXPR, exp, 0);
}
+/* Mark EXP as read, not just set, for set but not used -Wunused
+ warning purposes. */
+
+void
+mark_exp_read (tree exp)
+{
+ switch (TREE_CODE (exp))
+ {
+ case VAR_DECL:
+ case PARM_DECL:
+ DECL_READ_P (exp) = 1;
+ break;
+ case ARRAY_REF:
+ case COMPONENT_REF:
+ case MODIFY_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ CASE_CONVERT:
+ case ADDR_EXPR:
+ mark_exp_read (TREE_OPERAND (exp, 0));
+ break;
+ case COMPOUND_EXPR:
+ mark_exp_read (TREE_OPERAND (exp, 1));
+ break;
+ default:
+ break;
+ }
+}
+
/* Perform the default conversion of arrays and functions to pointers.
Return the result of converting EXP. For any other expression, just
return EXP.
return exp;
}
+struct c_expr
+default_function_array_read_conversion (location_t loc, struct c_expr exp)
+{
+ mark_exp_read (exp.value);
+ return default_function_array_conversion (loc, exp);
+}
/* EXP is an expression of integer type. Apply the integer promotions
to it and return the promoted value. */
enum tree_code code = TREE_CODE (type);
tree promoted_type;
+ mark_exp_read (exp);
+
/* Functions and arrays have been converted during parsing. */
gcc_assert (code != FUNCTION_TYPE);
if (code == ARRAY_TYPE)
return exp;
}
\f
-/* Look up COMPONENT in a structure or union DECL.
+/* Look up COMPONENT in a structure or union TYPE.
If the component name is not found, returns NULL_TREE. Otherwise,
the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
unions, the list steps down the chain to the component. */
static tree
-lookup_field (tree decl, tree component)
+lookup_field (tree type, tree component)
{
- tree type = TREE_TYPE (decl);
tree field;
/* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{
- tree anon = lookup_field (field, component);
+ tree anon = lookup_field (TREE_TYPE (field), component);
if (anon)
return tree_cons (NULL_TREE, field, anon);
&& (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
{
- tree anon = lookup_field (field, component);
+ tree anon = lookup_field (TREE_TYPE (field), component);
if (anon)
return tree_cons (NULL_TREE, field, anon);
return error_mark_node;
}
- field = lookup_field (datum, component);
+ field = lookup_field (type, component);
if (!field)
{
if (type == void_type_node)
{
- error ("too many arguments to function %qE", function);
+ error_at (input_location,
+ "too many arguments to function %qE", function);
+ if (fundecl && !DECL_BUILT_IN (fundecl))
+ inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
return parmnum;
}
if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
{
- error ("too few arguments to function %qE", function);
+ error_at (input_location,
+ "too few arguments to function %qE", function);
+ if (fundecl && !DECL_BUILT_IN (fundecl))
+ inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
return -1;
}
}
}
\f
+/* Convert EXPR to TYPE, warning about conversion problems with
+ constants. SEMANTIC_TYPE is the type this conversion would use
+ without excess precision. If SEMANTIC_TYPE is NULL, this function
+ is equivalent to convert_and_check. This function is a wrapper that
+ handles conversions that may be different than
+ the usual ones because of excess precision. */
+
+static tree
+ep_convert_and_check (tree type, tree expr, tree semantic_type)
+{
+ if (TREE_TYPE (expr) == type)
+ return expr;
+
+ if (!semantic_type)
+ return convert_and_check (type, expr);
+
+ if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+ && TREE_TYPE (expr) != semantic_type)
+ {
+ /* For integers, we need to check the real conversion, not
+ the conversion to the excess precision type. */
+ expr = convert_and_check (semantic_type, expr);
+ }
+ /* Result type is the excess precision type, which should be
+ large enough, so do not check. */
+ return convert (type, expr);
+}
+
/* Build and return a conditional expression IFEXP ? OP1 : OP2. If
IFEXP_BCP then the condition is a call to __builtin_constant_p, and
if folded to an integer constant then the unselected half may
enum tree_code code1;
enum tree_code code2;
tree result_type = NULL;
- tree ep_result_type = NULL;
+ tree semantic_result_type = NULL;
tree orig_op1 = op1, orig_op2 = op2;
bool int_const, op1_int_operands, op2_int_operands, int_operands;
bool ifexp_int_operands;
&& (code2 == INTEGER_TYPE || code2 == REAL_TYPE
|| code2 == COMPLEX_TYPE))
{
- ep_result_type = c_common_type (type1, type2);
+ semantic_result_type = c_common_type (type1, type2);
if (TREE_CODE (op1) == EXCESS_PRECISION_EXPR)
{
op1 = TREE_OPERAND (op1, 0);
TYPE_READONLY (type1) || TYPE_READONLY (type2),
TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2));
- if (result_type != type1)
- op1 = convert_and_check (result_type, op1);
- if (result_type != type2)
- op2 = convert_and_check (result_type, op2);
+ op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
+ op2 = ep_convert_and_check (result_type, op2, semantic_result_type);
if (ifexp_bcp && ifexp == truthvalue_true_node)
{
if (int_operands)
ret = note_integer_operands (ret);
}
- if (ep_result_type)
- ret = build1 (EXCESS_PRECISION_EXPR, ep_result_type, ret);
+ if (semantic_result_type)
+ ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
protected_set_expr_location (ret, colon_loc);
return ret;
if (field)
{
tree t;
+ bool maybe_const = true;
pedwarn (loc, OPT_pedantic, "ISO C forbids casts to union type");
- t = digest_init (loc, type,
- build_constructor_single (type, field, value),
+ t = c_fully_fold (value, false, &maybe_const);
+ t = build_constructor_single (type, field, t);
+ if (!maybe_const)
+ t = c_wrap_maybe_const (t, true);
+ t = digest_init (loc, type, t,
NULL_TREE, false, true, 0);
TREE_CONSTANT (t) = TREE_CONSTANT (value);
return t;
&& comptypes (type, rhstype))
return convert_and_check (type, rhs);
- /* Conversion to a transparent union from its member types.
+ /* Conversion to a transparent union or record from its member types.
This applies only to function arguments. */
- if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
+ if (((codel == UNION_TYPE || codel == RECORD_TYPE)
+ && TYPE_TRANSPARENT_AGGR (type))
&& errtype == ic_argpass)
{
tree memb, marginal_memb = NULL_TREE;
IMPLICIT is 1 (or 2 if the push is because of designator list). */
void
-push_init_level (int implicit)
+push_init_level (int implicit, struct obstack * braced_init_obstack)
{
struct constructor_stack *p;
tree value = NULL_TREE;
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
- process_init_element (pop_init_level (1), true);
+ process_init_element (pop_init_level (1, braced_init_obstack),
+ true, braced_init_obstack);
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& constructor_max_index
&& tree_int_cst_lt (constructor_max_index,
constructor_index))
- process_init_element (pop_init_level (1), true);
+ process_init_element (pop_init_level (1, braced_init_obstack),
+ true, braced_init_obstack);
else
break;
}
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields)
- value = find_init_member (constructor_fields);
+ value = find_init_member (constructor_fields, braced_init_obstack);
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
- value = find_init_member (constructor_index);
+ value = find_init_member (constructor_index, braced_init_obstack);
}
p = XNEW (struct constructor_stack);
if (!VEC_empty (constructor_elt, constructor_elements)
&& (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == ARRAY_TYPE))
- set_nonincremental_init ();
+ set_nonincremental_init (braced_init_obstack);
}
if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
/* We need to split the char/wchar array into individual
characters, so that we don't have to special case it
everywhere. */
- set_nonincremental_init_from_string (value);
+ set_nonincremental_init_from_string (value, braced_init_obstack);
}
}
else
Otherwise, return a CONSTRUCTOR expression as the value. */
struct c_expr
-pop_init_level (int implicit)
+pop_init_level (int implicit, struct obstack * braced_init_obstack)
{
struct constructor_stack *p;
struct c_expr ret;
/* When we come to an explicit close brace,
pop any inner levels that didn't have explicit braces. */
while (constructor_stack->implicit)
- process_init_element (pop_init_level (1), true);
-
+ {
+ process_init_element (pop_init_level (1, braced_init_obstack),
+ true, braced_init_obstack);
+ }
gcc_assert (!constructor_range_stack);
}
/* Now output all pending elements. */
constructor_incremental = 1;
- output_pending_init_elements (1);
+ output_pending_init_elements (1, braced_init_obstack);
p = constructor_stack;
ARRAY argument is nonzero for array ranges. Returns zero for success. */
static int
-set_designator (int array)
+set_designator (int array, struct obstack * braced_init_obstack)
{
tree subtype;
enum tree_code subcode;
/* Designator list starts at the level of closest explicit
braces. */
while (constructor_stack->implicit)
- process_init_element (pop_init_level (1), true);
+ {
+ process_init_element (pop_init_level (1, braced_init_obstack),
+ true, braced_init_obstack);
+ }
constructor_designated = 1;
return 0;
}
}
constructor_designated = 1;
- push_init_level (2);
+ push_init_level (2, braced_init_obstack);
return 0;
}
NULL_TREE if there is no range designator at this level. */
static void
-push_range_stack (tree range_end)
+push_range_stack (tree range_end, struct obstack * braced_init_obstack)
{
struct constructor_range_stack *p;
- p = GGC_NEW (struct constructor_range_stack);
+ p = (struct constructor_range_stack *)
+ obstack_alloc (braced_init_obstack,
+ sizeof (struct constructor_range_stack));
p->prev = constructor_range_stack;
p->next = 0;
p->fields = constructor_fields;
of indices, running from FIRST through LAST. */
void
-set_init_index (tree first, tree last)
+set_init_index (tree first, tree last,
+ struct obstack * braced_init_obstack)
{
- if (set_designator (1))
+ if (set_designator (1, braced_init_obstack))
return;
designator_erroneous = 1;
designator_depth++;
designator_erroneous = 0;
if (constructor_range_stack || last)
- push_range_stack (last);
+ push_range_stack (last, braced_init_obstack);
}
}
/* Within a struct initializer, specify the next field to be initialized. */
void
-set_init_label (tree fieldname)
+set_init_label (tree fieldname, struct obstack * braced_init_obstack)
{
- tree tail;
+ tree field;
- if (set_designator (0))
+ if (set_designator (0, braced_init_obstack))
return;
designator_erroneous = 1;
return;
}
- for (tail = TYPE_FIELDS (constructor_type); tail;
- tail = TREE_CHAIN (tail))
- {
- if (DECL_NAME (tail) == fieldname)
- break;
- }
+ field = lookup_field (constructor_type, fieldname);
- if (tail == 0)
+ if (field == 0)
error ("unknown field %qE specified in initializer", fieldname);
else
- {
- constructor_fields = tail;
- designator_depth++;
- designator_erroneous = 0;
- if (constructor_range_stack)
- push_range_stack (NULL_TREE);
- }
+ do
+ {
+ constructor_fields = TREE_VALUE (field);
+ designator_depth++;
+ designator_erroneous = 0;
+ if (constructor_range_stack)
+ push_range_stack (NULL_TREE, braced_init_obstack);
+ field = TREE_CHAIN (field);
+ if (field)
+ {
+ if (set_designator (0, braced_init_obstack))
+ return;
+ }
+ }
+ while (field != NULL_TREE);
}
\f
/* Add a new initializer to the tree of pending initializers. PURPOSE
existing initializer. */
static void
-add_pending_init (tree purpose, tree value, tree origtype, bool implicit)
+add_pending_init (tree purpose, tree value, tree origtype, bool implicit,
+ struct obstack * braced_init_obstack)
{
struct init_node *p, **q, *r;
}
}
- r = GGC_NEW (struct init_node);
+ r = (struct init_node *) obstack_alloc (braced_init_obstack,
+ sizeof (struct init_node));
r->purpose = purpose;
r->value = value;
r->origtype = origtype;
/* Build AVL tree from a sorted chain. */
static void
-set_nonincremental_init (void)
+set_nonincremental_init (struct obstack * braced_init_obstack)
{
unsigned HOST_WIDE_INT ix;
tree index, value;
return;
FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
- add_pending_init (index, value, NULL_TREE, false);
+ {
+ add_pending_init (index, value, NULL_TREE, false,
+ braced_init_obstack);
+ }
constructor_elements = 0;
if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
/* Build AVL tree from a string constant. */
static void
-set_nonincremental_init_from_string (tree str)
+set_nonincremental_init_from_string (tree str,
+ struct obstack * braced_init_obstack)
{
tree value, purpose, type;
HOST_WIDE_INT val[2];
}
value = build_int_cst_wide (type, val[1], val[0]);
- add_pending_init (purpose, value, NULL_TREE, false);
+ add_pending_init (purpose, value, NULL_TREE, false,
+ braced_init_obstack);
}
constructor_incremental = 0;
not initialized yet. */
static tree
-find_init_member (tree field)
+find_init_member (tree field, struct obstack * braced_init_obstack)
{
struct init_node *p;
{
if (constructor_incremental
&& tree_int_cst_lt (field, constructor_unfilled_index))
- set_nonincremental_init ();
+ set_nonincremental_init (braced_init_obstack);
p = constructor_pending_elts;
while (p)
&& (!constructor_unfilled_fields
|| tree_int_cst_lt (bitpos,
bit_position (constructor_unfilled_fields))))
- set_nonincremental_init ();
+ set_nonincremental_init (braced_init_obstack);
p = constructor_pending_elts;
while (p)
static void
output_init_element (tree value, tree origtype, bool strict_string, tree type,
- tree field, int pending, bool implicit)
+ tree field, int pending, bool implicit,
+ struct obstack * braced_init_obstack)
{
tree semantic_type = NULL_TREE;
constructor_elt *celt;
{
if (constructor_incremental
&& tree_int_cst_lt (field, constructor_unfilled_index))
- set_nonincremental_init ();
+ set_nonincremental_init (braced_init_obstack);
- add_pending_init (field, value, origtype, implicit);
+ add_pending_init (field, value, origtype, implicit,
+ braced_init_obstack);
return;
}
else if (TREE_CODE (constructor_type) == RECORD_TYPE
if (constructor_incremental)
{
if (!constructor_unfilled_fields)
- set_nonincremental_init ();
+ set_nonincremental_init (braced_init_obstack);
else
{
tree bitpos, unfillpos;
unfillpos = bit_position (constructor_unfilled_fields);
if (tree_int_cst_lt (bitpos, unfillpos))
- set_nonincremental_init ();
+ set_nonincremental_init (braced_init_obstack);
}
}
- add_pending_init (field, value, origtype, implicit);
+ add_pending_init (field, value, origtype, implicit,
+ braced_init_obstack);
return;
}
else if (TREE_CODE (constructor_type) == UNION_TYPE
/* Now output any pending elements which have become next. */
if (pending)
- output_pending_init_elements (0);
+ output_pending_init_elements (0, braced_init_obstack);
}
/* Output any pending elements which have become next.
If ALL is 1, we output space as necessary so that
we can output all the pending elements. */
-
static void
-output_pending_init_elements (int all)
+output_pending_init_elements (int all, struct obstack * braced_init_obstack)
{
struct init_node *elt = constructor_pending_elts;
tree next;
constructor_unfilled_index))
output_init_element (elt->value, elt->origtype, true,
TREE_TYPE (constructor_type),
- constructor_unfilled_index, 0, false);
+ constructor_unfilled_index, 0, false,
+ braced_init_obstack);
else if (tree_int_cst_lt (constructor_unfilled_index,
elt->purpose))
{
constructor_unfilled_fields = elt->purpose;
output_init_element (elt->value, elt->origtype, true,
TREE_TYPE (elt->purpose),
- elt->purpose, 0, false);
+ elt->purpose, 0, false,
+ braced_init_obstack);
}
else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
{
existing initializer. */
void
-process_init_element (struct c_expr value, bool implicit)
+process_init_element (struct c_expr value, bool implicit,
+ struct obstack * braced_init_obstack)
{
tree orig_value = value.value;
int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
- process_init_element (pop_init_level (1), true);
+ process_init_element (pop_init_level (1, braced_init_obstack),
+ true, braced_init_obstack);
else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
|| TREE_CODE (constructor_type) == VECTOR_TYPE)
&& (constructor_max_index == 0
|| tree_int_cst_lt (constructor_max_index,
constructor_index)))
- process_init_element (pop_init_level (1), true);
+ process_init_element (pop_init_level (1, braced_init_obstack),
+ true, braced_init_obstack);
else
break;
}
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
|| fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
{
- push_init_level (1);
+ push_init_level (1, braced_init_obstack);
continue;
}
push_member_name (constructor_fields);
output_init_element (value.value, value.original_type,
strict_string, fieldtype,
- constructor_fields, 1, implicit);
+ constructor_fields, 1, implicit,
+ braced_init_obstack);
RESTORE_SPELLING_DEPTH (constructor_depth);
}
else
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
|| fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
{
- push_init_level (1);
+ push_init_level (1, braced_init_obstack);
continue;
}
push_member_name (constructor_fields);
output_init_element (value.value, value.original_type,
strict_string, fieldtype,
- constructor_fields, 1, implicit);
+ constructor_fields, 1, implicit,
+ braced_init_obstack);
RESTORE_SPELLING_DEPTH (constructor_depth);
}
else
&& (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
|| eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
{
- push_init_level (1);
+ push_init_level (1, braced_init_obstack);
continue;
}
push_array_bounds (tree_low_cst (constructor_index, 1));
output_init_element (value.value, value.original_type,
strict_string, elttype,
- constructor_index, 1, implicit);
+ constructor_index, 1, implicit,
+ braced_init_obstack);
RESTORE_SPELLING_DEPTH (constructor_depth);
}
elttype = TYPE_MAIN_VARIANT (constructor_type);
output_init_element (value.value, value.original_type,
strict_string, elttype,
- constructor_index, 1, implicit);
+ constructor_index, 1, implicit,
+ braced_init_obstack);
}
constructor_index
if (value.value)
output_init_element (value.value, value.original_type,
strict_string, constructor_type,
- NULL_TREE, 1, implicit);
+ NULL_TREE, 1, implicit,
+ braced_init_obstack);
constructor_fields = 0;
}
while (constructor_stack != range_stack->stack)
{
gcc_assert (constructor_stack->implicit);
- process_init_element (pop_init_level (1), true);
+ process_init_element (pop_init_level (1,
+ braced_init_obstack),
+ true, braced_init_obstack);
}
for (p = range_stack;
!p->range_end || tree_int_cst_equal (p->index, p->range_end);
p = p->prev)
{
gcc_assert (constructor_stack->implicit);
- process_init_element (pop_init_level (1), true);
+ process_init_element (pop_init_level (1, braced_init_obstack),
+ true, braced_init_obstack);
}
p->index = size_binop_loc (input_location,
p = p->next;
if (!p)
break;
- push_init_level (2);
+ push_init_level (2, braced_init_obstack);
p->stack = constructor_stack;
if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
p->index = p->range_start;
tree
c_process_expr_stmt (location_t loc, tree expr)
{
+ tree exprv;
+
if (!expr)
return NULL_TREE;
&& warn_unused_value)
emit_side_effect_warnings (loc, expr);
+ exprv = expr;
+ while (TREE_CODE (exprv) == COMPOUND_EXPR)
+ exprv = TREE_OPERAND (exprv, 1);
+ if (DECL_P (exprv) || handled_component_p (exprv))
+ mark_exp_read (exprv);
+
/* If the expression is not of a type to which we cannot assign a line
number, wrap the thing in a no-op NOP_EXPR. */
if (DECL_P (expr) || CONSTANT_CLASS_P (expr))
/* When the computation is in excess precision, the type of the
final EXCESS_PRECISION_EXPR. */
- tree real_result_type = NULL;
+ tree semantic_result_type = NULL;
/* Nonzero means operands have already been type-converted
in whatever way is necessary.
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|| code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE))
short_compare = 1;
+ else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
+ {
+ if (TREE_CODE (op0) == ADDR_EXPR
+ && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
+ {
+ if (code == EQ_EXPR)
+ warning_at (location,
+ OPT_Waddress,
+ "the comparison will always evaluate as %<false%> "
+ "for the address of %qD will never be NULL",
+ TREE_OPERAND (op0, 0));
+ else
+ warning_at (location,
+ OPT_Waddress,
+ "the comparison will always evaluate as %<true%> "
+ "for 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_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
+ {
+ if (code == EQ_EXPR)
+ warning_at (location,
+ OPT_Waddress,
+ "the comparison will always evaluate as %<false%> "
+ "for the address of %qD will never be NULL",
+ TREE_OPERAND (op1, 0));
+ else
+ warning_at (location,
+ OPT_Waddress,
+ "the comparison will always evaluate as %<true%> "
+ "for the address of %qD will never be NULL",
+ TREE_OPERAND (op1, 0));
+ }
+ result_type = type1;
+ }
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
tree tt0 = TREE_TYPE (type0);
and both must be object or both incomplete. */
if (comp_target_types (location, type0, type1))
result_type = common_pointer_type (type0, type1);
- else if (null_pointer_constant_p (orig_op0))
- result_type = type1;
- else if (null_pointer_constant_p (orig_op1))
- result_type = type0;
else if (!addr_space_superset (as0, as1, &as_common))
{
error_at (location, "comparison of pointers to "
(build_qualified_type (void_type_node, qual));
}
}
- else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
- {
- if (TREE_CODE (op0) == ADDR_EXPR
- && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
- warning_at (location,
- OPT_Waddress, "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_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
- warning_at (location,
- OPT_Waddress, "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;
else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
pedwarn (location, OPT_pedantic, "ISO C forbids "
"ordered comparisons of pointers to functions");
+ else if (null_pointer_constant_p (orig_op0)
+ || null_pointer_constant_p (orig_op1))
+ warning_at (location, OPT_Wextra,
+ "ordered comparison of pointer with null pointer");
+
}
else if (!addr_space_superset (as0, as1, &as_common))
{
"ordered comparison of pointer with integer zero");
else if (extra_warnings)
warning_at (location, OPT_Wextra,
- "ordered comparison of pointer with integer zero");
+ "ordered comparison of pointer with integer zero");
}
else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
{
result_type = type1;
- pedwarn (location, OPT_pedantic,
- "ordered comparison of pointer with integer zero");
+ if (pedantic)
+ pedwarn (location, OPT_pedantic,
+ "ordered comparison of pointer with integer zero");
+ else if (extra_warnings)
+ warning_at (location, OPT_Wextra,
+ "ordered comparison of pointer with integer zero");
}
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
if (type0 != orig_type0 || type1 != orig_type1)
{
gcc_assert (may_need_excess_precision && common);
- real_result_type = c_common_type (orig_type0, orig_type1);
+ semantic_result_type = c_common_type (orig_type0, orig_type1);
}
if (first_complex)
{
return error_mark_node;
}
- if (!converted)
- {
- if (TREE_TYPE (op0) != result_type)
- op0 = convert_and_check (result_type, op0);
- if (TREE_TYPE (op1) != result_type)
- op1 = convert_and_check (result_type, op1);
-
- /* This can happen if one operand has a vector type, and the other
- has a different type. */
- if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
- return error_mark_node;
- }
-
if (build_type == NULL_TREE)
{
build_type = result_type;
if (type0 != orig_type0 || type1 != orig_type1)
{
gcc_assert (may_need_excess_precision && common);
- real_result_type = c_common_type (orig_type0, orig_type1);
+ semantic_result_type = c_common_type (orig_type0, orig_type1);
}
}
+ if (!converted)
+ {
+ op0 = ep_convert_and_check (result_type, op0, semantic_result_type);
+ op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
+
+ /* This can happen if one operand has a vector type, and the other
+ has a different type. */
+ if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
+ return error_mark_node;
+ }
+
/* Treat expressions in initializers specially as they can't trap. */
if (int_const_or_overflow)
ret = (require_constant_value
else if (TREE_CODE (ret) != INTEGER_CST && int_operands
&& !in_late_binary_op)
ret = note_integer_operands (ret);
- if (real_result_type)
- ret = build1 (EXCESS_PRECISION_EXPR, real_result_type, ret);
+ if (semantic_result_type)
+ ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
protected_set_expr_location (ret, location);
return ret;
}