Ejemplo n.º 1
0
static PTREE genVfunCall(       // DIRECTLY GENERATE VFUN CALL
    target_offset_t vf_offset,  // - offset to VF table ptr
    PTREE node,                 // - original "this" expression
    target_offset_t vf_index,   // - index into VF table
    SYMBOL sym )                // - symbol to access
{
    TYPE vfptr_type;            // - type[ ptr to VF table ]
    TYPE vfn_type;              // - type[ ptr to VF ]

    node = NodeBinary( CO_DOT, node, NodeOffset( vf_offset ) );
    vfptr_type = MakeVFTableFieldType( TRUE );
    node->type = vfptr_type;
    node->flags |= PTF_LVALUE;
    node = PtdExprConst( node );
    node = NodeRvalue( node );
    vfn_type = TypePointedAtModified( vfptr_type );
    node = NodeBinary( CO_DOT
                     , node
                     , NodeOffset( vf_index * CgMemorySize( vfn_type ) ) );
    node->type = vfn_type;
    node->flags |= PTF_LVALUE;
    node = NodeRvalue( node );
    node->type = sym->sym_type;
    return node;
}
Ejemplo n.º 2
0
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
    vindex 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 );
}
Ejemplo n.º 3
0
TYPE TypeFunctionCalled(        // GET FUNCTION DECLARATION TYPE CALLED
    TYPE type )                 // - function type called
{
    TYPE pted;                  // - NULL or type pointed at

    type = TypeReferenced( type );
    pted = TypePointedAtModified( type );
    if( NULL != pted ) {
        type = pted;
    }
    return( FunctionDeclarationType( type ) );
}
Ejemplo n.º 4
0
TYPE TypeConvertFromPcPtr(      // TRANSFORM TYPE AFTER CONVERSION FROM PC PTR
    TYPE ptype )                // - pointer type
{
    type_flag flags;            // - flags for item pointed at
    TYPE pted;                  // - type pointed at (modified)
    TYPE type;                  // - type pointed at (unmodified)
    SYMBOL baser;               // - basing infomation

    pted = TypePointedAtModified( ptype );
    type = TypeModExtract( pted, &flags, &baser, TC1_NOT_ENUM_CHAR );
    switch( flags & TF1_BASED ) {
    case 0 :
        if( flags & TF1_FAR16 ) {
            ptype = TypeRebuildPcPtr( type, flags, DefaultMemoryFlag( type ) );
        }
        break;
    case TF1_BASED_VOID :
        ptype = TypeRebuildPcPtr( type, flags, TF1_NEAR );
        break;
    case TF1_BASED_ADD :
      { type_flag bflags;       // - flags for baser
        TypePointedAt( baser->sym_type, &bflags );
        ptype = TypeRebuildPcPtr( type, flags, bflags & TF1_MEM_MODEL );
      } break;
    case TF1_BASED_SELF :
        ptype = TypeRebuildPcPtr( type, flags, TF1_FAR );
        break;
    case TF1_BASED_FETCH :
        ptype = TypeRebuildPcPtr( type, flags, TF1_FAR );
        break;
    case TF1_BASED_STRING :
        ptype = TypeRebuildPcPtr( type, flags, TF1_FAR );
        break;
    }
    return( ptype );
}
Ejemplo n.º 5
0
bool PtrCnvInfo(                // FILL IN PTR-CONVERSION INFORMATION
    TYPE ptr_src,               // - source type
    TYPE ptr_tgt,               // - target pointer type
    PTRCNV* info )              // - pointer-conversion information
{
    bool ok;                    // - return: true ==> can convert trivially
    bool first_level;           // - true ==> at first level
    bool const_always;          // - true ==> const on all preceding levels
    TYPE orig_src;              // - original src type

    info->converts = false;
    info->to_base = false;
    info->to_derived = false;
    info->to_void = false;
    info->ptr_integral_ext = false;
    info->cv_err_0 = false;
    info->reint_cast_ok = false;
    orig_src = ptr_src;
    ptr_src = TypePointedAtModified( ptr_src );
    ptr_tgt = TypePointedAtModified( ptr_tgt );
    if( ptr_src == NULL ) {
        info->pted_src = NULL;
        info->flags_src = 0;
        ptr_tgt = TypeGetActualFlags( ptr_tgt, &info->flags_tgt );
        info->pted_tgt = ptr_tgt;
        if( ptr_tgt->id == TYP_VOID ) {
            info->to_void = true;
        }
        if( NULL != orig_src && IntegralType( orig_src ) ) {
            info->reint_cast_ok = true;
        }
        ok = false;
    } else {
        first_level = true;
        const_always = true;
        info->reint_cast_ok = true;
        for( ; ; ) {
            type_flag flags_src;    // source flags
            type_flag flags_tgt;    // target flags
            type_flag cv_src;       // source CV flags
            type_flag cv_tgt;       // target CV flags
            ptr_src = TypeGetActualFlags( ptr_src, &flags_src );
            ptr_tgt = TypeGetActualFlags( ptr_tgt, &flags_tgt );
            cv_src = flags_src & TF1_CV_MASK;
            cv_tgt = flags_tgt & TF1_CV_MASK;
            if( cv_src != ( cv_tgt & cv_src ) ) {   // test cv-containment
                if( first_level ) {
                    info->cv_err_0 = true;          // - diagnose elsewhere
                } else {
                    ok = false;
                    break;
                }
            }
            if( first_level ) {
                TYPE cl_src;        // class for source
                TYPE cl_tgt;        // class for target
                ok = true;
                info->pted_src = ptr_src;
                info->pted_tgt = ptr_tgt;
                info->flags_src = flags_src;
                info->flags_tgt = flags_tgt;
                cl_src = StructType( ptr_src );
                if( ptr_tgt->id == TYP_VOID ) {
                    info->to_void = true;
//                  ok = (ptr_src == TYP_VOID);
//                  break;
                } else if( NULL != cl_src ) {
                    cl_tgt = StructType( ptr_tgt );
                    if( NULL != cl_tgt
                     && cl_tgt != cl_src ) {
                        if( TypeDerived( ptr_src, ptr_tgt ) ) {
                            info->to_base = true;
                            ok = false;
//                          break;
                        } else if( TypeDerived( ptr_tgt, ptr_src ) ) {
                            info->to_derived = true;
                            ok = false;
//                          break;
                        }
                    }
                } else if( ( ptr_src->id != ptr_tgt->id )
                        && IntegralType( ptr_src )
                        && IntegralType( ptr_tgt )
                        && ( CgMemorySize( ptr_src ) == CgMemorySize( ptr_tgt ) ) ) {
                    info->ptr_integral_ext = true;
                }
                if( !ok ) {
                    if( info->cv_err_0 ) {
                        info->reint_cast_ok = false;
                    }
                    break;
                }
                first_level = false;
            }
            if( cv_tgt != cv_src ) {                // test const'ed to here
                if( ! const_always ) {
                    info->reint_cast_ok = false;
                    ok = false;
                    break;
                }
            }
            if( (cv_tgt & TF1_CONST) == 0 ) {
                const_always = false;
            }
            if( ptr_src == ptr_tgt ) {
                ok = true;
                break;
            }
            if( TYP_FUNCTION == ptr_src->id
             || TYP_FUNCTION == ptr_tgt->id ) {
                ok = TypeCompareExclude( ptr_src
                                         , ptr_tgt
                                         , TC1_FUN_LINKAGE |
                                           TC1_NOT_ENUM_CHAR );
                break;
            }
            ptr_src = TypePointedAtModified( ptr_src );
            ptr_tgt = TypePointedAtModified( ptr_tgt );
            if( NULL == ptr_src ) {
                if( NULL != ptr_tgt
                 && NULL != FunctionDeclarationType( ptr_tgt ) ) {
                    info->reint_cast_ok = false;
                }
                ok = false;
                break;
            }
            if( NULL == ptr_tgt ) {
                ok = false;
                break;
            }
        }
    }
    return( ok );
}
Ejemplo n.º 6
0
CNV_RETN PtrConvertCommon(      // CONVERT TO COMMON PTR
    PTREE expr )                // - expression
{
    PTREE *r_left;              // - reference( left node )
    PTREE *r_right;             // - reference( right node )
    TYPE ltype;                 // - type on left
    TYPE rtype;                 // - type on right
    TYPE lptype;                // - new ptr type on left
    TYPE rptype;                // - new ptr type on right
    TYPE lbtype;                // - base type on left
    TYPE rbtype;                // - base type on right
    TYPE type;                  // - resultant type
    TYPE common;                // - common base type
    CNV_RETN retn;              // - conversion return

    r_left = &expr->u.subtree[0];
    ltype = NodeType( *r_left );
    r_right = &expr->u.subtree[1];
    rtype = NodeType( *r_right );
    if( same_ptr_types( ltype, rtype ) ) {
        type = ltype;
        if( CgTypeSize( ltype ) > CgTypeSize( rtype ) ) {
            expr->type = ltype;
        } else {
            expr->type = rtype;
        }
        retn = propogateNonZero( CNV_OK, expr );
    } else if( ptr_to_void( ltype ) ) {
        retn = NodeCheckCnvPtrVoid( &expr, rtype, ltype );
        retn = check_common( retn, expr, ltype );
    } else if( ptr_to_void( rtype ) ) {
        retn = NodeCheckCnvPtrVoid( &expr, ltype, rtype );
        retn = check_common( retn, expr, rtype );
    } else{
        lbtype = TypePointedAtModified( ltype );
        rbtype = TypePointedAtModified( rtype );
        switch( TypeCommonDerivation( lbtype, rbtype ) ) {
        case CTD_LEFT :
        case CTD_LEFT_VIRTUAL :
            retn = NodeConvertPtr( CNVPTR_DERIVED_ONLY, r_left, ltype, rtype );
            retn = check_common( retn, expr, rtype );
            break;
        case CTD_RIGHT :
        case CTD_RIGHT_VIRTUAL :
            retn = NodeConvertPtr( CNVPTR_DERIVED_ONLY, r_right, rtype, ltype );
            retn = check_common( retn, expr, ltype );
            break;
        case CTD_NO :
            common = TypeCommonBase( rbtype, lbtype );
            if( common != NULL ) {
                lptype = TypePointedAtReplace( ltype, common );
                rptype = TypePointedAtReplace( rtype, common );
                /* TypeCommonBase verified everything so these convs will work*/
                NodeConvertPtr( CNVPTR_DERIVED_ONLY, r_left, ltype, lptype );
                NodeConvertPtr( CNVPTR_DERIVED_ONLY, r_right, rtype, rptype);
                expr->type = expr->u.subtree[0]->type;
                retn = propogateNonZero( CNV_OK, expr );
            } else {
                retn = UserDefCnvToType( r_left, ltype, rtype );
                if( retn == CNV_IMPOSSIBLE ) {
                    retn = UserDefCnvToType( r_right, rtype, ltype );
                    retn = check_common( retn, expr, ltype );
                } else {
                    retn = check_common( retn, expr, rtype );
                }
            }
            break;
        case CTD_RIGHT_AMBIGUOUS :
            ConversionTypesSet( rtype, ltype );
        case CTD_LEFT_AMBIGUOUS :
            retn = CNV_AMBIGUOUS;
            break;
        case CTD_RIGHT_PRIVATE :
            ConversionTypesSet( rtype, ltype );
        case CTD_LEFT_PRIVATE :
            retn = CNV_PRIVATE;
            break;
        case CTD_RIGHT_PROTECTED :
            ConversionTypesSet( rtype, ltype );
        case CTD_LEFT_PROTECTED :
            retn = CNV_PROTECTED;
            break;
        }
    }
    return( retn );
}
Ejemplo n.º 7
0
CNV_RETN NodeConvertPtr(        // CONVERT A POINTER
    CNVPTR_REQD reqd_cnvptr,    // - type of conversion
    PTREE *expr,                // - expression to be converted
    TYPE src,                   // - source type (converted from)
    TYPE tgt )                  // - target type (converted to)
{
    SCOPE src_scope;            // - source scope
    SCOPE tgt_scope;            // - target scope
    CNV_RETN retn = CNV_ERR;    // - return: CNV_... indicates what happened

    if( same_ptr_types( src, tgt ) ) {
        (*expr)->type = src;
        return( CNV_OK );
    }
    src_scope = scope_for_ptr( src );
    tgt_scope = scope_for_ptr( tgt );
    switch( TypeCommonDerivation( TypePointedAtModified( src )
                                , TypePointedAtModified( tgt ) ) ) {
    case CTD_NO :
        if( ptr_to_void( tgt ) ) {
            *expr = NodeConvert( tgt, *expr );
            retn = check_result_cv( expr, src, tgt, reqd_cnvptr );
        } else {
            retn = CNV_IMPOSSIBLE;
        }
        break;
    case CTD_RIGHT_PROTECTED :
        if( (reqd_cnvptr & CNVPTR_CAST) == 0 ) {
            if( reqd_cnvptr & CNVPTR_VIRT_TO_DERIVED ) {
                retn = CNV_PROTECTED;
            } else {
                retn = CNV_IMPOSSIBLE;
            }
            break;
        }
        /* fall through */
    case CTD_RIGHT_PRIVATE :
        if( (reqd_cnvptr & CNVPTR_CAST) == 0 ) {
            if( reqd_cnvptr & CNVPTR_VIRT_TO_DERIVED ) {
                retn = CNV_PRIVATE;
            } else {
                retn = CNV_IMPOSSIBLE;
            }
            break;
        }
        /* fall through */
    case CTD_RIGHT :
        if( reqd_cnvptr & CNVPTR_VIRT_TO_DERIVED ) {
            NodeConvertBaseToDerived( expr, tgt, tgt_scope, src_scope );
            retn = check_result_cv( expr, src, tgt, reqd_cnvptr );
        } else {
            retn = CNV_IMPOSSIBLE;
        }
        break;
    case CTD_RIGHT_VIRTUAL :
        if( reqd_cnvptr & CNVPTR_VIRT_TO_DERIVED ) {
            retn = CNV_VIRT_DER;
        } else {
            retn = CNV_IMPOSSIBLE;
        }
        break;
    case CTD_RIGHT_AMBIGUOUS :
        if( reqd_cnvptr & CNVPTR_VIRT_TO_DERIVED ) {
            retn = CNV_AMBIGUOUS;
        } else {
            retn = CNV_IMPOSSIBLE;
        }
        break;
    case CTD_LEFT_PRIVATE :
        if( (reqd_cnvptr & CNVPTR_CAST) == 0 ) {
            retn = CNV_PRIVATE;
            break;
        }
        /* fall through */
    case CTD_LEFT_PROTECTED :
        if( (reqd_cnvptr & CNVPTR_CAST) == 0 ) {
            retn = CNV_PROTECTED;
            break;
        }
        /* fall through */
    case CTD_LEFT :
        NodeConvertDerivedToBase( expr, tgt, src_scope, tgt_scope );
        retn = check_result_cv( expr, src, tgt, reqd_cnvptr );
        break;
    case CTD_LEFT_VIRTUAL :
        NodeConvertDerivedToVirt( expr, tgt, src_scope, tgt_scope );
        retn = check_result_cv( expr, src, tgt, reqd_cnvptr );
        break;
    case CTD_LEFT_AMBIGUOUS :
        retn = CNV_AMBIGUOUS;
        break;
    }
    return( retn );
}
Ejemplo n.º 8
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 );
}
Ejemplo n.º 9
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;
}