static void write_const(CTX *ctx, struct ir_const_val v) { char *s = const_unparse(NULL, v); if (TEST_UNION(IR_TYPE, tarray, &v.type)) { fprintf(ctx->f, "{%s}", s); } else if (type_is_integer(v.type)) { // Get rid of annoying-but-correct gcc warning. This happens because we // negate a value not representable in intmax_t, even though the result // is representable, i.e. the only case is INT64_MIN. if (type_equals(v.type, type_integer(true, 64)) && *GET_UNION(VALUE, vuint64, &v.value) == INT64_MIN) { fprintf(ctx->f, "INT64_MIN"); } else { fprintf(ctx->f, "%s(%s)", int_const(v.type), s); } } else if (TEST_UNION(IR_TYPE, tslice, &v.type)) { if (TEST_UNION0(VALUE, vempty, &v.value)) { fprintf(ctx->f, "{0}"); } else if (type_equals(v.type, TYPE_STRING)) { char *raw = *GET_UNION(VALUE, vstring, &v.value); fprintf(ctx->f, "{ %s, %zd }", s, raw ? strlen(raw) : 0); } else { assert(false); } } else { fprintf(ctx->f, "%s", s); } talloc_free(s); }
static bool pointerint_conditional(type t1, type t2, expression e2) { if (type_pointer(t1) && type_integer(t2)) { if (!definite_zero(e2)) pedwarn("pointer/integer type mismatch in conditional expression"); return TRUE; } return FALSE; }
static void dump_type(type t) { if (type_complex(t)) { printf("C"); t = make_base_type(t); } if (type_network_base_type(t)) printf("N%s", type_networkdef(t)->name); /* Enums treated as ints for now */ else if (type_integer(t)) if (type_unsigned(t)) printf("U"); else printf("I"); else if (type_float(t)) printf("F"); else if (type_double(t)) printf("D"); else if (type_long_double(t)) printf("LD"); else if (type_union(t)) if (type_network(t)) printf("ANU"); else printf("AU"); else if (type_struct(t)) if (type_network(t)) printf("ANS"); else printf("AS"); else if (type_pointer(t)) printf("U"); else assert(0); }
type check_binary(int binop, expression e1, expression e2) { type t1 = default_conversion(e1), t2 = default_conversion(e2); type rtype = NULL; bool common = FALSE; /* XXX: Misc warnings (see build_binary_op) */ if (t1 == error_type || t2 == error_type) rtype = error_type; else switch(binop) { case kind_plus: if (type_pointer(t1) && type_integer(t2)) rtype = pointer_int_sum(t1, t2); else if (type_pointer(t2) && type_integer(t1)) rtype = pointer_int_sum(t2, t1); else common = TRUE; break; case kind_minus: if (type_pointer(t1) && type_integer(t2)) rtype = pointer_int_sum(t1, t2); else if (type_pointer(t1) && type_pointer(t2) && compatible_pointer_types(t1, t2)) rtype = ptrdiff_t_type; else common = TRUE; break; case kind_plus_assign: case kind_minus_assign: if (type_pointer(t1) && type_integer(t2)) rtype = pointer_int_sum(t1, t2); else common = TRUE; break; case kind_times: case kind_divide: case kind_times_assign: case kind_divide_assign: common = TRUE; break; case kind_modulo: case kind_bitand: case kind_bitor: case kind_bitxor: case kind_lshift: case kind_rshift: case kind_modulo_assign: case kind_bitand_assign: case kind_bitor_assign: case kind_bitxor_assign: case kind_lshift_assign: case kind_rshift_assign: if (type_integer(t1) && type_integer(t2)) rtype = common_type(t1, t2); break; case kind_leq: case kind_geq: case kind_lt: case kind_gt: rtype = int_type; /* Default to assuming success */ if (type_real(t1) && type_real(t2)) ; else if (type_pointer(t1) && type_pointer(t2)) { if (compatible_pointer_types(t1, t2)) { /* XXX: how can this happen ? */ if (type_incomplete(t1) != type_incomplete(t2)) pedwarn("comparison of complete and incomplete pointers"); else if (pedantic && type_function(type_points_to(t1))) pedwarn("ANSI C forbids ordered comparisons of pointers to functions"); } else pedwarn("comparison of distinct pointer types lacks a cast"); } /* XXX: Use of definite_zero may lead to extra warnings when !extra_warnings */ else if ((type_pointer(t1) && definite_zero(e2)) || (type_pointer(t2) && definite_zero(e1))) { if (pedantic || extra_warnings) pedwarn("ordered comparison of pointer with integer zero"); } else if ((type_pointer(t1) && type_integer(t2)) || (type_pointer(t2) && type_integer(t1))) { if (!flag_traditional) pedwarn("comparison between pointer and integer"); } else rtype = NULL; /* Force error */ break; case kind_eq: case kind_ne: rtype = int_type; /* Default to assuming success */ if (type_arithmetic(t1) && type_arithmetic(t2)) ; else if (type_pointer(t1) && type_pointer(t2)) { if (!compatible_pointer_types(t1, t2) && !valid_compare(t1, t2, e1) && !valid_compare(t2, t1, e2)) pedwarn("comparison of distinct pointer types lacks a cast"); } else if ((type_pointer(t1) && definite_null(e2)) || (type_pointer(t2) && definite_null(e1))) ; else if ((type_pointer(t1) && type_integer(t2)) || (type_pointer(t2) && type_integer(t1))) { if (!flag_traditional) pedwarn("comparison between pointer and integer"); } else rtype = NULL; /* Force error */ break; case kind_andand: case kind_oror: if (type_scalar(t1) && type_scalar(t2)) rtype = int_type; break; default: assert(0); break; } if (common && type_arithmetic(t1) && type_arithmetic(t2)) rtype = common_type(t1, t2); if (!rtype) { error("invalid operands to binary %s", binary_op_name(binop)); rtype = error_type; } return rtype; }
expression make_unary(location loc, int unop, expression e) { switch (unop) { case kind_address_of: return make_address_of(loc, e); case kind_preincrement: return make_preincrement(loc, e); case kind_predecrement: return make_predecrement(loc, e); default: { expression result = CAST(expression, newkind_unary(parse_region, unop, loc, e)); type etype = default_conversion(e); const char *errstring = NULL; if (etype == error_type) result->type = error_type; else { switch (unop) { case kind_unary_plus: if (!type_arithmetic(etype)) errstring = "wrong type argument to unary plus"; break; case kind_unary_minus: if (!type_arithmetic(etype)) errstring = "wrong type argument to unary minus"; break; case kind_bitnot: if (type_complex(etype)) result->kind = kind_conjugate; else if (!type_integer(etype)) errstring = "wrong type argument to bit-complement"; break; case kind_not: if (!type_scalar(etype)) errstring = "wrong type argument to unary exclamation mark"; else etype = int_type; break; case kind_realpart: case kind_imagpart: if (!type_arithmetic(etype)) if (unop == kind_realpart) errstring = "wrong type argument to __real__"; else errstring = "wrong type argument to __imag__"; else etype = type_complex(etype) ? make_base_type(etype) : etype; default: assert(0); } if (errstring) { error(errstring); result->type = error_type; } else { result->type = etype; result->cst = fold_unary(result); } } return result; } } }
bool check_conversion(type to, type from) { if (type_equal_unqualified(to, from)) return TRUE; if (to == error_type || from == error_type) return FALSE; if (type_void(from)) { error("void value not ignored as it ought to be"); return FALSE; } if (type_void(to)) return TRUE; if (type_integer(to)) { if (!type_scalar(from)) { error("aggregate value used where an integer was expected"); return FALSE; } } else if (type_pointer(to)) { if (!(type_integer(from) || type_pointer(from))) { error("cannot convert to a pointer type"); return FALSE; } } else if (type_floating(to)) { if (type_pointer(from)) { error("pointer value used where a floating point value was expected"); return FALSE; } else if (!type_arithmetic(from)) { error("aggregate value used where a float was expected"); return FALSE; } } else if (type_complex(to)) { if (type_pointer(from)) { error("pointer value used where a complex was expected"); return FALSE; } else if (!type_arithmetic(from)) { error("aggregate value used where a complex was expected"); return FALSE; } } else { error("conversion to non-scalar type requested"); return FALSE; } return TRUE; }
void check_switch(expression e) { if (e->type != error_type && !type_integer(e->type)) error("switch quantity not an integer"); }