fnovload.c

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

C
1,907
字号
    FNOV_LIST *curr;

    RingIterBegSafe( *from, curr ) {
        RingPrune( from, curr );
        RingInsert( to, curr, NULL );
    } RingIterEndSafe( curr );
}

static void resolveOneList( FNOV_LIST **list, FNOV_LIST **match,
/******************************************************************/
FNOV_LIST **rejects, boolean *ambiguous, boolean is_ctor )
// Continue resolving, starting from the current 'match' and 'rejects' lists.
{
    FNOV_LIST  *curr;           // current element of list
    OV_RESULT   result;         // result of comparision call
    arg_list    *arg;           // arg list for ctor

    RingIterBegSafe( *list, curr ) {
        if( curr->rankvector->rank != OV_RANK_NO_MATCH ) {
            RingPrune( list, curr );
            if( *match != NULL ) {
                result = compareArgument( (*match)->rankvector, NULL,
                                          curr->rankvector, NULL, FNC_DEFAULT );
                if( result == OV_CMP_SAME && !is_ctor ) {
                    result = compareArgument( &(*match)->thisrank, NULL
                                              , &curr->thisrank, NULL, FNC_DEFAULT );
                }
                switch( result ) {
                case OV_CMP_BETTER_FIRST:
                    RingInsert( rejects, curr, NULL );
                    break;
                case OV_CMP_BETTER_SECOND:
                    moveRingFromTo( match, rejects );
                    RingInsert( match, curr, NULL );
                    *ambiguous = FALSE;
                    break;
                case OV_CMP_SAME:
                    RingInsert( match, curr, NULL );
                    *ambiguous = TRUE;
                    break;
                }
            } else {
                RingInsert( match, curr, NULL );
            }
        } else {
            if( is_ctor ) {
                arg = SymFuncArgList( curr->sym );
                if( arg->num_args == 1 ) {
                    RingPrune( list, curr );
                    RingInsert( rejects, curr, NULL );
                }
            } else {
                RingPrune( list, curr );
                RingInsert( rejects, curr, NULL );
            }
        }
    } RingIterEndSafe( curr )
}

FNOV_COARSE_RANK RankandResolveUDCsDiag( FNOV_LIST **ctorList,
/***********************************************************************/
FNOV_LIST **udcfList, TYPE src, TYPE tgt, boolean *isctor,
FNOV_LIST **pmatch, FNOV_UDC_CONTROL control, FNOV_INTRNL_CONTROL ictl,
PTREE *src_ptree, FNOV_RANK *rank, FNOV_DIAG *fnov_diag)
// rank elements of both the ctor list an the udcf list
// resolve ranks of both lists as if they were in one merged list
{
    boolean             ambiguous;
    FNOV_LIST           *between_match;
    FNOV_LIST           *rejects;
    FNOV_COARSE_RANK    result;
    FNOV_LIST           *match;

    udcRankCtor( *ctorList, src, tgt, control, ictl, src_ptree );
    udcRankUDCF( *udcfList, src, tgt, ictl, src_ptree );
    match = NULL;
    rejects = NULL;
    ambiguous = FALSE;
    resolveOneList( ctorList, &match, &rejects, &ambiguous, TRUE );
    between_match = match;
    resolveOneList( udcfList, &match, &rejects, &ambiguous, FALSE );
    if( isctor != NULL ) {
        *isctor = ( between_match == match);
    }


    if( ambiguous ) {
        result = OV_RANK_UD_CONV_AMBIG;
    } else {
        if( match == NULL ) {
            result = OV_RANK_NO_MATCH;
        } else {
            result = OV_RANK_UD_CONV;
        }
    }
    if( rank != NULL ) {
        rank->rank = result;
        if( result != OV_RANK_NO_MATCH ) {
            rank->userdef = 1;
            if( between_match == match ) { // ctor
                rank->u.ud.in = match->rankvector->u.no_ud;
                // need rank->u.ud.out
                rank->u.ud.out = rankCtorReturn( match, tgt, src_ptree );
                if( match->rankvector->rank == OV_RANK_UD_CONV ) {
                    rank->u.ud.out.udcnv++;
                }
            } else { // UDCF
                rank->u.ud.out = match->rankvector->u.no_ud;
            }
        }
    }
    if( fnov_diag != NULL ) {
        fnov_diag->num_candidates = RingCount( match ) + RingCount( rejects );
    }
    if( ambiguous ) {
        setFnovDiagnosticAmbigList( fnov_diag, &match );
        match = NULL;
    }
    if( pmatch != NULL ) {
        *pmatch = match;
    } else {
        FnovListFree( &match );
    }
    setFnovDiagnosticRejectList( fnov_diag, &rejects );
    FnovListFree( ctorList ); // will contain those with other than one parm
    DbgAssert( *udcfList == NULL );
    return result;
}

static void computeFuncRankSym( SYMBOL fsym, SYMBOL curr, TYPE *tgt,
/***********************************************************************/
// ranks curr, updating bestrank
FNOV_RANK *bestrank, FNOV_RANK *curr_rank, boolean src_mptr )
{
    OV_RESULT       result;
    TYPE            curr_type;

    curr_rank->rank = OV_RANK_NO_MATCH;
    curr_type = NULL;
    if( SymIsThisFuncMember( curr ) ) {
        if( src_mptr ) {
            // curr is member function
            // src can be member function
            curr_type = MakeMemberPointerTo( SymClass( curr )
                                           , curr->sym_type );
        }
    } else {
        // curr is static member function
        // src can be static member functions
        curr_type = curr->sym_type;
    }
    if( curr_type != NULL ) {
        doComputeArgRank( fsym, curr_type, *tgt, NULL, curr_rank );
        if( curr_rank->rank != OV_RANK_NO_MATCH ) {
            result = compareArgument( bestrank, NULL, curr_rank, NULL, FNC_DEFAULT );
            if( result == OV_CMP_BETTER_SECOND ) {
                *bestrank = *curr_rank;
            }
        }
    }
}

static void computeFuncRank( SYMBOL fsym, SYMBOL sym, TYPE *tgt,
/***********************************************************************/
// called only when an argument is a (possible overloaded) function symbol
FNOV_RANK *bestrank, PTREE *ptlist )
{
    boolean             src_mptr;   // can src be a pointer to member
    PTREE               fn;
    unsigned            retn;
    SYMBOL              curr;
    SYM_REGION          *region;
    auto FNOV_RANK      curr_rank;
    SEARCH_RESULT       *result;

    initRankVector( FNC_DEFAULT, &curr_rank, 0 );
    retn = NodeAddrOfFun( *ptlist, &fn );
    DbgAssert( retn != ADDR_FN_NONE );
    src_mptr = FALSE;
    if( fn->flags & PTF_COLON_QUALED ) { // i.e. S::foo not just foo
        // &S::foo can be a mptr
        // just S:: can also be a mptr if extensions enabled
        src_mptr = ( retn == ADDR_FN_MANY || retn == ADDR_FN_ONE ||
                     CompFlags.extensions_enabled );

    }
    bestrank->rank = OV_RANK_NO_MATCH;
    result = fn->u.symcg.result;
    if( result == NULL || result->region == NULL ) {
        RingIterBeg( sym, curr ) {
            computeFuncRankSym( fsym
                              , curr
                              , tgt
                              , bestrank
                              , &curr_rank
                              , src_mptr );
        } RingIterEnd( curr )
    } else {

        RingIterBeg( result->region, region ) {
            RingIterBegFrom( region->from, curr ) {
                computeFuncRankSym( fsym
                                  , curr
                                  , tgt
                                  , bestrank
                                  , &curr_rank
                                  , src_mptr );
            } RingIterEndTo( curr, region->to )
        } RingIterEnd( region )

    }
}

static boolean computeFunctionRank( FNOV_INFO* info )
/***************************************************/
// fill in rankvector, ranking of conversion of arg_list to func arguments
// if function is a candidate, return TRUE, else FALSE
{
    int         index;
    TYPE        *tgt;
    TYPE        *src;
    FNOV_RANK   *rank;
    SYMBOL      sym;
    PTREE       *ptlist;
    FNOV_LIST   *func;

    index = info->alist->num_args;
    src   = info->alist->type_list;
    func  = info->candfunc;
    tgt   = func->alist->type_list;
    rank  = func->rankvector;
    ptlist = info->plist;
    for(;;) {
        if( index == 0 ) break;
        if( ptlist != NULL ) {
            sym = FunctionSymbol( *ptlist );
            if( sym != NULL ) {
                computeFuncRank( func->sym, sym, tgt, rank, ptlist );
            } else {
                doComputeArgRank( func->sym, *src, *tgt, ptlist, rank );
            }
        } else {
            doComputeArgRank( func->sym, *src, *tgt, NULL, rank );
        }
        if( rank->control & FNC_DISTINCT_CHECK ) {
            if( rank->rank > OV_RANK_SAME ) {
                // short circuit for distinct check
                return( FALSE );
            }
        }
        if( rank->rank == OV_RANK_NO_MATCH ) {
            return( FALSE );
        }
        index--;
        tgt++;
        src++;
        if( ptlist != NULL ) ptlist++;
        rank++;
    }
    return( TRUE );
}

static boolean getRank( FNOV_INFO* info )
/***************************************/
// get a rankvector (allocate if necessary) and compute the rank
// returns TRUE if rank is a contender, else FALSE
{
    boolean contender;
    FNOV_LIST* candidate = info->candfunc;

    if( candidate->rankvector != NULL ) {
        contender = TRUE;
    } else {
        FNOV_CONTROL control = info->control;
        if( candidate->member ) {
            control |= FNC_MEMBER;
        }
        if( candidate->stdops ) {
            control |= FNC_STDOPS;
        }
        addRankVector( candidate, control );
        assert( info->alist != NULL );
        if( control & FNC_RANK_RETURN ) {
            contender = computeUdcRank( info );
        } else {
            contender = computeFunctionRank( info );
        }
        if( contender && SymIsThisFuncMember( candidate->sym ) ) {
            type_flag   srcflags = info->alist->qualifier;
            type_flag   tgtflags = candidate->alist->qualifier;
            if( !FnovCvFlagsRank( srcflags, tgtflags, &candidate->thisrank ) ) {
                FnovMemFlagsRank( srcflags, tgtflags, NULL, NULL,
                              &candidate->thisrank );
            }
        }
    }
    return( contender );
}

static OV_RESULT updateMatchList( FNOV_INFO *info )
/*************************************************/
// walk pmatch list and compare candidate with each entry:
// if candidate is worse than entry then quit
// if candidate is better than entry then remove entry from pmatch
//      and insert entry onto the head of pcandidates
// if candidate is the same as entry then leave it be
// if we get to the end of the loop,
//      remove candidate from pcandidate list
//      and add candidate to the pmatch list
{
    FNOV_LIST   *entry;
    OV_RESULT   comparison;
    int         ambiguous;

    ambiguous = FALSE;
    RingIterBegSafe( *info->pmatch, entry ) {
        comparison = compareFunction( entry, info->candfunc, info->control );
        if( comparison == OV_CMP_BETTER_FIRST ) {
            return( OV_CMP_BETTER_FIRST );
        } else if( comparison == OV_CMP_BETTER_SECOND ) {
            RingPrune( info->pmatch, entry );
            RingInsert( info->pcandidates, entry, NULL );
        } else if( comparison == OV_CMP_SAME ) {
            if( entry->sym == info->candfunc->sym ) {
                return( OV_CMP_BETTER_FIRST ); // have the same symbol twice
            }
            ambiguous = TRUE;
        }
    } RingIterEndSafe( entry )
    RingPrune( info->pcandidates, info->candfunc );
    RingAppend( info->pmatch, info->candfunc );
    if( ambiguous ) {
        return( OV_CMP_SAME );
    }
    return( OV_CMP_BETTER_SECOND );
}

static void updateFnovList( FNOV_INFO *info )
/*******************************************/
// update lists and summary result
{
    OV_RESULT   comparison;

    comparison = updateMatchList( info );
    if( comparison == OV_CMP_SAME ) {
        // candidate is ambiguous with pmatch list
        info->result = FNOV_AMBIGUOUS;
    } else if( comparison == OV_CMP_BETTER_SECOND ) {
        // candidate is better than pmatch list
        info->result = FNOV_NONAMBIGUOUS;
    }
        // otherwise candidate is worse than pmatch list which doesn't
        // change the presult value
}

static FNOV_RESULT resolveOverload( FNOV_INFO* info )
/***************************************************/
// go through each member of pcandidates looking for best match
// returns FNOV_NO_MATCH     - no match found,
//                              pmatch = NULL
//         FNOV_AMBIGUOUS    - no unique match found,
//                              pmatch = list of ambiguous entries
//         FNOV_NONAMBIGUOUS - unique match found,
//                              pmatch = unique entry
{
    info->result = FNOV_NO_MATCH;
    *info->pmatch = NULL;
    RingIterBegSafe( *info->pcandidates, info->candfunc ) {
        if( getRank( info ) ) {
            updateFnovList( info );
        }
    } RingIterEndSafe( info->candfunc )
    return info->result;
}

static FNOV_RESULT genTemplateFunction( arg_list *alist, SYMBOL *psym,
/********************************************************************/
    TOKEN_LOCN *locn, SYMBOL *ambigs, boolean ok_if_no_exact_bind )
{
    FNOV_RESULT result;
    SYMBOL sym;

⌨️ 快捷键说明

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