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 + -
显示快捷键?