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