#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
#include "tree.h"
#include "langhooks.h"
#include "c-tree.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 "tree-gimple.h"
#include "tree-flow.h"
enum impl_conv {
ic_argpass,
ic_argpass_nonproto,
ic_assign,
ic_init,
ic_return
};
int in_alignof;
int in_sizeof;
int in_typeof;
struct c_label_context_se *label_context_stack_se;
struct c_label_context_vm *label_context_stack_vm;
static int missing_braces_mentioned;
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 function_types_compatible_p (tree, tree);
static int type_lists_compatible_p (tree, tree);
static tree decl_constant_value_for_broken_optimization (tree);
static tree lookup_field (tree, tree);
static tree convert_arguments (tree, tree, tree, tree);
static tree pointer_diff (tree, tree);
static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree,
int);
static tree valid_compound_expr_initializer (tree, tree);
static void push_string (const char *);
static void push_member_name (tree);
static int spelling_length (void);
static char *print_spelling (char *);
static void warning_init (const char *);
static tree digest_init (tree, tree, bool, int);
static void output_init_element (tree, bool, tree, tree, int);
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);
static void set_nonincremental_init (void);
static void set_nonincremental_init_from_string (tree);
static tree find_init_member (tree);
static void readonly_error (tree, enum lvalue_use);
static int lvalue_or_else (tree, enum lvalue_use);
static int lvalue_p (tree);
static void record_maybe_used_decl (tree);
static int comptypes_internal (tree, tree);
static bool
null_pointer_constant_p (tree expr)
{
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)));
}
struct tagged_tu_seen_cache {
const struct tagged_tu_seen_cache * next;
tree t1;
tree t2;
int val;
};
static const struct tagged_tu_seen_cache * tagged_tu_seen_base;
static void free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *);
tree
require_complete_type (tree value)
{
tree type = TREE_TYPE (value);
if (value == error_mark_node || type == error_mark_node)
return error_mark_node;
if (COMPLETE_TYPE_P (type))
return value;
c_incomplete_type_error (value, type);
return error_mark_node;
}
void
c_incomplete_type_error (tree value, tree type)
{
const char *type_code_string;
if (TREE_CODE (type) == ERROR_MARK)
return;
if (value != 0 && (TREE_CODE (value) == VAR_DECL
|| TREE_CODE (value) == PARM_DECL))
error ("%qD has an incomplete type", value);
else
{
retry:
switch (TREE_CODE (type))
{
case RECORD_TYPE:
type_code_string = "struct";
break;
case UNION_TYPE:
type_code_string = "union";
break;
case ENUMERAL_TYPE:
type_code_string = "enum";
break;
case VOID_TYPE:
error ("invalid use of void expression");
return;
case ARRAY_TYPE:
if (TYPE_DOMAIN (type))
{
if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL)
{
error ("invalid use of flexible array member");
return;
}
type = TREE_TYPE (type);
goto retry;
}
error ("invalid use of array with unspecified bounds");
return;
default:
gcc_unreachable ();
}
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
error ("invalid use of undefined type %<%s %E%>",
type_code_string, TYPE_NAME (type));
else
error ("invalid use of incomplete typedef %qD", TYPE_NAME (type));
}
}
tree
c_type_promotes_to (tree type)
{
if (TYPE_MAIN_VARIANT (type) == float_type_node)
return double_type_node;
if (c_promoting_integer_type_p (type))
{
if (TYPE_UNSIGNED (type)
&& (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
return unsigned_type_node;
return integer_type_node;
}
return type;
}
static tree
qualify_type (tree type, tree like)
{
return c_build_qualified_type (type,
TYPE_QUALS (type) | TYPE_QUALS (like));
}
bool
c_vla_type_p (tree t)
{
if (TREE_CODE (t) == ARRAY_TYPE
&& C_TYPE_VARIABLE_SIZE (t))
return true;
return false;
}
tree
composite_type (tree t1, tree t2)
{
enum tree_code code1;
enum tree_code code2;
tree attributes;
if (t1 == t2) return t1;
if (t1 == error_mark_node)
return t2;
if (t2 == error_mark_node)
return t1;
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
attributes = targetm.merge_type_attributes (t1, t2);
if (code1 == ENUMERAL_TYPE && code2 == INTEGER_TYPE)
return t1;
if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE)
return t2;
gcc_assert (code1 == code2);
switch (code1)
{
case POINTER_TYPE:
{
tree pointed_to_1 = TREE_TYPE (t1);
tree pointed_to_2 = TREE_TYPE (t2);
tree target = composite_type (pointed_to_1, pointed_to_2);
t1 = build_pointer_type (target);
t1 = build_type_attribute_variant (t1, attributes);
return qualify_type (t1, t2);
}
case ARRAY_TYPE:
{
tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
int quals;
tree unqual_elt;
tree d1 = TYPE_DOMAIN (t1);
tree d2 = TYPE_DOMAIN (t2);
bool d1_variable, d2_variable;
bool d1_zero, d2_zero;
gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
d1_zero = d1 == 0 || !TYPE_MAX_VALUE (d1);
d2_zero = d2 == 0 || !TYPE_MAX_VALUE (d2);
d1_variable = (!d1_zero
&& (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST));
d2_variable = (!d2_zero
&& (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)
&& (d2_variable || d2_zero || !d1_variable))
return build_type_attribute_variant (t1, attributes);
if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)
&& (d1_variable || d1_zero || !d2_variable))
return build_type_attribute_variant (t2, attributes);
if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
return build_type_attribute_variant (t1, attributes);
if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
return build_type_attribute_variant (t2, attributes);
quals = TYPE_QUALS (strip_array_types (elt));
unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
t1 = build_array_type (unqual_elt,
TYPE_DOMAIN ((TYPE_DOMAIN (t1)
&& (d2_variable
|| d2_zero
|| !d1_variable))
? t1
: t2));
t1 = c_build_qualified_type (t1, quals);
return build_type_attribute_variant (t1, attributes);
}
case ENUMERAL_TYPE:
case RECORD_TYPE:
case UNION_TYPE:
if (attributes != NULL)
{
if (attribute_list_equal (TYPE_ATTRIBUTES (t1), attributes))
return t1;
if (attribute_list_equal (TYPE_ATTRIBUTES (t2), attributes))
return t2;
}
return build_type_attribute_variant (t1, attributes);
case FUNCTION_TYPE:
{
tree valtype = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
tree p1 = TYPE_ARG_TYPES (t1);
tree p2 = TYPE_ARG_TYPES (t2);
int len;
tree newargs, n;
int i;
if (valtype == TREE_TYPE (t1) && !TYPE_ARG_TYPES (t2))
return build_type_attribute_variant (t1, attributes);
if (valtype == TREE_TYPE (t2) && !TYPE_ARG_TYPES (t1))
return build_type_attribute_variant (t2, attributes);
if (TYPE_ARG_TYPES (t1) == 0)
{
t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2));
t1 = build_type_attribute_variant (t1, attributes);
return qualify_type (t1, t2);
}
if (TYPE_ARG_TYPES (t2) == 0)
{
t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1));
t1 = build_type_attribute_variant (t1, attributes);
return qualify_type (t1, t2);
}
c_override_global_bindings_to_false = true;
len = list_length (p1);
newargs = 0;
for (i = 0; i < len; i++)
newargs = tree_cons (NULL_TREE, NULL_TREE, newargs);
n = newargs;
for (; p1;
p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n))
{
if (TREE_VALUE (p1) == 0)
{
TREE_VALUE (n) = TREE_VALUE (p2);
goto parm_done;
}
if (TREE_VALUE (p2) == 0)
{
TREE_VALUE (n) = TREE_VALUE (p1);
goto parm_done;
}
if (TREE_CODE (TREE_VALUE (p1)) == UNION_TYPE
&& TREE_VALUE (p1) != TREE_VALUE (p2))
{
tree memb;
tree mv2 = TREE_VALUE (p2);
if (mv2 && mv2 != error_mark_node
&& TREE_CODE (mv2) != ARRAY_TYPE)
mv2 = TYPE_MAIN_VARIANT (mv2);
for (memb = TYPE_FIELDS (TREE_VALUE (p1));
memb; memb = TREE_CHAIN (memb))
{
tree mv3 = TREE_TYPE (memb);
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE)
mv3 = TYPE_MAIN_VARIANT (mv3);
if (comptypes (mv3, mv2))
{
TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
TREE_VALUE (p2));
if (pedantic)
pedwarn ("function types not truly compatible in ISO C");
goto parm_done;
}
}
}
if (TREE_CODE (TREE_VALUE (p2)) == UNION_TYPE
&& TREE_VALUE (p2) != TREE_VALUE (p1))
{
tree memb;
tree mv1 = TREE_VALUE (p1);
if (mv1 && mv1 != error_mark_node
&& TREE_CODE (mv1) != ARRAY_TYPE)
mv1 = TYPE_MAIN_VARIANT (mv1);
for (memb = TYPE_FIELDS (TREE_VALUE (p2));
memb; memb = TREE_CHAIN (memb))
{
tree mv3 = TREE_TYPE (memb);
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE)
mv3 = TYPE_MAIN_VARIANT (mv3);
if (comptypes (mv3, mv1))
{
TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
TREE_VALUE (p1));
if (pedantic)
pedwarn ("function types not truly compatible in ISO C");
goto parm_done;
}
}
}
TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2));
parm_done: ;
}
c_override_global_bindings_to_false = false;
t1 = build_function_type (valtype, newargs);
t1 = qualify_type (t1, t2);
}
default:
return build_type_attribute_variant (t1, attributes);
}
}
static tree
common_pointer_type (tree t1, tree t2)
{
tree attributes;
tree pointed_to_1, mv1;
tree pointed_to_2, mv2;
tree target;
if (t1 == t2) return t1;
if (t1 == error_mark_node)
return t2;
if (t2 == error_mark_node)
return t1;
gcc_assert (TREE_CODE (t1) == POINTER_TYPE
&& TREE_CODE (t2) == POINTER_TYPE);
attributes = targetm.merge_type_attributes (t1, t2);
mv1 = pointed_to_1 = TREE_TYPE (t1);
mv2 = pointed_to_2 = TREE_TYPE (t2);
if (TREE_CODE (mv1) != ARRAY_TYPE)
mv1 = TYPE_MAIN_VARIANT (pointed_to_1);
if (TREE_CODE (mv2) != ARRAY_TYPE)
mv2 = TYPE_MAIN_VARIANT (pointed_to_2);
target = composite_type (mv1, mv2);
t1 = build_pointer_type (c_build_qualified_type
(target,
TYPE_QUALS (pointed_to_1) |
TYPE_QUALS (pointed_to_2)));
return build_type_attribute_variant (t1, attributes);
}
static tree
c_common_type (tree t1, tree t2)
{
enum tree_code code1;
enum tree_code code2;
if (t1 == error_mark_node)
return t2;
if (t2 == error_mark_node)
return t1;
if (TYPE_QUALS (t1) != TYPE_UNQUALIFIED)
t1 = TYPE_MAIN_VARIANT (t1);
if (TYPE_QUALS (t2) != TYPE_UNQUALIFIED)
t2 = TYPE_MAIN_VARIANT (t2);
if (TYPE_ATTRIBUTES (t1) != NULL_TREE)
t1 = build_type_attribute_variant (t1, NULL_TREE);
if (TYPE_ATTRIBUTES (t2) != NULL_TREE)
t2 = build_type_attribute_variant (t2, NULL_TREE);
if (t1 == t2) return t1;
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE
|| code1 == REAL_TYPE || code1 == INTEGER_TYPE);
gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
|| code2 == REAL_TYPE || code2 == INTEGER_TYPE);
if ((DECIMAL_FLOAT_TYPE_P (t1) || DECIMAL_FLOAT_TYPE_P (t2))
&& !(DECIMAL_FLOAT_TYPE_P (t1) && DECIMAL_FLOAT_TYPE_P (t2)))
{
if (code1 == VECTOR_TYPE || code2 == VECTOR_TYPE)
{
error ("can%'t mix operands of decimal float and vector types");
return error_mark_node;
}
if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
{
error ("can%'t mix operands of decimal float and complex types");
return error_mark_node;
}
if (code1 == REAL_TYPE && code2 == REAL_TYPE)
{
error ("can%'t mix operands of decimal float and other float types");
return error_mark_node;
}
}
if (code1 == VECTOR_TYPE)
return t1;
if (code2 == VECTOR_TYPE)
return t2;
if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
{
tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
tree subtype = c_common_type (subtype1, subtype2);
if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
return t1;
else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
return t2;
else
return build_complex_type (subtype);
}
if (code1 == REAL_TYPE && code2 != REAL_TYPE)
return t1;
if (code2 == REAL_TYPE && code1 != REAL_TYPE)
return t2;
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;
}
if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
return t1;
else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
return t2;
if (TYPE_MAIN_VARIANT (t1) == long_long_unsigned_type_node
|| TYPE_MAIN_VARIANT (t2) == long_long_unsigned_type_node)
return long_long_unsigned_type_node;
if (TYPE_MAIN_VARIANT (t1) == long_long_integer_type_node
|| TYPE_MAIN_VARIANT (t2) == long_long_integer_type_node)
{
if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
return long_long_unsigned_type_node;
else
return long_long_integer_type_node;
}
if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
|| TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
return long_unsigned_type_node;
if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node
|| TYPE_MAIN_VARIANT (t2) == long_integer_type_node)
{
if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
return long_unsigned_type_node;
else
return long_integer_type_node;
}
if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
|| TYPE_MAIN_VARIANT (t2) == long_double_type_node)
return long_double_type_node;
if (TYPE_UNSIGNED (t1))
return t1;
else
return t2;
}
tree
common_type (tree t1, tree t2)
{
if (TREE_CODE (t1) == ENUMERAL_TYPE)
t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
if (TREE_CODE (t2) == ENUMERAL_TYPE)
t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
if (TREE_CODE (t1) == BOOLEAN_TYPE
&& TREE_CODE (t2) == BOOLEAN_TYPE)
return boolean_type_node;
if (TREE_CODE (t1) == BOOLEAN_TYPE)
return t2;
if (TREE_CODE (t2) == BOOLEAN_TYPE)
return t1;
return c_common_type (t1, t2);
}
int
comptypes (tree type1, tree type2)
{
const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
int val;
val = comptypes_internal (type1, type2);
free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
return val;
}
static int
comptypes_internal (tree type1, tree type2)
{
tree t1 = type1;
tree t2 = type2;
int attrval, val;
if (t1 == t2 || !t1 || !t2
|| TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)
return 1;
if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1)
&& TYPE_ORIG_SIZE_TYPE (t1))
t1 = TYPE_ORIG_SIZE_TYPE (t1);
if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2)
&& TYPE_ORIG_SIZE_TYPE (t2))
t2 = TYPE_ORIG_SIZE_TYPE (t2);
if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE)
t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE)
t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
if (t1 == t2)
return 1;
if (TREE_CODE (t1) != TREE_CODE (t2))
return 0;
if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
return 0;
if (TREE_CODE (t1) != ARRAY_TYPE
&& TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return 1;
if (!(attrval = targetm.comp_type_attributes (t1, t2)))
return 0;
val = 0;
switch (TREE_CODE (t1))
{
case POINTER_TYPE:
if (TYPE_MODE (t1) != TYPE_MODE (t2)
|| TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
break;
val = (TREE_TYPE (t1) == TREE_TYPE (t2)
? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2)));
break;
case FUNCTION_TYPE:
val = function_types_compatible_p (t1, t2);
break;
case ARRAY_TYPE:
{
tree d1 = TYPE_DOMAIN (t1);
tree d2 = TYPE_DOMAIN (t2);
bool d1_variable, d2_variable;
bool d1_zero, d2_zero;
val = 1;
if (TREE_TYPE (t1) != TREE_TYPE (t2)
&& 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2))))
return 0;
if (d1 == 0 || d2 == 0 || d1 == d2)
break;
d1_zero = !TYPE_MAX_VALUE (d1);
d2_zero = !TYPE_MAX_VALUE (d2);
d1_variable = (!d1_zero
&& (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST));
d2_variable = (!d2_zero
&& (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
if (d1_variable || d2_variable)
break;
if (d1_zero && d2_zero)
break;
if (d1_zero || d2_zero
|| !tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2))
|| !tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)))
val = 0;
break;
}
case ENUMERAL_TYPE:
case RECORD_TYPE:
case UNION_TYPE:
if (val != 1 && !same_translation_unit_p (t1, t2))
{
tree a1 = TYPE_ATTRIBUTES (t1);
tree a2 = TYPE_ATTRIBUTES (t2);
if (! attribute_list_contained (a1, a2)
&& ! attribute_list_contained (a2, a1))
break;
if (attrval != 2)
return tagged_types_tu_compatible_p (t1, t2);
val = tagged_types_tu_compatible_p (t1, t2);
}
break;
case VECTOR_TYPE:
val = TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
&& comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2));
break;
default:
break;
}
return attrval == 2 && val == 1 ? 2 : val;
}
static int
comp_target_types (tree ttl, tree ttr)
{
int val;
tree mvl, mvr;
mvl = TREE_TYPE (ttl);
mvr = TREE_TYPE (ttr);
if (TREE_CODE (mvl) != ARRAY_TYPE)
mvl = TYPE_MAIN_VARIANT (mvl);
if (TREE_CODE (mvr) != ARRAY_TYPE)
mvr = TYPE_MAIN_VARIANT (mvr);
val = comptypes (mvl, mvr);
if (val == 2 && pedantic)
pedwarn ("types are not quite compatible");
return val;
}
int
same_translation_unit_p (tree t1, tree t2)
{
while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
switch (TREE_CODE_CLASS (TREE_CODE (t1)))
{
case tcc_declaration:
t1 = DECL_CONTEXT (t1); break;
case tcc_type:
t1 = TYPE_CONTEXT (t1); break;
case tcc_exceptional:
t1 = BLOCK_SUPERCONTEXT (t1); break;
default: gcc_unreachable ();
}
while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL)
switch (TREE_CODE_CLASS (TREE_CODE (t2)))
{
case tcc_declaration:
t2 = DECL_CONTEXT (t2); break;
case tcc_type:
t2 = TYPE_CONTEXT (t2); break;
case tcc_exceptional:
t2 = BLOCK_SUPERCONTEXT (t2); break;
default: gcc_unreachable ();
}
return t1 == t2;
}
static struct tagged_tu_seen_cache *
alloc_tagged_tu_seen_cache (tree t1, tree t2)
{
struct tagged_tu_seen_cache *tu = XNEW (struct tagged_tu_seen_cache);
tu->next = tagged_tu_seen_base;
tu->t1 = t1;
tu->t2 = t2;
tagged_tu_seen_base = tu;
tu->val = 1;
return tu;
}
static void
free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
{
const struct tagged_tu_seen_cache *tu = tagged_tu_seen_base;
while (tu != tu_til)
{
struct tagged_tu_seen_cache *tu1 = (struct tagged_tu_seen_cache*)tu;
tu = tu1->next;
free (tu1);
}
tagged_tu_seen_base = tu_til;
}
static int
tagged_types_tu_compatible_p (tree t1, tree t2)
{
tree s1, s2;
bool needs_warning = false;
while (TYPE_NAME (t1)
&& TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (TYPE_NAME (t1)))
t1 = DECL_ORIGINAL_TYPE (TYPE_NAME (t1));
while (TYPE_NAME (t2)
&& TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (TYPE_NAME (t2)))
t2 = DECL_ORIGINAL_TYPE (TYPE_NAME (t2));
if (flag_isoc99 && TYPE_NAME (t1) != TYPE_NAME (t2))
return 0;
if (TYPE_SIZE (t1) == NULL
|| TYPE_SIZE (t2) == NULL)
return 1;
{
const struct tagged_tu_seen_cache * tts_i;
for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next)
if (tts_i->t1 == t1 && tts_i->t2 == t2)
return tts_i->val;
}
switch (TREE_CODE (t1))
{
case ENUMERAL_TYPE:
{
struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
tree tv1 = TYPE_VALUES (t1);
tree tv2 = TYPE_VALUES (t2);
if (tv1 == tv2)
{
return 1;
}
for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2))
{
if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2))
break;
if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1)
{
tu->val = 0;
return 0;
}
}
if (tv1 == NULL_TREE && tv2 == NULL_TREE)
{
return 1;
}
if (tv1 == NULL_TREE || tv2 == NULL_TREE)
{
tu->val = 0;
return 0;
}
if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2)))
{
tu->val = 0;
return 0;
}
for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1))
{
s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2));
if (s2 == NULL
|| simple_cst_equal (TREE_VALUE (s1), TREE_VALUE (s2)) != 1)
{
tu->val = 0;
return 0;
}
}
return 1;
}
case UNION_TYPE:
{
struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2)))
{
tu->val = 0;
return 0;
}
for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2;
s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
{
int result;
if (DECL_NAME (s1) == NULL
|| DECL_NAME (s1) != DECL_NAME (s2))
break;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
if (result == 0)
{
tu->val = 0;
return 0;
}
if (result == 2)
needs_warning = true;
if (TREE_CODE (s1) == FIELD_DECL
&& simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
DECL_FIELD_BIT_OFFSET (s2)) != 1)
{
tu->val = 0;
return 0;
}
}
if (!s1 && !s2)
{
tu->val = needs_warning ? 2 : 1;
return tu->val;
}
for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1))
{
bool ok = false;
if (DECL_NAME (s1) != NULL)
for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
if (DECL_NAME (s1) == DECL_NAME (s2))
{
int result;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
if (result == 0)
{
tu->val = 0;
return 0;
}
if (result == 2)
needs_warning = true;
if (TREE_CODE (s1) == FIELD_DECL
&& simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
DECL_FIELD_BIT_OFFSET (s2)) != 1)
break;
ok = true;
break;
}
if (!ok)
{
tu->val = 0;
return 0;
}
}
tu->val = needs_warning ? 2 : 10;
return tu->val;
}
case RECORD_TYPE:
{
struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
s1 && s2;
s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
{
int result;
if (TREE_CODE (s1) != TREE_CODE (s2)
|| DECL_NAME (s1) != DECL_NAME (s2))
break;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
if (result == 0)
break;
if (result == 2)
needs_warning = true;
if (TREE_CODE (s1) == FIELD_DECL
&& simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
DECL_FIELD_BIT_OFFSET (s2)) != 1)
break;
}
if (s1 && s2)
tu->val = 0;
else
tu->val = needs_warning ? 2 : 1;
return tu->val;
}
default:
gcc_unreachable ();
}
}
static int
function_types_compatible_p (tree f1, tree f2)
{
tree args1, args2;
int val = 1;
int val1;
tree ret1, ret2;
ret1 = TREE_TYPE (f1);
ret2 = TREE_TYPE (f2);
if (TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2))
pedwarn ("function return types not compatible due to %<volatile%>");
if (TYPE_VOLATILE (ret1))
ret1 = build_qualified_type (TYPE_MAIN_VARIANT (ret1),
TYPE_QUALS (ret1) & ~TYPE_QUAL_VOLATILE);
if (TYPE_VOLATILE (ret2))
ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
val = comptypes_internal (ret1, ret2);
if (val == 0)
return 0;
args1 = TYPE_ARG_TYPES (f1);
args2 = TYPE_ARG_TYPES (f2);
if (args1 == 0)
{
if (!self_promoting_args_p (args2))
return 0;
if (TYPE_ACTUAL_ARG_TYPES (f1)
&& 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1)))
val = 2;
return val;
}
if (args2 == 0)
{
if (!self_promoting_args_p (args1))
return 0;
if (TYPE_ACTUAL_ARG_TYPES (f2)
&& 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2)))
val = 2;
return val;
}
val1 = type_lists_compatible_p (args1, args2);
return val1 != 1 ? val1 : val;
}
static int
type_lists_compatible_p (tree args1, tree args2)
{
int val = 1;
int newval = 0;
while (1)
{
tree a1, mv1, a2, mv2;
if (args1 == 0 && args2 == 0)
return val;
if (args1 == 0 || args2 == 0)
return 0;
mv1 = a1 = TREE_VALUE (args1);
mv2 = a2 = TREE_VALUE (args2);
if (mv1 && mv1 != error_mark_node && TREE_CODE (mv1) != ARRAY_TYPE)
mv1 = TYPE_MAIN_VARIANT (mv1);
if (mv2 && mv2 != error_mark_node && TREE_CODE (mv2) != ARRAY_TYPE)
mv2 = TYPE_MAIN_VARIANT (mv2);
if (a1 == 0)
{
if (c_type_promotes_to (a2) != a2)
return 0;
}
else if (a2 == 0)
{
if (c_type_promotes_to (a1) != a1)
return 0;
}
else if (TREE_CODE (a1) == ERROR_MARK
|| TREE_CODE (a2) == ERROR_MARK)
;
else if (!(newval = comptypes_internal (mv1, mv2)))
{
if (TREE_CODE (a1) == UNION_TYPE
&& (TYPE_NAME (a1) == 0
|| TYPE_TRANSPARENT_UNION (a1))
&& TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST
&& tree_int_cst_equal (TYPE_SIZE (a1),
TYPE_SIZE (a2)))
{
tree memb;
for (memb = TYPE_FIELDS (a1);
memb; memb = TREE_CHAIN (memb))
{
tree mv3 = TREE_TYPE (memb);
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE)
mv3 = TYPE_MAIN_VARIANT (mv3);
if (comptypes_internal (mv3, mv2))
break;
}
if (memb == 0)
return 0;
}
else if (TREE_CODE (a2) == UNION_TYPE
&& (TYPE_NAME (a2) == 0
|| TYPE_TRANSPARENT_UNION (a2))
&& TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST
&& tree_int_cst_equal (TYPE_SIZE (a2),
TYPE_SIZE (a1)))
{
tree memb;
for (memb = TYPE_FIELDS (a2);
memb; memb = TREE_CHAIN (memb))
{
tree mv3 = TREE_TYPE (memb);
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE)
mv3 = TYPE_MAIN_VARIANT (mv3);
if (comptypes_internal (mv3, mv1))
break;
}
if (memb == 0)
return 0;
}
else
return 0;
}
if (newval > val)
val = newval;
args1 = TREE_CHAIN (args1);
args2 = TREE_CHAIN (args2);
}
}
static tree
c_size_in_bytes (tree type)
{
enum tree_code code = TREE_CODE (type);
if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
return size_one_node;
if (!COMPLETE_OR_VOID_TYPE_P (type))
{
error ("arithmetic on pointer to an incomplete type");
return size_one_node;
}
return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
size_int (TYPE_PRECISION (char_type_node)
/ BITS_PER_UNIT));
}
tree
decl_constant_value (tree decl)
{
if (
current_function_decl != 0
&& TREE_CODE (decl) != PARM_DECL
&& !TREE_THIS_VOLATILE (decl)
&& TREE_READONLY (decl)
&& DECL_INITIAL (decl) != 0
&& TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
&& TREE_CONSTANT (DECL_INITIAL (decl))
&& TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
return DECL_INITIAL (decl);
return decl;
}
static tree
decl_constant_value_for_broken_optimization (tree decl)
{
tree ret;
if (pedantic || DECL_MODE (decl) == BLKmode)
return decl;
ret = decl_constant_value (decl);
if (ret != decl && TREE_STATIC (decl))
ret = unshare_expr (ret);
return ret;
}
static tree
array_to_pointer_conversion (tree exp)
{
tree orig_exp = exp;
tree type = TREE_TYPE (exp);
tree adr;
tree restype = TREE_TYPE (type);
tree ptrtype;
gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
STRIP_TYPE_NOPS (exp);
if (TREE_NO_WARNING (orig_exp))
TREE_NO_WARNING (exp) = 1;
ptrtype = build_pointer_type (restype);
if (TREE_CODE (exp) == INDIRECT_REF)
return convert (ptrtype, TREE_OPERAND (exp, 0));
if (TREE_CODE (exp) == VAR_DECL)
{
adr = build1 (ADDR_EXPR, ptrtype, exp);
if (!c_mark_addressable (exp))
return error_mark_node;
TREE_SIDE_EFFECTS (adr) = 0;
return adr;
}
adr = build_unary_op (ADDR_EXPR, exp, 1);
return convert (ptrtype, adr);
}
static tree
function_to_pointer_conversion (tree exp)
{
tree orig_exp = exp;
gcc_assert (TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE);
STRIP_TYPE_NOPS (exp);
if (TREE_NO_WARNING (orig_exp))
TREE_NO_WARNING (exp) = 1;
return build_unary_op (ADDR_EXPR, exp, 0);
}
struct c_expr
default_function_array_conversion (struct c_expr exp)
{
tree orig_exp = exp.value;
tree type = TREE_TYPE (exp.value);
enum tree_code code = TREE_CODE (type);
switch (code)
{
case ARRAY_TYPE:
{
bool not_lvalue = false;
bool lvalue_array_p;
while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR
|| TREE_CODE (exp.value) == NOP_EXPR
|| TREE_CODE (exp.value) == CONVERT_EXPR)
&& TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type)
{
if (TREE_CODE (exp.value) == NON_LVALUE_EXPR)
not_lvalue = true;
exp.value = TREE_OPERAND (exp.value, 0);
}
if (TREE_NO_WARNING (orig_exp))
TREE_NO_WARNING (exp.value) = 1;
lvalue_array_p = !not_lvalue && lvalue_p (exp.value);
if (!flag_isoc99 && !lvalue_array_p)
{
return exp;
}
exp.value = array_to_pointer_conversion (exp.value);
}
break;
case FUNCTION_TYPE:
exp.value = function_to_pointer_conversion (exp.value);
break;
default:
STRIP_TYPE_NOPS (exp.value);
if (TREE_NO_WARNING (orig_exp))
TREE_NO_WARNING (exp.value) = 1;
break;
}
return exp;
}
tree
perform_integral_promotions (tree exp)
{
tree type = TREE_TYPE (exp);
enum tree_code code = TREE_CODE (type);
gcc_assert (INTEGRAL_TYPE_P (type));
if (code == ENUMERAL_TYPE)
{
type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
TYPE_PRECISION (integer_type_node)),
((TYPE_PRECISION (type)
>= TYPE_PRECISION (integer_type_node))
&& TYPE_UNSIGNED (type)));
return convert (type, exp);
}
if (TREE_CODE (exp) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))
&& 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
TYPE_PRECISION (integer_type_node)))
return convert (integer_type_node, exp);
if (c_promoting_integer_type_p (type))
{
if (TYPE_UNSIGNED (type)
&& TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
return convert (unsigned_type_node, exp);
return convert (integer_type_node, exp);
}
return exp;
}
tree
default_conversion (tree exp)
{
tree orig_exp;
tree type = TREE_TYPE (exp);
enum tree_code code = TREE_CODE (type);
gcc_assert (code != FUNCTION_TYPE);
if (code == ARRAY_TYPE)
return exp;
if (TREE_CODE (exp) == CONST_DECL)
exp = DECL_INITIAL (exp);
else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE)
{
exp = decl_constant_value_for_broken_optimization (exp);
type = TREE_TYPE (exp);
}
orig_exp = exp;
STRIP_TYPE_NOPS (exp);
if (TREE_NO_WARNING (orig_exp))
TREE_NO_WARNING (exp) = 1;
if (INTEGRAL_TYPE_P (type))
return perform_integral_promotions (exp);
if (code == VOID_TYPE)
{
error ("void value not ignored as it ought to be");
return error_mark_node;
}
return exp;
}
static tree
lookup_field (tree decl, tree component)
{
tree type = TREE_TYPE (decl);
tree field;
if (TYPE_LANG_SPECIFIC (type) && TYPE_LANG_SPECIFIC (type)->s)
{
int bot, top, half;
tree *field_array = &TYPE_LANG_SPECIFIC (type)->s->elts[0];
field = TYPE_FIELDS (type);
bot = 0;
top = TYPE_LANG_SPECIFIC (type)->s->len;
while (top - bot > 1)
{
half = (top - bot + 1) >> 1;
field = field_array[bot+half];
if (DECL_NAME (field) == NULL_TREE)
{
while (DECL_NAME (field_array[bot]) == NULL_TREE)
{
field = field_array[bot++];
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{
tree anon = lookup_field (field, component);
if (anon)
return tree_cons (NULL_TREE, field, anon);
}
}
if (bot > top)
return NULL_TREE;
continue;
}
if (DECL_NAME (field) == component)
break;
if (DECL_NAME (field) < component)
bot += half;
else
top = bot + half;
}
if (DECL_NAME (field_array[bot]) == component)
field = field_array[bot];
else if (DECL_NAME (field) != component)
return NULL_TREE;
}
else
{
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
if (DECL_NAME (field) == NULL_TREE
&& (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
{
tree anon = lookup_field (field, component);
if (anon)
return tree_cons (NULL_TREE, field, anon);
}
if (DECL_NAME (field) == component)
break;
}
if (field == NULL_TREE)
return NULL_TREE;
}
return tree_cons (NULL_TREE, field, NULL_TREE);
}
tree
build_component_ref (tree datum, tree component)
{
tree type = TREE_TYPE (datum);
enum tree_code code = TREE_CODE (type);
tree field = NULL;
tree ref;
if (!objc_is_public (datum, component))
return error_mark_node;
if (code == RECORD_TYPE || code == UNION_TYPE)
{
if (!COMPLETE_TYPE_P (type))
{
c_incomplete_type_error (NULL_TREE, type);
return error_mark_node;
}
field = lookup_field (datum, component);
if (!field)
{
error ("%qT has no member named %qE", type, component);
return error_mark_node;
}
do
{
tree subdatum = TREE_VALUE (field);
int quals;
tree subtype;
if (TREE_TYPE (subdatum) == error_mark_node)
return error_mark_node;
quals = TYPE_QUALS (strip_array_types (TREE_TYPE (subdatum)));
quals |= TYPE_QUALS (TREE_TYPE (datum));
subtype = c_build_qualified_type (TREE_TYPE (subdatum), quals);
ref = build3 (COMPONENT_REF, subtype, datum, subdatum,
NULL_TREE);
if (TREE_READONLY (datum) || TREE_READONLY (subdatum))
TREE_READONLY (ref) = 1;
if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum))
TREE_THIS_VOLATILE (ref) = 1;
if (TREE_DEPRECATED (subdatum))
warn_deprecated_use (subdatum);
datum = ref;
field = TREE_CHAIN (field);
}
while (field);
return ref;
}
else if (code != ERROR_MARK)
error ("request for member %qE in something not a structure or union",
component);
return error_mark_node;
}
tree
build_indirect_ref (tree ptr, const char *errorstring)
{
tree pointer = default_conversion (ptr);
tree type = TREE_TYPE (pointer);
if (TREE_CODE (type) == POINTER_TYPE)
{
if (TREE_CODE (pointer) == ADDR_EXPR
&& (TREE_TYPE (TREE_OPERAND (pointer, 0))
== TREE_TYPE (type)))
return TREE_OPERAND (pointer, 0);
else
{
tree t = TREE_TYPE (type);
tree ref;
ref = build1 (INDIRECT_REF, t, pointer);
if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
{
error ("dereferencing pointer to incomplete type");
return error_mark_node;
}
if (VOID_TYPE_P (t) && skip_evaluation == 0)
warning (0, "dereferencing %<void *%> pointer");
TREE_READONLY (ref) = TYPE_READONLY (t);
TREE_SIDE_EFFECTS (ref)
= TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
return ref;
}
}
else if (TREE_CODE (pointer) != ERROR_MARK)
error ("invalid type argument of %qs", errorstring);
return error_mark_node;
}
tree
build_array_ref (tree array, tree index)
{
bool swapped = false;
if (TREE_TYPE (array) == error_mark_node
|| TREE_TYPE (index) == error_mark_node)
return error_mark_node;
if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE)
{
tree temp;
if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
{
error ("subscripted value is neither array nor pointer");
return error_mark_node;
}
temp = array;
array = index;
index = temp;
swapped = true;
}
if (!INTEGRAL_TYPE_P (TREE_TYPE (index)))
{
error ("array subscript is not an integer");
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (TREE_TYPE (array))) == FUNCTION_TYPE)
{
error ("subscripted value is pointer to function");
return error_mark_node;
}
if (!swapped)
warn_array_subscript_with_type_char (index);
index = default_conversion (index);
gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
{
tree rval, type;
if (TREE_CODE (index) != INTEGER_CST
|| (COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (array)))
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
{
if (!c_mark_addressable (array))
return error_mark_node;
}
if (TREE_CODE (index) == INTEGER_CST
&& TYPE_DOMAIN (TREE_TYPE (array))
&& !int_fits_type_p (index, TYPE_DOMAIN (TREE_TYPE (array))))
{
if (!c_mark_addressable (array))
return error_mark_node;
}
if (pedantic)
{
tree foo = array;
while (TREE_CODE (foo) == COMPONENT_REF)
foo = TREE_OPERAND (foo, 0);
if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
pedwarn ("ISO C forbids subscripting %<register%> array");
else if (!flag_isoc99 && !lvalue_p (foo))
pedwarn ("ISO C90 forbids subscripting non-lvalue array");
}
type = TREE_TYPE (TREE_TYPE (array));
if (TREE_CODE (type) != ARRAY_TYPE)
type = TYPE_MAIN_VARIANT (type);
rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
TREE_READONLY (rval)
|= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))
| TREE_READONLY (array));
TREE_SIDE_EFFECTS (rval)
|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
| TREE_SIDE_EFFECTS (array));
TREE_THIS_VOLATILE (rval)
|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
| TREE_THIS_VOLATILE (array));
return require_complete_type (fold (rval));
}
else
{
tree ar = default_conversion (array);
if (ar == error_mark_node)
return ar;
gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 0),
"array indexing");
}
}
tree
build_external_ref (tree id, int fun, location_t loc)
{
tree ref;
tree decl = lookup_name (id);
decl = objc_lookup_ivar (decl, id);
if (decl && decl != error_mark_node)
ref = decl;
else if (fun)
ref = implicitly_declare (id);
else if (decl == error_mark_node)
return error_mark_node;
else
{
undeclared_variable (id, loc);
return error_mark_node;
}
if (TREE_TYPE (ref) == error_mark_node)
return error_mark_node;
if (TREE_DEPRECATED (ref))
warn_deprecated_use (ref);
if (!skip_evaluation)
assemble_external (ref);
TREE_USED (ref) = 1;
if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
{
if (!in_sizeof && !in_typeof)
C_DECL_USED (ref) = 1;
else if (DECL_INITIAL (ref) == 0
&& DECL_EXTERNAL (ref)
&& !TREE_PUBLIC (ref))
record_maybe_used_decl (ref);
}
if (TREE_CODE (ref) == CONST_DECL)
{
used_types_insert (TREE_TYPE (ref));
ref = DECL_INITIAL (ref);
TREE_CONSTANT (ref) = 1;
TREE_INVARIANT (ref) = 1;
}
else if (current_function_decl != 0
&& !DECL_FILE_SCOPE_P (current_function_decl)
&& (TREE_CODE (ref) == VAR_DECL
|| TREE_CODE (ref) == PARM_DECL
|| TREE_CODE (ref) == FUNCTION_DECL))
{
tree context = decl_function_context (ref);
if (context != 0 && context != current_function_decl)
DECL_NONLOCAL (ref) = 1;
}
return ref;
}
struct maybe_used_decl
{
tree decl;
int level;
struct maybe_used_decl *next;
};
static struct maybe_used_decl *maybe_used_decls;
static void
record_maybe_used_decl (tree decl)
{
struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl);
t->decl = decl;
t->level = in_sizeof + in_typeof;
t->next = maybe_used_decls;
maybe_used_decls = t;
}
void
pop_maybe_used (bool used)
{
struct maybe_used_decl *p = maybe_used_decls;
int cur_level = in_sizeof + in_typeof;
while (p && p->level > cur_level)
{
if (used)
{
if (cur_level == 0)
C_DECL_USED (p->decl) = 1;
else
p->level = cur_level;
}
p = p->next;
}
if (!used || cur_level == 0)
maybe_used_decls = p;
}
struct c_expr
c_expr_sizeof_expr (struct c_expr expr)
{
struct c_expr ret;
if (expr.value == error_mark_node)
{
ret.value = error_mark_node;
ret.original_code = ERROR_MARK;
pop_maybe_used (false);
}
else
{
ret.value = c_sizeof (TREE_TYPE (expr.value));
ret.original_code = ERROR_MARK;
if (c_vla_type_p (TREE_TYPE (expr.value)))
{
ret.value = build2 (COMPOUND_EXPR, TREE_TYPE (ret.value), expr.value, ret.value);
}
pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
}
return ret;
}
struct c_expr
c_expr_sizeof_type (struct c_type_name *t)
{
tree type;
struct c_expr ret;
type = groktypename (t);
ret.value = c_sizeof (type);
ret.original_code = ERROR_MARK;
pop_maybe_used (type != error_mark_node
? C_TYPE_VARIABLE_SIZE (type) : false);
return ret;
}
tree
build_function_call (tree function, tree params)
{
tree fntype, fundecl = 0;
tree coerced_params;
tree name = NULL_TREE, result;
tree tem;
STRIP_TYPE_NOPS (function);
if (TREE_CODE (function) == FUNCTION_DECL)
{
tem = resolve_overloaded_builtin (function, params);
if (tem)
return tem;
name = DECL_NAME (function);
fundecl = function;
}
if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
function = function_to_pointer_conversion (function);
function = objc_rewrite_function_call (function, params);
fntype = TREE_TYPE (function);
if (TREE_CODE (fntype) == ERROR_MARK)
return error_mark_node;
if (!(TREE_CODE (fntype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE))
{
error ("called object %qE is not a function", function);
return error_mark_node;
}
if (fundecl && TREE_THIS_VOLATILE (fundecl))
current_function_returns_abnormally = 1;
fntype = TREE_TYPE (fntype);
if ((TREE_CODE (function) == NOP_EXPR
|| TREE_CODE (function) == CONVERT_EXPR)
&& TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
&& TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
&& !comptypes (fntype, TREE_TYPE (tem)))
{
tree return_type = TREE_TYPE (fntype);
tree trap = build_function_call (built_in_decls[BUILT_IN_TRAP],
NULL_TREE);
warning (0, "function called through a non-compatible type");
inform ("if this code is reached, the program will abort");
if (VOID_TYPE_P (return_type))
return trap;
else
{
tree rhs;
if (AGGREGATE_TYPE_P (return_type))
rhs = build_compound_literal (return_type,
build_constructor (return_type, 0));
else
rhs = fold_convert (return_type, integer_zero_node);
return build2 (COMPOUND_EXPR, return_type, trap, rhs);
}
}
coerced_params
= convert_arguments (TYPE_ARG_TYPES (fntype), params, function, fundecl);
if (coerced_params == error_mark_node)
return error_mark_node;
check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
TYPE_ARG_TYPES (fntype));
if (require_constant_value)
{
result = fold_build3_initializer (CALL_EXPR, TREE_TYPE (fntype),
function, coerced_params, NULL_TREE);
if (TREE_CONSTANT (result)
&& (name == NULL_TREE
|| strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0))
pedwarn_init ("initializer element is not constant");
}
else
result = fold_build3 (CALL_EXPR, TREE_TYPE (fntype),
function, coerced_params, NULL_TREE);
if (VOID_TYPE_P (TREE_TYPE (result)))
return result;
return require_complete_type (result);
}
static tree
convert_arguments (tree typelist, tree values, tree function, tree fundecl)
{
tree typetail, valtail;
tree result = NULL;
int parmnum;
tree selector;
if (TREE_CODE (function) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
function = TREE_OPERAND (function, 0);
selector = objc_message_selector ();
for (valtail = values, typetail = typelist, parmnum = 0;
valtail;
valtail = TREE_CHAIN (valtail), parmnum++)
{
tree type = typetail ? TREE_VALUE (typetail) : 0;
tree val = TREE_VALUE (valtail);
tree rname = function;
int argnum = parmnum + 1;
const char *invalid_func_diag;
if (type == void_type_node)
{
error ("too many arguments to function %qE", function);
break;
}
if (selector && argnum > 2)
{
rname = selector;
argnum -= 2;
}
STRIP_TYPE_NOPS (val);
val = require_complete_type (val);
if (type != 0)
{
tree parmval;
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
{
error ("type of formal parameter %d is incomplete", parmnum + 1);
parmval = val;
}
else
{
if (warn_conversion || warn_traditional)
{
unsigned int formal_prec = TYPE_PRECISION (type);
if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
warning (0, "passing argument %d of %qE as integer "
"rather than floating due to prototype",
argnum, rname);
if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
warning (0, "passing argument %d of %qE as integer "
"rather than complex due to prototype",
argnum, rname);
else if (TREE_CODE (type) == COMPLEX_TYPE
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
warning (0, "passing argument %d of %qE as complex "
"rather than floating due to prototype",
argnum, rname);
else if (TREE_CODE (type) == REAL_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (val)))
warning (0, "passing argument %d of %qE as floating "
"rather than integer due to prototype",
argnum, rname);
else if (TREE_CODE (type) == COMPLEX_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (val)))
warning (0, "passing argument %d of %qE as complex "
"rather than integer due to prototype",
argnum, rname);
else if (TREE_CODE (type) == REAL_TYPE
&& TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
warning (0, "passing argument %d of %qE as floating "
"rather than complex due to prototype",
argnum, rname);
else if (TREE_CODE (type) == REAL_TYPE
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
{
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);
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));
}
else if (warn_conversion && INTEGRAL_TYPE_P (type)
&& INTEGRAL_TYPE_P (TREE_TYPE (val)))
{
tree would_have_been = default_conversion (val);
tree type1 = TREE_TYPE (would_have_been);
if (TREE_CODE (type) == ENUMERAL_TYPE
&& (TYPE_MAIN_VARIANT (type)
== TYPE_MAIN_VARIANT (TREE_TYPE (val))))
;
else if (formal_prec != TYPE_PRECISION (type1))
warning (OPT_Wconversion, "passing argument %d of %qE "
"with different width due to prototype",
argnum, rname);
else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
;
else if (TREE_CODE (type) == ENUMERAL_TYPE)
;
else if (TREE_CODE (val) == INTEGER_CST
&& int_fits_type_p (val, type))
;
else if (TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type)
&& TYPE_UNSIGNED (TREE_TYPE (val)))
;
else if (TYPE_UNSIGNED (type))
warning (OPT_Wconversion, "passing argument %d of %qE "
"as unsigned due to prototype",
argnum, rname);
else
warning (OPT_Wconversion, "passing argument %d of %qE "
"as signed due to prototype", argnum, rname);
}
}
parmval = convert_for_assignment (type, val, ic_argpass,
fundecl, function,
parmnum + 1);
if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
&& INTEGRAL_TYPE_P (type)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
parmval = default_conversion (parmval);
}
result = tree_cons (NULL_TREE, parmval, result);
}
else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (val))
< TYPE_PRECISION (double_type_node))
&& !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val))))
result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
else if ((invalid_func_diag =
targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
{
error (invalid_func_diag);
return error_mark_node;
}
else
result = tree_cons (NULL_TREE, default_conversion (val), result);
if (typetail)
typetail = TREE_CHAIN (typetail);
}
if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
{
error ("too few arguments to function %qE", function);
return error_mark_node;
}
return nreverse (result);
}
struct c_expr
parser_build_unary_op (enum tree_code code, struct c_expr arg)
{
struct c_expr result;
result.original_code = ERROR_MARK;
result.value = build_unary_op (code, arg.value, 0);
overflow_warning (result.value);
return result;
}
struct c_expr
parser_build_binary_op (enum tree_code code, struct c_expr arg1,
struct c_expr arg2)
{
struct c_expr result;
enum tree_code code1 = arg1.original_code;
enum tree_code code2 = arg2.original_code;
result.value = build_binary_op (code, arg1.value, arg2.value, 1);
result.original_code = code;
if (TREE_CODE (result.value) == ERROR_MARK)
return result;
if (warn_parentheses)
{
if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
{
if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
warning (OPT_Wparentheses,
"suggest parentheses around + or - inside shift");
}
if (code == TRUTH_ORIF_EXPR)
{
if (code1 == TRUTH_ANDIF_EXPR
|| code2 == TRUTH_ANDIF_EXPR)
warning (OPT_Wparentheses,
"suggest parentheses around && within ||");
}
if (code == BIT_IOR_EXPR)
{
if (code1 == BIT_AND_EXPR || code1 == BIT_XOR_EXPR
|| code1 == PLUS_EXPR || code1 == MINUS_EXPR
|| code2 == BIT_AND_EXPR || code2 == BIT_XOR_EXPR
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
warning (OPT_Wparentheses,
"suggest parentheses around arithmetic in operand of |");
if (TREE_CODE_CLASS (code1) == tcc_comparison
|| TREE_CODE_CLASS (code2) == tcc_comparison)
warning (OPT_Wparentheses,
"suggest parentheses around comparison in operand of |");
}
if (code == BIT_XOR_EXPR)
{
if (code1 == BIT_AND_EXPR
|| code1 == PLUS_EXPR || code1 == MINUS_EXPR
|| code2 == BIT_AND_EXPR
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
warning (OPT_Wparentheses,
"suggest parentheses around arithmetic in operand of ^");
if (TREE_CODE_CLASS (code1) == tcc_comparison
|| TREE_CODE_CLASS (code2) == tcc_comparison)
warning (OPT_Wparentheses,
"suggest parentheses around comparison in operand of ^");
}
if (code == BIT_AND_EXPR)
{
if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
warning (OPT_Wparentheses,
"suggest parentheses around + or - in operand of &");
if (TREE_CODE_CLASS (code1) == tcc_comparison
|| TREE_CODE_CLASS (code2) == tcc_comparison)
warning (OPT_Wparentheses,
"suggest parentheses around comparison in operand of &");
}
if (TREE_CODE_CLASS (code) == tcc_comparison
&& (TREE_CODE_CLASS (code1) == tcc_comparison
|| TREE_CODE_CLASS (code2) == tcc_comparison))
warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not "
"have their mathematical meaning");
}
if (code == EQ_EXPR || code == NE_EXPR)
{
if ((code1 == STRING_CST && !integer_zerop (arg2.value))
|| (code2 == STRING_CST && !integer_zerop (arg1.value)))
warning (OPT_Waddress,
"comparison with string literal results in unspecified behaviour");
}
else if (TREE_CODE_CLASS (code) == tcc_comparison
&& (code1 == STRING_CST || code2 == STRING_CST))
warning (OPT_Waddress,
"comparison with string literal results in unspecified behaviour");
overflow_warning (result.value);
return result;
}
static tree
pointer_diff (tree op0, tree op1)
{
tree restype = ptrdiff_type_node;
tree target_type = TREE_TYPE (TREE_TYPE (op0));
tree con0, con1, lit0, lit1;
tree orig_op1 = op1;
if (pedantic || warn_pointer_arith)
{
if (TREE_CODE (target_type) == VOID_TYPE)
pedwarn ("pointer of type %<void *%> used in subtraction");
if (TREE_CODE (target_type) == FUNCTION_TYPE)
pedwarn ("pointer to a function used in subtraction");
}
if ((TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == CONVERT_EXPR)
&& (TYPE_PRECISION (TREE_TYPE (op0))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
con0 = TREE_OPERAND (op0, 0);
else
con0 = op0;
if ((TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == CONVERT_EXPR)
&& (TYPE_PRECISION (TREE_TYPE (op1))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))))
con1 = TREE_OPERAND (op1, 0);
else
con1 = op1;
if (TREE_CODE (con0) == PLUS_EXPR)
{
lit0 = TREE_OPERAND (con0, 1);
con0 = TREE_OPERAND (con0, 0);
}
else
lit0 = integer_zero_node;
if (TREE_CODE (con1) == PLUS_EXPR)
{
lit1 = TREE_OPERAND (con1, 1);
con1 = TREE_OPERAND (con1, 0);
}
else
lit1 = integer_zero_node;
if (operand_equal_p (con0, con1, 0))
{
op0 = lit0;
op1 = lit1;
}
op0 = build_binary_op (MINUS_EXPR, convert (restype, op0),
convert (restype, op1), 0);
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
error ("arithmetic on pointer to an incomplete type");
op1 = c_size_in_bytes (target_type);
return fold_build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
}
tree
build_unary_op (enum tree_code code, tree xarg, int flag)
{
tree arg = xarg;
tree argtype = 0;
enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
tree val;
int noconvert = flag;
const char *invalid_op_diag;
if (typecode == ERROR_MARK)
return error_mark_node;
if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
typecode = INTEGER_TYPE;
if ((invalid_op_diag
= targetm.invalid_unary_op (code, TREE_TYPE (xarg))))
{
error (invalid_op_diag);
return error_mark_node;
}
switch (code)
{
case CONVERT_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == COMPLEX_TYPE
|| typecode == VECTOR_TYPE))
{
error ("wrong type argument to unary plus");
return error_mark_node;
}
else if (!noconvert)
arg = default_conversion (arg);
arg = non_lvalue (arg);
break;
case NEGATE_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == COMPLEX_TYPE
|| typecode == VECTOR_TYPE))
{
error ("wrong type argument to unary minus");
return error_mark_node;
}
else if (!noconvert)
arg = default_conversion (arg);
break;
case BIT_NOT_EXPR:
if (typecode == INTEGER_TYPE || typecode == VECTOR_TYPE)
{
if (!noconvert)
arg = default_conversion (arg);
}
else if (typecode == COMPLEX_TYPE)
{
code = CONJ_EXPR;
if (pedantic)
pedwarn ("ISO C does not support %<~%> for complex conjugation");
if (!noconvert)
arg = default_conversion (arg);
}
else
{
error ("wrong type argument to bit-complement");
return error_mark_node;
}
break;
case ABS_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
{
error ("wrong type argument to abs");
return error_mark_node;
}
else if (!noconvert)
arg = default_conversion (arg);
break;
case CONJ_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == COMPLEX_TYPE))
{
error ("wrong type argument to conjugation");
return error_mark_node;
}
else if (!noconvert)
arg = default_conversion (arg);
break;
case TRUTH_NOT_EXPR:
if (typecode != INTEGER_TYPE
&& typecode != REAL_TYPE && typecode != POINTER_TYPE
&& typecode != COMPLEX_TYPE)
{
error ("wrong type argument to unary exclamation mark");
return error_mark_node;
}
arg = c_objc_common_truthvalue_conversion (arg);
return invert_truthvalue (arg);
case REALPART_EXPR:
if (TREE_CODE (arg) == COMPLEX_CST)
return TREE_REALPART (arg);
else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
return fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
else
return arg;
case IMAGPART_EXPR:
if (TREE_CODE (arg) == COMPLEX_CST)
return TREE_IMAGPART (arg);
else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
return fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
else
return convert (TREE_TYPE (arg), integer_zero_node);
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case POSTDECREMENT_EXPR:
if (typecode == COMPLEX_TYPE)
{
tree real, imag;
if (pedantic)
pedwarn ("ISO C does not support %<++%> and %<--%>"
" on complex types");
arg = stabilize_reference (arg);
real = build_unary_op (REALPART_EXPR, arg, 1);
imag = build_unary_op (IMAGPART_EXPR, arg, 1);
return build2 (COMPLEX_EXPR, TREE_TYPE (arg),
build_unary_op (code, real, 1), imag);
}
if (typecode != POINTER_TYPE
&& typecode != INTEGER_TYPE && typecode != REAL_TYPE)
{
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
error ("wrong type argument to increment");
else
error ("wrong type argument to decrement");
return error_mark_node;
}
{
tree inc;
tree result_type = TREE_TYPE (arg);
arg = get_unwidened (arg, 0);
argtype = TREE_TYPE (arg);
if (typecode == POINTER_TYPE)
{
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type)))
{
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
error ("increment of pointer to unknown structure");
else
error ("decrement of pointer to unknown structure");
}
else if ((pedantic || warn_pointer_arith)
&& (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
{
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
pedwarn ("wrong type argument to increment");
else
pedwarn ("wrong type argument to decrement");
}
inc = c_size_in_bytes (TREE_TYPE (result_type));
}
else
inc = integer_one_node;
inc = convert (argtype, inc);
if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? lv_increment
: lv_decrement)))
return error_mark_node;
if (TREE_READONLY (arg))
{
readonly_error (arg,
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? lv_increment : lv_decrement));
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
val = boolean_increment (code, arg);
else
val = build2 (code, TREE_TYPE (arg), arg, inc);
TREE_SIDE_EFFECTS (val) = 1;
val = convert (result_type, val);
if (TREE_CODE (val) != code)
TREE_NO_WARNING (val) = 1;
return val;
}
case ADDR_EXPR:
if (TREE_CODE (arg) == INDIRECT_REF)
{
if (lvalue_p (TREE_OPERAND (arg, 0)))
return non_lvalue (TREE_OPERAND (arg, 0));
return TREE_OPERAND (arg, 0);
}
if (TREE_CODE (arg) == ARRAY_REF)
{
tree op0 = TREE_OPERAND (arg, 0);
if (!c_mark_addressable (op0))
return error_mark_node;
return build_binary_op (PLUS_EXPR,
(TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
? array_to_pointer_conversion (op0)
: op0),
TREE_OPERAND (arg, 1), 1);
}
else if (typecode != FUNCTION_TYPE && !flag
&& !lvalue_or_else (arg, lv_addressof))
return error_mark_node;
argtype = TREE_TYPE (arg);
if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
&& (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
argtype = c_build_type_variant (argtype,
TREE_READONLY (arg),
TREE_THIS_VOLATILE (arg));
if (!c_mark_addressable (arg))
return error_mark_node;
gcc_assert (TREE_CODE (arg) != COMPONENT_REF
|| !DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)));
argtype = build_pointer_type (argtype);
val = get_base_address (arg);
if (val && TREE_CODE (val) == INDIRECT_REF
&& TREE_CONSTANT (TREE_OPERAND (val, 0)))
{
tree op0 = fold_convert (argtype, fold_offsetof (arg, val)), op1;
op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
return fold_build2 (PLUS_EXPR, argtype, op0, op1);
}
val = build1 (ADDR_EXPR, argtype, arg);
return val;
default:
gcc_unreachable ();
}
if (argtype == 0)
argtype = TREE_TYPE (arg);
return require_constant_value ? fold_build1_initializer (code, argtype, arg)
: fold_build1 (code, argtype, arg);
}
static int
lvalue_p (tree ref)
{
enum tree_code code = TREE_CODE (ref);
switch (code)
{
case REALPART_EXPR:
case IMAGPART_EXPR:
case COMPONENT_REF:
return lvalue_p (TREE_OPERAND (ref, 0));
case COMPOUND_LITERAL_EXPR:
case STRING_CST:
return 1;
case INDIRECT_REF:
case ARRAY_REF:
case VAR_DECL:
case PARM_DECL:
case RESULT_DECL:
case ERROR_MARK:
return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE);
case BIND_EXPR:
return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE;
default:
return 0;
}
}
static void
readonly_error (tree arg, enum lvalue_use use)
{
gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
|| use == lv_asm);
#define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A) \
: (use == lv_increment ? (I) \
: (use == lv_decrement ? (D) : (AS))))
if (TREE_CODE (arg) == COMPONENT_REF)
{
if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
readonly_error (TREE_OPERAND (arg, 0), use);
else
error (READONLY_MSG (G_("assignment of read-only member %qD"),
G_("increment of read-only member %qD"),
G_("decrement of read-only member %qD"),
G_("read-only member %qD used as %<asm%> output")),
TREE_OPERAND (arg, 1));
}
else if (TREE_CODE (arg) == VAR_DECL)
error (READONLY_MSG (G_("assignment of read-only variable %qD"),
G_("increment of read-only variable %qD"),
G_("decrement of read-only variable %qD"),
G_("read-only variable %qD used as %<asm%> output")),
arg);
else
error (READONLY_MSG (G_("assignment of read-only location"),
G_("increment of read-only location"),
G_("decrement of read-only location"),
G_("read-only location used as %<asm%> output")));
}
static int
lvalue_or_else (tree ref, enum lvalue_use use)
{
int win = lvalue_p (ref);
if (!win)
lvalue_error (use);
return win;
}
bool
c_mark_addressable (tree exp)
{
tree x = exp;
while (1)
switch (TREE_CODE (x))
{
case COMPONENT_REF:
if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
{
error
("cannot take address of bit-field %qD", TREE_OPERAND (x, 1));
return false;
}
case ADDR_EXPR:
case ARRAY_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
x = TREE_OPERAND (x, 0);
break;
case COMPOUND_LITERAL_EXPR:
case CONSTRUCTOR:
TREE_ADDRESSABLE (x) = 1;
return true;
case VAR_DECL:
case CONST_DECL:
case PARM_DECL:
case RESULT_DECL:
if (C_DECL_REGISTER (x)
&& DECL_NONLOCAL (x))
{
if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
{
error
("global register variable %qD used in nested function", x);
return false;
}
pedwarn ("register variable %qD used in nested function", x);
}
else if (C_DECL_REGISTER (x))
{
if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
error ("address of global register variable %qD requested", x);
else
error ("address of register variable %qD requested", x);
return false;
}
case FUNCTION_DECL:
TREE_ADDRESSABLE (x) = 1;
default:
return true;
}
}
tree
build_conditional_expr (tree ifexp, tree op1, tree op2)
{
tree type1;
tree type2;
enum tree_code code1;
enum tree_code code2;
tree result_type = NULL;
tree orig_op1 = op1, orig_op2 = op2;
if (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE)
op1 = default_conversion (op1);
if (TREE_CODE (TREE_TYPE (op2)) != VOID_TYPE)
op2 = default_conversion (op2);
if (TREE_CODE (ifexp) == ERROR_MARK
|| TREE_CODE (TREE_TYPE (op1)) == ERROR_MARK
|| TREE_CODE (TREE_TYPE (op2)) == ERROR_MARK)
return error_mark_node;
type1 = TREE_TYPE (op1);
code1 = TREE_CODE (type1);
type2 = TREE_TYPE (op2);
code2 = TREE_CODE (type2);
if (code1 == ARRAY_TYPE || code2 == ARRAY_TYPE)
{
error ("non-lvalue array in conditional expression");
return error_mark_node;
}
if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
{
if (type1 == type2)
result_type = type1;
else
result_type = TYPE_MAIN_VARIANT (type1);
}
else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE
|| code1 == COMPLEX_TYPE)
&& (code2 == INTEGER_TYPE || code2 == REAL_TYPE
|| code2 == COMPLEX_TYPE))
{
result_type = c_common_type (type1, type2);
if (warn_sign_compare && !skip_evaluation)
{
int unsigned_op1 = TYPE_UNSIGNED (TREE_TYPE (orig_op1));
int unsigned_op2 = TYPE_UNSIGNED (TREE_TYPE (orig_op2));
if (unsigned_op1 ^ unsigned_op2)
{
bool ovf;
if (!TYPE_UNSIGNED (result_type))
;
else if ((unsigned_op2
&& tree_expr_nonnegative_warnv_p (op1, &ovf))
|| (unsigned_op1
&& tree_expr_nonnegative_warnv_p (op2, &ovf)))
;
else
warning (0, "signed and unsigned type in conditional expression");
}
}
}
else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
{
if (pedantic && (code1 != VOID_TYPE || code2 != VOID_TYPE))
pedwarn ("ISO C forbids conditional expr with only one void side");
result_type = void_type_node;
}
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
{
if (comp_target_types (type1, type2))
result_type = common_pointer_type (type1, type2);
else if (null_pointer_constant_p (orig_op1))
result_type = qualify_type (type2, type1);
else if (null_pointer_constant_p (orig_op2))
result_type = qualify_type (type1, type2);
else if (VOID_TYPE_P (TREE_TYPE (type1)))
{
if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
pedwarn ("ISO C forbids conditional expr between "
"%<void *%> and function pointer");
result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
TREE_TYPE (type2)));
}
else if (VOID_TYPE_P (TREE_TYPE (type2)))
{
if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
pedwarn ("ISO C forbids conditional expr between "
"%<void *%> and function pointer");
result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
TREE_TYPE (type1)));
}
else
{
pedwarn ("pointer type mismatch in conditional expression");
result_type = build_pointer_type (void_type_node);
}
}
else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
{
if (!null_pointer_constant_p (orig_op2))
pedwarn ("pointer/integer type mismatch in conditional expression");
else
{
op2 = null_pointer_node;
}
result_type = type1;
}
else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
if (!null_pointer_constant_p (orig_op1))
pedwarn ("pointer/integer type mismatch in conditional expression");
else
{
op1 = null_pointer_node;
}
result_type = type2;
}
if (!result_type)
{
if (flag_cond_mismatch)
result_type = void_type_node;
else
{
error ("type mismatch in conditional expression");
return error_mark_node;
}
}
result_type
= build_type_variant (result_type,
TREE_READONLY (op1) || TREE_READONLY (op2),
TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
if (result_type != TREE_TYPE (op1))
op1 = convert_and_check (result_type, op1);
if (result_type != TREE_TYPE (op2))
op2 = convert_and_check (result_type, op2);
return fold_build3 (COND_EXPR, result_type, ifexp, op1, op2);
}
tree
build_compound_expr (tree expr1, tree expr2)
{
if (!TREE_SIDE_EFFECTS (expr1))
{
if (warn_unused_value)
{
if (VOID_TYPE_P (TREE_TYPE (expr1))
&& (TREE_CODE (expr1) == NOP_EXPR
|| TREE_CODE (expr1) == CONVERT_EXPR))
;
else if (VOID_TYPE_P (TREE_TYPE (expr1))
&& TREE_CODE (expr1) == COMPOUND_EXPR
&& (TREE_CODE (TREE_OPERAND (expr1, 1)) == CONVERT_EXPR
|| TREE_CODE (TREE_OPERAND (expr1, 1)) == NOP_EXPR))
;
else
warning (0, "left-hand operand of comma expression has no effect");
}
}
else if (warn_unused_value)
warn_if_unused_value (expr1, input_location);
if (expr2 == error_mark_node)
return error_mark_node;
return build2 (COMPOUND_EXPR, TREE_TYPE (expr2), expr1, expr2);
}
tree
build_c_cast (tree type, tree expr)
{
tree value = expr;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
if (objc_is_object_ptr (type) && objc_is_object_ptr (TREE_TYPE (expr)))
return build1 (NOP_EXPR, type, expr);
type = TYPE_MAIN_VARIANT (type);
if (TREE_CODE (type) == ARRAY_TYPE)
{
error ("cast specifies array type");
return error_mark_node;
}
if (TREE_CODE (type) == FUNCTION_TYPE)
{
error ("cast specifies function type");
return error_mark_node;
}
if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
{
if (pedantic)
{
if (TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE)
pedwarn ("ISO C forbids casting nonscalar to the same type");
}
}
else if (TREE_CODE (type) == UNION_TYPE)
{
tree field;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
TYPE_MAIN_VARIANT (TREE_TYPE (value))))
break;
if (field)
{
tree t;
if (pedantic)
pedwarn ("ISO C forbids casts to union type");
t = digest_init (type,
build_constructor_single (type, field, value),
true, 0);
TREE_CONSTANT (t) = TREE_CONSTANT (value);
TREE_INVARIANT (t) = TREE_INVARIANT (value);
return t;
}
error ("cast to union type from type not present in union");
return error_mark_node;
}
else
{
tree otype, ovalue;
if (type == void_type_node)
return build1 (CONVERT_EXPR, type, value);
otype = TREE_TYPE (value);
if (warn_cast_qual
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE)
{
tree in_type = type;
tree in_otype = otype;
int added = 0;
int discarded = 0;
do
{
in_otype = TREE_TYPE (in_otype);
in_type = TREE_TYPE (in_type);
if (TREE_CODE (in_otype) == FUNCTION_TYPE
&& TREE_CODE (in_type) == FUNCTION_TYPE)
added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
else
discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
}
while (TREE_CODE (in_type) == POINTER_TYPE
&& TREE_CODE (in_otype) == POINTER_TYPE);
if (added)
warning (0, "cast adds new qualifiers to function type");
if (discarded)
warning (0, "cast discards qualifiers from pointer target type");
}
if (STRICT_ALIGNMENT
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
&& TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
&& !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE
|| TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE)
&& TYPE_MODE (TREE_TYPE (otype)) == VOIDmode)
&& TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
warning (OPT_Wcast_align,
"cast increases required alignment of target type");
if (TREE_CODE (type) == INTEGER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE
&& TYPE_PRECISION (type) != TYPE_PRECISION (otype))
warning (OPT_Wpointer_to_int_cast,
"cast from pointer to integer of different size");
if (TREE_CODE (value) == CALL_EXPR
&& TREE_CODE (type) != TREE_CODE (otype))
warning (OPT_Wbad_function_cast, "cast from function call of type %qT "
"to non-matching type %qT", otype, type);
if (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == INTEGER_TYPE
&& TYPE_PRECISION (type) != TYPE_PRECISION (otype)
&& !TREE_CONSTANT (value))
warning (OPT_Wint_to_pointer_cast, "cast to pointer from integer "
"of different size");
strict_aliasing_warning (otype, type, expr);
if (pedantic
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (otype)) == FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
pedwarn ("ISO C forbids conversion of function pointer to object pointer type");
if (pedantic
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
&& !null_pointer_constant_p (value))
pedwarn ("ISO C forbids conversion of object pointer to function pointer type");
ovalue = value;
value = convert (type, value);
if (TREE_CODE (value) == INTEGER_CST)
{
if (CONSTANT_CLASS_P (ovalue)
&& (TREE_OVERFLOW (ovalue) || TREE_CONSTANT_OVERFLOW (ovalue)))
{
value = copy_node (value);
TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
}
else if (TREE_OVERFLOW (value) || TREE_CONSTANT_OVERFLOW (value))
value = build_int_cst_wide (TREE_TYPE (value),
TREE_INT_CST_LOW (value),
TREE_INT_CST_HIGH (value));
}
}
if (value == expr)
value = non_lvalue (value);
return value;
}
tree
c_cast_expr (struct c_type_name *type_name, tree expr)
{
tree type;
int saved_wsp = warn_strict_prototypes;
if (TREE_CODE (expr) == INTEGER_CST)
warn_strict_prototypes = 0;
type = groktypename (type_name);
warn_strict_prototypes = saved_wsp;
return build_c_cast (type, expr);
}
tree
build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
{
tree result;
tree newrhs;
tree lhstype = TREE_TYPE (lhs);
tree olhstype = lhstype;
lhs = require_complete_type (lhs);
if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
return error_mark_node;
if (!lvalue_or_else (lhs, lv_assign))
return error_mark_node;
STRIP_TYPE_NOPS (rhs);
newrhs = rhs;
if (modifycode != NOP_EXPR)
{
lhs = stabilize_reference (lhs);
newrhs = build_binary_op (modifycode, lhs, rhs, 1);
}
if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
|| ((TREE_CODE (lhstype) == RECORD_TYPE
|| TREE_CODE (lhstype) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (lhstype)))
{
readonly_error (lhs, lv_assign);
return error_mark_node;
}
if (TREE_CODE (lhs) == COMPONENT_REF
&& (TREE_CODE (lhstype) == INTEGER_TYPE
|| TREE_CODE (lhstype) == BOOLEAN_TYPE
|| TREE_CODE (lhstype) == REAL_TYPE
|| TREE_CODE (lhstype) == ENUMERAL_TYPE))
lhstype = TREE_TYPE (get_unwidened (lhs, 0));
if (lhstype != TREE_TYPE (lhs))
{
lhs = copy_node (lhs);
TREE_TYPE (lhs) = lhstype;
}
newrhs = convert_for_assignment (lhstype, newrhs, ic_assign,
NULL_TREE, NULL_TREE, 0);
if (TREE_CODE (newrhs) == ERROR_MARK)
return error_mark_node;
if (c_dialect_objc () && flag_objc_gc)
{
result = objc_generate_write_barrier (lhs, modifycode, newrhs);
if (result)
return result;
}
result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
TREE_SIDE_EFFECTS (result) = 1;
if (olhstype == TREE_TYPE (result))
return result;
return convert_for_assignment (olhstype, result, ic_assign,
NULL_TREE, NULL_TREE, 0);
}
static tree
convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
tree fundecl, tree function, int parmnum)
{
enum tree_code codel = TREE_CODE (type);
tree rhstype;
enum tree_code coder;
tree rname = NULL_TREE;
bool objc_ok = false;
if (errtype == ic_argpass || errtype == ic_argpass_nonproto)
{
tree selector;
if (TREE_CODE (function) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
function = TREE_OPERAND (function, 0);
selector = objc_message_selector ();
rname = function;
if (selector && parmnum > 2)
{
rname = selector;
parmnum -= 2;
}
}
#define WARN_FOR_ASSIGNMENT(AR, AS, IN, RE) \
do { \
switch (errtype) \
{ \
case ic_argpass: \
pedwarn (AR, parmnum, rname); \
break; \
case ic_argpass_nonproto: \
warning (0, AR, parmnum, rname); \
break; \
case ic_assign: \
pedwarn (AS); \
break; \
case ic_init: \
pedwarn (IN); \
break; \
case ic_return: \
pedwarn (RE); \
break; \
default: \
gcc_unreachable (); \
} \
} while (0)
STRIP_TYPE_NOPS (rhs);
if (optimize && TREE_CODE (rhs) == VAR_DECL
&& TREE_CODE (TREE_TYPE (rhs)) != ARRAY_TYPE)
rhs = decl_constant_value_for_broken_optimization (rhs);
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
if (coder == ERROR_MARK)
return error_mark_node;
if (c_dialect_objc ())
{
int parmno;
switch (errtype)
{
case ic_return:
parmno = 0;
break;
case ic_assign:
parmno = -1;
break;
case ic_init:
parmno = -2;
break;
default:
parmno = parmnum;
break;
}
objc_ok = objc_compare_types (type, rhstype, parmno, rname);
}
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{
overflow_warning (rhs);
return rhs;
}
if (coder == VOID_TYPE)
{
error ("void value not ignored as it ought to be");
return error_mark_node;
}
if (codel == REFERENCE_TYPE
&& comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1)
{
if (!lvalue_p (rhs))
{
error ("cannot pass rvalue to reference parameter");
return error_mark_node;
}
if (!c_mark_addressable (rhs))
return error_mark_node;
rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
if (TREE_TYPE (TREE_TYPE (rhs)) != TREE_TYPE (type))
rhs = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), rhs);
rhs = build1 (NOP_EXPR, type, rhs);
return rhs;
}
else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE
&& vector_types_convertible_p (type, TREE_TYPE (rhs)))
return convert (type, rhs);
else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
|| codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
|| codel == BOOLEAN_TYPE)
&& (coder == INTEGER_TYPE || coder == REAL_TYPE
|| coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
|| coder == BOOLEAN_TYPE))
return convert_and_check (type, rhs);
if ((codel == RECORD_TYPE || codel == UNION_TYPE)
&& codel == coder
&& comptypes (type, rhstype))
return convert_and_check (type, rhs);
if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
&& (errtype == ic_argpass || errtype == ic_argpass_nonproto))
{
tree memb, marginal_memb = NULL_TREE;
for (memb = TYPE_FIELDS (type); memb ; memb = TREE_CHAIN (memb))
{
tree memb_type = TREE_TYPE (memb);
if (comptypes (TYPE_MAIN_VARIANT (memb_type),
TYPE_MAIN_VARIANT (rhstype)))
break;
if (TREE_CODE (memb_type) != POINTER_TYPE)
continue;
if (coder == POINTER_TYPE)
{
tree ttl = TREE_TYPE (memb_type);
tree ttr = TREE_TYPE (rhstype);
if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
|| comp_target_types (memb_type, rhstype))
{
if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
|| ((TREE_CODE (ttr) == FUNCTION_TYPE
&& TREE_CODE (ttl) == FUNCTION_TYPE)
? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
== TYPE_QUALS (ttr))
: ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
== TYPE_QUALS (ttl))))
break;
if (!marginal_memb)
marginal_memb = memb;
}
}
if (null_pointer_constant_p (rhs))
{
rhs = null_pointer_node;
break;
}
}
if (memb || marginal_memb)
{
if (!memb)
{
tree ttl = TREE_TYPE (TREE_TYPE (marginal_memb));
tree ttr = TREE_TYPE (rhstype);
if (TREE_CODE (ttr) == FUNCTION_TYPE
&& TREE_CODE (ttl) == FUNCTION_TYPE)
{
if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE "
"makes qualified function "
"pointer from unqualified"),
G_("assignment makes qualified "
"function pointer from "
"unqualified"),
G_("initialization makes qualified "
"function pointer from "
"unqualified"),
G_("return makes qualified function "
"pointer from unqualified"));
}
else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards "
"qualifiers from pointer target type"),
G_("assignment discards qualifiers "
"from pointer target type"),
G_("initialization discards qualifiers "
"from pointer target type"),
G_("return discards qualifiers from "
"pointer target type"));
memb = marginal_memb;
}
if (pedantic && (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl)))
pedwarn ("ISO C prohibits argument conversion to union type");
return build_constructor_single (type, memb, rhs);
}
}
else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
&& (coder == codel))
{
tree ttl = TREE_TYPE (type);
tree ttr = TREE_TYPE (rhstype);
tree mvl = ttl;
tree mvr = ttr;
bool is_opaque_pointer;
int target_cmp = 0;
if (TREE_CODE (mvl) != ARRAY_TYPE)
mvl = TYPE_MAIN_VARIANT (mvl);
if (TREE_CODE (mvr) != ARRAY_TYPE)
mvr = TYPE_MAIN_VARIANT (mvr);
is_opaque_pointer = (targetm.vector_opaque_p (type)
|| targetm.vector_opaque_p (rhstype))
&& TREE_CODE (ttl) == VECTOR_TYPE
&& TREE_CODE (ttr) == VECTOR_TYPE;
if (VOID_TYPE_P (ttr) && rhs != null_pointer_node && !VOID_TYPE_P (ttl))
warning (OPT_Wc___compat, "request for implicit conversion from "
"%qT to %qT not permitted in C++", rhstype, type);
if (warn_missing_format_attribute
&& check_missing_format_attribute (type, rhstype))
{
switch (errtype)
{
case ic_argpass:
case ic_argpass_nonproto:
warning (OPT_Wmissing_format_attribute,
"argument %d of %qE might be "
"a candidate for a format attribute",
parmnum, rname);
break;
case ic_assign:
warning (OPT_Wmissing_format_attribute,
"assignment left-hand side might be "
"a candidate for a format attribute");
break;
case ic_init:
warning (OPT_Wmissing_format_attribute,
"initialization left-hand side might be "
"a candidate for a format attribute");
break;
case ic_return:
warning (OPT_Wmissing_format_attribute,
"return type might be "
"a candidate for a format attribute");
break;
default:
gcc_unreachable ();
}
}
if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
|| (target_cmp = comp_target_types (type, rhstype))
|| is_opaque_pointer
|| (c_common_unsigned_type (mvl)
== c_common_unsigned_type (mvr)))
{
if (pedantic
&& ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
||
(VOID_TYPE_P (ttr)
&& !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 "
"and %<void *%>"),
G_("ISO C forbids assignment between "
"function pointer and %<void *%>"),
G_("ISO C forbids initialization between "
"function pointer and %<void *%>"),
G_("ISO C forbids return between function "
"pointer and %<void *%>"));
else if (TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttl) != FUNCTION_TYPE)
{
if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
{
if (!objc_type_quals_match (ttl, ttr))
WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards "
"qualifiers from pointer target type"),
G_("assignment discards qualifiers "
"from pointer target type"),
G_("initialization discards qualifiers "
"from pointer target type"),
G_("return discards qualifiers from "
"pointer target type"));
}
else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
|| target_cmp)
;
else if (warn_pointer_sign)
WARN_FOR_ASSIGNMENT (G_("pointer targets in passing argument "
"%d of %qE differ in signedness"),
G_("pointer targets in assignment "
"differ in signedness"),
G_("pointer targets in initialization "
"differ in signedness"),
G_("pointer targets in return differ "
"in signedness"));
}
else if (TREE_CODE (ttl) == FUNCTION_TYPE
&& TREE_CODE (ttr) == FUNCTION_TYPE)
{
if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes "
"qualified function pointer "
"from unqualified"),
G_("assignment makes qualified function "
"pointer from unqualified"),
G_("initialization makes qualified "
"function pointer from unqualified"),
G_("return makes qualified function "
"pointer from unqualified"));
}
}
else
if (!objc_ok)
WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE from "
"incompatible pointer type"),
G_("assignment from incompatible pointer type"),
G_("initialization from incompatible "
"pointer type"),
G_("return from incompatible pointer type"));
return convert (type, rhs);
}
else if (codel == POINTER_TYPE && coder == ARRAY_TYPE)
{
error ("invalid use of non-lvalue array");
return error_mark_node;
}
else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
{
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 "
"without a cast"),
G_("initialization makes pointer from "
"integer without a cast"),
G_("return makes pointer from integer "
"without a cast"));
return convert (type, rhs);
}
else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
{
WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes integer "
"from pointer without a cast"),
G_("assignment makes integer from pointer "
"without a cast"),
G_("initialization makes integer from pointer "
"without a cast"),
G_("return makes integer from pointer "
"without a cast"));
return convert (type, rhs);
}
else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
return convert (type, rhs);
switch (errtype)
{
case ic_argpass:
case ic_argpass_nonproto:
error ("incompatible type for argument %d of %qE", parmnum, rname);
break;
case ic_assign:
error ("incompatible types in assignment");
break;
case ic_init:
error ("incompatible types in initialization");
break;
case ic_return:
error ("incompatible types in return");
break;
default:
gcc_unreachable ();
}
return error_mark_node;
}
tree
c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum)
{
tree ret, type;
if (!value
|| (TYPE_ARG_TYPES (TREE_TYPE (fn))
&& (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
== TYPE_MAIN_VARIANT (TREE_TYPE (value)))))
return value;
type = TREE_TYPE (parm);
ret = convert_for_assignment (type, value,
ic_argpass_nonproto, fn,
fn, argnum);
if (targetm.calls.promote_prototypes (TREE_TYPE (fn))
&& INTEGRAL_TYPE_P (type)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
ret = default_conversion (ret);
return ret;
}
static tree
valid_compound_expr_initializer (tree value, tree endtype)
{
if (TREE_CODE (value) == COMPOUND_EXPR)
{
if (valid_compound_expr_initializer (TREE_OPERAND (value, 0), endtype)
== error_mark_node)
return error_mark_node;
return valid_compound_expr_initializer (TREE_OPERAND (value, 1),
endtype);
}
else if (!initializer_constant_valid_p (value, endtype))
return error_mark_node;
else
return value;
}
void
store_init_value (tree decl, tree init)
{
tree value, type;
type = TREE_TYPE (decl);
if (TREE_CODE (type) == ERROR_MARK)
return;
value = digest_init (type, init, true, TREE_STATIC (decl));
if (!in_system_header
&& AGGREGATE_TYPE_P (TREE_TYPE (decl)) && !TREE_STATIC (decl))
warning (OPT_Wtraditional, "traditional C rejects automatic "
"aggregate initialization");
DECL_INITIAL (decl) = value;
STRIP_TYPE_NOPS (value);
constant_expression_warning (value);
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == 0
&& value != error_mark_node)
{
tree inside_init = init;
STRIP_TYPE_NOPS (inside_init);
inside_init = fold (inside_init);
if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
{
tree cldecl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
if (TYPE_DOMAIN (TREE_TYPE (cldecl)))
{
type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
TREE_TYPE (decl) = type;
TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (cldecl));
layout_type (type);
layout_decl (cldecl, 0);
}
}
}
}
struct spelling
{
int kind;
union
{
unsigned HOST_WIDE_INT i;
const char *s;
} u;
};
#define SPELLING_STRING 1
#define SPELLING_MEMBER 2
#define SPELLING_BOUNDS 3
static struct spelling *spelling;
static struct spelling *spelling_base;
static int spelling_size;
#define SPELLING_DEPTH() (spelling - spelling_base)
#define RESTORE_SPELLING_DEPTH(DEPTH) (spelling = spelling_base + (DEPTH))
#define PUSH_SPELLING(KIND, VALUE, MEMBER) \
{ \
int depth = SPELLING_DEPTH (); \
\
if (depth >= spelling_size) \
{ \
spelling_size += 10; \
spelling_base = XRESIZEVEC (struct spelling, spelling_base, \
spelling_size); \
RESTORE_SPELLING_DEPTH (depth); \
} \
\
spelling->kind = (KIND); \
spelling->MEMBER = (VALUE); \
spelling++; \
}
static void
push_string (const char *string)
{
PUSH_SPELLING (SPELLING_STRING, string, u.s);
}
static void
push_member_name (tree decl)
{
const char *const string
= DECL_NAME (decl) ? IDENTIFIER_POINTER (DECL_NAME (decl)) : "<anonymous>";
PUSH_SPELLING (SPELLING_MEMBER, string, u.s);
}
static void
push_array_bounds (unsigned HOST_WIDE_INT bounds)
{
PUSH_SPELLING (SPELLING_BOUNDS, bounds, u.i);
}
static int
spelling_length (void)
{
int size = 0;
struct spelling *p;
for (p = spelling_base; p < spelling; p++)
{
if (p->kind == SPELLING_BOUNDS)
size += 25;
else
size += strlen (p->u.s) + 1;
}
return size;
}
static char *
print_spelling (char *buffer)
{
char *d = buffer;
struct spelling *p;
for (p = spelling_base; p < spelling; p++)
if (p->kind == SPELLING_BOUNDS)
{
sprintf (d, "[" HOST_WIDE_INT_PRINT_UNSIGNED "]", p->u.i);
d += strlen (d);
}
else
{
const char *s;
if (p->kind == SPELLING_MEMBER)
*d++ = '.';
for (s = p->u.s; (*d = *s++); d++)
;
}
*d++ = '\0';
return buffer;
}
void
error_init (const char *msgid)
{
char *ofwhat;
error ("%s", _(msgid));
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
error ("(near initialization for %qs)", ofwhat);
}
void
pedwarn_init (const char *msgid)
{
char *ofwhat;
pedwarn ("%s", _(msgid));
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
pedwarn ("(near initialization for %qs)", ofwhat);
}
static void
warning_init (const char *msgid)
{
char *ofwhat;
warning (0, "%s", _(msgid));
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
warning (0, "(near initialization for %qs)", ofwhat);
}
void
maybe_warn_string_init (tree type, struct c_expr expr)
{
if (pedantic
&& TREE_CODE (type) == ARRAY_TYPE
&& TREE_CODE (expr.value) == STRING_CST
&& expr.original_code != STRING_CST)
pedwarn_init ("array initialized from parenthesized string constant");
}
static tree
digest_init (tree type, tree init, bool strict_string, int require_constant)
{
enum tree_code code = TREE_CODE (type);
tree inside_init = init;
if (type == error_mark_node
|| !init
|| init == error_mark_node
|| TREE_TYPE (init) == error_mark_node)
return error_mark_node;
STRIP_TYPE_NOPS (inside_init);
inside_init = fold (inside_init);
if (code == ARRAY_TYPE && inside_init
&& TREE_CODE (inside_init) == STRING_CST)
{
tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
bool char_array = (typ1 == char_type_node
|| typ1 == signed_char_type_node
|| typ1 == unsigned_char_type_node);
bool wchar_array = !!comptypes (typ1, wchar_type_node);
if (char_array || wchar_array)
{
struct c_expr expr;
bool char_string;
expr.value = inside_init;
expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
maybe_warn_string_init (type, expr);
char_string
= (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
== char_type_node);
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
TYPE_MAIN_VARIANT (type)))
return inside_init;
if (!wchar_array && !char_string)
{
error_init ("char-array initialized from wide string");
return error_mark_node;
}
if (char_string && !char_array)
{
error_init ("wchar_t-array initialized from non-wide string");
return error_mark_node;
}
TREE_TYPE (inside_init) = type;
if (TYPE_DOMAIN (type) != 0
&& TYPE_SIZE (type) != 0
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& 0 > compare_tree_int (TYPE_SIZE_UNIT (type),
TREE_STRING_LENGTH (inside_init)
- ((TYPE_PRECISION (typ1)
!= TYPE_PRECISION (char_type_node))
? (TYPE_PRECISION (wchar_type_node)
/ BITS_PER_UNIT)
: 1)))
pedwarn_init ("initializer-string for array of chars is too long");
return inside_init;
}
else if (INTEGRAL_TYPE_P (typ1))
{
error_init ("array of inappropriate type initialized "
"from string constant");
return error_mark_node;
}
}
if (code == VECTOR_TYPE
&& TREE_CODE (TREE_TYPE (inside_init)) == VECTOR_TYPE
&& vector_types_convertible_p (TREE_TYPE (inside_init), type)
&& TREE_CONSTANT (inside_init))
{
if (TREE_CODE (inside_init) == VECTOR_CST
&& comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
TYPE_MAIN_VARIANT (type)))
return inside_init;
if (TREE_CODE (inside_init) == CONSTRUCTOR)
{
unsigned HOST_WIDE_INT ix;
tree value;
bool constant_p = true;
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (inside_init), ix, value)
if (!CONSTANT_CLASS_P (value))
{
constant_p = false;
break;
}
if (constant_p)
return build_vector_from_ctor (type,
CONSTRUCTOR_ELTS (inside_init));
}
}
if (inside_init && TREE_TYPE (inside_init) != 0
&& (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
TYPE_MAIN_VARIANT (type))
|| (code == ARRAY_TYPE
&& comptypes (TREE_TYPE (inside_init), type))
|| (code == VECTOR_TYPE
&& comptypes (TREE_TYPE (inside_init), type))
|| (code == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
&& comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
TREE_TYPE (type)))))
{
if (code == POINTER_TYPE)
{
if (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE)
{
if (TREE_CODE (inside_init) == STRING_CST
|| TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
inside_init = array_to_pointer_conversion (inside_init);
else
{
error_init ("invalid use of non-lvalue array");
return error_mark_node;
}
}
}
if (code == VECTOR_TYPE)
inside_init = convert (type, inside_init);
if (require_constant
&& (code == VECTOR_TYPE || !flag_isoc99)
&& TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
{
tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
inside_init = DECL_INITIAL (decl);
}
if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
&& TREE_CODE (inside_init) != CONSTRUCTOR)
{
error_init ("array initialized from non-constant array expression");
return error_mark_node;
}
if (optimize && TREE_CODE (inside_init) == VAR_DECL)
inside_init = decl_constant_value_for_broken_optimization (inside_init);
if (require_constant && pedantic
&& TREE_CODE (inside_init) == COMPOUND_EXPR)
{
inside_init
= valid_compound_expr_initializer (inside_init,
TREE_TYPE (inside_init));
if (inside_init == error_mark_node)
error_init ("initializer element is not constant");
else
pedwarn_init ("initializer element is not constant");
if (flag_pedantic_errors)
inside_init = error_mark_node;
}
else if (require_constant
&& !initializer_constant_valid_p (inside_init,
TREE_TYPE (inside_init)))
{
error_init ("initializer element is not constant");
inside_init = error_mark_node;
}
if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE)
inside_init = convert_for_assignment (type, inside_init, ic_init, NULL_TREE,
NULL_TREE, 0);
return inside_init;
}
if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
|| code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
|| code == VECTOR_TYPE)
{
if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
&& (TREE_CODE (init) == STRING_CST
|| TREE_CODE (init) == COMPOUND_LITERAL_EXPR))
init = array_to_pointer_conversion (init);
inside_init
= convert_for_assignment (type, init, ic_init,
NULL_TREE, NULL_TREE, 0);
if (inside_init == error_mark_node)
;
else if (require_constant && !TREE_CONSTANT (inside_init))
{
error_init ("initializer element is not constant");
inside_init = error_mark_node;
}
else if (require_constant
&& !initializer_constant_valid_p (inside_init,
TREE_TYPE (inside_init)))
{
error_init ("initializer element is not computable at load time");
inside_init = error_mark_node;
}
return inside_init;
}
if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
error_init ("variable-sized object may not be initialized");
return error_mark_node;
}
error_init ("invalid initializer");
return error_mark_node;
}
static tree constructor_type;
static tree constructor_fields;
static tree constructor_index;
static tree constructor_max_index;
static tree constructor_unfilled_fields;
static tree constructor_unfilled_index;
static tree constructor_bit_index;
static VEC(constructor_elt,gc) *constructor_elements;
static int constructor_incremental;
static int constructor_constant;
static int constructor_simple;
static int constructor_erroneous;
struct init_node
{
struct init_node *left, *right;
struct init_node *parent;
int balance;
tree purpose;
tree value;
};
static struct init_node *constructor_pending_elts;
static int constructor_depth;
static tree constructor_decl;
static int constructor_top_level;
static int constructor_designated;
static int designator_depth;
static int designator_erroneous;
struct constructor_range_stack;
struct constructor_stack
{
struct constructor_stack *next;
tree type;
tree fields;
tree index;
tree max_index;
tree unfilled_index;
tree unfilled_fields;
tree bit_index;
VEC(constructor_elt,gc) *elements;
struct init_node *pending_elts;
int offset;
int depth;
struct c_expr replacement_value;
struct constructor_range_stack *range_stack;
char constant;
char simple;
char implicit;
char erroneous;
char outer;
char incremental;
char designated;
};
static struct constructor_stack *constructor_stack;
struct constructor_range_stack
{
struct constructor_range_stack *next, *prev;
struct constructor_stack *stack;
tree range_start;
tree index;
tree range_end;
tree fields;
};
static struct constructor_range_stack *constructor_range_stack;
struct initializer_stack
{
struct initializer_stack *next;
tree decl;
struct constructor_stack *constructor_stack;
struct constructor_range_stack *constructor_range_stack;
VEC(constructor_elt,gc) *elements;
struct spelling *spelling;
struct spelling *spelling_base;
int spelling_size;
char top_level;
char require_constant_value;
char require_constant_elements;
};
static struct initializer_stack *initializer_stack;
void
start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
{
const char *locus;
struct initializer_stack *p = XNEW (struct initializer_stack);
p->decl = constructor_decl;
p->require_constant_value = require_constant_value;
p->require_constant_elements = require_constant_elements;
p->constructor_stack = constructor_stack;
p->constructor_range_stack = constructor_range_stack;
p->elements = constructor_elements;
p->spelling = spelling;
p->spelling_base = spelling_base;
p->spelling_size = spelling_size;
p->top_level = constructor_top_level;
p->next = initializer_stack;
initializer_stack = p;
constructor_decl = decl;
constructor_designated = 0;
constructor_top_level = top_level;
if (decl != 0 && decl != error_mark_node)
{
require_constant_value = TREE_STATIC (decl);
require_constant_elements
= ((TREE_STATIC (decl) || (pedantic && !flag_isoc99))
&& (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE));
locus = IDENTIFIER_POINTER (DECL_NAME (decl));
}
else
{
require_constant_value = 0;
require_constant_elements = 0;
locus = "(anonymous)";
}
constructor_stack = 0;
constructor_range_stack = 0;
missing_braces_mentioned = 0;
spelling_base = 0;
spelling_size = 0;
RESTORE_SPELLING_DEPTH (0);
if (locus)
push_string (locus);
}
void
finish_init (void)
{
struct initializer_stack *p = initializer_stack;
while (constructor_stack)
{
struct constructor_stack *q = constructor_stack;
constructor_stack = q->next;
free (q);
}
gcc_assert (!constructor_range_stack);
free (spelling_base);
constructor_decl = p->decl;
require_constant_value = p->require_constant_value;
require_constant_elements = p->require_constant_elements;
constructor_stack = p->constructor_stack;
constructor_range_stack = p->constructor_range_stack;
constructor_elements = p->elements;
spelling = p->spelling;
spelling_base = p->spelling_base;
spelling_size = p->spelling_size;
constructor_top_level = p->top_level;
initializer_stack = p->next;
free (p);
}
void
really_start_incremental_init (tree type)
{
struct constructor_stack *p = XNEW (struct constructor_stack);
if (type == 0)
type = TREE_TYPE (constructor_decl);
if (targetm.vector_opaque_p (type))
error ("opaque vector types cannot be initialized");
p->type = constructor_type;
p->fields = constructor_fields;
p->index = constructor_index;
p->max_index = constructor_max_index;
p->unfilled_index = constructor_unfilled_index;
p->unfilled_fields = constructor_unfilled_fields;
p->bit_index = constructor_bit_index;
p->elements = constructor_elements;
p->constant = constructor_constant;
p->simple = constructor_simple;
p->erroneous = constructor_erroneous;
p->pending_elts = constructor_pending_elts;
p->depth = constructor_depth;
p->replacement_value.value = 0;
p->replacement_value.original_code = ERROR_MARK;
p->implicit = 0;
p->range_stack = 0;
p->outer = 0;
p->incremental = constructor_incremental;
p->designated = constructor_designated;
p->next = 0;
constructor_stack = p;
constructor_constant = 1;
constructor_simple = 1;
constructor_depth = SPELLING_DEPTH ();
constructor_elements = 0;
constructor_pending_elts = 0;
constructor_type = type;
constructor_incremental = 1;
constructor_designated = 0;
designator_depth = 0;
designator_erroneous = 0;
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
constructor_fields = TYPE_FIELDS (constructor_type);
while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
constructor_fields = TREE_CHAIN (constructor_fields);
constructor_unfilled_fields = constructor_fields;
constructor_bit_index = bitsize_zero_node;
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
if (TYPE_DOMAIN (constructor_type))
{
constructor_max_index
= TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
if (constructor_max_index == NULL_TREE
&& TYPE_SIZE (constructor_type))
constructor_max_index = build_int_cst (NULL_TREE, -1);
if (constructor_max_index
&& TREE_CODE (constructor_max_index) != INTEGER_CST)
constructor_max_index = build_int_cst (NULL_TREE, -1);
constructor_index
= convert (bitsizetype,
TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
}
else
{
constructor_index = bitsize_zero_node;
constructor_max_index = NULL_TREE;
}
constructor_unfilled_index = constructor_index;
}
else if (TREE_CODE (constructor_type) == VECTOR_TYPE)
{
constructor_max_index =
build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
constructor_index = bitsize_zero_node;
constructor_unfilled_index = constructor_index;
}
else
{
constructor_fields = constructor_type;
constructor_unfilled_fields = constructor_type;
}
}
void
push_init_level (int implicit)
{
struct constructor_stack *p;
tree value = NULL_TREE;
if (implicit != 1)
{
while (constructor_stack->implicit)
{
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
process_init_element (pop_init_level (1));
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));
else
break;
}
}
if (implicit)
{
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields)
value = find_init_member (constructor_fields);
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
value = find_init_member (constructor_index);
}
p = XNEW (struct constructor_stack);
p->type = constructor_type;
p->fields = constructor_fields;
p->index = constructor_index;
p->max_index = constructor_max_index;
p->unfilled_index = constructor_unfilled_index;
p->unfilled_fields = constructor_unfilled_fields;
p->bit_index = constructor_bit_index;
p->elements = constructor_elements;
p->constant = constructor_constant;
p->simple = constructor_simple;
p->erroneous = constructor_erroneous;
p->pending_elts = constructor_pending_elts;
p->depth = constructor_depth;
p->replacement_value.value = 0;
p->replacement_value.original_code = ERROR_MARK;
p->implicit = implicit;
p->outer = 0;
p->incremental = constructor_incremental;
p->designated = constructor_designated;
p->next = constructor_stack;
p->range_stack = 0;
constructor_stack = p;
constructor_constant = 1;
constructor_simple = 1;
constructor_depth = SPELLING_DEPTH ();
constructor_elements = 0;
constructor_incremental = 1;
constructor_designated = 0;
constructor_pending_elts = 0;
if (!implicit)
{
p->range_stack = constructor_range_stack;
constructor_range_stack = 0;
designator_depth = 0;
designator_erroneous = 0;
}
if (constructor_type == 0)
;
else if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
if (constructor_fields == 0)
constructor_type = 0;
else
{
constructor_type = TREE_TYPE (constructor_fields);
push_member_name (constructor_fields);
constructor_depth++;
}
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
constructor_type = TREE_TYPE (constructor_type);
push_array_bounds (tree_low_cst (constructor_index, 1));
constructor_depth++;
}
if (constructor_type == 0)
{
error_init ("extra brace group at end of initializer");
constructor_fields = 0;
constructor_unfilled_fields = 0;
return;
}
if (value && TREE_CODE (value) == CONSTRUCTOR)
{
constructor_constant = TREE_CONSTANT (value);
constructor_simple = TREE_STATIC (value);
constructor_elements = CONSTRUCTOR_ELTS (value);
if (!VEC_empty (constructor_elt, constructor_elements)
&& (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == ARRAY_TYPE))
set_nonincremental_init ();
}
if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
{
missing_braces_mentioned = 1;
warning_init ("missing braces around initializer");
}
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
constructor_fields = TYPE_FIELDS (constructor_type);
while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
constructor_fields = TREE_CHAIN (constructor_fields);
constructor_unfilled_fields = constructor_fields;
constructor_bit_index = bitsize_zero_node;
}
else if (TREE_CODE (constructor_type) == VECTOR_TYPE)
{
constructor_max_index =
build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
constructor_index = convert (bitsizetype, integer_zero_node);
constructor_unfilled_index = constructor_index;
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
if (TYPE_DOMAIN (constructor_type))
{
constructor_max_index
= TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
if (constructor_max_index == NULL_TREE
&& TYPE_SIZE (constructor_type))
constructor_max_index = build_int_cst (NULL_TREE, -1);
if (constructor_max_index
&& TREE_CODE (constructor_max_index) != INTEGER_CST)
constructor_max_index = build_int_cst (NULL_TREE, -1);
constructor_index
= convert (bitsizetype,
TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
}
else
constructor_index = bitsize_zero_node;
constructor_unfilled_index = constructor_index;
if (value && TREE_CODE (value) == STRING_CST)
{
set_nonincremental_init_from_string (value);
}
}
else
{
if (constructor_type != error_mark_node)
warning_init ("braces around scalar initializer");
constructor_fields = constructor_type;
constructor_unfilled_fields = constructor_type;
}
}
struct c_expr
pop_init_level (int implicit)
{
struct constructor_stack *p;
struct c_expr ret;
ret.value = 0;
ret.original_code = ERROR_MARK;
if (implicit == 0)
{
while (constructor_stack->implicit)
process_init_element (pop_init_level (1));
gcc_assert (!constructor_range_stack);
}
constructor_incremental = 1;
output_pending_init_elements (1);
p = constructor_stack;
if (constructor_type && constructor_fields
&& TREE_CODE (constructor_type) == ARRAY_TYPE
&& TYPE_DOMAIN (constructor_type)
&& !TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
{
if (integer_zerop (constructor_unfilled_index))
constructor_type = NULL_TREE;
else
{
gcc_assert (!TYPE_SIZE (constructor_type));
if (constructor_depth > 2)
error_init ("initialization of flexible array member in a nested context");
else if (pedantic)
pedwarn_init ("initialization of a flexible array member");
if (TREE_CHAIN (constructor_fields) != NULL_TREE)
constructor_type = NULL_TREE;
}
}
if (warn_missing_field_initializers
&& constructor_type
&& TREE_CODE (constructor_type) == RECORD_TYPE
&& constructor_unfilled_fields)
{
while (constructor_unfilled_fields
&& (!DECL_SIZE (constructor_unfilled_fields)
|| integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
if (constructor_unfilled_fields && !constructor_designated)
{
push_member_name (constructor_unfilled_fields);
warning_init ("missing initializer");
RESTORE_SPELLING_DEPTH (constructor_depth);
}
}
if (p->replacement_value.value)
ret = p->replacement_value;
else if (constructor_type == 0)
;
else if (TREE_CODE (constructor_type) != RECORD_TYPE
&& TREE_CODE (constructor_type) != UNION_TYPE
&& TREE_CODE (constructor_type) != ARRAY_TYPE
&& TREE_CODE (constructor_type) != VECTOR_TYPE)
{
if (VEC_empty (constructor_elt,constructor_elements))
{
if (!constructor_erroneous)
error_init ("empty scalar initializer");
ret.value = error_mark_node;
}
else if (VEC_length (constructor_elt,constructor_elements) != 1)
{
error_init ("extra elements in scalar initializer");
ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
}
else
ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
}
else
{
if (constructor_erroneous)
ret.value = error_mark_node;
else
{
ret.value = build_constructor (constructor_type,
constructor_elements);
if (constructor_constant)
TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
if (constructor_constant && constructor_simple)
TREE_STATIC (ret.value) = 1;
}
}
constructor_type = p->type;
constructor_fields = p->fields;
constructor_index = p->index;
constructor_max_index = p->max_index;
constructor_unfilled_index = p->unfilled_index;
constructor_unfilled_fields = p->unfilled_fields;
constructor_bit_index = p->bit_index;
constructor_elements = p->elements;
constructor_constant = p->constant;
constructor_simple = p->simple;
constructor_erroneous = p->erroneous;
constructor_incremental = p->incremental;
constructor_designated = p->designated;
constructor_pending_elts = p->pending_elts;
constructor_depth = p->depth;
if (!p->implicit)
constructor_range_stack = p->range_stack;
RESTORE_SPELLING_DEPTH (constructor_depth);
constructor_stack = p->next;
free (p);
if (ret.value == 0 && constructor_stack == 0)
ret.value = error_mark_node;
return ret;
}
static int
set_designator (int array)
{
tree subtype;
enum tree_code subcode;
if (constructor_type == 0)
return 1;
if (designator_erroneous)
return 1;
if (!designator_depth)
{
gcc_assert (!constructor_range_stack);
while (constructor_stack->implicit)
process_init_element (pop_init_level (1));
constructor_designated = 1;
return 0;
}
switch (TREE_CODE (constructor_type))
{
case RECORD_TYPE:
case UNION_TYPE:
subtype = TREE_TYPE (constructor_fields);
if (subtype != error_mark_node)
subtype = TYPE_MAIN_VARIANT (subtype);
break;
case ARRAY_TYPE:
subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
break;
default:
gcc_unreachable ();
}
subcode = TREE_CODE (subtype);
if (array && subcode != ARRAY_TYPE)
{
error_init ("array index in non-array initializer");
return 1;
}
else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE)
{
error_init ("field name not in record or union initializer");
return 1;
}
constructor_designated = 1;
push_init_level (2);
return 0;
}
static void
push_range_stack (tree range_end)
{
struct constructor_range_stack *p;
p = GGC_NEW (struct constructor_range_stack);
p->prev = constructor_range_stack;
p->next = 0;
p->fields = constructor_fields;
p->range_start = constructor_index;
p->index = constructor_index;
p->stack = constructor_stack;
p->range_end = range_end;
if (constructor_range_stack)
constructor_range_stack->next = p;
constructor_range_stack = p;
}
void
set_init_index (tree first, tree last)
{
if (set_designator (1))
return;
designator_erroneous = 1;
if (!INTEGRAL_TYPE_P (TREE_TYPE (first))
|| (last && !INTEGRAL_TYPE_P (TREE_TYPE (last))))
{
error_init ("array index in initializer not of integer type");
return;
}
if (TREE_CODE (first) != INTEGER_CST)
error_init ("nonconstant array index in initializer");
else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
error_init ("nonconstant array index in initializer");
else if (TREE_CODE (constructor_type) != ARRAY_TYPE)
error_init ("array index in non-array initializer");
else if (tree_int_cst_sgn (first) == -1)
error_init ("array index in initializer exceeds array bounds");
else if (constructor_max_index
&& tree_int_cst_lt (constructor_max_index, first))
error_init ("array index in initializer exceeds array bounds");
else
{
constructor_index = convert (bitsizetype, first);
if (last)
{
if (tree_int_cst_equal (first, last))
last = 0;
else if (tree_int_cst_lt (last, first))
{
error_init ("empty index range in initializer");
last = 0;
}
else
{
last = convert (bitsizetype, last);
if (constructor_max_index != 0
&& tree_int_cst_lt (constructor_max_index, last))
{
error_init ("array index range in initializer exceeds array bounds");
last = 0;
}
}
}
designator_depth++;
designator_erroneous = 0;
if (constructor_range_stack || last)
push_range_stack (last);
}
}
void
set_init_label (tree fieldname)
{
tree tail;
if (set_designator (0))
return;
designator_erroneous = 1;
if (TREE_CODE (constructor_type) != RECORD_TYPE
&& TREE_CODE (constructor_type) != UNION_TYPE)
{
error_init ("field name not in record or union initializer");
return;
}
for (tail = TYPE_FIELDS (constructor_type); tail;
tail = TREE_CHAIN (tail))
{
if (DECL_NAME (tail) == fieldname)
break;
}
if (tail == 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);
}
}
static void
add_pending_init (tree purpose, tree value)
{
struct init_node *p, **q, *r;
q = &constructor_pending_elts;
p = 0;
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
while (*q != 0)
{
p = *q;
if (tree_int_cst_lt (purpose, p->purpose))
q = &p->left;
else if (tree_int_cst_lt (p->purpose, purpose))
q = &p->right;
else
{
if (TREE_SIDE_EFFECTS (p->value))
warning_init ("initialized field with side-effects overwritten");
else if (warn_override_init)
warning_init ("initialized field overwritten");
p->value = value;
return;
}
}
}
else
{
tree bitpos;
bitpos = bit_position (purpose);
while (*q != NULL)
{
p = *q;
if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
q = &p->left;
else if (p->purpose != purpose)
q = &p->right;
else
{
if (TREE_SIDE_EFFECTS (p->value))
warning_init ("initialized field with side-effects overwritten");
else if (warn_override_init)
warning_init ("initialized field overwritten");
p->value = value;
return;
}
}
}
r = GGC_NEW (struct init_node);
r->purpose = purpose;
r->value = value;
*q = r;
r->parent = p;
r->left = 0;
r->right = 0;
r->balance = 0;
while (p)
{
struct init_node *s;
if (r == p->left)
{
if (p->balance == 0)
p->balance = -1;
else if (p->balance < 0)
{
if (r->balance < 0)
{
p->left = r->right;
if (p->left)
p->left->parent = p;
r->right = p;
p->balance = 0;
r->balance = 0;
s = p->parent;
p->parent = r;
r->parent = s;
if (s)
{
if (s->left == p)
s->left = r;
else
s->right = r;
}
else
constructor_pending_elts = r;
}
else
{
struct init_node *t = r->right;
r->right = t->left;
if (r->right)
r->right->parent = r;
t->left = r;
p->left = t->right;
if (p->left)
p->left->parent = p;
t->right = p;
p->balance = t->balance < 0;
r->balance = -(t->balance > 0);
t->balance = 0;
s = p->parent;
p->parent = t;
r->parent = t;
t->parent = s;
if (s)
{
if (s->left == p)
s->left = t;
else
s->right = t;
}
else
constructor_pending_elts = t;
}
break;
}
else
{
p->balance = 0;
break;
}
}
else
{
if (p->balance == 0)
p->balance++;
else if (p->balance > 0)
{
if (r->balance > 0)
{
p->right = r->left;
if (p->right)
p->right->parent = p;
r->left = p;
p->balance = 0;
r->balance = 0;
s = p->parent;
p->parent = r;
r->parent = s;
if (s)
{
if (s->left == p)
s->left = r;
else
s->right = r;
}
else
constructor_pending_elts = r;
}
else
{
struct init_node *t = r->left;
r->left = t->right;
if (r->left)
r->left->parent = r;
t->right = r;
p->right = t->left;
if (p->right)
p->right->parent = p;
t->left = p;
r->balance = (t->balance < 0);
p->balance = -(t->balance > 0);
t->balance = 0;
s = p->parent;
p->parent = t;
r->parent = t;
t->parent = s;
if (s)
{
if (s->left == p)
s->left = t;
else
s->right = t;
}
else
constructor_pending_elts = t;
}
break;
}
else
{
p->balance = 0;
break;
}
}
r = p;
p = p->parent;
}
}
static void
set_nonincremental_init (void)
{
unsigned HOST_WIDE_INT ix;
tree index, value;
if (TREE_CODE (constructor_type) != RECORD_TYPE
&& TREE_CODE (constructor_type) != ARRAY_TYPE)
return;
FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
add_pending_init (index, value);
constructor_elements = 0;
if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
constructor_unfilled_fields = TYPE_FIELDS (constructor_type);
while (constructor_unfilled_fields != 0
&& DECL_C_BIT_FIELD (constructor_unfilled_fields)
&& DECL_NAME (constructor_unfilled_fields) == 0)
constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
if (TYPE_DOMAIN (constructor_type))
constructor_unfilled_index
= convert (bitsizetype,
TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
else
constructor_unfilled_index = bitsize_zero_node;
}
constructor_incremental = 0;
}
static void
set_nonincremental_init_from_string (tree str)
{
tree value, purpose, type;
HOST_WIDE_INT val[2];
const char *p, *end;
int byte, wchar_bytes, charwidth, bitpos;
gcc_assert (TREE_CODE (constructor_type) == ARRAY_TYPE);
if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
== TYPE_PRECISION (char_type_node))
wchar_bytes = 1;
else
{
gcc_assert (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
== TYPE_PRECISION (wchar_type_node));
wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
}
charwidth = TYPE_PRECISION (char_type_node);
type = TREE_TYPE (constructor_type);
p = TREE_STRING_POINTER (str);
end = p + TREE_STRING_LENGTH (str);
for (purpose = bitsize_zero_node;
p < end && !tree_int_cst_lt (constructor_max_index, purpose);
purpose = size_binop (PLUS_EXPR, purpose, bitsize_one_node))
{
if (wchar_bytes == 1)
{
val[1] = (unsigned char) *p++;
val[0] = 0;
}
else
{
val[0] = 0;
val[1] = 0;
for (byte = 0; byte < wchar_bytes; byte++)
{
if (BYTES_BIG_ENDIAN)
bitpos = (wchar_bytes - byte - 1) * charwidth;
else
bitpos = byte * charwidth;
val[bitpos < HOST_BITS_PER_WIDE_INT]
|= ((unsigned HOST_WIDE_INT) ((unsigned char) *p++))
<< (bitpos % HOST_BITS_PER_WIDE_INT);
}
}
if (!TYPE_UNSIGNED (type))
{
bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR;
if (bitpos < HOST_BITS_PER_WIDE_INT)
{
if (val[1] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
{
val[1] |= ((HOST_WIDE_INT) -1) << bitpos;
val[0] = -1;
}
}
else if (bitpos == HOST_BITS_PER_WIDE_INT)
{
if (val[1] < 0)
val[0] = -1;
}
else if (val[0] & (((HOST_WIDE_INT) 1)
<< (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
val[0] |= ((HOST_WIDE_INT) -1)
<< (bitpos - HOST_BITS_PER_WIDE_INT);
}
value = build_int_cst_wide (type, val[1], val[0]);
add_pending_init (purpose, value);
}
constructor_incremental = 0;
}
static tree
find_init_member (tree field)
{
struct init_node *p;
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
if (constructor_incremental
&& tree_int_cst_lt (field, constructor_unfilled_index))
set_nonincremental_init ();
p = constructor_pending_elts;
while (p)
{
if (tree_int_cst_lt (field, p->purpose))
p = p->left;
else if (tree_int_cst_lt (p->purpose, field))
p = p->right;
else
return p->value;
}
}
else if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
tree bitpos = bit_position (field);
if (constructor_incremental
&& (!constructor_unfilled_fields
|| tree_int_cst_lt (bitpos,
bit_position (constructor_unfilled_fields))))
set_nonincremental_init ();
p = constructor_pending_elts;
while (p)
{
if (field == p->purpose)
return p->value;
else if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
p = p->left;
else
p = p->right;
}
}
else if (TREE_CODE (constructor_type) == UNION_TYPE)
{
if (!VEC_empty (constructor_elt, constructor_elements)
&& (VEC_last (constructor_elt, constructor_elements)->index
== field))
return VEC_last (constructor_elt, constructor_elements)->value;
}
return 0;
}
static void
output_init_element (tree value, bool strict_string, tree type, tree field,
int pending)
{
constructor_elt *celt;
if (type == error_mark_node || value == error_mark_node)
{
constructor_erroneous = 1;
return;
}
if (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
&& (TREE_CODE (value) == STRING_CST
|| TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
&& !(TREE_CODE (value) == STRING_CST
&& TREE_CODE (type) == ARRAY_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (type)))
&& !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
TYPE_MAIN_VARIANT (type)))
value = array_to_pointer_conversion (value);
if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
&& require_constant_value && !flag_isoc99 && pending)
{
tree decl = COMPOUND_LITERAL_EXPR_DECL (value);
value = DECL_INITIAL (decl);
}
if (value == error_mark_node)
constructor_erroneous = 1;
else if (!TREE_CONSTANT (value))
constructor_constant = 0;
else if (!initializer_constant_valid_p (value, TREE_TYPE (value))
|| ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& DECL_C_BIT_FIELD (field)
&& TREE_CODE (value) != INTEGER_CST))
constructor_simple = 0;
if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
{
if (require_constant_value)
{
error_init ("initializer element is not constant");
value = error_mark_node;
}
else if (require_constant_elements)
pedwarn ("initializer element is not computable at load time");
}
if (field
&& (TREE_TYPE (field) == error_mark_node
|| (COMPLETE_TYPE_P (TREE_TYPE (field))
&& integer_zerop (TYPE_SIZE (TREE_TYPE (field)))
&& (TREE_CODE (constructor_type) == ARRAY_TYPE
|| TREE_CHAIN (field)))))
return;
value = digest_init (type, value, strict_string, require_constant_value);
if (value == error_mark_node)
{
constructor_erroneous = 1;
return;
}
if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& (!constructor_incremental
|| !tree_int_cst_equal (field, constructor_unfilled_index)))
{
if (constructor_incremental
&& tree_int_cst_lt (field, constructor_unfilled_index))
set_nonincremental_init ();
add_pending_init (field, value);
return;
}
else if (TREE_CODE (constructor_type) == RECORD_TYPE
&& (!constructor_incremental
|| field != constructor_unfilled_fields))
{
if (constructor_incremental)
{
if (!constructor_unfilled_fields)
set_nonincremental_init ();
else
{
tree bitpos, unfillpos;
bitpos = bit_position (field);
unfillpos = bit_position (constructor_unfilled_fields);
if (tree_int_cst_lt (bitpos, unfillpos))
set_nonincremental_init ();
}
}
add_pending_init (field, value);
return;
}
else if (TREE_CODE (constructor_type) == UNION_TYPE
&& !VEC_empty (constructor_elt, constructor_elements))
{
if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
constructor_elements)->value))
warning_init ("initialized field with side-effects overwritten");
else if (warn_override_init)
warning_init ("initialized field overwritten");
constructor_elements = 0;
}
celt = VEC_safe_push (constructor_elt, gc, constructor_elements, NULL);
celt->index = field;
celt->value = value;
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
constructor_unfilled_index
= size_binop (PLUS_EXPR, constructor_unfilled_index,
bitsize_one_node);
else if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
constructor_unfilled_fields
= TREE_CHAIN (constructor_unfilled_fields);
while (constructor_unfilled_fields != 0
&& DECL_C_BIT_FIELD (constructor_unfilled_fields)
&& DECL_NAME (constructor_unfilled_fields) == 0)
constructor_unfilled_fields =
TREE_CHAIN (constructor_unfilled_fields);
}
else if (TREE_CODE (constructor_type) == UNION_TYPE)
constructor_unfilled_fields = 0;
if (pending)
output_pending_init_elements (0);
}
static void
output_pending_init_elements (int all)
{
struct init_node *elt = constructor_pending_elts;
tree next;
retry:
next = 0;
while (elt)
{
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
if (tree_int_cst_equal (elt->purpose,
constructor_unfilled_index))
output_init_element (elt->value, true,
TREE_TYPE (constructor_type),
constructor_unfilled_index, 0);
else if (tree_int_cst_lt (constructor_unfilled_index,
elt->purpose))
{
if (elt->left)
elt = elt->left;
else
{
next = elt->purpose;
break;
}
}
else
{
if (elt->right)
elt = elt->right;
else
{
while (elt->parent && elt->parent->right == elt)
elt = elt->parent;
elt = elt->parent;
if (elt && tree_int_cst_lt (constructor_unfilled_index,
elt->purpose))
{
next = elt->purpose;
break;
}
}
}
}
else if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
tree ctor_unfilled_bitpos, elt_bitpos;
if (constructor_unfilled_fields == 0)
break;
ctor_unfilled_bitpos = bit_position (constructor_unfilled_fields);
elt_bitpos = bit_position (elt->purpose);
if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
{
constructor_unfilled_fields = elt->purpose;
output_init_element (elt->value, true, TREE_TYPE (elt->purpose),
elt->purpose, 0);
}
else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
{
if (elt->left)
elt = elt->left;
else
{
next = elt->purpose;
break;
}
}
else
{
if (elt->right)
elt = elt->right;
else
{
while (elt->parent && elt->parent->right == elt)
elt = elt->parent;
elt = elt->parent;
if (elt
&& (tree_int_cst_lt (ctor_unfilled_bitpos,
bit_position (elt->purpose))))
{
next = elt->purpose;
break;
}
}
}
}
}
if (!(all && next != 0))
return;
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
constructor_unfilled_fields = next;
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
constructor_unfilled_index = next;
goto retry;
}
void
process_init_element (struct c_expr value)
{
tree orig_value = value.value;
int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
bool strict_string = value.original_code == STRING_CST;
designator_depth = 0;
designator_erroneous = 0;
if (string_flag
&& constructor_type
&& TREE_CODE (constructor_type) == ARRAY_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (constructor_type))
&& integer_zerop (constructor_unfilled_index))
{
if (constructor_stack->replacement_value.value)
error_init ("excess elements in char array initializer");
constructor_stack->replacement_value = value;
return;
}
if (constructor_stack->replacement_value.value != 0)
{
error_init ("excess elements in struct initializer");
return;
}
if (constructor_type == 0)
return;
while (constructor_stack->implicit)
{
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
process_init_element (pop_init_level (1));
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& (constructor_max_index == 0
|| tree_int_cst_lt (constructor_max_index,
constructor_index)))
process_init_element (pop_init_level (1));
else
break;
}
if (constructor_range_stack)
{
if (TREE_CODE (value.value) != COMPOUND_LITERAL_EXPR
|| !require_constant_value
|| flag_isoc99)
value.value = save_expr (value.value);
}
while (1)
{
if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
tree fieldtype;
enum tree_code fieldcode;
if (constructor_fields == 0)
{
pedwarn_init ("excess elements in struct initializer");
break;
}
fieldtype = TREE_TYPE (constructor_fields);
if (fieldtype != error_mark_node)
fieldtype = TYPE_MAIN_VARIANT (fieldtype);
fieldcode = TREE_CODE (fieldtype);
if (fieldcode == ARRAY_TYPE
&& !require_constant_value
&& TYPE_SIZE (fieldtype) == NULL_TREE
&& TREE_CHAIN (constructor_fields) == NULL_TREE)
{
error_init ("non-static initialization of a flexible array member");
break;
}
if (value.value != 0
&& fieldcode == ARRAY_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (fieldtype))
&& string_flag)
value.value = orig_value;
else if (value.value != 0
&& value.value != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
|| fieldcode == UNION_TYPE))
{
push_init_level (1);
continue;
}
if (value.value)
{
push_member_name (constructor_fields);
output_init_element (value.value, strict_string,
fieldtype, constructor_fields, 1);
RESTORE_SPELLING_DEPTH (constructor_depth);
}
else
{
if (DECL_SIZE (constructor_fields))
constructor_bit_index
= size_binop (PLUS_EXPR,
bit_position (constructor_fields),
DECL_SIZE (constructor_fields));
if (constructor_unfilled_fields == constructor_fields)
{
constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
while (constructor_unfilled_fields != 0
&& DECL_C_BIT_FIELD (constructor_unfilled_fields)
&& DECL_NAME (constructor_unfilled_fields) == 0)
constructor_unfilled_fields =
TREE_CHAIN (constructor_unfilled_fields);
}
}
constructor_fields = TREE_CHAIN (constructor_fields);
while (constructor_fields != 0
&& DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
constructor_fields = TREE_CHAIN (constructor_fields);
}
else if (TREE_CODE (constructor_type) == UNION_TYPE)
{
tree fieldtype;
enum tree_code fieldcode;
if (constructor_fields == 0)
{
pedwarn_init ("excess elements in union initializer");
break;
}
fieldtype = TREE_TYPE (constructor_fields);
if (fieldtype != error_mark_node)
fieldtype = TYPE_MAIN_VARIANT (fieldtype);
fieldcode = TREE_CODE (fieldtype);
if (!in_system_header && !constructor_designated
&& !(value.value && (integer_zerop (value.value)
|| real_zerop (value.value))))
warning (OPT_Wtraditional, "traditional C rejects initialization "
"of unions");
if (value.value != 0
&& fieldcode == ARRAY_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (fieldtype))
&& string_flag)
value.value = orig_value;
else if (value.value != 0
&& value.value != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
|| fieldcode == UNION_TYPE))
{
push_init_level (1);
continue;
}
if (value.value)
{
push_member_name (constructor_fields);
output_init_element (value.value, strict_string,
fieldtype, constructor_fields, 1);
RESTORE_SPELLING_DEPTH (constructor_depth);
}
else
{
constructor_bit_index = DECL_SIZE (constructor_fields);
constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
}
constructor_fields = 0;
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
enum tree_code eltcode = TREE_CODE (elttype);
if (value.value != 0
&& eltcode == ARRAY_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (elttype))
&& string_flag)
value.value = orig_value;
else if (value.value != 0
&& value.value != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype
&& (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
|| eltcode == UNION_TYPE))
{
push_init_level (1);
continue;
}
if (constructor_max_index != 0
&& (tree_int_cst_lt (constructor_max_index, constructor_index)
|| integer_all_onesp (constructor_max_index)))
{
pedwarn_init ("excess elements in array initializer");
break;
}
if (value.value)
{
push_array_bounds (tree_low_cst (constructor_index, 1));
output_init_element (value.value, strict_string,
elttype, constructor_index, 1);
RESTORE_SPELLING_DEPTH (constructor_depth);
}
constructor_index
= size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
if (!value.value)
constructor_unfilled_index = constructor_index;
}
else if (TREE_CODE (constructor_type) == VECTOR_TYPE)
{
tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
if (tree_int_cst_lt (constructor_max_index, constructor_index))
{
pedwarn_init ("excess elements in vector initializer");
break;
}
if (value.value)
output_init_element (value.value, strict_string,
elttype, constructor_index, 1);
constructor_index
= size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
if (!value.value)
constructor_unfilled_index = constructor_index;
}
else if (constructor_type != error_mark_node
&& constructor_fields == 0)
{
pedwarn_init ("excess elements in scalar initializer");
break;
}
else
{
if (value.value)
output_init_element (value.value, strict_string,
constructor_type, NULL_TREE, 1);
constructor_fields = 0;
}
if (constructor_range_stack)
{
struct constructor_range_stack *p, *range_stack;
int finish = 0;
range_stack = constructor_range_stack;
constructor_range_stack = 0;
while (constructor_stack != range_stack->stack)
{
gcc_assert (constructor_stack->implicit);
process_init_element (pop_init_level (1));
}
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));
}
p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node);
if (tree_int_cst_equal (p->index, p->range_end) && !p->prev)
finish = 1;
while (1)
{
constructor_index = p->index;
constructor_fields = p->fields;
if (finish && p->range_end && p->index == p->range_start)
{
finish = 0;
p->prev = 0;
}
p = p->next;
if (!p)
break;
push_init_level (2);
p->stack = constructor_stack;
if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
p->index = p->range_start;
}
if (!finish)
constructor_range_stack = range_stack;
continue;
}
break;
}
constructor_range_stack = 0;
}
tree
build_asm_stmt (tree cv_qualifier, tree args)
{
if (!ASM_VOLATILE_P (args) && cv_qualifier)
ASM_VOLATILE_P (args) = 1;
return add_stmt (args);
}
tree
build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
bool simple)
{
tree tail;
tree args;
int i;
const char *constraint;
const char **oconstraints;
bool allows_mem, allows_reg, is_inout;
int ninputs, noutputs;
ninputs = list_length (inputs);
noutputs = list_length (outputs);
oconstraints = (const char **) alloca (noutputs * sizeof (const char *));
string = resolve_asm_operand_names (string, outputs, inputs);
for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail))
{
tree output = TREE_VALUE (tail);
STRIP_NOPS (output);
if (!lvalue_or_else (output, lv_asm))
output = error_mark_node;
if (output != error_mark_node
&& (TREE_READONLY (output)
|| TYPE_READONLY (TREE_TYPE (output))
|| ((TREE_CODE (TREE_TYPE (output)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (output)) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (TREE_TYPE (output)))))
readonly_error (output, lv_asm);
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
oconstraints[i] = constraint;
if (parse_output_constraint (&constraint, i, ninputs, noutputs,
&allows_mem, &allows_reg, &is_inout))
{
if (!allows_reg && !c_mark_addressable (output))
output = error_mark_node;
}
else
output = error_mark_node;
TREE_VALUE (tail) = output;
}
for (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (tail))
{
tree input;
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
input = TREE_VALUE (tail);
if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
oconstraints, &allows_mem, &allows_reg))
{
if (!allows_reg && allows_mem)
{
STRIP_NOPS (input);
if (!c_mark_addressable (input))
input = error_mark_node;
}
}
else
input = error_mark_node;
TREE_VALUE (tail) = input;
}
args = build_stmt (ASM_EXPR, string, outputs, inputs, clobbers);
ASM_INPUT_P (args) = simple;
ASM_VOLATILE_P (args) = (noutputs == 0);
return args;
}
tree
c_finish_goto_label (tree label)
{
tree decl = lookup_label (label);
if (!decl)
return NULL_TREE;
if (C_DECL_UNJUMPABLE_STMT_EXPR (decl))
{
error ("jump into statement expression");
return NULL_TREE;
}
if (C_DECL_UNJUMPABLE_VM (decl))
{
error ("jump into scope of identifier with variably modified type");
return NULL_TREE;
}
if (!C_DECL_UNDEFINABLE_STMT_EXPR (decl))
{
struct c_label_list *nlist;
nlist = XOBNEW (&parser_obstack, struct c_label_list);
nlist->next = label_context_stack_se->labels_used;
nlist->label = decl;
label_context_stack_se->labels_used = nlist;
}
if (!C_DECL_UNDEFINABLE_VM (decl))
{
struct c_label_list *nlist;
nlist = XOBNEW (&parser_obstack, struct c_label_list);
nlist->next = label_context_stack_vm->labels_used;
nlist->label = decl;
label_context_stack_vm->labels_used = nlist;
}
TREE_USED (decl) = 1;
return add_stmt (build1 (GOTO_EXPR, void_type_node, decl));
}
tree
c_finish_goto_ptr (tree expr)
{
if (pedantic)
pedwarn ("ISO C forbids %<goto *expr;%>");
expr = convert (ptr_type_node, expr);
return add_stmt (build1 (GOTO_EXPR, void_type_node, expr));
}
tree
c_finish_return (tree retval)
{
tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)), ret_stmt;
bool no_warning = false;
if (TREE_THIS_VOLATILE (current_function_decl))
warning (0, "function declared %<noreturn%> has a %<return%> statement");
if (!retval)
{
current_function_returns_null = 1;
if ((warn_return_type || flag_isoc99)
&& valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
{
pedwarn_c99 ("%<return%> with no value, in "
"function returning non-void");
no_warning = true;
}
}
else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
{
current_function_returns_null = 1;
if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
pedwarn ("%<return%> with a value, in function returning void");
}
else
{
tree t = convert_for_assignment (valtype, retval, ic_return,
NULL_TREE, NULL_TREE, 0);
tree res = DECL_RESULT (current_function_decl);
tree inner;
current_function_returns_value = 1;
if (t == error_mark_node)
return NULL_TREE;
inner = t = convert (TREE_TYPE (res), t);
while (1)
{
switch (TREE_CODE (inner))
{
case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR:
case PLUS_EXPR:
inner = TREE_OPERAND (inner, 0);
continue;
case MINUS_EXPR:
{
tree op1 = TREE_OPERAND (inner, 1);
while (!POINTER_TYPE_P (TREE_TYPE (op1))
&& (TREE_CODE (op1) == NOP_EXPR
|| TREE_CODE (op1) == NON_LVALUE_EXPR
|| TREE_CODE (op1) == CONVERT_EXPR))
op1 = TREE_OPERAND (op1, 0);
if (POINTER_TYPE_P (TREE_TYPE (op1)))
break;
inner = TREE_OPERAND (inner, 0);
continue;
}
case ADDR_EXPR:
inner = TREE_OPERAND (inner, 0);
while (REFERENCE_CLASS_P (inner)
&& TREE_CODE (inner) != INDIRECT_REF)
inner = TREE_OPERAND (inner, 0);
if (DECL_P (inner)
&& !DECL_EXTERNAL (inner)
&& !TREE_STATIC (inner)
&& DECL_CONTEXT (inner) == current_function_decl)
warning (0, "function returns address of local variable");
break;
default:
break;
}
break;
}
retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t);
}
ret_stmt = build_stmt (RETURN_EXPR, retval);
TREE_NO_WARNING (ret_stmt) |= no_warning;
return add_stmt (ret_stmt);
}
struct c_switch {
tree switch_expr;
tree orig_type;
splay_tree cases;
unsigned int blocked_stmt_expr;
unsigned int blocked_vm;
struct c_switch *next;
};
struct c_switch *c_switch_stack;
tree
c_start_case (tree exp)
{
tree orig_type = error_mark_node;
struct c_switch *cs;
if (exp != error_mark_node)
{
orig_type = TREE_TYPE (exp);
if (!INTEGRAL_TYPE_P (orig_type))
{
if (orig_type != error_mark_node)
{
error ("switch quantity not an integer");
orig_type = error_mark_node;
}
exp = integer_zero_node;
}
else
{
tree type = TYPE_MAIN_VARIANT (orig_type);
if (!in_system_header
&& (type == long_integer_type_node
|| type == long_unsigned_type_node))
warning (OPT_Wtraditional, "%<long%> switch expression not "
"converted to %<int%> in ISO C");
exp = default_conversion (exp);
}
}
cs = XNEW (struct c_switch);
cs->switch_expr = build3 (SWITCH_EXPR, orig_type, exp, NULL_TREE, NULL_TREE);
cs->orig_type = orig_type;
cs->cases = splay_tree_new (case_compare, NULL, NULL);
cs->blocked_stmt_expr = 0;
cs->blocked_vm = 0;
cs->next = c_switch_stack;
c_switch_stack = cs;
return add_stmt (cs->switch_expr);
}
tree
do_case (tree low_value, tree high_value)
{
tree label = NULL_TREE;
if (c_switch_stack && !c_switch_stack->blocked_stmt_expr
&& !c_switch_stack->blocked_vm)
{
label = c_add_case_label (c_switch_stack->cases,
SWITCH_COND (c_switch_stack->switch_expr),
c_switch_stack->orig_type,
low_value, high_value);
if (label == error_mark_node)
label = NULL_TREE;
}
else if (c_switch_stack && c_switch_stack->blocked_stmt_expr)
{
if (low_value)
error ("case label in statement expression not containing "
"enclosing switch statement");
else
error ("%<default%> label in statement expression not containing "
"enclosing switch statement");
}
else if (c_switch_stack && c_switch_stack->blocked_vm)
{
if (low_value)
error ("case label in scope of identifier with variably modified "
"type not containing enclosing switch statement");
else
error ("%<default%> label in scope of identifier with variably "
"modified type not containing enclosing switch statement");
}
else if (low_value)
error ("case label not within a switch statement");
else
error ("%<default%> label not within a switch statement");
return label;
}
void
c_finish_case (tree body)
{
struct c_switch *cs = c_switch_stack;
location_t switch_location;
SWITCH_BODY (cs->switch_expr) = body;
gcc_assert (!cs->blocked_stmt_expr);
if (EXPR_HAS_LOCATION (cs->switch_expr))
switch_location = EXPR_LOCATION (cs->switch_expr);
else
switch_location = input_location;
c_do_switch_warnings (cs->cases, switch_location,
TREE_TYPE (cs->switch_expr),
SWITCH_COND (cs->switch_expr));
c_switch_stack = cs->next;
splay_tree_delete (cs->cases);
XDELETE (cs);
}
void
c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
tree else_block, bool nested_if)
{
tree stmt;
if (warn_parentheses && nested_if && else_block == NULL)
{
tree inner_if = then_block;
while (1)
switch (TREE_CODE (inner_if))
{
case COND_EXPR:
goto found;
case BIND_EXPR:
inner_if = BIND_EXPR_BODY (inner_if);
break;
case STATEMENT_LIST:
inner_if = expr_last (then_block);
break;
case TRY_FINALLY_EXPR:
case TRY_CATCH_EXPR:
inner_if = TREE_OPERAND (inner_if, 0);
break;
default:
gcc_unreachable ();
}
found:
if (COND_EXPR_ELSE (inner_if))
warning (OPT_Wparentheses,
"%Hsuggest explicit braces to avoid ambiguous %<else%>",
&if_locus);
}
empty_body_warning (then_block, else_block);
stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
SET_EXPR_LOCATION (stmt, if_locus);
add_stmt (stmt);
}
void
c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
tree blab, tree clab, bool cond_is_first)
{
tree entry = NULL, exit = NULL, t;
if (cond && integer_zerop (cond))
{
if (cond_is_first)
{
t = build_and_jump (&blab);
SET_EXPR_LOCATION (t, start_locus);
add_stmt (t);
}
}
else
{
tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
exit = build_and_jump (&LABEL_EXPR_LABEL (top));
if (cond && !integer_nonzerop (cond))
{
if (cond_is_first)
{
if (incr || !clab)
{
entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
t = build_and_jump (&LABEL_EXPR_LABEL (entry));
}
else
t = build1 (GOTO_EXPR, void_type_node, clab);
SET_EXPR_LOCATION (t, start_locus);
add_stmt (t);
}
t = build_and_jump (&blab);
exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
if (cond_is_first)
SET_EXPR_LOCATION (exit, start_locus);
else
SET_EXPR_LOCATION (exit, input_location);
}
add_stmt (top);
}
if (body)
add_stmt (body);
if (clab)
add_stmt (build1 (LABEL_EXPR, void_type_node, clab));
if (incr)
add_stmt (incr);
if (entry)
add_stmt (entry);
if (exit)
add_stmt (exit);
if (blab)
add_stmt (build1 (LABEL_EXPR, void_type_node, blab));
}
tree
c_finish_bc_stmt (tree *label_p, bool is_break)
{
bool skip;
tree label = *label_p;
skip = !block_may_fallthru (cur_stmt_list);
if (!label)
{
if (!skip)
*label_p = label = create_artificial_label ();
}
else if (TREE_CODE (label) == LABEL_DECL)
;
else switch (TREE_INT_CST_LOW (label))
{
case 0:
if (is_break)
error ("break statement not within loop or switch");
else
error ("continue statement not within a loop");
return NULL_TREE;
case 1:
gcc_assert (is_break);
error ("break statement used with OpenMP for loop");
return NULL_TREE;
default:
gcc_unreachable ();
}
if (skip)
return NULL_TREE;
return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
}
static void
emit_side_effect_warnings (tree expr)
{
if (expr == error_mark_node)
;
else if (!TREE_SIDE_EFFECTS (expr))
{
if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
warning (0, "%Hstatement with no effect",
EXPR_HAS_LOCATION (expr) ? EXPR_LOCUS (expr) : &input_location);
}
else if (warn_unused_value)
warn_if_unused_value (expr, input_location);
}
tree
c_process_expr_stmt (tree expr)
{
if (!expr)
return NULL_TREE;
if (warn_sequence_point)
verify_sequence_points (expr);
if (TREE_TYPE (expr) != error_mark_node
&& !COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (expr))
&& TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
error ("expression statement has incomplete type");
if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
&& (extra_warnings || warn_unused_value))
emit_side_effect_warnings (expr);
if (DECL_P (expr) || CONSTANT_CLASS_P (expr))
expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
if (EXPR_P (expr))
SET_EXPR_LOCATION (expr, input_location);
return expr;
}
tree
c_finish_expr_stmt (tree expr)
{
if (expr)
return add_stmt (c_process_expr_stmt (expr));
else
return NULL;
}
tree
c_begin_stmt_expr (void)
{
tree ret;
struct c_label_context_se *nstack;
struct c_label_list *glist;
keep_next_level ();
ret = c_begin_compound_stmt (true);
if (c_switch_stack)
{
c_switch_stack->blocked_stmt_expr++;
gcc_assert (c_switch_stack->blocked_stmt_expr != 0);
}
for (glist = label_context_stack_se->labels_used;
glist != NULL;
glist = glist->next)
{
C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 1;
}
nstack = XOBNEW (&parser_obstack, struct c_label_context_se);
nstack->labels_def = NULL;
nstack->labels_used = NULL;
nstack->next = label_context_stack_se;
label_context_stack_se = nstack;
STATEMENT_LIST_STMT_EXPR (ret) = 1;
return ret;
}
tree
c_finish_stmt_expr (tree body)
{
tree last, type, tmp, val;
tree *last_p;
struct c_label_list *dlist, *glist, *glist_prev = NULL;
body = c_end_compound_stmt (body, true);
if (c_switch_stack)
{
gcc_assert (c_switch_stack->blocked_stmt_expr != 0);
c_switch_stack->blocked_stmt_expr--;
}
for (dlist = label_context_stack_se->labels_def;
dlist != NULL;
dlist = dlist->next)
{
C_DECL_UNJUMPABLE_STMT_EXPR (dlist->label) = 1;
}
for (glist = label_context_stack_se->next->labels_used;
glist != NULL;
glist = glist->next)
{
C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 0;
glist_prev = glist;
}
if (glist_prev != NULL)
glist_prev->next = label_context_stack_se->labels_used;
else
label_context_stack_se->next->labels_used
= label_context_stack_se->labels_used;
label_context_stack_se = label_context_stack_se->next;
last_p = &BIND_EXPR_BODY (body);
last = BIND_EXPR_BODY (body);
continue_searching:
if (TREE_CODE (last) == STATEMENT_LIST)
{
tree_stmt_iterator i;
if (!TREE_SIDE_EFFECTS (last))
return body;
if (extra_warnings || warn_unused_value)
{
for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i))
emit_side_effect_warnings (tsi_stmt (i));
}
else
i = tsi_last (last);
last_p = tsi_stmt_ptr (i);
last = *last_p;
}
if (TREE_CODE (last) == TRY_FINALLY_EXPR
|| TREE_CODE (last) == TRY_CATCH_EXPR)
{
last_p = &TREE_OPERAND (last, 0);
last = *last_p;
goto continue_searching;
}
if (last == error_mark_node
|| (last == BIND_EXPR_BODY (body)
&& BIND_EXPR_VARS (body) == NULL))
{
if (EXPR_P (last))
TREE_NO_WARNING (last) = 1;
return last;
}
type = TREE_TYPE (last);
if (!type || VOID_TYPE_P (type))
return body;
tmp = create_tmp_var_raw (type, NULL);
val = last;
if (TREE_CODE (val) == NOP_EXPR
&& TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0)))
val = TREE_OPERAND (val, 0);
*last_p = build2 (MODIFY_EXPR, void_type_node, tmp, val);
SET_EXPR_LOCUS (*last_p, EXPR_LOCUS (last));
return build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
}
void
c_begin_vm_scope (unsigned int scope)
{
struct c_label_context_vm *nstack;
struct c_label_list *glist;
gcc_assert (scope > 0);
if (label_context_stack_vm == NULL)
return;
if (c_switch_stack && !c_switch_stack->blocked_vm)
c_switch_stack->blocked_vm = scope;
for (glist = label_context_stack_vm->labels_used;
glist != NULL;
glist = glist->next)
{
C_DECL_UNDEFINABLE_VM (glist->label) = 1;
}
nstack = XOBNEW (&parser_obstack, struct c_label_context_vm);
nstack->labels_def = NULL;
nstack->labels_used = NULL;
nstack->scope = scope;
nstack->next = label_context_stack_vm;
label_context_stack_vm = nstack;
}
void
c_end_vm_scope (unsigned int scope)
{
if (label_context_stack_vm == NULL)
return;
if (c_switch_stack && c_switch_stack->blocked_vm == scope)
c_switch_stack->blocked_vm = 0;
while (label_context_stack_vm->scope == scope)
{
struct c_label_list *dlist, *glist, *glist_prev = NULL;
for (dlist = label_context_stack_vm->labels_def;
dlist != NULL;
dlist = dlist->next)
{
C_DECL_UNJUMPABLE_VM (dlist->label) = 1;
}
for (glist = label_context_stack_vm->next->labels_used;
glist != NULL;
glist = glist->next)
{
C_DECL_UNDEFINABLE_VM (glist->label) = 0;
glist_prev = glist;
}
if (glist_prev != NULL)
glist_prev->next = label_context_stack_vm->labels_used;
else
label_context_stack_vm->next->labels_used
= label_context_stack_vm->labels_used;
label_context_stack_vm = label_context_stack_vm->next;
}
}
tree
c_begin_compound_stmt (bool do_scope)
{
tree stmt = push_stmt_list ();
if (do_scope)
push_scope ();
return stmt;
}
tree
c_end_compound_stmt (tree stmt, bool do_scope)
{
tree block = NULL;
if (do_scope)
{
if (c_dialect_objc ())
objc_clear_super_receiver ();
block = pop_scope ();
}
stmt = pop_stmt_list (stmt);
stmt = c_build_bind_expr (block, stmt);
if (cur_stmt_list
&& STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
&& TREE_CODE (stmt) != BIND_EXPR)
{
stmt = build3 (BIND_EXPR, void_type_node, NULL, stmt, NULL);
TREE_SIDE_EFFECTS (stmt) = 1;
}
return stmt;
}
void
push_cleanup (tree ARG_UNUSED (decl), tree cleanup, bool eh_only)
{
enum tree_code code;
tree stmt, list;
bool stmt_expr;
code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR;
stmt = build_stmt (code, NULL, cleanup);
add_stmt (stmt);
stmt_expr = STATEMENT_LIST_STMT_EXPR (cur_stmt_list);
list = push_stmt_list ();
TREE_OPERAND (stmt, 0) = list;
STATEMENT_LIST_STMT_EXPR (list) = stmt_expr;
}
tree
build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
int convert_p)
{
tree type0, type1;
enum tree_code code0, code1;
tree op0, op1;
const char *invalid_op_diag;
enum tree_code resultcode = code;
tree result_type = NULL;
int converted = 0;
tree build_type = 0;
tree final_type = 0;
int shorten = 0;
int short_compare = 0;
int short_shift = 0;
int common = 0;
bool objc_ok;
if (convert_p)
{
op0 = default_conversion (orig_op0);
op1 = default_conversion (orig_op1);
}
else
{
op0 = orig_op0;
op1 = orig_op1;
}
type0 = TREE_TYPE (op0);
type1 = TREE_TYPE (op1);
code0 = TREE_CODE (type0);
code1 = TREE_CODE (type1);
STRIP_TYPE_NOPS (op0);
STRIP_TYPE_NOPS (op1);
if (code0 == ERROR_MARK || code1 == ERROR_MARK)
return error_mark_node;
if ((invalid_op_diag
= targetm.invalid_binary_op (code, type0, type1)))
{
error (invalid_op_diag);
return error_mark_node;
}
objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
switch (code)
{
case PLUS_EXPR:
if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
return pointer_int_sum (PLUS_EXPR, op0, op1);
else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
return pointer_int_sum (PLUS_EXPR, op1, op0);
else
common = 1;
break;
case MINUS_EXPR:
if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
&& comp_target_types (type0, type1))
return pointer_diff (op0, op1);
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
return pointer_int_sum (MINUS_EXPR, op0, op1);
else
common = 1;
break;
case MULT_EXPR:
common = 1;
break;
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
if (skip_evaluation == 0 && integer_zerop (op1))
warning (OPT_Wdiv_by_zero, "division by zero");
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
|| code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|| code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
{
enum tree_code tcode0 = code0, tcode1 = code1;
if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
tcode0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
if (!(tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
else
shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0))
|| (TREE_CODE (op1) == INTEGER_CST
&& !integer_all_onesp (op1)));
common = 1;
}
break;
case BIT_AND_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
shorten = -1;
else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
common = 1;
break;
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
if (skip_evaluation == 0 && integer_zerop (op1))
warning (OPT_Wdiv_by_zero, "division by zero");
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0))
|| (TREE_CODE (op1) == INTEGER_CST
&& !integer_all_onesp (op1)));
common = 1;
}
break;
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE
|| code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
&& (code1 == INTEGER_TYPE || code1 == POINTER_TYPE
|| code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
{
result_type = integer_type_node;
op0 = c_common_truthvalue_conversion (op0);
op1 = c_common_truthvalue_conversion (op1);
converted = 1;
}
break;
case RSHIFT_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
{
if (tree_int_cst_sgn (op1) < 0)
warning (0, "right shift count is negative");
else
{
if (!integer_zerop (op1))
short_shift = 1;
if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
warning (0, "right shift count >= width of type");
}
}
result_type = type0;
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = convert (integer_type_node, op1);
converted = 1;
}
break;
case LSHIFT_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
{
if (tree_int_cst_sgn (op1) < 0)
warning (0, "left shift count is negative");
else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
warning (0, "left shift count >= width of type");
}
result_type = type0;
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = convert (integer_type_node, op1);
converted = 1;
}
break;
case EQ_EXPR:
case NE_EXPR:
if (code0 == REAL_TYPE || code1 == REAL_TYPE)
warning (OPT_Wfloat_equal,
"comparing floating point with == or != is unsafe");
build_type = integer_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
|| code0 == COMPLEX_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|| code1 == COMPLEX_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
tree tt0 = TREE_TYPE (type0);
tree tt1 = TREE_TYPE (type1);
if (comp_target_types (type0, type1))
result_type = common_pointer_type (type0, type1);
else if (VOID_TYPE_P (tt0))
{
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 && !null_pointer_constant_p (orig_op1)
&& TREE_CODE (tt0) == FUNCTION_TYPE)
pedwarn ("ISO C forbids comparison of %<void *%>"
" with function pointer");
}
else
if (!objc_ok)
pedwarn ("comparison of distinct pointer types lacks a cast");
if (result_type == NULL_TREE)
result_type = ptr_type_node;
}
else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
{
if (TREE_CODE (op0) == ADDR_EXPR
&& DECL_P (TREE_OPERAND (op0, 0))
&& (TREE_CODE (TREE_OPERAND (op0, 0)) == PARM_DECL
|| TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL
|| !DECL_WEAK (TREE_OPERAND (op0, 0))))
warning (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_P (TREE_OPERAND (op1, 0))
&& (TREE_CODE (TREE_OPERAND (op1, 0)) == PARM_DECL
|| TREE_CODE (TREE_OPERAND (op1, 0)) == LABEL_DECL
|| !DECL_WEAK (TREE_OPERAND (op1, 0))))
warning (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;
pedwarn ("comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
pedwarn ("comparison between pointer and integer");
}
break;
case LE_EXPR:
case GE_EXPR:
case LT_EXPR:
case GT_EXPR:
build_type = integer_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
if (comp_target_types (type0, type1))
{
result_type = common_pointer_type (type0, type1);
if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
!= !COMPLETE_TYPE_P (TREE_TYPE (type1)))
pedwarn ("comparison of complete and incomplete pointers");
else if (pedantic
&& TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
pedwarn ("ISO C forbids ordered comparisons of pointers to functions");
}
else
{
result_type = ptr_type_node;
pedwarn ("comparison of distinct pointer types lacks a cast");
}
}
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 && null_pointer_constant_p (orig_op0))
{
result_type = type1;
if (pedantic)
pedwarn ("ordered comparison of pointer with integer zero");
}
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
pedwarn ("comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
pedwarn ("comparison between pointer and integer");
}
break;
default:
gcc_unreachable ();
}
if (code0 == ERROR_MARK || code1 == ERROR_MARK)
return error_mark_node;
if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
&& (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1))
|| !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
TREE_TYPE (type1))))
{
binary_op_error (code);
return error_mark_node;
}
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
|| code0 == VECTOR_TYPE)
&&
(code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
|| code1 == VECTOR_TYPE))
{
int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
if (shorten || common || short_compare)
result_type = c_common_type (type0, type1);
if (shorten && none_complex)
{
int unsigned0, unsigned1;
tree arg0, arg1;
int uns;
tree type;
op0 = convert (result_type, op0);
op1 = convert (result_type, op1);
arg0 = get_narrower (op0, &unsigned0);
arg1 = get_narrower (op1, &unsigned1);
uns = TYPE_UNSIGNED (result_type);
final_type = result_type;
if ((TYPE_PRECISION (TREE_TYPE (op0))
== TYPE_PRECISION (TREE_TYPE (arg0)))
&& TREE_TYPE (op0) != final_type)
unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
if ((TYPE_PRECISION (TREE_TYPE (op1))
== TYPE_PRECISION (TREE_TYPE (arg1)))
&& TREE_TYPE (op1) != final_type)
unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
if (shorten == -1)
uns = unsigned0;
if ((TYPE_PRECISION (TREE_TYPE (arg0))
< TYPE_PRECISION (result_type))
&& (TYPE_PRECISION (TREE_TYPE (arg1))
== TYPE_PRECISION (TREE_TYPE (arg0)))
&& unsigned0 == unsigned1
&& (unsigned0 || !uns))
result_type
= c_common_signed_or_unsigned_type
(unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
else if (TREE_CODE (arg0) == INTEGER_CST
&& (unsigned1 || !uns)
&& (TYPE_PRECISION (TREE_TYPE (arg1))
< TYPE_PRECISION (result_type))
&& (type
= c_common_signed_or_unsigned_type (unsigned1,
TREE_TYPE (arg1)),
int_fits_type_p (arg0, type)))
result_type = type;
else if (TREE_CODE (arg1) == INTEGER_CST
&& (unsigned0 || !uns)
&& (TYPE_PRECISION (TREE_TYPE (arg0))
< TYPE_PRECISION (result_type))
&& (type
= c_common_signed_or_unsigned_type (unsigned0,
TREE_TYPE (arg0)),
int_fits_type_p (arg1, type)))
result_type = type;
}
if (short_shift)
{
int unsigned_arg;
tree arg0 = get_narrower (op0, &unsigned_arg);
final_type = result_type;
if (arg0 == op0 && final_type == TREE_TYPE (op0))
unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0));
if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
&& compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
&& (!TYPE_UNSIGNED (final_type) || unsigned_arg))
{
result_type
= c_common_signed_or_unsigned_type (unsigned_arg,
TREE_TYPE (arg0));
if (TREE_TYPE (op0) != result_type)
op0 = convert (result_type, op0);
converted = 1;
}
}
if (short_compare)
{
tree xop0 = op0, xop1 = op1, xresult_type = result_type;
enum tree_code xresultcode = resultcode;
tree val
= shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
if (val != 0)
return val;
op0 = xop0, op1 = xop1;
converted = 1;
resultcode = xresultcode;
if (warn_sign_compare && skip_evaluation == 0)
{
int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
int unsignedp0, unsignedp1;
tree primop0 = get_narrower (op0, &unsignedp0);
tree primop1 = get_narrower (op1, &unsignedp1);
xop0 = orig_op0;
xop1 = orig_op1;
STRIP_TYPE_NOPS (xop0);
STRIP_TYPE_NOPS (xop1);
if (!TYPE_UNSIGNED (result_type))
;
else if (op0_signed == op1_signed)
;
else
{
tree sop, uop;
bool ovf;
if (op0_signed)
sop = xop0, uop = xop1;
else
sop = xop1, uop = xop0;
if (tree_expr_nonnegative_warnv_p (sop, &ovf))
;
else if (TREE_CODE (uop) == INTEGER_CST
&& (resultcode == EQ_EXPR || resultcode == NE_EXPR)
&& int_fits_type_p
(uop, c_common_signed_type (result_type)))
;
else if (TREE_CODE (uop) == INTEGER_CST
&& TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
&& int_fits_type_p
(TYPE_MAX_VALUE (TREE_TYPE (uop)),
c_common_signed_type (result_type)))
;
else
warning (0, "comparison between signed and unsigned");
}
if ((TREE_CODE (primop0) == BIT_NOT_EXPR)
!= (TREE_CODE (primop1) == BIT_NOT_EXPR))
{
if (TREE_CODE (primop0) == BIT_NOT_EXPR)
primop0 = get_narrower (TREE_OPERAND (primop0, 0),
&unsignedp0);
else
primop1 = get_narrower (TREE_OPERAND (primop1, 0),
&unsignedp1);
if (host_integerp (primop0, 0) || host_integerp (primop1, 0))
{
tree primop;
HOST_WIDE_INT constant, mask;
int unsignedp, bits;
if (host_integerp (primop0, 0))
{
primop = primop1;
unsignedp = unsignedp1;
constant = tree_low_cst (primop0, 0);
}
else
{
primop = primop0;
unsignedp = unsignedp0;
constant = tree_low_cst (primop1, 0);
}
bits = TYPE_PRECISION (TREE_TYPE (primop));
if (bits < TYPE_PRECISION (result_type)
&& bits < HOST_BITS_PER_WIDE_INT && unsignedp)
{
mask = (~(HOST_WIDE_INT) 0) << bits;
if ((mask & constant) != mask)
warning (0, "comparison of promoted ~unsigned with constant");
}
}
else if (unsignedp0 && unsignedp1
&& (TYPE_PRECISION (TREE_TYPE (primop0))
< TYPE_PRECISION (result_type))
&& (TYPE_PRECISION (TREE_TYPE (primop1))
< TYPE_PRECISION (result_type)))
warning (0, "comparison of promoted ~unsigned with unsigned");
}
}
}
}
if (!result_type)
{
binary_op_error (code);
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);
if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
return error_mark_node;
}
if (build_type == NULL_TREE)
build_type = result_type;
{
tree result = require_constant_value ? fold_build2_initializer (resultcode,
build_type,
op0, op1)
: fold_build2 (resultcode, build_type,
op0, op1);
if (final_type != 0)
result = convert (final_type, result);
return result;
}
}
tree
c_objc_common_truthvalue_conversion (tree expr)
{
switch (TREE_CODE (TREE_TYPE (expr)))
{
case ARRAY_TYPE:
error ("used array that cannot be converted to pointer where scalar is required");
return error_mark_node;
case RECORD_TYPE:
error ("used struct type value where scalar is required");
return error_mark_node;
case UNION_TYPE:
error ("used union type value where scalar is required");
return error_mark_node;
case FUNCTION_TYPE:
gcc_unreachable ();
default:
break;
}
return c_common_truthvalue_conversion (expr);
}
tree
c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
bool *ti ATTRIBUTE_UNUSED, bool *se)
{
if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR)
{
tree decl = COMPOUND_LITERAL_EXPR_DECL (expr);
if (!TREE_STATIC (decl))
*se = true;
return decl;
}
else
return expr;
}
tree
c_begin_omp_parallel (void)
{
tree block;
keep_next_level ();
block = c_begin_compound_stmt (true);
return block;
}
tree
c_finish_omp_parallel (tree clauses, tree block)
{
tree stmt;
block = c_end_compound_stmt (block, true);
stmt = make_node (OMP_PARALLEL);
TREE_TYPE (stmt) = void_type_node;
OMP_PARALLEL_CLAUSES (stmt) = clauses;
OMP_PARALLEL_BODY (stmt) = block;
return add_stmt (stmt);
}
tree
c_finish_omp_clauses (tree clauses)
{
bitmap_head generic_head, firstprivate_head, lastprivate_head;
tree c, t, *pc = &clauses;
const char *name;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
for (pc = &clauses, c = clauses; c ; c = *pc)
{
bool remove = false;
bool need_complete = false;
bool need_implicitly_determined = false;
switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_SHARED:
name = "shared";
need_implicitly_determined = true;
goto check_dup_generic;
case OMP_CLAUSE_PRIVATE:
name = "private";
need_complete = true;
need_implicitly_determined = true;
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
name = "reduction";
need_implicitly_determined = true;
t = OMP_CLAUSE_DECL (c);
if (AGGREGATE_TYPE_P (TREE_TYPE (t))
|| POINTER_TYPE_P (TREE_TYPE (t)))
{
error ("%qE has invalid type for %<reduction%>", t);
remove = true;
}
else if (FLOAT_TYPE_P (TREE_TYPE (t)))
{
enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c);
const char *r_name = NULL;
switch (r_code)
{
case PLUS_EXPR:
case MULT_EXPR:
case MINUS_EXPR:
break;
case BIT_AND_EXPR:
r_name = "&";
break;
case BIT_XOR_EXPR:
r_name = "^";
break;
case BIT_IOR_EXPR:
r_name = "|";
break;
case TRUTH_ANDIF_EXPR:
r_name = "&&";
break;
case TRUTH_ORIF_EXPR:
r_name = "||";
break;
default:
gcc_unreachable ();
}
if (r_name)
{
error ("%qE has invalid type for %<reduction(%s)%>",
t, r_name);
remove = true;
}
}
goto check_dup_generic;
case OMP_CLAUSE_COPYPRIVATE:
name = "copyprivate";
goto check_dup_generic;
case OMP_CLAUSE_COPYIN:
name = "copyin";
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) != VAR_DECL || !DECL_THREAD_LOCAL_P (t))
{
error ("%qE must be %<threadprivate%> for %<copyin%>", t);
remove = true;
}
goto check_dup_generic;
check_dup_generic:
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
{
error ("%qE is not a variable in clause %qs", t, name);
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&firstprivate_head, DECL_UID (t))
|| bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
{
error ("%qE appears more than once in data clauses", t);
remove = true;
}
else
bitmap_set_bit (&generic_head, DECL_UID (t));
break;
case OMP_CLAUSE_FIRSTPRIVATE:
name = "firstprivate";
t = OMP_CLAUSE_DECL (c);
need_complete = true;
need_implicitly_determined = true;
if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
{
error ("%qE is not a variable in clause %<firstprivate%>", t);
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
{
error ("%qE appears more than once in data clauses", t);
remove = true;
}
else
bitmap_set_bit (&firstprivate_head, DECL_UID (t));
break;
case OMP_CLAUSE_LASTPRIVATE:
name = "lastprivate";
t = OMP_CLAUSE_DECL (c);
need_complete = true;
need_implicitly_determined = true;
if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
{
error ("%qE is not a variable in clause %<lastprivate%>", t);
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
{
error ("%qE appears more than once in data clauses", t);
remove = true;
}
else
bitmap_set_bit (&lastprivate_head, DECL_UID (t));
break;
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
pc = &OMP_CLAUSE_CHAIN (c);
continue;
default:
gcc_unreachable ();
}
if (!remove)
{
t = OMP_CLAUSE_DECL (c);
if (need_complete)
{
t = require_complete_type (t);
if (t == error_mark_node)
remove = true;
}
if (need_implicitly_determined)
{
const char *share_name = NULL;
if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
share_name = "threadprivate";
else switch (c_omp_predetermined_sharing (t))
{
case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
break;
case OMP_CLAUSE_DEFAULT_SHARED:
share_name = "shared";
break;
case OMP_CLAUSE_DEFAULT_PRIVATE:
share_name = "private";
break;
default:
gcc_unreachable ();
}
if (share_name)
{
error ("%qE is predetermined %qs for %qs",
t, share_name, name);
remove = true;
}
}
}
if (remove)
*pc = OMP_CLAUSE_CHAIN (c);
else
pc = &OMP_CLAUSE_CHAIN (c);
}
bitmap_obstack_release (NULL);
return clauses;
}