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