convctl.c

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

C
1,487
字号
    ( CONVCTL* ctl              // - control info.
    , PTREE expr                // - expression
    , CNV_REQD request          // - type of conversion
    , CNV_DIAG* diag )          // - diagnosis
{
    ctl->req = request;
    ctl->expr = expr;
    ctl->diag_good = &diagImpossible;
    if( diag == NULL ) {
        diag = &diagImpossible;
    }
    ctl->diag_cast = diag;
    ctl->conv_fun = NULL;
    ctl->conv_type = NULL;
    ctl->destination = NULL;
    ctl->mismatch = 0;
    #define CONVCTL_FLAG( flag ) ctl->flag = FALSE;
    CONVCTL_FLAGS
    #undef CONVCTL_FLAG
    ctl->ctd = 0;
    return ctl;
}


void ConvCtlInitTypes           // INITIALIZE CONVCTL, TYPES
    ( CONVCTL* ctl              // - control info.
    , TYPE src_type             // - source type
    , TYPE tgt_type )           // - target type
{
    ctl = convCtlInitData( ctl, NULL, 0, NULL );
    ConvCtlTypeInit( ctl, &ctl->src, src_type );
    ConvCtlTypeInit( ctl, &ctl->tgt, tgt_type );
}

void ConvCtlTypeDecay           // TYPE DECAY CONVCTL TYPES
    ( CONVCTL *ctl              // - convctl info.
    , CONVTYPE *ctype )         // - type to decay
{
    TYPE ref_type;

    if( ctype->reference ) {
        ref_type = TypeReference( ctype->unmod );
        ConvCtlTypeInit( ctl, ctype, PointerTypeForArray( ref_type ) );
    }
}


void ConvCtlInit                // INITIALIZE CONVCTL
    ( CONVCTL* ctl              // - control info.
    , PTREE expr                // - expression
    , CNV_REQD request          // - type of conversion
    , CNV_DIAG* diag )          // - diagnosis
{
    TYPE src;                   // - source type

    ctl = convCtlInitData( ctl, expr, request, diag );
    if( ConvCtlTypeInit( ctl, &ctl->tgt, expr->u.subtree[0]->type ) ) {
        ctl->src.orig = NULL;
        DbgVerify( 0 == ctl->tgt.bit_field, "unexpected bit field" );
        if( ctl->tgt.array ) {
            diagnoseError( ctl, ERR_CAST_TO_ARRAY );
        } else {
            diagnoseError( ctl, ERR_CAST_TO_FUNCTION );
        }
    } else {
        TYPE ref_type;
        if( ctl->tgt.kind == RKD_POINTER ) {
            TYPE pted = TypedefModifierRemoveOnly( ctl->tgt.unmod->of );
            type_id id = pted->id;
            if( ctl->tgt.reference ) {
                if( TYP_FUNCTION == id ) {
                    adjustFnAddrPtr( ctl );
                    checkSrcForError( ctl );
                } else if( TYP_MEMBER_POINTER == id ) {
                    adjustFnAddrMembPtr( ctl );
                    checkSrcForError( ctl );
                } else if( NodeIsUnaryOp( ctl->expr->u.subtree[1]
                                        , CO_BITFLD_CONVERT ) ) {
                    if( TypeIsConst( ctl->tgt.unmod->of ) ) {
                        ctl->expr->u.subtree[1]
                            = NodeRvalue( ctl->expr->u.subtree[1] );
                    } else {
                        ConversionInfDisable();
                        PTreeErrorExpr( ctl->expr->u.subtree[1]
                                      , ERR_CANT_REFERENCE_A_BIT_FIELD );
                        PTreeErrorNode( ctl->expr );
                        ctl->has_err_operand = TRUE;
                    }
                }
            } else if( TYP_FUNCTION == id ) {
                adjustFnAddrPtr( ctl );
                checkSrcForError( ctl );
            } else if ( TYP_VOID == id ) {
                TYPE pted_src;
                NodeRvalueRight( expr );
                ConvCtlTypeInit( ctl, &ctl->src, expr->u.subtree[1]->type );
                pted_src = TypedefModifierRemoveOnly( ctl->src.unmod->of );
                if( pted_src != NULL && pted_src->id == TYP_FUNCTION ) {
                    adjustFnAddrPtr( ctl );
                    checkSrcForError( ctl );
                }
            }
        } else if( ctl->tgt.kind == RKD_MEMBPTR ) {
            adjustFnAddrMembPtr( ctl );
            checkSrcForError( ctl );
        }
        if( ! ctl->has_err_operand ) for( ; ; ) {
            src = NodeType( expr->u.subtree[1] );
            ConvCtlTypeInit( ctl, &ctl->src, src );
            if( ctl->tgt.class_operand ) break;
            if( ctl->src.class_operand ) break;
            if( ctl->has_err_operand ) break;
            if( ctl->tgt.reference ) {
                if( ctl->src.reference ) break;
                // lvalue <- rvalue (must be const ref)
                ref_type = TypeReference( ctl->tgt.unmod );
                if( TypeIsConst( ref_type ) ) {
                    PTREE exp;
                    exp = NodeAssignTemporary( ref_type
                                             , ctl->expr->u.subtree[1] );
                    ctl->expr->u.subtree[1] = exp;
                } else {
                    diagnoseError( ctl, ERR_TEMP_AS_NONCONST_REF );
                    break;
                }
            } else {
                if( ! ctl->src.reference ) break;
                ref_type = TypeReference( ctl->src.unmod );
                if( FunctionDeclarationType( ref_type ) ) {
                    ctl->expr->u.subtree[1]->type = MakePointerTo( ref_type );
                    ctl->expr->u.subtree[1]->flags &= ~PTF_LVALUE;
                } else {
                    expr->u.subtree[1] = NodeRvalue( expr->u.subtree[1] );
                    src = expr->u.subtree[1]->type;
                }
            }
        }
        if( ctl->has_err_operand ) {
            // do nothing
        } else if( ctl->tgt.class_operand ) {
            ConvCtlClassAnalysis( &ctl->tgt );
            if( ctl->src.class_operand ) {
                ConvCtlClassAnalysis( &ctl->src );
                ctl->ctd = TypeCommonDerivation( ctl->src.class_type
                                               , ctl->tgt.class_type );
                ctl->rough = CRUFF_CL_TO_CL;
            } else {
                ctl->rough = CRUFF_SC_TO_CL;
            }
        } else {
            if( ctl->src.class_operand ) {
                ConvCtlClassAnalysis( &ctl->src );
                ctl->rough = CRUFF_CL_TO_SC;
            } else {
                ctl->rough = CRUFF_NO_CL;
            }
        }
    }
    if( ctl->has_err_operand ) {
        ctl->rough = CRUFF_NO_CL;
        ctl->src.kind = RKD_ERROR;
        ctl->tgt.kind = RKD_ERROR;
    }
}


void ConvCtlInitCast            // INITIALIZE CONVCTL FOR CAST EXPRESSION
    ( CONVCTL* ctl              // - control info.
    , PTREE expr                // - expression
    , CNV_DIAG* diag )          // - diagnosis
{
    ConvCtlInit( ctl, expr, CNV_CAST, diag );
}


// Note: This handles analysis of chains of references, pointers, and
//       member pointers. It is assumed that the unmodified starts are both
//       of the same type above.
//

#define TF1_EXT_ATTR (TF1_BASED | TF1_MEM_MODEL)
#define TF1_EXT_CV   (TF1_CV_MASK | TF1_UNALIGNED)
typedef struct {                // TYPE_FLAG -- various type flags
    TYPE type;                  // - ptr to ... being operated upon
    void* baser;                // - baser, when based object
    type_id id;                 // - id of current type
    type_flag object;           // - for object (default memory model added)
    type_flag cv;               // - CV + UNALIGNED
    type_flag ext;              // - based, memory model
} TYPE_FLAGS;


static void moveAhead           // MOVES TYPE_FLAGS AHEAD ONE LEVEL
    ( TYPE_FLAGS* tf )          // - the entry
{
    TYPE orig;                  // - original type

    orig = tf->type->of;
    tf->type = TypeModExtract( orig
                             , &tf->object
                             , &tf->baser
                             , TC1_NOT_MEM_MODEL | TC1_NOT_ENUM_CHAR );
    tf->id  = tf->type->id;
    tf->cv  = TF1_EXT_CV   & tf->object;
    tf->ext = TF1_EXT_ATTR & tf->object;
}


boolean ConvCtlAnalysePoints    // ANALYSE CONVERSION INFORMATION FOR POINTS
    ( CONVCTL* info )           // - pointer-conversion information
{
    boolean retn;               // - return: TRUE ==> can convert trivially
    boolean first_level;        // - TRUE ==> at first level
    boolean const_always;       // - TRUE ==> const on all preceding levels
    boolean cv_ok;              // - TRUE ==> no CV mismatch
    TYPE_FLAGS src;             // - source typing info
    TYPE_FLAGS tgt;             // - target typing info
    CTD mp_ctd;                 // - host derivation for member-ptr

    src.type = info->src.unmod;
    tgt.type = info->tgt.unmod;
    mp_ctd = CTD_LEFT;
    if( TYP_MEMBER_POINTER == src.type->id ) {
        if( src.type->u.mp.host != tgt.type->u.mp.host ) {
            mp_ctd = TypeCommonDerivation( tgt.type->u.mp.host
                                         , src.type->u.mp.host );
            if( CTD_NO == mp_ctd ) {
                info->bad_mptr_class = TRUE;
            }
            info->diff_mptr_class = TRUE;
        }
    }
    first_level = TRUE;
    const_always = TRUE;
    cv_ok = TRUE;
    for( ; ; ) {
        moveAhead( &src );
        moveAhead( &tgt );
        if( cv_ok ) {
            if( first_level ) {
                src.ext = 0;
                tgt.ext = 0;
                info->cv_err_0 = cv_ok;
                info->src.pted = src.type;
                info->tgt.pted = tgt.type;
                info->src.ptedflags = src.object;
                info->tgt.ptedflags = tgt.object;
                info->tgt.pc_ptr = TypePcPtr( tgt.object );
                info->src.pc_ptr = TypePcPtr( src.object );
                if( NULL != tgt.type ) {
                    if( tgt.id == TYP_VOID ) {
                        info->to_void = TRUE;
                        if( src.id == TYP_VOID ) {
                            info->from_void = TRUE;
                        }
                        info->dynamic_cast_ok = TRUE;
                    } else if( src.type != NULL ) {
                        if( TYP_CLASS == src.id ) {
                            if( TYP_CLASS == tgt.id ) {
                                info->ctd = TypeCommonDerivation( src.type
                                                                , tgt.type );
                                switch( info->ctd ) {
                                  case CTD_NO :
                                    break;
                                  case CTD_LEFT :
                                    if( tgt.type == src.type ) break;
                                  case CTD_LEFT_VIRTUAL :
                                    info->to_base = TRUE;
                                    break;
                                  case CTD_LEFT_PRIVATE :
                                    info->to_private = TRUE;
                                    info->to_base = TRUE;
                                    break;
                                  case CTD_LEFT_PROTECTED :
                                    info->to_protected = TRUE;
                                    info->to_base = TRUE;
                                    break;
                                  case CTD_LEFT_AMBIGUOUS :
                                    info->to_ambiguous = TRUE;
                                    info->to_base = TRUE;
                                    break;
                                  case CTD_RIGHT_AMBIGUOUS :
                                    info->to_ambiguous = TRUE;
                                  case CTD_RIGHT :
                                  case CTD_RIGHT_VIRTUAL :
                                  case CTD_RIGHT_PRIVATE :
                                  case CTD_RIGHT_PROTECTED :
                                    info->to_derived = TRUE;
                                    break;
                                }
                                info->dynamic_cast_ok = TRUE;
                            }
                        } else if( src.id != tgt.id
                                && IntegralType( tgt.type )
                                && IntegralType( src.type )
                                && tgt.id != TYP_ENUM
                                && src.id != TYP_ENUM
                                && CgMemorySize( src.type )
                                   == CgMemorySize( tgt.type ) ) {
                            info->ptr_integral_ext = TRUE;
                        } else if( src.id == TYP_VOID ) {
                            if( CgTypeSize( info->tgt.unmod ) <=
                                CgTypeSize( info->src.unmod ) ) {
                                // this is stupid, but p* --> void* iff
                                // sizeof( void*) >= sizeof( p )
                                info->from_void = TRUE;
                            }
                        }
                    }
                }
                first_level = FALSE;
            }
            if( cv_ok ) {
                type_flag both;
                if( info->to_void ) {
                    src.cv &= ~ TF1_UNALIGNED;
                }
                both = tgt.cv & src.cv;
                cv_ok = ( src.cv == both );// test cv-mismatch
                if( cv_ok ) {
                    if( tgt.cv != src.cv ) {
                        info->used_cv_convert = TRUE;
                        cv_ok = const_always;
                    }
                } else {
                    info->mismatch = src.cv & ~both;
                }
            }
            if( const_always
             && ! ( tgt.cv & TF1_CONST ) ) {
                const_always = FALSE;
            }
        }
        if( src.type == tgt.type ) {
            if( src.ext == tgt.ext ) {
                if( TYP_FUNCTION != src.id
                 || ( (TF1_MEM_MODEL & src.object)
                    ==(TF1_MEM_MODEL & tgt.object) )
                  ) {
                    retn = TRUE;
                    break;
                }
            }
            info->reint_cast_ok = cv_ok;
            retn = FALSE;
            break;
        } else if( src.id != tgt.id ) {
            if( info->to_void
             || info->from_void
             || info->ptr_integral_ext ) {
                retn = TRUE;
                break;
            }
            if( TYP_FUNCTION != src.id
             && TYP_FUNCTION != tgt.id ) {
                info->reint_cast_ok = cv_ok;
            }
            retn = FALSE;
            break;
        } else if( src.ext != tgt.ext ) {
            info->reint_cast_ok = cv_ok;
            retn = FALSE;
            break;
        }
        if( TYP_FUNCTION == src.id
         || TYP_ENUM     == src.id ) {
            info->reint_cast_ok = cv_ok;
            retn = ( src.ext == tgt.ext )
                && TypeCompareExclude( src.type
                                     , tgt.type
                                     , TC1_FUN_LINKAGE | TC1_NOT_ENUM_CHAR );
            break;

⌨️ 快捷键说明

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