+ assert(iter != NULL);
+ }
+ }
+
+ ARR_SHRINKLEN(*stack_ptr, (int) new_top);
+}
+
+static void environment_pop_to(size_t new_top)
+{
+ stack_pop_to(&environment_stack, new_top);
+}
+
+static void label_pop_to(size_t new_top)
+{
+ stack_pop_to(&label_stack, new_top);
+}
+
+
+static int get_rank(const type_t *type)
+{
+ /* The C-standard allows promoting to int or unsigned int (see § 7.2.2
+ * and esp. footnote 108). However we can't fold constants (yet), so we
+ * can't decide wether unsigned int is possible, while int always works.
+ * (unsigned int would be preferable when possible... for stuff like
+ * struct { enum { ... } bla : 4; } ) */
+ if(type->type == TYPE_ENUM)
+ return ATOMIC_TYPE_INT;
+
+ assert(type->type == TYPE_ATOMIC);
+ atomic_type_t *atomic_type = (atomic_type_t*) type;
+ atomic_type_type_t atype = atomic_type->atype;
+ return atype;
+}
+
+static type_t *promote_integer(type_t *type)
+{
+ if(get_rank(type) < ATOMIC_TYPE_INT)
+ type = type_int;
+
+ return type;
+}
+
+static expression_t *create_cast_expression(expression_t *expression,
+ type_t *dest_type)
+{
+ unary_expression_t *cast = allocate_ast_zero(sizeof(cast[0]));
+
+ cast->expression.type = EXPR_UNARY;
+ cast->type = UNEXPR_CAST;
+ cast->value = expression;
+ cast->expression.datatype = dest_type;
+
+ return (expression_t*) cast;
+}
+
+static bool is_null_expression(const expression_t *const expr)
+{
+ if (expr->type != EXPR_CONST) return false;
+
+ type_t *const type = skip_typeref(expr->datatype);
+ if (!is_type_integer(type)) return false;
+
+ const const_t *const const_expr = (const const_t*)expr;
+ return const_expr->v.int_value == 0;
+}
+
+static expression_t *create_implicit_cast(expression_t *expression,
+ type_t *dest_type)
+{
+ type_t *source_type = expression->datatype;
+
+ if(source_type == NULL)
+ return expression;
+
+ source_type = skip_typeref(source_type);
+ dest_type = skip_typeref(dest_type);
+
+ if(source_type == dest_type)
+ return expression;
+
+ if(dest_type->type == TYPE_ATOMIC) {
+ if(source_type->type != TYPE_ATOMIC)
+ panic("casting of non-atomic types not implemented yet");
+
+ if(is_type_floating(dest_type) && !is_type_scalar(source_type)) {
+ type_error_incompatible("can't cast types",
+ expression->source_position,
+ source_type, dest_type);
+ return expression;
+ }
+
+ return create_cast_expression(expression, dest_type);
+ }
+ if(dest_type->type == TYPE_POINTER) {
+ pointer_type_t *pointer_type
+ = (pointer_type_t*) dest_type;
+ switch (source_type->type) {
+ case TYPE_ATOMIC:
+ if (is_null_expression(expression)) {
+ return create_cast_expression(expression, dest_type);
+ }
+ break;
+
+ case TYPE_POINTER:
+ if (pointers_compatible(source_type, dest_type)) {
+ return create_cast_expression(expression, dest_type);
+ }
+ break;
+
+ case TYPE_ARRAY: {
+ array_type_t *const array_type = (array_type_t*) source_type;
+ if (types_compatible(array_type->element_type,
+ pointer_type->points_to)) {
+ return create_cast_expression(expression, dest_type);
+ }
+ break;
+ }
+
+ default:
+ panic("casting of non-atomic types not implemented yet");