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