Пример #1
0
static cmp_type DoCompatibleType( TYPEPTR typ1, TYPEPTR typ2, int ptr_indir_level )
{
    cmp_type         ret_val;
    type_modifiers   typ1_flags, typ2_flags;

    typ1_flags = FLAG_NONE;
    typ2_flags = FLAG_NONE;
    ret_val = OK;
    for( ;; ) {   // * [] loop
        typ1 = SkipTypeFluff( typ1 ); // skip typedefs, go into enum base
        typ2 = SkipTypeFluff( typ2 );
        if( typ1 == typ2 )
            break;
        if( typ1->decl_type != typ2->decl_type )
            break;
        if( typ1->decl_type == TYPE_ARRAY ) {
            /* See C99, 6.7.5.2p5 */
            if( typ1->u.array->dimension && typ2->u.array->dimension ) {
                if( typ1->u.array->dimension != typ2->u.array->dimension ) {
                    ret_val = PM;
                }
            }
        } else if( typ1->decl_type == TYPE_POINTER ) {
            typ1_flags = typ1->u.p.decl_flags;
            typ2_flags = typ2->u.p.decl_flags;
            if( (typ1_flags & MASK_QUALIFIERS) != (typ2_flags & MASK_QUALIFIERS) ) {
                if( ret_val == OK ) {   //PM is a worse case
                    ret_val = PQ;
                }
            }
            if( (typ1_flags & MASK_ALL_MEM_MODELS) != (typ2_flags & MASK_ALL_MEM_MODELS) ) {
                if( ( (typ1_flags & MASK_ALL_MEM_MODELS) != FLAG_NONE    // if same as mem model ok
                  && (typ2_flags & MASK_ALL_MEM_MODELS) != FLAG_NONE )
                  || TypeSize( typ1 ) != TypeSize( typ2 ) ) {
                    return( NO );
                }
            }
            ++ptr_indir_level;
        } else {
            break;
        }
        typ1 = typ1->object;
        typ2 = typ2->object;
    }
    if( typ1 != typ2 ) {    // if not equal see if diff by pointers
        if( ptr_indir_level > 0 ) {
            if( typ1->decl_type == TYPE_VOID || typ2->decl_type == TYPE_VOID ) {
                // allow  void ** with any ** (but warn about it)
                if( ( ptr_indir_level == 1 ) || !CompFlags.strict_ANSI ) {
                    if( ptr_indir_level > 1 ) {
                        ret_val = PM;
                    }
                    return( ret_val ); // void *  and  anything *
                }
            }
            if( typ1->decl_type == TYPE_POINTER && typ2->decl_type != TYPE_ARRAY ) {
                ret_val = PW;
                while( typ1->decl_type == TYPE_POINTER ) {
                    typ1 = SkipTypeFluff( typ1->object );
                    ++ptr_indir_level;
                }
            } else if( typ2->decl_type == TYPE_POINTER && typ1->decl_type != TYPE_ARRAY ) {
                ret_val = PW;
                while( typ2->decl_type == TYPE_POINTER ) {
                    typ2 = SkipTypeFluff( typ2->object );
                    ++ptr_indir_level;
                }
            }
        }
    }
    if( typ1->decl_type == typ2->decl_type ) {
        if( typ1->decl_type == TYPE_FUNCTION ) {
            typ1_flags = typ1->u.fn.decl_flags;
            typ2_flags = typ2->u.fn.decl_flags;
            if( !ChkCompatibleLanguage( typ1_flags, typ2_flags ) ) {
                ret_val = NO;
            } else if( ChkCompatibleFunctionParms( typ1, typ2, false ) != TCE_OK ) {
                ret_val = NO;
            } else if( !IdenticalType( typ1->object, typ2->object ) ) {
                ret_val = NO;
            }
        } else if( typ1->decl_type == TYPE_STRUCT || typ1->decl_type == TYPE_UNION ) {
           /* allow pointers to different structs */
           /* stop this for ANSI! */
            if( ( typ1 != typ2 ) ) {
                // Types are not the same
                // if extensions are enabled, then we can do a compatible struct test
                if( CompFlags.extensions_enabled ) {
                    if( CompatibleStructs( typ1->u.tag, typ2->u.tag ) != OK) {
                        if( ptr_indir_level > 0 ) {
                            if( ret_val != PW ) {
                                ret_val = PM;
                            } else {
                                ret_val = NO;
                            }
                        } else {
                            ret_val = NO;
                        }
                    }
                } else {
                    ret_val = NO;
                }
            }
        } else if( (TYPE_FIELD == typ1->decl_type) || (TYPE_UFIELD == typ1->decl_type) ) {
            if( typ2->u.f.field_width > typ1->u.f.field_width ) {
                ret_val = AC;
            }
        }
    } else if( typ1->decl_type == TYPE_UNION && ptr_indir_level > 0 ) {
        if( InUnion( typ1, typ2, false ) != OK ) {
            ret_val = NO;
        } else {
            ret_val = PM;
        }
    } else if( typ2->decl_type == TYPE_UNION && ptr_indir_level > 0 ) {
        if( InUnion( typ2, typ1, true ) != OK ) {
            ret_val = NO;
        } else {
            ret_val = PM;
        }
    } else if( typ1->decl_type == TYPE_ARRAY ) {
        TYPEPTR     typ = typ1->object;

        if( !IdenticalType( typ, typ2 ) ) {
            ret_val = NO;
            SKIP_ARRAYS( typ );
            if( IdenticalType( typ, typ2 ) ) {
                ret_val = PM;
            }
        }
    } else if( typ2->decl_type == TYPE_ARRAY ) {
        TYPEPTR     typ = typ2->object;

        if( !IdenticalType( typ, typ1 ) ) {
            ret_val = NO;
            SKIP_ARRAYS( typ );
            if( IdenticalType( typ, typ1 ) ) {
                ret_val = PM;
            }
        }
    } else if( typ1->decl_type >= TYPE_LAST_ENTRY || typ2->decl_type >= TYPE_LAST_ENTRY ) {
        ret_val = NO;
    } else if( ptr_indir_level == 0 ) {
        ret_val = CompTable[typ1->decl_type][typ2->decl_type];
    } else {
        ret_val = PM;
        switch( typ1->decl_type ) {
        case TYPE_CHAR:
        case TYPE_SHORT:
        case TYPE_INT:
        case TYPE_LONG:
        case TYPE_LONG64:
            if( typ2->decl_type == typ1->decl_type + 1 ) {
                ret_val = PS;
            }
            break;
        case TYPE_UCHAR:
        case TYPE_USHORT:
        case TYPE_UINT:
        case TYPE_ULONG:
        case TYPE_ULONG64:
            if( typ2->decl_type + 1 == typ1->decl_type ) {
                ret_val = PS;
            }
            break;
        default:
            break;
        }
    }
    return( ret_val );
}
Пример #2
0
static cmp_type DoCompatibleType( TYPEPTR typ1, TYPEPTR typ2, int top_level,
                                  voidptr_cmp_type voidptr_cmp )
{
    cmp_type         ret_val;
    type_modifiers   typ1_flags, typ2_flags;

    typ1_flags = FLAG_NONE;
    typ2_flags = FLAG_NONE;
    ret_val = OK;
    for( ;; ) {   // * [] loop
        typ1 = SkipTypeFluff( typ1 ); // skip typedefs, go into enum base
        typ2 = SkipTypeFluff( typ2 );
        if( typ1 == typ2 )
            break;
        if( typ1->decl_type != typ2->decl_type )
            break;
        if( typ1->decl_type != TYPE_ARRAY && typ1->decl_type != TYPE_POINTER )
            break;
        if( typ1->decl_type == TYPE_ARRAY && typ2->decl_type == TYPE_ARRAY ) {
            /* See C99, 6.7.5.2p5 */
            if( typ1->u.array->dimension && typ2->u.array->dimension ) {
                if( typ1->u.array->dimension != typ2->u.array->dimension ) {
                    ret_val = PM;
                }
            }
        }
        if( typ1->decl_type==TYPE_POINTER ) {
            typ1_flags = typ1->u.p.decl_flags;
            typ2_flags = typ2->u.p.decl_flags;
            if( (typ1_flags & QUAL_FLAGS)!=(typ2_flags & QUAL_FLAGS) ) {
                if( ret_val == OK ) {   //PT is a worse case
                    ret_val = PQ;
                }
            }
            if( (typ1_flags & FLAG_MEM_MODEL) != (typ2_flags & FLAG_MEM_MODEL) ) {
                if( ( (typ1_flags & FLAG_MEM_MODEL) != FLAG_NONE    // if same as mem model ok
                    && (typ2_flags & FLAG_MEM_MODEL) != FLAG_NONE )
                    ||  TypeSize( typ1 ) != TypeSize( typ2 ) ) {
                    return( NO );
                }
            }
            ++top_level;
        }
        typ1 = typ1->object;
        typ2 = typ2->object;
    }
    if( typ1 != typ2 ) {    // if not equal see if diff by pointers
        if( typ1->decl_type == TYPE_VOID || typ2->decl_type == TYPE_VOID ) {
            // allow  void ** with any ** (but warn about it)
            if( top_level==1 || !CompFlags.strict_ANSI ) {
                if( voidptr_cmp == VC_WARN || (top_level > 1) ) {
                    CWarn1( WARN_PCTYPE_MISMATCH, ERR_PCTYPE_MISMATCH );
                }
                return( ret_val ); // void *  and  anything *
            }
        }
        if( top_level > 0 ) {   //for PW both types must start as pointers
            if( typ1->decl_type == TYPE_POINTER
               && typ2->decl_type != TYPE_ARRAY ) {
                ret_val = PW;
                while( typ1->decl_type == TYPE_POINTER ) {
                    typ1 = typ1->object;
                    typ1 = SkipTypeFluff( typ1 );
                    ++top_level;
                }
            } else if( typ2->decl_type == TYPE_POINTER
                && typ1->decl_type != TYPE_ARRAY ) {
                ret_val = PW;
                while( typ2->decl_type == TYPE_POINTER ) {
                    typ2 = typ2->object;
                    typ2 = SkipTypeFluff( typ2 );
                    ++top_level;
                }
            }
        }
    }
    if( typ1->decl_type==typ2->decl_type ) {
        if( typ1->decl_type == TYPE_FUNCTION ) {
            typ1_flags = typ1->u.fn.decl_flags;
            typ2_flags = typ2->u.fn.decl_flags;
            if( !ChkCompatibleLanguage( typ1_flags, typ2_flags ) ) {
                ret_val = NO;
            } else {
                /* check to see if the two functions have identical parameters
                   and return types */
                if( ChkCompatibleFunction( typ1, typ2, 0 ) != TC_OK  ||
                    !IdenticalType( typ1->object, typ2->object ) ) {
                    CWarn1( WARN_PCTYPE_MISMATCH, ERR_PCTYPE_MISMATCH );
                }
            }
        } else if( typ1->decl_type == TYPE_STRUCT  || typ1->decl_type == TYPE_UNION ) {
           /* 11-jul-90: allow pointers to different structs */
           /* 29-oct-03: stop this for ANSI! */
            if( ( typ1 != typ2 ) ) {
                // Types are not the same
                // if extensions are enabled, then we can do a compatible struct test
                if( CompFlags.extensions_enabled ) {
                    if( CompatibleStructs( typ1->u.tag, typ2->u.tag ) != OK) {
                        if( top_level > 0 ) {
                            if( ret_val != PW ) {
                                ret_val = PM;
                            } else {
                                ret_val = NO;
                            }
                        } else {
                            ret_val = NO;
                        }
                    }
                } else {
                    ret_val = NO;
                }
            }
        } else if( (TYPE_FIELD == typ1->decl_type) || (TYPE_UFIELD == typ1->decl_type) ) { /* CarlYoung 31-Oct-03 */
            if( typ2->u.f.field_width > typ1->u.f.field_width ) {
                ret_val = AC;
            }
        }
    } else if( typ1->decl_type == TYPE_UNION && top_level > 0 ) {
        if( InUnion( typ1, typ2, 0 ) != OK ) {
            ret_val = NO;
        } else {
            ret_val = PM;
        }
    } else if( typ2->decl_type == TYPE_UNION && top_level > 0 ) {
        if( InUnion( typ2, typ1, 1 )!= OK ) {
            ret_val = NO;
        } else {
            ret_val = PM;
        }
    } else if( typ1->decl_type == TYPE_ARRAY ) {
        TYPEPTR     typ = typ1->object;

        if( !IdenticalType( typ, typ2 ) ) {
            ret_val = NO;
            while( typ->decl_type == TYPE_ARRAY ) {
                typ = typ->object;
            }
            if( IdenticalType( typ, typ2 ) ) {
                ret_val = PM;
            }
        }
    } else if( typ2->decl_type == TYPE_ARRAY ) {
        TYPEPTR     typ = typ2->object;

        if( !IdenticalType( typ, typ1 ) ) {
            ret_val = NO;
            while( typ->decl_type == TYPE_ARRAY ) {
                typ = typ->object;
            }
            if( IdenticalType( typ, typ1 ) ) {
                ret_val = PM;
            }
        }
    } else if( typ1->decl_type >= TYPE_LAST_ENTRY  ||
            typ2->decl_type >= TYPE_LAST_ENTRY ) {
        ret_val = NO;
    } else if( top_level == 0 ) {
        ret_val = CompTable[ typ1->decl_type ][ typ2->decl_type ];
    } else {
        ret_val = NO;
        switch( typ1->decl_type ) {
        case TYPE_CHAR:
        case TYPE_SHORT:
        case TYPE_INT:
        case TYPE_LONG:
        case TYPE_LONG64:
            if( typ2->decl_type == typ1->decl_type+1 ) {
                ret_val = PS;
            } else if( TypeSize( typ1 ) ==   TypeSize( typ2 ) ) {
                ret_val = PM;
            }
            break;
        case TYPE_UCHAR:
        case TYPE_USHORT:
        case TYPE_UINT:
        case TYPE_ULONG:
        case TYPE_ULONG64:
            if( typ2->decl_type+1 == typ1->decl_type ) {
                ret_val = PS;
            } else if( TypeSize( typ1 ) ==   TypeSize( typ2 ) ) {
                ret_val = PM;
            }
            break;
        default:
            break;
        }
    }
    return( ret_val );
}