analnew.c

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

C
913
字号
                node = NodeDupExpr( &dup );
                expr = setupArrayStorage( dup, new_expr_type, array_number );
                node = newCheckForNULL( node, expr );
            }
        }
    } else {
        ScopeFreeResult( result_dlt );
        if( initial != NULL || sym_ctor != NULL ) {
            dup = node;
            node = NodeDupExpr( &dup );
#if 0
            dup->type = type;
            dup->flags |= PTF_LVALUE;
#else
            dup = NodeConvertFlags( type, dup, PTF_LVALUE );
#endif
            if( sym_ctor != NULL && placement == NULL ) {
                dup = PtdNewAlloc( dup );
            }
            expr = EffectCtor( initial
                             , sym_ctor
                             , base_type
                             , dup
                             , &err_locn
                             , EFFECT_EXACT | EFFECT_VALUE_THIS );
            if( expr->op == PT_ERROR ) {
                NodeFreeDupedExpr( node );
                node = expr;
            } else {
                if( sym_ctor != NULL && placement == NULL ) {
                    FunctionHasRegistration();
                    expr = PtdNewCtor( expr, class_type );
                }
                expr = NodeConvert( new_expr_type, expr );
                node = newCheckForNULL( node, expr );
            }
        }
    }
    PTreeSetLocn( node, &err_locn );
    return( node );
}


static PTREE deleteCheckForNULL( PTREE value, PTREE t_expr )
{
    PTREE b_expr;
    PTREE f_expr;

    b_expr = NodeCompareToZero( value );
    f_expr = NodeOffset( 0 );
    return( NodeTestExpr( b_expr, t_expr, f_expr ) );
}


static PTREE setDeleteType( PTREE expr, TOKEN_LOCN *locn )
{
    expr = NodeConvertFlags( GetBasicType( TYP_VOID )
                           , expr
                           , PTF_MEANINGFUL | PTF_SIDE_EFF );
    PTreeSetLocn( expr, locn );
    return( expr );
}


PTREE AnalyseDelete(            // ANALYSE DELETE OPERATOR
    PTREE expr,                 // - delete expression
    boolean in_dtor )           // - TRUE ==> call from inside DTOR
{
    CGOP oper;                  // - operator (original)
    CGOP del_op;                // - delete operator class
    TYPE type;                  // - type of expression
    TYPE ptr_type;              // - pointer part of type
    TYPE pted;                  // - type pointed at
    TYPE cltype;                // - class type pointed at
    TYPE offset_type;           // - type of size to pass to op del()
    PTREE data;                 // - data to be deleted
    PTREE dup;                  // - duplicate of pointer value
    PTREE arg;                  // - temporary arg
    PTREE args;                 // - args for delete
    SCOPE class_scope;          // - scope of class type
    SCOPE opdel_scope;          // - scope to search op del for
    SYMBOL sym;                 // - symbol for delete routine
    CLASSINFO *info;            // - info part of delete type
    TOKEN_LOCN err_locn;        // - error location
    unsigned dtor_code;         // - code for DTOR routine
    unsigned num_args;          // - # of args for "op delete"
    struct {
      unsigned test_null:1;     // - TRUE ==> test for 0 address
      unsigned array_delete:1;  // - TRUE ==> delete[]
      unsigned inside_dtor:1;   // - TRUE ==> delete gening in DTOR
      unsigned num_in_alloc:1;  // - TRUE ==> number elements is in allocation
      unsigned really_dtorable:1;//- TRUE ==> non-trivial destructor req'd
      unsigned adjust_for_num:1;// - TRUE ==> subtract sizeof(int) from ptr
    } flag;

    flag.inside_dtor = in_dtor;
    oper = expr->cgop;
    flag.array_delete = ( oper == CO_DELETE_ARRAY || oper == CO_DELETE_G_ARRAY );
    data = expr->u.subtree[0];
    PTreeExtractLocn( expr, &err_locn );
    PTreeFree( expr );
    data = NodeRvalue( data );
    type = data->type;
    ptr_type = PointerType( type );
    if( ptr_type == NULL ) {
        PTreeErrorExpr( data, ERR_DLT_NOT_PTR_TO_DATA );
        return( data );
    }
    pted = ptr_type->of;
    if( TypeIsConst( pted ) ) {
        // 5.3.5 para 4 note
        PTreeErrorExpr( data, WARN_DLT_PTR_TO_CONST );
    }
    if( TypeTruncByMemModel( pted ) ) {
        PTreeErrorExpr( data, ERR_DLT_OBJ_MEM_MODEL  );
        return( data );
    }
    del_op = flag.array_delete ? CO_DELETE_ARRAY : CO_DELETE;
    flag.num_in_alloc = FALSE;
    pted = ArrayBaseType( pted );
    cltype = StructType( pted );
    if( cltype == NULL ) {
        /* simple type */
        if( FunctionDeclarationType( pted ) != NULL ) {
            PTreeErrorExpr( data, ERR_DLT_PTR_TO_FUNCTION );
            return( data );
        }
        opdel_scope = GetFileScope();
    } else {
        if( ! TypeDefined( cltype ) ) {
            // 5.3.5 para 5 can delete undef'd class ptr
            PTreeErrorExpr( data, WARN_CANT_DEL_UNDEFD );
        }
        info = cltype->u.c.info;
        class_scope = TypeScope( cltype );
        if( info->needs_dtor && ! flag.inside_dtor ) {
            /* class type needs a destructor */
            if( !info->needs_vdtor && ScopeHasVirtualFunctions( class_scope ) ) {
                /* possible problem: class has vfns but a non-virtual dtor */
                PTreeWarnExpr( data, WARN_VIRTUAL_DTOR_DELETE );
            }
        }
        opdel_scope = class_scope;
        switch( oper ) {
        case CO_DELETE_G_ARRAY:
            // find out what the op new side assumed
            accessDelete( del_op, opdel_scope, &num_args, NULL );
            if( num_args == 2 ) {
                flag.num_in_alloc = TRUE;
            }
            /* fall through */
        case CO_DELETE_G:
            opdel_scope = GetFileScope();
            break;
        }
    }
    sym = checkDeleteAccess( del_op, opdel_scope, &num_args, &err_locn, flag.inside_dtor );
    if( sym == NULL ) {
        PTreeErrorNode( data );
        return( data );
    }
    flag.test_null = FALSE;
    if( cltype == NULL ) {
        // delete a simple type; call op del() or op del []()
        args = NodeArgument( NULL, data );
        expr = NodeMakeCall( sym, GetBasicType( TYP_VOID ), args );
    } else {
        if( ! flag.inside_dtor && info->needs_vdtor ) {
            // call virtual dtor
            if( flag.array_delete ) {
                dtor_code = DTOR_DELETE_VECTOR;
            } else {
                dtor_code = DTOR_DELETE_THIS;
            }
            flag.test_null = TRUE;
            dup = data;
            data = NodeDupExpr( &dup );
            expr = AnalyseDtorCall( cltype, data, dtor_code );
        } else {
            target_size_t elem_size;    // - size of an element

            // cases:
            //  1 - simple delete
            //  2 - simple delete (needs dtor)
            //  3 - array delete
            //  4 - array delete (needs dtor)
            //  5 - simple delete (inside dtor)
            //  6 - array delete (inside dtor)

            elem_size = CgMemorySize( pted );
            if( ! ( flag.inside_dtor && oper == CO_DELETE ) && info->needs_dtor ) {
                // class needs a dtor
                // handle cases: 2, 4, 6
                flag.really_dtorable = TypeReallyDtorable( cltype );
                if( !flag.inside_dtor && !flag.really_dtorable ) {
                    // no dtor to call but check access anyway
                    // call to delete is done later in this code
                    // optimizes cases: 2, 4
                    ClassAccessDtor( cltype );
                    if( flag.array_delete ) {
                        flag.test_null = TRUE;
                        dup = data;
                        data = NodeDupExpr( &dup );
                        expr = NodeBinary( CO_MINUS, data, sizeOfUInt() );
                        expr->type = expr->u.subtree[0]->type;
                    } else {
                        expr = data;
                    }
                } else if( flag.array_delete ) {
                    // handle cases: 4, 6
                    boolean errors; // - errors accessing DTOR
                    TYPE_SIG* sig;  // - class type signature
                    sig = TypeSigFind( TSA_DTOR, cltype, &err_locn, &errors );
                    if( !errors ) {
                        if( num_args == 2 ) {
                            data = PtdDltDtorSize( data, elem_size );
                        }
                        data = PtdDltDtorArr( data, sym );
                        TypeSigReferenced( sig );
                        arg = NodeTypeSig( sig );
                        args = NodeArguments( arg, data, NULL );
                        expr = RunTimeCall( args, type, RTF_DTOR_AR_STORE );
                        expr = PtdDltDtorEnd( expr );
                    } else {
                        expr = data;
                    }
                } else {
                    // handle case: 2
                    flag.test_null = TRUE;
                    dup = data;
                    data = NodeDupExpr( &dup );
                    if( num_args == 2 ) {
                        data = PtdDltDtorSize( data, elem_size );
                    }
                    data = PtdDltDtorElm( data, sym );
                    dtor_code = DTOR_NULL;
                    expr = AnalyseDtorCall( cltype, data, dtor_code );
                    expr = PtdDltDtorEnd( expr );
                }
            } else {
                // no dtor call required
                // handle cases: 1, 3, 5
                if( flag.array_delete ) {
                    flag.adjust_for_num = FALSE;
                    if( num_args == 2 ) {
                        flag.adjust_for_num = TRUE;
                    } else if( flag.inside_dtor && oper == CO_DELETE_ARRAY ) {
                        flag.adjust_for_num = TRUE;
                    } else if( flag.num_in_alloc ) {
                        flag.adjust_for_num = TRUE;
                    }
                    if( flag.adjust_for_num ) {
                        flag.test_null = TRUE;
                        dup = data;
                        data = NodeDupExpr( &dup );
                        expr = NodeBinary( CO_MINUS, data, sizeOfUInt() );
                        expr->type = expr->u.subtree[0]->type;
                    } else {
                        expr = data;
                    }
                } else {
                    expr = data;
                }
            }
            if( num_args == 2 ) {
                args = NodeOffset( elem_size );
                if( flag.array_delete ) {
                    PTREE dup2;

                    // 'expr' must already be adjusted down by sizeof(unsigned)
                    dup2 = expr;
                    expr = NodeDupExpr( &dup2 );
                    expr = NodeConvert( MakeReferenceTo( GetBasicType( TYP_UINT ) )
                                      , expr );
                    args = NodeBinary( CO_TIMES, NodeRvalue( expr ), args );
                    offset_type = args->u.subtree[1]->type;
                    args->type = offset_type;
                    args = NodeBinary( CO_PLUS, args, sizeOfUInt() );
                    args->type = offset_type;
                    expr = dup2;
                    if( ! flag.test_null ) {
                        flag.test_null = TRUE;
                        dup = expr;
                        expr = NodeDupExpr( &dup );
                    }
                }
            } else {
                args = NULL;
            }
            if( args != NULL ) {
                args = NodeArg( args );
            }
            args = NodeArgument( args, expr );
            expr = NodeMakeCall( sym, GetBasicType( TYP_VOID ), args );
        }
    }
    if( flag.test_null ) {
        // 'dup' must be setup with a duplicate of the ptr expr
        expr = deleteCheckForNULL( dup, expr );
    }
    return setDeleteType( expr, &err_locn );
}

⌨️ 快捷键说明

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