membptr.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,688 行 · 第 1/4 页
C
1,688 行
( PTREE expr ) // - expression
{
return CompFlags.extensions_enabled
&& expr->op == PT_SYMBOL
&& expr->cgop != CO_NAME_THIS
&& SymIsThisFuncMember( expr->u.symcg.symbol );
}
static
boolean membPtrExtensionFmt // TEST IF EXTENDED FUNCTION MEMBER PTR FORMAT
( PTREE expr ) // - expression
{
return CompFlags.extensions_enabled
&& expr->op == PT_SYMBOL
&& expr->cgop != CO_NAME_THIS
&& SymIsFuncMember( expr->u.symcg.symbol );
}
PTREE MembPtrExtend // FAKE AN ADDRESS-OF NODE FOR BARE FUNCTION
( PTREE expr ) // - expression
{
SYMBOL sym; // - symbol for function
DbgVerify( CompFlags.extensions_enabled, "bad call of MembPtrExtend" );
expr->flags |= PTF_COLON_QUALED;
expr->flags &= ~PTF_LVALUE;
expr = NodeUnaryCopy( CO_ADDR_OF, expr );
sym = expr->u.symcg.symbol;
expr->type = MakeMemberPointerTo( SymClass(sym ), sym->sym_type );
return expr;
}
static MP_TYPE classifyMpExpr( // CLASSIFY A MEMBER-POINTER EXPRESSION
PTREE *a_expr ) // - addr[ expression ]
{
PTREE expr; // - expression
PTREE replace; // - replacement expression (CO_MEMPTR)
MP_TYPE retn; // - type of member-ptr expression
TYPE type_mp; // - type of member pointer
unsigned offset_delta; // - delta offset
unsigned offset_index; // - index offset
TYPE type; // - field type
PTREE func; // - accessed function
PTREE delta; // - accessed delta
PTREE index; // - accessed index
expr = PTreeOp( a_expr );
type_mp = MemberPtrType( (*a_expr)->type );
if( NodeIsUnaryOp( expr, CO_MEMPTR_CONST ) ) {
if( MembPtrZeroConst( expr ) ) {
retn = MP_ZERO;
} else {
expr = expr->u.subtree[0];
if( expr->u.subtree[1]->op == PT_SYMBOL ) {
expr = expr->u.subtree[0];
if( NULL == NodeGetConstantNode( expr->u.subtree[1] ) ) {
retn = MP_EXPR;
} else {
expr = expr->u.subtree[0];
if( NULL == NodeGetConstantNode( expr->u.subtree[1] ) ) {
retn = MP_EXPR;
} else {
retn = MP_CONST;
}
}
} else {
retn = MP_EXPR;
}
}
} else if( NodeIsZeroConstant( expr ) ) {
replace = MembPtrZero( TypeGetCache( TYPC_VOID_MEMBER_PTR ) );
*a_expr = NodeReplaceTop( *a_expr, replace );
retn = MP_ZERO;
} else if( membPtrAddrOfNode( expr ) ) {
retn = MP_ADDR_OF;
} else if( NULL != type_mp ) {
expr = *a_expr;
if( 0 == ( expr->flags & PTF_LVALUE ) ) {
if( ( PTreeOpFlags( expr ) & PTO_RVALUE )
&&( 0 == ( PTF_LVALUE & expr->u.subtree[0]->flags ) ) ) {
PTREE dlt; // - node to be deleted
dlt = expr;
expr = expr->u.subtree[0];
PTreeFree( dlt );
} else {
expr = membPtrTemporary( expr );
}
}
type = MakePointerTo( dereferenceFnType( type_mp->of ) );
func = accessOp( NodeDupExpr( &expr ), 0, type );
type = memberPtrLayout( &offset_delta, &offset_index );
delta = accessOp( NodeDupExpr( &expr ), offset_delta, type );
index = accessOp( expr, offset_index, type );
expr = makeMembPtrExpr( expr->type, func, delta, index );
expr->flags |= PTF_LVALUE;
*a_expr = expr;
retn = MP_EXPR;
} else if( membPtrExtensionFmt( expr ) ) {
retn = MP_MEMB_FN;
} else {
retn = MP_INVALID;
}
return retn;
}
CNV_RETN MembPtrAssign( // ASSIGNMENT/INITIALIZATION OF MEMBER POINTER
PTREE *a_expr ) // - addr[ assignment expression ]
{
PTREE expr; // - assignment expression
PTREE tgt; // - target operand
SYMBOL sym; // - symbol being initialized/assigned
CNV_RETN retn; // - return: CNV_...
expr = *a_expr;
retn = MembPtrConvert( &expr->u.subtree[1]
, expr->u.subtree[0]->type
, CNV_INIT_COPY );
if( retn == CNV_OK ) {
tgt = NodeDupExpr( &expr->u.subtree[0] );
classifyMpExpr( &expr->u.subtree[0] );
switch( classifyMpExpr( &expr->u.subtree[1] ) ) {
case MP_CONST :
case MP_ZERO :
if( NodeIsBinaryOp( expr, CO_INIT ) ) {
if( expr->flags & PTF_KEEP_MPTR_SIMPLE ) {
// we won't be executing this so keep it simple
NodeFreeDupedExpr( tgt );
NodeFreeDupedExpr( expr->u.subtree[0] );
expr->u.subtree[0] = NULL;
break;
}
if( tgt->op == PT_SYMBOL ) {
sym = tgt->u.symcg.symbol;
if( ( sym->id == SC_AUTO )
||( sym->id == SC_REGISTER ) ) {
expr = storeMembPtrCon( expr, tgt );
} else {
expr->u.subtree[0] = NodeReplace( expr->u.subtree[0]
, tgt );
expr->type = tgt->type;
expr->flags |= PTF_LVALUE;
}
} else {
expr = storeMembPtrCon( expr, tgt );
}
} else {
expr = storeMembPtrCon( expr, tgt );
}
break;
default :
expr = storeMembPtrCon( expr, tgt );
break;
}
*a_expr = expr;
if( expr->op == PT_ERROR ) {
retn = CNV_ERR;
} else {
retn = CNV_OK;
}
}
return retn;
}
static CNV_DIAG diagDerefPtr = // diagnosis for ptr conversion
{ ERR_MP_PTR_IMPOSSIBLE
, ERR_MP_PTR_AMBIGUOUS
, 0
, ERR_MP_PTR_PRIVATE
, ERR_MP_PTR_PROTECTED
};
static CNV_DIAG diagDerefObject = // diagnosis for ptr conversion
{ ERR_MP_OBJECT_IMPOSSIBLE
, ERR_MP_OBJECT_AMBIGUOUS
, 0
, ERR_MP_OBJECT_PRIVATE
, ERR_MP_OBJECT_PROTECTED
};
static PTREE doDereference( // GENERATE DE-REFERENCING CODE
PTREE lhs, // - node: ptr. to class
PTREE rhs ) // - node: member pointer object (lvalue)
{
TYPE type_mp; // - type of member pointer
TYPE type_mc; // - type of member pointer's class
TYPE type_cp; // - type of class pointer for member-ptr class
TYPE type_fn; // - type of de-referencing function
TYPE type_offset; // - type of the offset
SCOPE scope; // - scope of class for member-ptr
PTREE expr; // - resultant expression
PTREE expr_root; // - resultant expression root
PTREE func; // - function node
PTREE delta; // - delta node
PTREE index; // - index node
PTREE temp; // - temporary
PTREE *r_rhs; // - reference[ member-ptr constant ]
type_mp = MemberPtrType( rhs->type );
type_mc = MemberPtrClass( type_mp );
type_cp = MakePointerTo( type_mc );
scope = TypeScope( type_mc );
type_fn = dereferenceFnType( type_mp->of );
r_rhs = PTreeRef( &rhs );
expr_root = *r_rhs;
*r_rhs = NULL;
expr = expr_root;
expr = expr->u.subtree[0];
func = NodeRvalue( expr->u.subtree[1] );
expr->u.subtree[1] = NULL;
expr = expr->u.subtree[0];
delta = NodeRvalue( expr->u.subtree[1] );
expr->u.subtree[1] = NULL;
type_offset = delta->type;
if( ScopeHasVirtualBases( scope ) ) {
expr = expr->u.subtree[0];
index = NodeRvalue( expr->u.subtree[1] );
expr->u.subtree[1] = NULL;
temp = accessOp( NodeDupExpr( &lhs )
, ScopeVBPtrOffset( scope )
, MakePointerTo( type_offset ) );
expr = addToLeft( NodeFetch( NodeDupExpr( &temp ) )
, NodeDupExpr( &index )
, type_offset );
expr->flags |= PTF_LVALUE;
expr = addToLeft( temp, NodeFetch( expr ), type_cp );
expr->flags &= ~ PTF_LVALUE;
expr = NodeBinary( CO_COLON, expr, lhs );
expr->type = type_cp;
expr = NodeBinary( CO_QUESTION, NodeCompareToZero( index ), expr );
expr->type = type_cp;
} else {
expr = lhs;
}
NodeFreeDupedExpr( expr_root );
expr = addToLeft( delta, expr, type_cp );
expr = NodeArg( expr );
func = NodeUnaryCopy( CO_CALL_SETUP_IND, func );
func->type = type_fn;
expr = NodeBinary( CO_CALL_EXEC_IND, func, expr );
expr->type = type_mp->of;
expr->flags |= PTF_LVALUE;
if( FunctionDeclarationType( type_mp->of ) ) {
expr->flags |= PTF_CALLED_ONLY;
}
*r_rhs = NodeReplace( *r_rhs, expr );
return rhs;
}
// This routine could put out debugging code to ensure that a NULL
// member pointer is not being dereferenced.
//
PTREE MembPtrDereference( // DO '.*' AND '->*' operations
PTREE expr ) // - expression to be processed
{
PTREE left; // - "this" operand
PTREE right; // - member pointer operand
TYPE this_type; // - type for LHS conversion
TYPE unmod; // - unmodified type
TYPE ftype; // - NULL or function type
type_flag flags; // - flags for object type
CNV_DIAG *diag; // - diagnosis to be used
right = expr->u.subtree[1];
switch( classifyMpExpr( &right ) ) {
PTREE *ref; // - reference to right
SYMBOL sym; // - symbol being dereferenced
case MP_MEMB_FN :
case MP_INVALID :
PTreeErrorExpr( expr, ERR_RIGHT_MEMB_PTR_OPERAND );
break;
case MP_ZERO :
PTreeErrorExpr( expr, ERR_MEMB_PTR_DEREF_ZERO );
break;
case MP_ADDR_OF :
ref = PTreeRefRight( expr );
ref = &((*ref)->u.subtree[0]);
right = *ref;
*ref = NULL;
expr->u.subtree[1] = NodeComma( NodePruneTop( expr->u.subtree[1] )
, right );
sym = right->u.symcg.symbol;
if( expr->cgop == CO_DOT_STAR ) {
expr->cgop = CO_DOT;
} else {
expr->cgop = CO_ARROW;
}
expr->type = right->type;
if( SymIsThisDataMember( sym ) ) {
if( ! AnalyseThisDataItem( &expr ) ) {
PTreeErrorNode( expr );
}
} else if( ! SymIsThisFuncMember( sym ) ) {
PTreeErrorExpr( expr, ERR_RIGHT_MEMB_PTR_OPERAND );
}
break;
default :
unmod = TypedefModifierRemoveOnly( right->type );
this_type = MemberPtrClass( unmod );
ftype = FunctionDeclarationType( unmod->of );
if( NULL == ftype ) {
TypeModFlags( unmod->of, &flags );
} else {
flags = TypeArgList( ftype )->qualifier;
}
flags &= TF1_CV_MASK;
left = expr->u.subtree[0];
unmod = TypedefModifierRemoveOnly( NodeType( left ) );
{ type_flag lflags;
TypeModFlags( unmod->of, &lflags );
flags |= lflags & TF1_THIS_MASK;
}
if( 0 != flags ) {
this_type = MakeModifiedType( this_type, flags );
}
if( expr->cgop == CO_DOT_STAR ) {
diag = &diagDerefObject;
this_type = MakeReferenceTo( this_type );
} else {
diag = &diagDerefPtr;
this_type = MakePointerTo( this_type );
}
left->flags |= PTF_PTR_NONZERO;
left = CastImplicit( left, this_type, CNV_EXPR, diag );
expr->u.subtree[0] = left;
if( PT_ERROR == left->op ) {
PTreeErrorNode( expr );
} else {
expr->u.subtree[0] = NULL;
expr->u.subtree[1] = NULL;
expr = NodeReplace( expr, doDereference( left, right ) );
}
break;
}
return expr;
}
CNV_RETN MembPtrReint( // REINTERPRET A MEMBER POINTER
PTREE *a_expr, // - addr[ conversion expression, not class ]
TYPE tgt_type ) // - target type (member-pointer)
{
CNV_RETN retn; // - return: CNV_...
PTREE expr; // - conversion expression
unsigned classification; // - operand classification
classification = classifyMpExpr( a_expr );
expr = *a_expr;
switch( classification ) {
case MP_INVALID :
PTreeErrorExpr( expr, ERR_MEMB_PTR_OPERAND );
retn = CNV_ERR;
break;
case MP_MEMB_FN :
{ SYMBOL sym; // - symbol for node
sym = expr->u.symcg.symbol;
expr->flags |= PTF_COLON_QUALED;
expr = NodeUnaryCopy( CO_ADDR_OF, expr );
expr->type = MakeMemberPointerTo( SymClass(sym ), sym->sym_type );
} // drops thru
case MP_ADDR_OF :
expr = memPtrAddrOfCon( expr, expr->type, FALSE, FALSE );
DbgVerify( expr->op != PT_ERROR, "should work" );
// drops thru
case MP_EXPR :
case MP_CONST :
case MP_ZERO :
expr->type = tgt_type;
expr = membPtrStoreTemp( expr );
retn = CNV_OK;
break;
}
*a_expr = expr;
return retn;
}
CNV_RETN MembPtrConvert( // CONVERT A MEMBER POINTER
PTREE *a_expr, // - addr[ conversion expression, not class ]
TYPE tgt_type, // - target type (member-pointer)
unsigned conversion ) // - type of conversion
{
CNV_RETN retn; // - return: CNV_...
PTREE expr; // - conversion expression
boolean safe; // - TRUE ==> only safe conversion allowed
boolean init; // - TRUE ==> an initialization or assignment
unsigned classification; // - operand classification
switch( conversion ) {
case CNV_INIT :
case CNV_FUNC_ARG :
case CNV_FUNC_RET :
case CNV_ASSIGN :
safe = TRUE;
init = TRUE;
break;
case CNV_CAST :
safe = FALSE;
init = FALSE;
break;
default :
safe = TRUE;
init = FALSE;
break;
}
classification = classifyMpExpr( a_expr );
expr = *a_expr;
ConversionTypesSet( expr->type, tgt_type );
switch( classification ) {
case MP_INVALID :
PTreeErrorExpr( expr, ERR_MEMB_PTR_OPERAND );
retn = CNV_ERR;
break;
case MP_MEMB_FN :
{ SYMBOL sym; // - symbol for node
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?