fnovload.c

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

C
1,907
字号
    sym = *psym;
    result = TemplateFunctionGenerate( &sym, alist, locn, ambigs, ok_if_no_exact_bind );
    if( result == FNOV_NONAMBIGUOUS ) {
        *psym = sym;
    }
    return( result );
}

static SYMBOL findFunctionTemplate( FNOV_INFO *info )
/***************************************************/
{
    SYMBOL sym;
    FNOV_LIST *curr;

    RingIterBeg( *info->pcandidates, curr ){
        sym = curr->sym;
        if( SymIsFunctionTemplateModel( sym ) ) {
            return( sym );
        }
    } RingIterEnd( curr )
#ifndef NDEBUG
    CFatal( "can't find function template during overload" );
#endif
    return( NULL );
}

static TOKEN_LOCN *extractAGoodLocn( FNOV_INFO* info )
/****************************************************/
{
    TOKEN_LOCN *locn;
    PTREE *plist;

    plist = info->plist;
    /* simple for now; but who knows? */
    if( plist == NULL ) {
        // NYI: what location do we give to a "return foo;" when there is
        // more than one foo (currently a NULL locn because there are no args)
        return( NULL );
    }
    locn = &((*plist)->locn);
    return( locn );
}

static FNOV_RESULT doOverload( FNOV_INFO* info )
/**********************************************/
{
    FNOV_RESULT result = FNOV_NO_MATCH;
    FNOV_LIST   *match = NULL;
    TOKEN_LOCN *locn;

    *info->pmatch = NULL;
    if( *info->pcandidates != NULL ) {
        result = resolveOverload( info );
        if( result != FNOV_NONAMBIGUOUS
         || ! isRank( *info->pmatch, OV_RANK_SAME ) ) {
            if( ( info->control & ( FNC_TEMPLATE | FNC_DISTINCT_CHECK ) )
                == FNC_TEMPLATE ) {
                SYMBOL      sym;
                FNOV_RESULT t_result;
                auto SYMBOL ambigs[2];

                sym = findFunctionTemplate( info );
                t_result = FNOV_NO_MATCH;
                if( sym != NULL ) {
                    locn = extractAGoodLocn( info );
                    t_result = genTemplateFunction( info->alist
                                                  , &sym
                                                  , locn
                                                  , ambigs
                                                  , result == FNOV_NONAMBIGUOUS );
                }
                if( t_result == FNOV_NONAMBIGUOUS ) {
                    FnovListFree( info->pmatch );
                    addListEntry( FNC_DEFAULT
                                , info
                                , sym
                                , SymFuncArgList( sym )
                                , LENT_MATCH );
                    addRankVector( *info->pmatch, info->control );
                    setRank( *info->pmatch, OV_RANK_SAME );
                    result = FNOV_NONAMBIGUOUS;
                } else if( t_result == FNOV_AMBIGUOUS ) {
                    FnovListFree( info->pmatch );
                    result = FNOV_AMBIGUOUS;
                    addListEntry( FNC_DEFAULT
                                , info
                                , ambigs[0]
                                , SymFuncArgList( ambigs[0] )
                                , LENT_MATCH );
                    addListEntry( FNC_DEFAULT
                                , info
                                , ambigs[1]
                                , SymFuncArgList( ambigs[1] )
                                , LENT_MATCH );
                }
            }
            if( result != FNOV_NONAMBIGUOUS ) {
                match = *info->pmatch;
                *info->pmatch = NULL;
            }
        }
    }

#ifndef NDEBUG
    if( PragDbgToggle.dump_rank ) {
        printf( "\nOverloaded Symbol Resolution" );
        PrintFnovResolution( result
                           , info->alist
                           , match == NULL ? *info->pmatch : match
                           , *info->pcandidates
                           , NULL );
    }
#endif

    if( result != FNOV_NONAMBIGUOUS ) {
        setFnovDiagnosticAmbigList( info->fnov_diag, &match );
    }
    setFnovDiagnosticRejectList( info->fnov_diag, info->pcandidates );
    return( result );
}

FNOV_DIAG * FnovInitDiag( FNOV_DIAG *fnov_diag )
/**********************************************/
{
    if( fnov_diag != NULL ) {
        fnov_diag->diag_ambig = NULL;
        fnov_diag->diag_reject = NULL;
        fnov_diag->num_candidates = LIST_FREE;
    }
    return( fnov_diag );
}

FNOV_RESULT FuncOverloadedLimitDiag( SYMBOL *resolved,
/****************************************************************/
SEARCH_RESULT *result_in, SYMBOL sym, arg_list *alist, PTREE *ptlist,
FNOV_CONTROL control, FNOV_DIAG *fnov_diag )
// find overloaded function from sym for alist specified
{
    FNOV_LIST   *candidates = NULL;
    FNOV_INFO   info;
    FNOV_LIST   *match;
    FNOV_RESULT result;

    *resolved = NULL;

    info.alist = alist;
    info.plist = ptlist;
    info.pcandidates = &candidates;
    info.pmatch = &match;
    info.control = control;
    info.has_template = FALSE;
    info.fnov_diag = fnov_diag;

    if( ( result_in == NULL) || (result_in->region == NULL) ) {
        buildOverloadListFromSym( info.control, &info, sym );
    } else {
        buildOverloadListFromRegion( info.control, &info, result_in->region );
    }
    if( info.has_template ) {
        info.control |= FNC_TEMPLATE;
    }
    fnovNumCandidatesSet( info.fnov_diag, *info.pcandidates );
    result = doOverload( &info );
    if( match != NULL ) {
        *resolved = match->sym;
        FnovListFree( &match );
    }
    return( result );
}

FNOV_RESULT FuncOverloadedDiag( SYMBOL *resolved, SEARCH_RESULT *result,
/***********************************************************************/
SYMBOL sym, arg_list *alist, PTREE *ptlist, FNOV_DIAG *fnov_diag )
// find overloaded function from sym for alist specified
{
    fnov_diag = FnovInitDiag( fnov_diag );
    return( FuncOverloadedLimitDiag( resolved, result, sym, alist, ptlist,
                                     FNC_DEFAULT, fnov_diag ) );
}

FNOV_RESULT FuncOverloaded( SYMBOL *resolved, SEARCH_RESULT *result,
/***********************************************************************/
SYMBOL sym, arg_list *alist, PTREE *ptlist )
// find overloaded function from sym for alist specified
{
    return( FuncOverloadedDiag( resolved, result, sym, alist, ptlist, NULL ) );
}

FNOV_RESULT UdcOverloadedDiag( SYMBOL *resolved, SEARCH_RESULT *result,
/*****************************************************************/
SYMBOL sym, TYPE type, type_flag this_qualifier, FNOV_DIAG *fnov_diag )
// find overloaded user-defined conversion from sym for return type specified
// use this_qualifiers from arg_list
{
    arg_list        alist;

    InitArgList( &alist );
    alist.num_args = 1;
    alist.qualifier = this_qualifier;
    alist.type_list[0] = type;
    fnov_diag = FnovInitDiag( fnov_diag );
    return( FuncOverloadedLimitDiag( resolved
                                   , result
                                   , sym
                                   , &alist
                                   , NULL
                                   , FNC_RANK_RETURN
                                   , fnov_diag ));
}

FNOV_RESULT UdcOverloaded( SYMBOL *resolved, SEARCH_RESULT *result,
/*****************************************************************/
SYMBOL sym, TYPE type, type_flag this_qualifier )
// find overloaded user-defined conversion from sym for return type specified
// use this_qualifiers from arg_list
{
    return( UdcOverloadedDiag( resolved, result, sym, type, this_qualifier, NULL ) );

}

static FNOV_RESULT opOverloadedLimitExDiag( SYMBOL *resolved, SEARCH_RESULT *member,
/******************************************************************/
    SEARCH_RESULT *nonmember, SEARCH_RESULT *namesp, SYMBOL stdops, arg_list *alist, PTREE *ptlist,
    boolean scalar_convert, FNOV_CONTROL control, FNOV_DIAG *fnov_diag )
// find overloaded operator from member, nonmember and stdops for alist specified
// return FNOV_RESULT same as FuncOverloaded
// result points at the symbol chosen, if non-ambiguous
{
    FNOV_RESULT     result;
    FNOV_LIST       *match = NULL;
    FNOV_LIST       *candidates = NULL;
    SYMBOL          sym;
    FNOV_INFO       info;

    info.alist = alist;
    info.plist = ptlist;
    info.pcandidates = &candidates;
    info.pmatch = &match;
    info.control = control;
    info.has_template = FALSE;
    info.fnov_diag = FnovInitDiag( fnov_diag );

    *resolved = NULL;
    if( member != NULL ) {
        if( member->region == NULL ) {
            sym = member->sym_name->name_syms;
            buildOverloadListFromSym( FNC_MEMBER, &info, sym );
        } else {
            // namespaces
            buildOverloadListFromRegion( FNC_MEMBER
                                       , &info
                                       , member->region );
        }

    }
    if( nonmember != NULL ) {
        if( nonmember->region == NULL ) {
            sym = nonmember->sym_name->name_syms;
            buildOverloadListFromSym( FNC_DEFAULT, &info, sym );
        } else {
            buildOverloadListFromRegion( FNC_DEFAULT
                                       , &info
                                       , nonmember->region );
        }
    }
    if( namesp != NULL ) {
        if( namesp->region != NULL ) {
            // namespaces
            buildOverloadListFromRegion( FNC_DEFAULT
                                       , &info
                                       , namesp->region );
        } else {
            sym = namesp->sym_name->name_syms;
            buildOverloadListFromSym( FNC_DEFAULT, &info, sym );
        }
    }
    // don't include stdops
    fnovNumCandidatesSet( info.fnov_diag, candidates );
    if( stdops != NULL ) {
        FNOV_CONTROL ctl = scalar_convert ? FNC_DEFAULT : FNC_STDOPS;
        buildOverloadListFromSym( ctl, &info, stdops );
    }

    if( info.has_template ) {
        info.control |= FNC_TEMPLATE;
    }
    result = doOverload( &info );
    if( match != NULL ) {
        *resolved = match->sym;
        FnovListFree( &match );
    }
    return( result );
}

FNOV_RESULT OpOverloadedLimitDiag( SYMBOL *resolved, SEARCH_RESULT *member,
/****************************************************************/
    SEARCH_RESULT *nonmember,  SEARCH_RESULT *namesp, SYMBOL stdops, arg_list *alist, PTREE *ptlist,
    FNOV_CONTROL control, FNOV_DIAG *fnov_diag )
// find overloaded operator from member, nonmember and stdops for alist specified
// return FNOV_RESULT same as FuncOverloaded
// result points at the symbol chosen, if non-ambiguous
{
    return opOverloadedLimitExDiag( resolved, member, nonmember, namesp, stdops,
                alist, ptlist, FALSE, control, fnov_diag );
}

FNOV_RESULT OpOverloadedDiag( SYMBOL *resolved, SEARCH_RESULT *member,
/****************************************************************/
    SEARCH_RESULT *nonmember, SEARCH_RESULT *namesp, SYMBOL stdops, arg_list *alist, PTREE *ptlist,
    FNOV_DIAG *fnov_diag )
// find overloaded operator from member, nonmember and stdops for alist specified
// return FNOV_RESULT same as FuncOverloaded
// result points at the symbol chosen, if non-ambiguous
{
    return opOverloadedLimitExDiag( resolved, member, nonmember, namesp, stdops,
        alist, ptlist, FALSE, FNC_DEFAULT, fnov_diag );
}

static SYMBOL findNonDefargSym( FNOV_LIST *match)
{
    FNOV_LIST *curr;

    RingIterBeg( match, curr ) {
        if( !SymIsDefArg(curr->sym) ) {
            return( curr->sym );
        }
    } RingIterEnd( curr )
    DbgAssert( FALSE );         // should never get here
    return match->sym;
}

static FNOV_RESULT doFunctionDistinctCheck( FNOV_CONTROL control,
/***************************************************************/
    SYMBOL *pold_sym, SYMBOL new_sym, char*name )
// determine if new_sym is a distinct function w.r.t old_sym
// returns:
//    FNOV_DISTINCT             - completely distinct
//    FNOV_NOT_DISTINCT         - not distinct because of arguments
//    FNOV_NOT_DISTINCT_RETURN  - args match exactly but return type is wrong
//    FNOV_EXACT_MATCH          - function matches exactly
//    *pold_sym = match->sym if return != FNOV_DISTINCT
//
{
    SYMBOL          old_sym = *pold_sym;
    FNOV_RESULT     result = FNOV_DISTINCT;
    FNOV_RESULT     overload_result = FNOV_NO_MATCH;
    FNOV_LIST       *candidates = NULL; // list of symbols to resolve
    FNOV_LIST       *match = NULL;
    auto arg_list   alist;
    FNOV_INFO       info;

    *pold_sym = NULL;

    // check for conversion operator
    if( name == CppConversionName() ) {
        control |= FNC_RANK_RETURN;
        InitArgList( &alist );
        alist.num_args = 1;
        alist.type_list[0] = FunctionDeclarationType( new_sym->sym_type )->of;
        alist.qualifier = FunctionThisFlags( new_sym );
        info.alist = &alist;
    } else {
        info.alist = SymFuncArgList( new_sym );
    }

    info.plist = NULL;
    info.pcandidates = &candidates;
    info.pmatch = &match;
    info.control = control;
    info.has_template = FALSE;
    info.fnov_diag = NULL;

    buildOverloadListFromSym( control, &info, old_sym );
    fnovNumCandidatesSet( info.fnov_diag, *info.pcandidates );

    if( *info.pcandidates != NULL ) {
        overload_result = resolveOverload( &info );
        if( overload_result != FNOV_NO_MATCH ) {
            DbgAssert( overload_

⌨️ 快捷键说明

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