membptr.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,688 行 · 第 1/4 页
C
1,688 行
sym = expr->u.symcg.symbol;
expr->flags |= PTF_COLON_QUALED;
expr = NodeUnaryCopy( CO_ADDR_OF, expr );
expr->type = MakeMemberPointerTo( SymClass(sym ), sym->sym_type );
*a_expr = expr;
} // drops thru
case MP_ADDR_OF :
if( (! safe )
|| CNV_ERR != validateAddrOfObj( expr, tgt_type ) ) {
expr = memPtrAddrOfCon( expr, tgt_type, safe, init );
*a_expr = expr;
if( expr->op == PT_ERROR ) {
PTreeErrorNode( expr );
retn = CNV_ERR;
} else {
retn = CNV_OK;
}
} else {
retn = CNV_ERR;
}
break;
case MP_ZERO :
expr->type = tgt_type;
expr->flags &= PTF_LVALUE;
*a_expr = expr;
retn = CNV_OK;
break;
case MP_EXPR :
init = FALSE;
case MP_CONST :
if( (! safe )
// || conversion == CNV_CAST
|| CNV_OK == validateMpObjs( expr, TRUE, expr->type, tgt_type ) ) {
expr = convertMembPtrExpr( expr, tgt_type, safe, init );
*a_expr = expr;
if( expr->op == PT_ERROR ) {
retn = CNV_ERR;
} else {
retn = CNV_OK;
}
} else {
retn = CNV_ERR;
}
break;
}
return retn;
}
static boolean validateComparisonTypes( // VERIFY CONVERSION IS POSSIBLE
PTREE expr ) // expression
{
PTREE left; // - left operand
PTREE right; // - right operand
boolean retn; // - TRUE ==> can convert
CNV_RETN cnv_retn; // - return from validation
left = PTreeOpLeft( expr );
right = PTreeOpRight( expr );
if( ( left->op == PT_ERROR ) || ( right->op == PT_ERROR ) ) {
PTreeErrorNode( expr );
retn = FALSE;
} else {
TYPE host_left; // - host class to left
TYPE host_right; // - host class to right
host_right = memberPtrHostClass( right->type );
host_left = memberPtrHostClass( left->type );
switch( TypeCommonDerivation( host_left, host_right ) ) {
case CTD_LEFT :
if( host_left == host_right ) {
cnv_retn = validateMpObjs( expr
, FALSE
, right->type
, left->type );
if( cnv_retn == CNV_OK ) break;
if( cnv_retn == CNV_ERR ) break;
// will drop thru to test left --> right
} else {
case CTD_LEFT_VIRTUAL :
case CTD_LEFT_PRIVATE :
case CTD_LEFT_PROTECTED :
cnv_retn = validateMpObjs( expr
, TRUE
, right->type
, left->type );
break;
}
// drops thru
case CTD_RIGHT :
case CTD_RIGHT_VIRTUAL :
case CTD_RIGHT_PRIVATE :
case CTD_RIGHT_PROTECTED :
cnv_retn = validateMpObjs( expr, TRUE, left->type, right->type );
break;
default :
PTreeErrorExpr( expr, ERR_MEMB_PTR_CMP_NOT_DERIVED );
cnv_retn = CNV_ERR;
break;
}
if( CNV_OK == cnv_retn ) {
retn = TRUE;
} else {
retn = FALSE;
}
}
return retn;
}
static PTREE compareConst( // BUILD COMPARISON CONSTANT
PTREE *r_con ) // - reference( constant )
{
PTREE con; // - constant
MEMBER_PTR_CAST castinfo; // - information for casting
castinfo.safe = TRUE;
castinfo.init_conv = TRUE;
con = *r_con;
con = analyseAddrOf( con, con->type, &castinfo );
if( con->op != PT_ERROR ) {
con = generateMembPtrCon( con->type, con, &castinfo );
}
*r_con = con;
return con;
}
static PTREE replaceCompare( // REPLACE COMPARISON WITH A CONSTANT
PTREE expr, // - expression to be replaced
boolean val ) // - TRUE ==> operands are the same
{
PTREE con; // - constant node
if( expr->cgop == CO_NE ) {
val = ! val;
}
con = PTreeBoolConstant( val );
return NodeReplace( expr, con );
}
static MP_TYPE classifyCompare( // CLASSIFY COMPARISON
PTREE *ref ) // - reference[ comparison operand ]
{
MP_TYPE retn; // - operand type
retn = classifyMpExpr( ref );
switch( retn ) {
case MP_ADDR_OF :
*ref = compareConst( ref );
retn = MP_CONST;
break;
case MP_MEMB_FN :
retn = MP_INVALID;
break;
default :
break;
}
return retn;
}
static PTREE compareOperand( // GET COMPARISON OPERAND
PTREE *ref ) // - reference[ CO_MEMPTR_CONST operand ]
{
PTREE operand; // - function operand
PTREE *a_operand; // - operand ptr
ref = PTreeRef( ref );
a_operand = &( (*ref)->u.subtree[0]->u.subtree[1] );
operand = *a_operand;
*a_operand = NULL;
return operand;
}
static PTREE doCompare( // DO A COMPARISON
PTREE expr ) // - expression
{
PTREE left; // - left operand
PTREE right; // - right operand
left = compareOperand( &expr->u.subtree[0] );
right = compareOperand( &expr->u.subtree[1] );
if( ( left->op == PT_SYMBOL )
&&( right->op == PT_SYMBOL ) ) {
expr = replaceCompare( expr
, right->u.symcg.symbol == left->u.symcg.symbol
);
} else {
expr->u.subtree[0] = NodeReplace( expr->u.subtree[0]
, NodeRvalue( left ) );
expr->u.subtree[1] = NodeReplace( expr->u.subtree[1]
, NodeRvalue( right ) );
}
return expr;
}
PTREE MembPtrCommonType( // IMPLICIT CONVERSION TO COMMON TYPE
PTREE expr ) // - binary expression
{
PTREE *r_left; // - reference[ left operand ]
PTREE *r_right; // - reference[ right operand ]
TYPE orig_left; // - original left type
TYPE orig_right; // - original right type
PTREE right; // - right actual
PTREE left; // - left actual
r_left = PTreeRefLeft( expr );
r_right = PTreeRefRight( expr );
right = *r_right;
left = *r_left;
orig_left = NodeType( left );
orig_right = NodeType( right );
ConversionTypesSet( orig_right, orig_left );
switch( MP_OPS( classifyCompare( r_left )
, classifyCompare( r_right ) ) ) {
case MP_OPS( MP_ZERO, MP_ZERO ) :
case MP_OPS( MP_ZERO, MP_CONST ) :
case MP_OPS( MP_CONST, MP_ZERO ) :
case MP_OPS( MP_EXPR, MP_ZERO ) :
case MP_OPS( MP_ZERO, MP_EXPR ) :
case MP_OPS( MP_CONST, MP_EXPR ) :
case MP_OPS( MP_CONST, MP_CONST ) :
case MP_OPS( MP_EXPR, MP_CONST ) :
case MP_OPS( MP_EXPR, MP_EXPR ) :
{ TYPE host_left; // - host class to left
TYPE host_right; // - host class to right
right = *r_right;
left = *r_left;
if( left->type == TypeGetCache( TYPC_VOID_MEMBER_PTR ) ) {
left->type = orig_right;
orig_left = orig_right;
} else if( right->type == TypeGetCache( TYPC_VOID_MEMBER_PTR ) ) {
right->type = orig_left;
orig_right = orig_left;
}
if( ! validateComparisonTypes( expr ) ) break;
host_right = memberPtrHostClass( orig_right );
host_left = memberPtrHostClass( orig_left );
switch( TypeCommonDerivation( host_left, host_right ) ) {
case CTD_LEFT :
if( host_left != host_right
|| CNV_OK == validateMpObjs( expr
, FALSE
, orig_right
, orig_left ) ) {
case CTD_LEFT_VIRTUAL :
case CTD_LEFT_PRIVATE :
case CTD_LEFT_PROTECTED :
expr->type = orig_left;
if( CNV_ERR == MembPtrConvert( &expr->u.subtree[1]
, orig_left
, CNV_EXPR ) ) {
PTreeErrorNode( expr );
}
break;
} else {
case CTD_RIGHT :
case CTD_RIGHT_VIRTUAL :
case CTD_RIGHT_PRIVATE :
case CTD_RIGHT_PROTECTED :
ConversionTypesSet( orig_left, orig_right );
expr->type = orig_right;
if( CNV_ERR == MembPtrConvert( &expr->u.subtree[0]
, orig_right
, CNV_EXPR ) ) {
PTreeErrorNode( expr );
}
break;
}
default :
PTreeErrorExpr( expr, ERR_MEMB_PTR_CMP_NOT_DERIVED );
break;
}
} break;
case MP_OPS( MP_ZERO, MP_INVALID ) :
case MP_OPS( MP_CONST, MP_INVALID ) :
case MP_OPS( MP_EXPR, MP_INVALID ) :
PTreeErrorExpr( expr, ERR_RIGHT_MEMB_PTR_OPERAND );
break;
case MP_OPS( MP_INVALID, MP_ZERO ) :
case MP_OPS( MP_INVALID, MP_CONST ) :
case MP_OPS( MP_INVALID, MP_EXPR ) :
case MP_OPS( MP_INVALID, MP_INVALID ) :
PTreeErrorExpr( expr, ERR_LEFT_MEMB_PTR_OPERAND );
break;
DbgDefault( "MembPtrCommonType -- bad" );
}
return expr;
}
PTREE MembPtrCompare( // COMPARISON OF MEMBER POINTERS
PTREE expr ) // - comparison expression
{
PTREE *r_left; // - reference[ left operand ]
PTREE *r_right; // - reference[ right operand ]
r_left = PTreeRefLeft( expr );
r_right = PTreeRefRight( expr );
switch( MP_OPS( classifyCompare( r_left )
, classifyCompare( r_right ) ) ) {
case MP_OPS( MP_ZERO, MP_ZERO ) :
expr = replaceCompare( expr, TRUE );
break;
case MP_OPS( MP_ZERO, MP_CONST ) :
case MP_OPS( MP_CONST, MP_ZERO ) :
expr = replaceCompare( expr, FALSE );
break;
case MP_OPS( MP_EXPR, MP_ZERO ) :
case MP_OPS( MP_ZERO, MP_EXPR ) :
expr = doCompare( expr );
break;
case MP_OPS( MP_CONST, MP_EXPR ) :
case MP_OPS( MP_CONST, MP_CONST ) :
case MP_OPS( MP_EXPR, MP_CONST ) :
case MP_OPS( MP_EXPR, MP_EXPR ) :
if( validateComparisonTypes( expr ) ) {
expr = doCompare( expr );
}
break;
case MP_OPS( MP_ZERO, MP_INVALID ) :
case MP_OPS( MP_CONST, MP_INVALID ) :
case MP_OPS( MP_EXPR, MP_INVALID ) :
PTreeErrorExpr( expr, ERR_RIGHT_MEMB_PTR_OPERAND );
break;
case MP_OPS( MP_INVALID, MP_ZERO ) :
case MP_OPS( MP_INVALID, MP_CONST ) :
case MP_OPS( MP_INVALID, MP_EXPR ) :
case MP_OPS( MP_INVALID, MP_INVALID ) :
PTreeErrorExpr( expr, ERR_LEFT_MEMB_PTR_OPERAND );
break;
DbgDefault( "MembPtrCompare -- bad" );
}
return expr;
}
static SYMBOL funcArgSym( // DETERMINE COMPONENT'S SYMBOL, IF THERE
PTREE component, // - component to be checked
unsigned offset ) // - offset from field
{
PTREE con; // - constant node for offset
SYMBOL sym; // - symbol for member pointer
component = component->u.subtree[1];
if( PTreeOpFlags( component ) & PTO_RVALUE ) {
component = component->u.subtree[0];
}
if( NodeIsBinaryOp( component, CO_DOT )
|| NodeIsBinaryOp( component, CO_ARROW ) ) {
con = NodeGetConstantNode( component->u.subtree[1] );
if( con == NULL ) {
sym = NULL;
} else if( offset != con->u.uint_constant ) {
sym = NULL;
} else {
component = component->u.subtree[0];
if( component->op == PT_SYMBOL ) {
sym = component->u.symcg.symbol;
} else {
sym = NULL;
}
}
} else {
sym = NULL;
}
return sym;
}
PTREE MembPtrFuncArg( // EXPRESSION FOR FUNCTION ARGUMENT
PTREE arg ) // - converted expression
{
SYMBOL sym; // - symbol for function arg
PTREE component; // - member-ptr component
unsigned offset_delta; // - delta offset
unsigned offset_index; // - index offset
component = arg->u.subtree[0];
sym = funcArgSym( component, 0 );
if( sym != NULL ) {
memberPtrLayout( &offset_delta, &offset_index );
component = component->u.subtree[0];
if( sym == funcArgSym( component, offset_delta ) ) {
component = component->u.subtree[0];
if( sym != funcArgSym( component, offset_index ) ) {
sym = NULL;
}
} else {
sym = NULL;
}
}
if( sym == NULL ) {
arg = membPtrStoreTemp( arg );
} else {
// arg = NodeReplace( arg, MakeNodeSymbol( sym ) );
arg = NodeReplace( arg, NodeMakeCallee( sym ) );
}
return NodeRvalue( arg );
}
PTREE ConvertMembPtrConst( // CONVERT TO TEMP. A MEMBER-PTR CONST
PTREE *a_expr ) // - addr [expression]
{
PTREE expr; // - expression
expr = *a_expr;
if( ! ( PTreeOpFlags( expr ) & PTO_RVALUE ) ) {
MembPtrConvert( a_expr, expr->type, CNV_EXPR );
expr = *a_expr;
if( NodeIsUnaryOp( expr, CO_MEMPTR_CONST ) ) {
expr = membPtrStoreTemp( expr );
*a_expr = expr;
}
}
return expr;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?