fnovload.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,907 行 · 第 1/5 页

C
1,907
字号
        } else {
            // else they are both references
            DbgAssert( base_first != NULL && base_second != NULL );
        }
    } else if( MemberPtrType( first_type) != NULL &&
               MemberPtrType( second_type ) != NULL ) {
        // this is intentional
        // converting A::* -> B::* is better than A::* to C::*
        // so here we're converting from the least derived so the
        // longest distance will be to the most derived, the opposite
        // of what the test below looks for, so just switch them
        base_second = MemberPtrClass( first_type );
        base_first = MemberPtrClass( second_type );
    }

    first_scope = TypeScope( base_first );
    second_scope = TypeScope( base_second );

    if( first_scope == second_scope ) {
        return( OV_CMP_SAME );
    }
    if( ScopeDerived( first_scope, second_scope ) != DERIVED_NO  ) {
        return( OV_CMP_BETTER_FIRST );
    } else if( ScopeDerived( second_scope, first_scope ) != DERIVED_NO ) {
        return( OV_CMP_BETTER_SECOND );
    }
    return( OV_CMP_SAME );
}

#ifdef NEW_TRIVIAL_RULE
static FNOV_COARSE_RANK equateExactSameTrivial( FNOV_COARSE_RANK result )
/****************************************************************/
// make OV_RANK_SAME and OV_RANK_EXACT the same
{
    if( result == OV_RANK_EXACT ) {
        result = OV_RANK_TRIVIAL;
    }
    if( result == OV_RANK_SAME ) {
        result = OV_RANK_TRIVIAL;
    }
    return( result );
}
#else
static FNOV_COARSE_RANK equateExactSame( FNOV_COARSE_RANK result )
/****************************************************************/
// make OV_RANK_SAME and OV_RANK_EXACT the same
{
    if( result == OV_RANK_EXACT ) {
        result = OV_RANK_SAME;
    }
    return( result );
}
#endif

static FNOV_COARSE_RANK equateUDCAmbigUDC( FNOV_COARSE_RANK result )
/****************************************************************/
// make OV_RANK_UD_CONV and OV_RANK_UD_CONV_AMBIG the same
// so a class with two UDC is not made unviable, allowing another
// class with only one UDC to be selected
{
    if( result == OV_RANK_UD_CONV_AMBIG ) {
        result = OV_RANK_UD_CONV;
    }
    return( result );
}

#ifdef NEW_TRIVIAL_RULE
static OV_RESULT compareArgument( FNOV_RANK *first, TYPE * first_type,
/*********************************************************************/
FNOV_RANK *second, TYPE *second_type )
{
    OV_RESULT         retn;
    FNOV_COARSE_RANK  firstrank;
    FNOV_COARSE_RANK  secondrank;

    firstrank = equateExactSameTrivial( first->rank );
    secondrank = equateExactSameTrivial( second->rank );
    firstrank = equateUDCAmbigUDC( firstrank );
    secondrank = equateUDCAmbigUDC( secondrank );

    if( firstrank != secondrank ) {
        retn = compareInt( firstrank, secondrank );
    } else switch( firstrank ) {
    case OV_RANK_NO_MATCH:
    case OV_RANK_ELLIPSIS:
        retn = OV_CMP_SAME;
        break;
    case OV_RANK_UD_CONV:
        retn = compareScalar( &first->u.ud.out
                            , first_type
                            , &second->u.ud.out
                            , second_type, TRUE );
        break;
    case OV_RANK_STD_CONV_DERIV:
        if( ( first_type != NULL ) && ( second_type != NULL ) ) {
            retn = compareDerived( *first_type, *second_type );
            if( retn != OV_CMP_SAME ) {
                break;
            }
        }
        // two target types are not releated
        // do the following comparison
    case OV_RANK_STD_CONV_VOID:
    case OV_RANK_STD_CONV:
    case OV_RANK_STD_BOOL:
    case OV_RANK_PROMOTION:
    case OV_RANK_TRIVIAL:
        retn = compareScalar( &first->u.no_ud
                             , first_type
                             , &second->u.no_ud
                             , second_type, FALSE );
        break;
    case OV_RANK_UD_CONV_AMBIG:
    case OV_RANK_SAME:
    case OV_RANK_EXACT:
        DbgAssert( FALSE ); // made into something else above
        break;
    DbgDefault( "funny rank\n" );
    }
    return( retn );
}
#else
static OV_RESULT compareArgument(
/*******************************/
    FNOV_RANK *first
  , TYPE * first_type
  , FNOV_RANK *second
  , TYPE *second_type
  , FNOV_CONTROL control )
{
    OV_RESULT         retn;
    FNOV_COARSE_RANK  firstrank;
    FNOV_COARSE_RANK  secondrank;

    firstrank = equateExactSame( first->rank );
    secondrank = equateExactSame( second->rank );
    firstrank = equateUDCAmbigUDC( firstrank );
    secondrank = equateUDCAmbigUDC( secondrank );

    if( firstrank != secondrank ) {
        retn = compareInt( firstrank, secondrank );
        if( CompFlags.overload_13332 && ( control & FNC_USE_WP13332 ) ) {
            if( ( ( firstrank == OV_RANK_SAME )
               && ( secondrank == OV_RANK_TRIVIAL ) )
             || ( ( firstrank == OV_RANK_TRIVIAL )
               && ( secondrank == OV_RANK_SAME ) ) ) {
                  retn = WP13332( first_type, second_type, retn );
            }
        }
    } else switch( firstrank ) {
    case OV_RANK_NO_MATCH:
    case OV_RANK_ELLIPSIS:
    case OV_RANK_UD_CONV_AMBIG:
        retn = OV_CMP_SAME;
        break;
    case OV_RANK_UD_CONV:
        retn = compareScalar( &first->u.ud.out
                            , first_type
                            , &second->u.ud.out
                            , second_type
                            , TRUE
                            , control );
        break;
    case OV_RANK_STD_CONV_DERIV:
        if( ( first_type != NULL ) && ( second_type != NULL ) ) {
            retn = compareDerived( *first_type, *second_type );
            if( retn != OV_CMP_SAME ) {
                break;
            }
        }
        // two target types are not releated
        // otherwise, do the following comparison
    case OV_RANK_STD_CONV_VOID:
    case OV_RANK_STD_CONV:
    case OV_RANK_STD_BOOL:
    case OV_RANK_PROMOTION:
    case OV_RANK_TRIVIAL:
        retn = compareScalar( &first->u.no_ud
                             , first_type
                             , &second->u.no_ud
                             , second_type
                             , FALSE
                             , control);
        break;
    case OV_RANK_SAME:
    case OV_RANK_EXACT:
        retn = OV_CMP_SAME;
        break;
    DbgDefault( "funny rank\n" );
    }
    return( retn );
}
#endif

static OV_RESULT compareFunction(
/*******************************/
    FNOV_LIST *first
  , FNOV_LIST *second
  , FNOV_CONTROL control )
// compare ranking of first and second
// returns one of:
//       OV_CMP_BETTER_FIRST
//       OV_CMP_BETTER_SECOND
//       OV_CMP_SAME
{
    int         index;
    FNOV_RANK   *first_arg;
    FNOV_RANK   *second_arg;
    OV_RESULT   result;
    OV_RESULT   retn;
    TYPE        *first_type;
    TYPE        *second_type;

    retn = OV_CMP_UNDEFINED;
    index = first->num_args;
    first_arg  = first->rankvector;
    second_arg = second->rankvector;
    first_type = first->alist->type_list;
    second_type = second->alist->type_list;
    for(;;) {
        if( retn == OV_CMP_SAME ) break;
        if( index == 0 ) break;
        result = compareArgument( first_arg
                                , first_type
                                , second_arg
                                , second_type
                                , control );
        switch( result ) {
        case OV_CMP_BETTER_FIRST:
            switch( retn ) {
            case OV_CMP_UNDEFINED:
                retn = OV_CMP_BETTER_FIRST;
                break;
            case OV_CMP_BETTER_SECOND:
                retn = OV_CMP_SAME;
                break;
            }
            break;
        case OV_CMP_BETTER_SECOND:
            switch( retn ) {
            case OV_CMP_UNDEFINED:
                retn = OV_CMP_BETTER_SECOND;
                break;
            case OV_CMP_BETTER_FIRST:
                retn = OV_CMP_SAME;
                break;
            }
            break;
        }
        index--;
        first_arg++;
        second_arg++;
        first_type++;
        second_type++;
    }
    if( retn == OV_CMP_UNDEFINED ) {
        result = compareArgument( &first->thisrank
                                , NULL
                                , &second->thisrank
                                , NULL, FNC_DEFAULT );
        switch( result ) {
        case OV_CMP_BETTER_FIRST:
            retn = OV_CMP_BETTER_FIRST;
            break;
        case OV_CMP_BETTER_SECOND:
            retn = OV_CMP_BETTER_SECOND;
            break;
        default:
            retn = OV_CMP_SAME;
            break;
        }
    }
    return( retn );
}

static boolean isRank( FNOV_LIST *entry, FNOV_COARSE_RANK level )
/***************************************************************/
// see if rank of entry is all <= level
// if so, return TRUE, else FALSE
{
    int                 index;
    FNOV_RANK           *rank;
    boolean             retn;

    retn = TRUE;
    rank = entry->rankvector;
    index = entry->num_args;
    for(;;) {
        if( !retn ) break;
        if( index == 0 ) break;
        retn = ( rank->rank <= level );
        index--;
        rank++;
    }
    if( retn ) {
        retn = ( entry->thisrank.rank <= level );
    }
    return( retn );
}

static void setRank( FNOV_LIST *entry, FNOV_COARSE_RANK level )
/*************************************************************/
// make rank = level
{
    int                 index;
    FNOV_RANK           *rank;

    rank = entry->rankvector;
    index = entry->num_args;
    for(;;) {
        if( index == 0 ) break;
        rank->rank = level;
        index--;
        rank++;
    }
    entry->thisrank.rank = level;
}

static boolean isReturnIdentical( TYPE sym1, TYPE sym2 )
/******************************************************/
// see if two functions have indentical return types
{
    boolean retn;

    retn = TypesSameExclude( FunctionDeclarationType( sym1 )->of
                           , FunctionDeclarationType( sym2 )->of
                           , TC1_NOT_ENUM_CHAR );

    return( retn );
}

static void doComputeArgRank( SYMBOL sym, TYPE src, TYPE tgt, PTREE *pt,
/**********************************************************************/
    FNOV_RANK *rank )
{
    if( (rank->control & FNC_TEMPLATE) &&
        SymIsFunctionTemplateModel( sym ) ) {
        rank->rank = OV_RANK_NO_MATCH;
        return;
    }
    FnovArgRank( src, tgt, pt, rank );
    if( (rank->control & FNC_EXCLUDE_CONV) &&
        (rank->rank > OV_RANK_TRIVIAL) &&
        (TypeReference( tgt ) != NULL) ) {
        rank->rank = OV_RANK_NO_MATCH;
    } else if( (rank->control & FNC_TEMPLATE) &&
        (rank->rank > OV_RANK_TRIVIAL) &&
        SymIsFunctionTemplateInst( sym ) ) {
        rank->rank = OV_RANK_NO_MATCH;
    } else if( (rank->control & FNC_DISTINCT_CHECK) &&
        (rank->rank == OV_RANK_SAME) ) {
        FnovArgRank( tgt, src, NULL, rank );
    }
}


static boolean computeUdcRank( FNOV_INFO* info )
/***************************************************************/
// fill in rankvector, ranking of conversion func return value to arg_list
// if u-d conversion is a candidate, return TRUE, else FALSE
{
    FNOV_RANK   *frv;
    TYPE        src;
    TYPE        tgt;
    FNOV_LIST   *func;

    func = info->candfunc;
    src = FunctionDeclarationType( func->sym->sym_type )->of;
    tgt = info->alist->type_list[0];

    frv = func->rankvector;
    doComputeArgRank( func->sym, src, tgt, NULL, frv );
    if( frv->rank == OV_RANK_NO_MATCH ) {
        return( FALSE );
    }
    return( TRUE );
}

static void moveRingFromTo( FNOV_LIST **from, FNOV_LIST **to )
/************************************************************/
// remove each element in from list, add each into to list
{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?