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 + -
显示快捷键?