bool types_compatible_ignore_qualifiers(const type_t *type1, const type_t *type2) { assert(!is_typeref(type1)); assert(!is_typeref(type2)); /* shortcut: the same type is always compatible */ if (type1 == type2) return true; if (type1->kind != type2->kind) { /* enum types are compatible to their base integer type */ if ((type1->kind == TYPE_ENUM && is_type_atomic(type2, type1->enumt.base.akind)) || (type2->kind == TYPE_ENUM && is_type_atomic(type1, type2->enumt.base.akind))) return true; /* error types are compatible to everything to avoid follow-up errors */ if (!is_type_valid(type1) || !is_type_valid(type2)) return true; return false; } switch (type1->kind) { case TYPE_FUNCTION: return function_types_compatible(&type1->function, &type2->function); case TYPE_ATOMIC: case TYPE_IMAGINARY: case TYPE_COMPLEX: return type1->atomic.akind == type2->atomic.akind; case TYPE_ARRAY: return array_types_compatible(&type1->array, &type2->array); case TYPE_POINTER: { const type_t *const to1 = skip_typeref(type1->pointer.points_to); const type_t *const to2 = skip_typeref(type2->pointer.points_to); return types_compatible(to1, to2); } case TYPE_REFERENCE: { const type_t *const to1 = skip_typeref(type1->reference.refers_to); const type_t *const to2 = skip_typeref(type2->reference.refers_to); return types_compatible(to1, to2); } case TYPE_COMPOUND_STRUCT: case TYPE_COMPOUND_UNION: return type1->compound.compound == type2->compound.compound; case TYPE_ENUM: return type1->enumt.enume == type2->enumt.enume; case TYPE_ERROR: case TYPE_VOID: return true; case TYPE_TYPEDEF: case TYPE_TYPEOF: break; /* we already tested for is_typeref() above */ case TYPE_BUILTIN_TEMPLATE: panic("unexpected type"); } panic("invalid type kind"); }
bool types_compatible(const type_t *type1, const type_t *type2) { assert(!is_typeref(type1)); assert(!is_typeref(type2)); /* shortcut: the same type is always compatible */ if (type1 == type2) return true; if (!is_type_valid(type1) || !is_type_valid(type2)) return true; if (type1->base.qualifiers != type2->base.qualifiers) return false; if (type1->kind != type2->kind) return false; switch (type1->kind) { case TYPE_FUNCTION: return function_types_compatible(&type1->function, &type2->function); case TYPE_ATOMIC: case TYPE_IMAGINARY: case TYPE_COMPLEX: return type1->atomic.akind == type2->atomic.akind; case TYPE_ARRAY: return array_types_compatible(&type1->array, &type2->array); case TYPE_POINTER: { const type_t *const to1 = skip_typeref(type1->pointer.points_to); const type_t *const to2 = skip_typeref(type2->pointer.points_to); return types_compatible(to1, to2); } case TYPE_REFERENCE: { const type_t *const to1 = skip_typeref(type1->reference.refers_to); const type_t *const to2 = skip_typeref(type2->reference.refers_to); return types_compatible(to1, to2); } case TYPE_COMPOUND_STRUCT: case TYPE_COMPOUND_UNION: { break; } case TYPE_ENUM: /* TODO: not implemented */ break; case TYPE_ERROR: /* Hmm, the error type should be compatible to all other types */ return true; case TYPE_TYPEDEF: case TYPE_TYPEOF: panic("typerefs not skipped in compatible types?!?"); } return false; }
bool types_compatible(const type_t *type1, const type_t *type2) { assert(!is_typeref(type1)); assert(!is_typeref(type2)); /* shortcut: the same type is always compatible */ if (type1 == type2) return true; if (type1->base.qualifiers == type2->base.qualifiers && type1->kind == type2->kind) { switch (type1->kind) { case TYPE_FUNCTION: return function_types_compatible(&type1->function, &type2->function); case TYPE_ATOMIC: case TYPE_IMAGINARY: case TYPE_COMPLEX: return type1->atomic.akind == type2->atomic.akind; case TYPE_ARRAY: return array_types_compatible(&type1->array, &type2->array); case TYPE_POINTER: { const type_t *const to1 = skip_typeref(type1->pointer.points_to); const type_t *const to2 = skip_typeref(type2->pointer.points_to); return types_compatible(to1, to2); } case TYPE_REFERENCE: { const type_t *const to1 = skip_typeref(type1->reference.refers_to); const type_t *const to2 = skip_typeref(type2->reference.refers_to); return types_compatible(to1, to2); } case TYPE_COMPOUND_STRUCT: case TYPE_COMPOUND_UNION: break; case TYPE_ENUM: /* TODO: not implemented */ break; case TYPE_ERROR: case TYPE_VOID: return true; case TYPE_TYPEDEF: case TYPE_TYPEOF: panic("typeref not skipped"); case TYPE_BUILTIN_TEMPLATE: panic("unexpected type"); } } return !is_type_valid(type1) || !is_type_valid(type2); }
bool types_compatible(const type_t *type1, const type_t *type2) { assert(!is_typeref(type1)); assert(!is_typeref(type2)); /* shortcut: the same type is always compatible */ if (type1 == type2) return true; if (type1->base.qualifiers != type2->base.qualifiers) return false; return types_compatible_ignore_qualifiers(type1, type2); }
bool is_type_complete(type_t const *const type) { assert(!is_typeref(type)); switch (type->kind) { case TYPE_COMPOUND_STRUCT: case TYPE_COMPOUND_UNION: return type->compound.compound->complete; case TYPE_ARRAY: return type->array.size_expression || type->array.size_constant; case TYPE_ATOMIC: case TYPE_ENUM: case TYPE_COMPLEX: case TYPE_IMAGINARY: case TYPE_FUNCTION: case TYPE_POINTER: case TYPE_REFERENCE: case TYPE_ERROR: return true; case TYPE_VOID: return false; case TYPE_TYPEDEF: case TYPE_TYPEOF: case TYPE_BUILTIN_TEMPLATE: break; } panic("invalid type"); }
bool is_type_integer(const type_t *type) { assert(!is_typeref(type)); if (!is_type_arithmetic(type)) return false; return test_atomic_type_flag(type->atomic.akind, ATOMIC_TYPE_FLAG_INTEGER); }
bool is_type_incomplete(const type_t *type) { assert(!is_typeref(type)); switch(type->kind) { case TYPE_COMPOUND_STRUCT: case TYPE_COMPOUND_UNION: { const compound_type_t *compound_type = &type->compound; return !compound_type->compound->complete; } case TYPE_ENUM: return false; case TYPE_ARRAY: return type->array.size_expression == NULL && !type->array.size_constant; case TYPE_ATOMIC: case TYPE_IMAGINARY: case TYPE_COMPLEX: return type->atomic.akind == ATOMIC_TYPE_VOID; case TYPE_FUNCTION: case TYPE_POINTER: case TYPE_REFERENCE: case TYPE_ERROR: return false; case TYPE_TYPEDEF: case TYPE_TYPEOF: panic("is_type_incomplete called without typerefs skipped"); } panic("invalid type found"); }
bool is_type_signed(const type_t *type) { assert(!is_typeref(type)); if (!is_type_arithmetic(type)) return false; return test_atomic_type_flag(type->atomic.akind, ATOMIC_TYPE_FLAG_SIGNED); }
/** * get alignment of a type when used inside a compound. * Some ABIs are broken and alignment inside a compound is different from * recommended alignment of a type */ static unsigned get_type_alignment_compound(type_t *const type) { assert(!is_typeref(type)); if (type->kind == TYPE_ATOMIC) return atomic_type_properties[type->atomic.akind].struct_alignment; return get_type_alignment(type); }
bool is_type_float(const type_t *type) { assert(!is_typeref(type)); if (type->kind != TYPE_ATOMIC) return false; return test_atomic_type_flag(type->atomic.akind, ATOMIC_TYPE_FLAG_FLOAT); }
bool is_type_scalar(const type_t *type) { assert(!is_typeref(type)); if (type->kind == TYPE_POINTER) return true; return is_type_arithmetic(type); }
bool is_type_complex(const type_t *type) { assert(!is_typeref(type)); if (type->kind != TYPE_ATOMIC) return false; return test_atomic_type_flag(type->atomic.akind, ATOMIC_TYPE_FLAG_COMPLEX); }
bool is_type_integer(const type_t *type) { assert(!is_typeref(type)); if (type->kind == TYPE_ENUM) return true; if (type->kind != TYPE_ATOMIC) return false; return test_atomic_type_flag(type->atomic.akind, ATOMIC_TYPE_FLAG_INTEGER); }
bool is_type_signed(const type_t *type) { assert(!is_typeref(type)); /* enum types are int for now */ if (type->kind == TYPE_ENUM) return true; if (type->kind != TYPE_ATOMIC) return false; return test_atomic_type_flag(type->atomic.akind, ATOMIC_TYPE_FLAG_SIGNED); }
type_t *get_unqualified_type(type_t *type) { assert(!is_typeref(type)); if (type->base.qualifiers == TYPE_QUALIFIER_NONE) return type; type_t *unqualified_type = duplicate_type(type); unqualified_type->base.qualifiers = TYPE_QUALIFIER_NONE; return identify_new_type(unqualified_type); }
static type_t *add_modifiers(type_t *type, decl_modifiers_t modifiers) { if (is_typeref(type) || !is_type_function(type)) { return type; } if ((type->function.modifiers & modifiers) == modifiers) return type; type_t* new_type = duplicate_type(type); new_type->function.modifiers |= modifiers; return identify_new_type(new_type); }
static type_t *change_calling_convention(type_t *type, cc_kind_t cconv) { if (is_typeref(type) || !is_type_function(type)) { return type; } if (type->function.calling_convention == cconv) return type; type_t* new_type = duplicate_type(type); new_type->function.calling_convention = cconv; return identify_new_type(new_type); }
bool is_type_arithmetic(const type_t *type) { assert(!is_typeref(type)); switch(type->kind) { case TYPE_ENUM: return true; case TYPE_ATOMIC: case TYPE_COMPLEX: case TYPE_IMAGINARY: return test_atomic_type_flag(type->atomic.akind, ATOMIC_TYPE_FLAG_ARITHMETIC); default: return false; } }
bool is_type_arithmetic(const type_t *type) { assert(!is_typeref(type)); switch (type->kind) { case TYPE_ATOMIC: case TYPE_COMPLEX: case TYPE_ENUM: case TYPE_IMAGINARY: return true; default: return false; } }
bool is_type_enum(const type_t *type) { assert(!is_typeref(type)); return type->kind == TYPE_ENUM; }
bool is_type_complex(const type_t *type) { assert(!is_typeref(type)); return type->kind == TYPE_COMPLEX; }