diff options
author | Andre Vehreschild <vehre@gmx.de> | 2015-01-17 11:07:57 +0000 |
---|---|---|
committer | Paul Thomas <pault@gcc.gnu.org> | 2015-01-17 11:07:57 +0000 |
commit | adbfb3f8e04049409f9adcbc746fe43cc25f8a45 (patch) | |
tree | dceacc6b17bbb450a57dc347da50377d03f638f8 /gcc/fortran | |
parent | c39435736f0509200cb5f20022dc19bf722a98a0 (diff) | |
download | gcc-adbfb3f8e04049409f9adcbc746fe43cc25f8a45.zip gcc-adbfb3f8e04049409f9adcbc746fe43cc25f8a45.tar.gz gcc-adbfb3f8e04049409f9adcbc746fe43cc25f8a45.tar.bz2 |
re PR fortran/60334 (Segmentation fault on character pointer assignments)
2015-01-17 Andre Vehreschild <vehre@gmx.de>
PR fortran/60334
* trans-decl.c (gfc_get_symbol_decl):Use a ref on the string
length when the symbol is declared to be a result.
* trans-expr.c (gfc_conv_procedure_call): Strip deref on the
string length when functions are nested and the string length
is a reference already.
2015-01-17 Andre Vehreschild <vehre@gmx.de>
PR fortran/60334
* gfortran.dg/deferred_type_param_6.f90: Add tests for this PR.
From-SVN: r219798
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/fortran/trans-decl.c | 28 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.c | 16 |
3 files changed, 44 insertions, 9 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index c97de7f..eb02d88 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,12 @@ +2015-01-17 Andre Vehreschild <vehre@gmx.de> + + PR fortran/60334 + * trans-decl.c (gfc_get_symbol_decl):Use a ref on the string + length when the symbol is declared to be a result. + * trans-expr.c (gfc_conv_procedure_call): Strip deref on the + string length when functions are nested and the string length + is a reference already. + 2015-01-16 Janus Weil <janus@gcc.gnu.org> PR fortran/45290 diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index cad9b5b..a73620f 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -1370,12 +1370,30 @@ gfc_get_symbol_decl (gfc_symbol * sym) (sym->ts.u.cl->passed_length == sym->ts.u.cl->backend_decl)) sym->ts.u.cl->backend_decl = NULL_TREE; - if (sym->ts.deferred && fun_or_res - && sym->ts.u.cl->passed_length == NULL - && sym->ts.u.cl->backend_decl) + if (sym->ts.deferred && byref) { - sym->ts.u.cl->passed_length = sym->ts.u.cl->backend_decl; - sym->ts.u.cl->backend_decl = NULL_TREE; + /* The string length of a deferred char array is stored in the + parameter at sym->ts.u.cl->backend_decl as a reference and + marked as a result. Exempt this variable from generating a + temporary for it. */ + if (sym->attr.result) + { + /* We need to insert a indirect ref for param decls. */ + if (sym->ts.u.cl->backend_decl + && TREE_CODE (sym->ts.u.cl->backend_decl) == PARM_DECL) + sym->ts.u.cl->backend_decl = + build_fold_indirect_ref (sym->ts.u.cl->backend_decl); + } + /* For all other parameters make sure, that they are copied so + that the value and any modifications are local to the routine + by generating a temporary variable. */ + else if (sym->attr.function + && sym->ts.u.cl->passed_length == NULL + && sym->ts.u.cl->backend_decl) + { + sym->ts.u.cl->passed_length = sym->ts.u.cl->backend_decl; + sym->ts.u.cl->backend_decl = NULL_TREE; + } } if (sym->ts.u.cl->backend_decl == NULL_TREE) diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 5ebf3abb..420d6ad 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -5010,10 +5010,18 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, so that the value can be returned. */ if (parmse.string_length && fsym && fsym->ts.deferred) { - tmp = parmse.string_length; - if (TREE_CODE (tmp) != VAR_DECL) - tmp = gfc_evaluate_now (parmse.string_length, &se->pre); - parmse.string_length = gfc_build_addr_expr (NULL_TREE, tmp); + if (INDIRECT_REF_P (parmse.string_length)) + /* In chains of functions/procedure calls the string_length already + is a pointer to the variable holding the length. Therefore + remove the deref on call. */ + parmse.string_length = TREE_OPERAND (parmse.string_length, 0); + else + { + tmp = parmse.string_length; + if (TREE_CODE (tmp) != VAR_DECL) + tmp = gfc_evaluate_now (parmse.string_length, &se->pre); + parmse.string_length = gfc_build_addr_expr (NULL_TREE, tmp); + } } /* Character strings are passed as two parameters, a length and a |