analcall.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,248 行 · 第 1/3 页
C
1,248 行
/****************************************************************************
*
* 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 "memmgr.h"
#include "cgfront.h"
#include "fnovload.h"
#include "calldiag.h"
#include "errdefns.h"
#include "name.h"
#include "defarg.h"
#include "vfun.h"
#include "fnbody.h"
#include "objmodel.h"
static CNV_DIAG diagArgConv = // DIAGNOSIS FOR ARGUMENT CONVERSION
{ ERR_PARM_IMPOSSIBLE
, ERR_PARM_AMBIGUOUS
, ERR_CALL_WATCOM
, ERR_PARM_PRIVATE
, ERR_PARM_PROTECTED
};
static CNV_DIAG diagEllConv = // DIAGNOSIS FOR ELLIPSIS ARGUMENT CONVERSION
{ ERR_ELLIPSIS_IMPOSSIBLE
, ERR_ELLIPSIS_AMBIGUOUS
, ERR_CALL_WATCOM
, ERR_PARM_PRIVATE
, ERR_PARM_PROTECTED
};
static SYMBOL_DIAG diagAccess = // DIAGNOSIS FOR CALLER ACCESS
{ ERR_BARE_FUNCTION_ACCESS
, ERR_EXTRA_THIS_FOR_FUNCTION
, ERR_ENCLOSING_THIS_FUNCTION
};
typedef struct {
CGOP cgop; // operator name
char *name; // name of intrinsic function
} intrinsic_mapping;
static intrinsic_mapping mapIntrinsic[] = {
#include "ppopint.h"
{ CO_NOP, NULL }
};
PTREE NodeGetCallExpr( // POINT AT CALL EXPRESSION
PTREE expr ) // - result from AnalyseCall
{
PTREE call_expr; // - NULL or call expression
if( expr->op == PT_ERROR ) {
call_expr = NULL;
} else {
if( PTreeOpFlags( expr ) & PTO_RVALUE ) {
expr = expr->u.subtree[0];
}
call_expr = expr;
}
return call_expr;
}
static PTREE makeCall( // MAKE A CALL OR INDIRECT CALL
PTREE proc, // - procedure
TYPE type, // - return type
PTREE args, // - arguments
boolean direct_call ) // - TRUE ==> do a direct call
{
PTREE node; // - new node
if( direct_call ) {
node = NodeUnaryCopy( CO_CALL_SETUP, proc );
node = NodeBinary( CO_CALL_EXEC, node, args );
} else {
node = VfunSetupCall( proc );
node = NodeBinary( CO_CALL_EXEC_IND, node, args );
}
return NodeSetType( node, type, PTF_MEANINGFUL | PTF_SIDE_EFF );
}
PTREE NodeMakeCall( // FABRICATE A FUNCTION CALL EXPRESSION
SYMBOL proc, // - procedure
TYPE type, // - return type
PTREE args ) // - arguments
{
DbgVerify( (PointerTypeEquivalent( type ) == NULL)
== (PointerTypeEquivalent( SymFuncReturnType( proc ) ) == NULL)
, "NodeMakeCall -- return type mismatch" );
return makeCall( NodeMakeCallee( proc ), type, args, TRUE );
}
PTREE NodeReverseArgs( // REVERSE CALL ARGUMENTS
unsigned *arg_count, // - # args
PTREE arg ) // - start of arg. list (to be reversed)
{
PTREE last; // - last argument
PTREE right; // - right argument
unsigned count; // - counts arguments
for( last = NULL
, count = 0
; arg != NULL
; ++ count
, right = arg->u.subtree[0]
, arg->u.subtree[0] = last
, last = arg
, arg = right
);
*arg_count = count;
return( last );
}
void NodeBuildArgList( // BUILD ARGUMENT LIST FROM CALLER ARG.S
arg_list *alist, // - argument structure
PTREE *ptlist, // - list of parse tree nodes
PTREE arg, // - arguments
unsigned count ) // - number of arguments
{
TYPE *aptr; // - addr( current TYPE in arg. list )
alist->num_args = count;
aptr = alist->type_list;
for( ; count > 0; --count ) {
*aptr++ = NodeType( arg );
*ptlist++ = arg->u.subtree[1];
arg = arg->u.subtree[0];
}
}
boolean NodeConvertArgument( // CONVERT AN ARGUMENT VALUE
PTREE *a_expr, // - addr( argument value )
TYPE proto ) // - prototype type
{
boolean retn; // - return: TRUE ==> conversion ok
if( NULL != ArrayType( proto ) ) {
proto = PointerTypeForArray( proto );
} else {
// ( const int ) prototype should be ( int ) at this point
proto = TypedefModifierRemoveOnly( proto );
}
*a_expr = CastImplicit( *a_expr, proto, CNV_FUNC_ARG, &diagArgConv );
retn = (*a_expr)->op != PT_ERROR;
return retn;
}
static PTREE arg_fillout( // FILL OUT A CONVERTED ARGUMENT
PTREE arg ) // - the argument
{
PTREE right; // - converted tree
right = arg->u.subtree[1];
arg->type = right->type;
arg->flags = (arg->flags & PTF_ARGS ) | right->flags;
return arg;
}
static PTREE arg_finish( // FINISH A CONVERTED VALUE
PTREE converted, // - converted value
PTREE arg ) // - the argument node
{
arg->u.subtree[1] = converted;
return arg_fillout( arg );
}
static boolean arg_convert( // CONVERT AN ARGUMENT
PTREE arg, // - argument node
TYPE proto ) // - prototype type
{
boolean retn; // - return: TRUE ==> ok
if( NodeConvertArgument( &arg->u.subtree[1], proto ) ) {
arg_fillout( arg );
retn = TRUE;
} else {
PTreeErrorNode( arg );
retn = FALSE;
}
return( retn );
}
static boolean passStructOnStack( // PASS A STRUCT/CLASS ON STACK
PTREE arg, // - argument (CO_LIST)
unsigned warning ) // - internal-data warning
{
PTREE right; // - right operand
TYPE type; // - class type
right = NodeRvalue( arg->u.subtree[1] );
type = right->type;
if( right->flags & PTF_CLASS_RVREF ) {
if( right->op != PT_ERROR ) {
PTREE temp = NodeTemporary( type );
right = ClassDefaultCopyDiag( temp, right, &diagEllConv );
if( right->op != PT_ERROR ) {
right = NodeDtorExpr( right, temp->u.symcg.symbol );
if( right->op != PT_ERROR ) {
right->type = type;
right = NodeFetch( right );
right->flags &= ~PTF_LVALUE;
}
}
}
if( right->op == PT_ERROR ) {
arg->u.subtree[1] = right;
PTreeErrorNode( arg );
return FALSE;
}
}
arg_finish( right, arg );
if( TypeHasSpecialFields( type ) ) {
PTreeWarnExpr( arg, warning );
}
return TRUE;
}
static boolean convertEllipsisArg(// CONVERT AN ELLIPSIS (...) ARGUMENT
PTREE arg ) // - argument
{
boolean retn; // - return: TRUE ==> ok
PTREE right; // - argument
PTREE afun; // - &[ function ]
TYPE type; // - node type
switch( NodeAddrOfFun( PTreeOpRight( arg ), &afun ) ) {
case ADDR_FN_MANY :
case ADDR_FN_MANY_USED :
PTreeErrorExpr( arg->u.subtree[1], ERR_ELLIPSE_ADDR_OVERLOAD );
retn = FALSE;
break;
default :
right = NodeRvalue( arg->u.subtree[1] );
arg->u.subtree[1] = right;
type = TypedefModifierRemove( right->type );
switch( type->id ) {
case TYP_CHAR :
case TYP_SCHAR :
case TYP_UCHAR :
case TYP_SSHORT :
case TYP_WCHAR :
case TYP_USHORT :
type = TypeUnArithResult( type );
right = NodeConvert( type, right );
arg_finish( right, arg );
retn = TRUE;
break;
case TYP_FLOAT :
type = GetBasicType( TYP_DOUBLE );
right = NodeConvert( type, right );
arg_finish( right, arg );
retn = TRUE;
break;
case TYP_ARRAY :
type = PointerTypeForArray( right->type );
right = NodeConvert( type, right );
arg_finish( right, arg );
retn = TRUE;
break;
case TYP_MEMBER_POINTER :
ConvertMembPtrConst( &arg->u.subtree[1] );
arg_fillout( arg );
retn = TRUE;
break;
case TYP_POINTER :
if( NULL == FunctionDeclarationType( type->of ) ) {
type_flag def_flags;
type_flag act_flags;
type_flag arg_flags;
TYPE base_type;
PTREE cnv;
base_type = TypeGetActualFlags( type->of, &arg_flags );
act_flags = arg_flags & TF1_MEM_MODEL;
def_flags = DefaultMemoryFlag( type->of );
if( ( ( def_flags & TF1_FAR )
&&( act_flags != TF1_HUGE )
&&( act_flags != TF1_FAR ) )
||( ( def_flags & TF1_HUGE )
&&( act_flags != TF1_HUGE ) )
) {
type = MakeModifiedType( base_type
, ( arg_flags
& ~TF1_MEM_MODEL )
| def_flags );
type = MakePointerTo( type );
cnv = CastImplicit( arg->u.subtree[1]
, type
, CNV_EXPR
, NULL );
arg->u.subtree[1] = cnv;
DbgVerify( PT_ERROR != cnv->op
, "convertEllipsisArg -- failed ptr.cnv" );
arg_fillout( arg );
retn = TRUE;
} else {
arg_fillout( arg );
retn = TRUE;
}
} else {
arg_fillout( arg );
retn = TRUE;
}
break;
case TYP_CLASS :
retn = passStructOnStack( arg, WARN_ELLIPSIS_CLASS_ARG );
break;
default :
arg_fillout( arg );
retn = TRUE;
break;
}
break;
}
return retn;
}
PTREE NodeConvertCallArgList( // CONVERT CALL ARGUMENT LIST, AS REQ'D
PTREE call_expr, // - call expression (for errors only)
unsigned acount, // - # args, caller
TYPE type, // - function type
PTREE *args ) // - addr( caller argument nodes )
{
PTREE arg; // - caller argument nodes
arg_list *plist; // - prototype arguments
unsigned count; // - # args, processed
unsigned pcount; // - # args, prototype
TYPE *pptr; // - prototype type ptr.
TYPE proto; // - prototype arg. type
boolean extern_c_fun; // - TRUE ==> extern "C" function
TEMP_TYPE old; // - old default class for temp.s
if( call_expr != NULL
&& call_expr->op != PT_ERROR
&& acount > 0 ) {
old = TemporaryClass( TEMP_TYPE_EXPR );
plist = TypeArgList( type );
pptr = plist->type_list;
pcount = plist->num_args;
type = FunctionDeclarationType( type );
if( TypeHasEllipsisArg( type ) ) {
for( count = 1
; count <= acount
; ++count, args = &arg->u.subtree[0] ) {
arg = PTreeOp( args );
if( ! ( count < pcount
? arg_convert( arg, *pptr++ )
: convertEllipsisArg( arg ) ) ) {
PTreeErrorNode( call_expr );
break;
}
}
} else {
if( type->flag & TF1_PLUSPLUS ) {
extern_c_fun = FALSE;
} else {
extern_c_fun = TRUE;
}
for( count = 1
; count <= acount
; ++count, args = &arg->u.subtree[0] ) {
TYPE cl_type;
arg = PTreeOp( args );
proto = *pptr++;
if( ! arg_convert( arg, proto ) ) {
PTreeErrorNode( call_expr );
break;
}
cl_type = StructType( proto );
if( NULL != cl_type ) {
if( extern_c_fun ) {
if( ! passStructOnStack( arg
, WARN_EXTERN_C_CLASS_ARG ) ) {
PTreeErrorNode( call_expr );
break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?