analcast.c

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

C
1,805
字号
        result = diagNonConstRefBinding( ctl );
    }
    return result;
}


static CAST_RESULT findConvRtn   // LOCATE UDC FOR CONVERSION
    ( CONVCTL* ctl               // - conversion control
    , FNOV_UDC_CONTROL control ) // - control type of udc initialization
{
    CAST_RESULT result;         // - cast result
    FNOV_COARSE_RANK rank;      // - UDC RANKING
    boolean is_ctor;            // - TRUE ==> ctor udc, FALSE ==> udcf udc
    FNOV_LIST* fnov_list;       // - matches list

    if( ctl->tgt.class_operand ) {
        ClassAddDefaultCopy( ctl->tgt.class_type->u.c.scope );
    }
    if( ctl->tgt.reference ) {
        rank = UdcLocateRef( control
                           , ctl->src.orig
                           , ctl->tgt.orig
                           , &ctl->expr->u.subtree[1]
                           , &is_ctor
                           , &fnov_list
                           , &ctl->fnov_diag );
        if( rank == OV_RANK_NO_MATCH
         && ! ( ctl->tgt.ptedflags & TF1_CONST )
         && ! ( ( ctl->clscls_explicit || ctl->clscls_static )
             && ctl->src.reference )
         && NULL != ctl->tgt.pted
         && TYP_CLASS == ctl->tgt.pted->id
          ) {
            // later: use the following list for diagnosis or free it later
            // We may wish to save this list for possible later restore in
            //  this case.
            FnovFreeDiag( &ctl->fnov_diag );
            FnovListFree( &fnov_list );
            // Attempt to find conversion to class, so there would be a
            // binding to a non-const reference.
            // It is better to diagnose the error as a binding to a
            // non-const-ref than to report that no conversion was available.
            rank = UdcLocate( FNOV_UDC_DIRECT
                            , ctl->src.orig
                            , ctl->tgt.pted
                            , &ctl->expr->u.subtree[1]
                            , &is_ctor
                            , &fnov_list
                            , &ctl->fnov_diag );
            if( rank == OV_RANK_NO_MATCH ) {
                FnovListFree( &fnov_list );
                FnovFreeDiag( &ctl->fnov_diag );
                rank = UdcLocate( FNOV_UDC_COPY
                                , ctl->src.orig
                                , ctl->tgt.pted
                                , &ctl->expr->u.subtree[1]
                                , &is_ctor
                                , &fnov_list
                                , &ctl->fnov_diag );
            }
            if( rank == OV_RANK_UD_CONV ) {
                result = diagNonConstRefBinding( ctl );
                if( result != CAST_TESTED_OK ) {
                    rank = OV_RANK_NULL; // fake return, better diagnostic
                }
            } else {
                result = CAST_UDC_IMPOSSIBLE;
                rank = OV_RANK_NULL; // fake return, original rank
            }
        }
    } else {
        rank = UdcLocate( control
                        , ctl->src.orig
                        , ctl->tgt.orig
                        , &ctl->expr->u.subtree[1]
                        , &is_ctor
                        , &fnov_list
                        , &ctl->fnov_diag );
        if( rank == OV_RANK_NO_MATCH
         && NULL != ctl->tgt.pted
         && TYP_CLASS == ctl->tgt.pted->id
         && CompFlags.extensions_enabled ) {
            FNOV_UDC_CONTROL ext_ctl;
            // later: use the following list for diagnosis or free it later
            // We may wish to save this list for possible later restore in
            //  this case.
            FnovFreeDiag( &ctl->fnov_diag );
            FnovListFree( &fnov_list );
            if( control == FNOV_UDC_DIRECT ) {
                ext_ctl = FNOV_UDC_COPY;
            } else {
                ext_ctl = FNOV_UDC_DIRECT;
            }
            rank = UdcLocate( ext_ctl
                            , ctl->src.orig
                            , ctl->tgt.orig
                            , &ctl->expr->u.subtree[1]
                            , &is_ctor
                            , &fnov_list
                            , &ctl->fnov_diag );
            if( rank == OV_RANK_UD_CONV
             && is_ctor ) {
                // don't extend to explicit ctor.s
                TYPE ctor_type
                    = FunctionDeclarationType( fnov_list->sym->sym_type );
                if( ctor_type->flag & TF1_EXPLICIT ) {
                    rank = OV_RANK_NULL;
                }
            }
            if( rank == OV_RANK_UD_CONV ) {
                result = diagExtConversion( ctl );
                if( result != CAST_TESTED_OK ) {
                    rank = OV_RANK_NULL; // fake return, better diagnostic
                }
            } else {
                result = CAST_UDC_IMPOSSIBLE;
                rank = OV_RANK_NULL; // fake return, original rank
            }
        }
    }
    switch( rank ) {
      case OV_RANK_UD_CONV :
        ctl->conv_fun = fnov_list->sym;
        ctl->conv_type = SymFuncReturnType( ctl->conv_fun );
        if( is_ctor ) {
            if( NULL == ctl->destination
             && TypeAbstract( ctl->tgt.class_type ) ) {
                result = DIAG_TGT_ABSTRACT;
            } else {
                result = CAST_CTOR;
            }
        } else {
            result = CAST_UDCF;
        }
        // drops thru
      case OV_RANK_NULL :       // fake return
        FnovListFree( &fnov_list );
        FnovFreeDiag( &ctl->fnov_diag );
        break;
      case OV_RANK_UD_CONV_AMBIG :
        result = ctl->clscls_copy_init
                    ? DIAG_UDC_AMBIGUOUS
                    : DIAG_CTOR_AMBIGUOUS;
        break;
      case OV_RANK_NO_MATCH :
        // later: use the following list for diagnosis or free it later
        FnovListFree( &fnov_list );
        FnovFreeDiag( &ctl->fnov_diag );
        result = CAST_UDC_IMPOSSIBLE;
        break;
      DbgDefault( "FindConvRtn -- bad return from overloading" );
    }
    return result;
}


static CAST_RESULT findConvFunc // LOCATE UDC FOR CONVERSION
    ( CONVCTL* ctl )            // - conversion control
{
    FNOV_UDC_CONTROL control;

    control = ctl->clscls_copy_init ? FNOV_UDC_COPY : FNOV_UDC_DIRECT;
    return findConvRtn( ctl, control );
}


static CAST_RESULT findConvCtor // LOCATE CTOR FOR CONVERSION
    ( CONVCTL* ctl )            // - conversion control
{
    CAST_RESULT retn = findConvRtn( ctl, FNOV_UDC_DIRECT );
    if( retn == CAST_UDC_IMPOSSIBLE ) {
        retn = DIAG_CAST_ILLEGAL;
    } else if( retn == CAST_CTOR ) {
        SEARCH_RESULT* result =
            ScopeFindBaseMember( ctl->tgt.class_type->u.c.scope
                               , ctl->conv_fun->name->name );
        if( NULL == result ) {
            retn = DIAG_ALREADY;
        } else {
            ScopeFreeResult( result );
            retn = CAST_CTOR;
        }
    }
    return retn;
}


static CNV_DIAG* getDiagnosis   // GET DIAGNOSIS TO BE USED
    ( CONVCTL* ctl )            // - conversion control
{
    CNV_DIAG* diag;             // - diagnosis to be used

    diag = ctl->diag_cast;
    if( NULL == diag ) {
        diag = ctl->diag_good;
    }
    return diag;
}


static boolean warnTruncTypes   // WARN IF TRUNCATION
    ( CONVCTL* ctl              // - conversion control
    , TYPE src                  // - source type
    , TYPE tgt )                // - target type
{
    boolean retn;               // - return: TRUE ==> no truncation error
    unsigned msg_no;            // - message #

    if( src == tgt ) {
        retn = TRUE;
    } else {
        CNV_RETN trunc;
        if( ctl->clscls_implicit ) {
            trunc = NodeCheckPtrTrunc( src, tgt );
            msg_no = WARN_POINTER_TRUNCATION;
        } else {
            trunc = NodeCheckPtrCastTrunc( src, tgt );
            msg_no = WARN_POINTER_TRUNCATION_CAST;
        }
        if( trunc == CNV_OK ) {
            retn = TRUE;
        } else {
            retn = ! ConvCtlWarning( ctl, msg_no );
        }
    }
    return retn;
}


static CAST_RESULT warnRefTruncation // WARN IF TRUNCATION
    ( CONVCTL* ctl              // - conversion control
    , TYPE src_type )           // - source type
{
    return warnTruncTypes( ctl, ctl->tgt.unmod, src_type )
         ? CAST_TESTED_OK
         : DIAG_ALREADY;
}


static boolean zeroSrc          // TEST IF SOURCE OPERAND IS CONST ZERO
    ( CONVCTL* ctl )            // - conversion control
{
    PTREE expr = PTreeOpRight( ctl->expr );
    return NodeIsZeroConstant( expr );
}


static void setConversionNode   // SET CONVERSION TYPE INTO PTREE NODE
    ( CONVCTL* ctl )            // - conversion control
{
    NodeSetType( ctl->expr, ctl->tgt.orig, PTF_LV_CHECKED );
}


static PTREE doReintMPtrToMPtr  // DO A RE-INTERPRET MEMB-PTR CONVERSION
    ( CONVCTL* ctl )            // - conversion control
{
    unsigned retn;
    retn = MembPtrReint( &ctl->expr->u.subtree[1], ctl->tgt.orig );
    DbgVerify( CNV_OK == retn, "ReintCast -- should work" );
    DbgVerify( ctl->expr->u.subtree[1]->cgop != CO_MEMPTR_CONST, "ReintCast -- mp const" );
    stripOffCastOk( ctl );
    return ctl->expr;
}


// Not for member ptrs
//
static PTREE doCgConversion     // DO A CONVERSION ACCOMPLISHED BY CODEGEN
    ( CONVCTL* ctl )            // - conversion control
{
    TYPE result = NodeType( ctl->expr->u.subtree[1] );

    if( result != ctl->tgt.unmod
     && ! TypesIdentical( TypedefModifierRemoveOnly( result )
                        , ctl->tgt.unmod ) ) {
        ctl->keep_cast = TRUE;
    }
    ctl->expr->cgop = CO_CONVERT;
    markUserCast( ctl );
    setConversionNode( ctl );
    return ctl->expr;
}


static CAST_RESULT staticCvClClOk // TEST IF CONST CASTED AWAY ON STATIC CONV
    ( CONVCTL* ctl )            // - conversion control
{
    CAST_RESULT retn;           // - return: cast result

    if( ctl->clscls_cv
     && ! ctl->diag_bind_ncref ) {
        type_flag src = ctl->src.ptedflags & TF1_CV_MASK;
        type_flag tgt = ctl->tgt.ptedflags & TF1_CV_MASK;
        type_flag both = src & tgt;
        if( src == both ) {
            retn = CAST_TESTED_OK;
        } else {
            if( ctl->clscls_explicit ) {
                ctl->mismatch = src & ~ both;
                ctl->cv_mismatch = TRUE;
                retn = DIAG_CAST_AWAY_CONST;
            } else {
                retn = diagNonConstRefBinding( ctl );
            }
        }
    } else {
        retn = CAST_TESTED_OK;
    }
    return retn;
}


static TYPE getTargetAsReference// GET TARGET TYPE AS A REFERENCE
    ( CONVCTL* ctl )            // - conversion control
{
    return ctl->tgt.reference
         ? ctl->tgt.orig
         : MakeReferenceTo( ctl->tgt.orig );
}


static boolean castToBase       // DO CAST TO LV --> LV BASE
    ( CONVCTL* ctl )            // - conversion control
{
    NodeConvertDerivedToBase( &ctl->expr->u.subtree[1]
                            , getTargetAsReference( ctl )
                            , ctl->src.class_type->u.c.scope
                            , ctl->tgt.class_type->u.c.scope );
    return okSoFar( ctl );
}


static PTREE castLvToLvBase     // CAST LV-DERIVED --> LV-BASE
    ( CONVCTL* ctl )            // - conversion control
{
    if( castToBase( ctl ) ) {
        doCgConversion( ctl );
    }
    return ctl->expr;
}


static PTREE castLvToRvBase     // CAST LV-DERIVED --> RV-BASE
    ( CONVCTL* ctl )            // - conversion control
{
    if( castToBase( ctl )
     && getClassRvalue( ctl ) ) {
        doCgConversion( ctl );
    }
    return ctl->expr;
}


static PTREE castRvToLvBase     // CAST RV-DERIVED --> LV-BASE
    ( CONVCTL* ctl )            // - conversion control
{
    if( getLvalue( ctl, TRUE )
     && castToBase( ctl ) ) {
        doCgConversion( ctl );
    }

⌨️ 快捷键说明

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