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); }