[OpenMP 5.0] Parsing/sema support for from clause with mapper modifier.

This patch implements the parsing and sema support for the OpenMP
'from'-clause with potential user-defined mappers attached.
User-defined mappers are a new feature in OpenMP 5.0. A 'from'-clause
can have an explicit or implicit associated mapper, which instructs the
compiler to generate and use customized mapping functions. An example is
shown below:

    struct S { int len; int *d; };
    #pragma omp declare mapper(id: struct S s) map(s, s.d[0:s.len])
    struct S ss;
    #pragma omp target update from(mapper(id): ss) // use the mapper with name 'id' to map ss from device

Contributed-by: Lingda Li <lildmh@gmail.com>

Differential Revision: https://reviews.llvm.org/D58638

llvm-svn: 354817
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 68843f0..782ad12 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -2161,13 +2161,20 @@
 
     if (Tok.is(tok::colon))
       Data.ColonLoc = ConsumeToken();
-  } else if (Kind == OMPC_to) {
+  } else if (Kind == OMPC_to || Kind == OMPC_from) {
     if (Tok.is(tok::identifier)) {
       bool IsMapperModifier = false;
-      auto Modifier = static_cast<OpenMPToModifierKind>(
-          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
-      if (Modifier == OMPC_TO_MODIFIER_mapper)
-        IsMapperModifier = true;
+      if (Kind == OMPC_to) {
+        auto Modifier = static_cast<OpenMPToModifierKind>(
+            getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
+        if (Modifier == OMPC_TO_MODIFIER_mapper)
+          IsMapperModifier = true;
+      } else {
+        auto Modifier = static_cast<OpenMPFromModifierKind>(
+            getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
+        if (Modifier == OMPC_FROM_MODIFIER_mapper)
+          IsMapperModifier = true;
+      }
       if (IsMapperModifier) {
         // Parse the mapper modifier.
         ConsumeToken();
@@ -2282,7 +2289,7 @@
 ///    to-clause:
 ///       'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
 ///    from-clause:
-///       'from' '(' list ')'
+///       'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
 ///    use_device_ptr-clause:
 ///       'use_device_ptr' '(' list ')'
 ///    is_device_ptr-clause: