Example #1
0
static typecheck_err ChkCompatibleFunctionParms( TYPEPTR typ1, TYPEPTR typ2, bool topLevelCheck )
{
    TYPEPTR         *plist1;
    TYPEPTR         *plist2;
    TYPEPTR         p1;
    TYPEPTR         p2;
    int             parmno;
    typecheck_err   rc;

    rc = TCE_OK;        /* indicate functions are compatible */
    plist1 = typ1->u.fn.parms;
    plist2 = typ2->u.fn.parms;
    if( plist1 != plist2 ) {
        if( plist1 == NULL ) {
            plist1 = plist2;
            plist2 = NULL;
        }
        if( plist2 == NULL ) {
            for( parmno = 1; (p1 = *plist1++) != NULL; ++parmno ) {
                if( p1->decl_type == TYPE_DOT_DOT_DOT ) {
                    break;
                }
                if( !ChkParmPromotion( p1 ) ) {
                    if( topLevelCheck ) {
                        CErr2( ERR_PARM_TYPE_MISMATCH, parmno );
                    }
                    rc = TCE_TYPE_MISMATCH;
                }
            }
        } else {
            p1 = *plist1++; p2 = *plist2++;
            for( parmno = 1; p1 != NULL && p2 != NULL; ++parmno ) {
                if( p1->decl_type == TYPE_DOT_DOT_DOT || p2->decl_type == TYPE_DOT_DOT_DOT ) {
                    break;
                }
                if( !IdenticalType( p1, p2 ) ) {
                    if( topLevelCheck ) {
                        SetDiagType2( p1, p2 );
                        CErr2( ERR_PARM_TYPE_MISMATCH, parmno );
                        SetDiagPop();
                    }
                    rc = TCE_TYPE_MISMATCH;
                }
                p1 = *plist1++; p2 = *plist2++;
            }
            if( p1 != NULL && p1->decl_type == TYPE_DOT_DOT_DOT || p2 != NULL && p2->decl_type == TYPE_DOT_DOT_DOT ) {
                p1 = NULL;
                p2 = NULL;
            }
            if( p1 != NULL || p2 != NULL ) {
                if( topLevelCheck ) {
                    CErr1( ERR_PARM_COUNT_MISMATCH );
                }
                rc = TCE_PARM_COUNT_MISMATCH;
            }
        }
    }
    return( rc );
}
Example #2
0
static cmp_type InUnion( TYPEPTR typ1, TYPEPTR typ2, bool reversed )
{
    FIELDPTR    field;

    /* typ1->decl_type == TYPE_UNION */
    if( typ2->decl_type == TYPE_UNION )
        return( NO );
    for( field = typ1->u.tag->u.field_list; field != NULL; field = field->next_field ) {
        if( reversed ) {
            if( IdenticalType( typ2, field->field_type ) ) {
                return( OK );
            }
        } else {
            if( IdenticalType( field->field_type, typ2 ) ) {
                return( OK );
            }
        }
    }
    return( NO );
}
Example #3
0
static cmp_type CompatibleStructs( TAGPTR tag1, TAGPTR tag2 )
{
    FIELDPTR    field1;
    FIELDPTR    field2;
    TYPEPTR     typ1;
    TYPEPTR     typ2;

    if( tag1 == tag2 )
        return( OK );
    if( tag1->size != tag2->size )
        return( NO );
    field1 = tag1->u.field_list;
    field2 = tag2->u.field_list;
    /* if either struct is undefined, let's be conservative */
    if( (field1 == NULL) || (field2 == NULL) )
        return( NO );
    for( ;; ) {
        if( field1 == NULL )
            break;
        if( field2 == NULL )
            break;
        typ1 = field1->field_type;
        SKIP_TYPEDEFS( typ1 );
        typ2 = field2->field_type;
        SKIP_TYPEDEFS( typ2 );
        if( !IdenticalType( typ1, typ2 ) ) {
            if( ( typ1->decl_type == TYPE_STRUCT && typ2->decl_type == TYPE_STRUCT ) ||
                ( typ1->decl_type == TYPE_UNION && typ2->decl_type == TYPE_UNION ) ) {
                if( CompatibleStructs( typ1->u.tag, typ2->u.tag ) != OK ) {
                    return( NO );
                }
            } else {                                /* 11-jul-90 */
                return( NO );
            }
        }
        field1 = field1->next_field;
        field2 = field2->next_field;
    }
    /* one list longer than other (possible with -zp4) */
    if( field1 != NULL || field2 != NULL )
        return( NO );
    return( OK );
}
Example #4
0
int ChkCompatibleFunction( TYPEPTR typ1, TYPEPTR typ2, int topLevelCheck )
{
    TYPEPTR     *plist1;
    TYPEPTR     *plist2;
    int         parm_count;

    plist1 = typ1->u.fn.parms;
    plist2 = typ2->u.fn.parms;
    if( plist1 != plist2 ) {
        if( plist1 == NULL ) {
            return( ChkParmPromotion( plist2, topLevelCheck ) );
        } else if( plist2 == NULL ) {
            return( ChkParmPromotion( plist1, topLevelCheck ) );
        }
        parm_count = 1;
        for( ;; ) {
            if( *plist1 == NULL && *plist2 == NULL )
                break;
            if( *plist1 == NULL  ||  *plist2 == NULL ) {
                if( topLevelCheck ) {
                    CErr1( ERR_PARM_COUNT_MISMATCH );
                }
                return( TC_PARM_COUNT_MISMATCH );
            }
            if( ! IdenticalType( *plist1, *plist2 ) ) {
                if( topLevelCheck ) {
                    SetDiagType2( *plist1, *plist2 );
                    CErr2( ERR_PARM_TYPE_MISMATCH, parm_count );
                    SetDiagPop();
                }
                return( TC_PARM_TYPE_MISMATCH + parm_count );
            }
            ++plist1;
            ++plist2;
            ++parm_count;
        }
    }
    return( TC_OK );        /* indicate functions are compatible */
}
Example #5
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 );
}
Example #6
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 );
}