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