diff options
author | Daniel Kraft <d@domob.eu> | 2008-07-29 11:11:51 +0200 |
---|---|---|
committer | Daniel Kraft <domob@gcc.gnu.org> | 2008-07-29 11:11:51 +0200 |
commit | 1fbfb0e27a982802abc2cdd4e5a7d5c4eff49f5e (patch) | |
tree | 1aab016d4f8bfcb5d507252ce55dbb189ec16514 /gcc/fortran | |
parent | 8c54989af547fdee4f47a176270d8bd3363e5132 (diff) | |
download | gcc-1fbfb0e27a982802abc2cdd4e5a7d5c4eff49f5e.zip gcc-1fbfb0e27a982802abc2cdd4e5a7d5c4eff49f5e.tar.gz gcc-1fbfb0e27a982802abc2cdd4e5a7d5c4eff49f5e.tar.bz2 |
re PR fortran/36403 (Some fortran tests using eoshift fail on SH)
2008-07-29 Daniel Kraft <d@domob.eu>
PR fortran/36403
* trans-intrinsic.c (conv_generic_with_optional_char_arg): New method
to append a string-length even if the string argument is missing, e.g.
for EOSHIFT.
(gfc_conv_intrinsic_function): Call the new method for EOSHIFT, PACK
and RESHAPE.
2008-07-29 Daniel Kraft <d@domob.eu>
PR fortran/36403
* gfortran.dg/char_eoshift_5.f90: New test.
* gfortran.dg/intrinsic_optional_char_arg_1.f90: New test.
From-SVN: r138234
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/fortran/trans-intrinsic.c | 83 |
2 files changed, 91 insertions, 1 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 7206263..b15bcfb 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,12 @@ +2008-07-29 Daniel Kraft <d@domob.eu> + + PR fortran/36403 + * trans-intrinsic.c (conv_generic_with_optional_char_arg): New method + to append a string-length even if the string argument is missing, e.g. + for EOSHIFT. + (gfc_conv_intrinsic_function): Call the new method for EOSHIFT, PACK + and RESHAPE. + 2008-07-28 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> * gfortran.h (try): Remove macro. Replace try with gfc_try diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index a56f4c1..bbb129d 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -2652,6 +2652,64 @@ gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr) se->expr = fold_build3 (COND_EXPR, type, tmp, args[0], rrot); } + +/* Process an intrinsic with unspecified argument-types that has an optional + argument (which could be of type character), e.g. EOSHIFT. For those, we + need to append the string length of the optional argument if it is not + present and the type is really character. + primary specifies the position (starting at 1) of the non-optional argument + specifying the type and optional gives the position of the optional + argument in the arglist. */ + +static void +conv_generic_with_optional_char_arg (gfc_se* se, gfc_expr* expr, + unsigned primary, unsigned optional) +{ + gfc_actual_arglist* prim_arg; + gfc_actual_arglist* opt_arg; + unsigned cur_pos; + gfc_actual_arglist* arg; + gfc_symbol* sym; + tree append_args; + + /* Find the two arguments given as position. */ + cur_pos = 0; + prim_arg = NULL; + opt_arg = NULL; + for (arg = expr->value.function.actual; arg; arg = arg->next) + { + ++cur_pos; + + if (cur_pos == primary) + prim_arg = arg; + if (cur_pos == optional) + opt_arg = arg; + + if (cur_pos >= primary && cur_pos >= optional) + break; + } + gcc_assert (prim_arg); + gcc_assert (prim_arg->expr); + gcc_assert (opt_arg); + + /* If we do have type CHARACTER and the optional argument is really absent, + append a dummy 0 as string length. */ + append_args = NULL_TREE; + if (prim_arg->expr->ts.type == BT_CHARACTER && !opt_arg->expr) + { + tree dummy; + + dummy = build_int_cst (gfc_charlen_type_node, 0); + append_args = gfc_chainon_list (append_args, dummy); + } + + /* Build the call itself. */ + sym = gfc_get_symbol_for_expr (expr); + gfc_conv_function_call (se, sym, expr->value.function.actual, append_args); + gfc_free (sym); +} + + /* The length of a character string. */ static void gfc_conv_intrinsic_len (gfc_se * se, gfc_expr * expr) @@ -4128,7 +4186,22 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) { if (lib == 1) se->ignore_optional = 1; - gfc_conv_intrinsic_funcall (se, expr); + + switch (expr->value.function.isym->id) + { + case GFC_ISYM_EOSHIFT: + case GFC_ISYM_PACK: + case GFC_ISYM_RESHAPE: + /* For all of those the first argument specifies the type and the + third is optional. */ + conv_generic_with_optional_char_arg (se, expr, 1, 3); + break; + + default: + gfc_conv_intrinsic_funcall (se, expr); + break; + } + return; } } @@ -4606,6 +4679,14 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_funcall (se, expr); break; + case GFC_ISYM_EOSHIFT: + case GFC_ISYM_PACK: + case GFC_ISYM_RESHAPE: + /* For those, expr->rank should always be >0 and thus the if above the + switch should have matched. */ + gcc_unreachable (); + break; + default: gfc_conv_intrinsic_lib_function (se, expr); break; |