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