convctl.c

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

C
1,487
字号
/****************************************************************************
*
*                            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 "convctl.h"
#include "errdefns.h"
#include "class.h"


static CNV_DIAG diagImpossible  // DIAGNOSIS FOR IMPOSSIBLE CONVERT FAILURE
=   { ERR_CALL_WATCOM
    , ERR_CALL_WATCOM
    , ERR_CALL_WATCOM
    , ERR_CALL_WATCOM
    , ERR_CALL_WATCOM
    };
#if 0
static CNV_DIAG diagMembFunCnv= // diagnosis for member-ptr conversion
{   ERR_MEMB_PTR_FUN_IMPOSSIBLE
,   ERR_MEMB_PTR_FUN_AMBIGUOUS
,   ERR_MEMB_PTR_DERIVED
,   ERR_MEMB_PTR_FUN_PRIVATE
,   ERR_MEMB_PTR_FUN_PROTECTED
};
#endif


PTREE ConvCtlDiagnoseTypes      // DIAGNOSE CASTING TYPES
    ( CONVCTL* ctl )            // - conversion control
{
    ConversionTypesSet( ctl->src.orig, ctl->tgt.orig );
    if( NULL == ctl->src.orig ) {
        ConversionDiagnoseInfTgt();
    } else {
        ConversionDiagnoseInf();
    }
    return ctl->expr;
}


PTREE ConvCtlDiagnose           // DIAGNOSE CASTING ERROR
    ( CONVCTL* ctl )            // - conversion control
{
    PTreeErrorExpr( ctl->expr, ctl->msg_no );
    return ConvCtlDiagnoseTypes( ctl );
}


boolean ConvCtlWarning          // ISSUE WARNING
    ( CONVCTL* ctl              // - conversion control
    , unsigned msg_no )         // - message number
{
    boolean retn;               // - return: TRUE ==> ERROR was issued
    msg_status_t status;        // - message status

    status = PTreeErrorExpr( ctl->expr, msg_no );
    if( MS_PRINTED & status ) {
        if( MS_WARNING & status ) {
            ConvCtlDiagnoseTypes( ctl );
            retn = FALSE;
        } else {
            retn = TRUE;
        }
    } else {
        retn = FALSE;
    }
    return retn;
}


static void diagnoseError       // DIAGNOSE ERROR AND SET UP ERROR OPERAND(S)
    ( CONVCTL* ctl              // - conversion control
    , unsigned msg_no )         // - message #
{
    ctl->msg_no = msg_no;
    ConvCtlDiagnose( ctl );
    ctl->has_err_operand = TRUE;
}


boolean ConvCtlTypeInit         // INITIALIZE CONVTYPE
    ( CONVCTL* ctl              // - conversion control
    , CONVTYPE* ctype           // - control info.
    , TYPE type )               // - type
{
    type_id id;                 // - id for unmodified type
    boolean retn;               // - TRUE ==> is bit_field, array, function
    TYPE cl_type;               // - class type

    ctype->orig = type;
    ctype->unmod = TypeGetActualFlags( type, &ctype->modflags );
    ctype->pted = NULL;
    ctype->class_type = NULL;
    ctype->ptedflags = 0;
    ctype->reference = FALSE;
    ctype->array = FALSE;
    ctype->bit_field = FALSE;
    ctype->class_operand = FALSE;
    ctype->pc_ptr = PC_PTR_NOT;
    id = ctype->unmod->id;
    retn = FALSE;
    cl_type = NULL;
    if( id == TYP_BITFIELD ) {
        ctype->bit_field = TRUE;
        retn = TRUE;
    } else if( id == TYP_ARRAY ) {
        ctype->array = TRUE;
        retn = TRUE;
    } else {
        ctype->kind = RkdForTypeId( id );
        switch( ctype->kind ) {
          case RKD_POINTER :
            if( ctype->unmod->flag & TF1_REFERENCE ) {
                TYPE refed = ctype->unmod->of;
                ctype->reference = TRUE;
                cl_type = StructType( refed );
            }
            break;
          case RKD_FUNCTION :
            retn = TRUE;
            break;
          case RKD_CLASS :
            cl_type = ctype->unmod;
            break;
          case RKD_ERROR :
            ctl->has_err_operand = TRUE;
            break;
        }
    }
    if( NULL != cl_type ) {
        cl_type = StructType( cl_type );
        if( ClassCorrupted( cl_type ) ) {
            cl_type = NULL;
            ctype->kind = RKD_ERROR;
            ctl->has_err_operand = TRUE;
        } else {
            ctype->class_type = cl_type;
            ctype->class_operand = TRUE;
        }
    }
    return retn;
}


void ConvCtlClassAnalysis       // ANALYSE CLASS TYPE
    ( CONVTYPE* ctype )         // - control info.
{
    if( ctype->reference ) {
        ctype->pted = TypeGetActualFlags( ctype->unmod->of
                                        , &ctype->ptedflags );
    } else {
        ctype->ptedflags = ctype->modflags;
        ctype->pted = ctype->unmod;
    }
}


static void errForFunc          // ISSUE ERROR FOR A FUNCTION
    ( PTREE func                // - function node
    , unsigned msg_no           // - message #
    , CONVCTL* ctl )            // - conversion control
{
    PTreeErrorExpr( func, msg_no );
    ctl->has_err_operand = TRUE;
    ctl->tgt.kind = RKD_ERROR;
    PTreeErrorNode( ctl->expr );
}


static TYPE makeRefPtrFunc      // MAKE REFERENCE OR PTR TO FUNCTION
    ( CONVCTL* ctl              // - conversion control
    , TYPE ftype )              // - function type
{
    return ctl->tgt.reference
         ? MakeReferenceTo( ftype )
         : MakePointerTo( ftype );
}


static void setFunType          // SET FUNCTION TYPE
    ( PTREE node                // - node to be set
    , TYPE ftype )              // - function type
{
    node->flags &= ~ PTF_LVALUE;
    NodeSetType( node, ftype, 0 );
}


static void adjustFnAddr        // SET FUNCTION ADDR
    ( CONVCTL* ctl              // - conversion control
    , PTREE addrof              // - '&' node
    , PTREE func )              // - function node
{
    TYPE argument;              // - expression type
    SYMBOL sym;                 // - symbol for function

    sym = func->u.symcg.symbol;
    if( SymIsThisFuncMember( sym ) ) {
        errForFunc( func, ERR_ADDR_NONSTAT_MEMBER_FUNC, ctl );
    } else {
        sym->flag |= SF_ADDR_TAKEN;
        SymMarkRefed( sym );                                // ok?
        argument = makeRefPtrFunc( ctl, func->type );
        setFunType( addrof, argument );
        setFunType( ctl->expr->u.subtree[1], argument );
    }
}

static void adjustFnMembPtr     // SET MEMB-PTR TYPE
    ( CONVCTL* ctl              // - conversion control
    , PTREE func )              // - function node
{
    TYPE argument;              // - expression type
    SYMBOL sym;                 // - symbol
    CNV_RETN retn;              // - conversion return

//  func = NodeActualNonOverloaded( func );
    sym = func->u.symcg.symbol;
    if( SymIsThisFuncMember( sym ) ) {
        sym->flag |= SF_ADDR_TAKEN;
//      SymMarkRefed( sym );
        argument = MakeMemberPointerTo( SymClass( sym ), sym->sym_type );
//      ctl->expr->u.subtree[1]->type = argument;
        retn = MembPtrConvert( &ctl->expr->u.subtree[1]
                             , argument
                             , CNV_EXPR );
        DbgVerify( retn == CNV_OK, "failed memb ptr adjustment" );
    } else {
        errForFunc( func, ERR_MEMB_PTR_ADDR_OF, ctl );
    }
}


static void adjustFnAddrPtr     // ADJUST FOR &FUNCTION --> PTR
    ( CONVCTL* ctl )            // - conversion control
{
    PTREE addrof;               // - '&' node
    PTREE func;                 // - function node ( &class::func )

    addrof = PTreeOp( &ctl->expr->u.subtree[1] );
    switch( NodeAddrOfFun( addrof, &func ) ) {
      case ADDR_FN_ONE_USED :
      case ADDR_FN_ONE :
        func = NodeActualNonOverloaded( func );
        adjustFnAddr( ctl, addrof, func );
        break;
      case ADDR_FN_MANY_USED :
      case ADDR_FN_MANY :
        switch( _CNV_TYPE( ctl->req ) ) {
          case CNV_ASSIGN :
          case CNV_CAST :
          case CNV_INIT :
          case CNV_INIT_COPY :
          case CNV_FUNC_ARG :
          case CNV_FUNC_RET :
            switch( ConvertOvFunNode( ctl->tgt.orig, func ) ) {
              case CNV_OK :
                adjustFnAddr( ctl, addrof, func );
                break;
              case CNV_AMBIGUOUS :
                errForFunc( func, ctl->diag_cast->msg_ambiguous, ctl );
                break;
              case CNV_IMPOSSIBLE :
                errForFunc( func, ctl->diag_cast->msg_impossible, ctl );
                break;
              DbgDefault("ConvertOfFunNode -- unexpected return code");
            }
            break;
          default :
            errForFunc( func, ERR_ADDR_OF_OVERLOADED_FUN, ctl );
            break;
        }
        break;
    }
}

static void adjustFnAddrMembPtr // ADJUST FOR &FUNCTION --> MEMB-PTR
    ( CONVCTL* ctl )            // - conversion control
{
    PTREE addrof;               // - '&' node
    PTREE func;                 // - function node ( &class::func )
    TYPE ftype;                 // - function type
    TYPE mptype;                // - member-ptr type

    addrof = PTreeOp( &ctl->expr->u.subtree[1] );
    switch( NodeAddrOfFun( addrof, &func ) ) {
      case ADDR_FN_ONE_USED :
        if( ! CompFlags.extensions_enabled ) break;
        // drops thru
      case ADDR_FN_ONE :
        func = NodeActualNonOverloaded( func );
        adjustFnMembPtr( ctl, func );
        break;
      case ADDR_FN_MANY_USED :
        if( ! CompFlags.extensions_enabled ) break;
        // drops thru
      case ADDR_FN_MANY :
        switch( _CNV_TYPE( ctl->req ) ) {
          case CNV_ASSIGN :
          case CNV_INIT :
          case CNV_CAST :
          case CNV_FUNC_ARG :
          case CNV_FUNC_RET :
            mptype = ctl->tgt.unmod;
            if( ctl->tgt.reference ) {
                mptype = mptype->of;
            }
            ftype = MemberPtrType( mptype ) -> of;
            switch( ConvertOvFunNode( MakePointerTo( ftype ), func ) ) {
              case CNV_OK :
                adjustFnMembPtr( ctl, func );
                break;
              case CNV_AMBIGUOUS :
                errForFunc( func, ctl->diag_cast->msg_ambiguous, ctl );
                break;
              case CNV_IMPOSSIBLE :
                errForFunc( func, ctl->diag_cast->msg_impossible, ctl );
                break;
              DbgDefault("ConvertOfFuncnode -- unexpected return code");
            }
            break;
          default :
            errForFunc( func, ERR_ADDR_OF_OVERLOADED_FUN, ctl );
            break;
        }
        break;
    }
}


static void checkSrcForError    // CHECK IF SOURCE HAS ERROR
    ( CONVCTL* ctl )            // - control info.
{
    if( PT_ERROR == ctl->expr->op
     || PT_ERROR == ctl->expr->u.subtree[1]->op ) {
        ctl->has_err_operand = TRUE;
        ctl->tgt.kind = RKD_ERROR;
    }
}


static CONVCTL* convCtlInitData // INITIALIZE CONVCTL DATA

⌨️ 快捷键说明

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