[OpenMP 5.0] Parsing/sema support for "omp declare mapper" directive.
This patch implements parsing and sema for "omp declare mapper"
directive. User defined mapper, i.e., declare mapper directive, is a new
feature in OpenMP 5.0. It is introduced to extend existing map clauses
for the purpose of simplifying the copy of complex data structures
between host and device (i.e., deep copy). An example is shown below:
struct S { int len; int *d; };
#pragma omp declare mapper(struct S s) map(s, s.d[0:s.len]) // Memory region that d points to is also mapped using this mapper.
Contributed-by: Lingda Li <lildmh@gmail.com>
Differential Revision: https://reviews.llvm.org/D56326
llvm-svn: 352906
diff --git a/clang/test/OpenMP/declare_mapper_ast_print.c b/clang/test/OpenMP/declare_mapper_ast_print.c
new file mode 100644
index 0000000..a2c78a1
--- /dev/null
+++ b/clang/test/OpenMP/declare_mapper_ast_print.c
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+// CHECK: struct vec {
+struct vec {
+ int len;
+ double *data;
+};
+// CHECK: };
+
+// CHECK: struct dat {
+struct dat {
+ int i;
+ double d;
+#pragma omp declare mapper(id: struct vec v) map(v.len)
+// CHECK: #pragma omp declare mapper (id : struct vec v) map(tofrom: v.len){{$}}
+};
+// CHECK: };
+
+#pragma omp declare mapper(id: struct vec v) map(v.len)
+// CHECK: #pragma omp declare mapper (id : struct vec v) map(tofrom: v.len){{$}}
+#pragma omp declare mapper(default : struct vec kk) map(kk.len) map(kk.data[0:2])
+// CHECK: #pragma omp declare mapper (default : struct vec kk) map(tofrom: kk.len) map(tofrom: kk.data[0:2]){{$}}
+#pragma omp declare mapper(struct dat d) map(to: d.d)
+// CHECK: #pragma omp declare mapper (default : struct dat d) map(to: d.d){{$}}
+
+// CHECK: int main() {
+int main() {
+#pragma omp declare mapper(id: struct vec v) map(v.len)
+// CHECK: #pragma omp declare mapper (id : struct vec v) map(tofrom: v.len)
+ {
+#pragma omp declare mapper(id: struct vec v) map(v.len)
+// CHECK: #pragma omp declare mapper (id : struct vec v) map(tofrom: v.len)
+ }
+ return 0;
+}
+// CHECK: }
+
+#endif
diff --git a/clang/test/OpenMP/declare_mapper_ast_print.cpp b/clang/test/OpenMP/declare_mapper_ast_print.cpp
new file mode 100644
index 0000000..dab7455
--- /dev/null
+++ b/clang/test/OpenMP/declare_mapper_ast_print.cpp
@@ -0,0 +1,97 @@
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+// CHECK: namespace N1 {
+namespace N1
+{
+// CHECK: class vec {
+class vec {
+public:
+ int len;
+ double *data;
+};
+// CHECK: };
+
+#pragma omp declare mapper(id: vec v) map(v.len)
+// CHECK: #pragma omp declare mapper (id : N1::vec v) map(tofrom: v.len){{$}}
+};
+// CHECK: }
+// CHECK: ;
+
+template <class T>
+class dat {
+public:
+ class datin {
+ public:
+ T in;
+ };
+ int i;
+ T d;
+#pragma omp declare mapper(id: N1::vec v) map(v.len)
+#pragma omp declare mapper(id: datin v) map(v.in)
+};
+
+// CHECK: template <class T> class dat {
+// CHECK: #pragma omp declare mapper (id : N1::vec v) map(tofrom: v.len){{$}}
+// CHECK: #pragma omp declare mapper (id : dat::datin v) map(tofrom: v.in){{$}}
+// CHECK: };
+// CHECK: template<> class dat<double> {
+// CHECK: #pragma omp declare mapper (id : N1::vec v) map(tofrom: v.len){{$}}
+// CHECK: #pragma omp declare mapper (id : dat<double>::datin v) map(tofrom: v.in){{$}}
+// CHECK: };
+
+#pragma omp declare mapper(default : N1::vec kk) map(kk.len) map(kk.data[0:2])
+// CHECK: #pragma omp declare mapper (default : N1::vec kk) map(tofrom: kk.len) map(tofrom: kk.data[0:2]){{$}}
+#pragma omp declare mapper(dat<double> d) map(to: d.d)
+// CHECK: #pragma omp declare mapper (default : dat<double> d) map(to: d.d){{$}}
+
+template <typename T>
+T foo(T a) {
+ struct foodat {
+ T a;
+ };
+#pragma omp declare mapper(struct foodat v) map(v.a)
+#pragma omp declare mapper(id: N1::vec v) map(v.len)
+ {
+#pragma omp declare mapper(id: N1::vec v) map(v.len)
+ }
+ return 0;
+}
+
+// CHECK: template <typename T> T foo(T a) {
+// CHECK: #pragma omp declare mapper (default : struct foodat v) map(tofrom: v.a)
+// CHECK: #pragma omp declare mapper (id : N1::vec v) map(tofrom: v.len)
+// CHECK: {
+// CHECK: #pragma omp declare mapper (id : N1::vec v) map(tofrom: v.len)
+// CHECK: }
+// CHECK: }
+// CHECK: template<> int foo<int>(int a) {
+// CHECK: #pragma omp declare mapper (default : struct foodat v) map(tofrom: v.a)
+// CHECK: #pragma omp declare mapper (id : N1::vec v) map(tofrom: v.len)
+// CHECK: {
+// CHECK: #pragma omp declare mapper (id : N1::vec v) map(tofrom: v.len)
+// CHECK: }
+// CHECK: }
+
+// CHECK: int main() {
+int main() {
+#pragma omp declare mapper(id: N1::vec v) map(v.len)
+// CHECK: #pragma omp declare mapper (id : N1::vec v) map(tofrom: v.len)
+ {
+#pragma omp declare mapper(id: N1::vec v) map(v.len)
+// CHECK: #pragma omp declare mapper (id : N1::vec v) map(tofrom: v.len)
+ }
+ return foo<int>(0);
+}
+// CHECK: }
+
+#endif
diff --git a/clang/test/OpenMP/declare_mapper_messages.c b/clang/test/OpenMP/declare_mapper_messages.c
new file mode 100644
index 0000000..c8e65b2
--- /dev/null
+++ b/clang/test/OpenMP/declare_mapper_messages.c
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+
+int temp; // expected-note {{'temp' declared here}}
+
+struct vec { // expected-note {{definition of 'struct vec' is not complete until the closing '}'}}
+ int len;
+#pragma omp declare mapper(id: struct vec v) map(v.len) // expected-error {{incomplete definition of type 'struct vec'}}
+ double *data;
+};
+
+#pragma omp declare mapper // expected-error {{expected '(' after 'declare mapper'}}
+#pragma omp declare mapper { // expected-error {{expected '(' after 'declare mapper'}}
+#pragma omp declare mapper( // expected-error {{expected a type}} expected-error {{expected declarator on 'omp declare mapper' directive}}
+#pragma omp declare mapper(# // expected-error {{expected a type}} expected-error {{expected declarator on 'omp declare mapper' directive}}
+#pragma omp declare mapper(struct v // expected-error {{expected declarator on 'omp declare mapper' directive}}
+#pragma omp declare mapper(struct vec // expected-error {{expected declarator on 'omp declare mapper' directive}}
+#pragma omp declare mapper(S v // expected-error {{unknown type name 'S'}}
+#pragma omp declare mapper(struct vec v // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp declare mapper(aa:struct vec v) // expected-error {{expected at least one clause on '#pragma omp declare mapper' directive}}
+#pragma omp declare mapper(bb:struct vec v) private(v) // expected-error {{expected at least one clause on '#pragma omp declare mapper' directive}} // expected-error {{unexpected OpenMP clause 'private' in directive '#pragma omp declare mapper'}}
+#pragma omp declare mapper(cc:struct vec v) map(v) ( // expected-warning {{extra tokens at the end of '#pragma omp declare mapper' are ignored}}
+
+#pragma omp declare mapper(++: struct vec v) map(v.len) // expected-error {{illegal identifier on 'omp declare mapper' directive}}
+#pragma omp declare mapper(id1: struct vec v) map(v.len, temp) // expected-error {{only variable v is allowed in map clauses of this 'omp declare mapper' directive}}
+#pragma omp declare mapper(default : struct vec kk) map(kk.data[0:2]) // expected-note {{previous definition is here}}
+#pragma omp declare mapper(struct vec v) map(v.len) // expected-error {{redefinition of user-defined mapper for type 'struct vec' with name 'default'}}
+#pragma omp declare mapper(int v) map(v) // expected-error {{mapper type must be of struct, union or class type}}
+
+int fun(int arg) {
+#pragma omp declare mapper(id: struct vec v) map(v.len)
+ {
+#pragma omp declare mapper(id: struct vec v) map(v.len) // expected-note {{previous definition is here}}
+#pragma omp declare mapper(id: struct vec v) map(v.len) // expected-error {{redefinition of user-defined mapper for type 'struct vec' with name 'id'}}
+ {
+#pragma omp declare mapper(id: struct vec v) map(v.len)
+ }
+ }
+ return arg;
+}
diff --git a/clang/test/OpenMP/declare_mapper_messages.cpp b/clang/test/OpenMP/declare_mapper_messages.cpp
new file mode 100644
index 0000000..29c76ad
--- /dev/null
+++ b/clang/test/OpenMP/declare_mapper_messages.cpp
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++11 %s
+
+int temp; // expected-note {{'temp' declared here}}
+
+class vec { // expected-note {{definition of 'vec' is not complete until the closing '}'}}
+private:
+ int p; // expected-note {{declared private here}}
+public:
+ int len;
+#pragma omp declare mapper(id: vec v) map(v.len) // expected-error {{member access into incomplete type 'vec'}}
+ double *data;
+};
+
+#pragma omp declare mapper // expected-error {{expected '(' after 'declare mapper'}}
+#pragma omp declare mapper { // expected-error {{expected '(' after 'declare mapper'}}
+#pragma omp declare mapper( // expected-error {{expected a type}} expected-error {{expected declarator on 'omp declare mapper' directive}}
+#pragma omp declare mapper(# // expected-error {{expected a type}} expected-error {{expected declarator on 'omp declare mapper' directive}}
+#pragma omp declare mapper(v // expected-error {{unknown type name 'v'}} expected-error {{expected declarator on 'omp declare mapper' directive}}
+#pragma omp declare mapper(vec // expected-error {{expected declarator on 'omp declare mapper' directive}}
+#pragma omp declare mapper(S v // expected-error {{unknown type name 'S'}}
+#pragma omp declare mapper(vec v // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp declare mapper(aa: vec v) // expected-error {{expected at least one clause on '#pragma omp declare mapper' directive}}
+#pragma omp declare mapper(bb: vec v) private(v) // expected-error {{expected at least one clause on '#pragma omp declare mapper' directive}} // expected-error {{unexpected OpenMP clause 'private' in directive '#pragma omp declare mapper'}}
+#pragma omp declare mapper(cc: vec v) map(v) ( // expected-warning {{extra tokens at the end of '#pragma omp declare mapper' are ignored}}
+
+#pragma omp declare mapper(++: vec v) map(v.len) // expected-error {{illegal identifier on 'omp declare mapper' directive}}
+#pragma omp declare mapper(id1: vec v) map(v.len, temp) // expected-error {{only variable v is allowed in map clauses of this 'omp declare mapper' directive}}
+#pragma omp declare mapper(default : vec kk) map(kk.data[0:2]) // expected-note {{previous definition is here}}
+#pragma omp declare mapper(vec v) map(v.len) // expected-error {{redefinition of user-defined mapper for type 'vec' with name 'default'}}
+#pragma omp declare mapper(int v) map(v) // expected-error {{mapper type must be of struct, union or class type}}
+#pragma omp declare mapper(id2: vec v) map(v.len, v.p) // expected-error {{'p' is a private member of 'vec'}}
+
+namespace N1 {
+template <class T>
+class stack { // expected-note {{template is declared here}}
+public:
+ int len;
+ T *data;
+#pragma omp declare mapper(id: vec v) map(v.len) // expected-note {{previous definition is here}}
+#pragma omp declare mapper(id: vec v) map(v.len) // expected-error {{redefinition of user-defined mapper for type 'vec' with name 'id'}}
+};
+};
+
+#pragma omp declare mapper(default : N1::stack s) map(s.len) // expected-error {{use of class template 'N1::stack' requires template arguments}}
+#pragma omp declare mapper(id1: N1::stack<int> s) map(s.data)
+#pragma omp declare mapper(default : S<int> s) map(s.len) // expected-error {{no template named 'S'}}
+
+template <class T>
+T foo(T a) {
+#pragma omp declare mapper(id: vec v) map(v.len) // expected-note {{previous definition is here}}
+#pragma omp declare mapper(id: vec v) map(v.len) // expected-error {{redefinition of user-defined mapper for type 'vec' with name 'id'}}
+}
+
+int fun(int arg) {
+#pragma omp declare mapper(id: vec v) map(v.len)
+ {
+#pragma omp declare mapper(id: vec v) map(v.len) // expected-note {{previous definition is here}}
+ {
+#pragma omp declare mapper(id: vec v) map(v.len)
+ }
+#pragma omp declare mapper(id: vec v) map(v.len) // expected-error {{redefinition of user-defined mapper for type 'vec' with name 'id'}}
+ }
+ return arg;
+}