opovload.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,248 行 · 第 1/3 页
C
1,248 行
/****************************************************************************
*
* 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 "errdefns.h"
#include "fnovload.h"
#include "memmgr.h"
#include "name.h"
#include "ring.h"
#include "fold.h"
#include "initdefs.h"
#include "pcheader.h"
#include "stats.h"
#include "class.h"
typedef enum // Used to control scalar operand types
{ GETOP_CONST = 0x01 // - make type const
, GETOP_NOVOID = 0x02 // - don't allow void *
, GETOP_VOLATILE = 0x04 // - make type volatile
, GETOP_DEFAULT = 0x00 // - default behaviour
} GETOP_CONTROL;
#define OPM_NOAMB ( OPM_QUEST | OPM_FUN )
#define OPPRO( code ) __PASTE( OPPRO_NO_, code )
typedef enum
#include "ppopscnv.h"
OP_PROTO_NO;
#undef OPPRO
#define OPPRO( code ) __PASTE( OPM_, code ) = 1 << __PASTE( OPPRO_NO_, code )
typedef enum
#include "ppopscnv.h"
OP_MASK;
#undef OPPRO
#define OPBASIC( arg1, arg2, mask ) NULL
static SYMBOL ovfuns[] =
#include "ppopscnv.h"
;
#undef OPBASIC
#define MAX_FUN_PROTOS ( sizeof(ovfuns) / sizeof(ovfuns[0]) )
#define OPBASIC( arg1, arg2, mask ) mask
static OP_MASK opfun_mask[] =
#include "ppopscnv.h"
;
#undef OPBASIC
#define OPBASIC( arg1, arg2, mask ) { __PASTE( TYP_, arg1 ) , \
__PASTE( TYP_, arg2 ) }
static type_id op_basic_arg[][2] =
#include "ppopscnv.h"
;
#undef OPBASIC
#define OPCNV( code, protos ) protos
static OP_MASK opr_masks[] =
#include "ppopscnv.h"
;
#undef OPCNV
#define MAX_OPR_TYPES ( sizeof( fun_protos ) / sizeof( fun_protos[0] ) )
// If we get an ambiguity between an user-defined operator and a built-in
// operator, for Microsoft compatibility we try again, but this time use
// four void * functions in cv-pairs
// i.e. (void *, void*)
// (const void *, const void*)
// (volatile void *, volatile void*)
// (const volatile void *, const volatile void*)
// but this time check for cv-qualification matches, and rank accordinly
// this appears to be what Microsoft does -- LMW
#define OPBASIC_EXTRA( arg1, arg2, mask, ctl ) NULL
static SYMBOL ovfuns_extra[] =
#include "ppopscnv.h"
;
#undef OPBASIC_EXTRA
#define MAX_FUN_PROTOS_EXTRA ( sizeof(ovfuns_extra) / sizeof(ovfuns_extra[0]) )
#define OPBASIC_EXTRA( arg1, arg2, mask, ctl ) mask
static OP_MASK opfun_mask_extra[] =
#include "ppopscnv.h"
;
#undef OPBASIC_EXTRA
#define OPBASIC_EXTRA( arg1, arg2, mask, ctl ) { __PASTE( TYP_, arg1 ) , \
__PASTE( TYP_, arg2 ) }
static type_id op_basic_arg_extra[][2] =
#include "ppopscnv.h"
;
#undef OPBASIC_EXTRA
#define OPBASIC_EXTRA( arg1, arg2, mask, ctl ) ctl
static GETOP_CONTROL extra_ctl[] =
#include "ppopscnv.h"
;
#define OPM_REF_MASK (OPM_RA|OPM_RI|OPM_RP)
typedef struct { // OVOP -- operand types
PTREE operand; // - operand
TYPE node_type; // - NodeType for node
TYPE user_type; // - NULL, class, enum type
TYPE class_type; // - NULL, class type
} OVOP;
typedef struct { // OLINF -- overload information
PTREE expr; // - expression
OVOP left; // - operand classification: left
OVOP right; // - operand classification: right
SYMBOL scalars; // - scalars list
SEARCH_RESULT *result_mem; // - search result (member)
SEARCH_RESULT *result_nonmem; // - search result (non-member)
SEARCH_RESULT *result_nonmem_namespace; // - search result (non-member)
OP_MASK mask; // - mask for operator
PTO_FLAG flags; // - flags for operand
unsigned scalar_overloadable:1; // - TRUE ==> scalar overloadable
unsigned repeat_overload :1; // - TRUE ==> repeat overloading (->)
unsigned have_class_type :1; // - TRUE ==> have a class operand
unsigned have_user_type :1; // - TRUE ==> have a class,enum operand
} OLINF;
ExtraRptCtr( ctrBoolConv );
ExtraRptCtr( ctrBoolRes );
ExtraRptCtr( ctrOverloads );
ExtraRptCtr( ctrRepeats );
ExtraRptCtr( ctrOverloadOps );
ExtraRptCtr( ctrResolveOps );
ExtraRptCtr( ctrResolveFun );
ExtraRptCtr( ctrResolveNone );
ExtraRptCtr( ctrResolveMember );
ExtraRptCtr( ctrResolveScalar );
ExtraRptCtr( ctrResolveNaked );
static void setupOVOP( // SETUP OVOP
OLINF* olinf, // - overload information
PTREE node, // - node for operand
OVOP* ovop ) // - to be filled in
{
TYPE node_type; // - NodeType for operand
TYPE user_type; // - NULL, class, enum type
TYPE class_type; // - NULL, class type
ovop->operand = node;
class_type = NULL;
if( NULL == node ) {
node_type = NULL;
user_type = NULL;
} else {
node_type = NodeType( node );
user_type = UserDefTypeForType( node_type );
if( user_type != NULL ) {
olinf->have_user_type = TRUE;
if( user_type->id == TYP_CLASS ) {
olinf->have_class_type = TRUE;
class_type = user_type;
}
}
}
ovop->node_type = node_type;
ovop->user_type = user_type;
ovop->class_type = class_type;
}
static boolean initOLINF( // INITIALIZE OVERLOAD INFORMATION
PTREE node, // - overload node
OLINF* olinf ) // - overload information
{
unsigned cnv; // - conversion number for operator
OP_MASK mask; // - conversion mask
boolean scov; // - TRUE ==> needs scalar overload processing
olinf->expr = node;
olinf->flags = PTreeOpFlags( node );
olinf->have_class_type = FALSE;
olinf->have_user_type = FALSE;
setupOVOP( olinf, node->u.subtree[0], &olinf->left );
cnv = ( olinf->flags & PTO_CNV ) >> PTO_CNV_SHIFT;
if( cnv == 0 ) {
mask = 0;
scov = FALSE;
} else {
mask = opr_masks[ cnv - 1 ];
scov = ( mask & OPM_NOAMB ) ? FALSE : TRUE;
}
olinf->mask = mask;
olinf->scalar_overloadable = FALSE;
olinf->repeat_overload = FALSE;
if( scov ) {
olinf->scalar_overloadable = TRUE;
}
return scov || ( olinf->flags & PTO_OVLOAD );
}
static PTREE build_fun_name( // BUILD NAME FOR A FUNCTION
SEARCH_RESULT *result ) // - search result
{
SYMBOL_NAME sym_name;
sym_name = result->sym_name;
return( NodeSymbolNoRef( PTreeId( sym_name->name )
, sym_name->name_syms
, result ) );
}
enum // Used for ":" overloading
{ COLON_OP1 = 0x01 // - use( type1, type1 )
, COLON_OP2 = 0x02 // - use( type2, type2 )
, COLON_NOTSAME2 = 0x04 // - use( type2, type2 ) if type1 != type2
, COLON_NOTREF1 = 0x08 // - use( type2, type2 ) if ref(1) != type2
, COLON_NOTREF2 = 0x10 // - use( type2, type2 ) if type1 ! refd(2)
};
static uint_8 colonTable[3][3]= // Used to determine overloading for ":"
{ COLON_OP1 | COLON_NOTSAME2 // - ( ref : ref )
, COLON_OP1 | COLON_NOTREF1 // - ( ref : class )
, COLON_OP1 // - ( ref : other )
, COLON_OP1 | COLON_NOTREF2 // - ( class : ref )
, COLON_OP1 | COLON_NOTSAME2 // - ( class : class )
, COLON_OP1 // - ( class : other )
, COLON_OP2 // - ( other : ref )
, COLON_OP2 // - ( other : ref )
, 0 // - ( other : other )
};
enum // Used to check for enumeration operands
{ ENUM_IGNORE // - always include
, ENUM_MATCH_1 // - include if oper op(1) matches enum(1)
, ENUM_MATCH_2 // - include if oper op(2) matches enum(2)
, ENUM_MATCH_1_FUN // - include if func op(1) matches enum(1)
, ENUM_MATCH_2_FUN // - include if func op(2) matches enum(2)
, ENUM_MATCH_BOTH // - include if oper op(1,2) matches enum(1,2)
, ENUM_MATCH_MAX // - include if oper op(1,2) matches max.enum.s
};
static unsigned colonIndex( // COMPUTE INDEX FOR COLON OVERLOADING
TYPE type ) // - type of an operand
{
unsigned index; // - 0 == reference, 1 == class, 2 == other
if( TypeReference( type ) ) {
index = 0;
} else if( StructType( type ) ) {
index = 1;
} else {
index = 2;
}
return index;
}
static void colonFun( // SET UP SCALAR FOR COLON OVERLOADING
OLINF* olinf, // - overload information
unsigned curr, // - function index
TYPE type ) // - overloading type
{
SYMBOL fun; // - function in scalar-overload list
arg_list *alist; // - arguments for function
fun = ovfuns[ curr ];
alist = SymFuncArgList( fun );
alist->type_list[0] = type;
alist->type_list[1] = type;
RingAppend( &olinf->scalars, fun );
}
static void overloadColon( // OVERLOAD COLON OPERATOR
OLINF* olinf, // - overload information
unsigned curr ) // - current index
{
TYPE type1; // - NodeType( operand[1] )
TYPE type2; // - NodeType( operand[2] )
uint_8 mask; // - mask for overloading type
type1 = olinf->left.node_type;
type2 = olinf->right.node_type;
mask = colonTable[ colonIndex( type1 ) ][ colonIndex( type2 ) ];
if( mask & COLON_OP1 ) {
colonFun( olinf, curr, type1 );
}
++curr;
if( mask & COLON_OP2 ) {
colonFun( olinf, curr, type2 );
} else if( mask & COLON_NOTSAME2 ) {
if( ! TypesIdentical( type1, type2 ) ) {
colonFun( olinf, curr, type2 );
}
} else if( mask & COLON_NOTREF1 ) {
if( ! TypesIdentical( TypeReferenced( type1 ), type2 ) ) {
colonFun( olinf, curr, type2 );
}
} else if( mask & COLON_NOTREF2 ) {
if( ! TypesIdentical( type1, TypeReferenced( type2 ) ) ) {
colonFun( olinf, curr, type2 );
}
}
}
static void scalarOperators( // FIND SYMBOLS FOR SCALAR OPERATORS
OLINF* olinf ) // - overload information
{
unsigned curr; // - current item
PTREE right; // - NULL or right node if used in overloading
olinf->scalars = NULL;
olinf->result_mem = NULL;
olinf->result_nonmem = NULL;
olinf->result_nonmem_namespace = NULL;
right = NULL;
if( olinf->flags & PTO_BINARY ) {
if( !( olinf->mask & OPM_LT ) ) {
right = olinf->expr->u.subtree[1];
}
}
setupOVOP( olinf, right, &olinf->right );
if( olinf->scalar_overloadable ) {
if( olinf->mask & OPM_RR ) {
if( olinf->have_class_type ) {
for( curr = 0; curr < MAX_FUN_PROTOS; ++ curr ) {
OP_MASK fun_mask;
fun_mask = opfun_mask[ curr ];
if( fun_mask & OPM_RR ) {
overloadColon( olinf, curr );
} else if( olinf->mask & fun_mask ) {
RingAppend( &olinf->scalars, ovfuns[ curr ] );
}
}
}
} else {
if( olinf->have_user_type ) {
boolean complex_assign = ( olinf->mask & OPM_ASSIGN )
&&( olinf->left.class_type != NULL );
if( !complex_assign ||
( complex_assign && (olinf->mask & OPM_REF_MASK ) ) ) {
for( curr = 0; curr < MAX_FUN_PROTOS; ++ curr ) {
OP_MASK fun_mask;
fun_mask = opfun_mask[ curr ];
if( olinf->mask & fun_mask ) {
if( ( olinf->mask & fun_mask ) != OPM_ASSIGN ) {
// not just assign matching
RingAppend( &olinf->scalars, ovfuns[ curr ] );
}
}
}
}
}
}
}
}
static CNV_DIAG diag_transform =// diagnosis for transformation
{ ERR_CALL_WATCOM
, ERR_CALL_WATCOM
, ERR_CALL_WATCOM
, ERR_CALL_WATCOM
, ERR_CALL_WATCOM
};
static CNV_RETN transform_operand(// TRANSFORM AN OPERAND (TO SCALAR)
PTREE *a_operand, // - addr( operand )
TYPE type, // - target type
OP_MASK mask ) // - operator mask
{
TYPE nd_type; // - node type
CNV_RETN cnv_status; // - conversion status
nd_type = (*a_operand)->type;
if( ( NULL != PointerTypeEquivalent( type ) || MemberPtrType( type ) )
&&( 0 == ( mask & OPM_RR ) ) ) {
type = UdcFindType( nd_type, type );
}
if( ( type != NULL ) && ( NULL == EnumType( nd_type ) ) ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?