fnovload.c

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

C
1,907
字号
static void setFnovDiagnosticRejectList( FNOV_DIAG *fnov_diag,
                                         FNOV_LIST **reject )
/***********************************************************/
{
    if( fnov_diag == NULL ) {
        FnovListFree( reject );
    } else {
        if( fnov_diag->diag_reject != NULL ) {
            FnovListFree( &fnov_diag->diag_reject );
        }
        fnov_diag->diag_reject = *reject;
    }
}

static SYMBOL getNextDiagnosticEntry( FNOV_LIST **list )
/******************************************************/
{
    SYMBOL      sym = NULL;
    FNOV_LIST   *head;

    head = RingPop( list );
    if( head != NULL ) {
        sym = head->sym;
        head->next = head;
        FnovListFree( &head );
    }
    return( sym );
}

SYMBOL FnovNextAmbiguousEntry( FNOV_DIAG *fnov_diag )
/**********************************************/
{
    return getNextDiagnosticEntry( &fnov_diag->diag_ambig );
}

SYMBOL FnovGetAmbiguousEntry( FNOV_DIAG *fnov_diag, FNOV_LIST **ptr )
/*******************************************************************/
{
    SYMBOL sym;

    sym = NULL;
    if( *ptr == NULL ) {
        if( fnov_diag != NULL && fnov_diag->diag_ambig != NULL ) {
            sym = fnov_diag->diag_ambig->sym;
            *ptr = fnov_diag->diag_ambig->next;
        }
    } else if( ( fnov_diag == NULL) || (*ptr != fnov_diag->diag_ambig) ) {
        sym = (*ptr)->sym;
        *ptr = (*ptr)->next;
    }
    return( sym );
}

SYMBOL FnovNextRejectEntry( FNOV_DIAG *fnov_diag )
/*******************************************/
{
    return getNextDiagnosticEntry( &fnov_diag->diag_reject );
}

int FnovRejectParm( FNOV_DIAG *fnov_diag )
/****************************************/
{
    FNOV_RANK   *rank;
    int         index;
    int         num_args;

    if( ( fnov_diag != NULL ) && ( fnov_diag->diag_reject != NULL ) ) {
        rank = fnov_diag->diag_reject->rankvector;
        num_args = fnov_diag->diag_reject->num_args;
        if( (num_args == 0) || (rank->control & FNC_RANK_RETURN) ) {
            num_args = 1;
        }
        for( index = 0; index < num_args ; index++, rank++ ) {
            if( rank->rank >= OV_RANK_NO_MATCH ) return( index );
        }
        if( fnov_diag->diag_reject->member != 0 ) {
            if( fnov_diag->diag_reject->thisrank.rank >= OV_RANK_NO_MATCH ) return( -1 );
        }
    }
    return( -2 );
}

//--------------------------------------------------------------------
// General Support
//--------------------------------------------------------------------

static boolean isEllipsisCandidate( TYPE type, int num_args )
/***********************************************************/
// determine if type is a candidate based on:
//      type having more than zero arguments
//      type having fewer arguments than num_args and
//              last argument is ellipsis, or
//      type having exactly one more argument than num_args which is ellipsis
{
    TYPE argtype;
    arg_list *alist;

    type = FunctionDeclarationType( type );
    if( type != NULL ) {
        alist = TypeArgList( type );
        if( alist->num_args != 0 ) {
            if( ( alist->num_args < num_args )
              ||( alist->num_args == num_args+1 ) ) {
                argtype = alist->type_list[alist->num_args-1];
                if( argtype->id == TYP_DOT_DOT_DOT ) {
                    return( TRUE );
                }
            }
        }
    }
    return( FALSE );
}

static boolean isMemberCandidate( TYPE type, int num_args )
/*********************************************************/
// determine if sym is a candidate based on the number of arguments
// including a this pointer
{
    type = FunctionDeclarationType( type );
    if( type != NULL ) {
        if( (TypeArgList( type )->num_args+1) == num_args ) {
            return( TRUE );
        }
    }
    return( FALSE );
}


static boolean isSimpleCandidate( TYPE type, int num_args )
/*********************************************************/
// determine if sym is a candidate based on the number of arguments
{
    type = FunctionDeclarationType( type );
    if( type != NULL ) {
        if( TypeArgList( type )->num_args == num_args ) {
            return( TRUE );
        }
    }
    return( FALSE );
}

static void processSym( FNOV_CONTROL control, FNOV_INFO* info, SYMBOL sym )
/****************************************************************************/
{
    arg_list    *mock_args;
    arg_list    *func_args;

    if(( control & FNC_NO_DEALIAS ) == 0 ) {
        sym = SymDeAlias( sym );
    }
    func_args = SymFuncArgList( sym );
    if( control & FNC_RANK_RETURN ) {
        addListEntry( control, info, sym, func_args, LENT_DEFAULT );
    } else {
        int num_args = info->alist->num_args;
        TYPE sym_type = sym->sym_type;
        if( control & FNC_MEMBER ) {
            if( isMemberCandidate( sym_type, num_args ) ) {
                mock_args = MakeMemberArgList( sym, num_args );
                addListEntry( control, info, sym, mock_args, LENT_FREE_ARGS );
            }
        } else {
            if( !( SymIsDefArg(sym) && (control & FNC_EXCLUDE_DEFARG ) ) ) {
                if( isSimpleCandidate( sym_type, num_args ) ) {
                    addListEntry( control, info, sym, func_args, LENT_TPL_CHECK );
                } else if( !(control & FNC_EXCLUDE_ELLIPSIS) ) {
                    if( isEllipsisCandidate( sym_type, num_args ) ) {
                        mock_args = MakeMockArgList( sym_type, num_args );
                        addListEntry( control
                                    , info
                                    , sym
                                    , mock_args
                                    , LENT_FREE_ARGS | LENT_TPL_CHECK );
                    }
                }
            }
        }
    }
}

static void buildUdcListDiag(   // BUILD FNOV_LIST FOR USER-DEFD CONVERSIONS
/***************************/
    FNOV_LIST **pcandidates,    // - current list
    SYMBOL sym,                 // - symbol to add
    FNOV_DIAG *fnov_diag )      // - diagnosis information (can be NULL)
{
    FNOV_INFO info;

    info.control = FNC_RANK_RETURN;
    info.plist = NULL;
    info.alist = NULL;
    info.pcandidates = pcandidates;
    info.pmatch = NULL;
    info.has_template = FALSE;
    info.fnov_diag = fnov_diag;
    processSym( FNC_RANK_RETURN, &info, sym );
}

void BuildUdcList(              // BUILD FNOV_LIST FOR USER-DEFD CONVERSIONS
/****************/
    FNOV_LIST **pcandidates,    // - current list
    SYMBOL sym )                // - symbol to add
{
    buildUdcListDiag( pcandidates, sym, NULL );
}

static void buildOverloadListFromSym( FNOV_CONTROL control,
    FNOV_INFO *info, SYMBOL sym )
/*********************************************************/
{
    SYMBOL  ptr;

    if( control & FNC_ONLY_SYM ) {
        processSym( control, info, sym );
    } else {
        RingIterBeg( sym, ptr ) {
            processSym( control, info, ptr );
        } RingIterEnd( ptr )
    }
}

static void buildOverloadListFromRegion( FNOV_CONTROL control,
/*********************************************************/
FNOV_INFO *info, SYM_REGION *region )
{
    SYMBOL      sym;
    SYM_REGION  *ptr;

    DbgAssert( (control & FNC_ONLY_SYM) == 0 );
    RingIterBeg( region, ptr ) {

        RingIterBegFrom( ptr->from, sym ) {
            processSym( control, info, sym );
        } RingIterEndTo( sym, ptr->to )

    } RingIterEnd( ptr )
}

static OV_RESULT compareInt( int first, int second )
/**************************************************/
{
    OV_RESULT   retn;

    if( first < second ) {
        retn = OV_CMP_BETTER_FIRST;
    } else if( first > second ) {
        retn = OV_CMP_BETTER_SECOND;
    } else {
        retn = OV_CMP_SAME;
    }
    return( retn );
}

static boolean myTypesSame( TYPE first_type, TYPE second_type )
{
    void        *refbase;
    type_flag   flag;
    boolean     same;

    while( ( first_type->id == TYP_POINTER || first_type->flag & TF1_REFERENCE )
        && ( second_type->id == TYP_POINTER || second_type->flag & TF1_REFERENCE ) ) {
        first_type = TypeModExtract( first_type->of
                              , &flag
                              , &refbase
                              , TC1_NOT_ENUM_CHAR| TC1_FUN_LINKAGE  );
        second_type = TypeModExtract( second_type->of
                              , &flag
                              , &refbase
                              , TC1_NOT_ENUM_CHAR| TC1_FUN_LINKAGE  );
    }
    same = TypesSameExclude( first_type, second_type,
                             TC1_NOT_ENUM_CHAR| TC1_FUN_LINKAGE  );
    if( !same ) {
        if( first_type->flag & TF1_STDOP || second_type->flag & TF1_STDOP ) {
            same = TRUE;
        }
    }
    return same;
}

// code for WP13332
static OV_RESULT WP13332(
/***********************/
    TYPE * first_type,
    TYPE * second_type,
    OV_RESULT def_retn )
{
    TYPE *better;

    if( ( first_type == NULL ) || ( second_type == NULL ) ) {
        return( def_retn );
    }
    if( ( *first_type == NULL ) || ( *second_type == NULL ) ) {
        return( def_retn );
    }
    if( !myTypesSame( *first_type, *second_type ) ) {
        return( OV_CMP_SAME );
    }
    better = CompareWP13332( first_type, second_type );
    if( better != NULL ) {
        if( better == first_type ) {
            return( OV_CMP_BETTER_FIRST );
        } else {
            return( OV_CMP_BETTER_SECOND );
        }
    }
    return( OV_CMP_SAME );
}

static OV_RESULT compareScalar( FNOV_SCALAR *first, TYPE *first_type,
/**********************************************************************/
 FNOV_SCALAR *second, TYPE *second_type, boolean isUDC,
 FNOV_CONTROL control )
{
    OV_RESULT   retn;

    if( first->udcnv != second->udcnv ) {
        retn = compareInt( first->udcnv, second->udcnv );
    } else if( first->standard != second->standard ) {
        retn = compareInt( first->standard, second->standard );
    } else if( first->promotion != second->promotion ) {
        retn = compareInt( first->promotion, second->promotion );
    } else if( first->trivial != second->trivial &&
               (
#ifndef NEW_TRIVIAL_RULE
TRUE ||
#endif
               !isUDC || first_type == NULL || second_type == NULL ||
               myTypesSame( *first_type, *second_type ) ) ) {
        // all else being equal, can decide on number of added cv-qualifiers
        // if two implicit comversion sequences yield types identical except
        // for their cv-qualification
        // [over.ics.rank]
        retn = compareInt( first->trivial, second->trivial );

        if( CompFlags.overload_13332 && ( control & FNC_USE_WP13332 ) ) {
            // this is for full implementation of WP13332
            retn = WP13332( first_type, second_type, retn );
        }
    } else {
        retn = OV_CMP_SAME;
    }
    return( retn );
}


static OV_RESULT compareDerived(TYPE first_type, TYPE second_type )
/******************************************************************/
/*
  13.3.3.2 paragraph 4
   If class B is derived directly or indirectly from class A and class
   C is derived directly or indirectly from B:
   - converting C* -> B* is better than C* -> A*
   - binding    C  -> B&  is better than C -> A&
   - converting C -> B is better than C -> A
   - converting A::* -> B::* is better than A::* to C::*
   etc.
   basically, it the two target class are related, the one that is closer
   to the source was a better conversion
*/
{
    SCOPE first_scope;
    SCOPE second_scope;

    TYPE base_first = first_type;
    TYPE base_second = second_type;

    if( first_type->id != second_type->id ) {
        // if they're not both references, classes, pointers of member
        // pointers that we can't examine them here
        return( OV_CMP_SAME );
    }
    // check for reference to reference conversion
    if( first_type->id == TYP_POINTER && second_type->id == TYP_POINTER ) {
        // both either pointers or references
        base_first = TypeReference( first_type );
        base_second = TypeReference( second_type );

        if( base_first == NULL && base_second == NULL ) {
            // neither is a reference so both are pointers
            base_first = first_type->of;
            base_second = second_type->of;

⌨️ 快捷键说明

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