Commit f6bf4bc1 by Thomas Schwinge Committed by Thomas Schwinge

[PR89773] Fortran OpenACC 'routine' directive refuses procedures with implicit EXTERNAL attribute

	gcc/fortran/
	PR fortran/89773
	* gfortran.h (gfc_oacc_routine_name): Add loc member.
	(gfc_resolve_oacc_routines): Declare.
	* openmp.c (gfc_match_oacc_routine): Move some error checking
	into...
	(gfc_resolve_oacc_routines): ... this new function.
	* resolve.c (resolve_codes): Call it.
	gcc/testsuite/
	PR fortran/89773
	* gfortran.dg/goacc/pr89773.f90: New file.
	* gfortran.dg/goacc/pr77765.f90: Adjust.
	* gfortran.dg/goacc/routine-6.f90: Adjust, and extend.

From-SVN: r269857
parent 8ced98c6
2019-03-21 Thomas Schwinge <thomas@codesourcery.com> 2019-03-21 Thomas Schwinge <thomas@codesourcery.com>
PR fortran/89773
* gfortran.h (gfc_oacc_routine_name): Add loc member.
(gfc_resolve_oacc_routines): Declare.
* openmp.c (gfc_match_oacc_routine): Move some error checking
into...
(gfc_resolve_oacc_routines): ... this new function.
* resolve.c (resolve_codes): Call it.
PR fortran/72741 PR fortran/72741
* openmp.c (gfc_match_oacc_routine): Clarify. * openmp.c (gfc_match_oacc_routine): Clarify.
......
...@@ -1739,6 +1739,7 @@ typedef struct gfc_oacc_routine_name ...@@ -1739,6 +1739,7 @@ typedef struct gfc_oacc_routine_name
struct gfc_symbol *sym; struct gfc_symbol *sym;
struct gfc_omp_clauses *clauses; struct gfc_omp_clauses *clauses;
struct gfc_oacc_routine_name *next; struct gfc_oacc_routine_name *next;
locus loc;
} }
gfc_oacc_routine_name; gfc_oacc_routine_name;
...@@ -3210,6 +3211,7 @@ void gfc_resolve_oacc_directive (gfc_code *, gfc_namespace *); ...@@ -3210,6 +3211,7 @@ void gfc_resolve_oacc_directive (gfc_code *, gfc_namespace *);
void gfc_resolve_oacc_declare (gfc_namespace *); void gfc_resolve_oacc_declare (gfc_namespace *);
void gfc_resolve_oacc_parallel_loop_blocks (gfc_code *, gfc_namespace *); void gfc_resolve_oacc_parallel_loop_blocks (gfc_code *, gfc_namespace *);
void gfc_resolve_oacc_blocks (gfc_code *, gfc_namespace *); void gfc_resolve_oacc_blocks (gfc_code *, gfc_namespace *);
void gfc_resolve_oacc_routines (gfc_namespace *);
/* expr.c */ /* expr.c */
void gfc_free_actual_arglist (gfc_actual_arglist *); void gfc_free_actual_arglist (gfc_actual_arglist *);
......
...@@ -2322,15 +2322,10 @@ gfc_match_oacc_routine (void) ...@@ -2322,15 +2322,10 @@ gfc_match_oacc_routine (void)
sym = NULL; sym = NULL;
} }
if ((isym == NULL && st == NULL) if (isym == NULL && st == NULL)
|| (sym
&& !sym->attr.external
&& !sym->attr.function
&& !sym->attr.subroutine))
{ {
gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, " gfc_error ("Invalid NAME %qs in !$ACC ROUTINE ( NAME ) at %C",
"invalid function name %s", buffer);
(sym) ? sym->name : buffer);
gfc_current_locus = old_loc; gfc_current_locus = old_loc;
return MATCH_ERROR; return MATCH_ERROR;
} }
...@@ -2400,6 +2395,7 @@ gfc_match_oacc_routine (void) ...@@ -2400,6 +2395,7 @@ gfc_match_oacc_routine (void)
n->sym = sym; n->sym = sym;
n->clauses = c; n->clauses = c;
n->next = gfc_current_ns->oacc_routine_names; n->next = gfc_current_ns->oacc_routine_names;
n->loc = old_loc;
gfc_current_ns->oacc_routine_names = n; gfc_current_ns->oacc_routine_names = n;
} }
} }
...@@ -6072,6 +6068,27 @@ gfc_resolve_oacc_declare (gfc_namespace *ns) ...@@ -6072,6 +6068,27 @@ gfc_resolve_oacc_declare (gfc_namespace *ns)
} }
} }
void
gfc_resolve_oacc_routines (gfc_namespace *ns)
{
for (gfc_oacc_routine_name *orn = ns->oacc_routine_names;
orn;
orn = orn->next)
{
gfc_symbol *sym = orn->sym;
if (!sym->attr.external
&& !sym->attr.function
&& !sym->attr.subroutine)
{
gfc_error ("NAME %qs does not refer to a subroutine or function"
" in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
continue;
}
}
}
void void
gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED) gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
{ {
......
...@@ -16818,6 +16818,7 @@ resolve_codes (gfc_namespace *ns) ...@@ -16818,6 +16818,7 @@ resolve_codes (gfc_namespace *ns)
bitmap_obstack_initialize (&labels_obstack); bitmap_obstack_initialize (&labels_obstack);
gfc_resolve_oacc_declare (ns); gfc_resolve_oacc_declare (ns);
gfc_resolve_oacc_routines (ns);
gfc_resolve_omp_local_vars (ns); gfc_resolve_omp_local_vars (ns);
gfc_resolve_code (ns->code, ns); gfc_resolve_code (ns->code, ns);
......
2019-03-21 Thomas Schwinge <thomas@codesourcery.com> 2019-03-21 Thomas Schwinge <thomas@codesourcery.com>
PR fortran/89773
* gfortran.dg/goacc/pr89773.f90: New file.
* gfortran.dg/goacc/pr77765.f90: Adjust.
* gfortran.dg/goacc/routine-6.f90: Adjust, and extend.
PR fortran/72741 PR fortran/72741
* gfortran.dg/goacc/routine-module-mod-1.f90: Update. * gfortran.dg/goacc/routine-module-mod-1.f90: Update.
......
...@@ -14,5 +14,5 @@ end module m ...@@ -14,5 +14,5 @@ end module m
! { dg-error "Procedure 'f' at .1. is already defined" "" { target *-*-* } 8 } ! { dg-error "Procedure 'f' at .1. is already defined" "" { target *-*-* } 8 }
! { dg-error ".1." "" { target *-*-* } 10 } ! { dg-error ".1." "" { target *-*-* } 10 }
! { dg-error "Syntax error in ..ACC ROUTINE . NAME . at .1., invalid function name f" "" { target *-*-* } 11 } ! { dg-error "Invalid NAME 'f' in \\!\\\$ACC ROUTINE \\( NAME \\)" "" { target *-*-* } 11 }
! { dg-error "Expecting END MODULE statement" "" { target *-*-* } 12 } ! { dg-error "Expecting END MODULE statement" "" { target *-*-* } 12 }
! Valid usage of 'external' procedures with OpenACC 'routine' directives.
! { dg-additional-options "-fdump-tree-optimized-raw" }
subroutine test (x)
implicit none
integer, intent(inout) :: x
!$acc routine (test)
integer, external :: f_1
!$acc routine (f_1)
integer f_2 ! No explicit EXTERNAL attribute.
!$acc routine (f_2)
external s_1
!$acc routine (s_1)
! 's_2' will be an external subroutine without explicit EXTERNAL
! attribute, but we don't have a handle for it yet...
!!$acc routine (s_2) ..., so can't specify this, here.
if (x < 1) then
x = 1
else
x = x * x - 1 + f_1(f_2(x))
call s_1(x)
call s_2(x)
end if
end subroutine test
! { dg-final { scan-tree-dump-times "gimple_call" 4 "optimized" } }
! { dg-final { scan-tree-dump-times "gimple_call <f_1," 1 "optimized" } }
! { dg-final { scan-tree-dump-times "gimple_call <f_2," 1 "optimized" } }
! { dg-final { scan-tree-dump-times "gimple_call <s_1," 1 "optimized" } }
! { dg-final { scan-tree-dump-times "gimple_call <s_2," 1 "optimized" } }
...@@ -5,19 +5,30 @@ module m ...@@ -5,19 +5,30 @@ module m
contains contains
subroutine subr5 (x) subroutine subr5 (x)
implicit none implicit none
!$acc routine (m) ! { dg-error "Invalid NAME 'm' in \\!\\\$ACC ROUTINE \\( NAME \\)" }
!$acc routine (subr5) !$acc routine (subr5)
!$acc routine (m1int) ! { dg-error "invalid function name" } !$acc routine (m1int) ! { dg-error "Invalid NAME 'm1int' in \\!\\\$ACC ROUTINE \\( NAME \\)" }
integer f_1 ! Referenced.
!$acc routine (f_1)
integer f_2 ! Not referenced.
!$acc routine (f_2) ! { dg-error "NAME 'f_2' does not refer to a subroutine or function in \\!\\\$ACC ROUTINE \\( NAME \\)" }
integer v_1
!$acc routine (v_1) ! { dg-error "NAME 'v_1' does not refer to a subroutine or function in \\!\\\$ACC ROUTINE \\( NAME \\)" }
integer, intent(inout) :: x integer, intent(inout) :: x
!$acc routine (x) ! { dg-error "NAME 'x' does not refer to a subroutine or function in \\!\\\$ACC ROUTINE \\( NAME \\)" }
v_1 = x
if (x < 1) then if (x < 1) then
x = 1 x = 1
else else
x = x * x - 1 x = x * x - 1
x = f_1(x) + v_1
end if end if
end subroutine subr5 end subroutine subr5
end module m end module m
program main program main
implicit none implicit none
!$acc routine (main) ! { dg-error "PROGRAM attribute conflicts with SUBROUTINE attribute in 'main'" }
interface interface
function subr6 (x) function subr6 (x)
!$acc routine (subr6) ! { dg-error "without list is allowed in interface" } !$acc routine (subr6) ! { dg-error "without list is allowed in interface" }
...@@ -27,7 +38,10 @@ program main ...@@ -27,7 +38,10 @@ program main
end interface end interface
integer, parameter :: n = 10 integer, parameter :: n = 10
integer :: a(n), i integer :: a(n), i
!$acc routine (subr1) ! { dg-error "invalid function name" } !$acc routine (n) ! { dg-error "NAME 'n' does not refer to a subroutine or function in \\!\\\$ACC ROUTINE \\( NAME \\)" }
!$acc routine (a) ! { dg-error "NAME 'a' does not refer to a subroutine or function in \\!\\\$ACC ROUTINE \\( NAME \\)" }
!$acc routine (i) ! { dg-error "NAME 'i' does not refer to a subroutine or function in \\!\\\$ACC ROUTINE \\( NAME \\)" }
!$acc routine (subr1) ! { dg-error "Invalid NAME 'subr1' in \\!\\\$ACC ROUTINE \\( NAME \\)" }
external :: subr2 external :: subr2
!$acc routine (subr2) !$acc routine (subr2)
...@@ -63,8 +77,9 @@ subroutine subr1 (x) ...@@ -63,8 +77,9 @@ subroutine subr1 (x)
end subroutine subr1 end subroutine subr1
subroutine subr2 (x) subroutine subr2 (x)
!$acc routine (subr1) ! { dg-error "invalid function name" } !$acc routine (subr1) ! { dg-error "Invalid NAME 'subr1' in \\!\\\$ACC ROUTINE \\( NAME \\)" }
integer, intent(inout) :: x integer, intent(inout) :: x
!$acc routine (x) ! { dg-error "NAME 'x' does not refer to a subroutine or function in \\!\\\$ACC ROUTINE \\( NAME \\)" }
if (x < 1) then if (x < 1) then
x = 1 x = 1
else else
......
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