[OPENMP50]Parsing/sema support for 'implementation/vendor' context
selector.

Added basic parsing/semantic support for
'implementation={vendor(<vendor>)}' context selector.

llvm-svn: 372917
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 570f246..46c8238 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -786,12 +786,72 @@
       LinModifiers, Steps, SourceRange(Loc, EndLoc));
 }
 
+/// Parse context selector for 'implementation' selector set:
+/// 'vendor' '(' <vendor> ')'
+static void
+parseImplementationSelector(Parser &P,
+                            Sema::OpenMPDeclareVariantCtsSelectorData &Data) {
+  const Token &Tok = P.getCurToken();
+  // Parse inner context selector set name, if any.
+  if (!Tok.is(tok::identifier)) {
+    P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
+        << "implementation";
+    // Skip until either '}', ')', or end of directive.
+    while (!P.SkipUntil(tok::r_brace, tok::r_paren,
+                        tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+      ;
+    return;
+  }
+  SmallString<16> Buffer;
+  StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
+  OMPDeclareVariantAttr::CtxSelectorType CSKind =
+      OMPDeclareVariantAttr::CtxUnknown;
+  (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorType(CtxSelectorName,
+                                                           CSKind);
+  (void)P.ConsumeToken();
+  switch (CSKind) {
+  case OMPDeclareVariantAttr::CtxVendor: {
+    // Parse '('.
+    BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
+    (void)T.expectAndConsume(diag::err_expected_lparen_after,
+                             CtxSelectorName.data());
+    // Parse <vendor>.
+    StringRef VendorName;
+    if (Tok.is(tok::identifier)) {
+      VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
+      (void)P.ConsumeToken();
+    } else {
+      P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected)
+          << "vendor identifier" << "vendor" << "implementation";
+    }
+    // Parse ')'.
+    (void)T.consumeClose();
+    if (!VendorName.empty())
+      Data.ImplVendor = VendorName;
+    break;
+  }
+  case OMPDeclareVariantAttr::CtxUnknown:
+    P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
+        << "implementation";
+    // Skip until either '}', ')', or end of directive.
+    while (!P.SkipUntil(tok::r_brace, tok::r_paren,
+                        tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+      ;
+    return;
+  }
+  Data.CtxSet = OMPDeclareVariantAttr::CtxSetImplementation;
+  Data.Ctx = CSKind;
+}
+
 /// Parses clauses for 'declare variant' directive.
 /// clause:
 /// <selector_set_name> '=' '{' <context_selectors> '}'
 /// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ]
 bool Parser::parseOpenMPContextSelectors(
-    SourceLocation Loc, llvm::function_ref<void(SourceRange)> Callback) {
+    SourceLocation Loc,
+    llvm::function_ref<void(SourceRange,
+                            const Sema::OpenMPDeclareVariantCtsSelectorData &)>
+        Callback) {
   do {
     // Parse inner context selector set name.
     if (!Tok.is(tok::identifier)) {
@@ -800,30 +860,43 @@
       return true;
     }
     SmallString<16> Buffer;
-    StringRef CtxSelectorName = PP.getSpelling(Tok, Buffer);
+    StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer);
     // Parse '='.
     (void)ConsumeToken();
     if (Tok.isNot(tok::equal)) {
       Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected)
-          << CtxSelectorName;
+          << CtxSelectorSetName;
       return true;
     }
     (void)ConsumeToken();
     // TBD: add parsing of known context selectors.
     // Unknown selector - just ignore it completely.
+    Sema::OpenMPDeclareVariantCtsSelectorData Data;
     {
       // Parse '{'.
       BalancedDelimiterTracker TBr(*this, tok::l_brace,
                                    tok::annot_pragma_openmp_end);
       if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "="))
         return true;
-      while (!SkipUntil(tok::r_brace, tok::r_paren,
-                        tok::annot_pragma_openmp_end, StopBeforeMatch))
-        ;
+      OMPDeclareVariantAttr::CtxSelectorSetType CSSKind =
+          OMPDeclareVariantAttr::CtxSetUnknown;
+      (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorSetType(
+          CtxSelectorSetName, CSSKind);
+      switch (CSSKind) {
+      case OMPDeclareVariantAttr::CtxSetImplementation:
+        parseImplementationSelector(*this, Data);
+        break;
+      case OMPDeclareVariantAttr::CtxSetUnknown:
+        // Skip until either '}', ')', or end of directive.
+        while (!SkipUntil(tok::r_brace, tok::r_paren,
+                          tok::annot_pragma_openmp_end, StopBeforeMatch))
+          ;
+        break;
+      }
       // Parse '}'.
       (void)TBr.consumeClose();
     }
-    Callback(SourceRange(Loc, Tok.getLocation()));
+    Callback(SourceRange(Loc, Tok.getLocation()), Data);
     // Consume ','
     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end))
       (void)ExpectAndConsume(tok::comma);
@@ -888,11 +961,15 @@
   }
 
   // Parse inner context selectors.
-  if (!parseOpenMPContextSelectors(Loc, [this, &DeclVarData](SourceRange SR) {
-        if (DeclVarData.hasValue())
-          Actions.ActOnOpenMPDeclareVariantDirective(
-              DeclVarData.getValue().first, DeclVarData.getValue().second, SR);
-      })) {
+  if (!parseOpenMPContextSelectors(
+          Loc, [this, &DeclVarData](
+                   SourceRange SR,
+                   const Sema::OpenMPDeclareVariantCtsSelectorData &Data) {
+            if (DeclVarData.hasValue())
+              Actions.ActOnOpenMPDeclareVariantDirective(
+                  DeclVarData.getValue().first, DeclVarData.getValue().second,
+                  SR, Data);
+          })) {
     // Parse ')'.
     (void)T.consumeClose();
     // Need to check for extra tokens.
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 34ce66c..0403f11 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -5101,11 +5101,14 @@
   return std::make_pair(FD, cast<Expr>(DRE));
 }
 
-void Sema::ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD,
-                                              Expr *VariantRef,
-                                              SourceRange SR) {
-  auto *NewAttr =
-      OMPDeclareVariantAttr::CreateImplicit(Context, VariantRef, SR);
+void Sema::ActOnOpenMPDeclareVariantDirective(
+    FunctionDecl *FD, Expr *VariantRef, SourceRange SR,
+    const Sema::OpenMPDeclareVariantCtsSelectorData &Data) {
+  if (Data.CtxSet == OMPDeclareVariantAttr::CtxSetUnknown ||
+      Data.Ctx == OMPDeclareVariantAttr::CtxUnknown)
+    return;
+  auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
+      Context, VariantRef, Data.CtxSet, Data.Ctx, Data.ImplVendor, SR);
   FD->addAttr(NewAttr);
 }
 
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 684254b..f6cf369 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -395,9 +395,11 @@
   if (!DeclVarData)
     return;
   // Instantiate the attribute.
+  Sema::OpenMPDeclareVariantCtsSelectorData Data(
+      Attr.getCtxSelectorSet(), Attr.getCtxSelector(), Attr.getImplVendor());
   S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first,
                                        DeclVarData.getValue().second,
-                                       Attr.getRange());
+                                       Attr.getRange(), Data);
 }
 
 static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr(