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