diff options
author | Tobias Burnus <burnus@net-b.de> | 2008-07-27 12:45:44 +0200 |
---|---|---|
committer | Tobias Burnus <burnus@gcc.gnu.org> | 2008-07-27 12:45:44 +0200 |
commit | 0d52899f78e638f7a5e2a50954d3740d68907a91 (patch) | |
tree | d3c2ffda8f3516e7c1760aaa7f36971d80e86958 /gcc/fortran/trans-array.c | |
parent | 5aab248830d3a030530dfa49a9f9b0f97178a74f (diff) | |
download | gcc-0d52899f78e638f7a5e2a50954d3740d68907a91.zip gcc-0d52899f78e638f7a5e2a50954d3740d68907a91.tar.gz gcc-0d52899f78e638f7a5e2a50954d3740d68907a91.tar.bz2 |
re PR fortran/36132 (_gfortran_internal_pack on optional arguments)
2008-07-27 Tobias Burnus <burnus@net-b.de>
PR fortran/36132
PR fortran/29952
PR fortran/36909
* trans.c (gfc_trans_runtime_check): Allow run-time warning
* besides
run-time error.
* trans.h (gfc_trans_runtime_check): Update declaration.
* trans-array.c
* (gfc_trans_array_ctor_element,gfc_trans_array_bound_check,
gfc_conv_array_ref,gfc_conv_ss_startstride,gfc_trans_dummy_array_bias):
Updated gfc_trans_runtime_check calls.
(gfc_conv_array_parameter): Implement flag_check_array_temporaries,
fix packing/unpacking for nonpresent optional actuals to optional
formals.
* trans-array.h (gfc_conv_array_parameter): Update declaration.
* trans-expr.c (gfc_conv_substring,gfc_trans_arrayfunc_assign,
gfc_conv_function_call): Updated gfc_trans_runtime_check calls.
(gfc_conv_function_call): Update gfc_conv_array_parameter calls.
* trans-expr.c (gfc_trans_goto): Updated gfc_trans_runtime_check
calls.
* trans-io.c (set_string,gfc_conv_intrinsic_repeat): Ditto.
(gfc_conv_intrinsic_transfer,gfc_conv_intrinsic_loc): Same for
gfc_conv_array_parameter.
* trans-intrinsics.c (gfc_conv_intrinsic_bound): Ditto.
* trans-decl.c (gfc_build_builtin_function_decls): Add
gfor_fndecl_runtime_warning_at.
* lang.opt: New option fcheck-array-temporaries.
* gfortran.h (gfc_options): New flag_check_array_temporaries.
* options.c (gfc_init_options, gfc_handle_option): Handle flag.
* invoke.texi: New option fcheck-array-temporaries.
2008-07-27 Tobias Burnus <burnus@net-b.de>
PR fortran/36132
PR fortran/29952
PR fortran/36909
* runtime/error.c: New function runtime_error_at.
* gfortran.map: Ditto.
* libgfortran.h: Ditto.
2008-07-27 Tobias Burnus <burnus@net-b.de>
PR fortran/36132
PR fortran/29952
PR fortran/36909
gfortran.dg/internal_pack_4.f90: New.
gfortran.dg/internal_pack_5.f90: New.
gfortran.dg/array_temporaries_2.f90: New.
From-SVN: r138186
Diffstat (limited to 'gcc/fortran/trans-array.c')
-rw-r--r-- | gcc/fortran/trans-array.c | 86 |
1 files changed, 70 insertions, 16 deletions
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 9ec8406..14bab8e 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -1022,7 +1022,7 @@ gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc, tree cond = fold_build2 (NE_EXPR, boolean_type_node, first_len_val, se->string_length); gfc_trans_runtime_check - (cond, &se->pre, &expr->where, + (true, false, cond, &se->pre, &expr->where, "Different CHARACTER lengths (%ld/%ld) in array constructor", fold_convert (long_integer_type_node, first_len_val), fold_convert (long_integer_type_node, se->string_length)); @@ -2235,7 +2235,7 @@ gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n, else asprintf (&msg, "%s, lower bound of dimension %d exceeded (%%ld < %%ld)", gfc_msg_fault, n+1); - gfc_trans_runtime_check (fault, &se->pre, where, msg, + gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg, fold_convert (long_integer_type_node, index), fold_convert (long_integer_type_node, tmp)); gfc_free (msg); @@ -2251,7 +2251,7 @@ gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n, else asprintf (&msg, "%s, upper bound of dimension %d exceeded (%%ld > %%ld)", gfc_msg_fault, n+1); - gfc_trans_runtime_check (fault, &se->pre, where, msg, + gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg, fold_convert (long_integer_type_node, index), fold_convert (long_integer_type_node, tmp)); gfc_free (msg); @@ -2445,7 +2445,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym, asprintf (&msg, "%s for array '%s', " "lower bound of dimension %d exceeded (%%ld < %%ld)", gfc_msg_fault, sym->name, n+1); - gfc_trans_runtime_check (cond, &se->pre, where, msg, + gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg, fold_convert (long_integer_type_node, indexse.expr), fold_convert (long_integer_type_node, tmp)); @@ -2462,7 +2462,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym, asprintf (&msg, "%s for array '%s', " "upper bound of dimension %d exceeded (%%ld > %%ld)", gfc_msg_fault, sym->name, n+1); - gfc_trans_runtime_check (cond, &se->pre, where, msg, + gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg, fold_convert (long_integer_type_node, indexse.expr), fold_convert (long_integer_type_node, tmp)); @@ -3026,7 +3026,8 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop) asprintf (&msg, "Zero stride is not allowed, for dimension %d " "of array '%s'", info->dim[n]+1, ss->expr->symtree->name); - gfc_trans_runtime_check (tmp, &inner, &ss->expr->where, msg); + gfc_trans_runtime_check (true, false, tmp, &inner, + &ss->expr->where, msg); gfc_free (msg); desc = ss->data.info.descriptor; @@ -3068,7 +3069,8 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop) asprintf (&msg, "%s, lower bound of dimension %d of array '%s'" " exceeded (%%ld < %%ld)", gfc_msg_fault, info->dim[n]+1, ss->expr->symtree->name); - gfc_trans_runtime_check (tmp, &inner, &ss->expr->where, msg, + gfc_trans_runtime_check (true, false, tmp, &inner, + &ss->expr->where, msg, fold_convert (long_integer_type_node, info->start[n]), fold_convert (long_integer_type_node, @@ -3084,7 +3086,8 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop) asprintf (&msg, "%s, upper bound of dimension %d of array " "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault, info->dim[n]+1, ss->expr->symtree->name); - gfc_trans_runtime_check (tmp, &inner, &ss->expr->where, msg, + gfc_trans_runtime_check (true, false, tmp, &inner, + &ss->expr->where, msg, fold_convert (long_integer_type_node, info->start[n]), fold_convert (long_integer_type_node, ubound)); gfc_free (msg); @@ -3106,7 +3109,8 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop) asprintf (&msg, "%s, lower bound of dimension %d of array '%s'" " exceeded (%%ld < %%ld)", gfc_msg_fault, info->dim[n]+1, ss->expr->symtree->name); - gfc_trans_runtime_check (tmp, &inner, &ss->expr->where, msg, + gfc_trans_runtime_check (true, false, tmp, &inner, + &ss->expr->where, msg, fold_convert (long_integer_type_node, tmp2), fold_convert (long_integer_type_node, @@ -3121,7 +3125,8 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop) asprintf (&msg, "%s, upper bound of dimension %d of array " "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault, info->dim[n]+1, ss->expr->symtree->name); - gfc_trans_runtime_check (tmp, &inner, &ss->expr->where, msg, + gfc_trans_runtime_check (true, false, tmp, &inner, + &ss->expr->where, msg, fold_convert (long_integer_type_node, tmp2), fold_convert (long_integer_type_node, ubound)); gfc_free (msg); @@ -3144,7 +3149,8 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop) asprintf (&msg, "%s, size mismatch for dimension %d " "of array '%s' (%%ld/%%ld)", gfc_msg_bounds, info->dim[n]+1, ss->expr->symtree->name); - gfc_trans_runtime_check (tmp3, &inner, &ss->expr->where, msg, + gfc_trans_runtime_check (true, false, tmp3, &inner, + &ss->expr->where, msg, fold_convert (long_integer_type_node, tmp), fold_convert (long_integer_type_node, size[n])); gfc_free (msg); @@ -4383,7 +4389,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body) tmp = fold_build2 (NE_EXPR, gfc_array_index_type, tmp, stride2); asprintf (&msg, "%s for dimension %d of array '%s'", gfc_msg_bounds, n+1, sym->name); - gfc_trans_runtime_check (tmp, &block, &loc, msg); + gfc_trans_runtime_check (true, false, tmp, &block, &loc, msg); gfc_free (msg); } } @@ -5133,7 +5139,8 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) /* TODO: Optimize passing g77 arrays. */ void -gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77) +gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77, + const gfc_symbol *fsym, const char *proc_name) { tree ptr; tree desc; @@ -5230,17 +5237,59 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77) /* Repack the array. */ if (gfc_option.warn_array_temp) - gfc_warning ("Creating array temporary at %L", &expr->where); + { + if (fsym) + gfc_warning ("Creating array temporary at %L for argument '%s'", + &expr->where, fsym->name); + else + gfc_warning ("Creating array temporary at %L", &expr->where); + } ptr = build_call_expr (gfor_fndecl_in_pack, 1, desc); + + if (fsym && fsym->attr.optional && sym && sym->attr.optional) + { + tmp = gfc_conv_expr_present (sym); + ptr = build3 (COND_EXPR, TREE_TYPE (se->expr), tmp, ptr, + null_pointer_node); + } + ptr = gfc_evaluate_now (ptr, &se->pre); + se->expr = ptr; + if (gfc_option.flag_check_array_temporaries) + { + char * msg; + + if (fsym && proc_name) + asprintf (&msg, "An array temporary was created for argument " + "'%s' of procedure '%s'", fsym->name, proc_name); + else + asprintf (&msg, "An array temporary was created"); + + tmp = build_fold_indirect_ref (desc); + tmp = gfc_conv_array_data (tmp); + tmp = fold_build2 (NE_EXPR, boolean_type_node, + fold_convert (TREE_TYPE (tmp), ptr), tmp); + + if (fsym && fsym->attr.optional && sym && sym->attr.optional) + tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, + gfc_conv_expr_present (sym), tmp); + + gfc_trans_runtime_check (false, true, tmp, &se->pre, + &expr->where, msg); + gfc_free (msg); + } + gfc_start_block (&block); /* Copy the data back. */ - tmp = build_call_expr (gfor_fndecl_in_unpack, 2, desc, ptr); - gfc_add_expr_to_block (&block, tmp); + if (fsym == NULL || fsym->attr.intent != INTENT_IN) + { + tmp = build_call_expr (gfor_fndecl_in_unpack, 2, desc, ptr); + gfc_add_expr_to_block (&block, tmp); + } /* Free the temporary. */ tmp = gfc_call_free (convert (pvoid_type_node, ptr)); @@ -5255,6 +5304,11 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77) tmp = gfc_conv_array_data (tmp); tmp = fold_build2 (NE_EXPR, boolean_type_node, fold_convert (TREE_TYPE (tmp), ptr), tmp); + + if (fsym && fsym->attr.optional && sym && sym->attr.optional) + tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, + gfc_conv_expr_present (sym), tmp); + tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ()); gfc_add_expr_to_block (&block, tmp); |