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