+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>
PR fortran/38252
if (gfc_get_symbol (name, NULL, &r))
return MATCH_ERROR;
- if (gfc_add_flavor (&r->attr, FL_VARIABLE, r->name, NULL) == FAILURE
- || gfc_add_result (&r->attr, r->name, NULL) == FAILURE)
+ if (gfc_add_result (&r->attr, r->name, NULL) == FAILURE)
return MATCH_ERROR;
*result = r;
if (rvalue->expr_type == EXPR_NULL && rvalue->ts.type == BT_UNKNOWN)
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)
- 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_matching_procptr_assignment)
{
gfc_gobble_whitespace ();
- if (sym->attr.function && gfc_peek_ascii_char () == '(')
+ if (gfc_peek_ascii_char () == '(')
/* Parse functions returning a procptr. */
goto function0;
- if (sym->attr.flavor == FL_UNKNOWN) sym->attr.flavor = FL_PROCEDURE;
if (gfc_is_intrinsic (sym, 0, gfc_current_locus)
|| gfc_is_intrinsic (sym, 1, gfc_current_locus))
sym->attr.intrinsic = 1;
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);
return FAILURE;
break;
case FL_VARIABLE:
+ break;
+
case FL_NAMELIST:
+ conf2 (result);
break;
case FL_PROCEDURE:
conf2 (function);
conf2 (subroutine);
conf2 (threadprivate);
+ conf2 (result);
if (attr->intent != INTENT_UNKNOWN)
{
conf2 (threadprivate);
conf2 (value);
conf2 (is_bind_c);
+ conf2 (result);
break;
default:
tree type;
int byref;
- /* Procedure Pointers inside COMMON blocks. */
- if (sym->attr.proc_pointer && sym->attr.in_common)
+ /* Procedure Pointers inside COMMON blocks or as function result. */
+ if (sym->attr.proc_pointer && (sym->attr.in_common || sym->attr.result))
{
/* Unset proc_pointer as gfc_get_function_type calls gfc_sym_type. */
sym->attr.proc_pointer = 0;
type = gfc_typenode_for_spec (&sym->ts);
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
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>
PR middle-end/38343
MODULE TT
CONTAINS
FUNCTION K(I) RESULT(J)
- ENTRY J() ! { dg-error "conflicts with PROCEDURE attribute" }
+ ENTRY J() ! { dg-error "conflicts with RESULT attribute" }
END FUNCTION K
integer function foo ()
--- /dev/null
+! { 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
--- /dev/null
+! { 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
PROCEDURE(REAL), POINTER :: ptr
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" }
real function e1(x)
real :: x
- print *,'e1!',x
e1 = x * 3.0
end function
subroutine e2(a,b)
real, intent(inout) :: a
real, intent(in) :: b
- print *,'e2!',a,b
a = a + b
end subroutine
end subroutine sp
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
fp => e1
--- /dev/null
+! { 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