opovload.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,248 行 · 第 1/3 页

C
1,248
字号
        *a_operand = CastImplicit( *a_operand, type, CNV_INIT_COPY, &diag_transform );
        cnv_status = ( PT_ERROR == *a_operand ) ? CNV_ERR : CNV_OK;
    } else {
        cnv_status = CNV_OK;
    }
    return cnv_status;
}


static PTREE transform_conversions( // TRANSFORM OPERAND(S) BY CONVERSIONS
    OLINF* olinf,               // - overload information
    SYMBOL dummy )              // - dummy symbol for conversion
{
    PTREE node;                 // - node for operation
    OP_MASK mask;               // - operator mask
    arg_list *alist;            // - prototype for function
    unsigned error_right;       // - error occurred on right operand
    unsigned error_left;        // - error occurred on left operand

    node = olinf->expr;
    mask = olinf->mask;
    alist = SymFuncArgList( dummy );
    if( mask & OPM_ASSIGN ) {
        error_right = transform_operand( &node->u.subtree[1]
                                       , alist->type_list[1]
                                       , mask );
        error_left = transform_operand( &node->u.subtree[0]
                                      , alist->type_list[0]
                                      , mask );
    } else {
        error_left = transform_operand( &node->u.subtree[0]
                                      , alist->type_list[0]
                                      , mask );
        if( alist->num_args > 1
         && ! ( mask & OPM_POST ) ) {
            error_right = transform_operand( &node->u.subtree[1]
                                           , alist->type_list[1]
                                           , mask );
        } else {
            error_right = CNV_OK;
        }
    }
    if( ( error_right != CNV_OK ) || ( error_left != CNV_OK ) ) {
        PTreeErrorNode( node );
    }
    return node;
}

// did this symbol come from this search result ?
static boolean symInResult( SYMBOL sym, SEARCH_RESULT *result )
{
    SYMBOL      curr;
    SYM_REGION  *ptr;

    RingIterBeg( result->sym_name->name_syms, curr ) {
        if( curr == sym ) {
            return TRUE;
        }
    } RingIterEnd( curr )
    RingIterBeg( result->region, ptr ) {

        RingIterBegFrom( ptr->from, curr ) {
            if( curr == sym ) {
                return TRUE;
            }

        } RingIterEndTo( curr, ptr->to )

    } RingIterEnd( ptr )
    return FALSE;
}

static PTREE transform_to_call( // TRANSFORM NODE TO FUNCTION CALL
    PTREE node,                 // - type node
    PTREE left,                 // - left operand
    PTREE right )               // - right operand
{
    node->u.subtree[0] = left;
    node->u.subtree[1] = right;
    node->cgop = CO_CALL_NOOVLD;
    node->op = PT_BINARY;
    node->flags = 0;
    return( node );
}


static PTREE transform_naked(   // TRANSFORM TO CALL TO NON-MEMBER FUNCTION
    OLINF* olinf,
    SYMBOL fun )              // - overload information
{
    CGOP cgop;                  // - expression operator
    PTREE param;                // - parameters node
    PTREE retn;                 // - resultant call expression
    SEARCH_RESULT *result;

    cgop = olinf->expr->cgop;
    param = NodeArg( olinf->left.operand );
    if( olinf->flags & PTO_BINARY ) {
        if( cgop == CO_CALL ) {
            param->u.subtree[0] = olinf->right.operand;
        } else {
            param = NodeArgument( param, olinf->right.operand );
        }
    } else if( cgop == CO_POST_PLUS_PLUS
            || cgop == CO_POST_MINUS_MINUS ) {
        param = NodeArgument( param, NodeZero() );
    }
    result = NULL;
    if( olinf->result_nonmem != NULL ) {
        if( olinf->result_nonmem_namespace == NULL ) {
            result = olinf->result_nonmem;
        } else {
            // both non-null
            if( symInResult( fun, olinf->result_nonmem ) ) {
                result = olinf->result_nonmem;
                ScopeFreeResult( olinf->result_nonmem_namespace );
            } else {
                result = olinf->result_nonmem_namespace;
                ScopeFreeResult( olinf->result_nonmem );
            }
        }
    } else {
        result = olinf->result_nonmem_namespace;
    }
    DbgAssert( symInResult( fun, result ) );
    retn = transform_to_call( olinf->expr
                            , build_fun_name( result )
                            , param );
    retn = PTreeCopySrcLocation( retn, olinf->expr );
    return retn;
}


static PTREE transform_member(  // TRANSFORM TO CALL TO MEMBER FUNCTION
    OLINF* olinf )              // - overload information
{
    PTREE op;                   // - original operator
    PTREE param;                // - parameter list
    PTREE caller;               // - caller node
    SYMBOL op_sym;              // - symbol for overloaded op
    CGOP cgop;                  // - expression operator

    op = olinf->expr;
    cgop = op->cgop;
    if( cgop == CO_ARROW ) {
        op_sym = olinf->result_mem->sym_name->name_syms;
        if( ! ArrowMemberOK( op_sym ) ) {
            PTreeErrorExprSym( op, ERR_OPERATOR_ARROW_RETURN_BAD, op_sym );
            return op;
        }
        caller = NodeDottedFunction( olinf->left.operand
                                   , build_fun_name( olinf->result_mem ) );
        caller = PTreeCopySrcLocation( caller, op );
        caller = NodeBinary( CO_CALL, caller, NULL );
        caller = PTreeCopySrcLocation( caller, op );
        caller = AnalyseCall( caller, NULL );
        op->u.subtree[0] = caller;
        if( caller->op == PT_ERROR ) {
            PTreeErrorNode( op );
        } else {
            olinf->repeat_overload = TRUE;
        }
    } else {
        if( olinf->flags & PTO_BINARY ) {
            param = olinf->right.operand;
            if( cgop != CO_CALL ) {
                param = NodeArg( param );
            }
        } else {
            if( ( cgop == CO_POST_PLUS_PLUS   )
              ||( cgop == CO_POST_MINUS_MINUS ) ) {
                param = NodeArg( NodeZero() );
            } else {
                param = NULL;
            }
        }
        caller = NodeDottedFunction( olinf->left.operand
                                   , build_fun_name( olinf->result_mem ) );
        caller = PTreeCopySrcLocation( caller, op );
        op = transform_to_call( op, caller, param );
        op = PTreeCopySrcLocation( op, olinf->expr );
    }
    return op;
}


static PTREE resolve_symbols(   // RESOLVE MULTIPLE OVERLOAD DEFINITIONS
    OLINF* olinf )              // - overload information
{
    PTREE ptlist[2];            // - PT list for all but call
    PTREE zero_node;            // - , 0 ) parm for @++ and @-- overloading
    FNOV_RESULT ovret;          // - overload return
    unsigned count;             // - # of arguments
    SYMBOL fun;                 // - overloaded function to use
    struct                      // - arg.list
    {   arg_list    base;       // - - hdr, entry[1]
        TYPE        arg2;       // - - entry[2]
    } alist;
    FNOV_DIAG fnov_diag;        // - diagnosis information

    ExtraRptIncrementCtr( ctrResolveOps );
    if( olinf->mask & OPM_FUN ) {
        PTREE oper;
        ExtraRptIncrementCtr( ctrResolveFun );
        fun = olinf->result_mem->sym_name->name_syms;
        oper = PTreeIdSym( fun );
        oper = NodeSymbolNoRef( oper, fun, olinf->result_mem );
        oper->cgop = CO_NAME_DOT;
        olinf->expr->u.subtree[0] = NodeDottedFunction( olinf->left.operand
                                                      , oper );

        ScopeFreeResult( olinf->result_nonmem );
        ScopeFreeResult( olinf->result_nonmem_namespace );
        return olinf->expr;
    }
    InitArgList( &alist.base );
    zero_node = NULL;
    ptlist[0] = olinf->left.operand;
    alist.base.type_list[ 0 ] = olinf->left.node_type;
    if( olinf->flags & PTO_BINARY ) {
        if( olinf->mask & OPM_ASSIGN ) {
            ptlist[1] = olinf->right.operand;
            alist.base.type_list[ 1 ] = olinf->right.node_type;
            count = 2;
        } else if( olinf->mask & OPM_LT ) {
            count = 1;
        } else {
            if( ( olinf->mask & OPM_SUB )
              &&( olinf->result_mem != NULL ) ) {
                olinf->scalars = NULL;
            }
            ptlist[1] = olinf->right.operand;
            alist.base.type_list[ 1 ] = olinf->right.node_type;
            count = 2;
        }
    } else if( olinf->mask & OPM_POST ) {
        zero_node = NodeZero();
        setupOVOP( olinf, zero_node, &olinf->right );
        ptlist[1] = olinf->right.operand;
        alist.base.type_list[ 1 ] = olinf->right.node_type;
        count = 2;
    } else {
        count = 1;
    }
    alist.base.num_args = count;
    // this qualifier is handled explicitly by the first entry in the arg_list
    ovret = OpOverloadedDiag( &fun
                        , olinf->result_mem
                        , olinf->result_nonmem
                        , olinf->result_nonmem_namespace
                        , olinf->scalars
                        , (arg_list*)&alist
                        , ptlist
                        , &fnov_diag );
    if( ovret == FNOV_AMBIGUOUS && CompFlags.extensions_enabled ) {
        FNOV_LIST* amb_list;    // - ambiguity list
        SYMBOL next;            // - next symbol
        boolean have_user_defined = FALSE;
        boolean have_void = FALSE;
        if( ((olinf->mask & OPM_NV) == 0) && (olinf->mask & OPM_PP ) ) {
            // we're in the (void *, void *) area
            for( amb_list = NULL; ; ) {
                next = FnovGetAmbiguousEntry( &fnov_diag, &amb_list );
                if( next == NULL ) break;
                if( next->name != NULL ) {
                    have_user_defined = TRUE;
                } else if( op_basic_arg[ next->u.scalar_order ][ 0 ] ==
                           TYP_POINTER
                        && op_basic_arg[ next->u.scalar_order ][ 1 ] ==
                           TYP_POINTER ) {
                    // the (void *, void *) was one of the ambiguous ones
                    have_void = TRUE;
                }
                if( have_user_defined && have_void ) {
                    break;
                }
            }
        }
        if( have_user_defined && have_void ) { // try again
            int i;
            FnovFreeDiag( &fnov_diag );
            for( i = 0; i < MAX_FUN_PROTOS_EXTRA; i++ ) {
                OP_MASK fun_mask;
                fun_mask = opfun_mask_extra[ i ];
                if( olinf->mask & fun_mask ) {
                    RingAppend( &olinf->scalars, ovfuns_extra[ i ] );
                }
            }
            ovret = OpOverloadedLimitDiag( &fun
                                , olinf->result_mem
                                , olinf->result_nonmem
                                , olinf->result_nonmem_namespace
                                , olinf->scalars
                                , (arg_list*)&alist
                                , ptlist
                                , FNC_STDOP_CV_VOID
                                , &fnov_diag );
        }
    }
    if( ovret == FNOV_AMBIGUOUS && CompFlags.overload_13332 ) {
        FNOV_LIST* amb_list;    // - ambiguity list
        SYMBOL next;            // - next symbol
        boolean have_user_defined = FALSE;
        for( amb_list = NULL; ; ) {
            next = FnovGetAmbiguousEntry( &fnov_diag, &amb_list );
            if( next == NULL ) break;
            if( next->name != NULL ) {
                have_user_defined = TRUE;
                break;
            }
        }
        if( have_user_defined ) {
            FnovFreeDiag( &fnov_diag );
            ovret = OpOverloadedLimitDiag( &fun
                                , olinf->result_mem
                                , olinf->result_nonmem
                                , olinf->result_nonmem_namespace
                                , olinf->scalars
                                , (arg_list*)&alist
                                , ptlist
                                , FNC_USE_WP13332
                                , &fnov_diag );
        }
    }
    switch( ovret ) {
      case FNOV_AMBIGUOUS:
      { FNOV_LIST* amb_list;    // - ambiguity list
        SYMBOL next;            // - next symbol
        fun = NULL;
        for( amb_list = NULL; ; ) {
            next = FnovGetAmbiguousEntry( &fnov_diag, &amb_list );
            if( next == NULL ) break;
            if( next->name == NULL
             && next->id != SC_MEMBER
             && next->u.scalar_order < ( MAX_FUN_PROTOS - 2 ) ) {
                if( fun == NULL
                 || fun->u.scalar_order < next->u.scalar_order ) {
                    fun = next;
                }
            } else {
                    fun = NULL;
                    break;
            }
        }
        if( fun == NULL ) {
            PTreeErrorExpr( olinf->expr, ERR_OPERATOR_AMBIGUOUS_OVERLOAD );
            for( ; ; ) {
                SYMBOL reject = FnovNextAmbiguousEntry( &fnov_diag );
                if( reject == NULL ) break;
                if( reject->name == NULL ) {
                    CErr2p( INF_CONV_AMBIG_SCALAR
                          , SymFuncArgList( reject )->type_list[0] );
                } else {
                    InfSymbolAmbiguous( reject );
                }
            }
            ScopeFreeResult( olinf->result_mem );
            ScopeFreeResult( olinf->result_nonmem );
            ScopeFreeResult( olinf->result_nonmem_namespace );
            break;
        }
        // drops thru
      }
      case FNOV_NONAMBIGUOUS :
        if( fun->id == SC_MEMBER ) {
            ExtraRptIncrementCtr( ctrResolveMember );
            if( olinf->expr->cgop == CO_EQUAL
             && olinf->left.class_type ==
                 ClassTypeForType( SymFuncArgList( fun )->type_list[0] ) ) {
                ScopeFreeResult( olinf->result_mem );
            } else {
                olinf->expr = transform_member( olinf );
            }
            ScopeFreeResult( olinf->result_nonmem );
            ScopeFreeResult( olinf->result_nonmem_namespace );
        } else if( fun->name == NULL ) {
            ExtraRptIncrementCtr( ctrResolveScalar );
            olinf->expr = transform_conversions( olinf, fun );
            ScopeFreeResult( olinf->result_mem );
            ScopeFreeResult( olinf->result_nonmem );
            ScopeFreeResult( olinf->result_nonmem_namespace );
        } else {
            ExtraRptIncrementCtr( ctrResolveNaked );
            olinf->expr = transform_naked( olinf, fun );
            ScopeFreeResult( olinf->result_mem );
        }
        break;
      case FNOV_NO_MATCH:
        ExtraRptIncrementCtr( ctrResolveNone );
        ScopeFreeResult( olinf->result_mem );
        ScopeFreeResult( olinf->result_nonmem );
        ScopeFreeResult( olinf->result_nonmem_namespace );
        break;
    }
    if( zero_node != NULL ) {
        PTreeFree( zero_node );
    }
    FnovFreeDiag( &fnov_diag );
    return olinf->expr;
}

static SCOPE nsExtract( OLINF *inf )
{
    TYPE user_type;
    SCOPE scope;

    user_type = inf->left.user_type;
    if( user_type == NULL ) {
        user_type = inf->right.user_type;
    }
    if( user_type->id == TYP_CLASS ) {
        scope = user_type->u.c.scope;
    } else {
        DbgAssert( user_type->id == TYP_ENUM );
        scope = user_type->u.t.scope;
    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?