diff options
Diffstat (limited to 'gcc/fortran/trans-stmt.c')
-rw-r--r-- | gcc/fortran/trans-stmt.c | 104 |
1 files changed, 71 insertions, 33 deletions
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index 1da3a06..75d72a2 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -4686,8 +4686,10 @@ gfc_trans_allocate (gfc_code * code) tree tmp; tree parm; tree stat; - tree pstat; - tree error_label; + tree errmsg; + tree errlen; + tree label_errmsg; + tree label_finish; tree memsz; tree expr3; tree slen3; @@ -4699,21 +4701,39 @@ gfc_trans_allocate (gfc_code * code) if (!code->ext.alloc.list) return NULL_TREE; - pstat = stat = error_label = tmp = memsz = NULL_TREE; + stat = tmp = memsz = NULL_TREE; + label_errmsg = label_finish = errmsg = errlen = NULL_TREE; gfc_init_block (&block); gfc_init_block (&post); - /* Either STAT= and/or ERRMSG is present. */ - if (code->expr1 || code->expr2) + /* STAT= (and maybe ERRMSG=) is present. */ + if (code->expr1) { + /* STAT=. */ tree gfc_int4_type_node = gfc_get_int_type (4); - stat = gfc_create_var (gfc_int4_type_node, "stat"); - pstat = gfc_build_addr_expr (NULL_TREE, stat); - error_label = gfc_build_label_decl (NULL_TREE); - TREE_USED (error_label) = 1; + /* ERRMSG= only makes sense with STAT=. */ + if (code->expr2) + { + gfc_init_se (&se, NULL); + gfc_conv_expr_lhs (&se, code->expr2); + + errlen = gfc_get_expr_charlen (code->expr2); + errmsg = gfc_build_addr_expr (pchar_type_node, se.expr); + } + else + { + errmsg = null_pointer_node; + errlen = build_int_cst (gfc_charlen_type_node, 0); + } + + /* GOTO destinations. */ + label_errmsg = gfc_build_label_decl (NULL_TREE); + label_finish = gfc_build_label_decl (NULL_TREE); + TREE_USED (label_errmsg) = 1; + TREE_USED (label_finish) = 1; } expr3 = NULL_TREE; @@ -4732,7 +4752,7 @@ gfc_trans_allocate (gfc_code * code) se.descriptor_only = 1; gfc_conv_expr (&se, expr); - if (!gfc_array_allocate (&se, expr, pstat)) + if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen)) { /* A scalar or derived type. */ @@ -4847,28 +4867,16 @@ gfc_trans_allocate (gfc_code * code) /* Allocate - for non-pointers with re-alloc checking. */ if (gfc_expr_attr (expr).allocatable) - tmp = gfc_allocate_allocatable_with_status (&se.pre, se.expr, memsz, - pstat, expr); + tmp = gfc_allocate_allocatable (&se.pre, se.expr, memsz, + stat, errmsg, errlen, expr); else - tmp = gfc_allocate_with_status (&se.pre, memsz, pstat, false); + tmp = gfc_allocate_using_malloc (&se.pre, memsz, stat); tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, se.expr, fold_convert (TREE_TYPE (se.expr), tmp)); gfc_add_expr_to_block (&se.pre, tmp); - if (code->expr1 || code->expr2) - { - tmp = build1_v (GOTO_EXPR, error_label); - parm = fold_build2_loc (input_location, NE_EXPR, - boolean_type_node, stat, - build_int_cst (TREE_TYPE (stat), 0)); - tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, - parm, tmp, - build_empty_stmt (input_location)); - gfc_add_expr_to_block (&se.pre, tmp); - } - if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp) { tmp = build_fold_indirect_ref_loc (input_location, se.expr); @@ -4879,6 +4887,25 @@ gfc_trans_allocate (gfc_code * code) gfc_add_block_to_block (&block, &se.pre); + /* Error checking -- Note: ERRMSG only makes sense with STAT. */ + if (code->expr1) + { + /* The coarray library already sets the errmsg. */ + if (gfc_option.coarray == GFC_FCOARRAY_LIB + && gfc_expr_attr (expr).codimension) + tmp = build1_v (GOTO_EXPR, label_finish); + else + tmp = build1_v (GOTO_EXPR, label_errmsg); + + parm = fold_build2_loc (input_location, NE_EXPR, + boolean_type_node, stat, + build_int_cst (TREE_TYPE (stat), 0)); + tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, + parm, tmp, + build_empty_stmt (input_location)); + gfc_add_expr_to_block (&block, tmp); + } + if (code->expr3 && !code->expr3->mold) { /* Initialization via SOURCE block @@ -5005,16 +5032,11 @@ gfc_trans_allocate (gfc_code * code) } - /* STAT block. */ + /* STAT (ERRMSG only makes sense with STAT). */ if (code->expr1) { - tmp = build1_v (LABEL_EXPR, error_label); + tmp = build1_v (LABEL_EXPR, label_errmsg); gfc_add_expr_to_block (&block, tmp); - - gfc_init_se (&se, NULL); - gfc_conv_expr_lhs (&se, code->expr1); - tmp = convert (TREE_TYPE (se.expr), stat); - gfc_add_modify (&block, se.expr, tmp); } /* ERRMSG block. */ @@ -5022,7 +5044,7 @@ gfc_trans_allocate (gfc_code * code) { /* A better error message may be possible, but not required. */ const char *msg = "Attempt to allocate an allocated object"; - tree errmsg, slen, dlen; + tree slen, dlen; gfc_init_se (&se, NULL); gfc_conv_expr_lhs (&se, code->expr2); @@ -5050,6 +5072,22 @@ gfc_trans_allocate (gfc_code * code) gfc_add_expr_to_block (&block, tmp); } + /* STAT (ERRMSG only makes sense with STAT). */ + if (code->expr1) + { + tmp = build1_v (LABEL_EXPR, label_finish); + gfc_add_expr_to_block (&block, tmp); + } + + /* STAT block. */ + if (code->expr1) + { + gfc_init_se (&se, NULL); + gfc_conv_expr_lhs (&se, code->expr1); + tmp = convert (TREE_TYPE (se.expr), stat); + gfc_add_modify (&block, se.expr, tmp); + } + gfc_add_block_to_block (&block, &se.post); gfc_add_block_to_block (&block, &post); |