diff mbox series

Fortran/OpenMP: Extend defaultmap clause for OpenMP 5 [PR92568]

Message ID 90ebbf24-6d0f-7964-0586-e5fc4f615b40@codesourcery.com
State New
Headers show
Series Fortran/OpenMP: Extend defaultmap clause for OpenMP 5 [PR92568] | expand

Commit Message

Tobias Burnus June 9, 2021, 12:18 p.m. UTC
This patch add's OpenMP 5.1's  defaultmap extensions to Fortran.

There is one odd thing,
   integer :: ii, it
   target :: it
both count as nonallocatable, nonpointer scalars (i.e. category 'scalar').
But with implicit mapping (and 'defaultmap(default)'), 'it' is mapped
tofrom due to the TARGET attribute (cf. quote in the PR).

I also had fun with scalar vs. pointer, but solved it by adding an
additional argument, which solves the problems with different use.
(nonpointer/nonallocatable scalar vs. all scalars).

Tobias

PS: The run-time testcase (libgomp.fortran/defaultmap-8.f90) shows two
issues (cf. PR fortran/100991 + PR fortran/90742). Namely,
(a) optional scalars are not recognized as scalar (first PR),
(b) firstprivate does not handle absent scalars nor allocatables
(and all complex objects).

PPS:  There seem to be also issues with character handling, at least I get some
run-time errors with -fsanitize=address,undefined for the 'dg-do compile' tests,
which I have not debugged. (I think they are real issues and not test-case
issues, but I have not yet check this.)

PPPS: In principle, also OpenACC should use 'copy'/'map(tofrom:' instead of
'firstprivate' for allocatable/pointer scalars – but testing shows that
this patch does not affect OpenACC (at least not for my testcase).

-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank Thürauf

Comments

Jakub Jelinek June 14, 2021, 4:18 p.m. UTC | #1
On Wed, Jun 09, 2021 at 02:18:43PM +0200, Tobias Burnus wrote:
> This patch add's OpenMP 5.1's  defaultmap extensions to Fortran.
> 
> There is one odd thing,
>   integer :: ii, it
>   target :: it
> both count as nonallocatable, nonpointer scalars (i.e. category 'scalar').
> But with implicit mapping (and 'defaultmap(default)'), 'it' is mapped
> tofrom due to the TARGET attribute (cf. quote in the PR).

The list in 5.1 2.21.7 is ordered, so if defaultmap is present and is
not default, it takes precedence over TARGET attribute.
So, it above with defaultmap(firstprivate:scalar) will result in
firstprivate(it, ii), while no defaultmap or default for it will result in
map(tofrom: it) firstprivate (ii) (same for ALLOCATABLE/POINTER).

> +	  switch ((enum gfc_omp_defaultmap) i)
> +	    {
> +	      case OMP_DFLTMAP_CAT_SCALAR: dfltmap = "SCALAR"; break;
> +	      case OMP_DFLTMAP_CAT_AGGREGATE: dfltmap = "AGGREGATE"; break;
> +	      case OMP_DFLTMAP_CAT_ALLOCATABLE: dfltmap = "ALLOCATABLE"; break;
> +	      case OMP_DFLTMAP_CAT_POINTER: dfltmap = "POINTER"; break;
> +	      default: gcc_unreachable ();

Formatting.  case/default should be indented the same as {.

> --- a/gcc/fortran/gfortran.h
> +++ b/gcc/fortran/gfortran.h
> @@ -1241,6 +1241,29 @@ enum gfc_omp_map_op
>    OMP_MAP_ALWAYS_TOFROM
>  };
>  
> +enum gfc_omp_defaultmap
> +{
> +  OMP_DFLTMAP_UNSET,
> +  OMP_DFLTMAP_ALLOC,
> +  OMP_DFLTMAP_TO,
> +  OMP_DFLTMAP_FROM,
> +  OMP_DFLTMAP_TOFROM,
> +  OMP_DFLTMAP_FIRSTPRIVATE,
> +  OMP_DFLTMAP_NONE,
> +  OMP_DFLTMAP_DEFAULT,
> +  OMP_DFLTMAP_PRESENT

Any reason not to use full OMP_DEFAULTMAP_ ?  The extra 3 chars
will improve readability I think.
> +};
> +
> +enum gfc_omp_dfltmpap_category

Was this meant to be dfltmap rather than mpap?
I think I'd prefer omp_defaultmap_category

> +{
> +  OMP_DFLTMAP_CAT_UNCATEGORIZED,
> +  OMP_DFLTMAP_CAT_SCALAR,
> +  OMP_DFLTMAP_CAT_AGGREGATE,
> +  OMP_DFLTMAP_CAT_ALLOCATABLE,
> +  OMP_DFLTMAP_CAT_POINTER,
> +  OMP_DFLTMAP_CAT_NUM

And same as above.

> +      switch(clauses->defaultmap[i])

Missing space after switch.

> diff --git a/gcc/testsuite/gfortran.dg/gomp/defaultmap-1.f90 b/gcc/testsuite/gfortran.dg/gomp/defaultmap-1.f90
> new file mode 100644
> index 00000000000..299d971f23c

As for the testsuite, I miss the integer, target :: it case
in the gfortran.dg/gomp/defaultmap-*.f90 tests, it is only in the runtime
case if I'm not blind.

	Jakub
Tobias Burnus June 15, 2021, 1:45 p.m. UTC | #2
On 14.06.21 18:18, Jakub Jelinek wrote:

> On Wed, Jun 09, 2021 at 02:18:43PM +0200, Tobias Burnus wrote:
>> This patch add's OpenMP 5.1's  defaultmap extensions to Fortran.
>> There is one odd thing, [...]
> The list in 5.1 2.21.7 is ordered, so if defaultmap is present and is
> not default, it takes precedence over TARGET attribute.
> So, it above with defaultmap(firstprivate:scalar) will result in
> firstprivate(it, ii), while no defaultmap or default for it will result in
> map(tofrom: it) firstprivate (ii) (same for ALLOCATABLE/POINTER).

I think all makes kind of sense (hence, I don't think it is a spec bug) –
but, still, it is a bit unexpected and can easily be overlooked –
both by users and implementors. On the other hand, an unintended implicit
firstprivate for a normal integer/floating-point numbers is probably the
most common issue in real-world code – and that's independent of the
fine print.

  *  * *

Updated patch with the 'd(e)f(au)ltmap' change and other minor
naming/formatting fixes.

Thanks for the review and spotting those!

> As for the testsuite, I miss the integer, target :: it case
> in the gfortran.dg/gomp/defaultmap-*.f90 tests, it is only in the runtime
> case if I'm not blind.

As the filename still indicates, it started as testsuite/ testcase but then
it became too difficult to use -fdump-tree-* to check whether everything was
properly handled (too many D.1234 variables), hence, I turned it into a
'dg-do run' test. This force me to move it to libgomp/.

Thus, for me it is not "only" a runtime case – but "even" a runtime check,
given that the parsing is handled there as well and scan-tree-dump ... gimple
checks are (also) done.

What (other) checks do you would like to see (additionally) in testsuite/ ?
Probably not just cat libgomp/....f90 |sed -e 's/dg-do run/dg-do compile/' > testsuite/...,
I'd guess.

Tobias

-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank Thürauf
Jakub Jelinek June 15, 2021, 2:01 p.m. UTC | #3
On Tue, Jun 15, 2021 at 03:45:15PM +0200, Tobias Burnus wrote:
> 	PR fortran/92568
> 
> gcc/fortran/ChangeLog:
> 
> 	* dump-parse-tree.c (show_omp_clauses): Update for defaultmap.
> 	* f95-lang.c (LANG_HOOKS_OMP_ALLOCATABLE_P,
> 	LANG_HOOKS_OMP_SCALAR_TARGET_P): New.
> 	* gfortran.h (enum gfc_omp_defaultmap,
> 	enum gfc_omp_defaultmap_category): New.
> 	* openmp.c (gfc_match_omp_clauses): Update defaultmap matching.
> 	* trans-decl.c (gfc_finish_decl_attrs): Set GFC_DECL_SCALAR_TARGET.
> 	* trans-openmp.c (gfc_omp_allocatable_p, gfc_omp_scalar_target_p): New.
> 	(gfc_omp_scalar_p): Take 'ptr_alloc_ok' argument.
> 	(gfc_trans_omp_clauses, gfc_split_omp_clauses): Update for
> 	defaultmap changes.
> 	* trans.h (gfc_omp_scalar_p): Update prototype.
> 	(gfc_omp_allocatable_p, gfc_omp_scalar_target_p): New.
> 	(struct lang_decl): Add scalar_target.
> 	(GFC_DECL_SCALAR_TARGET, GFC_DECL_GET_SCALAR_TARGET): New.
> 
> gcc/ChangeLog:
> 
> 	* gimplify.c (enum gimplify_defaultmap_kind): Add GDMK_SCALAR_TARGET.
> 	(struct gimplify_omp_ctx): Extend defaultmap array by one.
> 	(new_omp_context): Init defaultmap[GDMK_SCALAR_TARGET].
> 	(omp_notice_variable): Update type classification for Fortran.
> 	(gimplify_scan_omp_clauses): Update calls for new argument; handle
> 	GDMK_SCALAR_TARGET; for Fortran, GDMK_POINTER avoid GOVD_MAP_0LEN_ARRAY.
> 	* langhooks-def.h (lhd_omp_scalar_p): Add 'ptr_ok' argument.
> 	* langhooks.c (lhd_omp_scalar_p): Likewise.
> 	(LANG_HOOKS_OMP_ALLOCATABLE_P, LANG_HOOKS_OMP_SCALAR_TARGET_P): New.
> 	(LANG_HOOKS_DECLS): Add them.
> 	* langhooks.h (struct lang_hooks_for_decls): Add new hooks, update
> 	omp_scalar_p pointer type to include the new bool argument.
> 
> libgomp/ChangeLog:
> 
> 	* testsuite/libgomp.fortran/defaultmap-8.f90: New test.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gfortran.dg/gomp/pr99928-1.f90: Uncomment 'defaultmap(none)'.
> 	* gfortran.dg/gomp/pr99928-2.f90: Uncomment 'defaultmap(none)'.
> 	* gfortran.dg/gomp/pr99928-3.f90: Uncomment 'defaultmap(none)'.
> 	* gfortran.dg/gomp/pr99928-4.f90: Uncomment 'defaultmap(none)'.
> 	* gfortran.dg/gomp/pr99928-5.f90: Uncomment 'defaultmap(none)'.
> 	* gfortran.dg/gomp/pr99928-6.f90: Uncomment 'defaultmap(none)'.
> 	* gfortran.dg/gomp/pr99928-8.f90: Uncomment 'defaultmap(none)'.
> 	* gfortran.dg/gomp/defaultmap-1.f90: New test.
> 	* gfortran.dg/gomp/defaultmap-2.f90: New test.
> 	* gfortran.dg/gomp/defaultmap-3.f90: New test.
> 	* gfortran.dg/gomp/defaultmap-4.f90: New test.
> 	* gfortran.dg/gomp/defaultmap-5.f90: New test.
> 	* gfortran.dg/gomp/defaultmap-6.f90: New test.
> 	* gfortran.dg/gomp/defaultmap-7.f90: New test.

LGTM, thanks.

	Jakub
Martin Liška June 23, 2021, 2:13 p.m. UTC | #4
Hello.

I noticed the patch causes the following clang warnings:

gcc/fortran/dump-parse-tree.c:1786:11: warning: comparison of different enumeration types in switch statement ('enum gfc_omp_defaultmap' and 'gfc_omp_defaultmap_category') [-Wenum-compare-switch]
gcc/fortran/dump-parse-tree.c:1787:11: warning: comparison of different enumeration types in switch statement ('enum gfc_omp_defaultmap' and 'gfc_omp_defaultmap_category') [-Wenum-compare-switch]
gcc/fortran/dump-parse-tree.c:1788:11: warning: comparison of different enumeration types in switch statement ('enum gfc_omp_defaultmap' and 'gfc_omp_defaultmap_category') [-Wenum-compare-switch]
gcc/fortran/dump-parse-tree.c:1789:11: warning: comparison of different enumeration types in switch statement ('enum gfc_omp_defaultmap' and 'gfc_omp_defaultmap_category') [-Wenum-compare-switch]

Can you please take a look?
Martin
diff mbox series

Patch

Fortran/OpenMP: Extend defaultmap clause for OpenMP 5 [PR92568]

	PR fortran/92568

gcc/fortran/ChangeLog:

	* dump-parse-tree.c (show_omp_clauses): Update for defaultmap.
	* f95-lang.c (LANG_HOOKS_OMP_ALLOCATABLE_P,
	LANG_HOOKS_OMP_SCALAR_TARGET_P): New.
	* gfortran.h (enum gfc_omp_defaultmap,
	enum gfc_omp_dfltmpap_category): New.
	* openmp.c (gfc_match_omp_clauses): Update defaultmap matching.
	* trans-decl.c (gfc_finish_decl_attrs): Set GFC_DECL_SCALAR_TARGET.
	* trans-openmp.c (gfc_omp_allocatable_p, gfc_omp_scalar_target_p): New.
	(gfc_omp_scalar_p): Take 'ptr_alloc_ok' argument.
	(gfc_trans_omp_clauses, gfc_split_omp_clauses): Update for
	defaultmap changes.
	* trans.h (gfc_omp_scalar_p): Update prototype.
	(gfc_omp_allocatable_p, gfc_omp_scalar_target_p): New.
	(struct lang_decl): Add scalar_target.
	(GFC_DECL_SCALAR_TARGET, GFC_DECL_GET_SCALAR_TARGET): New.

gcc/ChangeLog:

	* gimplify.c (enum gimplify_defaultmap_kind): Add GDMK_SCALAR_TARGET.
	(struct gimplify_omp_ctx): Extend defaultmap array by one.
	(new_omp_context): Init defaultmap[GDMK_SCALAR_TARGET].
	(omp_notice_variable): Update type classification for Fortran.
	(gimplify_scan_omp_clauses): Update calls for new argument; handle
	GDMK_SCALAR_TARGET; for Fortran, GDMK_POINTER avoid GOVD_MAP_0LEN_ARRAY.
	* langhooks-def.h (lhd_omp_scalar_p): Add 'ptr_ok' argument.
	* langhooks.c (lhd_omp_scalar_p): Likewise.
	(LANG_HOOKS_OMP_ALLOCATABLE_P, LANG_HOOKS_OMP_SCALAR_TARGET_P): New.
	(LANG_HOOKS_DECLS): Add them.
	* langhooks.h (struct lang_hooks_for_decls): Add new hooks, update
	omp_scalar_p pointer type to include the new bool argument.

libgomp/ChangeLog:

	* testsuite/libgomp.fortran/defaultmap-8.f90: New test.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/pr99928-1.f90: Uncomment 'defaultmap(none)'.
	* gfortran.dg/gomp/pr99928-2.f90: Uncomment 'defaultmap(none)'.
	* gfortran.dg/gomp/pr99928-3.f90: Uncomment 'defaultmap(none)'.
	* gfortran.dg/gomp/pr99928-4.f90: Uncomment 'defaultmap(none)'.
	* gfortran.dg/gomp/pr99928-5.f90: Uncomment 'defaultmap(none)'.
	* gfortran.dg/gomp/pr99928-6.f90: Uncomment 'defaultmap(none)'.
	* gfortran.dg/gomp/pr99928-8.f90: Uncomment 'defaultmap(none)'.
	* gfortran.dg/gomp/defaultmap-1.f90: New test.
	* gfortran.dg/gomp/defaultmap-2.f90: New test.
	* gfortran.dg/gomp/defaultmap-3.f90: New test.
	* gfortran.dg/gomp/defaultmap-4.f90: New test.
	* gfortran.dg/gomp/defaultmap-5.f90: New test.
	* gfortran.dg/gomp/defaultmap-6.f90: New test.
	* gfortran.dg/gomp/defaultmap-7.f90: New test.

 gcc/fortran/dump-parse-tree.c                      |  38 ++-
 gcc/fortran/f95-lang.c                             |   4 +
 gcc/fortran/gfortran.h                             |  26 +-
 gcc/fortran/openmp.c                               |  83 +++++-
 gcc/fortran/trans-decl.c                           |   5 +
 gcc/fortran/trans-openmp.c                         |  91 ++++++-
 gcc/fortran/trans.h                                |   9 +-
 gcc/gimplify.c                                     |  35 ++-
 gcc/langhooks-def.h                                |   6 +-
 gcc/langhooks.c                                    |   7 +-
 gcc/langhooks.h                                    |  13 +-
 gcc/testsuite/gfortran.dg/gomp/defaultmap-1.f90    |  19 ++
 gcc/testsuite/gfortran.dg/gomp/defaultmap-2.f90    | 108 ++++++++
 gcc/testsuite/gfortran.dg/gomp/defaultmap-3.f90    |  60 +++++
 gcc/testsuite/gfortran.dg/gomp/defaultmap-4.f90    | 141 +++++++++++
 gcc/testsuite/gfortran.dg/gomp/defaultmap-5.f90    | 145 +++++++++++
 gcc/testsuite/gfortran.dg/gomp/defaultmap-6.f90    | 104 ++++++++
 gcc/testsuite/gfortran.dg/gomp/defaultmap-7.f90    |  24 ++
 gcc/testsuite/gfortran.dg/gomp/pr99928-1.f90       |  22 +-
 gcc/testsuite/gfortran.dg/gomp/pr99928-2.f90       |  18 +-
 gcc/testsuite/gfortran.dg/gomp/pr99928-3.f90       |   6 +-
 gcc/testsuite/gfortran.dg/gomp/pr99928-4.f90       |   6 +-
 gcc/testsuite/gfortran.dg/gomp/pr99928-5.f90       |   8 +-
 gcc/testsuite/gfortran.dg/gomp/pr99928-6.f90       |   8 +-
 gcc/testsuite/gfortran.dg/gomp/pr99928-8.f90       |  22 +-
 libgomp/testsuite/libgomp.fortran/defaultmap-8.f90 | 279 +++++++++++++++++++++
 26 files changed, 1210 insertions(+), 77 deletions(-)

diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 141101e699d..9ade2a8c464 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1751,7 +1751,7 @@  show_omp_clauses (gfc_omp_clauses *omp_clauses)
     }
   if (omp_clauses->dist_sched_kind != OMP_SCHED_NONE)
     {
-      fprintf (dumpfile, " DIST_SCHEDULE (STATIC");
+      fputs (" DIST_SCHEDULE (STATIC", dumpfile);
       if (omp_clauses->dist_chunk_size)
 	{
 	  fputc (',', dumpfile);
@@ -1759,8 +1759,40 @@  show_omp_clauses (gfc_omp_clauses *omp_clauses)
 	}
       fputc (')', dumpfile);
     }
-  if (omp_clauses->defaultmap)
-    fputs (" DEFALTMAP (TOFROM: SCALAR)", dumpfile);
+  for (int i = 0; i < OMP_DFLTMAP_CAT_NUM; i++)
+    {
+      const char *dfltmap;
+      if (omp_clauses->defaultmap[i] == OMP_DFLTMAP_UNSET)
+	continue;
+      fputs (" DEFAULTMAP (", dumpfile);
+      switch (omp_clauses->defaultmap[i])
+	{
+	case OMP_DFLTMAP_ALLOC: dfltmap = "ALLOC"; break;
+	case OMP_DFLTMAP_TO: dfltmap = "TO"; break;
+	case OMP_DFLTMAP_FROM: dfltmap = "FROM"; break;
+	case OMP_DFLTMAP_TOFROM: dfltmap = "TOFROM"; break;
+	case OMP_DFLTMAP_FIRSTPRIVATE: dfltmap = "FIRSTPRIVATE"; break;
+	case OMP_DFLTMAP_NONE: dfltmap = "NONE"; break;
+	case OMP_DFLTMAP_DEFAULT: dfltmap = "DEFAULT"; break;
+	case OMP_DFLTMAP_PRESENT: dfltmap = "PRESENT"; break;
+	default: gcc_unreachable ();
+	}
+      fputs (dfltmap, dumpfile);
+      if (i != OMP_DFLTMAP_CAT_UNCATEGORIZED)
+	{
+	  fputc (':', dumpfile);
+	  switch ((enum gfc_omp_defaultmap) i)
+	    {
+	      case OMP_DFLTMAP_CAT_SCALAR: dfltmap = "SCALAR"; break;
+	      case OMP_DFLTMAP_CAT_AGGREGATE: dfltmap = "AGGREGATE"; break;
+	      case OMP_DFLTMAP_CAT_ALLOCATABLE: dfltmap = "ALLOCATABLE"; break;
+	      case OMP_DFLTMAP_CAT_POINTER: dfltmap = "POINTER"; break;
+	      default: gcc_unreachable ();
+	    }
+	  fputs (dfltmap, dumpfile);
+	}
+      fputc (')', dumpfile);
+    }
   if (omp_clauses->nogroup)
     fputs (" NOGROUP", dumpfile);
   if (omp_clauses->simd)
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index a346457b5e0..5fc848158f9 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -126,6 +126,8 @@  static const struct attribute_spec gfc_attribute_table[] =
 #undef LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR
 #undef LANG_HOOKS_OMP_CLAUSE_DTOR
 #undef LANG_HOOKS_OMP_FINISH_CLAUSE
+#undef LANG_HOOKS_OMP_ALLOCATABLE_P
+#undef LANG_HOOKS_OMP_SCALAR_TARGET_P
 #undef LANG_HOOKS_OMP_SCALAR_P
 #undef LANG_HOOKS_OMP_DISREGARD_VALUE_EXPR
 #undef LANG_HOOKS_OMP_PRIVATE_DEBUG_CLAUSE
@@ -162,7 +164,9 @@  static const struct attribute_spec gfc_attribute_table[] =
 #define LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR	gfc_omp_clause_linear_ctor
 #define LANG_HOOKS_OMP_CLAUSE_DTOR		gfc_omp_clause_dtor
 #define LANG_HOOKS_OMP_FINISH_CLAUSE		gfc_omp_finish_clause
+#define LANG_HOOKS_OMP_ALLOCATABLE_P		gfc_omp_allocatable_p
 #define LANG_HOOKS_OMP_SCALAR_P			gfc_omp_scalar_p
+#define LANG_HOOKS_OMP_SCALAR_TARGET_P		gfc_omp_scalar_target_p
 #define LANG_HOOKS_OMP_DISREGARD_VALUE_EXPR	gfc_omp_disregard_value_expr
 #define LANG_HOOKS_OMP_PRIVATE_DEBUG_CLAUSE	gfc_omp_private_debug_clause
 #define LANG_HOOKS_OMP_PRIVATE_OUTER_REF	gfc_omp_private_outer_ref
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index cbc95d3726d..26bd4a3ada6 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1241,6 +1241,29 @@  enum gfc_omp_map_op
   OMP_MAP_ALWAYS_TOFROM
 };
 
+enum gfc_omp_defaultmap
+{
+  OMP_DFLTMAP_UNSET,
+  OMP_DFLTMAP_ALLOC,
+  OMP_DFLTMAP_TO,
+  OMP_DFLTMAP_FROM,
+  OMP_DFLTMAP_TOFROM,
+  OMP_DFLTMAP_FIRSTPRIVATE,
+  OMP_DFLTMAP_NONE,
+  OMP_DFLTMAP_DEFAULT,
+  OMP_DFLTMAP_PRESENT
+};
+
+enum gfc_omp_dfltmpap_category
+{
+  OMP_DFLTMAP_CAT_UNCATEGORIZED,
+  OMP_DFLTMAP_CAT_SCALAR,
+  OMP_DFLTMAP_CAT_AGGREGATE,
+  OMP_DFLTMAP_CAT_ALLOCATABLE,
+  OMP_DFLTMAP_CAT_POINTER,
+  OMP_DFLTMAP_CAT_NUM
+};
+
 enum gfc_omp_linear_op
 {
   OMP_LINEAR_DEFAULT,
@@ -1423,9 +1446,10 @@  typedef struct gfc_omp_clauses
   enum gfc_omp_device_type device_type;
   struct gfc_expr *chunk_size;
   enum gfc_omp_default_sharing default_sharing;
+  enum gfc_omp_defaultmap defaultmap[OMP_DFLTMAP_CAT_NUM];
   int collapse, orderedc;
   bool nowait, ordered, untied, mergeable;
-  bool inbranch, notinbranch, defaultmap, nogroup;
+  bool inbranch, notinbranch, nogroup;
   bool sched_simd, sched_monotonic, sched_nonmonotonic;
   bool simd, threads, depend_source, destroy, order_concurrent, capture;
   enum gfc_omp_atomic_op atomic_op;
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 638a8233604..b9ab53c804b 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -1539,10 +1539,86 @@  gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 		continue;
 	    }
 	  if ((mask & OMP_CLAUSE_DEFAULTMAP)
-	      && !c->defaultmap
-	      && gfc_match ("defaultmap ( tofrom : scalar )") == MATCH_YES)
+	      && gfc_match ("defaultmap ( ") == MATCH_YES)
 	    {
-	      c->defaultmap = true;
+	      enum gfc_omp_defaultmap behavior;
+	      gfc_omp_dfltmpap_category category = OMP_DFLTMAP_CAT_UNCATEGORIZED;
+	      if (gfc_match ("alloc ") == MATCH_YES)
+		behavior = OMP_DFLTMAP_ALLOC;
+	      else if (gfc_match ("tofrom ") == MATCH_YES)
+		behavior = OMP_DFLTMAP_TOFROM;
+	      else if (gfc_match ("to ") == MATCH_YES)
+		behavior = OMP_DFLTMAP_TO;
+	      else if (gfc_match ("from ") == MATCH_YES)
+		behavior = OMP_DFLTMAP_FROM;
+	      else if (gfc_match ("firstprivate ") == MATCH_YES)
+		behavior = OMP_DFLTMAP_FIRSTPRIVATE;
+	      else if (gfc_match ("none ") == MATCH_YES)
+		behavior = OMP_DFLTMAP_NONE;
+	      else if (gfc_match ("default ") == MATCH_YES)
+		behavior = OMP_DFLTMAP_DEFAULT;
+	      else
+		{
+		  gfc_error ("Expected ALLOC, TO, FROM, TOFROM, FIRSTPRIVATE, "
+			   "NONE or DEFAULT at %C");
+		  break;
+		}
+	      if (')' == gfc_peek_ascii_char ())
+		;
+	      else if (gfc_match (": ") != MATCH_YES)
+		break;
+	      else
+		{
+		  if (gfc_match ("scalar ") == MATCH_YES)
+		    category = OMP_DFLTMAP_CAT_SCALAR;
+		  else if (gfc_match ("aggregate ") == MATCH_YES)
+		    category = OMP_DFLTMAP_CAT_AGGREGATE;
+		  else if (gfc_match ("allocatable ") == MATCH_YES)
+		    category = OMP_DFLTMAP_CAT_ALLOCATABLE;
+		  else if (gfc_match ("pointer ") == MATCH_YES)
+		    category = OMP_DFLTMAP_CAT_POINTER;
+		  else
+		    {
+		      gfc_error ("Expected SCALAR, AGGREGATE, ALLOCATABLE or "
+				 "POINTER at %C");
+		      break;
+		    }
+		}
+	      for (int i = 0; i < OMP_DFLTMAP_CAT_NUM; ++i)
+		{
+		  if (i != category
+		      && category != OMP_DFLTMAP_CAT_UNCATEGORIZED)
+		    continue;
+		  if (c->defaultmap[i] != OMP_DFLTMAP_UNSET)
+		    {
+		      const char *pcategory = NULL;
+		      switch (i)
+			{
+			case OMP_DFLTMAP_CAT_UNCATEGORIZED: break;
+			case OMP_DFLTMAP_CAT_SCALAR: pcategory = "SCALAR"; break;
+			case OMP_DFLTMAP_CAT_AGGREGATE:
+			  pcategory = "AGGREGATE";
+			  break;
+			case OMP_DFLTMAP_CAT_ALLOCATABLE:
+			  pcategory = "ALLOCATABLE";
+			  break;
+			case OMP_DFLTMAP_CAT_POINTER:
+			  pcategory = "POINTER";
+			  break;
+			default: gcc_unreachable ();
+			}
+		     if (i == OMP_DFLTMAP_CAT_UNCATEGORIZED)
+		      gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP with "
+				 "unspecified category");
+		     else
+		      gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP for "
+				 "category %s", pcategory);
+		     goto end;
+		    }
+		}
+	      c->defaultmap[category] = behavior;
+	      if (gfc_match (")") != MATCH_YES)
+		break;
 	      continue;
 	    }
 	  if ((mask & OMP_CLAUSE_DELETE)
@@ -2459,6 +2535,7 @@  gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
       break;
     }
 
+end:
   if (gfc_match_omp_eos () != MATCH_YES)
     {
       if (!gfc_error_flag_test ())
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index c32bd05bb1b..479ba6fa6ce 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -605,6 +605,11 @@  gfc_finish_decl_attrs (tree decl, symbol_attribute *attr)
 	  gfc_allocate_lang_decl (decl);
 	  GFC_DECL_SCALAR_POINTER (decl) = 1;
 	}
+      if (attr->target)
+	{
+	  gfc_allocate_lang_decl (decl);
+	  GFC_DECL_SCALAR_TARGET (decl) = 1;
+	}
     }
 }
 
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index f466ab675c3..077e108e17f 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -393,6 +393,28 @@  gfc_is_unlimited_polymorphic_nonptr (tree type)
   return true;
 }
 
+/* Return true if the DECL is for an allocatable array or scalar.  */
+
+bool
+gfc_omp_allocatable_p (tree decl)
+{
+  if (!DECL_P (decl))
+    return false;
+
+  if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
+    return true;
+
+  tree type = TREE_TYPE (decl);
+  if (gfc_omp_privatize_by_reference (decl))
+    type = TREE_TYPE (type);
+
+  if (GFC_DESCRIPTOR_TYPE_P (type)
+      && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
+    return true;
+
+  return false;
+}
+
 
 /* Return true if DECL in private clause needs
    OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause.  */
@@ -1663,10 +1685,11 @@  gfc_omp_finish_clause (tree c, gimple_seq *pre_p, bool openacc)
 
 
 /* Return true if DECL is a scalar variable (for the purpose of
-   implicit firstprivatization).  */
+   implicit firstprivatization/mapping). Only if 'ptr_alloc_ok.'
+   is true, allocatables and pointers are permitted. */
 
 bool
-gfc_omp_scalar_p (tree decl)
+gfc_omp_scalar_p (tree decl, bool ptr_alloc_ok)
 {
   tree type = TREE_TYPE (decl);
   if (TREE_CODE (type) == REFERENCE_TYPE)
@@ -1675,7 +1698,11 @@  gfc_omp_scalar_p (tree decl)
     {
       if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
 	  || GFC_DECL_GET_SCALAR_POINTER (decl))
-	type = TREE_TYPE (type);
+	{
+	  if (!ptr_alloc_ok)
+	    return false;
+	  type = TREE_TYPE (type);
+	}
       if (GFC_ARRAY_TYPE_P (type)
 	  || GFC_CLASS_TYPE_P (type))
 	return false;
@@ -1691,6 +1718,17 @@  gfc_omp_scalar_p (tree decl)
 }
 
 
+/* Return true if DECL is a scalar with target attribute but does not have the
+   allocatable (or pointer) attribute (for the purpose of implicit mapping).  */
+
+bool
+gfc_omp_scalar_target_p (tree decl)
+{
+  return (DECL_P (decl) && GFC_DECL_GET_SCALAR_TARGET (decl)
+	  && gfc_omp_scalar_p (decl, false));
+}
+
+
 /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
    disregarded in OpenMP construct, because it is going to be
    remapped during OpenMP lowering.  SHARED is true if DECL
@@ -4036,13 +4074,49 @@  gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOGROUP);
       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
     }
-  if (clauses->defaultmap)
+
+  for (int i = 0; i < OMP_DFLTMAP_CAT_NUM; i++)
     {
+      if (clauses->defaultmap[i] == OMP_DFLTMAP_UNSET)
+       continue;
+      enum omp_clause_defaultmap_kind behavior, category;
+      switch ((gfc_omp_dfltmpap_category) i)
+	{
+	case OMP_DFLTMAP_CAT_UNCATEGORIZED:
+	  category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
+	  break;
+	case OMP_DFLTMAP_CAT_SCALAR:
+	  category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
+	  break;
+	case OMP_DFLTMAP_CAT_AGGREGATE:
+	  category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
+	  break;
+	case OMP_DFLTMAP_CAT_ALLOCATABLE:
+	  category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE;
+	  break;
+	case OMP_DFLTMAP_CAT_POINTER:
+	  category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
+	  break;
+	default: gcc_unreachable ();
+	}
+      switch(clauses->defaultmap[i])
+	{
+	case OMP_DFLTMAP_ALLOC: behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC; break;
+	case OMP_DFLTMAP_TO: behavior = OMP_CLAUSE_DEFAULTMAP_TO; break;
+	case OMP_DFLTMAP_FROM: behavior = OMP_CLAUSE_DEFAULTMAP_FROM; break;
+	case OMP_DFLTMAP_TOFROM: behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM; break;
+	case OMP_DFLTMAP_FIRSTPRIVATE:
+	  behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
+	  break;
+	case OMP_DFLTMAP_NONE: behavior = OMP_CLAUSE_DEFAULTMAP_NONE; break;
+	case OMP_DFLTMAP_DEFAULT: behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT; break;
+	default: gcc_unreachable ();
+	}
       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULTMAP);
-      OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, OMP_CLAUSE_DEFAULTMAP_TOFROM,
-				      OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR);
+      OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
     }
+
   if (clauses->depend_source)
     {
       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEPEND);
@@ -5672,8 +5746,9 @@  gfc_split_omp_clauses (gfc_code *code,
 	    = code->ext.omp_clauses->lists[OMP_LIST_IS_DEVICE_PTR];
 	  clausesa[GFC_OMP_SPLIT_TARGET].device
 	    = code->ext.omp_clauses->device;
-	  clausesa[GFC_OMP_SPLIT_TARGET].defaultmap
-	    = code->ext.omp_clauses->defaultmap;
+	  for (int i = 0; i < OMP_DFLTMAP_CAT_NUM; i++)
+	    clausesa[GFC_OMP_SPLIT_TARGET].defaultmap[i]
+	      = code->ext.omp_clauses->defaultmap[i];
 	  clausesa[GFC_OMP_SPLIT_TARGET].if_exprs[OMP_IF_TARGET]
 	    = code->ext.omp_clauses->if_exprs[OMP_IF_TARGET];
 	  /* And this is copied to all.  */
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index d1d4a1d6a92..78578cfd732 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -823,7 +823,9 @@  tree gfc_omp_clause_assign_op (tree, tree, tree);
 tree gfc_omp_clause_linear_ctor (tree, tree, tree, tree);
 tree gfc_omp_clause_dtor (tree, tree);
 void gfc_omp_finish_clause (tree, gimple_seq *, bool);
-bool gfc_omp_scalar_p (tree);
+bool gfc_omp_allocatable_p (tree);
+bool gfc_omp_scalar_p (tree, bool);
+bool gfc_omp_scalar_target_p (tree);
 bool gfc_omp_disregard_value_expr (tree, bool);
 bool gfc_omp_private_debug_clause (tree, bool);
 bool gfc_omp_private_outer_ref (tree);
@@ -1030,6 +1032,7 @@  struct GTY(()) lang_decl {
   tree token, caf_offset;
   unsigned int scalar_allocatable : 1;
   unsigned int scalar_pointer : 1;
+  unsigned int scalar_target : 1;
   unsigned int optional_arg : 1;
 };
 
@@ -1044,12 +1047,16 @@  struct GTY(()) lang_decl {
   (DECL_LANG_SPECIFIC (node)->scalar_allocatable)
 #define GFC_DECL_SCALAR_POINTER(node) \
   (DECL_LANG_SPECIFIC (node)->scalar_pointer)
+#define GFC_DECL_SCALAR_TARGET(node) \
+  (DECL_LANG_SPECIFIC (node)->scalar_target)
 #define GFC_DECL_OPTIONAL_ARGUMENT(node) \
   (DECL_LANG_SPECIFIC (node)->optional_arg)
 #define GFC_DECL_GET_SCALAR_ALLOCATABLE(node) \
   (DECL_LANG_SPECIFIC (node) ? GFC_DECL_SCALAR_ALLOCATABLE (node) : 0)
 #define GFC_DECL_GET_SCALAR_POINTER(node) \
   (DECL_LANG_SPECIFIC (node) ? GFC_DECL_SCALAR_POINTER (node) : 0)
+#define GFC_DECL_GET_SCALAR_TARGET(node) \
+  (DECL_LANG_SPECIFIC (node) ? GFC_DECL_SCALAR_TARGET (node) : 0)
 #define GFC_DECL_PACKED_ARRAY(node) DECL_LANG_FLAG_0(node)
 #define GFC_DECL_PARTIAL_PACKED_ARRAY(node) DECL_LANG_FLAG_1(node)
 #define GFC_DECL_ASSIGN(node) DECL_LANG_FLAG_2(node)
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 39f5b973d18..65b6454528b 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -212,6 +212,7 @@  struct gimplify_ctx
 enum gimplify_defaultmap_kind
 {
   GDMK_SCALAR,
+  GDMK_SCALAR_TARGET, /* w/ Fortran's target attr, implicit mapping, only.  */
   GDMK_AGGREGATE,
   GDMK_ALLOCATABLE,
   GDMK_POINTER
@@ -236,7 +237,7 @@  struct gimplify_omp_ctx
   bool order_concurrent;
   bool has_depend;
   bool in_for_exprs;
-  int defaultmap[4];
+  int defaultmap[5];
 };
 
 static struct gimplify_ctx *gimplify_ctxp;
@@ -461,6 +462,7 @@  new_omp_context (enum omp_region_type region_type)
   else
     c->default_kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
   c->defaultmap[GDMK_SCALAR] = GOVD_MAP;
+  c->defaultmap[GDMK_SCALAR_TARGET] = GOVD_MAP;
   c->defaultmap[GDMK_AGGREGATE] = GOVD_MAP;
   c->defaultmap[GDMK_ALLOCATABLE] = GOVD_MAP;
   c->defaultmap[GDMK_POINTER] = GOVD_MAP;
@@ -7503,13 +7505,17 @@  omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
 		{
 		  int gdmk;
 		  enum omp_clause_defaultmap_kind kind;
-		  if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
-		      || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
-			  && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
-			      == POINTER_TYPE)))
-		    gdmk = GDMK_POINTER;
-		  else if (lang_hooks.decls.omp_scalar_p (decl))
+		  if (lang_hooks.decls.omp_allocatable_p (decl))
+		    gdmk = GDMK_ALLOCATABLE;
+		  else if (lang_hooks.decls.omp_scalar_target_p (decl))
+		    gdmk = GDMK_SCALAR_TARGET;
+		  else if (lang_hooks.decls.omp_scalar_p (decl, false))
 		    gdmk = GDMK_SCALAR;
+		  else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
+			   || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
+			       && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
+				   == POINTER_TYPE)))
+		    gdmk = GDMK_POINTER;
 		  else
 		    gdmk = GDMK_AGGREGATE;
 		  kind = lang_hooks.decls.omp_predetermined_mapping (decl);
@@ -8746,6 +8752,8 @@  gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
       if (!lang_GNU_Fortran ())
 	ctx->defaultmap[GDMK_POINTER] = GOVD_MAP | GOVD_MAP_0LEN_ARRAY;
       ctx->defaultmap[GDMK_SCALAR] = GOVD_FIRSTPRIVATE;
+      ctx->defaultmap[GDMK_SCALAR_TARGET] = (lang_GNU_Fortran ()
+					     ? GOVD_MAP : GOVD_FIRSTPRIVATE);
     }
   if (!lang_GNU_Fortran ())
     switch (code)
@@ -8827,7 +8835,7 @@  gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
 	  if (error_operand_p (decl))
 	    goto do_add;
 	  if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
-	      && !lang_hooks.decls.omp_scalar_p (decl))
+	      && !lang_hooks.decls.omp_scalar_p (decl, true))
 	    {
 	      error_at (OMP_CLAUSE_LOCATION (c),
 			"non-scalar variable %qD in conditional "
@@ -10025,7 +10033,8 @@  gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
 	      gdmkmax = GDMK_POINTER;
 	      break;
 	    case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
-	      gdmkmin = gdmkmax = GDMK_SCALAR;
+	      gdmkmin = GDMK_SCALAR;
+	      gdmkmax = GDMK_SCALAR_TARGET;
 	      break;
 	    case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
 	      gdmkmin = gdmkmax = GDMK_AGGREGATE;
@@ -10066,12 +10075,18 @@  gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
 		  case GDMK_SCALAR:
 		    ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
 		    break;
+		  case GDMK_SCALAR_TARGET:
+		    ctx->defaultmap[gdmk] = (lang_GNU_Fortran ()
+					     ? GOVD_MAP : GOVD_FIRSTPRIVATE);
+		    break;
 		  case GDMK_AGGREGATE:
 		  case GDMK_ALLOCATABLE:
 		    ctx->defaultmap[gdmk] = GOVD_MAP;
 		    break;
 		  case GDMK_POINTER:
-		    ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_0LEN_ARRAY;
+		    ctx->defaultmap[gdmk] = GOVD_MAP;
+		    if (!lang_GNU_Fortran ())
+		      ctx->defaultmap[gdmk] |= GOVD_MAP_0LEN_ARRAY;
 		    break;
 		  default:
 		    gcc_unreachable ();
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index ae3991c770a..8b744d96fb2 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -86,7 +86,7 @@  struct gimplify_omp_ctx;
 extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
 					       tree);
 extern bool lhd_omp_mappable_type (tree);
-extern bool lhd_omp_scalar_p (tree);
+extern bool lhd_omp_scalar_p (tree, bool);
 extern tree *lhd_omp_get_decl_init (tree);
 extern void lhd_omp_finish_decl_inits ();
 
@@ -266,7 +266,9 @@  extern tree lhd_unit_size_without_reusable_padding (tree);
 #define LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR NULL
 #define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null
 #define LANG_HOOKS_OMP_FINISH_CLAUSE lhd_omp_finish_clause
+#define LANG_HOOKS_OMP_ALLOCATABLE_P hook_bool_tree_false
 #define LANG_HOOKS_OMP_SCALAR_P lhd_omp_scalar_p
+#define LANG_HOOKS_OMP_SCALAR_TARGET_P hook_bool_tree_false
 #define LANG_HOOKS_OMP_GET_DECL_INIT lhd_omp_get_decl_init
 #define LANG_HOOKS_OMP_FINISH_DECL_INITS lhd_omp_finish_decl_inits
 
@@ -297,7 +299,9 @@  extern tree lhd_unit_size_without_reusable_padding (tree);
   LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR, \
   LANG_HOOKS_OMP_CLAUSE_DTOR, \
   LANG_HOOKS_OMP_FINISH_CLAUSE, \
+  LANG_HOOKS_OMP_ALLOCATABLE_P, \
   LANG_HOOKS_OMP_SCALAR_P, \
+  LANG_HOOKS_OMP_SCALAR_TARGET_P, \
   LANG_HOOKS_OMP_GET_DECL_INIT, \
   LANG_HOOKS_OMP_FINISH_DECL_INITS \
 }
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 12c99888e6c..d753199ffe0 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -615,10 +615,11 @@  lhd_omp_finish_clause (tree, gimple_seq *, bool)
 }
 
 /* Return true if DECL is a scalar variable (for the purpose of
-   implicit firstprivatization).  */
+   implicit firstprivatization & mapping). Only if alloc_ptr_ok
+   are allocatables and pointers accepted. */
 
 bool
-lhd_omp_scalar_p (tree decl)
+lhd_omp_scalar_p (tree decl, bool ptr_ok)
 {
   tree type = TREE_TYPE (decl);
   if (TREE_CODE (type) == REFERENCE_TYPE)
@@ -627,7 +628,7 @@  lhd_omp_scalar_p (tree decl)
     type = TREE_TYPE (type);
   if (INTEGRAL_TYPE_P (type)
       || SCALAR_FLOAT_TYPE_P (type)
-      || TREE_CODE (type) == POINTER_TYPE)
+      || (ptr_ok && TREE_CODE (type) == POINTER_TYPE))
     return true;
   return false;
 }
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 842e605c439..1b417a01a4e 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -296,9 +296,18 @@  struct lang_hooks_for_decls
   /* Do language specific checking on an implicitly determined clause.  */
   void (*omp_finish_clause) (tree clause, gimple_seq *pre_p, bool);
 
+  /* Return true if DECL is an allocatable variable (for the purpose of
+     implicit mapping).  */
+  bool (*omp_allocatable_p) (tree decl);
+
   /* Return true if DECL is a scalar variable (for the purpose of
-     implicit firstprivatization).  */
-  bool (*omp_scalar_p) (tree decl);
+     implicit firstprivatization). If 'ptr_or', pointers and
+     allocatables are also permitted.  */
+  bool (*omp_scalar_p) (tree decl, bool ptr_ok);
+
+  /* Return true if DECL is a scalar variable with Fortran target but not
+     allocatable or pointer attribute (for the purpose of implicit mapping).  */
+  bool (*omp_scalar_target_p) (tree decl);
 
   /* Return a pointer to the tree representing the initializer
      expression for the non-local variable DECL.  Return NULL if
diff --git a/gcc/testsuite/gfortran.dg/gomp/defaultmap-1.f90 b/gcc/testsuite/gfortran.dg/gomp/defaultmap-1.f90
new file mode 100644
index 00000000000..299d971f23c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/defaultmap-1.f90
@@ -0,0 +1,19 @@ 
+! PR fortran/92568
+
+implicit none
+
+!$omp target defaultmap(bar)  ! { dg-error "25: Expected ALLOC, TO, FROM, TOFROM, FIRSTPRIVATE, NONE or DEFAULT" }
+
+!$omp target defaultmap ( alloc: foo)  ! { dg-error "34: Expected SCALAR, AGGREGATE, ALLOCATABLE or POINTER" }
+
+!$omp target defaultmap(alloc:scalar) defaultmap(none:Scalar)  ! { dg-error "DEFAULTMAP at .1. but prior DEFAULTMAP for category SCALAR" }
+
+!$omp target defaultmap(default:aggregate) defaultmap(tofrom)  ! { dg-error "DEFAULTMAP at .1. but prior DEFAULTMAP for category AGGREGATE" }
+
+!$omp target defaultmap(from:pointer) defaultmap(tofrom:pointer)  ! { dg-error "DEFAULTMAP at .1. but prior DEFAULTMAP for category POINTER" }
+
+!$omp target defaultmap(from:scalar) defaultmap(to:allocatable) defaultmap(tofrom:allocatable)  ! { dg-error "DEFAULTMAP at .1. but prior DEFAULTMAP for category ALLOCATABLE" }
+
+!$omp target defaultmap(from) defaultmap(to)  !  { dg-error "DEFAULTMAP at .1. but prior DEFAULTMAP with unspecified category" }
+
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/defaultmap-2.f90 b/gcc/testsuite/gfortran.dg/gomp/defaultmap-2.f90
new file mode 100644
index 00000000000..1658424cf59
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/defaultmap-2.f90
@@ -0,0 +1,108 @@ 
+! PR fortran/92568
+!
+implicit none
+  type t
+  end type t
+
+  integer :: ii
+  integer :: arr(5)
+  integer, allocatable :: aii, aarr(:)
+  integer, pointer :: pii, parr(:)
+
+  character :: str1, str1arr(5), str1a, str1aarr(:), str1p, str1parr(:)
+  character(len=5) :: str5, str5arr(5), str5a, str5aarr(:), str5p, str5parr(:)
+  character(len=:) :: strXa, strXaarr(:), strXp, strXparr(:)
+  allocatable :: str1a, str1aarr, str5a, str5aarr, strXa, strXaarr
+  pointer :: str1p, str1parr, str5p, str5parr, strXp, strXparr
+
+  type(t) :: dt, dtarr(5), dta, dtaarr(:), dtp, dtparr(:)
+  allocatable :: dta, dtaarr
+  pointer :: dtp, dtparr
+
+  allocate(aii, aarr(5), str1a, str1aarr(5), dta, dtparr(5))
+  allocate(pii, parr(5), str1p, str1parr(5), dtp, dtparr(5))
+  allocate(character(len=7) :: strXa, strXaarr(5), strXp, strXparr(5))
+
+
+  !$omp target defaultmap ( none )  ! { dg-note "enclosing 'target'" }
+    ii = 42; arr = 42; aii = 42; aarr = 42; pii = 42; parr = 42
+    ! { dg-error "'ii' not specified in enclosing 'target'" "" { target *-*-* } .-1 }
+    ! { dg-error "'arr' not specified in enclosing 'target'" "" { target *-*-* } .-2 }
+    ! { dg-error "'aii' not specified in enclosing 'target'" "" { target *-*-* } .-3 }
+    ! { dg-error "'aarr' not specified in enclosing 'target'" "" { target *-*-* } .-4 }
+    ! { dg-error "'pii' not specified in enclosing 'target'" "" { target *-*-* } .-5 }
+    ! { dg-error "'parr' not specified in enclosing 'target'" "" { target *-*-* } .-6 }
+
+    str1 = ""; str1arr = ""; str1a = ""; str1aarr = ""; str1p = ""; str1parr = ""
+    ! { dg-error "'str1' not specified in enclosing 'target'" "" { target *-*-* } .-1 }
+    ! { dg-error "'str1arr' not specified in enclosing 'target'" "" { target *-*-* } .-2 }
+    ! { dg-error "'str1a' not specified in enclosing 'target'" "" { target *-*-* } .-3 }
+    ! { dg-error "'str1aarr' not specified in enclosing 'target'" "" { target *-*-* } .-4 }
+    ! { dg-error "'str1p' not specified in enclosing 'target'" "" { target *-*-* } .-5 }
+    ! { dg-error "'str1parr' not specified in enclosing 'target'" "" { target *-*-* } .-6 }
+
+    str5 = ""; str5arr = ""; str5a = ""; str5aarr = ""; str5p = ""; str5parr = ""
+    ! { dg-error "'str5' not specified in enclosing 'target'" "" { target *-*-* } .-1 }
+    ! { dg-error "'str5arr' not specified in enclosing 'target'" "" { target *-*-* } .-2 }
+    ! { dg-error "'str5a' not specified in enclosing 'target'" "" { target *-*-* } .-3 }
+    ! { dg-error "'str5aarr' not specified in enclosing 'target'" "" { target *-*-* } .-4 }
+    ! { dg-error "'str5p' not specified in enclosing 'target'" "" { target *-*-* } .-5 }
+    ! { dg-error "'str5parr' not specified in enclosing 'target'" "" { target *-*-* } .-6 }
+
+    strXa = ""; strXaarr = ""; strXp = ""; strXparr = ""
+    ! { dg-error "'strxa' not specified in enclosing 'target'" "" { target *-*-* } .-1 }
+    ! { dg-error "'strxaarr' not specified in enclosing 'target'" "" { target *-*-* } .-2 }
+    ! { dg-error "'strxp' not specified in enclosing 'target'" "" { target *-*-* } .-3 }
+    ! { dg-error "'strxparr' not specified in enclosing 'target'" "" { target *-*-* } .-4 }
+
+    dt = t(); dtarr = t(); dta = t(); dtaarr = t(); dtp = t(); dtparr = t()
+    ! { dg-error "'dt' not specified in enclosing 'target'" "" { target *-*-* } .-1 }
+    ! { dg-error "'dtarr' not specified in enclosing 'target'" "" { target *-*-* } .-2 }
+    ! { dg-error "'dta' not specified in enclosing 'target'" "" { target *-*-* } .-3 }
+    ! { dg-error "'dtaarr' not specified in enclosing 'target'" "" { target *-*-* } .-4 }
+    ! { dg-error "'dtp' not specified in enclosing 'target'" "" { target *-*-* } .-5 }
+    ! { dg-error "'dtparr' not specified in enclosing 'target'" "" { target *-*-* } .-6 }
+  !$omp end target
+
+
+  !$omp target defaultmap(none : scalar)  defaultmap(none : aggregate)  &
+  !$omp&       defaultmap(none : allocatable) defaultmap(none : pointer)   ! { dg-note "enclosing 'target'" }
+    ii = 42; arr = 42; aii = 42; aarr = 42; pii = 42; parr = 42
+    ! { dg-error "'ii' not specified in enclosing 'target'" "" { target *-*-* } .-1 }
+    ! { dg-error "'arr' not specified in enclosing 'target'" "" { target *-*-* } .-2 }
+    ! { dg-error "'aii' not specified in enclosing 'target'" "" { target *-*-* } .-3 }
+    ! { dg-error "'aarr' not specified in enclosing 'target'" "" { target *-*-* } .-4 }
+    ! { dg-error "'pii' not specified in enclosing 'target'" "" { target *-*-* } .-5 }
+    ! { dg-error "'parr' not specified in enclosing 'target'" "" { target *-*-* } .-6 }
+
+    str1 = ""; str1arr = ""; str1a = ""; str1aarr = ""; str1p = ""; str1parr = ""
+    ! { dg-error "'str1' not specified in enclosing 'target'" "" { target *-*-* } .-1 }
+    ! { dg-error "'str1arr' not specified in enclosing 'target'" "" { target *-*-* } .-2 }
+    ! { dg-error "'str1a' not specified in enclosing 'target'" "" { target *-*-* } .-3 }
+    ! { dg-error "'str1aarr' not specified in enclosing 'target'" "" { target *-*-* } .-4 }
+    ! { dg-error "'str1p' not specified in enclosing 'target'" "" { target *-*-* } .-5 }
+    ! { dg-error "'str1parr' not specified in enclosing 'target'" "" { target *-*-* } .-6 }
+
+    str5 = ""; str5arr = ""; str5a = ""; str5aarr = ""; str5p = ""; str5parr = ""
+    ! { dg-error "'str5' not specified in enclosing 'target'" "" { target *-*-* } .-1 }
+    ! { dg-error "'str5arr' not specified in enclosing 'target'" "" { target *-*-* } .-2 }
+    ! { dg-error "'str5a' not specified in enclosing 'target'" "" { target *-*-* } .-3 }
+    ! { dg-error "'str5aarr' not specified in enclosing 'target'" "" { target *-*-* } .-4 }
+    ! { dg-error "'str5p' not specified in enclosing 'target'" "" { target *-*-* } .-5 }
+    ! { dg-error "'str5parr' not specified in enclosing 'target'" "" { target *-*-* } .-6 }
+
+    strXa = ""; strXaarr = ""; strXp = ""; strXparr = ""
+    ! { dg-error "'strxa' not specified in enclosing 'target'" "" { target *-*-* } .-1 }
+    ! { dg-error "'strxaarr' not specified in enclosing 'target'" "" { target *-*-* } .-2 }
+    ! { dg-error "'strxp' not specified in enclosing 'target'" "" { target *-*-* } .-3 }
+    ! { dg-error "'strxparr' not specified in enclosing 'target'" "" { target *-*-* } .-4 }
+
+    dt = t(); dtarr = t(); dta = t(); dtaarr = t(); dtp = t(); dtparr = t()
+    ! { dg-error "'dt' not specified in enclosing 'target'" "" { target *-*-* } .-1 }
+    ! { dg-error "'dtarr' not specified in enclosing 'target'" "" { target *-*-* } .-2 }
+    ! { dg-error "'dta' not specified in enclosing 'target'" "" { target *-*-* } .-3 }
+    ! { dg-error "'dtaarr' not specified in enclosing 'target'" "" { target *-*-* } .-4 }
+    ! { dg-error "'dtp' not specified in enclosing 'target'" "" { target *-*-* } .-5 }
+    ! { dg-error "'dtparr' not specified in enclosing 'target'" "" { target *-*-* } .-6 }
+  !$omp end target
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/defaultmap-3.f90 b/gcc/testsuite/gfortran.dg/gomp/defaultmap-3.f90
new file mode 100644
index 00000000000..cfe40e8eea8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/defaultmap-3.f90
@@ -0,0 +1,60 @@ 
+! { dg-additional-options "-fdump-tree-original" }
+! { dg-additional-options "-fdump-tree-gimple" }
+!
+! PR fortran/92568
+!
+implicit none
+  type t
+  end type t
+
+  integer :: ii
+  integer :: arr(5)
+  integer, allocatable :: aii, aarr(:)
+  integer, pointer :: pii, parr(:)
+
+  character :: str1, str1arr(5), str1a, str1aarr(:), str1p, str1parr(:)
+  character(len=5) :: str5, str5arr(5), str5a, str5aarr(:), str5p, str5parr(:)
+  character(len=:) :: strXa, strXaarr(:), strXp, strXparr(:)
+  allocatable :: str1a, str1aarr, str5a, str5aarr, strXa, strXaarr
+  pointer :: str1p, str1parr, str5p, str5parr, strXp, strXparr
+
+  type(t) :: dt, dtarr(5), dta, dtaarr(:), dtp, dtparr(:)
+  allocatable :: dta, dtaarr
+  pointer :: dtp, dtparr
+
+  allocate(aii, aarr(5), str1a, str1aarr(5), dta, dtparr(5))
+  allocate(pii, parr(5), str1p, str1parr(5), dtp, dtparr(5))
+  allocate(character(len=7) :: strXa, strXaarr(5), strXp, strXparr(5))
+
+
+  !$omp target defaultmap ( none )  &
+  !$omp&  map(tofrom: ii, arr, aii, aarr, pii, parr)  &
+  !$omp&  map(tofrom: str1, str1arr, str1a, str1aarr, str1p, str1parr)  &
+  !$omp&  map(tofrom: str5, str5arr, str5a, str5aarr, str5p, str5parr)  &
+  !$omp&  map(tofrom: strXa, strXaarr, strXp, strXparr)  &
+  !$omp&  map(tofrom: dt, dtarr, dta, dtaarr, dtp, dtparr)
+    ii = 42; arr = 42; aii = 42; aarr = 42; pii = 42; parr = 42
+    str1 = ""; str1arr = ""; str1a = ""; str1aarr = ""; str1p = ""; str1parr = ""
+    str5 = ""; str5arr = ""; str5a = ""; str5aarr = ""; str5p = ""; str5parr = ""
+    strXa = ""; strXaarr = ""; strXp = ""; strXparr = ""
+    dt = t(); dtarr = t(); dta = t(); dtaarr = t(); dtp = t(); dtparr = t()
+  !$omp end target
+
+
+  !$omp target defaultmap(none : scalar)  defaultmap(none : aggregate)  &
+  !$omp&       defaultmap(none : allocatable) defaultmap(none : pointer) &
+  !$omp&  map(alloc: ii, arr, aii, aarr, pii, parr)  &
+  !$omp&  map(alloc: str1, str1arr, str1a, str1aarr, str1p, str1parr)  &
+  !$omp&  map(alloc: str5, str5arr, str5a, str5aarr, str5p, str5parr)  &
+  !$omp&  map(alloc: strXa, strXaarr, strXp, strXparr)  &
+  !$omp&  map(alloc: dt, dtarr, dta, dtaarr, dtp, dtparr)
+    ii = 42; arr = 42; aii = 42; aarr = 42; pii = 42; parr = 42
+    str1 = ""; str1arr = ""; str1a = ""; str1aarr = ""; str1p = ""; str1parr = ""
+    str5 = ""; str5arr = ""; str5a = ""; str5aarr = ""; str5p = ""; str5parr = ""
+    strXa = ""; strXaarr = ""; strXp = ""; strXparr = ""
+    dt = t(); dtarr = t(); dta = t(); dtaarr = t(); dtp = t(); dtparr = t()
+  !$omp end target
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp target map\\(tofrom:.* defaultmap\\(none\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target map\\(alloc:.* defaultmap\\(none:scalar\\) defaultmap\\(none:aggregate\\) defaultmap\\(none:allocatable\\) defaultmap\\(none:pointer\\)" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/defaultmap-4.f90 b/gcc/testsuite/gfortran.dg/gomp/defaultmap-4.f90
new file mode 100644
index 00000000000..89bbe87e570
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/defaultmap-4.f90
@@ -0,0 +1,141 @@ 
+! { dg-additional-options "-fdump-tree-original" }
+! { dg-additional-options "-fdump-tree-gimple" }
+!
+! PR fortran/92568
+!
+implicit none
+  type t
+  end type t
+
+  integer :: ii
+  integer :: arr(5)
+  integer, allocatable :: aii, aarr(:)
+  integer, pointer :: pii, parr(:)
+
+  character :: str1, str1arr(5), str1a, str1aarr(:), str1p, str1parr(:)
+  character(len=5) :: str5, str5arr(5), str5a, str5aarr(:), str5p, str5parr(:)
+  character(len=:) :: strXa, strXaarr(:), strXp, strXparr(:)
+  allocatable :: str1a, str1aarr, str5a, str5aarr, strXa, strXaarr
+  pointer :: str1p, str1parr, str5p, str5parr, strXp, strXparr
+
+  type(t) :: dt, dtarr(5), dta, dtaarr(:), dtp, dtparr(:)
+  allocatable :: dta, dtaarr
+  pointer :: dtp, dtparr
+
+  allocate(aii, aarr(5), str1a, str1aarr(5), dta, dtparr(5))
+  allocate(pii, parr(5), str1p, str1parr(5), dtp, dtparr(5))
+  allocate(character(len=7) :: strXa, strXaarr(5), strXp, strXparr(5))
+
+
+  !$omp target defaultmap ( alloc )
+    ii = 42; arr = 42; aii = 42; aarr = 42; pii = 42; parr = 42
+    str1 = ""; str1arr = ""; str1a = ""; str1aarr = ""; str1p = ""; str1parr = ""
+    str5 = ""; str5arr = ""; str5a = ""; str5aarr = ""; str5p = ""; str5parr = ""
+    strXa = ""; strXaarr = ""; strXp = ""; strXparr = ""
+    dt = t(); dtarr = t(); dta = t(); dtaarr = t(); dtp = t(); dtparr = t()
+  !$omp end target
+
+  !$omp target defaultmap(alloc : scalar)  defaultmap(to : aggregate)  &
+  !$omp&       defaultmap(tofrom : allocatable) defaultmap(firstprivate : pointer)
+    ii = 42; arr = 42; aii = 42; aarr = 42; pii = 42; parr = 42
+    str1 = ""; str1arr = ""; str1a = ""; str1aarr = ""; str1p = ""; str1parr = ""
+    str5 = ""; str5arr = ""; str5a = ""; str5aarr = ""; str5p = ""; str5parr = ""
+    strXa = ""; strXaarr = ""; strXp = ""; strXparr = ""
+    dt = t(); dtarr = t(); dta = t(); dtaarr = t(); dtp = t(); dtparr = t()
+  !$omp end target
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp target defaultmap\\(alloc:scalar\\) defaultmap\\(to:aggregate\\) defaultmap\\(tofrom:allocatable\\) defaultmap\\(firstprivate:pointer\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target defaultmap\\(alloc\\)" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "firstprivate\\(dtp\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(pii\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(str1p\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(str5p\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(strxp\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*aii \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:aii \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) dtaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) str1aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) str5aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) strxaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*\\(c_char \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\* restrict\\) str1aarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\* restrict\\) str5aarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxaarr\\\] \\* restrict\\) strxaarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*dta \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:dta \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:dtarr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:dt \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*dtp \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:dtp \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:ii \\\[len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) aarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*pii \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:pii \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*str1a \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str1a \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str1arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str1 \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*str1p \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str1p \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*str5a \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str5a \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str5arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str5 \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*str5p \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str5p \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(struct t\\\[0:\\\] \\* restrict\\) dtaarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*strxa \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:strxa \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\*strxp \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:strxp \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\*\\) str1parr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\*\\) str5parr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxparr\\\] \\*\\) strxparr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) parr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(struct t\\\[0:\\\] \\*\\) dtparr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:aarr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:dtaarr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:dtarr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:dt \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:dtparr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*aii \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) dtaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str1aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str5aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) strxaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*dta \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*str1a \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*str5a \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*strxa \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:parr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str1aarr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str1arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str1 \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str1parr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str5aarr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str5arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str5 \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str5parr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\.strxaarr \\\[len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:strxaarr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\.strxa \\\[len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\.strxparr \\\[len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:strxparr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\.strxp \\\[len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(1\\) thread_limit\\(0\\) defaultmap\\(alloc\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(1\\) thread_limit\\(0\\) defaultmap\\(alloc:scalar\\) defaultmap\\(to:aggregate\\) defaultmap\\(tofrom:allocatable\\) defaultmap\\(firstprivate:pointer\\)" 1 "gimple" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/defaultmap-5.f90 b/gcc/testsuite/gfortran.dg/gomp/defaultmap-5.f90
new file mode 100644
index 00000000000..d6b32dc90bc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/defaultmap-5.f90
@@ -0,0 +1,145 @@ 
+! { dg-additional-options "-fdump-tree-original" }
+! { dg-additional-options "-fdump-tree-gimple" }
+!
+! PR fortran/92568
+!
+implicit none
+  type t
+  end type t
+
+  integer :: ii
+  integer :: arr(5)
+  integer, allocatable :: aii, aarr(:)
+  integer, pointer :: pii, parr(:)
+
+  character :: str1, str1arr(5), str1a, str1aarr(:), str1p, str1parr(:)
+  character(len=5) :: str5, str5arr(5), str5a, str5aarr(:), str5p, str5parr(:)
+  character(len=:) :: strXa, strXaarr(:), strXp, strXparr(:)
+  allocatable :: str1a, str1aarr, str5a, str5aarr, strXa, strXaarr
+  pointer :: str1p, str1parr, str5p, str5parr, strXp, strXparr
+
+  type(t) :: dt, dtarr(5), dta, dtaarr(:), dtp, dtparr(:)
+  allocatable :: dta, dtaarr
+  pointer :: dtp, dtparr
+
+  allocate(aii, aarr(5), str1a, str1aarr(5), dta, dtparr(5))
+  allocate(pii, parr(5), str1p, str1parr(5), dtp, dtparr(5))
+  allocate(character(len=7) :: strXa, strXaarr(5), strXp, strXparr(5))
+
+
+  !$omp target defaultmap ( to )
+    ii = 42; arr = 42; aii = 42; aarr = 42; pii = 42; parr = 42
+    str1 = ""; str1arr = ""; str1a = ""; str1aarr = ""; str1p = ""; str1parr = ""
+    str5 = ""; str5arr = ""; str5a = ""; str5aarr = ""; str5p = ""; str5parr = ""
+    strXa = ""; strXaarr = ""; strXp = ""; strXparr = ""
+    dt = t(); dtarr = t(); dta = t(); dtaarr = t(); dtp = t(); dtparr = t()
+  !$omp end target
+
+
+  ! FIXME: strXp disabled because of PR fortran/100965
+
+  !$omp target defaultmap(to : scalar)  defaultmap(tofrom : aggregate)  &
+  !$omp&       defaultmap(firstprivate : allocatable) defaultmap(default : pointer)
+    ii = 42; arr = 42; aii = 42; aarr = 42; pii = 42; parr = 42
+    str1 = ""; str1arr = ""; str1a = ""; str1aarr = ""; str1p = ""; str1parr = ""
+    str5 = ""; str5arr = ""; str5a = ""; str5aarr = ""; str5p = ""; str5parr = ""
+    !strXa = "";
+    strXaarr = "";
+    ! strXp = ""
+    strXparr = ""
+    dt = t(); dtarr = t(); dta = t(); dtaarr = t(); dtp = t(); dtparr = t()
+  !$omp end target
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp target defaultmap\\(to\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target defaultmap\\(to:scalar\\) defaultmap\\(tofrom:aggregate\\) defaultmap\\(firstprivate:allocatable\\) defaultmap\\(default:pointer\\)" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "firstprivate\\(aarr\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(aii\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(dta\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(dtaarr\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(str1a\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(str1aarr\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(str5a\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(str5aarr\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(strxaarr\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:aii \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\* restrict\\) str1aarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\* restrict\\) str5aarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxaarr\\\] \\* restrict\\) strxaarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:dta \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:dtp \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) aarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:pii \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str1a \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str1p \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str5a \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str5p \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(struct t\\\[0:\\\] \\* restrict\\) dtaarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:strxa \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:strxp \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\*\\) str1parr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\*\\) str5parr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxparr\\\] \\*\\) strxparr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) parr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(struct t\\\[0:\\\] \\*\\) dtparr\\.data \\\[pointer assign, bias: 0\\\]\\)" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:aarr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*aii \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) dtaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) str1aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) str5aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) strxaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*\\(c_char \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:dtaarr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*dta \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:dtarr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:dt \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:dtparr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*dtp \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:dtarr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:dt \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*dtp \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*pii \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:str1arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:str1 \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*str1p \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:str5arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:str5 \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*str5p \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:ii \\\[len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:parr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*pii \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str1aarr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*str1a \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str1arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str1 \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str1parr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*str1p \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str5aarr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*str5a \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str5arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str5 \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str5parr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*str5p \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\.strxaarr \\\[len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:strxaarr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*strxa \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\.strxa \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\.strxparr \\\[len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:strxparr \\\[pointer set, len:" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\*strxp \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\.strxp \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(1\\) thread_limit\\(0\\) defaultmap\\(to\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(1\\) thread_limit\\(0\\) defaultmap\\(to:scalar\\) defaultmap\\(tofrom:aggregate\\) defaultmap\\(firstprivate:allocatable\\) defaultmap\\(default:pointer\\)" 1 "gimple" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/defaultmap-6.f90 b/gcc/testsuite/gfortran.dg/gomp/defaultmap-6.f90
new file mode 100644
index 00000000000..fabf771f9c7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/defaultmap-6.f90
@@ -0,0 +1,104 @@ 
+! { dg-additional-options "-fdump-tree-original" }
+! { dg-additional-options "-fdump-tree-gimple" }
+!
+! PR fortran/92568
+!
+implicit none
+  type t
+  end type t
+
+  integer :: ii
+  integer :: arr(5)
+  integer, allocatable :: aii, aarr(:)
+  integer, pointer :: pii, parr(:)
+
+  character :: str1, str1arr(5), str1a, str1aarr(:), str1p, str1parr(:)
+  character(len=5) :: str5, str5arr(5), str5a, str5aarr(:), str5p, str5parr(:)
+  character(len=:) :: strXa, strXaarr(:), strXp, strXparr(:)
+  allocatable :: str1a, str1aarr, str5a, str5aarr, strXa, strXaarr
+  pointer :: str1p, str1parr, str5p, str5parr, strXp, strXparr
+
+  type(t) :: dt, dtarr(5), dta, dtaarr(:), dtp, dtparr(:)
+  allocatable :: dta, dtaarr
+  pointer :: dtp, dtparr
+
+  allocate(aii, aarr(5), str1a, str1aarr(5), dta, dtparr(5))
+  allocate(pii, parr(5), str1p, str1parr(5), dtp, dtparr(5))
+  allocate(character(len=7) :: strXa, strXaarr(5), strXp, strXparr(5))
+
+
+  !$omp target defaultmap ( default )
+    ii = 42; arr = 42; aii = 42; aarr = 42; pii = 42; parr = 42
+    str1 = ""; str1arr = ""; str1a = ""; str1aarr = ""; str1p = ""; str1parr = ""
+    str5 = ""; str5arr = ""; str5a = ""; str5aarr = ""; str5p = ""; str5parr = ""
+    strXa = ""; strXaarr = ""; strXp = ""; strXparr = ""
+    dt = t(); dtarr = t(); dta = t(); dtaarr = t(); dtp = t(); dtparr = t()
+  !$omp end target
+
+end
+
+! { dg-final { scan-tree-dump-times "#pragma omp target defaultmap\\(default\\)" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "firstprivate\\(ii\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:aii \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\* restrict\\) str1aarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\* restrict\\) str5aarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxaarr\\\] \\* restrict\\) strxaarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:dta \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:dtp \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) aarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:pii \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str1a \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str1p \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str5a \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:str5p \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:\\(struct t\\\[0:\\\] \\* restrict\\) dtaarr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:strxa \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(alloc:strxp \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:1\\\] \\*\\) str1parr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:5\\\] \\*\\) str5parr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(character\\(kind=1\\)\\\[0:\\\]\\\[1:\\.strxparr\\\] \\*\\) strxparr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) parr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(always_pointer:\\(struct t\\\[0:\\\] \\*\\) dtparr\\.data \\\[pointer assign, bias: 0\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:aarr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:dtaarr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:dtparr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*aii \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) dtaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) dtparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str1aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str1parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str5aarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) str5parr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) strxaarr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*\\(c_char \\*\\) strxparr\\.data \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*dta \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:dtarr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:dt \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*dtp \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*pii \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*str1a \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:str1arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:str1 \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*str1p \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*str5a \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:str5arr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:str5 \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*str5p \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*strxa \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*strxp \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:parr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str1aarr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str1parr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str5aarr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:str5parr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\.strxaarr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:strxaarr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\.strxa \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\.strxparr \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:strxparr \\\[pointer set, len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(to:\\.strxp \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(1\\) thread_limit\\(0\\) defaultmap\\(default\\)" 1 "gimple" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/defaultmap-7.f90 b/gcc/testsuite/gfortran.dg/gomp/defaultmap-7.f90
new file mode 100644
index 00000000000..e1b4fc2364f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/defaultmap-7.f90
@@ -0,0 +1,24 @@ 
+! PR fortran/92568
+!
+! { dg-additional-options "-fdump-tree-original" }
+! { dg-additional-options "-fdump-tree-gimple" }
+implicit none
+  integer :: ii, aa, pp
+  allocatable :: aa
+  pointer :: pp
+  character :: str
+  character(len=2) :: str2
+
+!$omp target
+  ii = 1
+  aa = 5
+  pp = 7
+  str = '1'
+  str2 = '12'
+!$omp end target
+end
+! { dg-final { scan-tree-dump-times "firstprivate\\(ii\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*aa" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:\\*pp" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:str2 \\\[len:" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "map\\(tofrom:str \\\[len:" 1 "gimple" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr99928-1.f90 b/gcc/testsuite/gfortran.dg/gomp/pr99928-1.f90
index 9a590650520..b61b2fc32b7 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr99928-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr99928-1.f90
@@ -108,13 +108,13 @@  subroutine bar ()
   !$omp end parallel sections
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f13\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f13\\)" "gimple" } }
-  !$omp target parallel firstprivate (f13) default(none) ! defaultmap(none)
+  !$omp target parallel firstprivate (f13) default(none) defaultmap(none)
   f13 = f13 + 1
   !$omp end target parallel
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f14\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f14\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f14\\)" "gimple" } } ! FIXME. 
-  !$omp target parallel do firstprivate (f14) default(none) ! defaultmap(none)
+  !$omp target parallel do firstprivate (f14) default(none) defaultmap(none)
   do i = 1, 64
     f14 = f14 + 1
   end do
@@ -122,7 +122,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f15\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f15\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f15\\)" "gimple" } }
-  !$omp target parallel do simd firstprivate (f15) default(none) ! defaultmap(none)
+  !$omp target parallel do simd firstprivate (f15) default(none) defaultmap(none)
   do i = 1, 64
     f15 = f15 + 1
   end do
@@ -130,19 +130,19 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f16\\)" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f16\\)" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f16\\)" "gimple" } }
-  !$omp target parallel loop firstprivate (f16) default(none) ! defaultmap(none)
+  !$omp target parallel loop firstprivate (f16) default(none) defaultmap(none)
   do i = 1, 64
     f16 = f16 + 1
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f17\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f17\\)" "gimple" } }
-  !$omp target teams firstprivate (f17) default(none) ! defaultmap(none)
+  !$omp target teams firstprivate (f17) default(none) defaultmap(none)
   f17 = f17 + 1
   !$omp end target teams
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f18\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f18\\)" "gimple" } } ! FIXME: This should be on distribute instead. 
   ! { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f18\\)" "gimple" } } ! FIXME. 
-  !$omp target teams distribute firstprivate (f18) default(none) ! defaultmap(none)
+  !$omp target teams distribute firstprivate (f18) default(none) defaultmap(none)
   do i = 1, 64
     f18 = f18 + 1
   end do
@@ -151,7 +151,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f19\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f19\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f19\\)" "gimple" } } ! FIXME. 
-  !$omp target teams distribute parallel do firstprivate (f19) default(none) ! defaultmap(none)
+  !$omp target teams distribute parallel do firstprivate (f19) default(none) defaultmap(none)
   do i = 1, 64
     f19 = f19 + 1
   end do
@@ -161,7 +161,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f20\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f20\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f20\\)" "gimple" } }
-  !$omp target teams distribute parallel do simd firstprivate (f20) default(none) ! defaultmap(none)
+  !$omp target teams distribute parallel do simd firstprivate (f20) default(none) defaultmap(none)
   do i = 1, 64
     f20 = f20 + 1
   end do
@@ -169,7 +169,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f21\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f21\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f21\\)" "gimple" } }
-  !$omp target teams distribute simd firstprivate (f21) default(none) ! defaultmap(none)
+  !$omp target teams distribute simd firstprivate (f21) default(none) defaultmap(none)
   do i = 1, 64
     f21 = f21 + 1
   end do
@@ -179,13 +179,13 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(f22\\)" "gimple" } } ! NOTE: This is an implementation detail. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f22\\)" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f22\\)" "gimple" } }
-  !$omp target teams loop firstprivate (f22) default(none) ! defaultmap(none)
+  !$omp target teams loop firstprivate (f22) default(none) defaultmap(none)
   do i = 1, 64
     f22 = f22 + 1
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f23\\)" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f23\\)" "gimple" } }
-  !$omp target simd firstprivate (f23) ! defaultmap(none)
+  !$omp target simd firstprivate (f23) defaultmap(none)
   do i = 1, 64
     f23 = f23 + 1
   end do
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr99928-2.f90 b/gcc/testsuite/gfortran.dg/gomp/pr99928-2.f90
index 4a5b54915e8..7a9824865c2 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr99928-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr99928-2.f90
@@ -108,7 +108,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l11\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l11\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l11\\)" "gimple" } } ! FIXME. 
-  !$omp target parallel do lastprivate (l11) default(none) ! defaultmap(none)
+  !$omp target parallel do lastprivate (l11) default(none) defaultmap(none)
   do i = 1, 64
     l11 = i
   end do
@@ -117,7 +117,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l12\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l12\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l12\\)" "gimple" } }
-  !$omp target parallel do simd lastprivate (l12) default(none) ! defaultmap(none)
+  !$omp target parallel do simd lastprivate (l12) default(none) defaultmap(none)
   do i = 1, 64
     l12 = i
   end do
@@ -126,14 +126,14 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(j01\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(j01\\)" "gimple" } } ! NOTE: This is implementation detail. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(j01\\)" "gimple" } } ! NOTE: This is implementation detail. 
-  !$omp target parallel loop lastprivate (j01) default(none) ! defaultmap(none)
+  !$omp target parallel loop lastprivate (j01) default(none) defaultmap(none)
   do j01 = 0, 64
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l13" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l13\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l13\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l13\\)" "gimple" } }
-  !$omp target teams distribute lastprivate (l13) default(none) ! defaultmap(none)
+  !$omp target teams distribute lastprivate (l13) default(none) defaultmap(none)
   do i = 1, 64
     l13 = i
   end do
@@ -143,7 +143,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l14\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l14\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l14\\)" "gimple" } } ! FIXME. 
-  !$omp target teams distribute parallel do lastprivate (l14) default(none) ! defaultmap(none)
+  !$omp target teams distribute parallel do lastprivate (l14) default(none) defaultmap(none)
   do i = 1, 64
     l14 = i
   end do
@@ -154,7 +154,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l15\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l15\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l15\\)" "gimple" } }
-  !$omp target teams distribute parallel do simd lastprivate (l15) default(none) ! defaultmap(none)
+  !$omp target teams distribute parallel do simd lastprivate (l15) default(none) defaultmap(none)
   do i = 1, 64
     l15 = i
   end do
@@ -163,7 +163,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l16\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l16\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l16\\)" "gimple" } }
-  !$omp target teams distribute simd lastprivate (l16) default(none) ! defaultmap(none)
+  !$omp target teams distribute simd lastprivate (l16) default(none) defaultmap(none)
   do i = 1, 64
     l16 = i
   end do
@@ -174,13 +174,13 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(j02\\)" "gimple" } } ! NOTE: This is implementation detail. 
   ! { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(j02\\)" "gimple" } } ! NOTE: This is implementation detail. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(j02\\)" "gimple" } } ! NOTE: This is implementation detail. 
-  !$omp target teams loop lastprivate (j02) default(none) ! defaultmap(none)
+  !$omp target teams loop lastprivate (j02) default(none) defaultmap(none)
   do j02 = 0, 64
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l17" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l17\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l17\\)" "gimple" } }
-  !$omp target simd lastprivate (l17) ! defaultmap(none)
+  !$omp target simd lastprivate (l17) defaultmap(none)
   do i = 1, 64
     l17 = i
   end do
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr99928-3.f90 b/gcc/testsuite/gfortran.dg/gomp/pr99928-3.f90
index 82bb89338ca..3c02c88c483 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr99928-3.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr99928-3.f90
@@ -101,7 +101,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l08\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l08\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l08\\)" "gimple" } } ! FIXME. 
-  !$omp target parallel do firstprivate (l08) lastprivate (l08) default(none) ! defaultmap(none)
+  !$omp target parallel do firstprivate (l08) lastprivate (l08) default(none) defaultmap(none)
   do i = 1, 64
     l08 = i
   end do
@@ -114,7 +114,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l09\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l09\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l09\\)" "gimple" } }
-  !$omp target parallel do simd firstprivate (l09) lastprivate (l09) default(none) ! defaultmap(none)
+  !$omp target parallel do simd firstprivate (l09) lastprivate (l09) default(none) defaultmap(none)
   do i = 1, 64
     l09 = i
   end do
@@ -122,7 +122,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l10\\)" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l10\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l10\\)" "gimple" } }
-  !$omp target simd firstprivate (l10) lastprivate (l10) ! defaultmap(none)
+  !$omp target simd firstprivate (l10) lastprivate (l10) defaultmap(none)
   do i = 1, 64
     l10 = i
   end do
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr99928-4.f90 b/gcc/testsuite/gfortran.dg/gomp/pr99928-4.f90
index ead8f030e63..1563c4fbbd0 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr99928-4.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr99928-4.f90
@@ -57,7 +57,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l05\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(l05\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp for\[^\n\r]*linear\\(l05:1\\)" "gimple" } }
-  !$omp target parallel do linear (l05) default(none) ! defaultmap(none)
+  !$omp target parallel do linear (l05) default(none) defaultmap(none)
   do i = 1, 64
     l05 = l05 + 1
   end do
@@ -68,14 +68,14 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l06\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l06\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(l06:1\\)" "gimple" } }
-  !$omp target parallel do simd linear (l06) default(none) ! defaultmap(none)
+  !$omp target parallel do simd linear (l06) default(none) defaultmap(none)
   do i = 1, 64
     l06 = l06 + 1
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l07" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l07\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(l07:1\\)" "gimple" } }
-  !$omp target simd linear (l07) ! defaultmap(none)
+  !$omp target simd linear (l07) defaultmap(none)
   do i = 1, 64
     l07 = l07 + 1
   end do
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr99928-5.f90 b/gcc/testsuite/gfortran.dg/gomp/pr99928-5.f90
index 49cbf1e8cc2..259f6cc0136 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr99928-5.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr99928-5.f90
@@ -57,13 +57,13 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j06\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j06\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j06:1\\)" "gimple" } }
-  !$omp target parallel do simd linear (j06) default(none) ! defaultmap(none)
+  !$omp target parallel do simd linear (j06) default(none) defaultmap(none)
   do j06 = 1, 64
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j07" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j07\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j07:1\\)" "gimple" } }
-  !$omp target simd linear (j07) ! defaultmap(none)
+  !$omp target simd linear (j07) defaultmap(none)
   do j07 = 1, 64
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j08" "gimple" } }
@@ -73,7 +73,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j08:1\\)" "gimple" } }
-  !$omp target teams distribute parallel do simd linear (j08) default(none) ! defaultmap(none)
+  !$omp target teams distribute parallel do simd linear (j08) default(none) defaultmap(none)
   do j08 = 1, 64
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j09" "gimple" } }
@@ -81,7 +81,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j09\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j09\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j09:1\\)" "gimple" } }
-  !$omp target teams distribute simd linear (j09) default(none) ! defaultmap(none)
+  !$omp target teams distribute simd linear (j09) default(none) defaultmap(none)
   do j09 = 1, 64
   end do
   ! { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(j10\\)" "gimple" } } ! NOTE: This is implementation detail. 
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr99928-6.f90 b/gcc/testsuite/gfortran.dg/gomp/pr99928-6.f90
index 0e60199476b..a9ad2264e39 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr99928-6.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr99928-6.f90
@@ -57,13 +57,13 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j06\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j06\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j06:1\\)" "gimple" } }
-  !$omp target parallel do simd default(none) ! defaultmap(none)
+  !$omp target parallel do simd default(none) defaultmap(none)
   do j06 = 1, 64
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j07" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j07\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j07:1\\)" "gimple" } }
-  !$omp target simd ! defaultmap(none)
+  !$omp target simd defaultmap(none)
   do j07 = 1, 64
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j08" "gimple" } }
@@ -73,7 +73,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j08:1\\)" "gimple" } }
-  !$omp target teams distribute parallel do simd default(none) ! defaultmap(none)
+  !$omp target teams distribute parallel do simd default(none) defaultmap(none)
   do j08 = 1, 64
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j09" "gimple" } }
@@ -81,7 +81,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j09\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j09\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j09:1\\)" "gimple" } }
-  !$omp target teams distribute simd default(none) ! defaultmap(none)
+  !$omp target teams distribute simd default(none) defaultmap(none)
   do j09 = 1, 64
   end do
   ! { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(j10\\)" "gimple" } } ! NOTE: This is implementation detail. 
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr99928-8.f90 b/gcc/testsuite/gfortran.dg/gomp/pr99928-8.f90
index c5d1eb7a8de..a0414a57a51 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr99928-8.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr99928-8.f90
@@ -113,14 +113,14 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r13" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r13\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r13\\)" "gimple" } }
-  !$omp target parallel reduction(+:r13) default(none) ! defaultmap(none)
+  !$omp target parallel reduction(+:r13) default(none) defaultmap(none)
   r13 = r13 + 1
   !$omp end target parallel
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r14" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r14\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r14\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r14\\)" "gimple" } } ! FIXME. 
-  !$omp target parallel do reduction(+:r14) default(none) ! defaultmap(none)
+  !$omp target parallel do reduction(+:r14) default(none) defaultmap(none)
   do i = 1, 64
     r14 = r14 + 1
   end do
@@ -129,7 +129,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r15\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r15\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r15\\)" "gimple" } }
-  !$omp target parallel do simd reduction(+:r15) default(none) ! defaultmap(none)
+  !$omp target parallel do simd reduction(+:r15) default(none) defaultmap(none)
   do i = 1, 64
     r15 = r15 + 1
   end do
@@ -138,21 +138,21 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r16\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:r16\\)" "gimple" } } ! NOTE: This is implementation detail. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r16\\)" "gimple" } } ! NOTE: This is implementation detail. 
-  !$omp target parallel loop reduction(+:r16) default(none) ! defaultmap(none)
+  !$omp target parallel loop reduction(+:r16) default(none) defaultmap(none)
   do i = 1, 64
     r16 = r16 + 1
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r17" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r17\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r17\\)" "gimple" } }
-  !$omp target teams reduction(+:r17) default(none) ! defaultmap(none)
+  !$omp target teams reduction(+:r17) default(none) defaultmap(none)
   r17 = r17 + 1
   !$omp end target teams
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r18" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r18\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r18\\)" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r18\\)" "gimple" } }
-  !$omp target teams distribute reduction(+:r18) default(none) ! defaultmap(none)
+  !$omp target teams distribute reduction(+:r18) default(none) defaultmap(none)
   do i = 1, 64
     r18 = r18 + 1
   end do
@@ -162,7 +162,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r19\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r19\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r19\\)" "gimple" } } ! FIXME. 
-  !$omp target teams distribute parallel do reduction(+:r19) default(none) ! defaultmap(none)
+  !$omp target teams distribute parallel do reduction(+:r19) default(none) defaultmap(none)
   do i = 1, 64
     r19 = r19 + 1
   end do
@@ -173,7 +173,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r20\\)" "gimple" } } ! FIXME: This should be on for instead. 
   ! { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r20\\)" "gimple" } } ! FIXME. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r20\\)" "gimple" } }
-  !$omp target teams distribute parallel do simd reduction(+:r20) default(none) ! defaultmap(none)
+  !$omp target teams distribute parallel do simd reduction(+:r20) default(none) defaultmap(none)
   do i = 1, 64
     r20 = r20 + 1
   end do
@@ -182,7 +182,7 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r21\\)" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r21\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r21\\)" "gimple" } }
-  !$omp target teams distribute simd reduction(+:r21) default(none) ! defaultmap(none)
+  !$omp target teams distribute simd reduction(+:r21) default(none) defaultmap(none)
   do i = 1, 64
     r21 = r21 + 1
   end do
@@ -193,14 +193,14 @@  subroutine bar ()
   ! { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r22\\)" "gimple" } } ! NOTE: This is implementation detail. 
   ! { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:r22\\)" "gimple" } } ! NOTE: This is implementation detail. 
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r22\\)" "gimple" } } ! NOTE: This is implementation detail. 
-  !$omp target teams loop reduction(+:r22) default(none) ! defaultmap(none)
+  !$omp target teams loop reduction(+:r22) default(none) defaultmap(none)
   do i = 1, 64
     r22 = r22 + 1
   end do
   ! { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r23" "gimple" } }
   ! { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r23\\)" "gimple" } }
   ! { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r23\\)" "gimple" } }
-  !$omp target simd reduction(+:r23) ! defaultmap(none)
+  !$omp target simd reduction(+:r23) defaultmap(none)
   do i = 1, 64
     r23 = r23 + 1
   end do
diff --git a/libgomp/testsuite/libgomp.fortran/defaultmap-8.f90 b/libgomp/testsuite/libgomp.fortran/defaultmap-8.f90
new file mode 100644
index 00000000000..34c109d2c3f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/defaultmap-8.f90
@@ -0,0 +1,279 @@ 
+! { dg-do run }
+! { dg-additional-options "-fdump-tree-gimple" }
+!
+! PR fortran/92568
+!
+program main
+  implicit none
+  integer :: xa1, xa2, xp1, xp2, xat1, xat2, xt1, xt2, xi1, xi2
+  allocatable :: xa1, xa2, xat1, xat2
+  pointer :: xp1, xp2
+
+  allocate (xa1, xa2, xat1, xat2, xp1, xp2)
+
+  call foo (xa1, xa2, xp1, xp2, xat1, xat2, xt1, xt2, xi1, xi2)
+  call foo2 (xa1, xa2, xp1, xp2, xat1, xat2, xt1, xt2, xi1, xi2)
+  call foo3 (xa1, xa2, xp1, xp2, xat1, xat2, xt1, xt2, xi1, xi2)
+  call bar (xa1, xa2, xp1, xp2, xat1, xat2, xt1, xt2, xi1, xi2)
+
+  deallocate (xa1, xa2, xat1, xat2, xp1, xp2)
+contains
+! Implicit mapping
+subroutine foo (ia1, ia2, ip1, ip2, iat1, iat2, it1, it2, ii1, ii2)
+  implicit none
+  integer :: ia1, ia2, ia3, ip1, ip2, ip3, iat1, iat2, iat3, it1, it2, it3, ii1, ii2, ii3
+  allocatable :: ia1, ia2, ia3, iat1, iat2, iat3
+  pointer :: ip1, ip2, ip3
+  target :: iat1, iat2, iat3, it1, it2, it3
+  optional :: ia1, ip1, iat1, it1, ii1
+
+  allocate(ia3, iat3, ip3)
+
+  ia1 = 2; ia2 = 2; ia3 = 2; ip1 = 2; ip2 = 2; ip3 = 2;
+  iat1 = 2; iat2 = 2; iat3 = 2; it1 = 2; it2 = 2; it3 = 2
+  ii1 = 2; ii2 = 2; ii3 = 2
+
+  ! Implicitly, scalars are 'firstprivate' except
+  ! if target, allocatable, pointer they are always tofrom.
+  !$omp target
+    if (ia1 /= 2) stop 1
+    if (ia2 /= 2) stop 2
+    if (ia3 /= 2) stop 3
+    if (ip1 /= 2) stop 4
+    if (ip2 /= 2) stop 5
+    if (ip3 /= 2) stop 6
+    if (iat1 /= 2) stop 7
+    if (iat2 /= 2) stop 8 
+    if (iat3 /= 2) stop 9
+    if (it1 /= 2) stop 10
+    if (it2 /= 2) stop 11
+    if (it3 /= 2) stop 12
+    if (ii1 /= 2) stop 13
+    if (ii2 /= 2) stop 14
+    if (ii3 /= 2) stop 15
+
+    ia1 = 1; ia2 = 1; ia3 = 1; ip1 = 1; ip2 = 1; ip3 = 1;
+    iat1 = 1; iat2 = 1; iat3 = 1; it1 = 1; it2 = 1; it3 = 1
+    ii1 = 1; ii2 = 1; ii3 = 1
+  !$omp end target
+
+  ! (target,allocatable,pointer) -> tofrom
+  if (ia1 /= 1) stop 16
+  if (ia2 /= 1) stop 17
+  if (ia3 /= 1) stop 18
+  if (ip1 /= 1) stop 19
+  if (ip2 /= 1) stop 20
+  if (ip3 /= 1) stop 21
+  if (iat1 /= 1) stop 22
+  if (iat2 /= 1) stop 23
+  if (iat3 /= 1) stop 24
+  if (it1 /= 1) stop 25
+  if (it2 /= 1) stop 26
+  if (it3 /= 1) stop 27
+  ! non-(target,allocatable,pointer) -> firstprivate
+  !if (ii1 /= 2) stop 28  !  FIXME: optional scalar wrongly mapped as tofrom, PR fortran/100991
+  if (ii2 /= 2) stop 29
+  if (ii3 /= 2) stop 30
+
+  deallocate(ia3, iat3, ip3)
+end
+
+! Implicit mapping likewise even though there is defaultmap
+subroutine foo2 (ia1, ia2, ip1, ip2, iat1, iat2, it1, it2, ii1, ii2)
+  implicit none
+  integer :: ia1, ia2, ia3, ip1, ip2, ip3, iat1, iat2, iat3, it1, it2, it3, ii1, ii2, ii3
+  allocatable :: ia1, ia2, ia3, iat1, iat2, iat3
+  pointer :: ip1, ip2, ip3
+  target :: iat1, iat2, iat3, it1, it2, it3
+  optional :: ia1, ip1, iat1, it1, ii1
+
+  allocate(ia3, iat3, ip3)
+
+  ia1 = 2; ia2 = 2; ia3 = 2; ip1 = 2; ip2 = 2; ip3 = 2;
+  iat1 = 2; iat2 = 2; iat3 = 2; it1 = 2; it2 = 2; it3 = 2
+  ii1 = 2; ii2 = 2; ii3 = 2
+
+  ! Implicitly, scalars are 'firstprivate' except
+  ! if target, allocatable, pointer they are always tofrom.
+  !$omp target defaultmap(default)
+    if (ia1 /= 2) stop 31
+    if (ia2 /= 2) stop 32
+    if (ia3 /= 2) stop 33
+    if (ip1 /= 2) stop 34
+    if (ip2 /= 2) stop 35
+    if (ip3 /= 2) stop 36
+    if (iat1 /= 2) stop 37
+    if (iat2 /= 2) stop 38 
+    if (iat3 /= 2) stop 39
+    if (it1 /= 2) stop 40
+    if (it2 /= 2) stop 41
+    if (it3 /= 2) stop 42
+    if (ii1 /= 2) stop 43
+    if (ii2 /= 2) stop 44
+    if (ii3 /= 2) stop 45
+
+    ia1 = 1; ia2 = 1; ia3 = 1; ip1 = 1; ip2 = 1; ip3 = 1;
+    iat1 = 1; iat2 = 1; iat3 = 1; it1 = 1; it2 = 1; it3 = 1
+    ii1 = 1; ii2 = 1; ii3 = 1
+  !$omp end target
+
+  ! (target,allocatable,pointer) -> tofrom
+  if (ia1 /= 1) stop 46
+  if (ia2 /= 1) stop 47
+  if (ia3 /= 1) stop 48
+  if (ip1 /= 1) stop 49
+  if (ip2 /= 1) stop 50
+  if (ip3 /= 1) stop 51
+  if (iat1 /= 1) stop 52
+  if (iat2 /= 1) stop 53
+  if (iat3 /= 1) stop 54
+  if (it1 /= 1) stop 55
+  if (it2 /= 1) stop 56
+  if (it3 /= 1) stop 57
+  ! non-(target,allocatable,pointer) -> firstprivate
+  !if (ii1 /= 2) stop 58  !  FIXME: optional scalar wrongly mapped as tofrom, PR fortran/100991
+  if (ii2 /= 2) stop 59
+  if (ii3 /= 2) stop 60
+
+  deallocate(ia3, iat3, ip3)
+end
+
+! Implicit mapping likewise even though there is defaultmap
+subroutine foo3 (ia1, ia2, ip1, ip2, iat1, iat2, it1, it2, ii1, ii2)
+  implicit none
+  integer :: ia1, ia2, ia3, ip1, ip2, ip3, iat1, iat2, iat3, it1, it2, it3, ii1, ii2, ii3
+  allocatable :: ia1, ia2, ia3, iat1, iat2, iat3
+  pointer :: ip1, ip2, ip3
+  target :: iat1, iat2, iat3, it1, it2, it3
+  optional :: ia1, ip1, iat1, it1, ii1
+
+  allocate(ia3, iat3, ip3)
+
+  ia1 = 2; ia2 = 2; ia3 = 2; ip1 = 2; ip2 = 2; ip3 = 2;
+  iat1 = 2; iat2 = 2; iat3 = 2; it1 = 2; it2 = 2; it3 = 2
+  ii1 = 2; ii2 = 2; ii3 = 2
+
+  ! Implicitly, scalars are 'firstprivate' except
+  ! if target, allocatable, pointer they are always tofrom.
+  !$omp target defaultmap(none:aggregate)
+    if (ia1 /= 2) stop 61
+    if (ia2 /= 2) stop 62
+    if (ia3 /= 2) stop 63
+    if (ip1 /= 2) stop 64
+    if (ip2 /= 2) stop 65
+    if (ip3 /= 2) stop 66
+    if (iat1 /= 2) stop 67
+    if (iat2 /= 2) stop 68 
+    if (iat3 /= 2) stop 69
+    if (it1 /= 2) stop 70
+    if (it2 /= 2) stop 71
+    if (it3 /= 2) stop 72
+    if (ii1 /= 2) stop 73
+    if (ii2 /= 2) stop 74
+    if (ii3 /= 2) stop 75
+
+    ia1 = 1; ia2 = 1; ia3 = 1; ip1 = 1; ip2 = 1; ip3 = 1;
+    iat1 = 1; iat2 = 1; iat3 = 1; it1 = 1; it2 = 1; it3 = 1
+    ii1 = 1; ii2 = 1; ii3 = 1
+  !$omp end target
+
+  ! (target,allocatable,pointer) -> tofrom
+  if (ia1 /= 1) stop 76
+  if (ia2 /= 1) stop 77
+  if (ia3 /= 1) stop 78
+  if (ip1 /= 1) stop 79
+  if (ip2 /= 1) stop 80
+  if (ip3 /= 1) stop 81
+  if (iat1 /= 1) stop 82
+  if (iat2 /= 1) stop 83
+  if (iat3 /= 1) stop 84
+  if (it1 /= 1) stop 85
+  if (it2 /= 1) stop 86
+  if (it3 /= 1) stop 87
+  ! non-(target,allocatable,pointer) -> firstprivate
+  !if (ii1 /= 2) stop 88  !  FIXME: optional scalar wrongly mapped as tofrom, PR fortran/100991
+  if (ii2 /= 2) stop 89
+  if (ii3 /= 2) stop 90
+
+  deallocate(ia3, iat3, ip3)
+end
+
+subroutine bar (ea1, ea2, ep1, ep2, eat1, eat2, et1, et2, ei1, ei2)
+  implicit none
+  integer :: ea1, ea2, ea3, ep1, ep2, ep3, eat1, eat2, eat3, et1, et2, et3, ei1, ei2, ei3
+  allocatable :: ea1, ea2, ea3, eat1, eat2, eat3
+  pointer :: ep1, ep2, ep3
+  target :: eat1, eat2, eat3, et1, et2, et3
+  optional :: ea1, ep1, eat1, et1, ei1
+
+  allocate(ea3, eat3, ep3)
+
+  ea1 = 2; ea2 = 2; ea3 = 2; ep1 = 2; ep2 = 2; ep3 = 2;
+  eat1 = 2; eat2 = 2; eat3 = 2; et1 = 2; et2 = 2; et3 = 2
+  ei1 = 2; ei2 = 2; ei3 = 2
+
+  ! While here 'scalar' implies nonallocatable/nonpointer and
+  ! the target attribute plays no role.
+  !$omp target defaultmap(tofrom:scalar) defaultmap(firstprivate:allocatable) &
+  !$omp&       defaultmap(none:aggregate) defaultmap(firstprivate:pointer)
+    if (ea1 /= 2) stop 91
+    if (ea2 /= 2) stop 92
+    if (ea3 /= 2) stop 93
+    if (ep1 /= 2) stop 94
+    if (ep2 /= 2) stop 95
+    if (ep3 /= 2) stop 96
+    if (eat1 /= 2) stop 97
+    if (eat2 /= 2) stop 98 
+    if (eat3 /= 2) stop 99
+    if (et1 /= 2) stop 100
+    if (et2 /= 2) stop 101
+    if (et3 /= 2) stop 102
+    if (ei1 /= 2) stop 103
+    if (ei2 /= 2) stop 104
+    if (ei3 /= 2) stop 105
+    ep1 => null(); ep2 => null(); ep3 => null()
+    ea1 = 1; ea2 = 1; ea3 = 1
+    eat1 = 1; eat2 = 1; eat3 = 1
+    et1 = 1; et2 = 1; et3 = 1
+    ei1 = 1; ei2 = 1; ei3 = 1
+  !$omp end target
+  ! (allocatable,pointer) -> firstprivate
+
+! FIXME: allocatables not properly privatized, cf. PR fortran/90742
+
+!  if (ea1 /= 2) stop 106
+!  if (ea2 /= 2) stop 107
+!  if (ea3 /= 2) stop 108
+!  if (eat1 /= 2) stop 112
+!  if (eat2 /= 2) stop 113
+!  if (eat3 /= 2) stop 114
+  if (ep1 /= 2) stop 109
+  if (ep2 /= 2) stop 110
+  if (ep3 /= 2) stop 111
+  ! (scalar) -> tofrom
+  !if (et1 /= 1) stop 115  !  FIXME: optional scalar wrongly mapped as 'firstprivate', PR fortran/100991
+  if (et2 /= 1) stop 116
+  if (et3 /= 1) stop 117
+  !if (ei1 /= 1) stop 118  !  FIXME: optional scalar wrongly mapped as 'firstprivate', PR fortran/100991
+  if (ei2 /= 1) stop 119
+  if (ei3 /= 1) stop 120
+
+  deallocate(ea3, eat3, ep3)
+end
+
+end
+
+! FIXME/xfail: Optional scalars wrongly classified, PR fortran/100991
+! { dg-final { scan-tree-dump-times "firstprivate\\(ii1\\)" 3 "gimple" { xfail *-*-* } } }
+! { dg-final { scan-tree-dump-not "firstprivate\\(et1\\)" "gimple" { xfail *-*-* } } }
+! { dg-final { scan-tree-dump-not "firstprivate\\(ei1\\)" "gimple" { xfail *-*-* } } }
+
+! { dg-final { scan-tree-dump-times "firstprivate\\(ea1\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(ea2\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(ea3\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(eat1\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(eat2\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(eat3\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(ep1\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(ep2\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "firstprivate\\(ep3\\)" 1 "gimple" } }