[OpenMP] Parse+Sema for '#pragma omp declare target' syntax version 4.5

Support OpenMP version 4.5 syntax for #pragma omp declare target.

Syntax:
  #pragma omp declare target (extended-list) new-line
or
  #pragma omp declare target clause[ [,] clause ... ] new-line

Where clause is one of the following:
  to(extended-list)
  link(list)

Differential Revision: http://reviews.llvm.org/D20011

llvm-svn: 268925
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index cbcf70b..ea26f6a 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -1101,6 +1101,23 @@
     return false;
   }
 };
+
+class VarOrFuncDeclFilterCCC : public CorrectionCandidateCallback {
+private:
+  Sema &SemaRef;
+
+public:
+  explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
+  bool ValidateCandidate(const TypoCorrection &Candidate) override {
+    NamedDecl *ND = Candidate.getCorrectionDecl();
+    if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) {
+      return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
+                                   SemaRef.getCurScope());
+    }
+    return false;
+  }
+};
+
 } // namespace
 
 ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
@@ -10752,6 +10769,52 @@
   IsInOpenMPDeclareTargetContext = false;
 }
 
+void
+Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec,
+                                   const DeclarationNameInfo &Id,
+                                   OMPDeclareTargetDeclAttr::MapTypeTy MT,
+                                   NamedDeclSetType &SameDirectiveDecls) {
+  LookupResult Lookup(*this, Id, LookupOrdinaryName);
+  LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
+
+  if (Lookup.isAmbiguous())
+    return;
+  Lookup.suppressDiagnostics();
+
+  if (!Lookup.isSingleResult()) {
+    if (TypoCorrection Corrected =
+            CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr,
+                        llvm::make_unique<VarOrFuncDeclFilterCCC>(*this),
+                        CTK_ErrorRecovery)) {
+      diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
+                                  << Id.getName());
+      checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
+      return;
+    }
+
+    Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
+    return;
+  }
+
+  NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
+  if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) {
+    if (!SameDirectiveDecls.insert(cast<NamedDecl>(ND->getCanonicalDecl())))
+      Diag(Id.getLoc(), diag::err_omp_declare_target_multiple) << Id.getName();
+
+    if (!ND->hasAttr<OMPDeclareTargetDeclAttr>()) {
+      Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT);
+      ND->addAttr(A);
+      if (ASTMutationListener *ML = Context.getASTMutationListener())
+        ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
+      checkDeclIsAllowedInOpenMPTarget(nullptr, ND);
+    } else if (ND->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() != MT) {
+      Diag(Id.getLoc(), diag::err_omp_declare_target_to_and_link)
+          << Id.getName();
+    }
+  } else
+    Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
+}
+
 static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
                                      Sema &SemaRef, Decl *D) {
   if (!D)
@@ -10765,9 +10828,11 @@
     // If this is an implicit variable that is legal and we do not need to do
     // anything.
     if (cast<VarDecl>(D)->isImplicit()) {
-      D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(SemaRef.Context));
+      Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+          SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
+      D->addAttr(A);
       if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
-        ML->DeclarationMarkedOpenMPDeclareTarget(D);
+        ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
       return;
     }
 
@@ -10780,9 +10845,11 @@
     // target region (it can be e.g. a lambda) that is legal and we do not need
     // to do anything else.
     if (LD == D) {
-      D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(SemaRef.Context));
+      Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+          SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
+      D->addAttr(A);
       if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
-        ML->DeclarationMarkedOpenMPDeclareTarget(D);
+        ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
       return;
     }
   }
@@ -10810,9 +10877,11 @@
       SemaRef.Diag(SL, diag::note_used_here) << SR;
     }
     // Mark decl as declared target to prevent further diagnostic.
-    D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(SemaRef.Context));
+    Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+        SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
+    D->addAttr(A);
     if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
-      ML->DeclarationMarkedOpenMPDeclareTarget(D);
+      ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
   }
 }
 
@@ -10846,9 +10915,11 @@
         !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD)) {
       // Mark decl as declared target to prevent further diagnostic.
       if (isa<VarDecl>(VD) || isa<FunctionDecl>(VD)) {
-        VD->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(Context));
+        Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+            Context, OMPDeclareTargetDeclAttr::MT_To);
+        VD->addAttr(A);
         if (ASTMutationListener *ML = Context.getASTMutationListener())
-          ML->DeclarationMarkedOpenMPDeclareTarget(VD);
+          ML->DeclarationMarkedOpenMPDeclareTarget(VD, A);
       }
       return;
     }
@@ -10857,9 +10928,11 @@
     // Checking declaration inside declare target region.
     if (!D->hasAttr<OMPDeclareTargetDeclAttr>() &&
         (isa<VarDecl>(D) || isa<FunctionDecl>(D))) {
-      D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(Context));
+      Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
+          Context, OMPDeclareTargetDeclAttr::MT_To);
+      D->addAttr(A);
       if (ASTMutationListener *ML = Context.getASTMutationListener())
-        ML->DeclarationMarkedOpenMPDeclareTarget(D);
+        ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
     }
     return;
   }