opovload.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,248 行 · 第 1/3 页
C
1,248 行
*a_operand = CastImplicit( *a_operand, type, CNV_INIT_COPY, &diag_transform );
cnv_status = ( PT_ERROR == *a_operand ) ? CNV_ERR : CNV_OK;
} else {
cnv_status = CNV_OK;
}
return cnv_status;
}
static PTREE transform_conversions( // TRANSFORM OPERAND(S) BY CONVERSIONS
OLINF* olinf, // - overload information
SYMBOL dummy ) // - dummy symbol for conversion
{
PTREE node; // - node for operation
OP_MASK mask; // - operator mask
arg_list *alist; // - prototype for function
unsigned error_right; // - error occurred on right operand
unsigned error_left; // - error occurred on left operand
node = olinf->expr;
mask = olinf->mask;
alist = SymFuncArgList( dummy );
if( mask & OPM_ASSIGN ) {
error_right = transform_operand( &node->u.subtree[1]
, alist->type_list[1]
, mask );
error_left = transform_operand( &node->u.subtree[0]
, alist->type_list[0]
, mask );
} else {
error_left = transform_operand( &node->u.subtree[0]
, alist->type_list[0]
, mask );
if( alist->num_args > 1
&& ! ( mask & OPM_POST ) ) {
error_right = transform_operand( &node->u.subtree[1]
, alist->type_list[1]
, mask );
} else {
error_right = CNV_OK;
}
}
if( ( error_right != CNV_OK ) || ( error_left != CNV_OK ) ) {
PTreeErrorNode( node );
}
return node;
}
// did this symbol come from this search result ?
static boolean symInResult( SYMBOL sym, SEARCH_RESULT *result )
{
SYMBOL curr;
SYM_REGION *ptr;
RingIterBeg( result->sym_name->name_syms, curr ) {
if( curr == sym ) {
return TRUE;
}
} RingIterEnd( curr )
RingIterBeg( result->region, ptr ) {
RingIterBegFrom( ptr->from, curr ) {
if( curr == sym ) {
return TRUE;
}
} RingIterEndTo( curr, ptr->to )
} RingIterEnd( ptr )
return FALSE;
}
static PTREE transform_to_call( // TRANSFORM NODE TO FUNCTION CALL
PTREE node, // - type node
PTREE left, // - left operand
PTREE right ) // - right operand
{
node->u.subtree[0] = left;
node->u.subtree[1] = right;
node->cgop = CO_CALL_NOOVLD;
node->op = PT_BINARY;
node->flags = 0;
return( node );
}
static PTREE transform_naked( // TRANSFORM TO CALL TO NON-MEMBER FUNCTION
OLINF* olinf,
SYMBOL fun ) // - overload information
{
CGOP cgop; // - expression operator
PTREE param; // - parameters node
PTREE retn; // - resultant call expression
SEARCH_RESULT *result;
cgop = olinf->expr->cgop;
param = NodeArg( olinf->left.operand );
if( olinf->flags & PTO_BINARY ) {
if( cgop == CO_CALL ) {
param->u.subtree[0] = olinf->right.operand;
} else {
param = NodeArgument( param, olinf->right.operand );
}
} else if( cgop == CO_POST_PLUS_PLUS
|| cgop == CO_POST_MINUS_MINUS ) {
param = NodeArgument( param, NodeZero() );
}
result = NULL;
if( olinf->result_nonmem != NULL ) {
if( olinf->result_nonmem_namespace == NULL ) {
result = olinf->result_nonmem;
} else {
// both non-null
if( symInResult( fun, olinf->result_nonmem ) ) {
result = olinf->result_nonmem;
ScopeFreeResult( olinf->result_nonmem_namespace );
} else {
result = olinf->result_nonmem_namespace;
ScopeFreeResult( olinf->result_nonmem );
}
}
} else {
result = olinf->result_nonmem_namespace;
}
DbgAssert( symInResult( fun, result ) );
retn = transform_to_call( olinf->expr
, build_fun_name( result )
, param );
retn = PTreeCopySrcLocation( retn, olinf->expr );
return retn;
}
static PTREE transform_member( // TRANSFORM TO CALL TO MEMBER FUNCTION
OLINF* olinf ) // - overload information
{
PTREE op; // - original operator
PTREE param; // - parameter list
PTREE caller; // - caller node
SYMBOL op_sym; // - symbol for overloaded op
CGOP cgop; // - expression operator
op = olinf->expr;
cgop = op->cgop;
if( cgop == CO_ARROW ) {
op_sym = olinf->result_mem->sym_name->name_syms;
if( ! ArrowMemberOK( op_sym ) ) {
PTreeErrorExprSym( op, ERR_OPERATOR_ARROW_RETURN_BAD, op_sym );
return op;
}
caller = NodeDottedFunction( olinf->left.operand
, build_fun_name( olinf->result_mem ) );
caller = PTreeCopySrcLocation( caller, op );
caller = NodeBinary( CO_CALL, caller, NULL );
caller = PTreeCopySrcLocation( caller, op );
caller = AnalyseCall( caller, NULL );
op->u.subtree[0] = caller;
if( caller->op == PT_ERROR ) {
PTreeErrorNode( op );
} else {
olinf->repeat_overload = TRUE;
}
} else {
if( olinf->flags & PTO_BINARY ) {
param = olinf->right.operand;
if( cgop != CO_CALL ) {
param = NodeArg( param );
}
} else {
if( ( cgop == CO_POST_PLUS_PLUS )
||( cgop == CO_POST_MINUS_MINUS ) ) {
param = NodeArg( NodeZero() );
} else {
param = NULL;
}
}
caller = NodeDottedFunction( olinf->left.operand
, build_fun_name( olinf->result_mem ) );
caller = PTreeCopySrcLocation( caller, op );
op = transform_to_call( op, caller, param );
op = PTreeCopySrcLocation( op, olinf->expr );
}
return op;
}
static PTREE resolve_symbols( // RESOLVE MULTIPLE OVERLOAD DEFINITIONS
OLINF* olinf ) // - overload information
{
PTREE ptlist[2]; // - PT list for all but call
PTREE zero_node; // - , 0 ) parm for @++ and @-- overloading
FNOV_RESULT ovret; // - overload return
unsigned count; // - # of arguments
SYMBOL fun; // - overloaded function to use
struct // - arg.list
{ arg_list base; // - - hdr, entry[1]
TYPE arg2; // - - entry[2]
} alist;
FNOV_DIAG fnov_diag; // - diagnosis information
ExtraRptIncrementCtr( ctrResolveOps );
if( olinf->mask & OPM_FUN ) {
PTREE oper;
ExtraRptIncrementCtr( ctrResolveFun );
fun = olinf->result_mem->sym_name->name_syms;
oper = PTreeIdSym( fun );
oper = NodeSymbolNoRef( oper, fun, olinf->result_mem );
oper->cgop = CO_NAME_DOT;
olinf->expr->u.subtree[0] = NodeDottedFunction( olinf->left.operand
, oper );
ScopeFreeResult( olinf->result_nonmem );
ScopeFreeResult( olinf->result_nonmem_namespace );
return olinf->expr;
}
InitArgList( &alist.base );
zero_node = NULL;
ptlist[0] = olinf->left.operand;
alist.base.type_list[ 0 ] = olinf->left.node_type;
if( olinf->flags & PTO_BINARY ) {
if( olinf->mask & OPM_ASSIGN ) {
ptlist[1] = olinf->right.operand;
alist.base.type_list[ 1 ] = olinf->right.node_type;
count = 2;
} else if( olinf->mask & OPM_LT ) {
count = 1;
} else {
if( ( olinf->mask & OPM_SUB )
&&( olinf->result_mem != NULL ) ) {
olinf->scalars = NULL;
}
ptlist[1] = olinf->right.operand;
alist.base.type_list[ 1 ] = olinf->right.node_type;
count = 2;
}
} else if( olinf->mask & OPM_POST ) {
zero_node = NodeZero();
setupOVOP( olinf, zero_node, &olinf->right );
ptlist[1] = olinf->right.operand;
alist.base.type_list[ 1 ] = olinf->right.node_type;
count = 2;
} else {
count = 1;
}
alist.base.num_args = count;
// this qualifier is handled explicitly by the first entry in the arg_list
ovret = OpOverloadedDiag( &fun
, olinf->result_mem
, olinf->result_nonmem
, olinf->result_nonmem_namespace
, olinf->scalars
, (arg_list*)&alist
, ptlist
, &fnov_diag );
if( ovret == FNOV_AMBIGUOUS && CompFlags.extensions_enabled ) {
FNOV_LIST* amb_list; // - ambiguity list
SYMBOL next; // - next symbol
boolean have_user_defined = FALSE;
boolean have_void = FALSE;
if( ((olinf->mask & OPM_NV) == 0) && (olinf->mask & OPM_PP ) ) {
// we're in the (void *, void *) area
for( amb_list = NULL; ; ) {
next = FnovGetAmbiguousEntry( &fnov_diag, &amb_list );
if( next == NULL ) break;
if( next->name != NULL ) {
have_user_defined = TRUE;
} else if( op_basic_arg[ next->u.scalar_order ][ 0 ] ==
TYP_POINTER
&& op_basic_arg[ next->u.scalar_order ][ 1 ] ==
TYP_POINTER ) {
// the (void *, void *) was one of the ambiguous ones
have_void = TRUE;
}
if( have_user_defined && have_void ) {
break;
}
}
}
if( have_user_defined && have_void ) { // try again
int i;
FnovFreeDiag( &fnov_diag );
for( i = 0; i < MAX_FUN_PROTOS_EXTRA; i++ ) {
OP_MASK fun_mask;
fun_mask = opfun_mask_extra[ i ];
if( olinf->mask & fun_mask ) {
RingAppend( &olinf->scalars, ovfuns_extra[ i ] );
}
}
ovret = OpOverloadedLimitDiag( &fun
, olinf->result_mem
, olinf->result_nonmem
, olinf->result_nonmem_namespace
, olinf->scalars
, (arg_list*)&alist
, ptlist
, FNC_STDOP_CV_VOID
, &fnov_diag );
}
}
if( ovret == FNOV_AMBIGUOUS && CompFlags.overload_13332 ) {
FNOV_LIST* amb_list; // - ambiguity list
SYMBOL next; // - next symbol
boolean have_user_defined = FALSE;
for( amb_list = NULL; ; ) {
next = FnovGetAmbiguousEntry( &fnov_diag, &amb_list );
if( next == NULL ) break;
if( next->name != NULL ) {
have_user_defined = TRUE;
break;
}
}
if( have_user_defined ) {
FnovFreeDiag( &fnov_diag );
ovret = OpOverloadedLimitDiag( &fun
, olinf->result_mem
, olinf->result_nonmem
, olinf->result_nonmem_namespace
, olinf->scalars
, (arg_list*)&alist
, ptlist
, FNC_USE_WP13332
, &fnov_diag );
}
}
switch( ovret ) {
case FNOV_AMBIGUOUS:
{ FNOV_LIST* amb_list; // - ambiguity list
SYMBOL next; // - next symbol
fun = NULL;
for( amb_list = NULL; ; ) {
next = FnovGetAmbiguousEntry( &fnov_diag, &amb_list );
if( next == NULL ) break;
if( next->name == NULL
&& next->id != SC_MEMBER
&& next->u.scalar_order < ( MAX_FUN_PROTOS - 2 ) ) {
if( fun == NULL
|| fun->u.scalar_order < next->u.scalar_order ) {
fun = next;
}
} else {
fun = NULL;
break;
}
}
if( fun == NULL ) {
PTreeErrorExpr( olinf->expr, ERR_OPERATOR_AMBIGUOUS_OVERLOAD );
for( ; ; ) {
SYMBOL reject = FnovNextAmbiguousEntry( &fnov_diag );
if( reject == NULL ) break;
if( reject->name == NULL ) {
CErr2p( INF_CONV_AMBIG_SCALAR
, SymFuncArgList( reject )->type_list[0] );
} else {
InfSymbolAmbiguous( reject );
}
}
ScopeFreeResult( olinf->result_mem );
ScopeFreeResult( olinf->result_nonmem );
ScopeFreeResult( olinf->result_nonmem_namespace );
break;
}
// drops thru
}
case FNOV_NONAMBIGUOUS :
if( fun->id == SC_MEMBER ) {
ExtraRptIncrementCtr( ctrResolveMember );
if( olinf->expr->cgop == CO_EQUAL
&& olinf->left.class_type ==
ClassTypeForType( SymFuncArgList( fun )->type_list[0] ) ) {
ScopeFreeResult( olinf->result_mem );
} else {
olinf->expr = transform_member( olinf );
}
ScopeFreeResult( olinf->result_nonmem );
ScopeFreeResult( olinf->result_nonmem_namespace );
} else if( fun->name == NULL ) {
ExtraRptIncrementCtr( ctrResolveScalar );
olinf->expr = transform_conversions( olinf, fun );
ScopeFreeResult( olinf->result_mem );
ScopeFreeResult( olinf->result_nonmem );
ScopeFreeResult( olinf->result_nonmem_namespace );
} else {
ExtraRptIncrementCtr( ctrResolveNaked );
olinf->expr = transform_naked( olinf, fun );
ScopeFreeResult( olinf->result_mem );
}
break;
case FNOV_NO_MATCH:
ExtraRptIncrementCtr( ctrResolveNone );
ScopeFreeResult( olinf->result_mem );
ScopeFreeResult( olinf->result_nonmem );
ScopeFreeResult( olinf->result_nonmem_namespace );
break;
}
if( zero_node != NULL ) {
PTreeFree( zero_node );
}
FnovFreeDiag( &fnov_diag );
return olinf->expr;
}
static SCOPE nsExtract( OLINF *inf )
{
TYPE user_type;
SCOPE scope;
user_type = inf->left.user_type;
if( user_type == NULL ) {
user_type = inf->right.user_type;
}
if( user_type->id == TYP_CLASS ) {
scope = user_type->u.c.scope;
} else {
DbgAssert( user_type->id == TYP_ENUM );
scope = user_type->u.t.scope;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?