opovload.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,248 行 · 第 1/3 页
C
1,248 行
scope = ScopeEnclosingId( scope, SCOPE_FILE );
if( scope == GetFileScope() ) {
scope = NULL;
}
return( scope );
}
PTREE OverloadOperator( // HANDLE OPERATOR OVERLOADING, IF REQ'D
PTREE op ) // - node containing operator
{
OLINF oli; // - overload info
SCOPE enclosing;
ExtraRptIncrementCtr( ctrOverloads );
for( ; ; ) {
if( ! initOLINF( op, &oli ) ) break;
scalarOperators( &oli );
if( ! oli.have_user_type ) break;
if( oli.flags & PTO_OVLOAD ) {
char *ov_fun_name; // - name of overloaded function
TYPE type; // - class type
SCOPE scope; // - class scope
CGOP cgop; // - expression operator
ExtraRptIncrementCtr( ctrOverloadOps );
cgop = oli.expr->cgop;
type = oli.left.class_type;
if( type == NULL ) {
if( ( 0 == ( oli.mask & ( OPM_QUEST | OPM_FUN | OPM_SUB ) ) )
&& cgop != CO_EQUAL ) {
SCOPE scope;
ov_fun_name = CppOperatorName( cgop );
oli.result_nonmem = ScopeFindNaked( GetFileScope()
, ov_fun_name );
scope = nsExtract( &oli );
if( scope != NULL ) {
oli.result_nonmem_namespace = ScopeContainsNaked( scope, ov_fun_name );
}
}
} else {
scope = TypeScope( type );
ov_fun_name = CppOperatorName( cgop );
if( cgop == CO_EQUAL ) {
ClassDefaultOpEq( type, type );
oli.result_mem = ScopeContainsMember( scope, ov_fun_name );
} else {
oli.result_mem = ScopeFindMember( scope, ov_fun_name );
oli.result_nonmem = ScopeFindNaked( GetFileScope(), ov_fun_name );
enclosing = nsExtract( &oli );
if( enclosing != NULL ) {
oli.result_nonmem_namespace = ScopeContainsNaked( enclosing, ov_fun_name );
}
}
}
if( oli.result_mem == NULL
&& oli.result_nonmem == NULL
&& oli.result_nonmem_namespace == NULL ) {
if( oli.scalars == NULL ) break;
if( ! oli.have_class_type ) break;
}
op = resolve_symbols( &oli );
if( ! oli.repeat_overload ) break;
if( op->op == PT_ERROR ) break;
ExtraRptIncrementCtr( ctrRepeats );
} else {
if( NULL == oli.scalars ) break;
op = resolve_symbols( &oli );
break;
}
}
return op;
}
static boolean isBadFun( // DIAGNOSE IF MEMBER FUNC. OR OVERLOADED
PTREE expr, // - expression being analysed
PTREE operand ) // - operand to be diagnosed
{
boolean retn; // - return: TRUE ==> diagnosed
PTREE fnode; // - function node
PTREE node; // - node to be examined
node = PTreeOp( &operand );
switch( NodeAddrOfFun( node, &fnode ) ) {
default :
retn = FALSE;
break;
case ADDR_FN_ONE :
if( SymIsThisFuncMember( fnode->u.symcg.symbol ) ) {
PTreeErrorExprSymInf( node
, ERR_ADDR_NONSTAT_MEMBER_FUNC
, fnode->u.symcg.symbol );
PTreeErrorNode( expr );
retn = TRUE;
} else {
retn = FALSE;
}
break;
case ADDR_FN_MANY :
PTreeErrorExprSymInf( node
, ERR_ADDR_OF_OVERLOADED_FUN
, fnode->u.symcg.symbol );
PTreeErrorNode( expr );
retn = TRUE;
break;
}
return retn;
}
PTREE ConvertBoolean( // CONVERSION TO BOOLEAN EXPRESSION
PTREE bexpr ) // - the boolean expression
{
PTREE left; // - left expression
OLINF oli; // - overload info
ExtraRptIncrementCtr( ctrBoolConv );
initOLINF( bexpr, &oli );
bexpr = oli.expr;
left = bexpr->u.subtree[0];
if( NULL != oli.left.user_type ) {
ExtraRptIncrementCtr( ctrBoolRes );
scalarOperators( &oli );
if( NULL != oli.scalars ) {
bexpr = resolve_symbols( &oli );
if( ( bexpr->op != PT_ERROR )
&&( NULL != ClassTypeForType( bexpr->u.subtree[0]->type ) ) ) {
PTreeErrorExpr( PTreeOpLeft( bexpr ), ERR_NOT_BOOLEAN );
PTreeErrorNode( bexpr );
return bexpr;
}
}
if( MemberPtrType( bexpr->u.subtree[0]->type ) ) {
bexpr = MembPtrCompare( bexpr );
if( bexpr->op == PT_ERROR ) return bexpr;
}
if( PT_BINARY == bexpr->op ) {
bexpr = FoldBinary( bexpr );
} else if( PT_UNARY == bexpr->op ) {
bexpr = FoldUnary( bexpr );
}
} else if( NULL != MemberPtrType( left->type ) ) {
bexpr = MembPtrCompare( bexpr );
} else if( oli.flags & PTO_BINARY ) {
if( ! isBadFun( bexpr, bexpr->u.subtree[0] )
&& ! isBadFun( bexpr, bexpr->u.subtree[1] ) ) {
bexpr = FoldBinary( bexpr );
}
} else if( oli.flags & PTO_UNARY ) {
if( ! isBadFun( bexpr, bexpr->u.subtree[0] ) ) {
bexpr = FoldUnary( bexpr );
}
}
return bexpr;
}
static TYPE getOperandType( // GET OPERAND TYPE
type_id id, // - type id
GETOP_CONTROL ctl ) // - control flavour
{
TYPE type; // - manufactured type
switch( id ) {
case TYP_POINTER :
if( ctl & GETOP_CONST ) {
if( ctl & GETOP_VOLATILE ) {
// const volatile
DbgAssert( ( ctl & GETOP_NOVOID ) == 0 );
type = TypePtrToConstVolatileVoidStdop();
} else {
// const
if( ctl & GETOP_NOVOID ) {
type = TypePtrToConstVoidStdopArith();
} else {
type = TypePtrToConstVoidStdop();
}
}
} else {
if( ctl & GETOP_VOLATILE ) {
// volatile
DbgAssert( ( ctl & GETOP_NOVOID ) == 0 );
type = TypePtrToVolatileVoidStdop();
} else {
// neither const nor volatile
if( ctl & GETOP_NOVOID ) {
type = TypePtrToVoidStdopArith();
} else {
type = TypePtrToVoidStdop();
}
}
}
break;
case TYP_MEMBER_POINTER :
type = TypeGetCache( TYPC_VOID_MEMBER_PTR );
break;
default :
type = GetBasicType( id );
break;
}
return( type );
}
static void overloadOperatorInit( // INITIALIZATION
INITFINI* defn ) // - definition
{
unsigned arg; // - current basic argument
type_id arg1; // - type of argument(1)
type_id arg2; // - type of argument(2)
TYPE fn_type; // - full type for function
TYPE retn_type; // - return type
TYPE arg1_type; // - first argument type
TYPE arg2_type; // - second argument type
SYMBOL fun; // - dummy symbol for function
OP_MASK mask; // - mask for function
defn = defn;
for( arg = 0; arg < MAX_FUN_PROTOS; ++arg ) {
mask = opfun_mask[arg];
if( ( mask == 0 ) || ( mask & OPM_RR ) ) {
arg_list *alist; // - this gets hammered on overloading
arg1_type = MakeReferenceTo( GetBasicType( TYP_CHAR ) );
alist = AllocArgListPerm( 2 );
alist->type_list[0] = arg1_type;
alist->type_list[1] = arg1_type;
fn_type = MakeType( TYP_FUNCTION );
fn_type->flag |= TF1_PLUSPLUS;
fn_type->u.f.args = alist;
fn_type->of = arg1_type;
CheckUniqueType( fn_type ); // - don't use CheckDupType
} else {
GETOP_CONTROL ctl;
arg1 = op_basic_arg[ arg ][ 0 ];
retn_type = getOperandType( arg1, GETOP_CONST );
if( mask & OPM_ASSIGN ) {
ctl = GETOP_CONST;
} else {
ctl = GETOP_DEFAULT;
}
if( mask & OPM_NV ) {
ctl |= GETOP_NOVOID;
}
arg1_type = getOperandType( arg1, ctl );
if( mask & OPM_ASSIGN ) {
arg1_type = MakeReferenceTo( arg1_type );
retn_type = MakeReferenceTo( retn_type );
}
arg2 = op_basic_arg[ arg ][ 1 ];
if( arg2 == TYP_MAX ) {
fn_type = MakeSimpleFunction( retn_type
, arg1_type
, NULL );
} else {
ctl = GETOP_DEFAULT;
if( mask & OPM_NV ) {
ctl |= GETOP_NOVOID;
}
arg2_type = getOperandType( arg2, ctl );
fn_type = MakeSimpleFunction( retn_type
, arg1_type
, arg2_type
, NULL );
}
}
fun = AllocSymbol();
fun->sym_type = fn_type;
fun->u.scalar_order = arg;
ovfuns[ arg ] = fun;
}
if( CompFlags.extensions_enabled ) {
// initializes extra function needed to implement extension for
// Microsoft compatibility
for( arg = 0; arg < MAX_FUN_PROTOS_EXTRA; ++arg ) {
mask = opfun_mask_extra[arg];
arg1 = op_basic_arg_extra[ arg ][ 0 ];
arg1_type = getOperandType( arg1, extra_ctl[arg] );
fn_type = MakeSimpleFunction( arg1_type, arg1_type, arg1_type, NULL );
fun = AllocSymbol();
fun->sym_type = fn_type;
fun->u.scalar_order = arg;
ovfuns_extra[ arg ] = fun;
}
}
ExtraRptRegisterCtr( &ctrBoolConv, "# Boolean Coversions" );
ExtraRptRegisterCtr( &ctrBoolRes, "# Boolean overload resolutions" );
ExtraRptRegisterCtr( &ctrOverloads, "# operator overloads" );
ExtraRptRegisterCtr( &ctrRepeats, "# repeats of overloading" );
ExtraRptRegisterCtr( &ctrOverloadOps, "# operators with C++ overloading" );
ExtraRptRegisterCtr( &ctrResolveOps, "# operators requiring resolution" );
ExtraRptRegisterCtr( &ctrResolveFun, "# resolved function calls" );
ExtraRptRegisterCtr( &ctrResolveNone, "# unresolved overloads" );
ExtraRptRegisterCtr( &ctrResolveMember, "# resolved by member fun" );
ExtraRptRegisterCtr( &ctrResolveScalar, "# resolved by scalar conversion" );
ExtraRptRegisterCtr( &ctrResolveNaked, "# resolved by file-scope fun" );
}
static void overloadOperatorFini( // COMPLETION
INITFINI* defn ) // - definition
{
unsigned arg; // - current basic argument
defn = defn;
for( arg = 0; arg < MAX_FUN_PROTOS; ++arg ) {
if( ovfuns[ arg ] != NULL ) {
FreeSymbol( ovfuns[ arg ] );
}
}
if( CompFlags.extensions_enabled ) {
for( arg = 0; arg < MAX_FUN_PROTOS_EXTRA; ++arg ) {
if( ovfuns_extra[ arg ] != NULL ) {
FreeSymbol( ovfuns_extra[ arg ] );
}
}
}
}
INITDEFN( overload_operator, overloadOperatorInit, overloadOperatorFini )
pch_status PCHWriteOperatorOverloadData( void )
{
SYMBOL sym;
unsigned arg;
for( arg = 0; arg < MAX_FUN_PROTOS; ++arg ) {
sym = SymbolGetIndex( ovfuns[ arg ] );
PCHWrite( &sym, sizeof( sym ) );
}
for( arg = 0; arg < MAX_FUN_PROTOS_EXTRA; ++arg ) {
sym = SymbolGetIndex( ovfuns_extra[ arg ] );
PCHWrite( &sym, sizeof( sym ) );
}
return( PCHCB_OK );
}
pch_status PCHReadOperatorOverloadData( void )
{
SYMBOL sym;
unsigned arg;
for( arg = 0; arg < MAX_FUN_PROTOS; ++arg ) {
PCHRead( &sym, sizeof( sym ) );
ovfuns[ arg ] = SymbolMapIndex( sym );
}
for( arg = 0; arg < MAX_FUN_PROTOS_EXTRA; ++arg ) {
PCHRead( &sym, sizeof( sym ) );
ovfuns_extra[ arg ] = SymbolMapIndex( sym );
}
return( PCHCB_OK );
}
pch_status PCHInitOperatorOverloadData( boolean writing )
{
writing = writing;
return( PCHCB_OK );
}
pch_status PCHFiniOperatorOverloadData( boolean writing )
{
writing = writing;
return( PCHCB_OK );
}
#ifndef NDEBUG
#include "dbg.h"
#include <stdio.h>
static void dumpOVOP // DEBUG -- DUMP OVOP structure
( OVOP* ovop // - OVOP
, char const *operand ) // - title info
{
printf( "Operand[%x] (%s)\n"
, ovop->operand
, operand );
printf( " node_type: " );
DumpFullType( ovop->node_type );
printf( " user_type: " );
DumpFullType( ovop->user_type );
printf( " class_type: " );
DumpFullType( ovop->class_type );
}
void DumpOpovLoad // DEBUG -- DUMP ROUTINE
( OLINF* oli ) // - overload info
{
SYMBOL sym;
DbgPrintPTREE( oli->expr );
dumpOVOP( &oli->left, "left" );
dumpOVOP( &oli->right, "right" );
printf( "\nScalars:" );
RingIterBeg( oli->scalars, sym ) {
PrintFullType( sym->sym_type );
} RingIterEnd( sym );
printf( "\nSearch results: memb[%x] non-memb[%x]"
"\nMask[%x] Flags[%x] scalar_overload(%d) repeat_overload(%d)"
"\nhave_user_type(%d) have_class_type(%d)"
"\n"
, oli->result_mem
, oli->result_nonmem
, oli->mask
, oli->flags
, oli->scalar_overloadable
, oli->repeat_overload
, oli->have_class_type
, oli->have_user_type
);
}
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?