Commit 726d8566 by Janus Weil

re PR fortran/36704 (Procedure pointer as function result)

2008-12-02  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/36704
	PR fortran/38290
	* decl.c (match_result): Result may be a standard variable or a
	procedure pointer.
	* expr.c (gfc_check_pointer_assign): Additional checks for procedure
	pointer assignments.
	* primary.c (gfc_match_rvalue): Bugfix for procedure pointer
	assignments.
	* resolve.c (resolve_function): Check for attr.subroutine.
	* symbol.c (check_conflict): Addtional checks for RESULT statements.
	* trans-types.c (gfc_sym_type,gfc_get_function_type): Support procedure
	pointers as function result.


2008-12-02  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/36704
	PR fortran/38290
	* gfortran.dg/entry_7.f90: Modified.
	* gfortran.dg/proc_ptr_2.f90: Extended.
	* gfortran.dg/proc_ptr_3.f90: Modified.
	* gfortran.dg/proc_ptr_11.f90: New.
	* gfortran.dg/proc_ptr_12.f90: New.
	* gfortran.dg/result_1.f90: New.

From-SVN: r142351
parent b72bbbcb
2008-12-02 Janus Weil <janus@gcc.gnu.org>
PR fortran/36704
PR fortran/38290
* decl.c (match_result): Result may be a standard variable or a
procedure pointer.
* expr.c (gfc_check_pointer_assign): Additional checks for procedure
pointer assignments.
* primary.c (gfc_match_rvalue): Bugfix for procedure pointer
assignments.
* resolve.c (resolve_function): Check for attr.subroutine.
* symbol.c (check_conflict): Addtional checks for RESULT statements.
* trans-types.c (gfc_sym_type,gfc_get_function_type): Support procedure
pointers as function result.
2008-12-01 Mikael Morin <mikael.morin@tele2.fr> 2008-12-01 Mikael Morin <mikael.morin@tele2.fr>
PR fortran/38252 PR fortran/38252
......
...@@ -3974,8 +3974,7 @@ match_result (gfc_symbol *function, gfc_symbol **result) ...@@ -3974,8 +3974,7 @@ match_result (gfc_symbol *function, gfc_symbol **result)
if (gfc_get_symbol (name, NULL, &r)) if (gfc_get_symbol (name, NULL, &r))
return MATCH_ERROR; return MATCH_ERROR;
if (gfc_add_flavor (&r->attr, FL_VARIABLE, r->name, NULL) == FAILURE if (gfc_add_result (&r->attr, r->name, NULL) == FAILURE)
|| gfc_add_result (&r->attr, r->name, NULL) == FAILURE)
return MATCH_ERROR; return MATCH_ERROR;
*result = r; *result = r;
......
...@@ -3112,9 +3112,30 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue) ...@@ -3112,9 +3112,30 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue)
if (rvalue->expr_type == EXPR_NULL && rvalue->ts.type == BT_UNKNOWN) if (rvalue->expr_type == EXPR_NULL && rvalue->ts.type == BT_UNKNOWN)
return SUCCESS; return SUCCESS;
/* TODO checks on rvalue for a procedure pointer assignment. */ /* Checks on rvalue for procedure pointer assignments. */
if (lvalue->symtree->n.sym->attr.proc_pointer) if (lvalue->symtree->n.sym->attr.proc_pointer)
return SUCCESS; {
attr = gfc_expr_attr (rvalue);
if (!((rvalue->expr_type == EXPR_NULL)
|| (rvalue->expr_type == EXPR_FUNCTION && attr.proc_pointer)
|| (rvalue->expr_type == EXPR_VARIABLE
&& attr.flavor == FL_PROCEDURE)))
{
gfc_error ("Invalid procedure pointer assignment at %L",
&rvalue->where);
return FAILURE;
}
if (rvalue->expr_type == EXPR_VARIABLE
&& lvalue->symtree->n.sym->attr.if_source != IFSRC_UNKNOWN
&& !gfc_compare_interfaces (lvalue->symtree->n.sym,
rvalue->symtree->n.sym, 0))
{
gfc_error ("Interfaces don't match "
"in procedure pointer assignment at %L", &rvalue->where);
return FAILURE;
}
return SUCCESS;
}
if (!gfc_compare_types (&lvalue->ts, &rvalue->ts)) if (!gfc_compare_types (&lvalue->ts, &rvalue->ts))
{ {
......
...@@ -2509,11 +2509,10 @@ gfc_match_rvalue (gfc_expr **result) ...@@ -2509,11 +2509,10 @@ gfc_match_rvalue (gfc_expr **result)
if (gfc_matching_procptr_assignment) if (gfc_matching_procptr_assignment)
{ {
gfc_gobble_whitespace (); gfc_gobble_whitespace ();
if (sym->attr.function && gfc_peek_ascii_char () == '(') if (gfc_peek_ascii_char () == '(')
/* Parse functions returning a procptr. */ /* Parse functions returning a procptr. */
goto function0; goto function0;
if (sym->attr.flavor == FL_UNKNOWN) sym->attr.flavor = FL_PROCEDURE;
if (gfc_is_intrinsic (sym, 0, gfc_current_locus) if (gfc_is_intrinsic (sym, 0, gfc_current_locus)
|| gfc_is_intrinsic (sym, 1, gfc_current_locus)) || gfc_is_intrinsic (sym, 1, gfc_current_locus))
sym->attr.intrinsic = 1; sym->attr.intrinsic = 1;
......
...@@ -2327,7 +2327,7 @@ resolve_function (gfc_expr *expr) ...@@ -2327,7 +2327,7 @@ resolve_function (gfc_expr *expr)
return FAILURE; return FAILURE;
} }
if (sym && sym->attr.flavor == FL_VARIABLE) if (sym && (sym->attr.flavor == FL_VARIABLE || sym->attr.subroutine))
{ {
gfc_error ("'%s' at %L is not a function", sym->name, &expr->where); gfc_error ("'%s' at %L is not a function", sym->name, &expr->where);
return FAILURE; return FAILURE;
......
...@@ -618,7 +618,10 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where) ...@@ -618,7 +618,10 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where)
break; break;
case FL_VARIABLE: case FL_VARIABLE:
break;
case FL_NAMELIST: case FL_NAMELIST:
conf2 (result);
break; break;
case FL_PROCEDURE: case FL_PROCEDURE:
...@@ -672,6 +675,7 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where) ...@@ -672,6 +675,7 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where)
conf2 (function); conf2 (function);
conf2 (subroutine); conf2 (subroutine);
conf2 (threadprivate); conf2 (threadprivate);
conf2 (result);
if (attr->intent != INTENT_UNKNOWN) if (attr->intent != INTENT_UNKNOWN)
{ {
...@@ -698,6 +702,7 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where) ...@@ -698,6 +702,7 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where)
conf2 (threadprivate); conf2 (threadprivate);
conf2 (value); conf2 (value);
conf2 (is_bind_c); conf2 (is_bind_c);
conf2 (result);
break; break;
default: default:
......
...@@ -1613,8 +1613,8 @@ gfc_sym_type (gfc_symbol * sym) ...@@ -1613,8 +1613,8 @@ gfc_sym_type (gfc_symbol * sym)
tree type; tree type;
int byref; int byref;
/* Procedure Pointers inside COMMON blocks. */ /* Procedure Pointers inside COMMON blocks or as function result. */
if (sym->attr.proc_pointer && sym->attr.in_common) if (sym->attr.proc_pointer && (sym->attr.in_common || sym->attr.result))
{ {
/* Unset proc_pointer as gfc_get_function_type calls gfc_sym_type. */ /* Unset proc_pointer as gfc_get_function_type calls gfc_sym_type. */
sym->attr.proc_pointer = 0; sym->attr.proc_pointer = 0;
...@@ -2143,6 +2143,9 @@ gfc_get_function_type (gfc_symbol * sym) ...@@ -2143,6 +2143,9 @@ gfc_get_function_type (gfc_symbol * sym)
type = gfc_typenode_for_spec (&sym->ts); type = gfc_typenode_for_spec (&sym->ts);
sym->ts.kind = gfc_default_real_kind; sym->ts.kind = gfc_default_real_kind;
} }
else if (sym->result && sym->result->attr.proc_pointer)
/* Procedure pointer return values. */
type = gfc_sym_type (sym->result);
else else
type = gfc_sym_type (sym); type = gfc_sym_type (sym);
......
2008-12-02 Janus Weil <janus@gcc.gnu.org>
PR fortran/36704
PR fortran/38290
* gfortran.dg/entry_7.f90: Modified.
* gfortran.dg/proc_ptr_2.f90: Extended.
* gfortran.dg/proc_ptr_3.f90: Modified.
* gfortran.dg/proc_ptr_11.f90: New.
* gfortran.dg/proc_ptr_12.f90: New.
* gfortran.dg/result_1.f90: New.
2008-12-02 Jakub Jelinek <jakub@redhat.com> 2008-12-02 Jakub Jelinek <jakub@redhat.com>
PR middle-end/38343 PR middle-end/38343
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
MODULE TT MODULE TT
CONTAINS CONTAINS
FUNCTION K(I) RESULT(J) FUNCTION K(I) RESULT(J)
ENTRY J() ! { dg-error "conflicts with PROCEDURE attribute" } ENTRY J() ! { dg-error "conflicts with RESULT attribute" }
END FUNCTION K END FUNCTION K
integer function foo () integer function foo ()
......
! { dg-do compile }
!
! PR 38290: Procedure pointer assignment checking.
!
! Test case found at http://de.wikibooks.org/wiki/Fortran:_Fortran_2003:_Zeiger
! Adapted by Janus Weil <janus@gcc.gnu.org>
program bsp
implicit none
abstract interface
subroutine up()
end subroutine up
end interface
procedure( up ) , pointer :: pptr
pptr => add ! { dg-error "Interfaces don't match" }
print *, pptr() ! { dg-error "is not a function" }
contains
function add( a, b )
integer :: add
integer, intent( in ) :: a, b
add = a + b
end function add
end program bsp
! { dg-do run }
!
! PR 36704: Procedure pointer as function result
!
! Contributed by Janus Weil <janus@gcc.gnu.org>
procedure(integer),pointer :: p
p => foo()
if (p(-1)/=1) call abort
contains
function foo() result(bar)
procedure(integer),pointer :: bar
bar => iabs
end function
end
...@@ -6,8 +6,11 @@ ...@@ -6,8 +6,11 @@
PROCEDURE(REAL), POINTER :: ptr PROCEDURE(REAL), POINTER :: ptr
PROCEDURE(REAL), SAVE :: noptr ! { dg-error "attribute conflicts with" } PROCEDURE(REAL), SAVE :: noptr ! { dg-error "attribute conflicts with" }
REAL :: x
ptr => cos(4.0) ! { dg-error "Invalid character" } ptr => cos(4.0) ! { dg-error "Invalid procedure pointer assignment" }
ptr => x ! { dg-error "Invalid procedure pointer assignment" }
ptr => sin(x) ! { dg-error "Invalid procedure pointer assignment" }
ALLOCATE(ptr) ! { dg-error "must be ALLOCATABLE" } ALLOCATE(ptr) ! { dg-error "must be ALLOCATABLE" }
......
...@@ -6,14 +6,12 @@ ...@@ -6,14 +6,12 @@
real function e1(x) real function e1(x)
real :: x real :: x
print *,'e1!',x
e1 = x * 3.0 e1 = x * 3.0
end function end function
subroutine e2(a,b) subroutine e2(a,b)
real, intent(inout) :: a real, intent(inout) :: a
real, intent(in) :: b real, intent(in) :: b
print *,'e2!',a,b
a = a + b a = a + b
end subroutine end subroutine
...@@ -29,7 +27,15 @@ interface ...@@ -29,7 +27,15 @@ interface
end subroutine sp end subroutine sp
end interface end interface
external :: e1,e2 external :: e1
interface
subroutine e2(a,b)
real, intent(inout) :: a
real, intent(in) :: b
end subroutine e2
end interface
real :: c = 1.2 real :: c = 1.2
fp => e1 fp => e1
......
! { dg-do compile }
!
! PR 36704: Procedure pointer as function result
!
! Contributed by Janus Weil <janus@gcc.gnu.org>
function f() result(r)
real, parameter :: r = 5.0 ! { dg-error "attribute conflicts" }
end function
function g() result(s)
real :: a,b,c
namelist /s/ a,b,c ! { dg-error "attribute conflicts" }
end function
function h() result(t)
type t ! { dg-error "attribute conflicts" }
end function
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