opovload.c

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

C
1,248
字号
    scope = ScopeEnclosingId( scope, SCOPE_FILE );
    if( scope == GetFileScope() ) {
        scope = NULL;
    }
    return( scope );
}


PTREE OverloadOperator(         // HANDLE OPERATOR OVERLOADING, IF REQ'D
    PTREE op )                  // - node containing operator
{
    OLINF oli;                  // - overload info
    SCOPE enclosing;

    ExtraRptIncrementCtr( ctrOverloads );
    for( ; ; ) {
        if( ! initOLINF( op, &oli ) ) break;
        scalarOperators( &oli );
        if( ! oli.have_user_type ) break;
        if( oli.flags & PTO_OVLOAD ) {
            char *ov_fun_name;          // - name of overloaded function
            TYPE type;                  // - class type
            SCOPE scope;                // - class scope
            CGOP cgop;                  // - expression operator
            ExtraRptIncrementCtr( ctrOverloadOps );
            cgop = oli.expr->cgop;
            type = oli.left.class_type;
            if( type == NULL ) {
                if( ( 0 == ( oli.mask & ( OPM_QUEST | OPM_FUN | OPM_SUB ) ) )
                 && cgop != CO_EQUAL ) {
                    SCOPE scope;
                    ov_fun_name = CppOperatorName( cgop );
                    oli.result_nonmem = ScopeFindNaked( GetFileScope()
                                                      , ov_fun_name );
                    scope = nsExtract( &oli );
                    if( scope != NULL ) {
                        oli.result_nonmem_namespace = ScopeContainsNaked( scope, ov_fun_name );
                    }
                }
            } else {
                scope = TypeScope( type );
                ov_fun_name = CppOperatorName( cgop );
                if( cgop == CO_EQUAL ) {
                    ClassDefaultOpEq( type, type );
                    oli.result_mem = ScopeContainsMember( scope, ov_fun_name );
                } else {
                    oli.result_mem = ScopeFindMember( scope, ov_fun_name );
                    oli.result_nonmem = ScopeFindNaked( GetFileScope(), ov_fun_name );
                    enclosing = nsExtract( &oli );
                    if( enclosing != NULL ) {
                        oli.result_nonmem_namespace = ScopeContainsNaked( enclosing, ov_fun_name );
                    }
                }
            }
            if( oli.result_mem == NULL
             && oli.result_nonmem == NULL
             && oli.result_nonmem_namespace == NULL ) {
                if( oli.scalars == NULL ) break;
                if( ! oli.have_class_type ) break;
            }
            op = resolve_symbols( &oli );
            if( ! oli.repeat_overload ) break;
            if( op->op == PT_ERROR ) break;
            ExtraRptIncrementCtr( ctrRepeats );
        } else {
            if( NULL == oli.scalars ) break;
            op = resolve_symbols( &oli );
            break;
        }
    }
    return op;
}


static boolean isBadFun(        // DIAGNOSE IF MEMBER FUNC. OR OVERLOADED
    PTREE expr,                 // - expression being analysed
    PTREE operand )             // - operand to be diagnosed
{
    boolean retn;               // - return: TRUE ==> diagnosed
    PTREE fnode;                // - function node
    PTREE node;                 // - node to be examined

    node = PTreeOp( &operand );
    switch( NodeAddrOfFun( node, &fnode ) ) {
      default :
        retn = FALSE;
        break;
      case ADDR_FN_ONE :
        if( SymIsThisFuncMember( fnode->u.symcg.symbol ) ) {
            PTreeErrorExprSymInf( node
                                , ERR_ADDR_NONSTAT_MEMBER_FUNC
                                , fnode->u.symcg.symbol );
            PTreeErrorNode( expr );
            retn = TRUE;
        } else {
            retn = FALSE;
        }
        break;
      case ADDR_FN_MANY :
        PTreeErrorExprSymInf( node
                            , ERR_ADDR_OF_OVERLOADED_FUN
                            , fnode->u.symcg.symbol );
        PTreeErrorNode( expr );
        retn = TRUE;
        break;
    }
    return retn;
}


PTREE ConvertBoolean(           // CONVERSION TO BOOLEAN EXPRESSION
    PTREE bexpr )               // - the boolean expression
{
    PTREE left;                 // - left expression
    OLINF oli;                  // - overload info

    ExtraRptIncrementCtr( ctrBoolConv );
    initOLINF( bexpr, &oli );
    bexpr = oli.expr;
    left = bexpr->u.subtree[0];
    if( NULL != oli.left.user_type ) {
        ExtraRptIncrementCtr( ctrBoolRes );
        scalarOperators( &oli );
        if( NULL != oli.scalars ) {
            bexpr = resolve_symbols( &oli );
            if( ( bexpr->op != PT_ERROR )
              &&( NULL != ClassTypeForType( bexpr->u.subtree[0]->type ) ) ) {
                PTreeErrorExpr( PTreeOpLeft( bexpr ), ERR_NOT_BOOLEAN );
                PTreeErrorNode( bexpr );
                return bexpr;
            }
        }
        if( MemberPtrType( bexpr->u.subtree[0]->type ) ) {
            bexpr = MembPtrCompare( bexpr );
            if( bexpr->op == PT_ERROR ) return bexpr;
        }
        if( PT_BINARY == bexpr->op ) {
            bexpr = FoldBinary( bexpr );
        } else if( PT_UNARY == bexpr->op ) {
            bexpr = FoldUnary( bexpr );
        }
    } else if( NULL != MemberPtrType( left->type ) ) {
        bexpr = MembPtrCompare( bexpr );
    } else if( oli.flags & PTO_BINARY ) {
        if( ! isBadFun( bexpr, bexpr->u.subtree[0] )
         && ! isBadFun( bexpr, bexpr->u.subtree[1] ) ) {
            bexpr = FoldBinary( bexpr );
        }
    } else if( oli.flags & PTO_UNARY ) {
        if( ! isBadFun( bexpr, bexpr->u.subtree[0] ) ) {
            bexpr = FoldUnary( bexpr );
        }
    }
    return bexpr;
}


static TYPE getOperandType(     // GET OPERAND TYPE
    type_id id,                 // - type id
    GETOP_CONTROL ctl )         // - control flavour
{
    TYPE type;                  // - manufactured type

    switch( id ) {
      case TYP_POINTER :
        if( ctl & GETOP_CONST ) {
            if( ctl & GETOP_VOLATILE ) {
                // const volatile
                DbgAssert( ( ctl & GETOP_NOVOID ) == 0 );
                type = TypePtrToConstVolatileVoidStdop();
            } else {
                // const
                if( ctl & GETOP_NOVOID ) {
                    type = TypePtrToConstVoidStdopArith();
                } else {
                    type = TypePtrToConstVoidStdop();
                }
            }
        } else {
            if( ctl & GETOP_VOLATILE ) {
                // volatile
                DbgAssert( ( ctl & GETOP_NOVOID ) == 0 );
                type = TypePtrToVolatileVoidStdop();
            } else {
                // neither const nor volatile
                if( ctl & GETOP_NOVOID ) {
                    type = TypePtrToVoidStdopArith();
                } else {
                    type = TypePtrToVoidStdop();
                }
            }
        }
        break;
      case TYP_MEMBER_POINTER :
        type = TypeGetCache( TYPC_VOID_MEMBER_PTR );
        break;
      default :
        type = GetBasicType( id );
        break;
    }
    return( type );
}

static void overloadOperatorInit( // INITIALIZATION
    INITFINI* defn )            // - definition
{
    unsigned arg;               // - current basic argument
    type_id arg1;               // - type of argument(1)
    type_id arg2;               // - type of argument(2)
    TYPE fn_type;               // - full type for function
    TYPE retn_type;             // - return type
    TYPE arg1_type;             // - first argument type
    TYPE arg2_type;             // - second argument type
    SYMBOL fun;                 // - dummy symbol for function
    OP_MASK mask;               // - mask for function

    defn = defn;
    for( arg = 0; arg < MAX_FUN_PROTOS; ++arg ) {
        mask = opfun_mask[arg];
        if( ( mask == 0 ) || ( mask & OPM_RR ) ) {
            arg_list *alist;    // - this gets hammered on overloading
            arg1_type = MakeReferenceTo( GetBasicType( TYP_CHAR ) );
            alist = AllocArgListPerm( 2 );
            alist->type_list[0] = arg1_type;
            alist->type_list[1] = arg1_type;
            fn_type = MakeType( TYP_FUNCTION );
            fn_type->flag |= TF1_PLUSPLUS;
            fn_type->u.f.args = alist;
            fn_type->of = arg1_type;
            CheckUniqueType( fn_type );    // - don't use CheckDupType
        } else {
            GETOP_CONTROL ctl;
            arg1 = op_basic_arg[ arg ][ 0 ];
            retn_type = getOperandType( arg1, GETOP_CONST );
            if( mask & OPM_ASSIGN ) {
                ctl = GETOP_CONST;
            } else {
                ctl = GETOP_DEFAULT;
            }
            if( mask & OPM_NV ) {
                ctl |= GETOP_NOVOID;
            }
            arg1_type = getOperandType( arg1, ctl );
            if( mask & OPM_ASSIGN ) {
                arg1_type = MakeReferenceTo( arg1_type );
                retn_type = MakeReferenceTo( retn_type );
            }
            arg2 = op_basic_arg[ arg ][ 1 ];
            if( arg2 == TYP_MAX ) {
                fn_type = MakeSimpleFunction( retn_type
                                            , arg1_type
                                            , NULL );
            } else {
                ctl = GETOP_DEFAULT;
                if( mask & OPM_NV ) {
                    ctl |= GETOP_NOVOID;
                }
                arg2_type = getOperandType( arg2, ctl );
                fn_type = MakeSimpleFunction( retn_type
                                            , arg1_type
                                            , arg2_type
                                            , NULL );
            }
        }
        fun = AllocSymbol();
        fun->sym_type = fn_type;
        fun->u.scalar_order = arg;
        ovfuns[ arg ] = fun;
    }
    if( CompFlags.extensions_enabled ) {
        // initializes extra function needed to implement extension for
        // Microsoft compatibility
        for( arg = 0; arg < MAX_FUN_PROTOS_EXTRA; ++arg ) {
            mask = opfun_mask_extra[arg];

            arg1 = op_basic_arg_extra[ arg ][ 0 ];
            arg1_type = getOperandType( arg1, extra_ctl[arg] );

            fn_type = MakeSimpleFunction( arg1_type, arg1_type, arg1_type, NULL );
            fun = AllocSymbol();
            fun->sym_type = fn_type;
            fun->u.scalar_order = arg;
            ovfuns_extra[ arg ] = fun;
        }
    }
    ExtraRptRegisterCtr( &ctrBoolConv,      "# Boolean Coversions" );
    ExtraRptRegisterCtr( &ctrBoolRes,       "# Boolean overload resolutions" );
    ExtraRptRegisterCtr( &ctrOverloads,     "# operator overloads" );
    ExtraRptRegisterCtr( &ctrRepeats,       "# repeats of overloading" );
    ExtraRptRegisterCtr( &ctrOverloadOps,   "# operators with C++ overloading" );
    ExtraRptRegisterCtr( &ctrResolveOps,    "# operators requiring resolution" );
    ExtraRptRegisterCtr( &ctrResolveFun,    "# resolved function calls" );
    ExtraRptRegisterCtr( &ctrResolveNone,   "# unresolved overloads" );
    ExtraRptRegisterCtr( &ctrResolveMember, "# resolved by member fun" );
    ExtraRptRegisterCtr( &ctrResolveScalar, "# resolved by scalar conversion" );
    ExtraRptRegisterCtr( &ctrResolveNaked,  "# resolved by file-scope fun" );
}


static void overloadOperatorFini( // COMPLETION
    INITFINI* defn )            // - definition
{
    unsigned arg;               // - current basic argument

    defn = defn;
    for( arg = 0; arg < MAX_FUN_PROTOS; ++arg ) {
        if( ovfuns[ arg ] != NULL ) {
            FreeSymbol( ovfuns[ arg ] );
        }
    }
    if( CompFlags.extensions_enabled ) {
        for( arg = 0; arg < MAX_FUN_PROTOS_EXTRA; ++arg ) {
            if( ovfuns_extra[ arg ] != NULL ) {
                FreeSymbol( ovfuns_extra[ arg ] );
            }
        }
    }
}


INITDEFN( overload_operator, overloadOperatorInit, overloadOperatorFini )

pch_status PCHWriteOperatorOverloadData( void )
{
    SYMBOL sym;
    unsigned arg;

    for( arg = 0; arg < MAX_FUN_PROTOS; ++arg ) {
        sym = SymbolGetIndex( ovfuns[ arg ] );
        PCHWrite( &sym, sizeof( sym ) );
    }
    for( arg = 0; arg < MAX_FUN_PROTOS_EXTRA; ++arg ) {
        sym = SymbolGetIndex( ovfuns_extra[ arg ] );
        PCHWrite( &sym, sizeof( sym ) );
    }
    return( PCHCB_OK );
}

pch_status PCHReadOperatorOverloadData( void )
{
    SYMBOL sym;
    unsigned arg;

    for( arg = 0; arg < MAX_FUN_PROTOS; ++arg ) {
        PCHRead( &sym, sizeof( sym ) );
        ovfuns[ arg ] = SymbolMapIndex( sym );
    }
    for( arg = 0; arg < MAX_FUN_PROTOS_EXTRA; ++arg ) {
        PCHRead( &sym, sizeof( sym ) );
        ovfuns_extra[ arg ] = SymbolMapIndex( sym );
    }
    return( PCHCB_OK );
}

pch_status PCHInitOperatorOverloadData( boolean writing )
{
    writing = writing;
    return( PCHCB_OK );
}

pch_status PCHFiniOperatorOverloadData( boolean writing )
{
    writing = writing;
    return( PCHCB_OK );
}


#ifndef NDEBUG

#include "dbg.h"
#include <stdio.h>

static void dumpOVOP            // DEBUG -- DUMP OVOP structure
    ( OVOP* ovop                // - OVOP
    , char const *operand )     // - title info
{
    printf( "Operand[%x] (%s)\n"
          , ovop->operand
          , operand );
    printf( "  node_type: " );
    DumpFullType( ovop->node_type );
    printf( "  user_type: " );
    DumpFullType( ovop->user_type );
    printf( "  class_type: " );
    DumpFullType( ovop->class_type );
}

void DumpOpovLoad               // DEBUG -- DUMP ROUTINE
    ( OLINF* oli )              // - overload info
{
    SYMBOL sym;

    DbgPrintPTREE( oli->expr );
    dumpOVOP( &oli->left, "left" );
    dumpOVOP( &oli->right, "right" );
    printf( "\nScalars:" );
    RingIterBeg( oli->scalars, sym ) {
        PrintFullType( sym->sym_type );
    } RingIterEnd( sym );
    printf( "\nSearch results: memb[%x] non-memb[%x]"
            "\nMask[%x] Flags[%x] scalar_overload(%d) repeat_overload(%d)"
            "\nhave_user_type(%d) have_class_type(%d)"
            "\n"
          , oli->result_mem
          , oli->result_nonmem
          , oli->mask
          , oli->flags
          , oli->scalar_overloadable
          , oli->repeat_overload
          , oli->have_class_type
          , oli->have_user_type
          );
}

#endif

⌨️ 快捷键说明

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