types.c
// Check two types are compatible. Prevent infinite loops by keeping a map of seen tags
Check two types are compatible. Prevent infinite loops by keeping a map of seen tags
Check two types are compatible . Prevent infinite loops by keeping a map of seen tags
static int recursive_types_are_compatible(Type *type1, Type *type2, StrMap *seen_tags, int check_qualifiers) {
    if (type1->type == TYPE_STRUCT_OR_UNION && type1->tag) {
        if (strmap_get(seen_tags, type1->tag->identifier)) return 1;
        strmap_put(seen_tags, type1->tag->identifier, type1);
    }
    if (type2->type == TYPE_STRUCT_OR_UNION && type2->tag) {
        if (strmap_get(seen_tags, type2->tag->identifier)) return 1;
        strmap_put(seen_tags, type2->tag->identifier, type2);
    }
    if (check_qualifiers && type1->is_const != type2->is_const) return 0;
    if (type1->type == TYPE_PTR && type2->type == TYPE_PTR)
        return recursive_types_are_compatible(type1->target, type2->target, seen_tags, 0);
    if (type1->type == TYPE_ARRAY && type2->type == TYPE_ARRAY) {
        if (!recursive_types_are_compatible(type1->target, type2->target, seen_tags, 0)) return 0;
        if (type1->array_size && type2->array_size && type1->array_size != type2->array_size) return 0;
        return 1;
    }
    if (type1->type == TYPE_STRUCT_OR_UNION && type2->type == TYPE_STRUCT_OR_UNION) {
        if (type1->tag) strmap_put(seen_tags, type1->tag->identifier, type1);
        if (type2->tag) strmap_put(seen_tags, type2->tag->identifier, type2);
        if (!types_tags_are_compatible(type1, type2)) return 0;
    }
    if (type1->type == TYPE_ENUM && type2->type == TYPE_ENUM) {
        if (!types_tags_are_compatible(type1, type2)) return 0;
      return 1;
    }
    if (type1->type == TYPE_ENUM && type2->type == TYPE_INT) return 1;
    if (type2->type == TYPE_ENUM && type1->type == TYPE_INT) return 1;
    if (type1->type == TYPE_STRUCT_OR_UNION && type2->type == TYPE_STRUCT_OR_UNION)
        return struct_or_unions_are_compatible(type1->struct_or_union_desc, type2->struct_or_union_desc, seen_tags);
    if (type1->type == TYPE_FUNCTION && type2->type == TYPE_FUNCTION)
        return functions_are_compatible(type1, type2, seen_tags);
    return (type1->type == type2->type);
}
static int recursive_types_are_compatible ( Type * type1 , Type * type2 , StrMap * seen_tags , int check_qualifiers ) { if ( type1 -> type == TYPE_STRUCT_OR_UNION && type1 -> tag ) { if ( strmap_get ( seen_tags , type1 -> tag -> identifier ) ) return 1 ; strmap_put ( seen_tags , type1 -> tag -> identifier , type1 ) ; } if ( type2 -> type == TYPE_STRUCT_OR_UNION && type2 -> tag ) { if ( strmap_get ( seen_tags , type2 -> tag -> identifier ) ) return 1 ; strmap_put ( seen_tags , type2 -> tag -> identifier , type2 ) ; } if ( check_qualifiers && type1 -> is_const != type2 -> is_const ) return 0 ; if ( type1 -> type == TYPE_PTR && type2 -> type == TYPE_PTR ) return recursive_types_are_compatible ( type1 -> target , type2 -> target , seen_tags , 0 ) ; if ( type1 -> type == TYPE_ARRAY && type2 -> type == TYPE_ARRAY ) { if ( ! recursive_types_are_compatible ( type1 -> target , type2 -> target , seen_tags , 0 ) ) return 0 ; if ( type1 -> array_size && type2 -> array_size && type1 -> array_size != type2 -> array_size ) return 0 ; return 1 ; } if ( type1 -> type == TYPE_STRUCT_OR_UNION && type2 -> type == TYPE_STRUCT_OR_UNION ) { if ( type1 -> tag ) strmap_put ( seen_tags , type1 -> tag -> identifier , type1 ) ; if ( type2 -> tag ) strmap_put ( seen_tags , type2 -> tag -> identifier , type2 ) ; if ( ! types_tags_are_compatible ( type1 , type2 ) ) return 0 ; } if ( type1 -> type == TYPE_ENUM && type2 -> type == TYPE_ENUM ) { if ( ! types_tags_are_compatible ( type1 , type2 ) ) return 0 ; return 1 ; } if ( type1 -> type == TYPE_ENUM && type2 -> type == TYPE_INT ) return 1 ; if ( type2 -> type == TYPE_ENUM && type1 -> type == TYPE_INT ) return 1 ; if ( type1 -> type == TYPE_STRUCT_OR_UNION && type2 -> type == TYPE_STRUCT_OR_UNION ) return struct_or_unions_are_compatible ( type1 -> struct_or_union_desc , type2 -> struct_or_union_desc , seen_tags ) ; if ( type1 -> type == TYPE_FUNCTION && type2 -> type == TYPE_FUNCTION ) return functions_are_compatible ( type1 , type2 , seen_tags ) ; return ( type1 -> type == type2 -> type ) ; }
Check two types are compatible.
Check two types are compatible .
// Following https://en.cppreference.com/w/c/language/type // They are identically qualified versions of compatible unqualified types // They are pointer types and are pointing to compatible types // They are array types, and if both have constant size, that size is the same // and element types are compatible // Note: enum members aren't checked since it's not possible to declare two // anonymous enums with the same member names since they would have clashing // symbols Enum values checks are useless, since if the names don't match, they // are incompatible. Therefore, it suffices to only check the tag. // One is an enumerated type and the other is that enumeration's underlying type