fnovload.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,907 行 · 第 1/5 页
C
1,907 行
/****************************************************************************
*
* 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 <assert.h>
#include "errdefns.h"
#include "fnovload.h"
#include "cgfront.h"
#include "memmgr.h"
#include "carve.h"
#include "vbuf.h"
#include "ring.h"
#include "fmtsym.h"
#include "toggle.h"
#include "template.h"
#include "initdefs.h"
#include "dbg.h"
#ifndef NDEBUG
#include "pragdefn.h"
#endif
//#define NEW_TRIVIAL_RULE
typedef enum // comparison and resolution results
{ OV_CMP_SAME, // no difference
OV_CMP_BETTER_FIRST, // first argument is better
OV_CMP_BETTER_SECOND, // second argument is better
OV_CMP_UNDEFINED // result is undefined
} OV_RESULT;
typedef struct // FNOV_INFO -- overload information
{
arg_list* alist; // - argument definition
PTREE* plist; // - arguments used
FNOV_LIST** pcandidates; // - hdr: candidates
FNOV_LIST** pmatch; // - hdr: matches
FNOV_LIST* candfunc; // - candidate function
FNOV_CONTROL control; // - control item
FNOV_RESULT result; // - result for candidates
FNOV_DIAG *fnov_diag; // - information used for diagnosis
uint_8 has_template :1; // - TRUE ==> has template candidate
} FNOV_INFO;
#define CACHE_FNOVRANK_SIZE 16
// carve storage for fnov list structures
#define BLOCK_FNOVLIST 16
static carve_t carveFNOVLIST;
#define BLOCK_ManyFNOVRANK 16
static carve_t carveManyFNOVRANK;
// static storage for diagnostic lists
#define LIST_FREE -1
//--------------------------------------------------------------------
// Manage # of candidates
//--------------------------------------------------------------------
static void fnovNumCandidatesSet( FNOV_DIAG *fnov_diag, FNOV_LIST *candidates )
{
if( fnov_diag != NULL ) {
if( fnov_diag->num_candidates == LIST_FREE ) {
fnov_diag->num_candidates = RingCount( candidates );
}
}
}
//--------------------------------------------------------------------
// FNOV_RANK Support
//--------------------------------------------------------------------
static FNOV_RANK *newRank( unsigned n )
{
FNOV_RANK *rank;
if( n > CACHE_FNOVRANK_SIZE ) {
rank = CMemAlloc( sizeof( *rank ) * n );
} else {
rank = CarveAlloc( carveManyFNOVRANK );
}
return( rank );
}
static void deleteRank( FNOV_RANK *rank, unsigned n )
{
if( n > CACHE_FNOVRANK_SIZE ) {
CMemFree( rank );
} else {
CarveFree( carveManyFNOVRANK, rank );
}
}
static void initRankVector( FNOV_CONTROL control, FNOV_RANK *rv, int num_args )
/***************************************************************************/
// initialize vector of rank information
{
int i;
FNOV_RANK *rank;
if( num_args == 0 ) num_args = 1;
rank = rv;
memset( rank, 0, sizeof( *rank ) * num_args );
for( i = num_args ; i > 0 ; i--, rank++ ) {
rank->rank = OV_RANK_INVALID;
rank->control = control;
}
// for member functions, don't check u-d conversion on this ptr
if( control & FNC_MEMBER ) {
rv->control |= FNC_EXCLUDE_UDCONV;
}
// for standard operators which are member functions,
// don't check any conversion on first parm
if( ( control & FNC_STDOPS) && ( control & FNC_MEMBER ) ) {
rv->control |= FNC_EXCLUDE_CONV;
}
}
static void addRankVector( FNOV_LIST *candidate, FNOV_CONTROL control )
/*********************************************************************/
// allocate and initialize vector of rank information
{
FNOV_RANK *rank;
unsigned num_args;
num_args = candidate->num_args;
if( num_args == 0 ) {
num_args = 1;
}
rank = newRank( num_args );
initRankVector( control, rank, num_args );
candidate->rankvector = rank;
}
static boolean hasOneArg( arg_list *arg )
{
if( arg->num_args > 0 &&
(arg->type_list[arg->num_args-1])->id == TYP_DOT_DOT_DOT ) {
return (arg->num_args == 2 || arg->num_args == 1);
// ellipsis args take up space in array, but we want to match
// fns with one real arg plus ellipsis args as having one arg
// also, fns with just ellipsis args can match as having one arg
}
return (arg->num_args == 1);
}
static void udcRankCtor( FNOV_LIST *list, TYPE src, TYPE tgt,
/**********************************************************/
FNOV_UDC_CONTROL control, FNOV_INTRNL_CONTROL ictl, PTREE *src_ptree )
// rank ctors in list, going from src to tgt.
{
FNOV_LIST *curr; // current element in list
arg_list *arg; // arg list to ctor
FNOV_CONTROL fnov_control;
TYPE inter; // intermediate type (src->inter->tgt)
FNOV_CONTROL curr_control; // control for current ctor;
if( ictl & FNOV_INTRNL_ONCE_ONLY ) {
fnov_control = FNC_EXCLUDE_UDCONV;
} else {
if( !IsCopy(control) || // direct or
( ictl & FNOV_INTRNL_DERIVED ) ) { // copy and derived
fnov_control = FNC_DEFAULT; // allow second UDC
} else {
fnov_control = FNC_EXCLUDE_UDCONV;
}
}
RingIterBeg( list, curr ) {
arg = SymFuncArgList( curr->sym );
curr_control = fnov_control;
if( hasOneArg( arg ) &&
( ( control & FNOV_UDC_USE_EXPLICIT ) ||
( curr->sym->sym_type->flag & TF1_EXPLICIT ) == 0 ) ) {
inter = arg->type_list[0];
if( ( ictl & FNOV_INTRNL_EXCLUDE_UDCONV_PARAM ) == 0 &&
IsCopy(control) && CompFlags.extensions_enabled &&
( ictl & FNOV_INTRNL_ONCE_ONLY ) == 0 ) {
TYPE tgt_type;
TYPE inter_type;
tgt_type = ClassTypeForType( tgt );
inter_type = ClassTypeForType(inter);
if( tgt_type != inter_type ) {
// copy case, extensions enabled
// tgt and inter not same
// allow second UDC, but not another
curr_control = FNC_DEFAULT | FNC_RANKING_CTORS;
}
}
if( ictl & FNOV_INTRNL_8_5_3_ANSI ) {
curr_control |= FNC_8_5_3_ANSI;
}
if( ictl & FNOV_INTRNL_STDOP_CV_VOID ) {
curr_control |= FNC_STDOP_CV_VOID;
}
addRankVector( curr, curr_control );
FnovArgRank( src, inter, src_ptree, curr->rankvector );
} else {
addRankVector( curr, curr_control );
curr->rankvector->rank = OV_RANK_NO_MATCH;
}
} RingIterEnd( curr )
}
static FNOV_SCALAR rankCtorReturn(
FNOV_LIST *match,
TYPE tgt,
PTREE *src_ptree )
{
TYPE ret_type;
FNOV_RANK rank;
ret_type = SymFuncReturnType( match->sym );
// ctor type returned above is class &, but the type
// of a ctor is defined to be just the class
ret_type = ClassTypeForType( ret_type );
initRankVector( FNC_EXCLUDE_UDCONV, &rank, 0 );
FnovArgRank( ret_type, tgt, src_ptree, &rank );
return( rank.u.no_ud );
}
static void udcRankUDCF( FNOV_LIST *list, TYPE src, TYPE tgt,
FNOV_INTRNL_CONTROL ictl, PTREE *src_ptree )
/**********************************************************/
// rank UDCFs in list, going from src to tgt.
{
FNOV_LIST *curr; // current element in list
type_flag srcflags;
type_flag tgtflags;
void *unused;
TYPE ret_type;
FNOV_CONTROL control;
TypeModExtract( TypeReferenced( src )
, &srcflags
, &unused
, TC1_NOT_ENUM_CHAR|TC1_NOT_MEM_MODEL );
control = FNC_EXCLUDE_UDCONV;
if( ictl & FNOV_INTRNL_STDOP_CV_VOID ) {
control |= FNC_STDOP_CV_VOID;
}
RingIterBeg( list, curr ) {
addRankVector( curr, control );
ret_type = SymFuncReturnType( curr->sym );
FnovArgRank( ret_type, tgt, src_ptree, curr->rankvector );
if( SymIsThisFuncMember( curr->sym ) ) { // rank src->this
tgtflags = curr->alist->qualifier;
FnovCvFlagsRank( srcflags, tgtflags, &curr->thisrank );
}
} RingIterEnd( curr )
}
//--------------------------------------------------------------------
// FNOV_LIST Support
//--------------------------------------------------------------------
void FnovListFree( FNOV_LIST **plist )
/************************************/
// free memory used by list of overloaded functions
{
FNOV_LIST *ptr;
RingIterBeg( *plist, ptr ) {
if( ptr->rankvector ) {
deleteRank( ptr->rankvector, ptr->num_args );
}
if( ptr->free_args ) {
CMemFree( ptr->alist );
}
} RingIterEnd( ptr )
RingCarveFree( carveFNOVLIST, plist );
}
typedef enum // LENT -- flags for addListEntry
{ LENT_DEFAULT =0x00 // - default: add to candidates
, LENT_MATCH =0x01 // - add to matches
, LENT_TPL_CHECK =0x02 // - check for template candidate
, LENT_FREE_ARGS =0x04 // - mark args to be freed
} LENT;
static void addListEntry( FNOV_CONTROL control, FNOV_INFO *info, SYMBOL sym,
/**************************************************************************/
arg_list *alist, LENT flags )
// add an entry to list of overloaded functions
{
FNOV_LIST *new;
FNOV_LIST **hdr; // - header for list addition
if( flags & LENT_MATCH ) {
hdr = info->pmatch;
} else {
hdr = info->pcandidates;
}
// allocate and initialize the storage
new = RingCarveAlloc( carveFNOVLIST, hdr );
new->sym = sym;
new->alist = alist;
if( control & FNC_RANK_RETURN ) {
new->num_args = 1;
} else {
new->num_args = alist->num_args;
}
if( flags & LENT_FREE_ARGS ) {
new->free_args = TRUE;
} else {
new->free_args = FALSE;
}
new->member = ((control & FNC_MEMBER) != 0 );
new->stdops = ((control & FNC_STDOPS) != 0 );
new->rankvector = NULL;
initRankVector( FNC_DEFAULT, &new->thisrank, 1 );
new->thisrank.rank = OV_RANK_EXACT;
new->flags = TF1_NULL;
if( flags & LENT_TPL_CHECK ) {
if( SymIsFunctionTemplateModel( sym ) ) {
info->has_template = TRUE;
}
}
}
//--------------------------------------------------------------------
// Diagnostic Support
//--------------------------------------------------------------------
void FnovFreeDiag( FNOV_DIAG *fnov_diag )
{
if( fnov_diag != NULL ) {
fnov_diag->num_candidates = LIST_FREE;
FnovListFree( &fnov_diag->diag_ambig );
fnov_diag->diag_ambig = NULL;
FnovListFree( &fnov_diag->diag_reject );
fnov_diag->diag_reject = NULL;
}
}
static void setFnovDiagnosticAmbigList( FNOV_DIAG *fnov_diag, FNOV_LIST **ambig )
/************************************************************************/
{
if( fnov_diag == NULL ) {
FnovListFree( ambig );
} else {
if( fnov_diag->diag_ambig != NULL ) {
FnovListFree( &fnov_diag->diag_ambig );
}
fnov_diag->diag_ambig = *ambig;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?