[gcc/devel/omp/gcc-16] OpenMP: mapper [C/C++] reject w/o map usage, reject C++98, fix map decay

Sandra Loosemore via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:a81936e59ea37abbd318ca252dd90c96e4f7b405

commit a81936e59ea37abbd318ca252dd90c96e4f7b405
Author: Tobias Burnus <[email protected]>
Date:   Thu May 14 18:23:57 2026 +0200

    OpenMP: mapper [C/C++] reject w/o map usage, reject C++98, fix map decay
    
    This commit adds a check for the following 'declare mapper restriction:
    "At least one map clause that maps var or at least one element of var is
     required."
    
    It additionally fixes a bug in the map-decay code, which did not handle
    map modifiers like 'always' when specified in the declare mapper's map
    clause.
    
    For C++, some checks are now also run when templates are involved.
    Additionally, it turned out that the internal use of constexpr caused
    bogus errors when compiled with -std=c++98; therefore, a sorry is now
    shown. Solution is to use -std=c++11 or higher.
    
    gcc/c-family/ChangeLog:
    
            * c-omp.cc (omp_map_decayed_kind): Handle map modifiers
            also for declare-mapper's map clauses.
    
    gcc/c/ChangeLog:
    
            * c-parser.cc (c_parser_omp_declare_mapper): Check that the
            struct var is actually used by at least one map clause.
    
    gcc/cp/ChangeLog:
    
            * semantics.cc (cp_check_omp_declare_mapper): Change what
            argument is expected; check that the struct var is used by at
            least one map war. Print sorry when compiling with -std=c++98.
            * pt.cc (tsubst_stmt, tsubst_expr): Call it.
            * parser.cc (cp_parser_omp_declare_mapper): Update call.
    
    gcc/testsuite/ChangeLog:
    
            * c-c++-common/gomp/declare-mapper-10.c: Exclude C++98.
            * c-c++-common/gomp/declare-mapper-15.c: Likewise.
            * c-c++-common/gomp/declare-mapper-16.c: Likewise.
            * c-c++-common/gomp/declare-mapper-3.c: Likewise.
            * c-c++-common/gomp/declare-mapper-4.c: Likewise.
            * c-c++-common/gomp/declare-mapper-5.c: Likewise.
            * c-c++-common/gomp/declare-mapper-6.c: Likewise.
            * c-c++-common/gomp/declare-mapper-7.c: Likewise.
            * c-c++-common/gomp/declare-mapper-8.c: Likewise.
            * c-c++-common/gomp/declare-mapper-9.c: Likewise.
            * g++.dg/gomp/declare-mapper-1.C: Likewise.
            * g++.dg/gomp/declare-mapper-2.C: Likewise.
            * c-c++-common/gomp/pr122866.c: Expect sorry with C++98.
            * c-c++-common/gomp/declare-mapper-11.c: Likewise.
            Add dg-error for missing var-in-map-clause use.
            * g++.dg/gomp/declare-mapper-3.C: Likewise.
            * c-c++-common/gomp/declare-mapper-17.c: New test.
            * c-c++-common/gomp/declare-mapper-18.c: New test.
            * g++.dg/gomp/declare-mapper-4.C: New test.
            * g++.dg/gomp/declare-mapper-5.C: New test.
    
    (cherry picked from commit 325b88b9a4588c08c4dca9bc9ff19f029e90cc45)

Diff:
---
 gcc/c-family/c-omp.cc                              |  5 ++-
 gcc/c/c-parser.cc                                  | 12 +++++
 gcc/cp/parser.cc                                   |  2 +-
 gcc/cp/pt.cc                                       |  2 +
 gcc/cp/semantics.cc                                | 52 ++++++++++++++++++++--
 .../c-c++-common/gomp/declare-mapper-10.c          |  2 +-
 .../c-c++-common/gomp/declare-mapper-11.c          |  5 +++
 .../c-c++-common/gomp/declare-mapper-15.c          |  2 +-
 .../c-c++-common/gomp/declare-mapper-16.c          |  2 +-
 .../c-c++-common/gomp/declare-mapper-17.c          | 23 ++++++++++
 .../c-c++-common/gomp/declare-mapper-18.c          | 39 ++++++++++++++++
 gcc/testsuite/c-c++-common/gomp/declare-mapper-3.c |  2 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-4.c |  2 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-5.c |  2 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-6.c |  3 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-7.c |  3 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-8.c |  2 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-9.c |  2 +-
 gcc/testsuite/c-c++-common/gomp/pr122866.c         |  1 +
 gcc/testsuite/g++.dg/gomp/declare-mapper-1.C       |  2 +-
 gcc/testsuite/g++.dg/gomp/declare-mapper-2.C       |  2 +-
 gcc/testsuite/g++.dg/gomp/declare-mapper-3.C       |  6 +++
 gcc/testsuite/g++.dg/gomp/declare-mapper-4.C       | 23 ++++++++++
 gcc/testsuite/g++.dg/gomp/declare-mapper-5.C       | 29 ++++++++++++
 24 files changed, 207 insertions(+), 18 deletions(-)

diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc
index f75f0788ac66..b48243a22616 100644
--- a/gcc/c-family/c-omp.cc
+++ b/gcc/c-family/c-omp.cc
@@ -4517,8 +4517,10 @@ omp_map_decayed_kind (enum gomp_map_kind mapper_kind,
   if (invoked_as == GOMP_MAP_RELEASE || invoked_as == GOMP_MAP_DELETE)
     return invoked_as;
 
+  bool m_force_p, m_always_p, m_present_p;
   bool force_p, always_p, present_p;
 
+  mapper_kind = omp_split_map_kind (mapper_kind, &m_force_p, &m_always_p, &m_present_p);
   invoked_as = omp_split_map_kind (invoked_as, &force_p, &always_p, &present_p);
   gomp_map_kind decay_to;
 
@@ -4556,7 +4558,8 @@ omp_map_decayed_kind (enum gomp_map_kind mapper_kind,
       gcc_unreachable ();
     }
 
-  return omp_join_map_kind (decay_to, force_p, always_p, present_p);
+  return omp_join_map_kind (decay_to, m_force_p | force_p,
+			    m_always_p | always_p, m_present_p | present_p);
 }
 
 /* Instantiate a mapper MAPPER for expression EXPR, adding new clauses to
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 9c0e65a74e5b..a2d40c43027f 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -29212,6 +29212,18 @@ c_parser_omp_declare_mapper (c_parser *parser, enum pragma_context context)
       error_at (input_location, "missing %<map%> clause");
       goto fail;
     }
+  tree list;
+  for (list = maplist; list; list = OMP_CLAUSE_CHAIN (list))
+    {
+      tree dvar = OMP_CLAUSE_DECL (list);
+      while (!DECL_P (dvar) && TREE_OPERAND_LENGTH (dvar))
+	dvar = TREE_OPERAND (dvar, 0);
+      if (dvar == var)
+	break;
+    }
+  if (!list)
+    error_at (input_location, "at least one %<map%> clause must map %qD or an "
+			      "element of it", var);
 
   stmt = make_node (OMP_DECLARE_MAPPER);
   TREE_TYPE (stmt) = type;
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index edbd3431643c..9dcc2c475363 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -55689,7 +55689,7 @@ cp_parser_omp_declare_mapper (cp_parser *parser, cp_token *pragma_tok,
   else
     pushdecl (vardecl);
 
-  cp_check_omp_declare_mapper (vardecl);
+  cp_check_omp_declare_mapper (mapper);
 
   cp_parser_require_pragma_eol (parser, pragma_tok);
   return;
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 25982f02820c..c75871719b14 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -20760,6 +20760,7 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	TREE_TYPE (t) = type;
 	OMP_DECLARE_MAPPER_DECL (t) = decl;
 	OMP_DECLARE_MAPPER_CLAUSES (t) = clauses;
+	cp_check_omp_declare_mapper (t);
 	RETURN (t);
       }
 
@@ -21879,6 +21880,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	TREE_TYPE (t) = type;
 	OMP_DECLARE_MAPPER_DECL (t) = decl;
 	OMP_DECLARE_MAPPER_CLAUSES (t) = clauses;
+	cp_check_omp_declare_mapper (t);
 	RETURN (t);
       }
 
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 6535376a5f97..344b03738c69 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -7445,25 +7445,69 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
 bool
 cp_check_omp_declare_mapper (tree udm)
 {
-  tree type = TREE_TYPE (udm);
-  location_t loc = DECL_SOURCE_LOCATION (udm);
+  tree var = OMP_DECLARE_MAPPER_DECL (udm);
+  tree type = TREE_TYPE (var);
+  location_t loc = DECL_SOURCE_LOCATION (var);
 
   if (type == error_mark_node)
     return false;
 
-  if (!processing_template_decl && !RECORD_OR_UNION_TYPE_P (type))
+  if (processing_template_decl)
+    return true;
+
+  if (!RECORD_OR_UNION_TYPE_P (type))
     {
       error_at (loc, "%qT is not a struct, union or class type in "
 		"%<#pragma omp declare mapper%>", type);
       return false;
     }
-  if (!processing_template_decl && CLASSTYPE_VBASECLASSES (type))
+  if (CLASSTYPE_VBASECLASSES (type))
     {
       error_at (loc, "%qT must not be a virtual base class in "
 		"%<#pragma omp declare mapper%>", type);
       return false;
     }
 
+  tree c = OMP_DECLARE_MAPPER_CLAUSES (udm);
+  for ( ; c; c = OMP_CLAUSE_CHAIN (c))
+    {
+      tree dvar = OMP_CLAUSE_DECL (c);
+      while (!DECL_P (dvar) && TREE_OPERAND_LENGTH (dvar))
+	dvar = TREE_OPERAND (dvar, 0);
+      if (dvar == var)
+	break;
+    }
+  if (!c)
+    {
+      // After template handling, the var is mangled, demangle it
+      const char *name = IDENTIFIER_POINTER (DECL_NAME (var));
+      char *n = NULL;
+      if (startswith (name, "omp declare mapper "))
+	{
+	  name += strlen ("omp declare mapper ");
+	  n = xstrdup (name);
+	  n[strchr (n, '~')-n] = '\0';
+	  name = n;
+	}
+      error_at (loc, "at least one %<map%> clause must map %qs or an "
+		     "element of it", name);
+      if (n)
+	free (n);
+      return false;
+    }
+
+  /* FIXME: The vardecl created for the mapper_id uses DECL_DECLARED_CONSTEXPR_P
+     = 1, which is set to false in finalize_literal_type_property for C++ < 11,
+     leading to an error in ensure_literal_type_for_constexpr_object.
+     Examples (compile with -std=c++98): gcc.dg/gomp/declare-mapper-13.c and
+     libgomp.c++/declare-mapper-{5,6,8}.C.  */
+  if (cxx_dialect < cxx11)
+    {
+      sorry_at (loc, "%<#pragma omp declare mapper%> with %<-std=%> set to "
+		     "before C++11");
+      return false;
+    }
+
   return true;
 }
 
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-10.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-10.c
index 4020c4bae307..6d0f285ee029 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-mapper-10.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-10.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
 /* { dg-additional-options "-fdump-tree-gimple" } */
 
 struct S {
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-11.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-11.c
index 1f65bad694dd..89d84db87a04 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-mapper-11.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-11.c
@@ -18,9 +18,11 @@ struct XT {
 // { dg-error "expected primary-expression before '\\)' token" "" { target c++ } .-1 }
 // { dg-error "unknown type name 'XT'" "" { target c } .-2 }
 // { dg-error "expected end of line before 'y'" "" { target c } .-3 }
+// { dg-error "at least one 'map' clause must map 'y' or an element of it" "" { target c++ } .-4 }
 #pragma omp declare mapper ( bar : struct XT y) map()
 // { dg-error "expected primary-expression before '\\)' token" "" { target c++ } .-1 }
 // { dg-error "expected expression before '\\)' token" "" { target c } .-2 }
+// { dg-error "at least one 'map' clause must map 'y' or an element of it" "" { target *-*-* } .-3 }
 
 struct t {
   int x;
@@ -45,8 +47,10 @@ typedef struct t myStruct;
 // { dg-error "expected primary-expression before '\\)' token" "" { target c++ } .-1 }
 // { dg-error "unknown type name 't'" "" { target c } .-2 }
 // { dg-error "expected end of line before 'v'" "" { target c } .-3 }
+// { dg-error "at least one 'map' clause must map 'v' or an element of it" "" { target c++ } .-4 }
 
 #pragma omp declare mapper(fancy : struct t v) map(always,present,close,mapper(d),tofrom: v) // { dg-error "in 'declare mapper' directives, parameter to 'mapper' modifier must be 'default'" }
+// { dg-message "sorry, unimplemented: '#pragma omp declare mapper' with '-std=' set to before C++11" "" { target c++98_only } .-1 }
 
 #pragma omp declare mapper(myStruct v) map(v, v.x)
 // { dg-note "'#pragma omp declare mapper \\(myStruct\\)' previously declared here" "" { target c++ } .-1 }
@@ -61,6 +65,7 @@ union u_q { };
 #pragma omp declare mapper(union u_t v) map()
 // { dg-error "expected primary-expression before '\\)' token" "" { target c++ } .-1 }
 // { dg-error "expected expression before '\\)' token" "" { target c } .-2 }
+// { dg-error "at least one 'map' clause must map 'v' or an element of it" "" { target *-*-* } .-3 }
 
 #pragma omp declare mapper( one : union u_t v) map(v)
 // { dg-note "'#pragma omp declare mapper \\(one: u_t\\)' previously declared here" "" { target c++ } .-1 }
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-15.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-15.c
index ecda2e5ebd1a..2d5c50eb4eae 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-mapper-15.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-15.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
 /* { dg-options "-fopenmp -fdump-tree-gimple" } */
 
 typedef struct {
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-16.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-16.c
index 20383cc2d69f..ba3559293c4d 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-mapper-16.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-16.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
 /* { dg-options "-fopenmp -fdump-tree-gimple" } */
 
 typedef struct {
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-17.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-17.c
new file mode 100644
index 000000000000..a77896fe4cc3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-17.c
@@ -0,0 +1,23 @@
+typedef struct S { int x;} S;
+int x;
+S s;
+
+void f() {
+  #pragma omp declare mapper(S var) map(to: x) /* { dg-error "at least one 'map' clause must map 'var' or an element of it" } */
+  #pragma omp target enter data map(s)
+}
+
+void f2()
+{
+  int x;
+  #pragma omp declare mapper (int var) map(always, to: var)
+// { dg-error "'int' is not a struct or union type in '#pragma omp declare mapper'" "" { target c } .-1 }
+// { dg-error "'int' is not a struct, union or class type in '#pragma omp declare mapper'" "" { target c++ } .-2 }
+  #pragma omp target enter data map(x)
+}
+
+void f3() {
+  float g[2];
+  #pragma omp declare mapper (S var) map(always, to: g[var.x]) // { dg-error "at least one 'map' clause must map 'var' or an element of it" }
+  #pragma omp target enter data map(g)
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-18.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-18.c
new file mode 100644
index 000000000000..6b53b1b1e18d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-18.c
@@ -0,0 +1,39 @@
+// { dg-do compile { target { c || c++11 } } }
+// { dg-additional-options "-fdump-tree-gimple" }
+
+typedef struct S { int x;} S;
+int x;
+S s1;
+S s2;
+
+void f() {
+  #pragma omp declare mapper(S var) map(to: var)
+  #pragma omp target exit data map(always, from: s1)
+}
+
+void f2() {
+  #pragma omp declare mapper(S var) map(present, to: var)
+  #pragma omp target enter data map(always, tofrom : s2)
+}
+
+void f3()
+{
+  S x;
+  int y;
+  #pragma omp declare mapper (S var) map(always, to: var, y)
+  #pragma omp target enter data map(x)
+}
+
+
+// to + 'exit date' always from -> release
+// { dg final { scan-dump "static int omp declare mapper <default> = struct S #pragma omp declare mapper \\(struct S var\\) map\\(to:var\\);" "gimple" }
+// { dg final { scan-dump "#pragma omp target exit data map\\(release:s1 \\\[len: 4\\\]\\)" "gimple" }
+
+
+// present,to + always,from -> always,present,to
+// { dg final { scan-dump "static int omp declare mapper <default> = struct S #pragma omp declare mapper \\(struct S var\\) map\\(present,to:var\\);" "gimple" }
+// { dg final { scan-dump "#pragma omp target enter data map\\(always,present,to:s2 \\\[len: 4\\\]\\)" "gimple" }
+
+// always,to + - -> always,to
+// { dg final { scan-dump "static int omp declare mapper <default> = struct S #pragma omp declare mapper \\(struct S var\\) map\\(always,to:y\\) map\\(always,to:var\\);" "gimple" }
+// { dg final { scan-dump "#pragma omp target enter data map\\(always,to:y \\\[len: 4\\\]\\) map\\(always,to:x \\\[len: 4\\\]\\)" "gimple" }
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-3.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-3.c
index c0ec21b1b380..c78e54293b96 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-mapper-3.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-3.c
@@ -1,4 +1,4 @@
-// { dg-do compile }
+// { dg-do compile { target { c || c++11 } } }
 // { dg-additional-options "-fdump-tree-gimple" }
 
 #include <stdlib.h>
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-4.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-4.c
index 39e3ab114199..55a9af8edef6 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-mapper-4.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-4.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
 /* { dg-additional-options "-fdump-tree-original" } */
 
 /* Check mapper binding clauses.  */
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-5.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-5.c
index e8ab15941419..7671595f8d5d 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-mapper-5.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-5.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
 
 typedef struct S_ {
   int *myarr;
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-6.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-6.c
index c13eb8b5816e..6d0b607041ae 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-mapper-6.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-6.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
 
 int x = 5;
 
@@ -19,5 +19,6 @@ struct R {
 #pragma omp declare mapper (struct R myr) map(myr.arr3[0:y])
 /* { dg-error "'y' undeclared" "" { target c } .-1 } */
 /* { dg-error "'y' was not declared in this scope" "" { target c++ } .-2 } */
+/* { dg-error "at least one 'map' clause must map 'myr' or an element of it" "" { target c++ } .-3 } */
 
 int y = 7;
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-7.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-7.c
index 0f8dd25a18dc..acd00678b569 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-mapper-7.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-7.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
 
 struct Q {
   int *arr1;
@@ -24,6 +24,7 @@ int bar (void)
   #pragma omp declare mapper (struct R myr) map(myr.arr3[0:y])
   /* { dg-error "'y' undeclared" "" { target c } .-1 } */
   /* { dg-error "'y' was not declared in this scope" "" { target c++ } .-2 } */
+  /* { dg-error "at least one 'map' clause must map 'myr' or an element of it" "" { target c++ } .-3 } */
   int y = 7;
   return y;
 }
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-8.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-8.c
index dadca282711c..6cf25df0ab7f 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-mapper-8.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-8.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
 
 struct Q {
   int *arr1;
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-9.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-9.c
index 709bc0c8f4de..6e00bb688f6c 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-mapper-9.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-9.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
 
 int x = 5;
 
diff --git a/gcc/testsuite/c-c++-common/gomp/pr122866.c b/gcc/testsuite/c-c++-common/gomp/pr122866.c
index bb42bc634dbd..58972e1b9f41 100644
--- a/gcc/testsuite/c-c++-common/gomp/pr122866.c
+++ b/gcc/testsuite/c-c++-common/gomp/pr122866.c
@@ -8,6 +8,7 @@ void froggify (struct test);
 
 #pragma omp declare mapper(struct test v) map(iterator(i = 0:1), tofrom: v.x)
 /* { dg-message "sorry, unimplemented: user-defined mapper that uses a .map. clause with .iterator." "" { target *-*-* } .-1 } */
+/* { dg-message "'#pragma omp declare mapper' with '-std=' set to before C++11" "" { target c++98_only } .-2 } */
 
 int
 main ()
diff --git a/gcc/testsuite/g++.dg/gomp/declare-mapper-1.C b/gcc/testsuite/g++.dg/gomp/declare-mapper-1.C
index 2f2dd219bcb5..f74c3bb38929 100644
--- a/gcc/testsuite/g++.dg/gomp/declare-mapper-1.C
+++ b/gcc/testsuite/g++.dg/gomp/declare-mapper-1.C
@@ -1,4 +1,4 @@
-// { dg-do compile }
+// { dg-do compile { target c++11 } }
 // { dg-additional-options "-fdump-tree-gimple" }
 
 // "omp declare mapper" support -- check expansion in gimple.
diff --git a/gcc/testsuite/g++.dg/gomp/declare-mapper-2.C b/gcc/testsuite/g++.dg/gomp/declare-mapper-2.C
index 379be2900182..cf2e4d0aaa3c 100644
--- a/gcc/testsuite/g++.dg/gomp/declare-mapper-2.C
+++ b/gcc/testsuite/g++.dg/gomp/declare-mapper-2.C
@@ -1,4 +1,4 @@
-// { dg-do compile }
+// { dg-do compile { target c++11 } }
 
 // Error-checking tests for "omp declare mapper".
 
diff --git a/gcc/testsuite/g++.dg/gomp/declare-mapper-3.C b/gcc/testsuite/g++.dg/gomp/declare-mapper-3.C
index 1f019c710ca1..4ad09b2ffd2e 100644
--- a/gcc/testsuite/g++.dg/gomp/declare-mapper-3.C
+++ b/gcc/testsuite/g++.dg/gomp/declare-mapper-3.C
@@ -1,3 +1,5 @@
+// { dg-do compile { target c++11 } }
+
 #pragma omp declare mapper (int v)  // { dg-error "missing 'map' clause before end of line" }
 #pragma omp declare mapper (float v) map()  // { dg-error "expected primary-expression before '\\)' token" }
 // { dg-error "'float' is not a struct, union or class type in '#pragma omp declare mapper'" "" { target *-*-* } .-1 }
@@ -8,6 +10,8 @@ struct XT {
   int x;
 };
 #pragma omp declare mapper (XT y) map()  // { dg-error "expected primary-expression before '\\)' token" }
+// { dg-error "at least one 'map' clause must map 'y' or an element of it" "" { target *-*-* } .-1 }
+
 
 struct t {
   int x;
@@ -20,6 +24,7 @@ typedef struct t myStruct;
 #pragma omp declare mapper(myStruct) // { dg-error "expected unqualified-id before '\\)' token" }
 
 #pragma omp declare mapper(name : t v)  map() // { dg-error "expected primary-expression before '\\)' token" } 
+// { dg-error "at least one 'map' clause must map 'v' or an element of it" "" { target *-*-* } .-1 }
 
 #pragma omp declare mapper(fancy : struct t v) map(always,present,close,mapper(d),tofrom: v) // { dg-error "in 'declare mapper' directives, parameter to 'mapper' modifier must be 'default'" }
 
@@ -37,3 +42,4 @@ class B : public virtual A { };
 union u_t { };
 
 #pragma omp declare mapper(u_t v) map()  // { dg-error "expected primary-expression before '\\)' token" }
+// { dg-error "at least one 'map' clause must map 'v' or an element of it" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/gomp/declare-mapper-4.C b/gcc/testsuite/g++.dg/gomp/declare-mapper-4.C
new file mode 100644
index 000000000000..52ad3d7e95ff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/declare-mapper-4.C
@@ -0,0 +1,23 @@
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-fdump-tree-original" }
+
+// Ensure that always in mapper does not ICE and gets propagated to both 'x' and 'y'
+
+struct S { int x; };
+
+template<typename T>
+void f()
+{
+  T x;
+  int y;
+  #pragma omp declare mapper (T var) map(always, to: var, y)
+// error: the type 'S' of 'constexpr' variable '#pragma omp declare mapper' is not literal
+  #pragma omp target enter data map(x)
+}
+
+void g()
+{
+  f<S>();
+}
+
+// { dg-final { scan-tree-dump "#pragma omp target enter data map\\(always,to:y\\) map\\(always,to:x\\)" "original" } }
diff --git a/gcc/testsuite/g++.dg/gomp/declare-mapper-5.C b/gcc/testsuite/g++.dg/gomp/declare-mapper-5.C
new file mode 100644
index 000000000000..b20b5e2ff71d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/declare-mapper-5.C
@@ -0,0 +1,29 @@
+// { dg-do compile { target c++11 } }
+
+struct S { int x; };
+
+template<typename T>
+void f()
+{
+  T x;
+  int y;
+  #pragma omp declare mapper (T var) map(always, to: var, y) // { dg-error "'int' is not a struct, union or class type in '#pragma omp declare mapper'" }
+  #pragma omp target enter data map(x)
+}
+
+void g()
+{
+  f<int>();
+}
+
+template<typename T>
+void h() {
+  T g[2];
+  #pragma omp declare mapper (S var) map(always, to: g[var.x]) // { dg-error "at least one 'map' clause must map 'var' or an element of it" }
+  #pragma omp target enter data map(g)
+}
+
+void h2()
+{
+  h<S>();
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.