jacobdweightman created this revision.
jacobdweightman added a reviewer: ABataev.
jacobdweightman added a project: OpenMP.
Herald added subscribers: cfe-commits, guansong, yaxunl.
Herald added a project: clang.
jacobdweightman requested review of this revision.
Herald added a reviewer: jdoerfert.
Herald added a subscriber: sstefan1.

This patch aims to fully support this change from OpenMP 4.5 to 5.0:

> The to and from clauses on the target update construct (see Section 2.12.6 on 
> page 176), the depend clause on task generating constructs (see Section 
> 2.17.11 on page 255), and the map clause (see Section 2.19.7.1 on page 315) 
> were extended to allow any lvalue expression as a list item for C/C++.

Specifically, support is added for:

- calling functions which return references/constexprs
- cast expressions as part of a larger lvalue expression
- expressions with the ternary Elvis operators (A ? B : C and A ?: C)

This patch modifies Sema to accept such expressions. A few small changes in 
CodeGen were required to avoid asserts, but CodeGen appeared to already handle 
such expressions correctly.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D91373

Files:
  clang/lib/CodeGen/CGOpenMPRuntime.cpp
  clang/lib/Sema/SemaOpenMP.cpp
  clang/test/OpenMP/target_map_messages.cpp
  clang/test/OpenMP/target_parallel_for_map_messages.cpp
  clang/test/OpenMP/target_parallel_for_simd_map_messages.cpp
  clang/test/OpenMP/target_parallel_map_messages.cpp
  clang/test/OpenMP/target_simd_map_messages.cpp
  clang/test/OpenMP/target_teams_distribute_map_messages.cpp
  clang/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp
  clang/test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp
  clang/test/OpenMP/target_teams_distribute_simd_map_messages.cpp
  clang/test/OpenMP/target_teams_map_messages.cpp
  clang/test/OpenMP/target_update_from_messages.cpp
  clang/test/OpenMP/target_update_to_messages.cpp

Index: clang/test/OpenMP/target_update_to_messages.cpp
===================================================================
--- clang/test/OpenMP/target_update_to_messages.cpp
+++ clang/test/OpenMP/target_update_to_messages.cpp
@@ -1,12 +1,12 @@
-// RUN: %clang_cc1 -verify=expected,le50 -fopenmp -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,le45 -fopenmp -fopenmp-version=40 -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,le45 -fopenmp -fopenmp-version=45 -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,le50 -fopenmp -fopenmp-version=50 -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le50 -fopenmp -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le45 -fopenmp -fopenmp-version=40 -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le45 -fopenmp -fopenmp-version=45 -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le50 -fopenmp -fopenmp-version=50 -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
 
-// RUN: %clang_cc1 -verify=expected,le50 -fopenmp-simd -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,le45 -fopenmp-simd -fopenmp-version=40 -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,le45 -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,le50 -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le50 -fopenmp-simd -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le45 -fopenmp-simd -fopenmp-version=40 -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le45 -fopenmp-simd -fopenmp-version=45 -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le50 -fopenmp-simd -fopenmp-version=50 -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
 
 void foo() {
 }
@@ -15,6 +15,14 @@
   return argc;
 }
 
+int &id(int &x) {
+    return x;
+}
+
+int *id2(int *x) {
+    return x;
+}
+
 struct S1; // expected-note 2 {{declared here}}
 extern S1 a;
 class S2 {
@@ -83,6 +91,12 @@
     double marr[10][5][10];
 #pragma omp target update to(marr [0:1][2:4][1:2]) // le45-error {{array section does not specify contiguous storage}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
     {}
+
+#pragma omp target update to(id) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'to' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(id(this->a)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(id(id(this->a))) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(*id2(&(this->a))) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(id2(&(this->a))) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'to' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
   }
 };
 
@@ -120,7 +134,8 @@
 #pragma omp target update to(S2::S2sc)
 #pragma omp target update to(to)
 #pragma omp target update to(y x) // expected-error {{expected ',' or ')' in 'to' clause}}
-#pragma omp target update to(argc > 0 ? x : y) // le50-error 2 {{expected addressable lvalue in 'to' clause}} le45-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target update to(argc > 0 ? x : y) // le45-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target update to(x ?: y) // le45-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target update to(S1) // expected-error {{'S1' does not refer to a value}}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
 #pragma omp target update to(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}}
 #pragma omp target update to(ba)
@@ -147,6 +162,16 @@
   return 0;
 }
 
+class S9 {
+public:
+    virtual void foo() {}
+} s9;
+
+class S10: public S9 {
+    int a;
+    void foo() {}
+} s10;
+
 int main(int argc, char **argv) {
   const int d = 5;
   const int da[5] = { 0 };
@@ -175,7 +200,8 @@
 #pragma omp target update to(S2::S2sc)
 #pragma omp target update to(to)
 #pragma omp target update to(y x) // expected-error {{expected ',' or ')' in 'to' clause}}
-#pragma omp target update to(argc > 0 ? x : y) // le50-error {{expected addressable lvalue in 'to' clause}} le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(argc > 0 ? x : y) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(x ?: y) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
 #pragma omp target update to(S1) // expected-error {{'S1' does not refer to a value}}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
 #pragma omp target update to(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}}
 #pragma omp target update to(ba)
@@ -212,6 +238,23 @@
 #pragma omp target update to(*(m+(m))) // expected-error {{invalid operands to binary expression ('int *' and 'int *')}}
 #pragma omp target update to(*(1+y+y)) // expected-error {{indirection requires pointer operand ('int' invalid)}}
   {}
+
+#pragma omp target update to(id) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'to' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(id(x)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(id(id(x))) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(*id2(&x)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(id2(&x)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'to' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+
+#pragma omp target update to(reinterpret_cast<int*>(&s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'to' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(*reinterpret_cast<int*>(&s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(static_cast<S9>(s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'to' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(*static_cast<S9*>(&s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(*dynamic_cast<S9*>(&s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(const_cast<S10*>(&s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'to' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(*const_cast<S10*>(&s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to((S9) s10) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'to' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update to(*((S9*) &s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+
   return tmain<int, 3>(argc)+tmain<from, 4>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<int, 4>' requested here}}
 }
 
Index: clang/test/OpenMP/target_update_from_messages.cpp
===================================================================
--- clang/test/OpenMP/target_update_from_messages.cpp
+++ clang/test/OpenMP/target_update_from_messages.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 -verify=expected,le50 -fopenmp -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,le45 -fopenmp -fopenmp-version=40 -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,le45 -fopenmp -fopenmp-version=45 -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,le50 -fopenmp -fopenmp-version=50 -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le50 -fopenmp -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le45 -fopenmp -fopenmp-version=40 -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le45 -fopenmp -fopenmp-version=45 -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le50 -fopenmp -fopenmp-version=50 -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
 
-// RUN: %clang_cc1 -verify=expected,le50 -fopenmp-simd -ferror-limit 100 %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le50 -fopenmp-simd -ferror-limit 200 %s -Wno-openmp-mapping -Wuninitialized
 
 void foo() {
 }
@@ -12,6 +12,14 @@
   return argc;
 }
 
+int &id(int &x) {
+    return x;
+}
+
+int *id2(int *x) {
+    return x;
+}
+
 struct S1; // expected-note 2 {{declared here}}
 extern S1 a;
 class S2 {
@@ -75,6 +83,12 @@
 #pragma omp target update from(*(a+this->ptr)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
 #pragma omp target update from(*(*(this->ptr)+a+this->ptr)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
 #pragma omp target update from(*(this+this)) // expected-error {{invalid operands to binary expression ('S8 *' and 'S8 *')}}
+
+#pragma omp target update from(id) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'from' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(id(this->a)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(id(id(this->a))) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(*id2(&(this->a))) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(id2(&(this->a))) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'from' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
   }
 };
 
@@ -112,7 +126,8 @@
 #pragma omp target update from(S2::S2sc)
 #pragma omp target update from(from)
 #pragma omp target update from(y x) // expected-error {{expected ',' or ')' in 'from' clause}}
-#pragma omp target update from(argc > 0 ? x : y) // le50-error 2 {{expected addressable lvalue in 'from' clause}} le45-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target update from(argc > 0 ? x : y) // le45-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target update from(x ?: y) // le45-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 
 #pragma omp target update from(S1) // expected-error {{'S1' does not refer to a value}}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
 #pragma omp target update from(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}}
@@ -141,6 +156,16 @@
   return 0;
 }
 
+class S9 {
+public:
+    virtual void foo() {}
+} s9;
+
+class S10: public S9 {
+    int a;
+    void foo() {}
+} s10;
+
 int main(int argc, char **argv) {
   const int d = 5;
   const int da[5] = { 0 };
@@ -169,7 +194,8 @@
 #pragma omp target update from(S2::S2sc)
 #pragma omp target update from(from)
 #pragma omp target update from(y x) // expected-error {{expected ',' or ')' in 'from' clause}}
-#pragma omp target update from(argc > 0 ? x : y) // le50-error {{expected addressable lvalue in 'from' clause}} le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(argc > 0 ? x : y) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(x ?: y) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
 #pragma omp target update from(S1) // expected-error {{'S1' does not refer to a value}}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
 #pragma omp target update from(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}}
 #pragma omp target update from(ba)
@@ -204,6 +230,21 @@
   {
 #pragma omp target update from(s7.x)
   }
+#pragma omp target update from(id) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'from' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(id(x)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(id(id(x))) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(*id2(&x)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(id2(&x)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'from' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+
+#pragma omp target update from(reinterpret_cast<int*>(&s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'from' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(*reinterpret_cast<int*>(&s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(static_cast<S9>(s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'from' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(*static_cast<S9*>(&s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(*dynamic_cast<S9*>(&s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(const_cast<S10*>(&s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'from' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(*const_cast<S10*>(&s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from((S9) s10) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} le50-error {{expected addressable lvalue in 'from' clause}} le50-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(*((S9*) &s10)) // le45-error {{expected expression containing only member accesses and/or array sections based on named variables}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
 
   return tmain<int, 3>(argc)+tmain<to, 4>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<int, 4>' requested here}}
 }
Index: clang/test/OpenMP/target_teams_map_messages.cpp
===================================================================
--- clang/test/OpenMP/target_teams_map_messages.cpp
+++ clang/test/OpenMP/target_teams_map_messages.cpp
@@ -30,6 +30,14 @@
     ;
 }
 
+int &id(int &x) {
+    return x;
+}
+
+int *id2(int *x) {
+    return x;
+}
+
 template <typename T, int I>
 struct SA {
   static int ss;
@@ -56,6 +64,16 @@
     {}
     #pragma omp target teams map(arg,a,d[:2]) // expected-error {{subscripted value is not an array or pointer}}
     {}
+    #pragma omp target teams map(id) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+    {}
+    #pragma omp target teams map(id(b[3])) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+    {}
+    #pragma omp target teams map(id(id(b[3]))) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+    {}
+    #pragma omp target teams map(id2(&b[3])) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+    {}
+    #pragma omp target teams map(*id2(&b[3])) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+    {}
 
     #pragma omp target teams map(to:ss) // expected-error {{threadprivate variables are not allowed in 'map' clause}}
     {}
@@ -97,6 +115,9 @@
   float *foo() {
     return &Arr[0];
   }
+  float &bar() {
+      return Arr[0];
+  }
 };
 
 struct SC {
@@ -256,10 +277,17 @@
   {}
   #pragma omp target teams map(r.S.Arr[:12])
   {}
-  // ge50-error@+2 {{expected addressable lvalue in 'map' clause}}
+  #pragma omp target teams map(r.S.foo) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+  {}
+  #pragma omp target teams map(r.S.foo()) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+  {}
+  #pragma omp target teams map(*(r.S.foo())) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
   // lt50-error@+1 {{expected expression containing only member accesses and/or array sections based on named variables}}
   #pragma omp target teams map(r.S.foo()[:12])
   {}
+  #pragma omp target teams map(r.S.bar()) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
   #pragma omp target teams map(r.C, r.D)
   {}
   #pragma omp target teams map(r.C, r.C) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}}
@@ -381,6 +409,16 @@
    virtual void foo();
 };
 
+class S9 {
+public:
+  virtual void foo() {}
+} s9;
+
+class S10: public S9 {
+    int a;
+    void foo() {};
+} s10;
+
 S3 h;
 #pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
 
@@ -443,9 +481,10 @@
   foo();
 
 #pragma omp target data map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
-// ge50-error@+2 2 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+1 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target data map(tofrom: argc > 0 ? x : y)
+// lt50-error@+1 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target data map(tofrom: x ?: y)
 
 #pragma omp target data map(argc)
 #pragma omp target data map(S1) // expected-error {{'S1' does not refer to a value}}
@@ -526,9 +565,10 @@
   foo();
 
 #pragma omp target data map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
-// ge50-error@+2 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+1 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target data map(tofrom: argc > 0 ? argv[1] : argv[2])
+// lt50-error@+1 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target data map(tofrom: argv[1] ?: argv[2])
 #pragma omp target data map(argc)
 #pragma omp target data map(S1) // expected-error {{'S1' does not refer to a value}}
 #pragma omp target data map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}}
@@ -613,6 +653,24 @@
   {}
 #pragma omp target teams map(*(1+*a+*a)) // expected-error {{indirection requires pointer operand ('int' invalid)}}
   {}
+#pragma omp target teams map(reinterpret_cast<int*>(&s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+  {}
+#pragma omp target teams map(*reinterpret_cast<int*>(&s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
+#pragma omp target teams map(static_cast<S9>(s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+  {}
+#pragma omp target teams map(*static_cast<S9*>(&s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
+#pragma omp target teams map(*dynamic_cast<S9*>(&s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
+#pragma omp target teams map(const_cast<S10*>(&s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+  {}
+#pragma omp target teams map(*const_cast<S10*>(&s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
+#pragma omp target teams map((S9) s10) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+  {}
+#pragma omp target teams map(*((S9*) &s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
 
 #pragma omp target teams map(delete: j) // expected-error {{map type 'delete' is not allowed for '#pragma omp target teams'}}
   {}
Index: clang/test/OpenMP/target_teams_distribute_simd_map_messages.cpp
===================================================================
--- clang/test/OpenMP/target_teams_distribute_simd_map_messages.cpp
+++ clang/test/OpenMP/target_teams_distribute_simd_map_messages.cpp
@@ -127,11 +127,14 @@
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute simd map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i) foo();
-// ge50-error@+3 2 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target teams distribute simd map(tofrom \
                                              : argc > 0 ? x : y)
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target teams distribute simd map(tofrom \
+                                             : x ?: y)
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute simd map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute simd map(S1) // expected-error {{'S1' does not refer to a value}}
@@ -242,11 +245,14 @@
 #pragma omp target teams distribute simd map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i)
     foo();
-// ge50-error@+3 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target teams distribute simd map(tofrom \
                                              : argc > 0 ? argv[1] : argv[2])
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target teams distribute simd map(tofrom \
+                                             : argv[1] ?: argv[2])
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute simd map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute simd map(S1) // expected-error {{'S1' does not refer to a value}}
Index: clang/test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp
===================================================================
--- clang/test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp
+++ clang/test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp
@@ -127,11 +127,14 @@
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute parallel for simd map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i) foo();
-// ge50-error@+3 2 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target teams distribute parallel for simd map(tofrom \
                                                           : argc > 0 ? x : y)
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target teams distribute parallel for simd map(tofrom \
+                                                          : x ?: y)
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute parallel for simd map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute parallel for simd map(S1) // expected-error {{'S1' does not refer to a value}}
@@ -241,11 +244,14 @@
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute parallel for simd map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i) foo();
-// ge50-error@+3 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target teams distribute parallel for simd map(tofrom \
                                                           : argc > 0 ? argv[1] : argv[2])
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target teams distribute parallel for simd map(tofrom \
+                                                          : argv[1] ?: argv[2])
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute parallel for simd map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute parallel for simd map(S1) // expected-error {{'S1' does not refer to a value}}
Index: clang/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp
===================================================================
--- clang/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp
+++ clang/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp
@@ -125,11 +125,14 @@
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute parallel for map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i) foo();
-// ge50-error@+3 2 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target teams distribute parallel for map(tofrom \
                                                      : argc > 0 ? x : y)
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target teams distribute parallel for map(tofrom \
+                                                     : x ?: y)
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute parallel for map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute parallel for map(S1) // expected-error {{'S1' does not refer to a value}}
@@ -239,11 +242,14 @@
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute parallel for map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i) foo();
-// ge50-error@+3 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target teams distribute parallel for map(tofrom \
                                                      : argc > 0 ? argv[1] : argv[2])
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target teams distribute parallel for map(tofrom \
+                                                     : argv[1] ?: argv[2])
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute parallel for map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute parallel for map(S1) // expected-error {{'S1' does not refer to a value}}
Index: clang/test/OpenMP/target_teams_distribute_map_messages.cpp
===================================================================
--- clang/test/OpenMP/target_teams_distribute_map_messages.cpp
+++ clang/test/OpenMP/target_teams_distribute_map_messages.cpp
@@ -127,11 +127,14 @@
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i) foo();
-// ge50-error@+3 2 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target teams distribute map(tofrom \
                                         : argc > 0 ? x : y)
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target teams distribute map(tofrom \
+                                        : x ?: y)
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute map(S1) // expected-error {{'S1' does not refer to a value}}
@@ -242,11 +245,14 @@
 #pragma omp target teams distribute map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i)
     foo();
-// ge50-error@+3 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target teams distribute map(tofrom \
                                         : argc > 0 ? argv[1] : argv[2])
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target teams distribute map(tofrom \
+                                        : argv[1] ?: argv[2])
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target teams distribute map(S1) // expected-error {{'S1' does not refer to a value}}
Index: clang/test/OpenMP/target_simd_map_messages.cpp
===================================================================
--- clang/test/OpenMP/target_simd_map_messages.cpp
+++ clang/test/OpenMP/target_simd_map_messages.cpp
@@ -121,11 +121,14 @@
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target simd map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i) foo();
-// ge50-error@+3 2 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target simd map(tofrom \
                             : argc > 0 ? x : y)
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target simd map(tofrom \
+                            : x ?: y)
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target simd map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target simd map(S1) // expected-error {{'S1' does not refer to a value}}
@@ -230,11 +233,14 @@
 #pragma omp target simd map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i)
     foo();
-// ge50-error@+3 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target simd map(tofrom \
                             : argc > 0 ? argv[1] : argv[2])
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target simd map(tofrom \
+                            : argv[1] ?: argv[2])
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target simd map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target simd map(S1) // expected-error {{'S1' does not refer to a value}}
Index: clang/test/OpenMP/target_parallel_map_messages.cpp
===================================================================
--- clang/test/OpenMP/target_parallel_map_messages.cpp
+++ clang/test/OpenMP/target_parallel_map_messages.cpp
@@ -127,11 +127,14 @@
   foo();
 #pragma omp target parallel map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   foo();
-// ge50-error@+3 2 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target parallel map(tofrom \
                                 : argc > 0 ? x : y)
   foo();
+// lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target parallel map(tofrom \
+                                : x ?: y)
+  foo();
 #pragma omp target parallel map(argc)
   foo();
 #pragma omp target parallel map(S1) // expected-error {{'S1' does not refer to a value}}
@@ -240,11 +243,14 @@
   foo();
 #pragma omp target parallel map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   foo();
-// ge50-error@+3 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target parallel map(tofrom \
                                 : argc > 0 ? argv[1] : argv[2])
   foo();
+// lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target parallel map(tofrom \
+                                : argv[1] ?: argv[2])
+  foo();
 #pragma omp target parallel map(argc)
   foo();
 #pragma omp target parallel map(S1) // expected-error {{'S1' does not refer to a value}}
Index: clang/test/OpenMP/target_parallel_for_simd_map_messages.cpp
===================================================================
--- clang/test/OpenMP/target_parallel_for_simd_map_messages.cpp
+++ clang/test/OpenMP/target_parallel_for_simd_map_messages.cpp
@@ -127,11 +127,14 @@
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target parallel for simd map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i) foo();
-// ge50-error@+3 2 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target parallel for simd map(tofrom \
                                          : argc > 0 ? x : y)
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target parallel for simd map(tofrom \
+                                         : x ?: y)
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target parallel for simd map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target parallel for simd map(S1) // expected-error {{'S1' does not refer to a value}}
@@ -242,11 +245,14 @@
 #pragma omp target parallel for simd map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i)
     foo();
-// ge50-error@+3 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target parallel for simd map(tofrom \
                                          : argc > 0 ? argv[1] : argv[2])
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target parallel for simd map(tofrom \
+                                         : argv[1] ?: argv[2])
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target parallel for simd map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target parallel for simd map(S1) // expected-error {{'S1' does not refer to a value}}
Index: clang/test/OpenMP/target_parallel_for_map_messages.cpp
===================================================================
--- clang/test/OpenMP/target_parallel_for_map_messages.cpp
+++ clang/test/OpenMP/target_parallel_for_map_messages.cpp
@@ -127,11 +127,14 @@
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target parallel for map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i) foo();
-// ge50-error@+3 2 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target parallel for map(tofrom \
                                     : argc > 0 ? x : y)
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target parallel for map(tofrom \
+                                    : x ?: y)
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target parallel for map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target parallel for map(S1) // expected-error {{'S1' does not refer to a value}}
@@ -242,11 +245,14 @@
 #pragma omp target parallel for map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
   for (i = 0; i < argc; ++i)
     foo();
-// ge50-error@+3 {{expected addressable lvalue in 'map' clause}}
 // lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target parallel for map(tofrom \
                                     : argc > 0 ? argv[1] : argv[2])
   for (i = 0; i < argc; ++i) foo();
+// lt50-error@+2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target parallel for map(tofrom \
+                                    : argv[1] ?: argv[2])
+  for (i = 0; i < argc; ++i) foo();
 #pragma omp target parallel for map(argc)
   for (i = 0; i < argc; ++i) foo();
 #pragma omp target parallel for map(S1) // expected-error {{'S1' does not refer to a value}}
Index: clang/test/OpenMP/target_map_messages.cpp
===================================================================
--- clang/test/OpenMP/target_map_messages.cpp
+++ clang/test/OpenMP/target_map_messages.cpp
@@ -1,16 +1,16 @@
-// RUN: %clang_cc1 -verify=expected,ge50,lt51 -fopenmp -ferror-limit 200 %s -Wno-openmp-target -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,lt50,lt51 -fopenmp -fopenmp-version=40 -ferror-limit 200 %s -Wno-openmp-target -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,lt50,lt51 -fopenmp -fopenmp-version=45 -ferror-limit 200 %s -Wno-openmp-target -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,ge50,lt51 -fopenmp -fopenmp-version=50 -ferror-limit 200 %s -Wno-openmp-target -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,ge50,ge51 -fopenmp -fopenmp-version=51 -ferror-limit 200 %s -Wno-openmp-target -Wuninitialized
-// RUN: %clang_cc1 -DCCODE -verify -fopenmp -ferror-limit 200 -x c %s -Wno-openmp -Wuninitialized
-
-// RUN: %clang_cc1 -verify=expected,ge50,lt51 -fopenmp-simd -ferror-limit 200 %s -Wno-openmp-target -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,lt50,lt51 -fopenmp-simd -fopenmp-version=40 -ferror-limit 200 %s -Wno-openmp-target -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,lt50,lt51 -fopenmp-simd -fopenmp-version=45 -ferror-limit 200 %s -Wno-openmp-target -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,ge50,lt51 -fopenmp-simd -fopenmp-version=50 -ferror-limit 200 %s -Wno-openmp-target -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,ge50,ge51 -fopenmp-simd -fopenmp-version=51 -ferror-limit 200 %s -Wno-openmp-target -Wuninitialized
-// RUN: %clang_cc1 -DCCODE -verify -fopenmp-simd -ferror-limit 200 -x c %s -Wno-openmp-mapping -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,ge50,lt51 -fopenmp -ferror-limit 400 %s -Wno-openmp-target -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,lt50,lt51 -fopenmp -fopenmp-version=40 -ferror-limit 400 %s -Wno-openmp-target -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,lt50,lt51 -fopenmp -fopenmp-version=45 -ferror-limit 400 %s -Wno-openmp-target -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,ge50,lt51 -fopenmp -fopenmp-version=50 -ferror-limit 400 %s -Wno-openmp-target -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,ge50,ge51 -fopenmp -fopenmp-version=51 -ferror-limit 400 %s -Wno-openmp-target -Wuninitialized
+// RUN: %clang_cc1 -DCCODE -verify -fopenmp -ferror-limit 400 -x c %s -Wno-openmp -Wuninitialized
+
+// RUN: %clang_cc1 -verify=expected,ge50,lt51 -fopenmp-simd -ferror-limit 400 %s -Wno-openmp-target -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,lt50,lt51 -fopenmp-simd -fopenmp-version=40 -ferror-limit 400 %s -Wno-openmp-target -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,lt50,lt51 -fopenmp-simd -fopenmp-version=45 -ferror-limit 400 %s -Wno-openmp-target -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,ge50,lt51 -fopenmp-simd -fopenmp-version=50 -ferror-limit 400 %s -Wno-openmp-target -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,ge50,ge51 -fopenmp-simd -fopenmp-version=51 -ferror-limit 400 %s -Wno-openmp-target -Wuninitialized
+// RUN: %clang_cc1 -DCCODE -verify -fopenmp-simd -ferror-limit 400 -x c %s -Wno-openmp-mapping -Wuninitialized
 #ifdef CCODE
 void foo(int arg) {
   const int n = 0;
@@ -42,6 +42,14 @@
   SREF(int &a) : a(a) {}
 };
 
+int &id(int &x) {
+    return x;
+}
+
+int *id2(int *x) {
+    return x;
+}
+
 template <typename T, int I>
 struct SA {
   static int ss;
@@ -73,6 +81,16 @@
     {}
     #pragma omp target map(arg,a,d[:2]) // expected-error {{subscripted value is not an array or pointer}}
     {}
+    #pragma omp target map(id) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+    {}
+    #pragma omp target map(id(b[3])) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+    {}
+    #pragma omp target map(id(id(b[3]))) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+    {}
+    #pragma omp target map(id2(&b[3])) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+    {}
+    #pragma omp target map(*id2(&b[3])) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+    {}
 
     #pragma omp target map(to:ss) // expected-error {{threadprivate variables are not allowed in 'map' clause}}
     {}
@@ -197,6 +215,9 @@
   float *foo() {
     return &Arr[0];
   }
+  float &bar() {
+      return Arr[0];
+  }
 };
 
 struct SC {
@@ -356,7 +377,13 @@
   {}
 #pragma omp target map(r.S.Arr[:12])
   {}
-#pragma omp target map(r.S.foo() [:12]) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+#pragma omp target map(r.S.foo) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+  {}
+#pragma omp target map(r.S.foo()) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+  {}
+#pragma omp target map(r.S.foo() [:12]) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
+#pragma omp target map(r.S.bar()) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
   {}
 #pragma omp target map(r.C, r.D)
   {}
@@ -570,7 +597,8 @@
 #pragma omp target map(to, x)
   foo();
 #pragma omp target data map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
-#pragma omp target data map(tofrom: argc > 0 ? x : y) // lt50-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error 2 {{expected addressable lvalue in 'map' clause}}
+#pragma omp target data map(tofrom: argc > 0 ? x : y) // lt50-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target data map(tofrom: x ?: y) // lt50-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target data map(argc)
 #pragma omp target data map(S1) // expected-error {{'S1' does not refer to a value}}
 #pragma omp target data map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} warn-warning 2 {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} warn-warning 2 {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}}
@@ -668,6 +696,12 @@
   virtual void foo() {}
 } s9;
 
+class S10: public S9 {
+public:
+  int a;
+  void foo() {}
+} s10;
+
 
 int main(int argc, char **argv) {
   const int d = 5;
@@ -704,7 +738,8 @@
 #pragma omp target map(to, x)
   foo();
 #pragma omp target data map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
-#pragma omp target data map(tofrom: argc > 0 ? argv[1] : argv[2]) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+#pragma omp target data map(tofrom: argc > 0 ? argv[1] : argv[2]) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target data map(tofrom: argv[1] ?: argv[2]) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
 #pragma omp target data map(argc)
 #pragma omp target data map(S1) // expected-error {{'S1' does not refer to a value}}
 #pragma omp target data map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} warn-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} warn-warning {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}}
@@ -835,6 +870,24 @@
   {}
 #pragma omp target map(*(1+*a+*a)) // expected-error {{indirection requires pointer operand ('int' invalid)}}
   {}
+#pragma omp target map(reinterpret_cast<int*>(&s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+  {}
+#pragma omp target map(*reinterpret_cast<int*>(&s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
+#pragma omp target map(static_cast<S9>(s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+  {}
+#pragma omp target map(*static_cast<S9*>(&s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
+#pragma omp target map(*dynamic_cast<S9*>(&s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
+#pragma omp target map(const_cast<S10*>(&s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+  {}
+#pragma omp target map(*const_cast<S10*>(&s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
+#pragma omp target map((S9) s10) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}}
+  {}
+#pragma omp target map(*((S9*) &s10)) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+  {}
 
 #pragma omp target map(delete: a) // expected-error {{map type 'delete' is not allowed for '#pragma omp target'}}
   {}
Index: clang/lib/Sema/SemaOpenMP.cpp
===================================================================
--- clang/lib/Sema/SemaOpenMP.cpp
+++ clang/lib/Sema/SemaOpenMP.cpp
@@ -16834,7 +16834,12 @@
 
 public:
   bool VisitDeclRefExpr(DeclRefExpr *DRE) {
-    if (!isa<VarDecl>(DRE->getDecl())) {
+    // Allow variables, and also allow functions if they are part of a call
+    // expression. However, we must not map functions themselves. This is
+    // prevented since a call expression will always be added to Components
+    // first.
+    if (!isa<VarDecl>(DRE->getDecl()) &&
+        (Components.empty() || !isa<FunctionDecl>(DRE->getDecl()))) {
       emitErrorMsg();
       return false;
     }
@@ -16857,6 +16862,13 @@
       E = BaseE;
     }
 
+    // Allow results of method calls to be mapped.
+    if (isa<CXXMethodDecl>(ME->getMemberDecl())) {
+      RelevantExpr = ME;
+      Components.emplace_back(ME, ME->getMemberDecl(), IsNonContiguous);
+      return true;
+    }
+
     if (!isa<FieldDecl>(ME->getMemberDecl())) {
       if (!NoDiagnose) {
         SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
@@ -16917,6 +16929,13 @@
     return RelevantExpr || Visit(E);
   }
 
+  bool VisitOpaqueValueExpr(OpaqueValueExpr *OVE) {
+    // An OpaqueValue expression may be encountered e.g. in the operands of a
+    // binary conditional ("Elvis") operator. For now, it is sufficient to
+    // forward to the source expression.
+    return Visit(OVE->getSourceExpr()->IgnoreParenImpCasts());
+  }
+
   bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
     Expr *E = AE->getBase()->IgnoreParenImpCasts();
 
@@ -17047,8 +17066,9 @@
   }
 
   bool VisitUnaryOperator(UnaryOperator *UO) {
-    if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
-        UO->getOpcode() != UO_Deref) {
+    if (SemaRef.getLangOpts().OpenMP < 50 ||
+        (Components.empty() &&
+         (!UO->isLValue() || UO->getOpcode() != UO_Deref))) {
       emitErrorMsg();
       return false;
     }
@@ -17089,6 +17109,37 @@
     Components.emplace_back(COCE, nullptr, IsNonContiguous);
     return true;
   }
+  bool VisitCallExpr(CallExpr *CE) {
+    if (SemaRef.getLangOpts().OpenMP < 50 ||
+        (Components.empty() && !CE->isLValue())) {
+      emitErrorMsg();
+      return false;
+    }
+    assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
+    Components.emplace_back(CE, nullptr, IsNonContiguous);
+    return RelevantExpr || Visit(CE->getCallee()->IgnoreParenImpCasts());
+  }
+  bool VisitCastExpr(CastExpr *CE) {
+    if (SemaRef.getLangOpts().OpenMP < 50 ||
+        (Components.empty() && !CE->isLValue())) {
+      emitErrorMsg();
+      return false;
+    }
+    assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
+    Components.emplace_back(CE, nullptr, false);
+    return RelevantExpr || Visit(CE->getSubExpr()->IgnoreParenImpCasts());
+  }
+  bool VisitAbstractConditionalOperator(AbstractConditionalOperator *ACO) {
+    if (SemaRef.getLangOpts().OpenMP < 50) {
+      emitErrorMsg();
+      return false;
+    }
+    assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
+    Components.emplace_back(ACO, nullptr, false);
+    return RelevantExpr ||
+           Visit(ACO->getTrueExpr()->IgnoreParenImpCasts()) ||
+           Visit(ACO->getFalseExpr()->IgnoreParenImpCasts());
+  }
   bool VisitStmt(Stmt *) {
     emitErrorMsg();
     return false;
@@ -17265,7 +17316,7 @@
         }
 
         QualType DerivedType =
-            std::prev(CI)->getAssociatedDeclaration()->getType();
+            std::prev(CI)->getAssociatedExpression()->getType();
         SourceLocation DerivedLoc =
             std::prev(CI)->getAssociatedExpression()->getExprLoc();
 
@@ -17274,6 +17325,20 @@
         //  will be considered to be T for all purposes of this clause.
         DerivedType = DerivedType.getNonReferenceType();
 
+        // There are restrictions on when arrays and structs may be mapped which
+        // are checked in this function. It is difficult to check these
+        // conditions at compile time for a general lvalue (e.g. for a ternary),
+        // so instead we whitelist the kind of expressions we would like to
+        // perform these checks on.
+        const Expr *nextComponentExpr = (CI == CE)
+                                            ? SI->getAssociatedExpression()
+                                            : CI->getAssociatedExpression();
+        const bool shouldCheckForOverlap =
+            isa<ArraySubscriptExpr>(nextComponentExpr) ||
+            isa<OMPArraySectionExpr>(nextComponentExpr) ||
+            isa<OMPArrayShapingExpr>(nextComponentExpr) ||
+            isa<MemberExpr>(nextComponentExpr);
+
         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
         //  A variable for which the type is pointer and an array section
         //  derived from that variable must not appear as list items of map
@@ -17285,7 +17350,7 @@
         //  storage in the device data environment, all of the original storage
         //  must have corresponding storage in the device data environment.
         //
-        if (DerivedType->isAnyPointerType()) {
+        if (shouldCheckForOverlap && DerivedType->isAnyPointerType()) {
           if (CI == CE || SI == SE) {
             SemaRef.Diag(
                 DerivedLoc,
@@ -17313,7 +17378,8 @@
         //  original storage.
         //
         // An expression is a subset of the other.
-        if (CurrentRegionOnly && (CI == CE || SI == SE)) {
+        if (shouldCheckForOverlap && CurrentRegionOnly &&
+            (CI == CE || SI == SE)) {
           if (CKind == OMPC_map) {
             if (CI != CE || SI != SE) {
               // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
@@ -17348,7 +17414,7 @@
 
         // The current expression uses the same base as other expression in the
         // data environment but does not contain it completely.
-        if (!CurrentRegionOnly && SI != SE)
+        if (shouldCheckForOverlap && !CurrentRegionOnly && SI != SE)
           EnclosingExpr = RE;
 
         // The current expression is a subset of the expression in the data
@@ -17650,8 +17716,10 @@
 
     auto *VD = dyn_cast<VarDecl>(CurDeclaration);
     const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
+    const auto *FnD = dyn_cast<FunctionDecl>(CurDeclaration);
 
-    assert((VD || FD) && "Only variables or fields are expected here!");
+    assert((VD || FD || FnD) &&
+           "Only variables, fields, or functions are expected here!");
     (void)FD;
 
     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
Index: clang/lib/CodeGen/CGOpenMPRuntime.cpp
===================================================================
--- clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7672,15 +7672,19 @@
           dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
       const auto *OAShE =
           dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
-      const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
-      const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
       bool IsPointer =
           OAShE ||
           (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
                        .getCanonicalType()
                        ->isAnyPointerType()) ||
           I->getAssociatedExpression()->getType()->isAnyPointerType();
-      bool IsNonDerefPointer = IsPointer && !UO && !BO && !IsNonContiguous;
+      bool IsNonDerefPointer =
+          IsPointer &&
+          !isa<UnaryOperator>(I->getAssociatedExpression()) &&
+          !isa<BinaryOperator>(I->getAssociatedExpression()) &&
+          !isa<CastExpr>(I->getAssociatedExpression()) &&
+          !isa<AbstractConditionalOperator>(I->getAssociatedExpression()) &&
+          !IsNonContiguous;
 
       if (OASE)
         ++DimSize;
@@ -7694,7 +7698,9 @@
                 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) ||
                 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) ||
                 isa<UnaryOperator>(Next->getAssociatedExpression()) ||
-                isa<BinaryOperator>(Next->getAssociatedExpression())) &&
+                isa<BinaryOperator>(Next->getAssociatedExpression()) ||
+                isa<AbstractConditionalOperator>(
+                    Next->getAssociatedExpression())) &&
                "Unexpected expression");
 
         Address LB = Address::invalid();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to