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