Commit 8ae1ec92 by Alessandro Fanfarillo Committed by Tobias Burnus

re PR fortran/52158 (Regression on character function with gfortran 4.7)

2012-05-13  Alessandro Fanfarillo  <fanfarillo.gcc@gmail.com>
            Tobias Burnus  <burnus@net-b.de>

        PR fortran/52158
        PR fortran/45170
        PR fortran/49430
        * resolve.c (resolve_fl_derived0): Deferred character length 
        procedure components are supported.
        * trans-expr.c (gfc_conv_procedure_call): Handle TBP with 
        deferred-length results.
        (gfc_string_to_single_character): Add a new check to prevent
        NULL read.
        (gfc_conv_procedure_call): Remove unuseful checks on 
        symbol's attributes. Add new checks to prevent NULL read on
        string length. 

2012-05-13  Alessandro Fanfarillo  <fanfarillo.gcc@gmail.com>

        PR fortran/45170
        * gfortran.dg/deferred_type_param_3.f90: New.
        * gfortran.dg/deferred_type_proc_pointer_1.f90: New.
        * gfortran.dg/deferred_type_proc_pointer_2.f90: New.


Co-Authored-By: Tobias Burnus <burnus@net-b.de>

From-SVN: r187436
parent bf4c7d4a
2012-05-13 Alessandro Fanfarillo <fanfarillo.gcc@gmail.com>
Tobias Burnus <burnus@net-b.de>
PR fortran/52158
PR fortran/45170
PR fortran/49430
* resolve.c (resolve_fl_derived0): Deferred character length
procedure components are supported.
* trans-expr.c (gfc_conv_procedure_call): Handle TBP with
deferred-length results.
(gfc_string_to_single_character): Add a new check to prevent
NULL read.
(gfc_conv_procedure_call): Remove unuseful checks on
symbol's attributes. Add new checks to prevent NULL read on
string length.
2012-05-12 Tobias Burnus <burnus@net-b.de> 2012-05-12 Tobias Burnus <burnus@net-b.de>
PR fortran/49110 PR fortran/49110
......
...@@ -11665,7 +11665,7 @@ resolve_fl_derived0 (gfc_symbol *sym) ...@@ -11665,7 +11665,7 @@ resolve_fl_derived0 (gfc_symbol *sym)
for ( ; c != NULL; c = c->next) for ( ; c != NULL; c = c->next)
{ {
/* See PRs 51550, 47545, 48654, 49050, 51075 - and 45170. */ /* See PRs 51550, 47545, 48654, 49050, 51075 - and 45170. */
if (c->ts.type == BT_CHARACTER && c->ts.deferred) if (c->ts.type == BT_CHARACTER && c->ts.deferred && !c->attr.function)
{ {
gfc_error ("Deferred-length character component '%s' at %L is not " gfc_error ("Deferred-length character component '%s' at %L is not "
"yet supported", c->name, &c->loc); "yet supported", c->name, &c->loc);
......
...@@ -2073,7 +2073,8 @@ tree ...@@ -2073,7 +2073,8 @@ tree
gfc_string_to_single_character (tree len, tree str, int kind) gfc_string_to_single_character (tree len, tree str, int kind)
{ {
if (!INTEGER_CST_P (len) || TREE_INT_CST_HIGH (len) != 0 if (len == NULL
|| !INTEGER_CST_P (len) || TREE_INT_CST_HIGH (len) != 0
|| !POINTER_TYPE_P (TREE_TYPE (str))) || !POINTER_TYPE_P (TREE_TYPE (str)))
return NULL_TREE; return NULL_TREE;
...@@ -4175,7 +4176,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, ...@@ -4175,7 +4176,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
we take the character length of the first argument for the result. we take the character length of the first argument for the result.
For dummies, we have to look through the formal argument list for For dummies, we have to look through the formal argument list for
this function and use the character length found there.*/ this function and use the character length found there.*/
if (ts.deferred && (sym->attr.allocatable || sym->attr.pointer)) if (ts.deferred)
cl.backend_decl = gfc_create_var (gfc_charlen_type_node, "slen"); cl.backend_decl = gfc_create_var (gfc_charlen_type_node, "slen");
else if (!sym->attr.dummy) else if (!sym->attr.dummy)
cl.backend_decl = VEC_index (tree, stringargs, 0); cl.backend_decl = VEC_index (tree, stringargs, 0);
...@@ -4186,6 +4187,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, ...@@ -4186,6 +4187,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
if (strcmp (formal->sym->name, sym->name) == 0) if (strcmp (formal->sym->name, sym->name) == 0)
cl.backend_decl = formal->sym->ts.u.cl->backend_decl; cl.backend_decl = formal->sym->ts.u.cl->backend_decl;
} }
len = cl.backend_decl;
} }
else else
{ {
...@@ -4343,9 +4345,13 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, ...@@ -4343,9 +4345,13 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
if ((!comp && sym->attr.allocatable) if ((!comp && sym->attr.allocatable)
|| (comp && comp->attr.allocatable)) || (comp && comp->attr.allocatable))
gfc_add_modify (&se->pre, var, {
fold_convert (TREE_TYPE (var), gfc_add_modify (&se->pre, var,
null_pointer_node)); fold_convert (TREE_TYPE (var),
null_pointer_node));
tmp = gfc_call_free (convert (pvoid_type_node, var));
gfc_add_expr_to_block (&se->post, tmp);
}
/* Provide an address expression for the function arguments. */ /* Provide an address expression for the function arguments. */
var = gfc_build_addr_expr (NULL_TREE, var); var = gfc_build_addr_expr (NULL_TREE, var);
...@@ -4364,17 +4370,16 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, ...@@ -4364,17 +4370,16 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
VEC_safe_push (tree, gc, retargs, var); VEC_safe_push (tree, gc, retargs, var);
} }
if (ts.type == BT_CHARACTER && ts.deferred /* Add the string length to the argument list. */
&& (sym->attr.allocatable || sym->attr.pointer)) if (ts.type == BT_CHARACTER && ts.deferred)
{ {
tmp = len; tmp = len;
if (TREE_CODE (tmp) != VAR_DECL) if (TREE_CODE (tmp) != VAR_DECL)
tmp = gfc_evaluate_now (len, &se->pre); tmp = gfc_evaluate_now (len, &se->pre);
len = gfc_build_addr_expr (NULL_TREE, tmp); tmp = gfc_build_addr_expr (NULL_TREE, tmp);
VEC_safe_push (tree, gc, retargs, tmp);
} }
else if (ts.type == BT_CHARACTER)
/* Add the string length to the argument list. */
if (ts.type == BT_CHARACTER)
VEC_safe_push (tree, gc, retargs, len); VEC_safe_push (tree, gc, retargs, len);
} }
gfc_free_interface_mapping (&mapping); gfc_free_interface_mapping (&mapping);
...@@ -4483,10 +4488,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, ...@@ -4483,10 +4488,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
else else
se->expr = var; se->expr = var;
if (!ts.deferred) se->string_length = len;
se->string_length = len;
else if (sym->attr.allocatable || sym->attr.pointer)
se->string_length = cl.backend_decl;
} }
else else
{ {
...@@ -5776,8 +5778,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) ...@@ -5776,8 +5778,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
really added if -fbounds-check is enabled. Exclude deferred really added if -fbounds-check is enabled. Exclude deferred
character length lefthand sides. */ character length lefthand sides. */
if (expr1->ts.type == BT_CHARACTER && expr2->expr_type != EXPR_NULL if (expr1->ts.type == BT_CHARACTER && expr2->expr_type != EXPR_NULL
&& !(expr1->ts.deferred && !expr1->ts.deferred
&& (TREE_CODE (lse.string_length) == VAR_DECL))
&& !expr1->symtree->n.sym->attr.proc_pointer && !expr1->symtree->n.sym->attr.proc_pointer
&& !gfc_is_proc_ptr_comp (expr1, NULL)) && !gfc_is_proc_ptr_comp (expr1, NULL))
{ {
...@@ -5790,11 +5791,11 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) ...@@ -5790,11 +5791,11 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
/* The assignment to an deferred character length sets the string /* The assignment to an deferred character length sets the string
length to that of the rhs. */ length to that of the rhs. */
if (expr1->ts.deferred && (TREE_CODE (lse.string_length) == VAR_DECL)) if (expr1->ts.deferred)
{ {
if (expr2->expr_type != EXPR_NULL) if (expr2->expr_type != EXPR_NULL && lse.string_length != NULL)
gfc_add_modify (&block, lse.string_length, rse.string_length); gfc_add_modify (&block, lse.string_length, rse.string_length);
else else if (lse.string_length != NULL)
gfc_add_modify (&block, lse.string_length, gfc_add_modify (&block, lse.string_length,
build_int_cst (gfc_charlen_type_node, 0)); build_int_cst (gfc_charlen_type_node, 0));
} }
......
2012-05-13 Alessandro Fanfarillo <fanfarillo.gcc@gmail.com>
PR fortran/45170
* gfortran.dg/deferred_type_param_3.f90: New.
* gfortran.dg/deferred_type_proc_pointer_1.f90: New.
* gfortran.dg/deferred_type_proc_pointer_2.f90: New.
2012-05-12 Eric Botcazou <ebotcazou@adacore.com> 2012-05-12 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/null_pointer_deref3.adb: New test. * gnat.dg/null_pointer_deref3.adb: New test.
......
! { dg-do compile }
!
! PR fortran/45170
! PR fortran/52158
!
! Contributed by Damian Rouson
module speaker_class
type speaker
contains
procedure :: speak
end type
contains
function speak(this)
class(speaker) ,intent(in) :: this
character(:) ,allocatable :: speak
end function
subroutine say_something(somebody)
class(speaker) :: somebody
print *,somebody%speak()
end subroutine
end module
! { dg-do compile }
!
! PR fortran/45170
! PR fortran/52158
!
! Contributed by Tobias Burnus
module test
implicit none
type t
procedure(deferred_len), pointer, nopass :: ppt
end type t
contains
function deferred_len()
character(len=:), allocatable :: deferred_len
deferred_len = 'abc'
end function deferred_len
subroutine doIt()
type(t) :: x
x%ppt => deferred_len
if ("abc" /= x%ppt()) call abort()
end subroutine doIt
end module test
use test
call doIt ()
end
! { dg-do compile }
!
! PR fortran/45170
! PR fortran/52158
module test
implicit none
type t
procedure(deferred_len), pointer, nopass :: ppt
end type t
contains
function deferred_len()
character(len=:), allocatable :: deferred_len
deferred_len = 'abc'
end function deferred_len
subroutine doIt()
type(t) :: x
character(:), allocatable :: temp
x%ppt => deferred_len
temp = deferred_len()
if ("abc" /= temp) call abort()
end subroutine doIt
end module test
use test
call doIt ()
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment