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