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