analpcnv.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 792 行 · 第 1/2 页

C
792
字号
/****************************************************************************
*
*                            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 "fold.h"
#include "errdefns.h"
#include "ptrcnv.h"

enum                            // DEFINE CONVERSION TO BE DONE
{   CNV_DER_BASE                // - derived -> non-virtual base
,   CNV_DER_VIRT                // - derived -> virtual base
,   CNV_BASE_DER                // - non-virtual base -> derived
,   CNV_ERR_NO_DERIVATION       // - error: no derivation exists
,   CNV_ERR_VIRT_DER            // - error: virtual base -> derived
,   CNV_ERR_AMBIGUOUS           // - error: derivation is ambiguous
,   CNV_ERR_PRIVATE             // - error: derivation is thru a private base
,   CNV_ERR_PROTECTED           // - error: derivation is thru a protected base
};


static TYPE type_pointed_to(    // GET BASE TYPE POINTED TO
    TYPE type )                 // - the type
{
    type_flag not_used;         // - not used

    return TypePointedAt( type, &not_used );
}


static boolean same_ptr_types(  // TEST FOR EQUIVALENT POINTER TYPES
    TYPE t1,                    // - type [1]
    TYPE t2 )                   // - type [2]
{
    return TypeCompareExclude( type_pointed_to( t1 )
                             , type_pointed_to( t2 )
                             , TC1_FUN_LINKAGE );
}


static boolean ptr_to_void(     // TEST IF PTR TYPE IS POINTER TO VOID
    TYPE type )                 // - the type
{
    return type_pointed_to( type )->id == TYP_VOID;
}


static PTREE adjust_base_ptr(   // ADJUST BASE PTR AS TRUE/TESTING CONVERSION
    PTREE orig,                 // - original node
    PTREE offset,               // - offset calculation
    TYPE type )                 // - type, after conversion
{
    if( orig->flags & PTF_PTR_NONZERO ) {
        orig = NodeBinary( CO_DOT, orig, offset );
    } else {
        orig = NodeBinary( CO_PTR_DELTA, orig, offset );
    }
    orig->type = type;
    return orig;
}

PTREE NodeConvertVirtualPtr(    // EXECUTE A VIRTUAL BASE CAST
    PTREE expr,                 // - expr to cast
    TYPE final_type,            // - final type after cast
    target_offset_t vb_offset,  // - offset of vbptr
    target_offset_t vb_index )  // - index in vbtable
{
    PTREE offset;
    TYPE vbptr_type;
    TYPE adjust_type;
    PTREE dup;

    vbptr_type = MakeVBTableFieldType( TRUE );
    offset = NodeOffset( vb_offset );
    expr = NodeBinary( CO_DOT, expr, offset );
    expr->flags |= PTF_LVALUE | PTF_PTR_NONZERO;
    expr->type = vbptr_type;
    dup = NodeDupExpr( &expr );
    expr->flags |= PTF_LVALUE | PTF_PTR_NONZERO;
    expr = NodeFetch( expr );
    expr->type = vbptr_type;
    expr->flags &= ~ PTF_LVALUE;
    expr->flags |= PTF_PTR_NONZERO;
    adjust_type = TypePointedAtModified( vbptr_type );
    offset = NodeOffset( vb_index * CgMemorySize( adjust_type ) );
    expr = NodeBinary( CO_DOT, expr, offset );
    expr->type = adjust_type;
    expr->flags |= PTF_LVALUE | PTF_PTR_NONZERO;
    expr = NodeFetch( expr );
    expr->type = adjust_type;
    expr->flags |= PTF_PTR_NONZERO;
    expr = NodeBinary( CO_DOT, dup, expr );
    expr->type = final_type;
    expr->flags |= PTF_LVALUE | PTF_PTR_NONZERO;
    return expr;
}


static void adjust_by_delta(    // COMPUTE DELTA ADJUSTMENT
    PTREE *a_expr,              // - addr( ptr to be converted )
    TYPE base,                  // - base type
    unsigned delta,             // - adjustment
    boolean positive )          // - TRUE ==> use positive value
{
    PTREE offset;               // - node containing delta

    if( delta == 0 ) {
        *a_expr = NodeConvert( base, *a_expr );
    } else {
        offset = NodeOffset( delta );
        if( ! positive ) {
            offset->u.int_constant = - delta;
        }
        *a_expr = adjust_base_ptr( *a_expr, offset, base );
    }
}


void NodeConvertToBasePtr(      // CONVERT TO A BASE PTR, USING SEARCH_RESULT
    PTREE *a_expr,              // - addr( ptr to be converted )
    TYPE base,                  // - base type
    SEARCH_RESULT *result,      // - search result
    boolean positive )          // - TRUE ==> use positive value
{
    target_offset_t vb_offset;  // - offset of vbptr
    target_offset_t vb_index;   // - index in vbtable
    target_offset_t delta;      // - delta for class
    PTREE node;                 // - new node
    PTREE dup;                  // - node containing duplicate of original
    PTREE orig;                 // - original value
    TYPE ref_type;              // - reference type for original value

    node = *a_expr;
    /* references can never be NULL by definition */
    ref_type = TypeReference( NodeType( node ) );
    if( ref_type != NULL ) {
        node->flags |= PTF_PTR_NONZERO;
    }
    if( node->flags & PTF_MEMORY_EXACT ) {
        adjust_by_delta( a_expr, base, result->exact_delta, positive );
    } else if( result->non_virtual ) {
        adjust_by_delta( a_expr, base, result->delta, positive );
    } else {
        PTO_FLAG orig_prop;     // - flags propogated from original
        SYMBOL ibp;             // - inline bound reference parameter
        target_offset_t offset; // - offset to ibp
#if 0
        orig_prop = ( node->flags & PTF_FETCH ) | PTF_LVALUE;
#else
        orig_prop = node->flags & PTF_FETCH;
        if( NULL != ref_type ) {
            orig_prop |= PTF_LVALUE;
        }
#endif
        if( NodeGetIbpSymbol( node, &ibp, &offset ) ) {
            PTREE expr;         // - expression under construction
            unsigned vb_exact;  // - exact offset for conversion
            vb_exact = result->exact_delta;
            if( ! positive ) {
                vb_exact = - vb_exact;
            }
            vb_exact += offset;
            if( NULL == ibp ) {
                expr = NULL;
            } else {
                expr = NodeMakeCallee( ibp );
                expr->cgop = CO_IGNORE;
            }
            expr = NodeUnary( CO_VBASE_FETCH, expr );
            expr = PtdVbaseFetch( expr
                                , result->vb_offset
                                , result->vb_index
                                , result->delta + offset
                                , vb_exact );
            expr->type = base;
            expr->flags = orig_prop;
            node = NodeReplace( node, expr );
        } else {
            dup = NULL;
            if( ! NodePtrNonZero( node ) ) {
                dup = NodeDupExpr( &node );
            }
            vb_offset = result->vb_offset;
            vb_index = result->vb_index;
            node = NodeConvertVirtualPtr( node, base, vb_offset, vb_index );
            delta = result->delta;
            if( delta != 0 ) {
                node = NodeBinary( CO_DOT, node, NodeOffset( delta ) );
                node->type = base;
                node->flags |= orig_prop;
            }
            if( dup != NULL ) {
                orig = NodeDupExpr( &dup );
                node = NodeTestExpr( NodeCompareToZero( orig ), node, dup );
            }
        }
        *a_expr = node;
    }
    if( ref_type != NULL ) {
        (*a_expr)->flags |= PTF_LVALUE;
    }
}



static TYPE convert_base_ptr(   // CONVERT TO A BASE-CLASS POINTER
    PTREE *expr,                // - addr( ptr to be converted )
    TYPE base,                  // - base type
    SCOPE derived_scope,        // - derived scope
    SCOPE base_scope,           // - base scope
    boolean positive )          // - TRUE ==> use positive value
{
    SEARCH_RESULT *result;

    result = ScopeBaseResult( derived_scope, base_scope );
    NodeConvertToBasePtr( expr, base, result, positive );
    ScopeFreeResult( result );
    return base;
}


TYPE NodeConvertDerivedToBase(  // CONVERT DERIVED PTR TO NONVIRTUAL BASE PTR
    PTREE *expr,                // - addr( ptr to be converted )
    TYPE tgt,                   // - derived type
    SCOPE derived_scope,        // - derived scope
    SCOPE base_scope )          // - base scope
{
    return convert_base_ptr( expr, tgt, derived_scope, base_scope, TRUE );
}


static TYPE NodeConvertDerivedToVirt(  // CONVERT DERIVED PTR TO VIRTUAL BASE PTR
    PTREE *expr,                // - addr( ptr to be converted )
    TYPE tgt,                   // - derived type
    SCOPE derived_scope,        // - derived scope
    SCOPE base_scope )          // - base scope
{
    return convert_base_ptr( expr, tgt, derived_scope, base_scope, TRUE );
}


TYPE NodeConvertBaseToDerived(  // CONVERT BASE PTR TO DERIVED PTR
    PTREE *expr,                // - addr( ptr to be converted )
    TYPE tgt,                   // - derived type
    SCOPE derived_scope,        // - derived scope
    SCOPE base_scope )          // - base scope
{
    return convert_base_ptr( expr, tgt, derived_scope, base_scope, FALSE );
}


void NodeWarnPtrTrunc(          // WARN FOR POINTER/REFERENCE TRUNCATION
    PTREE node )                // - node for warning
{
    PTreeWarnExpr( node, WARN_POINTER_TRUNCATION );
}


void NodeWarnPtrTruncCast(      // WARN FOR CAST POINTER/REFERENCE TRUNCATION
    PTREE node )                // - node for warning
{
    PTreeWarnExpr( node, WARN_POINTER_TRUNCATION_CAST );
}


CNV_RETN NodeCheckPtrTrunc(     // CHECK FOR POINTER TRUNCATION WARNING
    TYPE tgt,                   // - target type
    TYPE src )                  // - source type
{
    return CgTypeTruncation( tgt, src );
}


CNV_RETN NodeCheckPtrCastTrunc( // CHECK FOR CAST POINTER TRUNCATION WARNING
    TYPE tgt,                   // - target type
    TYPE src )                  // - source type
{
    CNV_RETN retn;              // - return: CNV_OK, CNV_OK_TRUNC_CAST

    retn = CgTypeTruncation( tgt, src );
    if( retn == CNV_OK_TRUNC ) {
        retn = CNV_OK_TRUNC_CAST;
    }
    return retn;
}


static SCOPE scope_for_ptr(     // GET SCOPE FOR CLASS POINTED AT
    TYPE type )                 // - pointer type
{
    return TypeScope( type_pointed_to( type ) );
}


static CNV_RETN check_result(   // CHECK RESULT OF A CONVERSION
    PTREE *expr,                // - addr( resultant tree )
    TYPE src,                   // - source type
    TYPE tgt )                  // - target type
{
    CNV_RETN retn;              // - return: CNV_ERR or CNV_OK
    PTREE node;                 // - resultant tree

    node = *expr;
    if( node->op == PT_ERROR ) {
        retn = CNV_ERR;
    } else {
        node->type = tgt;
        NodeSetReference( tgt, node );
        retn = NodeCheckPtrTrunc( tgt, src );
    }
    return retn;
}


static CNV_RETN check_result_cv(// CHECK RESULT FOR CONST/VOLATILE RETURN
    PTREE *expr,                // - addr( resultant tree )
    TYPE src,                   // - source type
    TYPE tgt,                   // - target type
    unsigned conversion )       // - type of conversion
{
    CNV_RETN retn;              // - return: CNV_ERR or CNV_OK

    if( conversion & CNVPTR_NO_TRUNC ) {
        retn = CNV_OK;
    } else {
        retn = check_result( expr, src, tgt );
    }
    if( conversion & CNVPTR_CONST_VOLATILE ) {
        switch( retn ) {
          case CNV_OK :
            retn = CNV_OK_CV;
            break;
          case CNV_OK_TRUNC :
            if( conversion & CNVPTR_CAST ) {
                retn = CNV_OK_TRUNC_CAST_CV;
            } else {
                retn = CNV_OK_TRUNC_CV;
            }
            break;
        }
    }
    return retn;
}


static CNV_RETN emitConvMsg(    // EMIT A CONVERSION MESSAGE
    PTREE expr,                 // - expression for error
    TYPE src,                   // - source type
    TYPE tgt,                   // - target type
    unsigned msg )              // - message code
{
    ConversionTypesSet( src, tgt );
    PTreeErrorExpr( expr, msg );
    return CNV_ERR;
}


CNV_RETN NodeCheckCnvPtrVoid(   // CHECK CONVERSION TO 'VOID*'
    PTREE *a_expr,              // - addr( resultant tree )
    TYPE src,                   // - source type
    TYPE tgt )                  // - target type
{
    CNV_RETN retn;              // - return: CNV_ERR or CNV_OK
    type_flag src_flags;        // - source modifier flags
    type_flag tgt_flags;        // - target modifier flags
    TYPE type;                  // - type pointed at by src
    PTREE expr;                 // - expression

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?