Example #1
0
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 ) {
        arg->type = BindTemplateClass( arg->type, &arg->locn, TRUE );
        if( ( arg->flags & PTF_LVALUE )
         && NodeReferencesTemporary( arg->u.subtree[1] ) ) {
            // temporaries may only be bound to const references
            if( NULL == TypeReference( arg->type ) ) {
                arg->type = MakeConstReferenceTo( arg->type );
            }
            *aptr = arg->type;
            aptr++;
        } else {
            *aptr++ = NodeType( arg );
        }
        arg->u.subtree[1]->type = BindTemplateClass( arg->u.subtree[1]->type,
                                                     &arg->u.subtree[1]->locn,
                                                     TRUE );
        *ptlist++ = arg->u.subtree[1];
        arg = arg->u.subtree[0];
    }
}
Example #2
0
TYPE TypeAutoDefault(           // ADD NEAR QUALIFIER FOR AUTO SYMBOL
    TYPE type,                  // - a type
    PTREE expr )                // - possible PT_SYMBOL of SC_AUTO
{
#if 0
    if( PtreeOpFlags( expr ) & PTO_RVALUE ) {
        type = augmentWithNear( type );
    } else if( expr->op == PT_SYMBOL ) {
#else
    if( expr->op == PT_SYMBOL ) {
#endif
        SYMBOL sym = expr->u.symcg.symbol;
        if( sym->id == SC_AUTO ) {
            type_flag flags;
            TypeGetActualFlags( sym->sym_type, &flags );
            if( 0 == ( flags & TF1_MEM_MODEL ) ) {
                type = augmentWithNear( type );
            }
        }
    }
    return( type );
}


TYPE TypeForLvalue              // GET TYPE FOR LVALUE
    ( PTREE expr )              // - lvalue expression
{
    TYPE type_expr;             // - expression type
    TYPE type_lv;               // - type of LVALUE

    type_expr = NodeType( expr );
    type_lv = TypeReference( type_expr );
    DbgVerify( type_lv != NULL, "TypeForLvalue -- not lvalue" );
    return( type_lv );
}
Example #3
0
unsigned ThrowCnvInit(          // THROW CONVERSIONS: INITIALIZE
    THROW_CNV_CTL *ctl,         // - control area
    TYPE type )                 // - type thrown
{
    type_flag not_used;         // - not used
    THROBJ thr_obj;             // - type of throw object

    ctl->carver = CarveCreate( sizeof( THROW_CNV ), 8 );
    ctl->hdr = NULL;
    ctl->cur = NULL;
    type = TypeCanonicalThr( type );
    ctl->error_occurred = false;
    thr_obj = ThrowCategory( type );
    if( thr_obj == THROBJ_REFERENCE ) {
        makeThrowCnvNoAcc( ctl, type, 0 );
    } else {
        makeThrowCnv( ctl, type, 0 );
    }
    switch( thr_obj ) {
      case THROBJ_VOID_STAR :
      case THROBJ_ANYTHING :
      case THROBJ_SCALAR :
        break;
      case THROBJ_PTR_SCALAR :
        makeCnvVoidStar( ctl );
        break;
      case THROBJ_REFERENCE :
        type = TypeReference( type );
        if( NULL != StructType( type ) ) {
            throwClassCnvs( type, ctl );
        } else {
            type = TypePointedAt( type, &not_used );
            if( type != NULL ) {
                type = StructType( type );
                if( type != NULL ) {
                    throwClassPtrCnvs( type, ctl );
                }
                makeCnvVoidStar( ctl );
            }
        }
        break;
      case THROBJ_CLASS :
      case THROBJ_CLASS_VIRT :
        throwClassCnvs( type, ctl );
        break;
      case THROBJ_PTR_CLASS :
        throwClassPtrCnvs( type, ctl );
        makeCnvVoidStar( ctl );
        break;
      case THROBJ_PTR_FUN :
        if( CgCodePtrSize() <= CgDataPtrSize() ) {
            makeCnvVoidStar( ctl );
        }
        break;
      DbgDefault( "EXCEPT -- illegal throw object" );
    }
    return RingCount( ctl->hdr );
}
Example #4
0
static bool referenceSymbol( PTREE expr )
{
    SYMBOL ref_sym;

    ref_sym = expr->u.symcg.symbol;
    if( ref_sym != NULL && TypeReference( ref_sym->sym_type ) != NULL ) {
        return( true );
    }
    return( false );
}
Example #5
0
TYPE TypeReferenced(            // GET TYPE OR TYPE REFERENCED
    TYPE type )                 // - original type
{
    TYPE refed;                 // - referenced type

    refed = TypeReference( type );
    if( refed == NULL ) {
        refed = type;
    }
    return( refed );
}
Example #6
0
TYPE TypeCanonicalThr(          // GET CANONICAL THROW TYPE
    TYPE type )
{
    TYPE test;                  // - used to test type

    if( type != NULL ) {
        test = TypeReference( type );
        if( test == NULL ) {
            type = canonicalPtrType( type );
        } else {
            type = MakeReferenceTo( canonicalPtrType( test ) );
        }
    }
    return type;
}
Example #7
0
bool ExprIsLvalue               // TEST IF EXPRESSION IS LVALUE
    ( PTREE expr )              // - expression
{
    bool ok;                    // - return: true ==> is lvalue

    if( expr->flags & PTF_LVALUE ) {
        ok = true;
    } else {
#ifndef NDEBUG
        TYPE type_expr;
        TYPE type_lv;
        type_expr = NodeType( expr );
        type_lv = TypeReference( type_expr );
        ok = ( NULL != type_lv );
#else
        ok = ( NULL != TypeForLvalue( expr ) );
#endif
    }
    return( ok );
}
Example #8
0
void TypeSigSymOffset(          // GET SYMBOL,OFFSET FOR TYPE-SIG REFERENCE
    TYPE_SIG* sig,              // - type signature
    SYMBOL* a_sym,              // - addr[ symbol ]
    target_offset_t* a_offset ) // - addr[ offset ]
{
    target_offset_t offset;     // - offset

    if( NULL == sig->base ) {
        *a_sym = sig->sym;
        offset = offsetof( TS_HDR, hdr_actual );
    } else {
        *a_sym = sig->base->sym;
        if( NULL == TypeReference( sig->type ) ) {
            offset = offsetof( TS_HDR, hdr_ptr );
        } else {
            offset = offsetof( TS_HDR, hdr_ref );
        }
    }
    *a_offset = offset;
    DbgVerify( sig->type == NULL || *a_sym != NULL
             , "TypeSigSymOffset -- no symbol found" );
}
Example #9
0
THROBJ ThrowCategory(           // GET THROW-OBJECT CATEGORY FOR A TYPE
    TYPE type )                 // - type
{
    TYPE cltype;                // - class type or NULL
    THROBJ retn;                // - category of object

    if( type == NULL ) {
        retn = THROBJ_ANYTHING;
    } else if( NULL != FunctionDeclarationType( type ) ) {
        retn = THROBJ_PTR_FUN;
    } else if( NULL != TypeReference( type ) ) {
        retn = THROBJ_REFERENCE;
    } else if( NULL != (cltype = StructType( type ) ) ) {
        if( cltype->u.c.info->last_vbase == 0 ) {
            retn = THROBJ_CLASS;
        } else {
            retn = THROBJ_CLASS_VIRT;
        }
    } else {
        type = PointerTypeEquivalent( type );
        if( type == NULL ) {
            retn = THROBJ_SCALAR;
        } else if( StructType( type->of ) ) {
            retn = THROBJ_PTR_CLASS;
        } else {
            type = TypedefModifierRemove( type->of );
            if( type->id == TYP_VOID ) {
                retn = THROBJ_VOID_STAR;
            } else if( type->id == TYP_FUNCTION ) {
                retn = THROBJ_PTR_FUN;
            } else {
                retn = THROBJ_PTR_SCALAR;
            }
        }
    }
    return retn;
}
Example #10
0
TypeReference makeTypeReference(Type* type) {

    return TypeReference(new TypeReferenceCore(type->getTypeName(), type));
}
Example #11
0
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
    bool positive )             // - true ==> use positive value
{
    target_offset_t vb_offset;  // - offset of vbptr
    vindex 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 {
        PTF_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;
    }
}
Example #12
0
static void checkAutoReturn(    // CHECK IF AUTOMATIC BEING RETURNED
    PTREE node,                 // - node to be checked
    TYPE ret_type )             // - return type
{
    TYPE func_ret;              // - type of function return
    SYMBOL func;                // - function called
    SYMBOL comped;              // - function being compiled
    PTREE expr;                 // - node for error
    TYPE refed;                 // - NULL ==> not reference

    comped = ScopeFunctionInProgress();
    if( SymIsGenedFunc( comped ) ) {
        return;
    }
    expr = node;
    refed = TypeReference( ret_type );
    for( ; ; ) {
        node = NodeRemoveCastsCommas( node );
        if( ( node->op == PT_SYMBOL )
          &&( SymIsAutomatic( node->u.symcg.symbol ) ) ) {
            if( NULL == refed ) {
                PTreeWarnExpr( expr, WARN_RET_ADDR_OF_AUTO );
            } else {
                PTreeErrorExpr( expr, ERR_RET_AUTO_REF );
            }
            break;
        } else if( NodeIsBinaryOp( node, CO_DOT )
                || NodeIsBinaryOp( node, CO_DOT_STAR ) ) {
            node = PTreeOpLeft( node );
        } else if( NodeIsUnaryOp( node, CO_ADDR_OF ) ) {
            node = PTreeOpLeft( node );
        } else if( NULL != refed ) {
            if( NodeIsBinaryOp( node, CO_DTOR ) ) {
                node = PTreeOpRight( node );
            } else if( NodeIsBinaryOp( node, CO_CALL_EXEC ) ) {
                node = PTreeOpLeft( PTreeOpLeft( node ) );
                if( node->op == PT_SYMBOL ) {
                    func = node->u.symcg.symbol;
                    if( SymIsCtor( func ) ) {
                        PTreeErrorExpr( expr, ERR_RET_AUTO_REF );
                    } else {
                        func_ret = SymFuncReturnType( func );
                        if( NULL != StructType( func_ret ) ) {
                            PTreeErrorExpr( expr, ERR_RET_AUTO_REF );
                        }
                    }
                }
                break;
            } else if( NodeIsBinaryOp( node, CO_CALL_EXEC_IND ) ) {
                func_ret = TypeFunctionCalled( NodeFuncForCall( node )->type );
                func_ret = func_ret->of;
                if( NULL != StructType( func_ret ) ) {
                    PTreeErrorExpr( expr, ERR_RET_AUTO_REF );
                }
                break;
            } else {
                break;
            }
        } else {
            break;
        }
    }
}
Example #13
0
SYMBOL FormatMsg( VBUF *pbuf, char *fmt, va_list arg )
/****************************************************/
// this function assumes that pbuf is initialized
// all information is concatenated to the end of pbuf
{
    VBUF    prefix, suffix;
    char    cfmt;
    char    local_buf[ 1 + sizeof( int ) * 2 + 1 ];
    unsigned len;
    SYMBOL  retn_symbol;

    retn_symbol = NULL;
    cfmt = *fmt;
    while( cfmt ) {
        if( cfmt == '%' ) {
            fmt++;
            cfmt = *fmt;
            switch( cfmt ) {
            case '1':   /* %01d */
            case '2':   /* %02d */
            case '3':   /* %03d */
            case '4':   /* %04d */
            case '5':   /* %05d */
            case '6':   /* %06d */
            case '7':   /* %07d */
            case '8':   /* %08d */
            case '9':   /* %09d */
                len = sticpy( local_buf, va_arg( arg, int ) ) - local_buf;
                leading( pbuf, '0', ( cfmt - '0' ) - len );
                VbufConcStr( pbuf, local_buf );
                break;
            case 'c':   /* %c */
                VbufConcChr( pbuf, va_arg( arg, int ) );
                break;
            case 's':   /* %s */
                VbufConcStr( pbuf, va_arg( arg, char * ) );
                break;
            case 'u':   /* %u */
                VbufConcDecimal( pbuf, va_arg( arg, unsigned int ) );
                break;
            case 'd':   /* %d */
                VbufConcInteger( pbuf, va_arg( arg, int ) );
                break;
            case 'L':   /* token location */
            {   TOKEN_LOCN *locn;
                locn = va_arg( arg, TOKEN_LOCN * );
                if( locn == NULL ) {
                    VbufConcStr( pbuf, "by compiler" );
                } else {
                    char *src_file = SrcFileName( locn->src_file );
                    if( src_file == NULL ) {
                        VbufConcStr( pbuf, "on the command line" );
                    } else {
                        if( ( CompFlags.ew_switch_used )
                          &&( locn->src_file == SrcFileTraceBackFile() ) ) {
                            VbufConcStr( pbuf, "at: " );
                        } else {
                            VbufConcStr( pbuf, "in: " );
                            VbufConcStr( pbuf, SrcFileName( locn->src_file ) );
                        }
                        VbufConcChr( pbuf, '(' );
                        VbufConcInteger( pbuf, locn->line );
                        if( locn->column ) {
                            if( CompFlags.ew_switch_used ) {
                                VbufConcChr( pbuf, ',' );
                                VbufConcInteger( pbuf, locn->column );
                            } else {
                                VbufConcStr( pbuf, ") (col " );
                                VbufConcInteger( pbuf, locn->column );
                            }
                        }
                        VbufConcChr( pbuf, ')' );
                    }
                }
            }   break;
            case 'N':   /* name */
                FormatName( va_arg( arg, NAME ), &prefix );
                VbufConcVbuf( pbuf, &prefix );
                VbufFree( &prefix );
                break;
            case 'F':   /* symbol name (decorated) */
            {   SYMBOL      sym;
                sym = va_arg( arg, SYMBOL );
                FormatSym( sym, &prefix );
                VbufConcVbuf( pbuf, &prefix );
                VbufFree( &prefix );
            }   break;
            case 'S':   /* symbol name (abbreviated) */
            {   SYMBOL      sym;
                SYMBOL_NAME sn;
                NAME        name;
                sym = va_arg( arg, SYMBOL );
                if( sym == NULL ) {
                    VbufConcStr( pbuf, "module data" );
                } else {
                    if( formatClassForSym( sym, pbuf ) ) {
                        VbufConcStr( pbuf, "::" );
                    }
                    if( SymIsCtor( sym ) ) {
                        formatClassForSym( sym, pbuf );
                    } else if( SymIsDtor( sym ) ) {
                        VbufConcChr( pbuf, '~' );
                        formatClassForSym( sym, pbuf );
                    } else {
                        sn = sym->name;
#ifndef NDEBUG
                        if( sn == NULL ) {
                            CFatal( "FormatMsg -- %S symbol has NULL SYMBOL_NAME" );
                        }
#endif
                        name = sn->name;
#ifndef NDEBUG
                        if( name == NULL ) {
                            CFatal( "FormatMsg -- %S SYMBOL_NAME has NULL name" );
                        }
#endif
                        if( name == CppConversionName() ) {
                            VbufConcStr( pbuf, "operator " );
                            FormatType( SymFuncReturnType( sym )
                                      , &prefix
                                      , &suffix );
                            VbufFree( &suffix );
                        } else {
                            FormatName( name, &prefix );
                        }
                        VbufConcVbuf( pbuf, &prefix );
                        VbufFree( &prefix );
                    }
                    if( sym->flag2 & SF2_TOKEN_LOCN ) {
                        DbgVerify( retn_symbol == NULL, "too many symbols" );
                        retn_symbol = sym;
                    }
                }
            }   break;
            case 'T':   /* type name */
            {   TYPE type = va_arg( arg, TYPE );
                TYPE refed = TypeReference( type );
                if( NULL != refed ) {
                    type = refed;
                }
                FormatType( type, &prefix, &suffix );
                VbufConcVbuf( pbuf, &prefix );
                VbufConcVbuf( pbuf, &suffix );
                VbufFree( &prefix );
                VbufFree( &suffix );
                VbufTruncWhite( pbuf );
                if( NULL != refed ) {
                    VbufConcStr( pbuf, " (lvalue)" );
                }
            }   break;
            case 'P':   /* PTREE list */
            {   const PTREE p = va_arg( arg, PTREE );

                FormatPTreeList( p, &prefix );
                VbufConcVbuf( pbuf, &prefix );
                VbufFree( &prefix );
            }   break;
            case 'I':   /* PTREE id */
            {   const PTREE p = va_arg( arg, PTREE );

                FormatPTreeId( p, &prefix );
                VbufConcVbuf( pbuf, &prefix );
                VbufFree( &prefix );
            }   break;
            case 'M':   /* template info */
            {   TEMPLATE_INFO * const tinfo = va_arg( arg, TEMPLATE_INFO * );
                const SYMBOL sym = tinfo->sym;

                FormatTemplateInfo( tinfo, &prefix );
                VbufConcVbuf( pbuf, &prefix );
                VbufFree( &prefix );
                if( sym->flag2 & SF2_TOKEN_LOCN ) {
                    DbgVerify( retn_symbol == NULL, "too many symbols" );
                    retn_symbol = sym;
                }
            }   break;
            case 'C':   /* template specialisation */
            {   TEMPLATE_SPECIALIZATION * const tspec =
                    va_arg( arg, TEMPLATE_SPECIALIZATION * );

                FormatTemplateSpecialization( tspec, &prefix );
                VbufConcVbuf( pbuf, &prefix );
                VbufFree( &prefix );
            }   break;
            default:
                VbufConcChr( pbuf, cfmt );
            }
        } else {
Example #14
0
TYPE_SIG *TypeSigFind(          // FIND TYPE SIGNATURE
    TYPE_SIG_ACCESS acc,        // - access type
    TYPE type,                  // - type for signature
    TOKEN_LOCN* err_locn,       // - error location for access errors
    bool *error_occurred )      // - to set error indication
{
    TYPE_SIG *srch;             // - signature for searching
    TYPE_SIG *sig;              // - signature
    SYMBOL sym;                 // - symbol
    unsigned size;              // - size of R/O data
    NAME typesig_name;          // - name of type signature
    TYPE typesig_type;          // - type of type signature
    bool err_this_time;         // - true ==> we have error
    TYPE_SIG_ACCESS acc_ind;    // - indirect access

    err_this_time = false;
    type = TypeCanonicalThr( type );
    sig = NULL;
    RingIterBeg( type_sigs, srch ) {
        if( TypesSameExclude( srch->type, type, TC1_NOT_ENUM_CHAR ) ) {
            sig = srch;
            break;
        }
    } RingIterEnd( srch );
    if( sig == NULL ) {
        THROBJ thr;             // - category of object
        DbgVerify( 0 == ( acc & TSA_GEN )
                 , "TypeSigFind -- no type signature & TSA_GEN" );
        sig = RingCarveAlloc( carveTYPE_SIG, &type_sigs );
        sig->type = type;
        sig->default_ctor = NULL;
        sig->copy_ctor = NULL;
        sig->dtor = NULL;
        sig->sym = NULL;
        sig->base = NULL;
        sig->cgref = false;
        sig->cggen = false;
        sig->free = false;
        thr = ThrowCategory( type );
        if( acc & TSA_INDIRECT ) {
            acc_ind = acc | TSA_INDIRECT_ACCESS;
        } else if( acc & TSA_INDIRECT_ACCESS ) {
            acc_ind = ( acc & ~ TSA_INDIRECT ) | TSA_INDIRECT_GEN;
        } else {
            acc_ind = acc;
        }
        size = 0;
        switch( thr ) {
        case THROBJ_PTR_SCALAR :
        case THROBJ_PTR_CLASS :
            sig->base = TypeSigFind( acc_ind & TSA_INDIRECT
                                   , TypePointedAtModified( type )
                                   , err_locn
                                   , &err_this_time );
            size = typeSigHdrSize();
            break;
        case THROBJ_SCALAR :
        case THROBJ_PTR_FUN :
        case THROBJ_VOID_STAR :
            size = typeSigHdrSize() + SizeTargetSizeT();
            break;
        case THROBJ_REFERENCE :
            sig->base = TypeSigFind( acc_ind
                                   , TypeReference( type )
                                   , err_locn
                                   , &err_this_time );
            break;
        case THROBJ_CLASS :
        case THROBJ_CLASS_VIRT :
            size = 3 * CgCodePtrSize() + CgDataPtrSize() + typeSigHdrSize();
            break;
        case THROBJ_ANYTHING :
            break;
        default :
            DbgStmt( CFatal( "cgTypeSignature -- invalid throw category" ) );
        }
        size += typeSigNameSize( thr );
        if( size == 0 ) {
            sym = NULL;
        } else {                // - type for TYPE SIGNATURE variable
            typesig_name = CppNameTypeSig( type );
            sym = ScopeAlreadyExists( GetFileScope(), typesig_name );
            if( sym == NULL ) {
                typesig_type = MakeInternalType( size );
                typesig_type = MakeCompilerConstCommonData( typesig_type );
                sym = SymCreateFileScope( typesig_type
                                        , SC_PUBLIC
                                        , SF_REFERENCED | SF_ADDR_TAKEN
                                        , typesig_name );
                LinkageSet( sym, "C++" );
                CgSegId( sym );
            }
        }
        sig->sym = sym;
    }
    if( err_this_time ) {
        *error_occurred = true;
    } else {
        if( NULL != sig->sym ) {
            SegmentMarkUsed( sig->sym->segid );
        }
        *error_occurred = false;
        typeSigAccess( acc, sig, err_locn, error_occurred );
    }
    return( sig );
}
Example #15
0
PTREE AnalyseCall(              // ANALYSIS FOR CALL
    PTREE expr,                 // - call expression
    CALL_DIAG *diagnostic )     // - diagnostics used for function problems
{
    PTREE *r_args;              // - reference( arguments )
    PTREE *r_func;              // - reference( function )
    PTREE *ptlist;              // - nodes for arguments
    PTREE left;                 // - left operand ( the function )
    PTREE right;                // - right operand ( the arguments )
    PTREE this_node;            // - node for "this" computation
    PTREE deref_args;           // - member pointer dereference args
    PTREE last_arg;             // - last argument
    PTREE static_fn_this;       // - "this" for a static member
    PTREE templ_args;           // - explicit template arguments
    SYMBOL sym;                 // - function symbol
    SYMBOL caller_sym;          // - function that is doing the call
    TYPE type;                  // - temporary type
    TYPE fn_type;               // - function type
    type_flag fn_mod;           // - function modifier flags
    unsigned count;             // - # args, caller
    arg_list *alist;            // - arg_list for caller
    intrinsic_mapping *intr_map;// - mapping for intrinsic function
    SEARCH_RESULT *result;      // - searching result
    boolean membptr_deref;      // - TRUE ==> member pointer dereference
    boolean has_ellipsis;       // - TRUE ==> ellipsis in argument list
    boolean virtual_call;       // - TRUE ==> virtual call
    TEMP_PT_LIST default_list;  // - default PTREE list
    TEMP_ARG_LIST default_args; // - default arg_list
    FNOV_DIAG fnov_diag;        // - diagnosis information;

    r_args = PTreeRefRight( expr );
    last_arg = *r_args;
    right = NodeReverseArgs( &count, last_arg );
    *r_args = right;
    r_func = PTreeRefLeft( expr );
    left = *r_func;
    membptr_deref = FALSE;
    this_node = NULL;
    intr_map = NULL;
    static_fn_this = NULL;
    virtual_call = FALSE;
    switch( left->cgop ) {
      case CO_DOT:
      case CO_ARROW:
        this_node = left->u.subtree[0];
        left->u.subtree[0] = NULL;
        left = NodePruneTop( left );
        *r_func = left;
        r_func = PTreeRefLeft( expr );
        left = *r_func;
        if( ( left->op == PT_ID ) && ( left->cgop == CO_NAME_DTOR ) ) {
            /* dtor of a non-class type */
            left = NodePruneTop( *r_func );
            /* NYI: verify dtor call has no arguments */
            expr->u.subtree[0] = NULL;
            NodeFreeDupedExpr( expr );
            expr = NodeConvert( GetBasicType( TYP_VOID ), this_node );
            expr = NodeComma( expr, left );
            return( expr );
        }
        break;
      case CO_CALL_EXEC_IND:
        if( left->flags & PTF_CALLED_ONLY ) {
            /* member pointer dereference being called */
            deref_args = left->u.subtree[1];
            this_node = NodeDupExpr( &(deref_args->u.subtree[1]) );
            membptr_deref = TRUE;
        }
        break;
    }
    alist = ArgListTempAlloc( &default_args, count );
    ptlist = PtListAlloc( default_list, count );
    NodeBuildArgList( alist, ptlist, right, count );
    if( this_node == NULL ) {
        alist->qualifier = FunctionThisQualifier();
    } else {
        alist->qualifier = BaseTypeClassFlags( NodeType( this_node ) );
    }

    if( NodeIsBinaryOp( left, CO_TEMPLATE ) ) {
        DbgAssert( left->u.subtree[0]->op == PT_SYMBOL );

        templ_args = left->u.subtree[1];

        left->u.subtree[1] = NULL;
        left = NodePruneTop( left );
        *r_func = left;
        r_func = PTreeRefLeft( expr );
        left = *r_func;
    } else {
        templ_args = NULL;
    }

    if( left->op == PT_SYMBOL ) {
        FNOV_RESULT ovret;
        SYMBOL orig;        // - original symbol
        sym = left->u.symcg.symbol;
        orig = sym;
        if( left->cgop == CO_NAME_CONVERT ) {
            ovret = UdcOverloadedDiag( &sym
                                 , left->u.symcg.result
                                 , sym
                                 , SymFuncReturnType( sym )
                                 , alist->qualifier
                                 , &fnov_diag );
        } else {
            ovret = FuncOverloadedDiag( &sym
                                   , left->u.symcg.result
                                   , sym
                                   , alist
                                   , ptlist
                                   , templ_args
                                   , &fnov_diag );
        }

        switch( ovret ) {
          case FNOV_AMBIGUOUS :
            CallDiagAmbiguous( expr, diagnostic->msg_ambiguous, &fnov_diag );
            NodeFreeDupedExpr( this_node );
            ArgListTempFree( alist, count );
            PtListFree( ptlist, count );
            return( expr );
          case FNOV_NO_MATCH :
            if( this_node == NULL ) {
                if( SymIsThisFuncMember( orig ) ) {
                    this_node = NodeThisCopyLocation( left );
                }
            }
            if( this_node != NULL ) {
                if( ( ! SymIsCtor( orig ) )
                  &&( ! SymIsDtor( orig ) )
                  &&( CNV_OK != AnalysePtrCV
                                ( this_node
                                , TypeThisSymbol( orig
                                                , this_node->flags & PTF_LVALUE )
                                , NodeType( this_node )
                                , CNV_FUNC_THIS ) ) ) {
                    PTreeErrorNode( expr );
                    InfSymbolDeclaration( orig );
                    NodeFreeDupedExpr( this_node );
                    ArgListTempFree( alist, count );
                    PtListFree( ptlist, count );
                    return( expr );
                }
            }
            CallDiagNoMatch( expr
                           , diagnostic->msg_no_match_one
                           , diagnostic->msg_no_match_many
                           , this_node
                           , orig
                           , &fnov_diag );
            NodeFreeDupedExpr( this_node );
            ArgListTempFree( alist, count );
            PtListFree( ptlist, count );
            return( expr );
        }
        FnovFreeDiag( &fnov_diag );
        left->u.symcg.symbol = sym;
        result = left->u.symcg.result;
        if( this_node == NULL ) {
            if( SymIsThisFuncMember( sym ) ) {
                if( result->use_this ) {
                    this_node = NodeThisCopyLocation( left );
                    if( this_node == NULL ) {
                        PTreeErrorExpr( expr, ERR_INVALID_NONSTATIC_ACCESS );
                        InfSymbolDeclaration( sym );
                        ArgListTempFree( alist, count );
                        PtListFree( ptlist, count );
                        return( expr );
                    }
                } else {
                    PTreeErrorExpr( expr, ERR_BARE_FUNCTION_ACCESS );
                    InfSymbolDeclaration( sym );
                    ArgListTempFree( alist, count );
                    PtListFree( ptlist, count );
                    return( expr );
                }
            }
        }
        if( ! AnalyseSymbolAccess( expr, left, this_node, &diagAccess ) ) {
            NodeFreeDupedExpr( this_node );
            ArgListTempFree( alist, count );
            PtListFree( ptlist, count );
            return( expr );
        }
        type = sym->sym_type;
        fn_type = TypeGetActualFlags( type, &fn_mod );
        if( fn_type->flag & TF1_INTRINSIC ) {
            intr_map = intrinsicMapping( sym );
            if( intr_map == NULL ) {
                outputCallTriggeredWarning( expr, sym );
            }
        }
        if( fn_mod & TF1_FAR16 ) {
            /* we are calling a far16 function */
            caller_sym = ScopeFunctionInProgress();
            caller_sym->flag |= SF_FAR16_CALLER;
        }
        left->type = type;
        if( this_node == NULL ) {
            if( SymIsThisFuncMember( sym ) ) {
                this_node = NodeThisCopyLocation( left );
            }
        } else {
            if( SymIsStaticFuncMember( sym ) ) {
                #ifdef OLD_STATIC_MEMBER_ACCESS
                    NodeFreeDupedExpr( this_node );
                #else
                    static_fn_this = this_node;
                #endif
                this_node = NULL;
            }
        }
        if( this_node != NULL ) {
            TYPE pted;
            pted = TypePointedAtModified( this_node->type );
            if( pted == NULL ) {
                pted = this_node->type;
            }
            if( TypeTruncByMemModel( pted ) ) {
                if( SymIsCtor( sym ) ) {
                    PTreeErrorExpr( this_node, ERR_CTOR_OBJ_MEM_MODEL );
                } else if( SymIsDtor( sym ) ) {
                    PTreeErrorExpr( this_node, ERR_DTOR_OBJ_MEM_MODEL );
                } else {
                    PTreeErrorExpr( this_node, ERR_THIS_OBJ_MEM_MODEL );
                }
                InfSymbolDeclaration( sym );
                PTreeErrorNode( expr );
                NodeFreeDupedExpr( this_node );
                ArgListTempFree( alist, count );
                PtListFree( ptlist, count );
                NodeFreeDupedExpr( static_fn_this );
                return( expr );
            }
            if( adjustForVirtualCall( &this_node, r_func, result ) ) {
                virtual_call = TRUE;
                expr->cgop = CO_CALL_EXEC_IND;
                left = VfunSetupCall( expr->u.subtree[0] );
                left = VfnDecorateCall( left, sym );
            } else {
                expr->cgop = CO_CALL_EXEC;
                left = NodeUnaryCopy( CO_CALL_SETUP, expr->u.subtree[0] );
                SymMarkRefed( sym );
            }
        } else {
            NodeFreeSearchResult( left );
            expr->cgop = CO_CALL_EXEC;
            left = NodeUnaryCopy( CO_CALL_SETUP, expr->u.subtree[0] );
            SymMarkRefed( sym );
        }
    } else {
        if( ! membptr_deref ) {
            /* i.e, p->foo() where foo is a pointer to a function */
            NodeFreeDupedExpr( this_node );
            this_node = NULL;
        }
        sym = NULL;
        left = expr->u.subtree[0];
        type = TypedefModifierRemove( left->type );
        if( type->id == TYP_POINTER ) {
            type = type->of;
        }
        fn_type = TypeGetActualFlags( type, &fn_mod );
        if( fn_mod & TF1_FAR16 ) {
            /* we are calling a far16 function */
            caller_sym = ScopeFunctionInProgress();
            caller_sym->flag |= SF_FAR16_CALLER;
        }
        if( ! TypeHasNumArgs( type, count ) ) {
            PTreeErrorExpr( expr, ERR_PARM_COUNT_MISMATCH_POINTER );
            CErr2p( INF_FUNCTION_TYPE, type );
            ArgListTempFree( alist, count );
            PtListFree( ptlist, count );
            NodeFreeDupedExpr( static_fn_this );
            return( expr );
        }
        expr->cgop = CO_CALL_EXEC_IND;
        left = VfunSetupCall( left );
    }
    expr->u.subtree[0] = left;
#if _CPU == _AXP
    if( intr_map != NULL && intr_map->cgop == CO_VASTART ) {
        expr = convertVaStart( expr, alist, type );
    } else {
        expr = NodeConvertCallArgList( expr, count, type, &expr->u.subtree[1] );
    }
#else
    expr = NodeConvertCallArgList( expr, count, type, &expr->u.subtree[1] );
#endif
    if( expr->op != PT_ERROR ) {
        TYPE ftype;             // - function type
        PTREE cdtor;            // - CDTOR node
        PTREE callnode;         // - call node
        PTREE retnnode;         // - return node (for struct return)
        callnode = expr;
        if( this_node == NULL ) {
            cdtor = NULL;
        } else {
            this_node = NodeArg( this_node );
            if( virtual_call ) {
                this_node->flags |= PTF_ARG_THIS_VFUN;
            }
            if( sym != NULL && SymIsDtor( sym ) ) {
                cdtor = NodeArg( NodeCDtorArg( DTOR_NULL ) );
            } else {
                cdtor = NULL;
            }
        }
        ftype = type;
        type = TypedefModifierRemove( type );
        has_ellipsis = TypeHasEllipsisArg( type );
        type = type->of;
        {
            TYPE tgt = TypeReference( type );
            if( tgt == NULL ) {
                expr->type = type;
            } else {
                expr->type = tgt;
                expr->flags |= PTF_LVALUE;
            }
        }
        if( sym != NULL ) {
            if( ! AddDefaultArgs( sym, expr ) ) {
                NodeFreeDupedExpr( cdtor );
                NodeFreeDupedExpr( this_node );
                ArgListTempFree( alist, count );
                PtListFree( ptlist, count );
                return expr;
            }
        }
        if( NULL != TypeReference( type ) ) {
            expr->flags |= PTF_LVALUE;
        }
        if( OMR_CLASS_REF == ObjModelArgument( type ) ) {
            retnnode = NodeTemporary( type );
            retnnode = PTreeCopySrcLocation( retnnode, expr );
        } else {
            retnnode = NULL;
        }
        expr = CallArgsArrange( ftype
                              , callnode
                              , callnode->u.subtree[1]
                              , this_node
                              , cdtor
                              , retnnode );
        if( retnnode != NULL ) {
            expr = NodeDtorExpr( expr, retnnode->u.symcg.symbol );
            if( SymRequiresDtoring( retnnode->u.symcg.symbol ) ) {
                expr = PtdCtoredExprType( expr, NULL, type );
            }
        }
        type = StructType( type );
        if( type != NULL && ! TypeDefined( type ) ) {
            PTreeErrorExpr( expr, ERR_RETURN_UNDEFD_TYPE );
        }
        if( intr_map != NULL && expr->op != PT_ERROR ) {
#if _CPU == _AXP
            if( intr_map->cgop == CO_VASTART ) {
                expr = transformVaStart( expr );
            } else {
                expr = PTreeIntrinsicOperator( expr, intr_map->cgop );
            }
#else
            expr = PTreeIntrinsicOperator( expr, intr_map->cgop );
#endif
            expr->flags |= PTF_MEANINGFUL | PTF_SIDE_EFF;
        }
    }
    if( static_fn_this != NULL ) {
        expr = NodeCommaIfSideEffect( static_fn_this, expr );
    }
    ArgListTempFree( alist, count );
    PtListFree( ptlist, count );
    return expr;
}