analnew.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 913 行 · 第 1/3 页

C
913
字号
    alist = ArgListTempAlloc( &default_args, count_placement );
    ptlist = PtListAlloc( default_list, count_placement );
    NodeBuildArgList( alist, ptlist, node, count_placement );
    /* find the appropriate "operator new" or operator new[] */
    sym = result_new->sym_name->name_syms;
    ovret = FuncOverloadedDiag( &sym
                           , result_new
                           , sym
                           , alist
                           , ptlist
                           , &fnov_diag ) ;
    if( ovret == FNOV_NONAMBIGUOUS ) {
        if( ScopeCheckSymbol( result_new, sym ) ) {
            PTreeErrorNode( node );
        } else {
            node = NodeMakeCall( sym, new_expr_type, node );
            node = NodeConvertCallArgList( node
                                         , alist->num_args
                                         , sym->sym_type
                                         , &node->u.subtree[1] );
            if( node->op != PT_ERROR ) {
                AddDefaultArgs( sym, node );
            }
        }
    } else {
        sym = result_new->sym_name->name_syms;
        node = NodeMakeCall( sym, new_expr_type, node );
        switch( ovret ) {
          case FNOV_AMBIGUOUS:
            CallDiagAmbiguous( node, ERR_NEW_OVERLOAD_AMBIGUOUS, &fnov_diag );
            break;
          case FNOV_NO_MATCH:
            CallDiagNoMatch( node
                           , ERR_FUNCTION_NO_MATCH
                           , ERR_NEW_OVERLOAD_FAILURE
                           , NULL
                           , sym
                           , &fnov_diag
                           );
            break;
          DbgDefault( "buildNewCall: unexpected return from FuncOverloaded" );
        }
    }
    FnovFreeDiag( &fnov_diag );
    ScopeFreeResult( result_new );
    ArgListTempFree( alist, count_placement );
    PtListFree( ptlist, count_placement );
    return node;
}


PTREE AnalyseNew(               // ANALYSE A "NEW" OPERATOR (WITH OVERLOADING)
    PTREE expr,                 // - "new" expression
    TYPE type )                 // - type of expression
{
    unsigned count_placement;   // - # placement arg.s
    unsigned ctor_overload;     // - result of ctor overload
    unsigned num_args;          // - number of args for delete operator
    PTREE new_parms1;           // - CO_NEW_PARMS1 node
    PTREE new_parms2;           // - CO_NEW_PARMS2 node
    PTREE elem_size;            // - constant for size of an element
    PTREE node;                 // - new node
    PTREE dup;                  // - duplicated node
    PTREE placement;            // - placement arguments
    PTREE initial;              // - initialization arguments
    PTREE array_number;         // - number of array arguments
    TYPE base_type;             // - base type of element
    TYPE class_type;            // - != NULL if base_type is a class
    TYPE new_expr_type;         // - final type of the new-expr
    TYPE offset_type;           // - type for offset computations
    SYMBOL sym_ctor;            // - constructor function
    SYMBOL op_dlt;              // - delete operator used to free new'ed store
    SYMBOL addr_op_del;         // - addressible operator delete
    SEARCH_RESULT *result_dlt;  // - search result for operator delete
    CGOP cgop;                  // - type of new expression
    TOKEN_LOCN err_locn;        // - error location
    struct {
      unsigned needs_dtor : 1;  // - class says DTOR is req'd (DTOR may be empty)
      unsigned really_dtorable:1;//- class DTOR really req'd
      unsigned needs_count:1;   // - array new needs count in allocation
      unsigned free_array_no :1;// - "array_number" needs to be freed
    } flag;


    /*
                        CO_NEW
                       /      \
        PT_TYPE(type)           CO_NEW_PARMS1
                               /             \
                placement ->  ,               CO_NEW_PARMS2
                             / \             /             \
                            ,   arg n      nelem            , <- new-init
                           / \          (may be NULL)      / \
                          ,   ...                         ,   arg n
                           \                             / \
                            arg 1                       ,   ...
                                                         \
                                                          arg 1
    */
    if( ! TypeDefined( type ) ) {
        PTreeErrorExpr( expr, ERR_CANT_NEW_UNDEFD );
        return( expr );
    }
    PTreeExtractLocn( expr, &err_locn );
    /* extract the components of the new-expression and free the CO_NEW* parts */
    new_parms1 = expr->u.subtree[1];
    placement = NodeReverseArgs( &count_placement, new_parms1->u.subtree[0] );
    new_parms1->u.subtree[0] = NULL;
    new_parms2 = new_parms1->u.subtree[1];
    initial = new_parms2->u.subtree[1];
    new_parms2->u.subtree[1] = NULL;
    array_number = new_parms2->u.subtree[0];
    new_parms2->u.subtree[0] = NULL;
    cgop = expr->cgop;
    NodeFreeDupedExpr( expr );
    /* 'type', 'placement', 'array_number', and 'initial' are set now */
    new_expr_type = figureOutNewType( &array_number, &type );
    elem_size = NodeOffset( CgTypeSize( type ) );
    offset_type = elem_size->type;
    base_type = ArrayBaseType( type );
    class_type = StructType( type );
    //
    // verify CTORING is ok
    //
    ctor_overload = checkNewCtor( class_type
                                , base_type
                                , &sym_ctor
                                , &initial
                                , &err_locn );
    if( ctor_overload != CNV_OK ) {
        NodeFreeDupedExpr( placement );
        NodeFreeDupedExpr( elem_size );
        NodeFreeDupedExpr( array_number );
        NodeFreeDupedExpr( initial );
        return( PTreeErrorNode( NULL ) );
    }
    //
    // optimize away CTORing if possible
    //
    if( sym_ctor != NULL ) {
        if( initial == NULL && ! TypeReallyDefCtorable( class_type ) ) {
            sym_ctor = NULL;
        }
    }
    flag.needs_count = FALSE;
    flag.needs_dtor = FALSE;
    flag.really_dtorable = FALSE;
    flag.free_array_no = FALSE;
    if( TypeRequiresDtoring( class_type ) ) {
        flag.needs_dtor = TRUE;
        // the structure of the allocation can't be influenced by 'really_dtorable'
        // since the alloc and delete may not agree on 'really_dtorable'
        // the flag is currently not used in the new but could be used to
        // influence the choice of run-time routines for array news in the
        // face of exceptions
        //if( TypeReallyDtorable( class_type ) ) {
            //flag.really_dtorable = TRUE;
        //}
    }
    op_dlt = accessDelete( array_number == NULL ? CO_DELETE : CO_DELETE_ARRAY
                         , scopeLookup( class_type )
                         , &num_args
                         , &result_dlt );
    addr_op_del = ClassFunMakeAddressable( op_dlt );
    //
    // compute size
    //
    if( array_number != NULL ) {
        if( flag.needs_dtor || num_args == 2 ) {
            flag.needs_count = TRUE;
        }
        array_number = NodeRvalue( array_number );
        if( IntegralType( array_number->type ) == NULL ) {
            PTreeErrorExpr( array_number, ERR_NEW_ARRAY_EXPRESSION );
            ScopeFreeResult( result_dlt );
            NodeFreeDupedExpr( placement );
            NodeFreeDupedExpr( elem_size );
            NodeFreeDupedExpr( array_number );
            NodeFreeDupedExpr( initial );
            return( PTreeErrorNode( NULL ) );
        }
        if( initial != NULL ) {
            PTreeErrorExpr( initial, ERR_CANT_INIT_NEW_ARRAY );
            ScopeFreeResult( result_dlt );
            NodeFreeDupedExpr( placement );
            NodeFreeDupedExpr( elem_size );
            NodeFreeDupedExpr( array_number );
            NodeFreeDupedExpr( initial );
            return( PTreeErrorNode( NULL ) );
        }
        /* calculate "nelem * sizeof( elem )" */
        dup = array_number;
        if( sym_ctor != NULL || flag.needs_count ) {
            array_number = NodeDupExpr( &dup );
            flag.free_array_no = TRUE;
        }
        node = NodeBinary( CO_TIMES, dup, elem_size );
        node->type = offset_type;
        node = FoldBinary( node );
        if( flag.needs_count ) {
            node = NodeBinary( CO_PLUS, node, sizeOfUInt() );
            node->type = offset_type;
            node = FoldBinary( node );
        }
    } else {
        node = elem_size;
    }
    //
    // build call to appropriate operator new
    //
    node->locn = err_locn;
    node = NodeArgument( placement, node );
    ++count_placement;
    node = buildNewCall( node
                       , opNewSearchScope( class_type, cgop )
                       , new_expr_type
                       , count_placement
                       , &err_locn
                       , array_number == NULL ? CO_NEW : CO_NEW_ARRAY );
    if( node->op == PT_ERROR ) {
        ScopeFreeResult( result_dlt );
        NodeFreeDupedExpr( node );
        if( flag.free_array_no ) {
            NodeFreeDupedExpr( array_number );
        }
        NodeFreeDupedExpr( initial );
        return( PTreeErrorNode( NULL ) );
    }
    //
    // CTOR the new'ed memory and set up ARRAY_STORAGE, if required
    //
    if( array_number != NULL ) {
        if( sym_ctor != NULL ) {
            unsigned rt_code;       // - run-time function code
            PTREE args;             // - run-time call arguments
            TYPE_SIG *sig;          // - type signature for class
            boolean errors;         // - TRUE ==> errors
            TYPE_SIG_ACCESS acc;    // - rtn.s to be accessed
            if( flag.needs_dtor ) {
                acc = TSA_DTOR | TSA_DEFAULT_CTOR;
            } else {
                acc = TSA_DEFAULT_CTOR;
            }
            sig = TypeSigFind( acc, class_type, &err_locn, &errors );
            if( errors ) {
                ScopeFreeResult( result_dlt );
                NodeFreeDupedExpr( node );
                if( flag.free_array_no ) {
                    NodeFreeDupedExpr( array_number );
                }
                NodeFreeDupedExpr( initial );
                return( PTreeErrorNode( NULL ) );
            }
            TypeSigReferenced( sig );
            op_dlt = checkDeleteResult( op_dlt
                                      , result_dlt
                                      , &err_locn
                                      , FALSE );
            if( op_dlt == NULL ) {
                NodeFreeDupedExpr( node );
                if( flag.free_array_no ) {
                    NodeFreeDupedExpr( array_number );
                }
                NodeFreeDupedExpr( initial );
                return( PTreeErrorNode( NULL ) );
            }
            if( num_args == 1 ) {
                if( ScopeId( SymScope( op_dlt ) ) == SCOPE_FILE
                 && addr_op_del == op_dlt ) {
                    if( flag.needs_count ) {
                        rt_code = RTF_CTAS_GS;
                    } else {
                        rt_code = RTF_CTAS_GM;
                    }
                    args = NULL;
                } else {
                    if( flag.needs_count ) {
                        rt_code = RTF_CTAS_1S;
                    } else {
                        rt_code = RTF_CTAS_1M;
                    }
                    args = NodeArg( MakeNodeSymbol( addr_op_del ) );
                    args = PtdScopeCall( args, op_dlt );
                }
            } else {
                DbgVerify( flag.needs_count
                         , "AnalyseNew -- flags mismatch" );
                rt_code = RTF_CTAS_2S;
                args = NodeArg( MakeNodeSymbol( addr_op_del ) );
                args = PtdScopeCall( args, op_dlt );
            }
            args = NodeArgument( args, NodeTypeSig( sig ) );
            args = NodeArgument( args, array_number );
            args = NodeArgument( args, node );
            node = RunTimeCall( args, new_expr_type, rt_code );
            if( placement != NULL ) {
                dup = node;
                node = NodeDupExpr( &dup );
                node = newCheckForNULL( dup, node );
            }
        } else {
            ScopeFreeResult( result_dlt );
            /* no constructor req'd */
            if( flag.needs_count ) {
                dup = node;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?