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