https://gcc.gnu.org/g:451b6dbf47595922518b96728677d1fafa11e2ad
commit r16-2213-g451b6dbf47595922518b96728677d1fafa11e2ad Author: Tobias Burnus <tbur...@baylibre.com> Date: Sat Jul 12 07:18:06 2025 +0200 Fortran/OpenACC: Permit PARAMETER as 'var' in clauses (+ ignore) It turned out that other compilers permit (require?) named constants to appear in clauses - and programs actually use this. OpenACC 3.4 added therefore the following: In this spec, a _var_ (in italics) is one of the following: ... * a named constant in Fortran. plus If during an optimization phase _var_ is removed by the compiler, appearances of var in data clauses are ignored. Thus, all errors related to PARAMETER are now downgraded, most to a -Wsurprising warning, but for 'acc declare device_resident' (which kind of makes sense), no warning is printed. In trans-openmp.cc, those are ignored, unless I missed some code path. (If so, I hope the middle end removes them; but before removing them for the covered cases, the program just compiled & linked fine.) Note that 'ignore PARAMETER inside clauses' in trans-openmp.cc would in principle also apply to expressions ('if (var)') but those should be evaluated during 'resolve.cc' + 'openmp.cc' to their (numeric, logical, string) value such that there should be no issue. gcc/fortran/ChangeLog: * invoke.texi (-Wsurprising): Note about OpenACC warning related to PARAMATER. * openmp.cc (resolve_omp_clauses, gfc_resolve_oacc_declare): Accept PARAMETER for OpenACC but add surprising warning. * trans-openmp.cc (gfc_trans_omp_variable_list, gfc_trans_omp_clauses): Ignore PARAMETER inside clauses. gcc/testsuite/ChangeLog: * gfortran.dg/goacc/parameter.f95: Add -Wsurprising flag and update expected diagnostic. * gfortran.dg/goacc/parameter-3.f90: New test. * gfortran.dg/goacc/parameter-4.f90: New test. Diff: --- gcc/fortran/invoke.texi | 4 ++++ gcc/fortran/openmp.cc | 30 ++++++++++++++++++++----- gcc/fortran/trans-openmp.cc | 13 ++++++++--- gcc/testsuite/gfortran.dg/goacc/parameter-3.f90 | 16 +++++++++++++ gcc/testsuite/gfortran.dg/goacc/parameter-4.f90 | 26 +++++++++++++++++++++ gcc/testsuite/gfortran.dg/goacc/parameter.f95 | 27 +++++++++++----------- 6 files changed, 94 insertions(+), 22 deletions(-) diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi index da085d124f91..0b893e876a5d 100644 --- a/gcc/fortran/invoke.texi +++ b/gcc/fortran/invoke.texi @@ -1170,6 +1170,10 @@ A @code{CHARACTER} variable is declared with negative length. With @option{-fopenmp}, for fixed-form source code, when an @code{omx} vendor-extension sentinel is encountered. (The equivalent @code{ompx}, used in free-form source code, is diagnosed by default.) + +@item +With @option{-fopenacc}, when using named constances with clauses that +take a variable as doing so has no effect. @end itemize @opindex Wtabs diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index fe0a47a6948b..f1acc00f561b 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -8895,15 +8895,21 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, if (list == OMP_LIST_MAP && n->sym->attr.flavor == FL_PARAMETER) { + /* OpenACC since 3.4 permits for Fortran named constants, but + permits removing then as optimization is not needed and such + ignore them. Likewise below for FIRSTPRIVATE. */ if (openacc) - gfc_error ("Object %qs is not a variable at %L; parameters" - " cannot be and need not be copied", n->sym->name, - &n->where); + gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is " + "ignored as parameters need not be copied", + n->sym->name, &n->where); else gfc_error ("Object %qs is not a variable at %L; parameters" " cannot be and need not be mapped", n->sym->name, &n->where); } + else if (openacc && n->sym->attr.flavor == FL_PARAMETER) + gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is ignored" + " as it is a parameter", n->sym->name, &n->where); else if (list != OMP_LIST_USES_ALLOCATORS) gfc_error ("Object %qs is not a variable at %L", n->sym->name, &n->where); @@ -12756,9 +12762,21 @@ gfc_resolve_oacc_declare (gfc_namespace *ns) && (n->sym->attr.flavor != FL_PROCEDURE || n->sym->result != n->sym)) { - gfc_error ("Object %qs is not a variable at %L", - n->sym->name, &oc->loc); - continue; + if (n->sym->attr.flavor != FL_PARAMETER) + { + gfc_error ("Object %qs is not a variable at %L", + n->sym->name, &oc->loc); + continue; + } + /* Note that OpenACC 3.4 permits name constants, but the + implementation is permitted to ignore the clause; + as semantically, device_resident kind of makes sense + (and the wording with it is a bit odd), the warning + is suppressed. */ + if (list != OMP_LIST_DEVICE_RESIDENT) + gfc_warning (OPT_Wsurprising, "Object %qs at %L is ignored as" + " parameters need not be copied", n->sym->name, + &oc->loc); } if (n->expr && n->expr->ref->type == REF_ARRAY) diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index a2e70fca0b37..f3d7cd4ffee9 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -2792,8 +2792,13 @@ gfc_trans_omp_variable_list (enum omp_clause_code code, gfc_omp_namelist *namelist, tree list, bool declare_simd) { + /* PARAMETER (named constants) are excluded as OpenACC 3.4 permits them now + as 'var' but permits compilers to ignore them. In expressions, it should + have been replaced by the value (and this function should not be called + anyway) and for var-using clauses, they should just be skipped. */ for (; namelist != NULL; namelist = namelist->next) - if (namelist->sym->attr.referenced || declare_simd) + if ((namelist->sym->attr.referenced || declare_simd) + && namelist->sym->attr.flavor != FL_PARAMETER) { tree t = gfc_trans_omp_variable (namelist->sym, declare_simd); if (t != error_mark_node) @@ -4029,7 +4034,8 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, case OMP_LIST_MAP: for (; n != NULL; n = n->next) { - if (!n->sym->attr.referenced) + if (!n->sym->attr.referenced + || n->sym->attr.flavor == FL_PARAMETER) continue; location_t map_loc = gfc_get_location (&n->where); @@ -4986,7 +4992,8 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, case OMP_LIST_CACHE: for (; n != NULL; n = n->next) { - if (!n->sym->attr.referenced) + if (!n->sym->attr.referenced + && n->sym->attr.flavor != FL_PARAMETER) continue; switch (list) diff --git a/gcc/testsuite/gfortran.dg/goacc/parameter-3.f90 b/gcc/testsuite/gfortran.dg/goacc/parameter-3.f90 new file mode 100644 index 000000000000..2c8aa618cc22 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/goacc/parameter-3.f90 @@ -0,0 +1,16 @@ +! { dg-do compile } + +subroutine x + integer :: var + integer, parameter :: ilog = 0 + integer, parameter :: array(*) = [11,22,33] + !$ACC DECLARE COPYIN(ilog, array, var, array) ! { dg-error "Symbol 'array' present on multiple clauses" } +end subroutine x + +integer :: a +integer, parameter :: b = 4 +integer, parameter :: c(*) = [1,2,3] + +!$acc parallel copy(a,c,b,c) ! { dg-error "Symbol 'c' present on multiple clauses" } +!$acc end parallel +end diff --git a/gcc/testsuite/gfortran.dg/goacc/parameter-4.f90 b/gcc/testsuite/gfortran.dg/goacc/parameter-4.f90 new file mode 100644 index 000000000000..aadd7cffe810 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/goacc/parameter-4.f90 @@ -0,0 +1,26 @@ +! { dg-do compile } +! { dg-additional-options "-fdump-tree-original" } + +subroutine x + integer :: var + integer, parameter :: ilog = 0 + integer, parameter :: array(*) = [11,22,33] + !$ACC DECLARE COPYIN(ilog, array, var) +end subroutine x + +integer :: a +integer, parameter :: b = 4 +integer, parameter :: c(*) = [1,2,3] + +!$acc parallel copy(a,c,b) + a = c(2) + b +!$acc end parallel + +!$acc parallel firstprivate(a,c,b) + a = c(2) + b +!$acc end parallel +end + +! { dg-final { scan-tree-dump-times "#pragma acc data map\\(to:var\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma acc parallel map\\(tofrom:a\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma acc parallel firstprivate\\(a\\)" 1 "original" } } diff --git a/gcc/testsuite/gfortran.dg/goacc/parameter.f95 b/gcc/testsuite/gfortran.dg/goacc/parameter.f95 index b58133867217..a9bde4a67ec1 100644 --- a/gcc/testsuite/gfortran.dg/goacc/parameter.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/parameter.f95 @@ -1,4 +1,5 @@ ! { dg-do compile } +! { dg-additional-options "-Wsurprising" } module test contains @@ -6,37 +7,37 @@ contains implicit none integer :: i integer, parameter :: a = 1 - !$acc declare device_resident (a) ! { dg-error "is not a variable" } - !$acc data copy (a) ! { dg-error "not a variable" } + !$acc declare device_resident (a) ! (no warning here - for semi-good reasons) + !$acc data copy (a) ! { dg-warning "Clause for object 'a' at .1. is ignored as parameters need not be copied \\\[-Wsurprising\\\]" } !$acc end data - !$acc data deviceptr (a) ! { dg-error "not a variable" } + !$acc data deviceptr (a) ! { dg-warning "Clause for object 'a' at .1. is ignored as parameters need not be copied \\\[-Wsurprising\\\]" } !$acc end data - !$acc parallel private (a) ! { dg-error "not a variable" } + !$acc parallel private (a) ! { dg-warning "Clause for object 'a' at .1. is ignored as it is a parameter \\\[-Wsurprising\\\]" } !$acc end parallel - !$acc serial private (a) ! { dg-error "not a variable" } + !$acc serial private (a) ! { dg-warning "Clause for object 'a' at .1. is ignored as it is a parameter \\\[-Wsurprising\\\]" } !$acc end serial - !$acc host_data use_device (a) ! { dg-error "not a variable" } + !$acc host_data use_device (a) ! { dg-warning "Clause for object 'a' at .1. is ignored as it is a parameter \\\[-Wsurprising\\\]" } !$acc end host_data - !$acc parallel loop reduction(+:a) ! { dg-error "not a variable" } + !$acc parallel loop reduction(+:a) ! { dg-warning "Clause for object 'a' at .1. is ignored as it is a parameter \\\[-Wsurprising\\\]" } do i = 1,5 enddo !$acc end parallel loop - !$acc serial loop reduction(+:a) ! { dg-error "not a variable" } + !$acc serial loop reduction(+:a) ! { dg-warning "Clause for object 'a' at .1. is ignored as it is a parameter \\\[-Wsurprising\\\]" } do i = 1,5 enddo !$acc end serial loop !$acc parallel loop do i = 1,5 - !$acc cache (a) ! { dg-error "not a variable" } + !$acc cache (a) ! { dg-warning "Clause for object 'a' at .1. is ignored as it is a parameter \\\[-Wsurprising\\\]" } enddo !$acc end parallel loop !$acc serial loop do i = 1,5 - !$acc cache (a) ! { dg-error "not a variable" } + !$acc cache (a) ! { dg-warning "Clause for object 'a' at .1. is ignored as it is a parameter \\\[-Wsurprising\\\]" } enddo !$acc end serial loop - !$acc update device (a) ! { dg-error "not a variable" } - !$acc update host (a) ! { dg-error "not a variable" } - !$acc update self (a) ! { dg-error "not a variable" } + !$acc update device (a) ! { dg-warning "Clause for object 'a' at .1. is ignored as parameters need not be copied \\\[-Wsurprising\\\]" } + !$acc update host (a) ! { dg-warning "Clause for object 'a' at .1. is ignored as parameters need not be copied \\\[-Wsurprising\\\]" } + !$acc update self (a) ! { dg-warning "Clause for object 'a' at .1. is ignored as parameters need not be copied \\\[-Wsurprising\\\]" } end subroutine oacc1 end module test