https://gcc.gnu.org/g:325b88b9a4588c08c4dca9bc9ff19f029e90cc45

commit r17-515-g325b88b9a4588c08c4dca9bc9ff19f029e90cc45
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.

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 daf57061ee9a..07c7900c332e 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -29219,6 +29219,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 c7708f15f39b..1ab462160da8 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -55723,7 +55723,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 b6e8948f005a..d19864774a3c 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -20762,6 +20762,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);
       }
 
@@ -21881,6 +21882,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 e9fc01ef28fb..6564d9e37a6f 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -7440,25 +7440,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>();
+}

Reply via email to