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;
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
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;
else
pushdecl (vardecl);
- cp_check_omp_declare_mapper (vardecl);
+ cp_check_omp_declare_mapper (mapper);
cp_parser_require_pragma_eol (parser, pragma_tok);
return;
TREE_TYPE (t) = type;
OMP_DECLARE_MAPPER_DECL (t) = decl;
OMP_DECLARE_MAPPER_CLAUSES (t) = clauses;
+ cp_check_omp_declare_mapper (t);
RETURN (t);
}
TREE_TYPE (t) = type;
OMP_DECLARE_MAPPER_DECL (t) = decl;
OMP_DECLARE_MAPPER_CLAUSES (t) = clauses;
+ cp_check_omp_declare_mapper (t);
RETURN (t);
}
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;
}
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
/* { dg-additional-options "-fdump-tree-gimple" } */
struct S {
// { 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;
// { 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 }
#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 }
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
/* { dg-options "-fopenmp -fdump-tree-gimple" } */
typedef struct {
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
/* { dg-options "-fopenmp -fdump-tree-gimple" } */
typedef struct {
--- /dev/null
+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)
+}
--- /dev/null
+// { 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" }
-// { dg-do compile }
+// { dg-do compile { target { c || c++11 } } }
// { dg-additional-options "-fdump-tree-gimple" }
#include <stdlib.h>
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
/* { dg-additional-options "-fdump-tree-original" } */
/* Check mapper binding clauses. */
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
typedef struct S_ {
int *myarr;
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
int x = 5;
#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;
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
struct Q {
int *arr1;
#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;
}
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
struct Q {
int *arr1;
-/* { dg-do compile } */
+/* { dg-do compile { target { c || c++11 } } } */
int x = 5;
#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 ()
-// { dg-do compile }
+// { dg-do compile { target c++11 } }
// { dg-additional-options "-fdump-tree-gimple" }
// "omp declare mapper" support -- check expansion in gimple.
-// { dg-do compile }
+// { dg-do compile { target c++11 } }
// Error-checking tests for "omp declare mapper".
+// { 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 }
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;
#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'" }
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 }
--- /dev/null
+// { 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" } }
--- /dev/null
+// { 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>();
+}