analcast.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,805 行 · 第 1/5 页
C
1,805 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "plusplus.h"
#include "cgfront.h"
#include "fold.h"
#include "errdefns.h"
#include "convctl.h"
#include "class.h"
#include "ptrcnv.h"
#include "defarg.h"
#include "objmodel.h"
#include "calldiag.h"
static CNV_DIAG diagExplicit = // DIAGNOSIS FOR EXPLICIT CAST
{ ERR_CAST_ILLEGAL // - impossible
, ERR_CAST_AMBIGUOUS // - ambiguous
, ERR_CONVERT_FROM_VIRTUAL_BASE
, ERR_CAST_PROTECTED // - protected violation
, ERR_CAST_PRIVATE // - private violation
};
#define diagImplicit diagExplicit
#define diagConst diagExplicit
#define diagReint diagExplicit
#define diagStatic diagExplicit
#define diagDynamic diagExplicit
#define dfnCAST_RESULTs \
dfnCAST_RESULT( CAST_ERR_NODE ) /* one or both nodes in error */ \
, dfnCAST_RESULT( CAST_REINT_PTR_TO_ARITH ) /* do reinterpret ptr->ar*/ \
, dfnCAST_RESULT( CAST_REINT_MPTR_TO_MPTR ) /* do reinterpret mp->mp */ \
, dfnCAST_RESULT( CAST_EXPLICIT_MPTR_REINT ) /* do reinterpret mp->mp */ \
, dfnCAST_RESULT( CAST_STATIC_MEMBPTR ) /* static, mptr -> mptr */ \
, dfnCAST_RESULT( CAST_IMPLICIT_MEMBPTR ) /* implicit, mptr -> mptr */ \
, dfnCAST_RESULT( CAST_DO_DYNAMIC ) /* do dynamic cast */ \
, dfnCAST_RESULT( CAST_DO_CGCONV ) /* do codegen cast */ \
, dfnCAST_RESULT( CAST_TO_VOID ) /* do cast to void */ \
, dfnCAST_RESULT( CAST_ARITH_TO_PTR)/* (ptr)arith */ \
, dfnCAST_RESULT( CAST_PTR_TO_PTR) /* (ptr)ptr */ \
, dfnCAST_RESULT( CAST_TO_VOID_PTR )/* (void cv *)ptr */ \
, dfnCAST_RESULT( CAST_TO_BASE ) /* (base ptr)ptr */ \
, dfnCAST_RESULT( CAST_LV_TO_BASE_LV ) /* (lvalue base)(lvalue) */ \
, dfnCAST_RESULT( CAST_RV_TO_BASE_LV ) /* (lvalue base)(rvalue) */ \
, dfnCAST_RESULT( CAST_LV_TO_BASE_RV ) /* (rvalue base)(lvalue) */ \
, dfnCAST_RESULT( CAST_RV_TO_BASE_RV ) /* (rvalue base)(rvalue) */ \
, dfnCAST_RESULT( CAST_TO_DERIVED ) /* (derived ptr)ptr */ \
, dfnCAST_RESULT( CAST_LV_TO_DERIVED_LV ) /* (lvalue derived)(lvalue)*/ \
, dfnCAST_RESULT( CAST_RV_TO_DERIVED_LV ) /* (lvalue derived)(rvalue)*/ \
, dfnCAST_RESULT( CAST_LV_TO_DERIVED_RV ) /* (rvalue derived)(lvalue)*/ \
, dfnCAST_RESULT( CAST_RV_TO_DERIVED_RV ) /* (rvalue derived)(rvalue)*/ \
, dfnCAST_RESULT( CAST_TO_SAME_PTR) /* (T cv *)T cv-2 * */ \
, dfnCAST_RESULT( CAST_CTOR_LV ) /* ctor making lvalue */ \
, dfnCAST_RESULT( CAST_CTOR_RV ) /* ctor making rvalue */ \
, dfnCAST_RESULT( CAST_UDCF_LV ) /* udcf making lvalue */ \
, dfnCAST_RESULT( CAST_UDCF_RV ) /* udcf making rvalue */ \
, dfnCAST_RESULT( CAST_CONVERT_TO_BOOL ) /* convert to bool */ \
, dfnCAST_RESULT( CAST_REPLACE_INTEGRAL) /* replace with integral # */ \
\
/* ERRORS */ \
, dfnCAST_RESULT( DIAG_ALREADY ) /* already diagnosed(must be 1st)*/ \
, dfnCAST_RESULT( DIAG_MESSAGE ) /* message set */ \
, dfnCAST_RESULT( DIAG_CORRUPTED ) /* class corrupted */ \
, dfnCAST_RESULT( DIAG_IMPOSSIBLE ) \
, dfnCAST_RESULT( DIAG_CAST_AWAY_CONST ) \
, dfnCAST_RESULT( DIAG_CAST_ILLEGAL ) \
, dfnCAST_RESULT( DIAG_CAST_PRIVATE ) \
, dfnCAST_RESULT( DIAG_CAST_PROTECTED ) \
, dfnCAST_RESULT( DIAG_CAST_TO_AMBIGUITY ) \
, dfnCAST_RESULT( DIAG_CAST_FROM_AMBIGUITY ) \
, dfnCAST_RESULT( DIAG_CONVERT_FROM_UNDEFD_TYPE ) \
, dfnCAST_RESULT( DIAG_CONVERT_TO_UNDEFD_TYPE ) \
, dfnCAST_RESULT( DIAG_CTOR_IMPOSSIBLE ) \
, dfnCAST_RESULT( DIAG_UNDEFD_CLASS_PTR ) \
, dfnCAST_RESULT( DIAG_CONST_CAST_REF_TYPE ) \
, dfnCAST_RESULT( DIAG_CONST_CAST_PTR_TYPE ) \
, dfnCAST_RESULT( DIAG_CONST_CAST_MPTR_CLASS ) \
, dfnCAST_RESULT( DIAG_CONST_CAST_MPTR_TYPE ) \
, dfnCAST_RESULT( DIAG_CONST_CAST_TYPE ) \
, dfnCAST_RESULT( DIAG_REINT_CAST_REF_TYPE ) \
, dfnCAST_RESULT( DIAG_REINT_CAST_INT_TYPE ) \
, dfnCAST_RESULT( DIAG_REINT_CAST_PTR_TYPE ) \
, dfnCAST_RESULT( DIAG_REINT_CAST_MPTR_TYPE ) \
, dfnCAST_RESULT( DIAG_REINT_CAST_TYPE ) \
, dfnCAST_RESULT( DIAG_REINT_TO_INT_TYPE ) \
, dfnCAST_RESULT( DIAG_STATIC_CAST_REF_TYPE ) \
, dfnCAST_RESULT( DIAG_STATIC_CAST_PTR_TYPE ) \
, dfnCAST_RESULT( DIAG_STATIC_CAST_MPTR_TYPE ) \
, dfnCAST_RESULT( DIAG_STATIC_CAST_TYPE ) \
, dfnCAST_RESULT( DIAG_STATIC_CAST_EXPR ) \
, dfnCAST_RESULT( DIAG_STATIC_CAST_OTHER_TO_ENUM ) \
, dfnCAST_RESULT( DIAG_DYNAMIC_CAST_TYPE ) \
, dfnCAST_RESULT( DIAG_DYNAMIC_CAST_EXPR ) \
, dfnCAST_RESULT( DIAG_DYNAMIC_CAST_NO_VFN_SRC ) \
, dfnCAST_RESULT( DIAG_DYNAMIC_CAST_NO_VFN_TGT ) \
, dfnCAST_RESULT( DIAG_EXPLICIT_CAST_TYPE ) \
, dfnCAST_RESULT( DIAG_BASE_AMBIGUOUS ) \
, dfnCAST_RESULT( DIAG_BASE_PRIVATE ) \
, dfnCAST_RESULT( DIAG_BASE_PROTECTED ) \
, dfnCAST_RESULT( DIAG_CTOR_AMBIGUOUS ) \
, dfnCAST_RESULT( DIAG_DERIVED_AMBIGUOUS ) \
, dfnCAST_RESULT( DIAG_SRC_UNDEFED ) \
, dfnCAST_RESULT( DIAG_TGT_ABSTRACT ) \
, dfnCAST_RESULT( DIAG_TGT_UNDEFED ) \
, dfnCAST_RESULT( DIAG_TO_DERIVED ) \
, dfnCAST_RESULT( DIAG_UDCF_IMPOSSIBLE ) \
, dfnCAST_RESULT( DIAG_UDCF_AMBIGUOUS ) \
, dfnCAST_RESULT( DIAG_VIRTUAL_DERIVED ) \
, dfnCAST_RESULT( DIAG_UDC_AMBIGUOUS ) \
, dfnCAST_RESULT( DIAG_MPTR_NOT_DERIVED ) \
, dfnCAST_RESULT( DIAG_BAD_ENUM_TGT ) \
, dfnCAST_RESULT( DIAG_TGT_VOID_VOLATILE_STAR ) \
, dfnCAST_RESULT( DIAG_TGT_VOID_CONST_STAR ) \
, dfnCAST_RESULT( DIAG_TGT_VOID_STAR ) \
, dfnCAST_RESULT( DIAG_REF_ADDS_BOTH ) \
, dfnCAST_RESULT( DIAG_REF_ADDS_CONST ) \
, dfnCAST_RESULT( DIAG_REF_ADDS_VOLATILE ) \
, dfnCAST_RESULT( DIAG_NOT_CONST_REF ) \
, dfnCAST_RESULT( DIAG_FROM_BASE_PRIVATE ) \
, dfnCAST_RESULT( DIAG_FROM_BASE_PROTECTED ) \
/* */ \
/* following are only used as codes */ \
/* */ \
, dfnCAST_RESULT( CAST_TESTED_OK ) /* TEST SUCCEEDED */ \
, dfnCAST_RESULT( CAST_CTOR ) /* CTOR FOUND */ \
, dfnCAST_RESULT( CAST_UDCF ) /* UDCF FOUND */ \
, dfnCAST_RESULT( CAST_UDC_IMPOSSIBLE ) \
#define dfnCAST_RESULT(a) a
typedef enum
{ dfnCAST_RESULTs
, DIAGNOSIS_START = DIAG_ALREADY // start of diagnosis results
} CAST_RESULT;
#undef dfnCAST_RESULT
static boolean okSoFar // TEST IF STILL OK
( CONVCTL* ctl ) // - conversion control
{
boolean retn; // - return: TRUE ==> is ok so far
PTREE expr; // - current expression
expr = ctl->expr;
if( PT_ERROR == expr->op ) {
retn = FALSE;
} else {
if( PT_ERROR == expr->u.subtree[1]->op ) {
PTreeErrorNode( expr );
retn = FALSE;
} else {
retn = TRUE;
}
}
return retn;
}
static PTREE stripOffCast // STRIP CAST NODES
( CONVCTL* ctl // - conversion control
, boolean ok ) // - true ==> set type from cast node
{
if( ! ctl->keep_cast
&& ( NodeIsBinaryOp( ctl->expr, CO_CONVERT )
|| NodeIsBinaryOp( ctl->expr, CO_CONST_CAST )
|| NodeIsBinaryOp( ctl->expr, CO_STATIC_CAST )
|| NodeIsBinaryOp( ctl->expr, CO_REINTERPRET_CAST )
|| NodeIsBinaryOp( ctl->expr, CO_DYNAMIC_CAST ) ) ) {
PTREE old = ctl->expr;
PTREE right = PTreeCopySrcLocation( old->u.subtree[1], old );
if( ok ) {
ctl->expr = NodeSetType( right
, ctl->tgt.orig
, old->flags & PTF_LVALUE );
} else {
ctl->expr = right;
}
PTreeFree( old->u.subtree[0] );
old->u.subtree[0] = NULL;
PTreeFree( old );
}
return ctl->expr;
}
static PTREE stripOffCastOk // STRIP CAST NODES, WHEN OK
( CONVCTL* ctl ) // - conversion control
{
return stripOffCast( ctl, TRUE );
}
static PTREE stripOffCastOrig // STRIP CAST NODES, WHEN ORIGINAL TO BE LEFT
( CONVCTL* ctl ) // - conversion control
{
return stripOffCast( ctl, FALSE );
}
static void markUserCast // MARK AS USER CAST
( CONVCTL* ctl ) // - conversion control
{
PTREE expr = ctl->expr;
expr->cgop = CO_CONVERT;
expr->flags |= ( ~PTF_NEVER_PROPPED ) & expr->u.subtree[1]->flags;
if( ! ctl->clscls_implicit ) {
expr->u.subtree[0]->cgop = CO_USER_CAST;
}
}
static boolean getClassRvalue // GET RVALUE FOR CLASS EXPRESSION
( CONVCTL* ctl ) // - conversion control
{
PTREE expr = ctl->expr->u.subtree[1];
if( OMR_CLASS_VAL == ObjModelArgument( ctl->tgt.class_type ) ) {
expr = NodeRvalue( expr );
} else {
expr = NodeRvForRefClass( expr );
}
ctl->expr->u.subtree[1] = expr;
return okSoFar( ctl );
}
static boolean getLvalue // GET LVALUE FOR EXPRESSION
( CONVCTL* ctl // - conversion control
, boolean force_to_temp ) // - TRUE ==> force it into a temp
{
PTREE expr = ctl->expr->u.subtree[1];
if( expr->flags & PTF_CLASS_RVREF ) {
expr = NodeLvForRefClass( expr );
} else {
TYPE type = expr->type;
OMR obj_model = ObjModelArgument( type );
switch( obj_model ) {
case OMR_CLASS_VAL :
if( force_to_temp ) {
expr = NodeCopyClassObject( NodeTemporary( type ), expr );
} else {
expr = NodeForceLvalue( expr );
}
break;
case OMR_CLASS_REF :
expr = NodeLvForRefClass( expr );
if( ! force_to_temp ) break;
// drops thru
case OMR_SCALAR :
break;
DbgDefault( "funny OMR" );
}
}
ctl->expr->u.subtree[1] = expr;
return okSoFar( ctl );
}
static CAST_RESULT diagNonConstRefBinding // DIAGNOSE BINDING TO NON-CONST REF
( CONVCTL* ctl ) // - conversion control
{
CAST_RESULT result; // - cast result
if( ctl->diag_bind_ncref ) {
result = CAST_TESTED_OK;
} else {
ctl->diag_bind_ncref = TRUE;
if( SymIsThunk( ScopeFunctionInProgress() ) ) {
result = CAST_TESTED_OK;
} else if( ConvCtlWarning( ctl, ANSI_TEMP_USED_TO_INIT_NONCONST_REF ) ) {
result = DIAG_ALREADY;
} else {
result = CAST_TESTED_OK;
}
}
return result;
}
static CAST_RESULT diagExtConversion // DIAGNOSE EXTENDED CONVERSION
( CONVCTL* ctl ) // - conversion control
{
CAST_RESULT result; // - cast result
if( ctl->diag_ext_conv ) {
result = CAST_TESTED_OK;
} else {
ctl->diag_ext_conv = TRUE;
if( ConvCtlWarning( ctl, ANSI_EXTENDED_CONVERSION_UDC ) ) {
result = DIAG_ALREADY;
} else {
result = CAST_TESTED_OK;
}
}
return result;
}
static CAST_RESULT checkConstRef// CHECK FOR TEMP -> NON-CONST REFERENCE
( CONVCTL* ctl // - conversion control
, CAST_RESULT def_result ) // - default result
{
CAST_RESULT result; // - cast result
if( ! ctl->clscls_cv ) {
result = CAST_TESTED_OK;
} else if( TypeIsConst( ctl->tgt.unmod->of ) ) {
result = CAST_TESTED_OK;
} else {
PTREE expr;
expr = ctl->expr->u.subtree[1];
if( ! ExprIsLvalue( expr )
|| NodeReferencesTemporary( expr ) ) {
result = diagNonConstRefBinding( ctl );
} else {
// always an error if not a temp.
result = def_result;
}
}
return result;
}
static CAST_RESULT reqdConstRef // CHECK FOR TEMP -> NON-CONST REFERENCE
( CONVCTL* ctl ) // - conversion control
{
CAST_RESULT result; // - cast result
if( ctl->diag_bind_ncref
|| TypeIsConst( ctl->tgt.unmod->of ) ) {
result = CAST_TESTED_OK;
} else {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?