This patch adds the first OpenMP 5 feature to gfortran – which is trivial as it justs adds some parsing, the heavy lifting is already done in the middle end. (Minus bugs.)

Additionally, I add a check for "is_device_ptr" – which is explicitly is specified in the OpenMP 4.5/5.0 spec. (i.e. dummy argument w/o pointer/allocatable/value attribute; C/C++ have the requirement pointer or array - or (C++) reference to those.) – I am not sure whether the Fortran restrictions make sense, but that's a OpenMP spec issue (for OpenMP 5.x?).

I am a bit unsure about checks for use_device_…. The spec has no explicit rules, only some with can be deduced from the semantic. For C/C++, gcc/g++ has for OpenMP 4.5 (_ptr) and for OpenMP 5 (_addr): only accept pointer or array type and C++ additionally for references to those. OpenMP 5 for _ptr accepts only POINTER_TYPE (C++: plus refs to it).

The current omp-low.c implementation has in any case issues with use_device_ptr and nonallocatable, nonpointer scalars, which are locally defined or have the value attribute.

Build and regtested on x86_64-gnu-linux.

OK for the trunk?

Tobias

	* dump-parse-tree.c (show_omp_clauses): Handle OMP_LIST_USE_DEVICE_ADDR.
	* gfortran.h (enum): Add OMP_LIST_USE_DEVICE_ADDR.
	* openmp.c (omp_mask1): Likewise.
	(gfc_match_omp_clauses): Match 'use_device_addr'.
	(OMP_TARGET_DATA_CLAUSES): Add OMP_LIST_USE_DEVICE_ADDR.
	(resolve_omp_clauses): Add it; add is_device_ptr checks.

	* gfortran.dg/gomp/is_device_ptr-1.f90: New.

diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 513f211b68b..9d7b26f5f6a 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1507,6 +1507,7 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
 	  case OMP_LIST_CACHE: type = "CACHE"; break;
 	  case OMP_LIST_IS_DEVICE_PTR: type = "IS_DEVICE_PTR"; break;
 	  case OMP_LIST_USE_DEVICE_PTR: type = "USE_DEVICE_PTR"; break;
+	  case OMP_LIST_USE_DEVICE_ADDR: type = "USE_DEVICE_ADDR"; break;
 	  default:
 	    gcc_unreachable ();
 	  }
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 6f7717d1134..a70978bf49b 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1263,6 +1263,7 @@ enum
   OMP_LIST_CACHE,
   OMP_LIST_IS_DEVICE_PTR,
   OMP_LIST_USE_DEVICE_PTR,
+  OMP_LIST_USE_DEVICE_ADDR,
   OMP_LIST_NUM
 };
 
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index bda7f288989..17b0461276a 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -780,6 +780,7 @@ enum omp_mask1
   OMP_CLAUSE_SIMD,
   OMP_CLAUSE_THREADS,
   OMP_CLAUSE_USE_DEVICE_PTR,
+  OMP_CLAUSE_USE_DEVICE_ADDR,  /* Actually, OpenMP 5.0.  */
   OMP_CLAUSE_NOWAIT,
   /* This must come last.  */
   OMP_MASK1_LAST
@@ -1849,6 +1850,11 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 		   ("use_device_ptr (",
 		    &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
 	    continue;
+	  if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR)
+	      && gfc_match_omp_variable_list
+		   ("use_device_addr (",
+		    &c->lists[OMP_LIST_USE_DEVICE_ADDR], false) == MATCH_YES)
+	    continue;
 	  break;
 	case 'v':
 	  /* VECTOR_LENGTH must be matched before VECTOR, because the latter
@@ -2477,7 +2485,7 @@ cleanup:
    | OMP_CLAUSE_IS_DEVICE_PTR)
 #define OMP_TARGET_DATA_CLAUSES \
   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF	\
-   | OMP_CLAUSE_USE_DEVICE_PTR)
+   | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)
 #define OMP_TARGET_ENTER_DATA_CLAUSES \
   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF	\
    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
@@ -4006,7 +4014,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
     = { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
 	"COPYIN", "UNIFORM", "ALIGNED", "LINEAR", "DEPEND", "MAP",
 	"TO", "FROM", "REDUCTION", "DEVICE_RESIDENT", "LINK", "USE_DEVICE",
-	"CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR" };
+	"CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR" };
 
   if (omp_clauses == NULL)
     return;
@@ -4563,7 +4571,25 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 		}
 	    break;
 	  case OMP_LIST_IS_DEVICE_PTR:
+	    if (!n->sym->attr.dummy)
+		  gfc_error ("Non-dummy object %qs in %s clause at %L",
+			     n->sym->name, name, &n->where);
+	    if (n->sym->attr.allocatable
+		|| (n->sym->ts.type == BT_CLASS
+		    && CLASS_DATA (n->sym)->attr.allocatable))
+		  gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
+			     n->sym->name, name, &n->where);
+	    if (n->sym->attr.pointer
+		|| (n->sym->ts.type == BT_CLASS
+		    && CLASS_DATA (n->sym)->attr.pointer))
+		  gfc_error ("POINTER object %qs in %s clause at %L",
+			     n->sym->name, name, &n->where);
+	    if (n->sym->attr.value)
+		  gfc_error ("VALUE object %qs in %s clause at %L",
+			     n->sym->name, name, &n->where);
+	    break;
 	  case OMP_LIST_USE_DEVICE_PTR:
+	  case OMP_LIST_USE_DEVICE_ADDR:
 	    /* FIXME: Handle these.  */
 	    break;
 	  default:
diff --git a/gcc/testsuite/gfortran.dg/gomp/is_device_ptr-1.f90 b/gcc/testsuite/gfortran.dg/gomp/is_device_ptr-1.f90
new file mode 100644
index 00000000000..18211df0ea4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/is_device_ptr-1.f90
@@ -0,0 +1,24 @@
+! { dg-do compile }
+subroutine test(b,c,d)
+  implicit none
+  integer, value, target :: b
+  integer, pointer :: c
+  integer, allocatable, target :: d
+
+  integer, target :: a(5)
+
+  !$omp target is_device_ptr(a) ! { dg-error "Non-dummy object .a. in IS_DEVICE_PTR clause" }
+  !$omp target is_device_ptr(b) ! { dg-error "VALUE object .b. in IS_DEVICE_PTR clause" }
+  !$omp target is_device_ptr(c) ! { dg-error "POINTER object .c. in IS_DEVICE_PTR clause" }
+  !$omp target is_device_ptr(d) ! { dg-error "ALLOCATABLE object .d. in IS_DEVICE_PTR clause" }
+  !$omp end target
+  !$omp end target
+  !$omp end target
+  !$omp end target
+
+  !$omp target data map(a) use_device_addr(a)  ! Should be okay
+  !$omp end target data
+
+  !$omp target data map(c) use_device_ptr(c)  ! Should be okay
+  !$omp end target data
+end subroutine test

Reply via email to