membptr.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,688 行 · 第 1/4 页
C
1,688 行
return new_index;
}
static PTREE computeDeltaIndex( // COMPUTE NEW DELTA, INDEX
PTREE expr, // - expression (CO_MEMPTR)
TYPE type, // - expression type
MEMBER_PTR_CAST *inf ) // - cast information
{
PTREE original; // - original expression
PTREE new_index; // - computed new index
PTREE new_delta; // - computed new delta
original = expr;
expr = PTreeOpLeft( original );
expr = expr->u.subtree[0];
new_delta = NodeRvalue( expr->u.subtree[1] );
new_index = NodeRvalue( expr->u.subtree[0]->u.subtree[1] );
if( inf->safe ) {
new_delta = computeNewDelta( new_delta, &new_index, inf );
new_index = computeNewIndex( new_index, inf );
} else {
new_index = computeNewIndex( new_index, inf );
new_delta = computeNewDelta( new_delta, &new_index, inf );
}
expr->u.subtree[1] = new_delta;
expr->flags &= ~ PTF_LVALUE;
expr = expr->u.subtree[0];
expr->u.subtree[1] = new_index;
expr->flags &= ~ PTF_LVALUE;
original->type = type;
original->flags &= ~PTF_LVALUE;
return original;
}
static PTREE makeMembPtrExpr( // MAKE A MEMBER-PTR EXPRESSION
TYPE type, // - type of member pointer
PTREE func, // - dereferencing function
PTREE delta, // - delta expression
PTREE index ) // - index expression
{
PTREE expr; // - resultant expression
expr = NodeUnary( CO_MEMPTR_CONST
, NodeArguments( index, delta, func, NULL ) );
expr->type = type;
return expr;
}
static PTREE makeMembPtrCon( // MAKE A MEMBER-PTR CONSTANT EXPRESSION
TYPE type, // - type of member pointer
SYMBOL func, // - dereferencing function
unsigned delta, // - delta offset
unsigned index ) // - index offset
{
PTREE deref; // - expression for dereferencing function
if( func == NULL ) {
deref = NodeIntegralConstant( 0, MembPtrDerefFnPtr() );
} else {
deref = MakeNodeSymbol( func );
}
return makeMembPtrExpr( type
, deref
, NodeOffset( delta )
, NodeOffset( index ) );
}
PTREE MembPtrZero( // MAKE A NULL MEMBER POINTER CONSTANT
TYPE type ) // - type for constant
{
PTREE zero;
zero = makeMembPtrCon( type, NULL, 0, 0 );
return( zero );
}
static PTREE generateMembPtrCon(// GENERATE MEMBER-PTR CONSTANT
TYPE type, // - type of member pointer
PTREE item_addrof, // - node for &[ base item for constant ]
MEMBER_PTR_CAST *inf ) // - conversion information
{
SYMBOL addrfun; // - memb-ptr offset function
PTREE expr; // - resultant expression
PTREE item; // - node for base item for constant
item = PTreeOpLeft( item_addrof );
addrfun = membPtrOffsetFunc( item );
NodeFreeSearchResult( item );
expr = makeMembPtrCon( type, addrfun, 0, 0 );
expr = computeDeltaIndex( expr, type, inf );
expr = PTreeCopySrcLocation( expr, item_addrof );
item_addrof = NodePruneLeft( item_addrof );
return NodeReplaceTop( item_addrof, expr );
}
static PTREE nextArg( // PRUNE NEXT ASSIGNMENT ARGUMENT
PTREE *ref ) // - reference( argument before )
{
PTREE arg; // - next argument
PTREE retn; // - return value
arg = (*ref)->u.subtree[0];
*ref = arg;
retn = arg->u.subtree[1];
arg->u.subtree[1] = NULL;
return retn;
}
static PTREE assignMembPtrArg( // ASSIGN A MEMBER-PTR ARGUMENT
PTREE *a_left, // - addr[ left operand ]
PTREE *a_right ) // - addr[ right operand ]
{
return NodeAssign( nextArg( a_left ), NodeRvalue( nextArg( a_right ) ) );
}
static PTREE storeMembPtrCon( // STORE MEMBER-PTR CONSTANT
PTREE expr, // - expression to be stored
PTREE tgt ) // - target
{
PTREE left; // - left operand
PTREE right; // - right operand
PTREE result; // - result
left = PTreeOpLeft( expr );
right = PTreeOpRight( expr );
result = assignMembPtrArg( &left, &right );
result = NodeComma( result, assignMembPtrArg( &left, &right ) );
result = NodeComma( result, assignMembPtrArg( &left, &right ) );
result = NodeReplace( expr , result );
result = NodeComma( result, tgt );
result->flags |= PTF_SIDE_EFF;
return result;
}
static CNV_DIAG diagMembPtrOps= // diagnosis for analyse of memb-ptr operands
{ ERR_MEMB_PTR_NOT_DERIVED
, ERR_MEMB_PTR_AMBIGUOUS
, ERR_MEMB_PTR_DERIVED
, ERR_MEMB_PTR_PRIVATE
, ERR_MEMB_PTR_PROTECTED
};
// Note: inf->safe is set on input to indicate whether an unsafe (cast)
// can be performed. On output, it is set to indicate whether an unsafe
// cast will be performed.
//
static boolean analyseMembPtr( // ANALYSE MEMBER-PTR OPERANDS
MEMBER_PTR_CAST *inf, // - operands information
PTREE expr ) // - expression for errors
{
boolean retn; // - TRUE ==> analysis ok
CNV_RETN cnv; // - CNV_...: conversion result
SCOPE scope; // - used to switch scopes
boolean check_safety; // - check if safe req'd
msg_status_t status; // - status for warning
check_safety = FALSE;
switch( TypeCommonDerivation( ScopeClass( inf->derived )
, ScopeClass( inf->base ) ) ) {
case CTD_NO :
cnv = CNV_IMPOSSIBLE;
break;
case CTD_RIGHT :
check_safety = TRUE;
cnv = CNV_OK;
break;
case CTD_RIGHT_VIRTUAL :
check_safety = TRUE;
// drops thru
case CTD_LEFT_VIRTUAL :
status = PTreeWarnExpr( expr, ANSI_MPTR_ACROSS_VIRTUAL );
if( !( status & MS_WARNING ) ) {
cnv = CNV_ERR;
break;
}
if( status & MS_PRINTED ) {
ConversionDiagnoseInf();
}
case CTD_LEFT :
cnv = CNV_OK;
break;
case CTD_RIGHT_AMBIGUOUS :
check_safety = TRUE;
// drops thru
case CTD_LEFT_AMBIGUOUS :
cnv = CNV_AMBIGUOUS;
break;
case CTD_RIGHT_PRIVATE :
check_safety = TRUE;
// drops thru
case CTD_LEFT_PRIVATE :
cnv = CNV_PRIVATE;
break;
case CTD_RIGHT_PROTECTED :
check_safety = TRUE;
// drops thru
case CTD_LEFT_PROTECTED :
cnv = CNV_PROTECTED;
break;
}
if( check_safety ) {
if( inf->safe ) {
cnv = CNV_VIRT_DER;
} else {
scope = inf->derived;
inf->derived = inf->base;
inf->base = scope;
}
} else {
if( cnv != CNV_IMPOSSIBLE ) {
inf->safe = TRUE;
}
}
if( CNV_OK == ConversionDiagnose( cnv, expr, &diagMembPtrOps ) ) {
ScopeMemberPtrCastAction( inf );
#ifndef NDEBUG
if( PragDbgToggle.dump_mptr ) {
DumpMemberPtrInfo( inf );
}
#endif
retn = TRUE;
} else {
retn = FALSE;
}
return retn;
}
static CNV_DIAG diagMembFunCnv= // diagnosis for member-ptr conversion
{ ERR_MEMB_PTR_FUN_IMPOSSIBLE
, ERR_MEMB_PTR_FUN_AMBIGUOUS
, ERR_MEMB_PTR_DERIVED
, ERR_MEMB_PTR_FUN_PRIVATE
, ERR_MEMB_PTR_FUN_PROTECTED
};
static CNV_RETN analyseAddrOfNode( // ANALYSE NODE FOR (& item)
PTREE item, // - source item
TYPE type_mp, // - unmodified member-ptr type
MEMBER_PTR_CAST *castinfo, // - information for casting
unsigned conversion ) // - type of conversion
{
CNV_RETN retn; // - return: CNV_...
SYMBOL base_item; // - item required
TYPE type_pted; // - type pointed at
base_item = item->u.symcg.symbol;
type_mp = MemberPtrType( type_mp );
type_pted = MakePointerTo( type_mp->of );
if( SymIsThisDataMember( base_item ) ) {
if( ScopeCheckSymbol( item->u.symcg.result, base_item ) ) {
retn = CNV_ERR;
} else {
retn = CNV_OK;
}
} else if( SymIsFunction( base_item ) ) {
if( ADDR_FN_ONE_USED == NodeAddrOfFun( item, &item ) ) {
item->u.symcg.symbol = ActualNonOverloadedFunc( base_item,
item->u.symcg.result );
retn = CNV_OK;
} else {
switch( conversion ) {
// case CNV_CAST :
case CNV_EXPR :
retn = CNV_ERR;
break;
default :
retn = ConvertOvFunNode( type_pted, item );
break;
}
}
if( ( retn == CNV_OK ) || ( retn == CNV_OK_TRUNC ) ) {
base_item = item->u.symcg.symbol;
if( ScopeCheckSymbol( item->u.symcg.result, base_item )
|| CNV_ERR == validateOkObjs( item
, TRUE
, base_item->sym_type
, membPtrObject( type_mp ) )
) {
retn = CNV_ERR;
} else if( SymIsThisFuncMember( base_item ) ) {
item->type = MakeMemberPointerTo( SymClass( base_item )
, base_item->sym_type );
} else {
PTreeErrorExpr( item, ERR_MEMB_PTR_ADDR_OF );
retn = CNV_ERR;
}
}
} else {
PTreeErrorExpr( item, ERR_MEMB_PTR_ADDR_OF );
retn = CNV_ERR;
}
if( ( retn == CNV_OK ) || ( retn == CNV_OK_TRUNC ) ) {
castinfo->base = item->u.symcg.result->scope;
castinfo->derived = scopeMembPtrType( type_mp );
if( ! analyseMembPtr( castinfo, item ) ) {
retn = CNV_ERR;
}
}
return retn;
}
static PTREE analyseAddrOf( // ANALYSE (& item)
PTREE src, // - source item
TYPE type_mp, // - unmodified member-ptr type
MEMBER_PTR_CAST *castinfo ) // - information for casting
{
PTREE item; // - item being pointed at
CNV_RETN convert; // - type of conversion
item = PTreeOpLeft( src );
if( nodeIsMembPtrCon( item ) ) {
if( castinfo->safe ) {
convert = CNV_ASSIGN;
} else {
convert = CNV_CAST;
}
if( CNV_OK != ConversionDiagnose( analyseAddrOfNode( item
, type_mp
, castinfo
, convert )
, src
, &diagMembFunCnv ) ) {
PTreeErrorNode( src );
}
} else {
PTreeErrorExpr( src, ERR_MEMB_PTR_ADDR_OF );
}
return src;
}
static PTREE memPtrAddrOfCon( // MAKE MEMPTR EXPRN FROM &class::item
PTREE expr, // - expression to be converted
TYPE type_mp, // - type of member ptr result
boolean safe, // - TRUE ==> only safe assignment allowed
boolean init ) // - TRUE ==> an initialization
{
MEMBER_PTR_CAST castinfo; // - information for casting
PTREE mp_node; // - member-ptr node
castinfo.safe = safe;
castinfo.init_conv = init;
mp_node = analyseAddrOf( expr, type_mp, &castinfo );
if( mp_node->op == PT_ERROR ) {
PTreeErrorNode( expr );
} else {
expr = generateMembPtrCon( type_mp, mp_node, &castinfo );
}
return expr;
}
static PTREE convertMembPtrExpr(// CONVERT A MEMBER POINTER EXPRESSION
PTREE expr, // - expression (CO_MEMPTR)
TYPE type, // - expression type
boolean safe, // - TRUE ==> safe cast only
boolean init ) // - TRUE ==> initialization expression
{
MEMBER_PTR_CAST inf; // - cast information
inf.init_conv = init;
inf.safe = safe;
inf.derived = scopeMembPtrType( type );
inf.base = scopeMembPtrType( expr->type );
if( analyseMembPtr( &inf, expr ) ) {
expr = computeDeltaIndex( expr, type, &inf );
expr->type = type;
expr->flags = ( expr->flags & ~PTF_LVALUE ) | PTF_LV_CHECKED;
}
return expr;
}
static boolean membPtrAddrOfNode( // TEST IF (& class::member)
PTREE node )
{
TYPE mbrptr;
PTREE fn;
CNV_RETN retn;
if( NodeIsUnaryOp( node, CO_ADDR_OF ) ) {
mbrptr = MemberPtrType( node->type );
if( NULL != mbrptr ) {
return TRUE;
} else {
retn = NodeAddrOfFun( node, &fn );
if( (retn != ADDR_FN_NONE ) &&
( (fn->flags & PTF_COLON_QUALED) || // S::foo not just foo
( CompFlags.extensions_enabled ) ) ) { // just foo (MFC ext)
return (retn == ADDR_FN_MANY ||
retn == ADDR_FN_ONE ||
CompFlags.extensions_enabled ); // S::foo OK (ext)
}
}
}
return FALSE;
}
boolean MembPtrZeroConst( // DETERMINE IF ZERO MEMBER-PTR CONSTANT
PTREE expr ) // - CO_MEMPTR_CONST expression
{
expr = expr->u.subtree[0];
expr = expr->u.subtree[1];
return NodeIsZeroConstant( expr );
}
boolean MembPtrExtension // TEST IF EXTENDED FUNCTION MEMBER PTR
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?