diff options
author | Janus Weil <janus@gcc.gnu.org> | 2011-01-07 13:08:21 +0100 |
---|---|---|
committer | Janus Weil <janus@gcc.gnu.org> | 2011-01-07 13:08:21 +0100 |
commit | 0d87fa8ca8f0ccf7184e7606d60693530d0c4a13 (patch) | |
tree | 023ebc065d893b6ac71d6d6906442cf961c2e194 /gcc | |
parent | a14e516339b8d3b5a3a35ec1c6e33e74019bb576 (diff) | |
download | gcc-0d87fa8ca8f0ccf7184e7606d60693530d0c4a13.tar.gz |
re PR fortran/47189 ([OOP] calling STORAGE_SIZE on a NULL-initialized class pointer)
2011-01-07 Janus Weil <janus@gcc.gnu.org>
PR fortran/47189
PR fortran/47194
* gfortran.h (gfc_lval_expr_from_sym): Moved prototype.
* class.c (gfc_class_null_initializer): Initialize _vptr to declared
type.
* expr.c (gfc_lval_expr_from_sym): Moved here from symbol.c.
* resolve.c (resolve_deallocate_expr): _data component will be added
at translation stage.
* symbol.c (gfc_lval_expr_from_sym): Moved to expr.c.
* trans-stmt.c (gfc_trans_deallocate): Reset _vptr to declared type.
2011-01-07 Janus Weil <janus@gcc.gnu.org>
PR fortran/47189
PR fortran/47194
* gfortran.dg/storage_size_3.f08: Extended.
From-SVN: r168565
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/fortran/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/fortran/class.c | 10 | ||||
-rw-r--r-- | gcc/fortran/expr.c | 26 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 3 | ||||
-rw-r--r-- | gcc/fortran/resolve.c | 6 | ||||
-rw-r--r-- | gcc/fortran/symbol.c | 29 | ||||
-rw-r--r-- | gcc/fortran/trans-stmt.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/storage_size_3.f08 | 15 |
9 files changed, 88 insertions, 46 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 3181e5e1a35..aadd14326d9 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,16 @@ +2011-01-07 Janus Weil <janus@gcc.gnu.org> + + PR fortran/47189 + PR fortran/47194 + * gfortran.h (gfc_lval_expr_from_sym): Moved prototype. + * class.c (gfc_class_null_initializer): Initialize _vptr to declared + type. + * expr.c (gfc_lval_expr_from_sym): Moved here from symbol.c. + * resolve.c (resolve_deallocate_expr): _data component will be added + at translation stage. + * symbol.c (gfc_lval_expr_from_sym): Moved to expr.c. + * trans-stmt.c (gfc_trans_deallocate): Reset _vptr to declared type. + 2011-01-06 Daniel Franke <franke.daniel@gmail.com> PR fortran/33117 diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c index 7095d3ea752..d07df87b088 100644 --- a/gcc/fortran/class.c +++ b/gcc/fortran/class.c @@ -83,7 +83,8 @@ gfc_add_component_ref (gfc_expr *e, const char *name) /* Build a NULL initializer for CLASS pointers, - initializing the _data and _vptr components to zero. */ + initializing the _data component to NULL and + the _vptr component to the declared type. */ gfc_expr * gfc_class_null_initializer (gfc_typespec *ts) @@ -98,9 +99,10 @@ gfc_class_null_initializer (gfc_typespec *ts) for (comp = ts->u.derived->components; comp; comp = comp->next) { gfc_constructor *ctor = gfc_constructor_get(); - ctor->expr = gfc_get_expr (); - ctor->expr->expr_type = EXPR_NULL; - ctor->expr->ts = comp->ts; + if (strcmp (comp->name, "_vptr") == 0) + ctor->expr = gfc_lval_expr_from_sym (gfc_find_derived_vtab (ts->u.derived)); + else + ctor->expr = gfc_get_null_expr (NULL); gfc_constructor_append (&init->value.constructor, ctor); } diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index a222ff20fac..e331b5b2cf7 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -3707,6 +3707,32 @@ gfc_get_variable_expr (gfc_symtree *var) } +gfc_expr * +gfc_lval_expr_from_sym (gfc_symbol *sym) +{ + gfc_expr *lval; + lval = gfc_get_expr (); + lval->expr_type = EXPR_VARIABLE; + lval->where = sym->declared_at; + lval->ts = sym->ts; + lval->symtree = gfc_find_symtree (sym->ns->sym_root, sym->name); + + /* It will always be a full array. */ + lval->rank = sym->as ? sym->as->rank : 0; + if (lval->rank) + { + lval->ref = gfc_get_ref (); + lval->ref->type = REF_ARRAY; + lval->ref->u.ar.type = AR_FULL; + lval->ref->u.ar.dimen = lval->rank; + lval->ref->u.ar.where = sym->declared_at; + lval->ref->u.ar.as = sym->as; + } + + return lval; +} + + /* Returns the array_spec of a full array expression. A NULL is returned otherwise. */ gfc_array_spec * diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index b18a43db414..d4443ecc68f 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2536,8 +2536,6 @@ void gfc_free_st_label (gfc_st_label *); void gfc_define_st_label (gfc_st_label *, gfc_sl_type, locus *); gfc_try gfc_reference_st_label (gfc_st_label *, gfc_sl_type); -gfc_expr * gfc_lval_expr_from_sym (gfc_symbol *); - gfc_namespace *gfc_get_namespace (gfc_namespace *, int); gfc_symtree *gfc_new_symtree (gfc_symtree **, const char *); gfc_symtree *gfc_find_symtree (gfc_symtree *, const char *); @@ -2701,6 +2699,7 @@ gfc_try gfc_check_assign_symbol (gfc_symbol *, gfc_expr *); bool gfc_has_default_initializer (gfc_symbol *); gfc_expr *gfc_default_initializer (gfc_typespec *); gfc_expr *gfc_get_variable_expr (gfc_symtree *); +gfc_expr * gfc_lval_expr_from_sym (gfc_symbol *); gfc_array_spec *gfc_get_full_arrayspec_from_expr (gfc_expr *expr); diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 28fec7d9b43..1d8a7b6a2e7 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -6417,12 +6417,6 @@ resolve_deallocate_expr (gfc_expr *e) if (gfc_check_vardef_context (e, false, _("DEALLOCATE object")) == FAILURE) return FAILURE; - if (e->ts.type == BT_CLASS) - { - /* Only deallocate the DATA component. */ - gfc_add_data_component (e); - } - return SUCCESS; } diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index 283bfce796b..998eac9b3df 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -2245,35 +2245,6 @@ done: } -/*******A helper function for creating new expressions*************/ - - -gfc_expr * -gfc_lval_expr_from_sym (gfc_symbol *sym) -{ - gfc_expr *lval; - lval = gfc_get_expr (); - lval->expr_type = EXPR_VARIABLE; - lval->where = sym->declared_at; - lval->ts = sym->ts; - lval->symtree = gfc_find_symtree (sym->ns->sym_root, sym->name); - - /* It will always be a full array. */ - lval->rank = sym->as ? sym->as->rank : 0; - if (lval->rank) - { - lval->ref = gfc_get_ref (); - lval->ref->type = REF_ARRAY; - lval->ref->u.ar.type = AR_FULL; - lval->ref->u.ar.dimen = lval->rank; - lval->ref->u.ar.where = sym->declared_at; - lval->ref->u.ar.as = sym->as; - } - - return lval; -} - - /************** Symbol table management subroutines ****************/ /* Basic details: Fortran 95 requires a potentially unlimited number diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index c64b5f2bcd9..5f6b1d07e74 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -4738,7 +4738,6 @@ gfc_trans_deallocate (gfc_code *code) { gfc_se se; gfc_alloc *al; - gfc_expr *expr; tree apstat, astat, pstat, stat, tmp; stmtblock_t block; @@ -4766,9 +4765,12 @@ gfc_trans_deallocate (gfc_code *code) for (al = code->ext.alloc.list; al != NULL; al = al->next) { - expr = al->expr; + gfc_expr *expr = gfc_copy_expr (al->expr); gcc_assert (expr->expr_type == EXPR_VARIABLE); + if (expr->ts.type == BT_CLASS) + gfc_add_data_component (expr); + gfc_init_se (&se, NULL); gfc_start_block (&se.pre); @@ -4797,6 +4799,7 @@ gfc_trans_deallocate (gfc_code *code) } } tmp = gfc_array_deallocate (se.expr, pstat, expr); + gfc_add_expr_to_block (&se.pre, tmp); } else { @@ -4804,13 +4807,26 @@ gfc_trans_deallocate (gfc_code *code) expr, expr->ts); gfc_add_expr_to_block (&se.pre, tmp); + /* Set to zero after deallocation. */ tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, se.expr, build_int_cst (TREE_TYPE (se.expr), 0)); + gfc_add_expr_to_block (&se.pre, tmp); + + if (al->expr->ts.type == BT_CLASS) + { + /* Reset _vptr component to declared type. */ + gfc_expr *rhs, *lhs = gfc_copy_expr (al->expr); + gfc_symbol *vtab = gfc_find_derived_vtab (al->expr->ts.u.derived); + gfc_add_vptr_component (lhs); + rhs = gfc_lval_expr_from_sym (vtab); + tmp = gfc_trans_pointer_assignment (lhs, rhs); + gfc_add_expr_to_block (&se.pre, tmp); + gfc_free_expr (lhs); + gfc_free_expr (rhs); + } } - gfc_add_expr_to_block (&se.pre, tmp); - /* Keep track of the number of failed deallocations by adding stat of the last deallocation to the running total. */ if (code->expr1 || code->expr2) @@ -4822,7 +4838,7 @@ gfc_trans_deallocate (gfc_code *code) tmp = gfc_finish_block (&se.pre); gfc_add_expr_to_block (&block, tmp); - + gfc_free_expr (expr); } /* Set STAT. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2bab56a9ded..49e7001d00b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-01-07 Janus Weil <janus@gcc.gnu.org> + + PR fortran/47189 + PR fortran/47194 + * gfortran.dg/storage_size_3.f08: Extended. + 2011-01-07 Jakub Jelinek <jakub@redhat.com> PR c++/47022 diff --git a/gcc/testsuite/gfortran.dg/storage_size_3.f08 b/gcc/testsuite/gfortran.dg/storage_size_3.f08 index 71f50112de1..57b50af5610 100644 --- a/gcc/testsuite/gfortran.dg/storage_size_3.f08 +++ b/gcc/testsuite/gfortran.dg/storage_size_3.f08 @@ -1,12 +1,27 @@ ! { dg-do run } ! ! PR 47024: [OOP] STORAGE_SIZE (for polymorphic types): Segfault at run time +! PR 47189: [OOP] calling STORAGE_SIZE on a NULL-initialized class pointer +! PR 47194: [OOP] EXTENDS_TYPE_OF still returns the wrong result if the polymorphic variable is unallocated ! ! Contributed by Tobias Burnus <burnus@gcc.gnu.org> type t integer(kind=4) :: a end type + +class(t), pointer :: x => null() class(t), allocatable :: y + +if (storage_size(x)/=32) call abort() +if (storage_size(y)/=32) call abort() + +allocate(y) + if (storage_size(y)/=32) call abort() + +deallocate(y) + +if (storage_size(y)/=32) call abort() + end |