#include "tree-iterator.h"
#include "tree-gimple.h"
+/* The level of nesting inside "__alignof__". */
+int in_alignof;
+
+/* The level of nesting inside "sizeof". */
+int in_sizeof;
+
+/* The level of nesting inside "typeof". */
+int in_typeof;
/* Nonzero if we've already printed a "missing braces around initializer"
message within this initializer. */
return;
default:
- abort ();
+ gcc_unreachable ();
}
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE)
return t2;
- if (code1 != code2)
- abort ();
+ gcc_assert (code1 == code2);
switch (code1)
{
tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
/* We should not have any type quals on arrays at all. */
- if (TYPE_QUALS (t1) || TYPE_QUALS (t2))
- abort ();
+ gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
/* Save space: see if the result is identical to one of the args. */
if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
if (t2 == error_mark_node)
return t1;
- if (TREE_CODE (t1) != POINTER_TYPE || TREE_CODE (t2) != POINTER_TYPE)
- abort ();
+ gcc_assert (TREE_CODE (t1) == POINTER_TYPE
+ && TREE_CODE (t2) == POINTER_TYPE);
/* Merge the attributes. */
attributes = targetm.merge_type_attributes (t1, t2);
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
- if (code1 != VECTOR_TYPE && code1 != COMPLEX_TYPE
- && code1 != REAL_TYPE && code1 != INTEGER_TYPE)
- abort ();
-
- if (code2 != VECTOR_TYPE && code2 != COMPLEX_TYPE
- && code2 != REAL_TYPE && code2 != INTEGER_TYPE)
- abort ();
+ 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 one type is a vector type, return that type. (How the usual
arithmetic conversions apply to the vector types extension is not
case 'd': t1 = DECL_CONTEXT (t1); break;
case 't': t1 = TYPE_CONTEXT (t1); break;
case 'x': t1 = BLOCK_SUPERCONTEXT (t1); break; /* assume block */
- default: abort ();
+ default: gcc_unreachable ();
}
while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL)
case 'd': t2 = DECL_CONTEXT (t2); break;
case 't': t2 = TYPE_CONTEXT (t2); break;
case 'x': t2 = BLOCK_SUPERCONTEXT (t2); break; /* assume block */
- default: abort ();
+ default: gcc_unreachable ();
}
return t1 == t2;
}
default:
- abort ();
+ gcc_unreachable ();
}
}
{
tree ref;
tree decl = lookup_name (id);
- tree objc_ivar = lookup_objc_ivar (id);
+ tree objc_ivar = objc_lookup_ivar (id);
if (decl && decl != error_mark_node)
{
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)
{
ref = DECL_INITIAL (ref);
return ref;
}
+/* Record details of decls possibly used inside sizeof or typeof. */
+struct maybe_used_decl
+{
+ /* The decl. */
+ tree decl;
+ /* The level seen at (in_sizeof + in_typeof). */
+ int level;
+ /* The next one at this level or above, or NULL. */
+ struct maybe_used_decl *next;
+};
+
+static struct maybe_used_decl *maybe_used_decls;
+
+/* Record that DECL, an undefined static function reference seen
+ inside sizeof or typeof, might be used if the operand of sizeof is
+ a VLA type or the operand of typeof is a variably modified
+ type. */
+
+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;
+}
+
+/* Pop the stack of decls possibly used inside sizeof or typeof. If
+ USED is false, just discard them. If it is true, mark them used
+ (if no longer inside sizeof or typeof) or move them to the next
+ level up (if still inside sizeof or typeof). */
+
+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;
+}
+
+/* Return the result of sizeof applied to EXPR. */
+
+struct c_expr
+c_expr_sizeof_expr (struct c_expr expr)
+{
+ struct c_expr ret;
+ ret.value = c_sizeof (TREE_TYPE (expr.value));
+ ret.original_code = ERROR_MARK;
+ pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
+ return ret;
+}
+
+/* Return the result of sizeof applied to T, a structure for the type
+ name passed to sizeof (rather than the type itself). */
+
+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 (C_TYPE_VARIABLE_SIZE (type));
+ return ret;
+}
+
/* Build a function call to function FUNCTION with parameters PARAMS.
PARAMS is a list--a chain of TREE_LIST nodes--in which the
TREE_VALUE of each node is a parameter-expression.
TREE_READONLY (arg),
TREE_THIS_VOLATILE (arg));
- argtype = build_pointer_type (argtype);
-
if (!c_mark_addressable (arg))
return error_mark_node;
- {
- tree addr;
-
- if (TREE_CODE (arg) == COMPONENT_REF)
- {
- tree field = TREE_OPERAND (arg, 1);
-
- addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag);
-
- if (DECL_C_BIT_FIELD (field))
- {
- error ("attempt to take address of bit-field structure member `%s'",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- return error_mark_node;
- }
+ if (TREE_CODE (arg) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
+ {
+ error ("attempt to take address of bit-field structure member `%D'",
+ TREE_OPERAND (arg, 1));
+ return error_mark_node;
+ }
- addr = fold (build2 (PLUS_EXPR, argtype,
- convert (argtype, addr),
- convert (argtype, byte_position (field))));
-
- /* If the folded PLUS_EXPR is not a constant address, wrap
- it in an ADDR_EXPR. */
- if (!TREE_CONSTANT (addr))
- addr = build1 (ADDR_EXPR, argtype, arg);
- }
- else
- addr = build1 (ADDR_EXPR, argtype, arg);
+ argtype = build_pointer_type (argtype);
+ val = build1 (ADDR_EXPR, argtype, arg);
- if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
- TREE_INVARIANT (addr) = TREE_CONSTANT (addr) = 1;
+ if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
+ TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1;
- return addr;
- }
+ return val;
default:
break;
/* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing
only in <protocol> qualifications. But when constructing cast expressions,
the protocols do matter and must be kept around. */
- if (!c_dialect_objc () || !objc_is_object_ptr (type))
- type = TYPE_MAIN_VARIANT (type);
+ 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)
{
/* Interpret a cast of expression EXPR to type TYPE. */
tree
-c_cast_expr (tree type, tree expr)
+c_cast_expr (struct c_type_name *type_name, tree expr)
{
+ tree type;
int saved_wsp = warn_strict_prototypes;
/* This avoids warnings about unprototyped casts on
integers. E.g. "#define SIG_DFL (void(*)())0". */
if (TREE_CODE (expr) == INTEGER_CST)
warn_strict_prototypes = 0;
- type = groktypename (type);
+ type = groktypename (type_name);
warn_strict_prototypes = saved_wsp;
return build_c_cast (type, expr);
return rhs;
}
/* Some types can interconvert without explicit casts. */
- else if (codel == VECTOR_TYPE
+ else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE
&& vector_types_convertible_p (type, TREE_TYPE (rhs)))
return convert (type, rhs);
/* Arithmetic types all interconvert, and enum is treated like int. */
return valid_compound_expr_initializer (TREE_OPERAND (value, 1),
endtype);
}
- else if (! TREE_CONSTANT (value)
- && ! initializer_constant_valid_p (value, endtype))
+ else if (!initializer_constant_valid_p (value, endtype))
return error_mark_node;
else
return value;
vector constructor is not constant (e.g. {1,2,3,foo()}) then punt
below and handle as a constructor. */
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))
{
inside_init = error_mark_node;
}
else if (require_constant
- && (!TREE_CONSTANT (inside_init)
- /* This test catches things like `7 / 0' which
- result in an expression for which TREE_CONSTANT
- is true, but which is not actually something
- that is a legal constant. We really should not
- be using this function, because it is a part of
- the back-end. Instead, the expression should
- already have been turned into ERROR_MARK_NODE. */
- || !initializer_constant_valid_p (inside_init,
- TREE_TYPE (inside_init))))
+ && !initializer_constant_valid_p (inside_init,
+ TREE_TYPE (inside_init)))
{
error_init ("initializer element is not constant");
inside_init = error_mark_node;
= convert_for_assignment (type, init, _("initialization"),
NULL_TREE, NULL_TREE, 0);
- if (require_constant && ! TREE_CONSTANT (inside_init))
+ /* Check to see if we have already given an error message. */
+ 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)) == 0)
+ && !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;
free (q);
}
- if (constructor_range_stack)
- abort ();
+ gcc_assert (!constructor_range_stack);
/* Pop back to the data of the outer initializer (if any). */
free (spelling_base);
while (constructor_stack->implicit)
process_init_element (pop_init_level (1));
- if (constructor_range_stack)
- abort ();
+ gcc_assert (!constructor_range_stack);
}
/* Now output all pending elements. */
already have pedwarned for empty brackets. */
if (integer_zerop (constructor_unfilled_index))
constructor_type = NULL_TREE;
- else if (! TYPE_SIZE (constructor_type))
+ 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)
if (TREE_CHAIN (constructor_fields) != NULL_TREE)
constructor_type = NULL_TREE;
}
- else
- /* Zero-length arrays are no longer special, so we should no longer
- get here. */
- abort ();
}
/* Warn when some struct elements are implicitly initialized to zero. */
if (constructor_type == 0)
return 1;
- /* If there were errors in this designator list already, bail out silently. */
+ /* If there were errors in this designator list already, bail out
+ silently. */
if (designator_errorneous)
return 1;
if (!designator_depth)
{
- if (constructor_range_stack)
- abort ();
+ gcc_assert (!constructor_range_stack);
/* Designator list starts at the level of closest explicit
braces. */
return 1;
}
- if (TREE_CODE (constructor_type) == RECORD_TYPE
- || TREE_CODE (constructor_type) == UNION_TYPE)
+ 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);
- }
- else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
- {
+ break;
+ case ARRAY_TYPE:
subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
+ break;
+ default:
+ gcc_unreachable ();
}
- else
- abort ();
subcode = TREE_CODE (subtype);
if (array && subcode != ARRAY_TYPE)
const char *p, *end;
int byte, wchar_bytes, charwidth, bitpos;
- if (TREE_CODE (constructor_type) != ARRAY_TYPE)
- abort ();
+ 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 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
- == TYPE_PRECISION (wchar_type_node))
- wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
else
- abort ();
-
+ {
+ 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);
constructor_erroneous = 1;
else if (!TREE_CONSTANT (value))
constructor_constant = 0;
- else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 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 (require_constant_value && ! TREE_CONSTANT (value))
+ if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
{
- error_init ("initializer element is not constant");
- value = error_mark_node;
+ 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");
}
- else if (require_constant_elements
- && initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
- pedwarn ("initializer element is not computable at load time");
/* If this field is empty (and not at the end of structure),
don't do anything other than checking the initializer. */
constructor_range_stack = 0;
while (constructor_stack != range_stack->stack)
{
- if (!constructor_stack->implicit)
- abort ();
+ 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)
{
- if (!constructor_stack->implicit)
- abort ();
+ gcc_assert (constructor_stack->implicit);
process_init_element (pop_init_level (1));
}
inner_if = TREE_OPERAND (inner_if, 0);
break;
default:
- abort ();
+ gcc_unreachable ();
}
found:
return result;
}
}
-
-/* Build the result of __builtin_offsetof. TYPE is the first argument to
- offsetof, i.e. a type. LIST is a tree_list that encodes component and
- array references; PURPOSE is set for the former and VALUE is set for
- the later. */
-
-tree
-build_offsetof (tree type, tree list)
-{
- tree t;
-
- /* Build "*(type *)0". */
- t = convert (build_pointer_type (type), null_pointer_node);
- t = build_indirect_ref (t, "");
-
- /* Build COMPONENT and ARRAY_REF expressions as needed. */
- for (list = nreverse (list); list ; list = TREE_CHAIN (list))
- if (TREE_PURPOSE (list))
- t = build_component_ref (t, TREE_PURPOSE (list));
- else
- t = build_array_ref (t, TREE_VALUE (list));
-
- /* Finalize the offsetof expression. For now all we need to do is take
- the address of the expression we created, and cast that to an integer
- type; this mirrors the traditional macro implementation of offsetof. */
- t = build_unary_op (ADDR_EXPR, t, 0);
- return convert (size_type_node, t);
-}