fnovrank.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,635 行 · 第 1/4 页
C
1,635 行
/****************************************************************************
*
* 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 "stats.h"
#include "initdefs.h"
#include "typerank.h"
#include "convctl.h"
typedef struct // FNOV_TYPE -- conversion being classified
{
PTREE *ptnode; // addr( ptr to parse tree node for arguemnt )
TYPE original; // the original type provided
TYPE reftype; // reference type that was skipped
TYPE basic; // basic type (skipping any references)
TYPE final; // final basic type after 'of' from basic type
type_flag leadflag; // any leading flags
type_flag refflag; // any flags after reference removed
type_flag finalflag; // any flags after basic type
void *leadbase; // any leading base
void *refbase; // any base after reference removed
void *finalbase; // any base after basic type
unsigned reference : 1; // was a reference removed?
} FNOV_TYPE;
typedef struct // FNOV_CONV -- control for a conversion
{
FNOV_TYPE wsrc; // - source
FNOV_TYPE wtgt; // - target
FNOV_RANK* rank; // - ranking
} FNOV_CONV;
boolean FnovCvFlagsRank( type_flag src, type_flag tgt, FNOV_RANK *rank )
/**********************************************************************/
{
src &= TF1_CV_MASK;
tgt &= TF1_CV_MASK;
if( src != tgt ) {
// check for allowable conversions
if( src & ~tgt ) {
// not allowed to remove const or volatile
rank->rank = OV_RANK_NO_MATCH;
return TRUE; // <<<--- early return
} else {
// special trivial cases:
// T* -> {const|volatile} T*
// T& -> {const|volatile} T&
rank->rank = OV_RANK_TRIVIAL;
rank->u.no_ud.trivial = 1;
}
}
return FALSE;
}
void FnovMemFlagsRank( type_flag src, type_flag tgt,
void *srcbase, void *tgtbase, FNOV_RANK *rank )
/**************************************************/
{
src &= TF1_MEM_MODEL;
tgt &= TF1_MEM_MODEL;
if( src != tgt ) {
rank->rank = OV_RANK_STD_CONV;
rank->u.no_ud.standard++;
} else if( (src & TF1_BASED) &&
!TypeBasesEqual( src, srcbase, tgtbase ) ) {
rank->rank = OV_RANK_STD_CONV;
rank->u.no_ud.standard++;
}
}
#if 0
static boolean functionsAreIdentical( TYPE fn_type1, TYPE fn_type2 )
/******************************************************************/
{
boolean retn;
retn = TypesSameFnov( fn_type1, fn_type2 );
return( retn );
}
#else
#define functionsAreIdentical( fn_type1, fn_type2 ) \
TypesSameFnov( fn_type1, fn_type2 )
#endif
static RKD initFNOV_TYPE( FNOV_TYPE *ft, TYPE basic, PTREE* pt )
/**************************************************************/
{
ft->original = basic;
ft->ptnode = pt;
ft->final = NULL;
ft->refflag = TF1_NULL;
ft->finalflag = TF1_NULL;
basic = TypeModExtract( basic
, &ft->leadflag
, &ft->leadbase
, TC1_NOT_ENUM_CHAR|TC1_NOT_MEM_MODEL );
if( ( basic->id == TYP_POINTER )
&&( basic->flag & TF1_REFERENCE ) ) {
ft->reference = TRUE;
ft->reftype = basic;
basic = TypeModExtract( basic->of
, &ft->refflag
, &ft->refbase
, TC1_NOT_ENUM_CHAR|TC1_NOT_MEM_MODEL );
} else {
ft->reference = FALSE;
ft->reftype = NULL;
}
basic = PointerTypeForArray( basic );
ft->basic = basic;
return RkdForTypeId( basic->id );
}
static void completeFNOV_TYPE( FNOV_TYPE* ft )
/********************************************/
{
#if 0
TYPE basic = ft->basic;
if( ( basic->id == TYP_POINTER )
||( basic->id == TYP_MEMBER_POINTER ) ) {
ft->final = TypeModExtract( basic->of
, &ft->finalflag
, &ft->finalbase
, TC1_NOT_ENUM_CHAR | TC1_NOT_MEM_MODEL );
}
#else
ft->final = TypeModExtract( ft->basic->of
, &ft->finalflag
, &ft->finalbase
, TC1_NOT_ENUM_CHAR | TC1_NOT_MEM_MODEL );
if( ft->final != NULL ) {
while( ft->final->id == TYP_POINTER ) {
ft->final = TypeModExtract( ft->final->of
, &ft->finalflag
, &ft->finalbase
, TC1_NOT_ENUM_CHAR | TC1_NOT_MEM_MODEL );
}
}
#endif
}
static boolean trivialRankPtrToPtr( FNOV_CONV *conv )
/***************************************************/
// return TRUE if a qualification conversion is needed
// but not possible, otherwise return FALSE
{
CONVCTL info;
TYPE src;
TYPE tgt;
// check for stdop conversion that should ignore cv-qualifiers
if( ( conv->wtgt.final->id == TYP_VOID )
&&( conv->wtgt.final->flag & TF1_STDOP )
&&( ( conv->rank->control & FNC_STDOP_CV_VOID ) == 0 ) ) {
return FALSE;
} else {
// need to look down all levels here
src = conv->wsrc.original;
tgt = conv->wtgt.original;
ConvCtlInitTypes( &info, src, tgt );
ConvCtlTypeDecay( &info, &info.src );
ConvCtlTypeDecay( &info, &info.tgt );
if( !ConvCtlAnalysePoints( &info ) ) {
conv->rank->rank = OV_RANK_NO_MATCH;
return TRUE;
} else if( info.used_cv_convert ) {
conv->rank->rank = OV_RANK_TRIVIAL;
conv->rank->u.no_ud.trivial = 1;
}
return FALSE;
}
}
TYPE *CompareWP13332(
/*******************/
TYPE *first_type
, TYPE *second_type )
{
TYPE *better = NULL;
RKD rkd_src;
RKD rkd_tgt;
FNOV_CONV conv; // - conversion data
rkd_src = initFNOV_TYPE( &conv.wsrc, *first_type, NULL );
rkd_tgt = initFNOV_TYPE( &conv.wtgt, *second_type, NULL );
if( conv.wsrc.reference && conv.wtgt.reference ) {
type_flag first_flag = conv.wsrc.refflag & TF1_CV_MASK;
type_flag second_flag = conv.wtgt.refflag & TF1_CV_MASK;
// two references
// both are references
// first: S cv1 &
// second: S cv1 cv2 &
// first is better
if( ( first_flag & ~second_flag ) == 0 ) { // didn't remove anything
better = first_type;
} else {
// first: S cv1 cv2 & or S cv1 cv2 *
// second: S cv1 & or S cv1 *
// second is better
if( ( second_flag & ~first_flag ) == 0 ) {
better = second_type;
}
}
} else if( !conv.wsrc.reference && !conv.wtgt.reference ) {
if( rkd_src == RKD_POINTER && rkd_tgt == RKD_POINTER ) {
FNOV_RANK rank;
rank.rank = OV_RANK_NO_MATCH;
conv.rank = &rank;
completeFNOV_TYPE( &conv.wsrc );
completeFNOV_TYPE( &conv.wtgt );
trivialRankPtrToPtr( &conv );
if( conv.rank->rank != OV_RANK_NO_MATCH ) {
better = first_type;
} else {
initFNOV_TYPE( &conv.wsrc, *second_type, NULL );
initFNOV_TYPE( &conv.wtgt, *first_type, NULL );
completeFNOV_TYPE( &conv.wsrc );
completeFNOV_TYPE( &conv.wtgt );
trivialRankPtrToPtr( &conv );
if( conv.rank->rank != OV_RANK_NO_MATCH ) {
better = second_type;
}
}
}
}
return( better );
}
static boolean fromConstZero( FNOV_CONV *conv )
/*********************************************/
{
PTREE *pnode;
PTREE node;
pnode = conv->wsrc.ptnode;
if( pnode == NULL ) {
return( FALSE );
}
node = *pnode;
if( node != NULL && NodeIsZeroConstant( node ) ) {
/* we don't want 0's that are cast to pointer types here */
if( IntegralType( conv->wsrc.basic ) ) {
conv->rank->rank = OV_RANK_STD_CONV;
conv->rank->u.no_ud.standard++;
return TRUE;
}
}
return FALSE;
}
static boolean exactRank( FNOV_CONV *conv )
/*****************************************/
// return TRUE if these are identical, otherwise FALSE
{
boolean retn;
// check for non-ranking reference or flag change (for distinctness)
if( ( conv->wsrc.reference == conv->wtgt.reference )
&&( conv->wsrc.leadflag == conv->wtgt.leadflag )
&&( conv->wsrc.refflag == conv->wtgt.refflag )
&&( TypesSameFnov( conv->wsrc.basic, conv->wtgt.basic ) ) ) {
conv->rank->rank = OV_RANK_EXACT;
retn = TRUE;
} else {
retn = FALSE;
}
return( retn );
}
static boolean sameRankPtrToPtr( FNOV_CONV *conv )
/**************************************************************************/
// return TRUE if wsrc must be the same as wtgt to be convertable and
// they are not, otherwise return FALSE
// this routine handles enum->enum and invalid function->function conversions
{
TYPE src_final;
TYPE tgt_final;
tgt_final = conv->wtgt.final;
if( tgt_final->id == TYP_FUNCTION ) {
src_final = conv->wsrc.final;
if( src_final->id == TYP_FUNCTION ) {
if( !functionsAreIdentical( src_final, tgt_final ) ) {
conv->rank->rank = OV_RANK_NO_MATCH;
return TRUE;
}
}
}
return FALSE;
}
static boolean trivialRank( FNOV_CONV *conv )
/*******************************************/
// return TRUE if no standard conversion possible, else FALSE
{
boolean quit;
// check for allowable conversions
// only care if changing reference or pointer
if( conv->wsrc.reference ) {
quit = FnovCvFlagsRank( conv->wsrc.refflag
, conv->wtgt.refflag
, conv->rank );
} else {
quit = FnovCvFlagsRank( conv->wsrc.leadflag
, conv->wtgt.refflag
, conv->rank );
}
return quit;
}
static boolean rankTgtRefCvMem( FNOV_CONV *conv )
/***********************************************/
{
boolean triv; // - TRUE ==> trivial conversion
type_flag first; // - first CV flag
if( conv->wsrc.reference ) {
first = conv->wsrc.refflag;
} else {
first = conv->wsrc.leadflag;
}
triv = FnovCvFlagsRank( first
, conv->wtgt.refflag
, conv->rank );
if( ! triv ) {
if( conv->rank->rank < OV_RANK_NO_MATCH ) {
if( conv->wsrc.reference ) {
FnovMemFlagsRank( conv->wsrc.refflag
, conv->wtgt.refflag
, conv->wsrc.refbase
, conv->wtgt.refbase
, conv->rank );
} else {
FnovMemFlagsRank( conv->wsrc.leadflag
, conv->wtgt.refflag
, conv->wsrc.leadbase
, conv->wtgt.refbase
, conv->rank );
}
}
triv = FALSE;
}
return triv;
}
static boolean functionRank( FNOV_CONV *conv )
/********************************************/
// return TRUE if conversion found or no conversion possible, else FALSE
// this routine handles valid function->function conversions
{
TYPE src_final;
TYPE tgt_final;
tgt_final = conv->wtgt.final;
if( tgt_final->id == TYP_FUNCTION ) {
src_final = conv->wsrc.final;
if( src_final->id == TYP_FUNCTION ) {
if( !functionsAreIdentical( src_final, tgt_final ) ) {
conv->rank->rank = OV_RANK_NO_MATCH;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?