diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -6703,6 +6703,9 @@
                              llvm::omp::VariantMatchInfo &VMI,
                              bool DeviceSetOnly) const;
 
+  /// Return a string representation identifying this context selector.
+  std::string getMangledName() const;
+
   /// Print a human readable representation into \p OS.
   void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
 };
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1248,6 +1248,9 @@
   "unexpected '%0' clause, '%1' is specified already">;
 def err_expected_end_declare_target_or_variant : Error<
   "expected '#pragma omp end declare %select{target|variant}0'">;
+def err_expected_begin_declare_variant
+    : Error<"expected '#pragma omp begin declare variant' to match this stray "
+            "`#pragma omp end delcare variant`">;
 def err_omp_declare_target_unexpected_clause: Error<
   "unexpected '%0' clause, only %select{'to' or 'link'|'to', 'link' or 'device_type'}1 clauses expected">;
 def err_omp_expected_clause: Error<
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10110,6 +10110,12 @@
   "'flush' directive with memory order clause '%0' cannot have the list">;
 def note_omp_flush_order_clause_here : Note<
   "memory order clause '%0' is specified here">;
+
+def warn_nested_declare_variant
+    : Warning<"nesting `omp begin/end declare variant` is not supported yet; "
+              "nested context ignored">,
+      InGroup<SourceUsesOpenMP>;
+
 } // end of OpenMP category
 
 let CategoryName = "Related Result Type Issue" in {
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9708,14 +9708,54 @@
                                      MapT &Map, unsigned Selector = 0,
                                      SourceRange SrcRange = SourceRange());
 
-  /// Marks all the functions that might be required for the currently active
-  /// OpenMP context.
-  void markOpenMPDeclareVariantFuncsReferenced(SourceLocation Loc,
-                                               FunctionDecl *Func,
-                                               bool MightBeOdrUse);
+  /// Helper to keep information about the current `omp begin/end declare
+  /// variant` nesting.
+  struct OMPDeclareVariantScope {
+    /// The associated OpenMP context selector.
+    OMPTraitInfo TI;
+
+    /// The associated OpenMP context selector mangling.
+    std::string NameSuffix;
+
+    OMPDeclareVariantScope(const OMPTraitInfo &TI)
+        : TI(TI), NameSuffix(TI.getMangledName()) {}
+  };
+
+  /// The current `omp begin/end declare variant` scopes.
+  SmallVector<OMPDeclareVariantScope, 4> OMPDeclareVariantScopes;
+
+  /// The declarator \p D defines a function in the socpe \p S which is nested
+  /// in an `omp begin/end declare variant` scope. In this method we create a
+  /// declaration for \p D and rename \p D according to the OpenMP context
+  /// selector of the surrounding scope.
+  FunctionDecl *
+  ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D);
+
+  /// Register \p FD as specialization of \p BaseFD in the current `omp
+  /// begin/end declare variant` scope.
+  void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
+      FunctionDecl *FD, FunctionDecl *BaseFD);
 
 public:
-  /// Struct to store the context selectors info for declare variant directive.
+
+  /// Can we exit a scope at the moment.
+  bool isInOpenMPDeclareVariantScope() {
+    return !OMPDeclareVariantScopes.empty();
+  }
+
+  /// Given the potential call expression \p Call, determine if there is a
+  /// specialization via the OpenMP declare variant mechanism available. If
+  /// there is, return the specialized call expression, otherwise return the
+  /// original \p Call.
+  ExprResult ActOnOpenMPCall(Sema &S, ExprResult Call, Scope *Scope,
+                             SourceLocation LParenLoc, MultiExprArg ArgExprs,
+                             SourceLocation RParenLoc, Expr *ExecConfig);
+
+  /// Handle a `omp begin declare variant`.
+  void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI);
+
+  /// Handle a `omp end declare variant`.
+  void ActOnOpenMPEndDeclareVariant();
 
   /// Checks if the variant/multiversion functions are compatible.
   bool areMultiversionVariantFunctionsCompatible(
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -1823,6 +1823,36 @@
   }
 }
 
+std::string OMPTraitInfo::getMangledName() const {
+  std::string MangledName;
+  llvm::raw_string_ostream OS(MangledName);
+  for (const OMPTraitInfo::OMPTraitSet &Set : Sets) {
+    OS << 'S'
+       << llvm::omp::getOpenMPContextTraitSetName(Set.Kind).take_front(3);
+    for (const OMPTraitInfo::OMPTraitSelector &Selector : Set.Selectors) {
+
+      bool AllowsTraitScore = false;
+      bool RequiresProperty = false;
+      llvm::omp::isValidTraitSelectorForTraitSet(
+          Selector.Kind, Set.Kind, AllowsTraitScore, RequiresProperty);
+
+      if (!RequiresProperty ||
+          Selector.Kind == llvm::omp::TraitSelector::user_condition) {
+        OS << 'T'
+           << llvm::omp::getOpenMPContextTraitSelectorName(Selector.Kind)
+                  .take_front(3);
+        continue;
+      }
+
+      for (const OMPTraitInfo::OMPTraitProperty &Property : Selector.Properties)
+        OS << 'P'
+           << llvm::omp::getOpenMPContextTraitPropertyName(Property.Kind)
+                  .take_front(3);
+    }
+  }
+  return OS.str();
+}
+
 llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
                                      const OMPTraitInfo &TI) {
   LangOptions LO;
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h
--- a/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -333,17 +333,6 @@
   /// default location.
   virtual unsigned getDefaultLocationReserved2Flags() const { return 0; }
 
-  /// Tries to emit declare variant function for \p OldGD from \p NewGD.
-  /// \param OrigAddr LLVM IR value for \p OldGD.
-  /// \param IsForDefinition true, if requested emission for the definition of
-  /// \p OldGD.
-  /// \returns true, was able to emit a definition function for \p OldGD, which
-  /// points to \p NewGD.
-  virtual bool tryEmitDeclareVariant(const GlobalDecl &NewGD,
-                                     const GlobalDecl &OldGD,
-                                     llvm::GlobalValue *OrigAddr,
-                                     bool IsForDefinition);
-
   /// Returns default flags for the barriers depending on the directive, for
   /// which this barier is going to be emitted.
   static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind);
@@ -685,12 +674,6 @@
   /// must be emitted.
   llvm::SmallDenseSet<const VarDecl *> DeferredGlobalVariables;
 
-  /// Mapping of the original functions to their variants and original global
-  /// decl.
-  llvm::MapVector<CanonicalDeclPtr<const FunctionDecl>,
-                  std::pair<GlobalDecl, GlobalDecl>>
-      DeferredVariantFunction;
-
   using NontemporalDeclsSet = llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>>;
   /// Stack for list of declarations in current context marked as nontemporal.
   /// The set is the union of all current stack elements.
@@ -1717,9 +1700,6 @@
   /// Return whether the unified_shared_memory has been specified.
   bool hasRequiresUnifiedSharedMemory() const;
 
-  /// Emits the definition of the declare variant function.
-  virtual bool emitDeclareVariant(GlobalDecl GD, bool IsForDefinition);
-
   /// Checks if the \p VD variable is marked as nontemporal declaration in
   /// current context.
   bool isNontemporalDecl(const ValueDecl *VD) const;
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -1269,52 +1269,6 @@
   loadOffloadInfoMetadata();
 }
 
-bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD,
-                                            const GlobalDecl &OldGD,
-                                            llvm::GlobalValue *OrigAddr,
-                                            bool IsForDefinition) {
-  // Emit at least a definition for the aliasee if the the address of the
-  // original function is requested.
-  if (IsForDefinition || OrigAddr)
-    (void)CGM.GetAddrOfGlobal(NewGD);
-  StringRef NewMangledName = CGM.getMangledName(NewGD);
-  llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName);
-  if (Addr && !Addr->isDeclaration()) {
-    const auto *D = cast<FunctionDecl>(OldGD.getDecl());
-    const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(NewGD);
-    llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI);
-
-    // Create a reference to the named value.  This ensures that it is emitted
-    // if a deferred decl.
-    llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD);
-
-    // Create the new alias itself, but don't set a name yet.
-    auto *GA =
-        llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule());
-
-    if (OrigAddr) {
-      assert(OrigAddr->isDeclaration() && "Expected declaration");
-
-      GA->takeName(OrigAddr);
-      OrigAddr->replaceAllUsesWith(
-          llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType()));
-      OrigAddr->eraseFromParent();
-    } else {
-      GA->setName(CGM.getMangledName(OldGD));
-    }
-
-    // Set attributes which are particular to an alias; this is a
-    // specialization of the attributes which may be set on a global function.
-    if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() ||
-        D->isWeakImported())
-      GA->setLinkage(llvm::Function::WeakAnyLinkage);
-
-    CGM.SetCommonAttributes(OldGD, GA);
-    return true;
-  }
-  return false;
-}
-
 void CGOpenMPRuntime::clear() {
   InternalVars.clear();
   // Clean non-target variable declarations possibly used only in debug info.
@@ -1328,14 +1282,6 @@
       continue;
     GV->eraseFromParent();
   }
-  // Emit aliases for the deferred aliasees.
-  for (const auto &Pair : DeferredVariantFunction) {
-    StringRef MangledName = CGM.getMangledName(Pair.second.second);
-    llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName);
-    // If not able to emit alias, just emit original declaration.
-    (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr,
-                                /*IsForDefinition=*/false);
-  }
 }
 
 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
@@ -11075,57 +11021,6 @@
   return Address(Addr, Align);
 }
 
-/// Finds the variant function that matches current context with its context
-/// selector.
-static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM,
-                                                     const FunctionDecl *FD) {
-  if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
-    return FD;
-
-  SmallVector<Expr *, 8> VariantExprs;
-  SmallVector<VariantMatchInfo, 8> VMIs;
-  for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
-    const OMPTraitInfo &TI = A->getTraitInfos();
-    VMIs.push_back(VariantMatchInfo());
-    TI.getAsVariantMatchInfo(CGM.getContext(), VMIs.back(),
-                             /* DeviceSetOnly */ false);
-    VariantExprs.push_back(A->getVariantFuncRef());
-  }
-
-  OMPContext Ctx(CGM.getLangOpts().OpenMPIsDevice, CGM.getTriple());
-  // FIXME: Keep the context in the OMPIRBuilder so we can add constructs as we
-  //        build them.
-
-  int BestMatchIdx = getBestVariantMatchForContext(VMIs, Ctx);
-  if (BestMatchIdx < 0)
-    return FD;
-
-  return cast<FunctionDecl>(
-      cast<DeclRefExpr>(VariantExprs[BestMatchIdx]->IgnoreParenImpCasts())
-          ->getDecl());
-}
-
-bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) {
-  const auto *D = cast<FunctionDecl>(GD.getDecl());
-  // If the original function is defined already, use its definition.
-  StringRef MangledName = CGM.getMangledName(GD);
-  llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName);
-  if (Orig && !Orig->isDeclaration())
-    return false;
-  const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D);
-  // Emit original function if it does not have declare variant attribute or the
-  // context does not match.
-  if (NewFD == D)
-    return false;
-  GlobalDecl NewGD = GD.getWithDecl(NewFD);
-  if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) {
-    DeferredVariantFunction.erase(D);
-    return true;
-  }
-  DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD)));
-  return true;
-}
-
 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII(
     CodeGenModule &CGM, const OMPLoopDirective &S)
     : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) {
diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
--- a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
+++ b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
@@ -193,18 +193,6 @@
   /// Full/Lightweight runtime mode. Used for better optimization.
   unsigned getDefaultLocationReserved2Flags() const override;
 
-  /// Tries to emit declare variant function for \p OldGD from \p NewGD.
-  /// \param OrigAddr LLVM IR value for \p OldGD.
-  /// \param IsForDefinition true, if requested emission for the definition of
-  /// \p OldGD.
-  /// \returns true, was able to emit a definition function for \p OldGD, which
-  /// points to \p NewGD.
-  /// NVPTX backend does not support global aliases, so just use the function,
-  /// emitted for \p NewGD instead of \p OldGD.
-  bool tryEmitDeclareVariant(const GlobalDecl &NewGD, const GlobalDecl &OldGD,
-                             llvm::GlobalValue *OrigAddr,
-                             bool IsForDefinition) override;
-
 public:
   explicit CGOpenMPRuntimeNVPTX(CodeGenModule &CGM);
   void clear() override;
diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
--- a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
@@ -1923,19 +1923,6 @@
   llvm_unreachable("Unknown flags are requested.");
 }
 
-bool CGOpenMPRuntimeNVPTX::tryEmitDeclareVariant(const GlobalDecl &NewGD,
-                                                 const GlobalDecl &OldGD,
-                                                 llvm::GlobalValue *OrigAddr,
-                                                 bool IsForDefinition) {
-  // Emit the function in OldGD with the body from NewGD, if NewGD is defined.
-  auto *NewFD = cast<FunctionDecl>(NewGD.getDecl());
-  if (NewFD->isDefined()) {
-    CGM.emitOpenMPDeviceFunctionRedefinition(OldGD, NewGD, OrigAddr);
-    return true;
-  }
-  return false;
-}
-
 CGOpenMPRuntimeNVPTX::CGOpenMPRuntimeNVPTX(CodeGenModule &CGM)
     : CGOpenMPRuntime(CGM, "_", "$") {
   if (!CGM.getLangOpts().OpenMPIsDevice)
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1293,11 +1293,6 @@
   /// \param D Requires declaration
   void EmitOMPRequiresDecl(const OMPRequiresDecl *D);
 
-  /// Emits the definition of \p OldGD function with body from \p NewGD.
-  /// Required for proper handling of declare variant directive on the GPU.
-  void emitOpenMPDeviceFunctionRedefinition(GlobalDecl OldGD, GlobalDecl NewGD,
-                                            llvm::GlobalValue *GV);
-
   /// Returns whether the given record has hidden LTO visibility and therefore
   /// may participate in (single-module) CFI and whole-program vtable
   /// optimization.
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2579,11 +2579,6 @@
     return;
   }
 
-    // Check if this must be emitted as declare variant.
-  if (LangOpts.OpenMP && isa<FunctionDecl>(Global) && OpenMPRuntime &&
-      OpenMPRuntime->emitDeclareVariant(GD, /*IsForDefinition=*/false))
-    return;
-
   // If we're deferring emission of a C++ variable with an
   // initializer, remember the order in which it appeared in the file.
   if (getLangOpts().CPlusPlus && isa<VarDecl>(Global) &&
@@ -2789,50 +2784,6 @@
     EmitGlobalFunctionDefinition(GD, GV);
 }
 
-void CodeGenModule::emitOpenMPDeviceFunctionRedefinition(
-    GlobalDecl OldGD, GlobalDecl NewGD, llvm::GlobalValue *GV) {
-  assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice &&
-         OpenMPRuntime && "Expected OpenMP device mode.");
-  const auto *D = cast<FunctionDecl>(OldGD.getDecl());
-
-  // Compute the function info and LLVM type.
-  const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(OldGD);
-  llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
-
-  // Get or create the prototype for the function.
-  if (!GV || (GV->getType()->getElementType() != Ty)) {
-    GV = cast<llvm::GlobalValue>(GetOrCreateLLVMFunction(
-        getMangledName(OldGD), Ty, GlobalDecl(), /*ForVTable=*/false,
-        /*DontDefer=*/true, /*IsThunk=*/false, llvm::AttributeList(),
-        ForDefinition));
-    SetFunctionAttributes(OldGD, cast<llvm::Function>(GV),
-                          /*IsIncompleteFunction=*/false,
-                          /*IsThunk=*/false);
-  }
-  // We need to set linkage and visibility on the function before
-  // generating code for it because various parts of IR generation
-  // want to propagate this information down (e.g. to local static
-  // declarations).
-  auto *Fn = cast<llvm::Function>(GV);
-  setFunctionLinkage(OldGD, Fn);
-
-  // FIXME: this is redundant with part of
-  // setFunctionDefinitionAttributes
-  setGVProperties(Fn, OldGD);
-
-  MaybeHandleStaticInExternC(D, Fn);
-
-  maybeSetTrivialComdat(*D, *Fn);
-
-  CodeGenFunction(*this).GenerateCode(NewGD, Fn, FI);
-
-  setNonAliasAttributes(OldGD, Fn);
-  SetLLVMFunctionAttributesForDefinition(D, Fn);
-
-  if (D->hasAttr<AnnotateAttr>())
-    AddGlobalAnnotations(D, Fn);
-}
-
 void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
   const auto *D = cast<ValueDecl>(GD.getDecl());
 
@@ -3147,10 +3098,6 @@
         EmitGlobal(GDDef);
       }
     }
-    // Check if this must be emitted as declare variant and emit reference to
-    // the the declare variant function.
-    if (LangOpts.OpenMP && OpenMPRuntime)
-      (void)OpenMPRuntime->emitDeclareVariant(GD, /*IsForDefinition=*/true);
 
     if (FD->isMultiVersion()) {
       const auto *TA = FD->getAttr<TargetAttr>();
@@ -4446,11 +4393,6 @@
 
 void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
                                                  llvm::GlobalValue *GV) {
-  // Check if this must be emitted as declare variant.
-  if (LangOpts.OpenMP && OpenMPRuntime &&
-      OpenMPRuntime->emitDeclareVariant(GD, /*IsForDefinition=*/true))
-    return;
-
   const auto *D = cast<FunctionDecl>(GD.getDecl());
 
   // Compute the function info and LLVM type.
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -1782,8 +1782,10 @@
     OMPContext OMPCtx(ASTCtx.getLangOpts().OpenMPIsDevice,
                       ASTCtx.getTargetInfo().getTriple());
 
-    if (isVariantApplicableInContext(VMI, OMPCtx))
+    if (isVariantApplicableInContext(VMI, OMPCtx)) {
+      Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI);
       break;
+    }
 
     // Elide all the code till the matching end declare variant was found.
     unsigned Nesting = 1;
@@ -1807,11 +1809,14 @@
       return nullptr;
     break;
   }
-  case OMPD_end_declare_variant:
-    // FIXME: With the sema changes we will keep track of nesting and be able to
-    // diagnose unmatchend OMPD_end_declare_variant.
+  case OMPD_end_declare_variant: {
+    if (Actions.isInOpenMPDeclareVariantScope())
+      Actions.ActOnOpenMPEndDeclareVariant();
+    else
+      Diag(Loc, diag::err_expected_begin_declare_variant);
     ConsumeToken();
     break;
+  }
   case OMPD_declare_variant:
   case OMPD_declare_simd: {
     // The syntax is:
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2720,6 +2720,11 @@
       // honored it.
       ++I;
       continue;
+    } else if (isa<OMPDeclareVariantAttr>(NewAttribute)) {
+      // We allow to add OMP[Begin]DeclareVariantAttr to be added to
+      // declarations after defintions.
+      ++I;
+      continue;
     }
 
     S.Diag(NewAttribute->getLocation(),
@@ -13542,9 +13547,21 @@
   assert(D.isFunctionDeclarator() && "Not a function declarator!");
   Scope *ParentScope = FnBodyScope->getParent();
 
+  FunctionDecl *BaseFD = nullptr;
+  if (LangOpts.OpenMP && isInOpenMPDeclareVariantScope() &&
+      TemplateParameterLists.empty())
+    BaseFD = ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
+        ParentScope, D);
+
   D.setFunctionDefinitionKind(FDK_Definition);
   Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists);
-  return ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody);
+  Decl *Dcl = ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody);
+
+  if (BaseFD)
+    ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
+        cast<FunctionDecl>(Dcl), BaseFD);
+
+  return Dcl;
 }
 
 void Sema::ActOnFinishInlineFunctionDef(FunctionDecl *D) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5724,6 +5724,10 @@
     }
   }
 
+  if (LangOpts.OpenMP)
+    Call = ActOnOpenMPCall(*this, Call, Scope, LParenLoc, ArgExprs, RParenLoc,
+                           ExecConfig);
+
   return Call;
 }
 
@@ -15959,7 +15963,6 @@
   }
 
   if (LangOpts.OpenMP) {
-    markOpenMPDeclareVariantFuncsReferenced(Loc, Func, MightBeOdrUse);
     if (LangOpts.OpenMPIsDevice)
       checkOpenMPDeviceFunction(Loc, Func);
     else
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -2208,6 +2208,22 @@
 
 void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
 
+void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
+                                          OMPTraitInfo &TI) {
+  if (!OMPDeclareVariantScopes.empty()) {
+    Diag(Loc, diag::warn_nested_declare_variant);
+    return;
+  }
+  OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
+}
+
+void Sema::ActOnOpenMPEndDeclareVariant() {
+  assert(isInOpenMPDeclareVariantScope() &&
+         "Not in OpenMP declare variant scope!");
+
+  OMPDeclareVariantScopes.pop_back();
+}
+
 void Sema::finalizeOpenMPDelayedAnalysis() {
   assert(LangOpts.OpenMP && "Expected OpenMP compilation mode.");
   // Diagnose implicit declare target functions and their callees.
@@ -5371,6 +5387,119 @@
   FD->setParams(Params);
 }
 
+FunctionDecl *
+Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S,
+                                                                Declarator &D) {
+  auto *BaseFD = dyn_cast_or_null<FunctionDecl>(
+      LookupSingleName(S, DeclarationName(D.getIdentifier()), D.getBeginLoc(),
+                       LookupNameKind::LookupOrdinaryName,
+                       RedeclarationKind::NotForRedeclaration));
+  if (!BaseFD)
+    BaseFD = cast<FunctionDecl>(ActOnDeclarator(S, D));
+
+  OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
+  IdentifierInfo &VariangtII = Context.Idents.get(
+      (D.getIdentifier()->getName() + "." + DVScope.NameSuffix).str());
+  D.SetIdentifier(&VariangtII, D.getBeginLoc());
+  return BaseFD;
+}
+
+void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
+    FunctionDecl *FD, FunctionDecl *BaseFD) {
+  // Do not mark function as is used to prevent its emission if this is the
+  // only place where it is used.
+  EnterExpressionEvaluationContext Unevaluated(
+      *this, Sema::ExpressionEvaluationContext::Unevaluated);
+
+  Expr *VariantFuncRef = DeclRefExpr::Create(
+      Context, NestedNameSpecifierLoc(), SourceLocation(), FD,
+      /* RefersToEnclosingVariableOrCapture */ false,
+      /* NameLoc */ FD->getLocation(), FD->getType(), ExprValueKind::VK_RValue);
+
+  OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
+  auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
+      Context, VariantFuncRef, DVScope.TI);
+  BaseFD->addAttr(OMPDeclareVariantA);
+}
+
+ExprResult Sema::ActOnOpenMPCall(Sema &S, ExprResult Call, Scope *Scope,
+                                 SourceLocation LParenLoc,
+                                 MultiExprArg ArgExprs,
+                                 SourceLocation RParenLoc, Expr *ExecConfig) {
+  // The common case is a regular call we do not want to specialize at all. Try
+  // to make that case fast by bailing early.
+  CallExpr *CE = dyn_cast<CallExpr>(Call.get());
+  if (!CE)
+    return Call;
+
+  FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
+  if (!CalleeFnDecl)
+    return Call;
+
+  if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
+    return Call;
+
+  ASTContext &Context = S.getASTContext();
+  OMPContext OMPCtx(S.getLangOpts().OpenMPIsDevice,
+                    Context.getTargetInfo().getTriple());
+
+  SmallVector<Expr *, 4> Exprs;
+  SmallVector<VariantMatchInfo, 4> VMIs;
+  while (CalleeFnDecl) {
+    for (OMPDeclareVariantAttr *A :
+         CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
+      Expr *VariantRef = A->getVariantFuncRef();
+
+      VariantMatchInfo VMI;
+      OMPTraitInfo &TI = A->getTraitInfo();
+      TI.getAsVariantMatchInfo(Context, VMI, /* DeviceSetOnly */ false);
+      if (!isVariantApplicableInContext(VMI, OMPCtx))
+        continue;
+
+      VMIs.push_back(VMI);
+      Exprs.push_back(VariantRef);
+    }
+
+    CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
+  }
+
+  ExprResult NewCall;
+  do {
+    int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
+    if (BestIdx < 0)
+      return Call;
+    Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
+    Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
+
+    {
+      // Try to build a (member) call expression for the current best applicable
+      // variant expression. We allow this to fail in which case we continue with
+      // the next best variant expression.
+      Sema::TentativeAnalysisScope Trap(*this);
+
+      if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
+        auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
+        BestExpr = MemberExpr::CreateImplicit(
+            S.Context, MemberCall->getImplicitObjectArgument(),
+            /* IsArrow */ false, SpecializedMethod, S.Context.BoundMemberTy,
+            MemberCall->getValueKind(), MemberCall->getObjectKind());
+      }
+      NewCall = S.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc,
+                                ExecConfig);
+      if (NewCall.isUsable())
+        break;
+    }
+
+    VMIs.erase(VMIs.begin() + BestIdx);
+    Exprs.erase(Exprs.begin() + BestIdx);
+  } while (!VMIs.empty());
+
+  if (!NewCall.isUsable())
+    return Call;
+
+  return PseudoObjectExpr::Create(Context, CE, {NewCall.get()}, 0);
+}
+
 Optional<std::pair<FunctionDecl *, Expr *>>
 Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
                                         Expr *VariantRef, OMPTraitInfo &TI,
@@ -5643,25 +5772,6 @@
   FD->addAttr(NewAttr);
 }
 
-void Sema::markOpenMPDeclareVariantFuncsReferenced(SourceLocation Loc,
-                                                   FunctionDecl *Func,
-                                                   bool MightBeOdrUse) {
-  assert(LangOpts.OpenMP && "Expected OpenMP mode.");
-
-  if (!Func->isDependentContext() && Func->hasAttrs()) {
-    for (OMPDeclareVariantAttr *A :
-         Func->specific_attrs<OMPDeclareVariantAttr>()) {
-      // TODO: add checks for active OpenMP context where possible.
-      Expr *VariantRef = A->getVariantFuncRef();
-      auto *DRE = cast<DeclRefExpr>(VariantRef->IgnoreParenImpCasts());
-      auto *F = cast<FunctionDecl>(DRE->getDecl());
-      if (!F->isDefined() && F->isTemplateInstantiation())
-        InstantiateFunctionDefinition(Loc, F->getFirstDecl());
-      MarkFunctionReferenced(Loc, F, MightBeOdrUse);
-    }
-  }
-}
-
 StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
                                               Stmt *AStmt,
                                               SourceLocation StartLoc,
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -334,6 +334,11 @@
     }
   } else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
     const Expr *Source = POE->getSyntacticForm();
+    // Handle the actually selected call of an OpenMP specialized call.
+    if (LangOpts.OpenMP && isa<CallExpr>(Source) &&
+        POE->getNumSemanticExprs() == 1 &&
+        isa<CallExpr>(POE->getSemanticExpr(0)))
+      return DiagnoseUnusedExprResult(POE->getSemanticExpr(0));
     if (isa<ObjCSubscriptRefExpr>(Source))
       DiagID = diag::warn_unused_container_subscript_expr;
     else
diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant.c
deleted file mode 100644
--- a/clang/test/AST/ast-dump-openmp-begin-declare-variant.c
+++ /dev/null
@@ -1,55 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -ast-dump %s | FileCheck %s
-
-#pragma omp begin declare variant match(device={kind(cpu)})
-int also_before(void) {
-  return 0;
-}
-#pragma omp end declare variant
-
-#pragma omp begin declare variant match(device={kind(gpu)})
-int also_after(void) {
-  return 2;
-}
-int also_before(void) {
-  return 2;
-}
-#pragma omp end declare variant
-
-
-#pragma omp begin declare variant match(device={kind(fpga)})
-
-This text is never parsed!
-
-#pragma omp end declare variant
-
-int also_after(void) {
-  return 0;
-}
-
-int test() {
-  return also_after() + also_before();
-}
-
-// Make sure:
-//  - we do see the ast nodes for the cpu kind
-//  - we do not see the ast nodes for the gpu kind
-//  - we do not choke on the text in the kind(fpga) guarded scope.
-
-// CHECK:       -FunctionDecl {{.*}} <{{.*}}4:1, line:{{.*}}:1> line:{{.*}}:5 used also_before 'int (void)'
-// CHECK-NEXT:   -CompoundStmt {{.*}} <col:23, line:{{.*}}:1>
-// CHECK-NEXT:    `-ReturnStmt {{.*}} <line:{{.*}}:3, col:10>
-// CHECK-NEXT:      `-IntegerLiteral {{.*}} <col:10> 'int' 0
-// CHECK-NEXT:  -FunctionDecl {{.*}} <line:{{.*}}:1, line:{{.*}}:1> line:{{.*}}:5 used also_after 'int (void)'
-// CHECK-NEXT:   -CompoundStmt {{.*}} <col:22, line:{{.*}}:1>
-// CHECK-NEXT:    `-ReturnStmt {{.*}} <line:{{.*}}:3, col:10>
-// CHECK-NEXT:      `-IntegerLiteral {{.*}} <col:10> 'int' 0
-// CHECK-NEXT:  `-FunctionDecl {{.*}} <line:{{.*}}:1, line:{{.*}}:1> line:{{.*}}:5 test 'int ()'
-// CHECK-NEXT:    `-CompoundStmt {{.*}} <col:12, line:{{.*}}:1>
-// CHECK-NEXT:      `-ReturnStmt {{.*}} <line:{{.*}}:3, col:37>
-// CHECK-NEXT:        `-BinaryOperator {{.*}} <col:10, col:37> 'int' '+'
-// CHECK-NEXT:          |-CallExpr {{.*}} <col:10, col:21> 'int'
-// CHECK-NEXT:          | `-ImplicitCastExpr {{.*}} <col:10> 'int (*)(void)' <FunctionToPointerDecay>
-// CHECK-NEXT:          |   `-DeclRefExpr {{.*}} <col:10> 'int (void)' Function {{.*}} 'also_after' 'int (void)'
-// CHECK-NEXT:          `-CallExpr {{.*}} <col:25, col:37> 'int'
-// CHECK-NEXT:            `-ImplicitCastExpr {{.*}} <col:25> 'int (*)(void)' <FunctionToPointerDecay>
-// CHECK-NEXT:              `-DeclRefExpr {{.*}} <col:25> 'int (void)' Function {{.*}} 'also_before' 'int (void)'
diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_1.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_1.c
new file mode 100644
--- /dev/null
+++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_1.c
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s       | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s
+// expected-no-diagnostics
+
+int also_before(void) {
+  return 0;
+}
+
+#pragma omp begin declare variant match(device={kind(gpu)})
+int also_after(void) {
+  return 1;
+}
+int also_before(void) {
+  return 2;
+}
+#pragma omp end declare variant
+
+
+#pragma omp begin declare variant match(device={kind(fpga)})
+
+This text is never parsed!
+
+#pragma omp end declare variant
+
+int also_after(void) {
+  return 0;
+}
+
+int test() {
+  // Should return 0.
+  return also_after() + also_before();
+}
+
+// Make sure:
+//  - we do not see the ast nodes for the gpu kind
+//  - we do not choke on the text in the kind(fpga) guarded scopes
+
+// CHECK:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] <col:23, line:7:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] <line:6:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: |-FunctionDecl [[ADDR_4:0x[a-z0-9]*]] <line:25:1, line:27:1> line:25:5 used also_after 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_5:0x[a-z0-9]*]] <col:22, line:27:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_6:0x[a-z0-9]*]] <line:26:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_7:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: `-FunctionDecl [[ADDR_8:0x[a-z0-9]*]] <line:29:1, line:32:1> line:29:5 test 'int ({{.*}})'
+// CHECK-NEXT:   `-CompoundStmt [[ADDR_9:0x[a-z0-9]*]] <col:12, line:32:1>
+// CHECK-NEXT:     `-ReturnStmt [[ADDR_10:0x[a-z0-9]*]] <line:31:3, col:37>
+// CHECK-NEXT:       `-BinaryOperator [[ADDR_11:0x[a-z0-9]*]] <col:10, col:37> 'int' '+'
+// CHECK-NEXT:         |-CallExpr [[ADDR_12:0x[a-z0-9]*]] <col:10, col:21> 'int'
+// CHECK-NEXT:         | `-ImplicitCastExpr [[ADDR_13:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:         |   `-DeclRefExpr [[ADDR_14:0x[a-z0-9]*]] <col:10> 'int ({{.*}})' {{.*}}Function [[ADDR_4]] 'also_after' 'int ({{.*}})'
+// CHECK-NEXT:         `-CallExpr [[ADDR_15:0x[a-z0-9]*]] <col:25, col:37> 'int'
+// CHECK-NEXT:           `-ImplicitCastExpr [[ADDR_16:0x[a-z0-9]*]] <col:25> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:             `-DeclRefExpr [[ADDR_17:0x[a-z0-9]*]] <col:25> 'int ({{.*}})' {{.*}}Function [[ADDR_0]] 'also_before' 'int ({{.*}})'
diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_2.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_2.c
new file mode 100644
--- /dev/null
+++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_2.c
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s       | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s
+// expected-no-diagnostics
+
+#pragma omp begin declare variant match(device={kind(cpu)})
+int also_before(void) {
+  return 0;
+}
+#pragma omp end declare variant
+
+#pragma omp begin declare variant match(implementation={vendor(score(100):llvm)})
+int also_after(void) {
+  return 0;
+}
+#pragma omp end declare variant
+#pragma omp begin declare variant match(implementation={vendor(score(0):llvm)})
+int also_before(void) {
+  return 1;
+}
+#pragma omp end declare variant
+
+int also_after(void) {
+  return 2;
+}
+
+int test() {
+  // Should return 0.
+  return also_after() + also_before();
+}
+
+// Make sure:
+//  - we do see the ast nodes for the cpu kind
+//  - we do see the ast nodes for the llvm vendor
+//  - we pick the right callees
+
+// CHECK:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, col:21> col:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_1:0x[a-z0-9]*]] <<invalid sloc>> Implicit device={kind(cpu)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_2:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_3:0x[a-z0-9]*]] 'also_before.SdevPcpu' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_3]] <col:1, line:8:1> line:6:1 also_before.SdevPcpu 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_4:0x[a-z0-9]*]] <col:23, line:8:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_5:0x[a-z0-9]*]] <line:7:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_6:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: |-FunctionDecl [[ADDR_7:0x[a-z0-9]*]] <line:12:1, col:20> col:5 used also_after 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_8:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(score(100): llvm)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_9:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_10:0x[a-z0-9]*]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_10]] <col:1, line:14:1> line:12:1 also_after.SimpPllv 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_11:0x[a-z0-9]*]] <col:22, line:14:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_12:0x[a-z0-9]*]] <line:13:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_13:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: |-FunctionDecl [[ADDR_14:0x[a-z0-9]*]] prev [[ADDR_0]] <line:17:1, col:21> col:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: | |-OMPDeclareVariantAttr [[ADDR_15:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit device={kind(cpu)}
+// CHECK-NEXT: | | `-DeclRefExpr [[ADDR_2]] <line:6:1> 'int ({{.*}})' Function [[ADDR_3]] 'also_before.SdevPcpu' 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_16:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(score(0): llvm)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_17:0x[a-z0-9]*]] <line:17:1> 'int ({{.*}})' Function [[ADDR_18:0x[a-z0-9]*]] 'also_before.SimpPllv' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_18]] <col:1, line:19:1> line:17:1 also_before.SimpPllv 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_19:0x[a-z0-9]*]] <col:23, line:19:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_20:0x[a-z0-9]*]] <line:18:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_21:0x[a-z0-9]*]] <col:10> 'int' 1
+// CHECK-NEXT: |-FunctionDecl [[ADDR_22:0x[a-z0-9]*]] prev [[ADDR_7]] <line:22:1, line:24:1> line:22:5 used also_after 'int ({{.*}})'
+// CHECK-NEXT: | |-CompoundStmt [[ADDR_23:0x[a-z0-9]*]] <col:22, line:24:1>
+// CHECK-NEXT: | | `-ReturnStmt [[ADDR_24:0x[a-z0-9]*]] <line:23:3, col:10>
+// CHECK-NEXT: | |   `-IntegerLiteral [[ADDR_25:0x[a-z0-9]*]] <col:10> 'int' 2
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_26:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(score(100): llvm)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_9]] <line:12:1> 'int ({{.*}})' Function [[ADDR_10]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CHECK-NEXT: `-FunctionDecl [[ADDR_27:0x[a-z0-9]*]] <line:26:1, line:29:1> line:26:5 test 'int ({{.*}})'
+// CHECK-NEXT:   `-CompoundStmt [[ADDR_28:0x[a-z0-9]*]] <col:12, line:29:1>
+// CHECK-NEXT:     `-ReturnStmt [[ADDR_29:0x[a-z0-9]*]] <line:28:3, col:37>
+// CHECK-NEXT:       `-BinaryOperator [[ADDR_30:0x[a-z0-9]*]] <col:10, col:37> 'int' '+'
+// CHECK-NEXT:         |-PseudoObjectExpr [[ADDR_31:0x[a-z0-9]*]] <col:10, col:21> 'int'
+// CHECK-NEXT:         | |-CallExpr [[ADDR_32:0x[a-z0-9]*]] <col:10, col:21> 'int'
+// CHECK-NEXT:         | | `-ImplicitCastExpr [[ADDR_33:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:         | |   `-DeclRefExpr [[ADDR_34:0x[a-z0-9]*]] <col:10> 'int ({{.*}})' {{.*}}Function [[ADDR_22]] 'also_after' 'int ({{.*}})'
+// CHECK-NEXT:         | `-CallExpr [[ADDR_35:0x[a-z0-9]*]] <line:12:1, line:28:21> 'int'
+// CHECK-NEXT:         |   `-ImplicitCastExpr [[ADDR_36:0x[a-z0-9]*]] <line:12:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:         |     `-DeclRefExpr [[ADDR_9]] <col:1> 'int ({{.*}})' Function [[ADDR_10]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CHECK-NEXT:         `-PseudoObjectExpr [[ADDR_37:0x[a-z0-9]*]] <line:28:25, col:37> 'int'
+// CHECK-NEXT:           |-CallExpr [[ADDR_38:0x[a-z0-9]*]] <col:25, col:37> 'int'
+// CHECK-NEXT:           | `-ImplicitCastExpr [[ADDR_39:0x[a-z0-9]*]] <col:25> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:           |   `-DeclRefExpr [[ADDR_40:0x[a-z0-9]*]] <col:25> 'int ({{.*}})' {{.*}}Function [[ADDR_14]] 'also_before' 'int ({{.*}})'
+// CHECK-NEXT:           `-CallExpr [[ADDR_41:0x[a-z0-9]*]] <line:6:1, line:28:37> 'int'
+// CHECK-NEXT:             `-ImplicitCastExpr [[ADDR_42:0x[a-z0-9]*]] <line:6:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:               `-DeclRefExpr [[ADDR_2]] <col:1> 'int ({{.*}})' Function [[ADDR_3]] 'also_before.SdevPcpu' 'int ({{.*}})'
diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_3.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_3.c
new file mode 100644
--- /dev/null
+++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_3.c
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s       | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s
+// expected-no-diagnostics
+
+#pragma omp begin declare variant match(device={kind(cpu)})
+int also_before(void) {
+  return 1;
+}
+#pragma omp end declare variant
+
+#pragma omp begin declare variant match(implementation={vendor(score(0):llvm)})
+int also_after(void) {
+  return 0;
+}
+#pragma omp end declare variant
+#pragma omp begin declare variant match(implementation={vendor(score(100):llvm)})
+int also_before(void) {
+  return 0;
+}
+#pragma omp end declare variant
+
+int also_after(void) {
+  return 2;
+}
+
+int test() {
+  // Should return 0.
+  return also_after() + also_before();
+}
+
+// Make sure:
+//  - we do see the ast nodes for the cpu kind
+//  - we do see the ast nodes for the llvm vendor
+//  - we pick the right callees
+
+// CHECK:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, col:21> col:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_1:0x[a-z0-9]*]] <<invalid sloc>> Implicit device={kind(cpu)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_2:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_3:0x[a-z0-9]*]] 'also_before.SdevPcpu' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_3]] <col:1, line:8:1> line:6:1 also_before.SdevPcpu 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_4:0x[a-z0-9]*]] <col:23, line:8:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_5:0x[a-z0-9]*]] <line:7:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_6:0x[a-z0-9]*]] <col:10> 'int' 1
+// CHECK-NEXT: |-FunctionDecl [[ADDR_7:0x[a-z0-9]*]] <line:12:1, col:20> col:5 used also_after 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_8:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(score(0): llvm)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_9:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_10:0x[a-z0-9]*]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_10]] <col:1, line:14:1> line:12:1 also_after.SimpPllv 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_11:0x[a-z0-9]*]] <col:22, line:14:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_12:0x[a-z0-9]*]] <line:13:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_13:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: |-FunctionDecl [[ADDR_14:0x[a-z0-9]*]] prev [[ADDR_0]] <line:17:1, col:21> col:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: | |-OMPDeclareVariantAttr [[ADDR_15:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit device={kind(cpu)}
+// CHECK-NEXT: | | `-DeclRefExpr [[ADDR_2]] <line:6:1> 'int ({{.*}})' Function [[ADDR_3]] 'also_before.SdevPcpu' 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_16:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(score(100): llvm)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_17:0x[a-z0-9]*]] <line:17:1> 'int ({{.*}})' Function [[ADDR_18:0x[a-z0-9]*]] 'also_before.SimpPllv' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_18]] <col:1, line:19:1> line:17:1 also_before.SimpPllv 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_19:0x[a-z0-9]*]] <col:23, line:19:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_20:0x[a-z0-9]*]] <line:18:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_21:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: |-FunctionDecl [[ADDR_22:0x[a-z0-9]*]] prev [[ADDR_7]] <line:22:1, line:24:1> line:22:5 used also_after 'int ({{.*}})'
+// CHECK-NEXT: | |-CompoundStmt [[ADDR_23:0x[a-z0-9]*]] <col:22, line:24:1>
+// CHECK-NEXT: | | `-ReturnStmt [[ADDR_24:0x[a-z0-9]*]] <line:23:3, col:10>
+// CHECK-NEXT: | |   `-IntegerLiteral [[ADDR_25:0x[a-z0-9]*]] <col:10> 'int' 2
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_26:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(score(0): llvm)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_9]] <line:12:1> 'int ({{.*}})' Function [[ADDR_10]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CHECK-NEXT: `-FunctionDecl [[ADDR_27:0x[a-z0-9]*]] <line:26:1, line:29:1> line:26:5 test 'int ({{.*}})'
+// CHECK-NEXT:   `-CompoundStmt [[ADDR_28:0x[a-z0-9]*]] <col:12, line:29:1>
+// CHECK-NEXT:     `-ReturnStmt [[ADDR_29:0x[a-z0-9]*]] <line:28:3, col:37>
+// CHECK-NEXT:       `-BinaryOperator [[ADDR_30:0x[a-z0-9]*]] <col:10, col:37> 'int' '+'
+// CHECK-NEXT:         |-PseudoObjectExpr [[ADDR_31:0x[a-z0-9]*]] <col:10, col:21> 'int'
+// CHECK-NEXT:         | |-CallExpr [[ADDR_32:0x[a-z0-9]*]] <col:10, col:21> 'int'
+// CHECK-NEXT:         | | `-ImplicitCastExpr [[ADDR_33:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:         | |   `-DeclRefExpr [[ADDR_34:0x[a-z0-9]*]] <col:10> 'int ({{.*}})' {{.*}}Function [[ADDR_22]] 'also_after' 'int ({{.*}})'
+// CHECK-NEXT:         | `-CallExpr [[ADDR_35:0x[a-z0-9]*]] <line:12:1, line:28:21> 'int'
+// CHECK-NEXT:         |   `-ImplicitCastExpr [[ADDR_36:0x[a-z0-9]*]] <line:12:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:         |     `-DeclRefExpr [[ADDR_9]] <col:1> 'int ({{.*}})' Function [[ADDR_10]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CHECK-NEXT:         `-PseudoObjectExpr [[ADDR_37:0x[a-z0-9]*]] <line:28:25, col:37> 'int'
+// CHECK-NEXT:           |-CallExpr [[ADDR_38:0x[a-z0-9]*]] <col:25, col:37> 'int'
+// CHECK-NEXT:           | `-ImplicitCastExpr [[ADDR_39:0x[a-z0-9]*]] <col:25> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:           |   `-DeclRefExpr [[ADDR_40:0x[a-z0-9]*]] <col:25> 'int ({{.*}})' {{.*}}Function [[ADDR_14]] 'also_before' 'int ({{.*}})'
+// CHECK-NEXT:           `-CallExpr [[ADDR_41:0x[a-z0-9]*]] <line:17:1, line:28:37> 'int'
+// CHECK-NEXT:             `-ImplicitCastExpr [[ADDR_42:0x[a-z0-9]*]] <line:17:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:               `-DeclRefExpr [[ADDR_17]] <col:1> 'int ({{.*}})' Function [[ADDR_18]] 'also_before.SimpPllv' 'int ({{.*}})'
diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_4.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_4.c
new file mode 100644
--- /dev/null
+++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_4.c
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s       | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s
+// expected-no-diagnostics
+
+#pragma omp begin declare variant match(device={kind(cpu)})
+int also_before(void) {
+  return 0;
+}
+#pragma omp end declare variant
+
+int also_after(void) {
+  return 0;
+}
+
+int test() {
+  // Should return 0.
+  return also_after() + also_before();
+}
+
+// Make sure:
+//  - we do see the ast nodes for the cpu kind
+//  - we pick the right callees
+
+// CHECK:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, col:21> col:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_1:0x[a-z0-9]*]] <<invalid sloc>> Implicit device={kind(cpu)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_2:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_3:0x[a-z0-9]*]] 'also_before.SdevPcpu' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_3]] <col:1, line:8:1> line:6:1 also_before.SdevPcpu 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_4:0x[a-z0-9]*]] <col:23, line:8:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_5:0x[a-z0-9]*]] <line:7:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_6:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: |-FunctionDecl [[ADDR_7:0x[a-z0-9]*]] <line:11:1, line:13:1> line:11:5 used also_after 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_8:0x[a-z0-9]*]] <col:22, line:13:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_9:0x[a-z0-9]*]] <line:12:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_10:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: `-FunctionDecl [[ADDR_11:0x[a-z0-9]*]] <line:15:1, line:18:1> line:15:5 test 'int ({{.*}})'
+// CHECK-NEXT:   `-CompoundStmt [[ADDR_12:0x[a-z0-9]*]] <col:12, line:18:1>
+// CHECK-NEXT:     `-ReturnStmt [[ADDR_13:0x[a-z0-9]*]] <line:17:3, col:37>
+// CHECK-NEXT:       `-BinaryOperator [[ADDR_14:0x[a-z0-9]*]] <col:10, col:37> 'int' '+'
+// CHECK-NEXT:         |-CallExpr [[ADDR_15:0x[a-z0-9]*]] <col:10, col:21> 'int'
+// CHECK-NEXT:         | `-ImplicitCastExpr [[ADDR_16:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:         |   `-DeclRefExpr [[ADDR_17:0x[a-z0-9]*]] <col:10> 'int ({{.*}})' {{.*}}Function [[ADDR_7]] 'also_after' 'int ({{.*}})'
+// CHECK-NEXT:         `-PseudoObjectExpr [[ADDR_18:0x[a-z0-9]*]] <col:25, col:37> 'int'
+// CHECK-NEXT:           |-CallExpr [[ADDR_19:0x[a-z0-9]*]] <col:25, col:37> 'int'
+// CHECK-NEXT:           | `-ImplicitCastExpr [[ADDR_20:0x[a-z0-9]*]] <col:25> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:           |   `-DeclRefExpr [[ADDR_21:0x[a-z0-9]*]] <col:25> 'int ({{.*}})' {{.*}}Function [[ADDR_0]] 'also_before' 'int ({{.*}})'
+// CHECK-NEXT:           `-CallExpr [[ADDR_22:0x[a-z0-9]*]] <line:6:1, line:17:37> 'int'
+// CHECK-NEXT:             `-ImplicitCastExpr [[ADDR_23:0x[a-z0-9]*]] <line:6:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:               `-DeclRefExpr [[ADDR_2]] <col:1> 'int ({{.*}})' Function [[ADDR_3]] 'also_before.SdevPcpu' 'int ({{.*}})'
diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_5.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_5.c
new file mode 100644
--- /dev/null
+++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_5.c
@@ -0,0 +1,158 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s       | FileCheck %s --check-prefix=C
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s --check-prefix=CXX
+// expected-no-diagnostics
+
+int also_before(void) {
+  return 1;
+}
+
+#pragma omp begin declare variant match(implementation={vendor(llvm)})
+int also_after(void) {
+  return 0;
+}
+int also_before(void) {
+  return 0;
+}
+#pragma omp end declare variant
+
+int also_after(void) {
+  return 2;
+}
+
+int main() {
+  // Should return 0.
+  return (also_after)() +
+         (also_before)() +
+         (&also_after)() +
+         (&also_before)();
+}
+
+// Make sure:
+//  - we see the specialization in the AST
+//  - we pick the right callees
+
+// C:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})'
+// C-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] <col:23, line:7:1>
+// C-NEXT: |   `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] <line:6:3, col:10>
+// C-NEXT: |     `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] <col:10> 'int' 1
+// C-NEXT: |-FunctionDecl [[ADDR_4:0x[a-z0-9]*]] <line:10:1, col:20> col:5 used also_after 'int ({{.*}})'
+// C-NEXT: | `-OMPDeclareVariantAttr [[ADDR_5:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(llvm)}
+// C-NEXT: |   `-DeclRefExpr [[ADDR_6:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_7:0x[a-z0-9]*]] 'also_after.SimpPllv' 'int ({{.*}})'
+// C-NEXT: |-FunctionDecl [[ADDR_7]] <col:1, line:12:1> line:10:1 also_after.SimpPllv 'int ({{.*}})'
+// C-NEXT: | `-CompoundStmt [[ADDR_8:0x[a-z0-9]*]] <col:22, line:12:1>
+// C-NEXT: |   `-ReturnStmt [[ADDR_9:0x[a-z0-9]*]] <line:11:3, col:10>
+// C-NEXT: |     `-IntegerLiteral [[ADDR_10:0x[a-z0-9]*]] <col:10> 'int' 0
+// C-NEXT: |-FunctionDecl [[ADDR_11:0x[a-z0-9]*]] prev [[ADDR_0]] <line:13:1, col:21> col:5 used also_before 'int ({{.*}})'
+// C-NEXT: | `-OMPDeclareVariantAttr [[ADDR_12:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(llvm)}
+// C-NEXT: |   `-DeclRefExpr [[ADDR_13:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_14:0x[a-z0-9]*]] 'also_before.SimpPllv' 'int ({{.*}})'
+// C-NEXT: |-FunctionDecl [[ADDR_14]] <col:1, line:15:1> line:13:1 also_before.SimpPllv 'int ({{.*}})'
+// C-NEXT: | `-CompoundStmt [[ADDR_15:0x[a-z0-9]*]] <col:23, line:15:1>
+// C-NEXT: |   `-ReturnStmt [[ADDR_16:0x[a-z0-9]*]] <line:14:3, col:10>
+// C-NEXT: |     `-IntegerLiteral [[ADDR_17:0x[a-z0-9]*]] <col:10> 'int' 0
+// C-NEXT: |-FunctionDecl [[ADDR_18:0x[a-z0-9]*]] prev [[ADDR_4]] <line:18:1, line:20:1> line:18:5 used also_after 'int ({{.*}})'
+// C-NEXT: | |-CompoundStmt [[ADDR_19:0x[a-z0-9]*]] <col:22, line:20:1>
+// C-NEXT: | | `-ReturnStmt [[ADDR_20:0x[a-z0-9]*]] <line:19:3, col:10>
+// C-NEXT: | |   `-IntegerLiteral [[ADDR_21:0x[a-z0-9]*]] <col:10> 'int' 2
+// C-NEXT: | `-OMPDeclareVariantAttr [[ADDR_22:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(llvm)}
+// C-NEXT: |   `-DeclRefExpr [[ADDR_6]] <line:10:1> 'int ({{.*}})' Function [[ADDR_7]] 'also_after.SimpPllv' 'int ({{.*}})'
+// C-NEXT: `-FunctionDecl [[ADDR_23:0x[a-z0-9]*]] <line:22:1, line:28:1> line:22:5 main 'int ({{.*}})'
+// C-NEXT:   `-CompoundStmt [[ADDR_24:0x[a-z0-9]*]] <col:12, line:28:1>
+// C-NEXT:     `-ReturnStmt [[ADDR_25:0x[a-z0-9]*]] <line:24:3, line:27:25>
+// C-NEXT:       `-BinaryOperator [[ADDR_26:0x[a-z0-9]*]] <line:24:10, line:27:25> 'int' '+'
+// C-NEXT:         |-BinaryOperator [[ADDR_27:0x[a-z0-9]*]] <line:24:10, line:26:24> 'int' '+'
+// C-NEXT:         | |-BinaryOperator [[ADDR_28:0x[a-z0-9]*]] <line:24:10, line:25:24> 'int' '+'
+// C-NEXT:         | | |-PseudoObjectExpr [[ADDR_29:0x[a-z0-9]*]] <line:24:10, col:23> 'int'
+// C-NEXT:         | | | |-CallExpr [[ADDR_30:0x[a-z0-9]*]] <col:10, col:23> 'int'
+// C-NEXT:         | | | | `-ImplicitCastExpr [[ADDR_31:0x[a-z0-9]*]] <col:10, col:21> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// C-NEXT:         | | | |   `-ParenExpr [[ADDR_32:0x[a-z0-9]*]] <col:10, col:21> 'int ({{.*}})'
+// C-NEXT:         | | | |     `-DeclRefExpr [[ADDR_33:0x[a-z0-9]*]] <col:11> 'int ({{.*}})' Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// C-NEXT:         | | | `-CallExpr [[ADDR_34:0x[a-z0-9]*]] <line:10:1, line:24:23> 'int'
+// C-NEXT:         | | |   `-ImplicitCastExpr [[ADDR_35:0x[a-z0-9]*]] <line:10:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// C-NEXT:         | | |     `-DeclRefExpr [[ADDR_6]] <col:1> 'int ({{.*}})' Function [[ADDR_7]] 'also_after.SimpPllv' 'int ({{.*}})'
+// C-NEXT:         | | `-PseudoObjectExpr [[ADDR_36:0x[a-z0-9]*]] <line:25:10, col:24> 'int'
+// C-NEXT:         | |   |-CallExpr [[ADDR_37:0x[a-z0-9]*]] <col:10, col:24> 'int'
+// C-NEXT:         | |   | `-ImplicitCastExpr [[ADDR_38:0x[a-z0-9]*]] <col:10, col:22> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// C-NEXT:         | |   |   `-ParenExpr [[ADDR_39:0x[a-z0-9]*]] <col:10, col:22> 'int ({{.*}})'
+// C-NEXT:         | |   |     `-DeclRefExpr [[ADDR_40:0x[a-z0-9]*]] <col:11> 'int ({{.*}})' Function [[ADDR_11]] 'also_before' 'int ({{.*}})'
+// C-NEXT:         | |   `-CallExpr [[ADDR_41:0x[a-z0-9]*]] <line:13:1, line:25:24> 'int'
+// C-NEXT:         | |     `-ImplicitCastExpr [[ADDR_42:0x[a-z0-9]*]] <line:13:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// C-NEXT:         | |       `-DeclRefExpr [[ADDR_13]] <col:1> 'int ({{.*}})' Function [[ADDR_14]] 'also_before.SimpPllv' 'int ({{.*}})'
+// C-NEXT:         | `-PseudoObjectExpr [[ADDR_43:0x[a-z0-9]*]] <line:26:10, col:24> 'int'
+// C-NEXT:         |   |-CallExpr [[ADDR_44:0x[a-z0-9]*]] <col:10, col:24> 'int'
+// C-NEXT:         |   | `-ParenExpr [[ADDR_45:0x[a-z0-9]*]] <col:10, col:22> 'int (*)({{.*}})'
+// C-NEXT:         |   |   `-UnaryOperator [[ADDR_46:0x[a-z0-9]*]] <col:11, col:12> 'int (*)({{.*}})' prefix '&' cannot overflow
+// C-NEXT:         |   |     `-DeclRefExpr [[ADDR_47:0x[a-z0-9]*]] <col:12> 'int ({{.*}})' Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// C-NEXT:         |   `-CallExpr [[ADDR_48:0x[a-z0-9]*]] <line:10:1, line:26:24> 'int'
+// C-NEXT:         |     `-ImplicitCastExpr [[ADDR_49:0x[a-z0-9]*]] <line:10:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// C-NEXT:         |       `-DeclRefExpr [[ADDR_6]] <col:1> 'int ({{.*}})' Function [[ADDR_7]] 'also_after.SimpPllv' 'int ({{.*}})'
+// C-NEXT:         `-PseudoObjectExpr [[ADDR_50:0x[a-z0-9]*]] <line:27:10, col:25> 'int'
+// C-NEXT:           |-CallExpr [[ADDR_51:0x[a-z0-9]*]] <col:10, col:25> 'int'
+// C-NEXT:           | `-ParenExpr [[ADDR_52:0x[a-z0-9]*]] <col:10, col:23> 'int (*)({{.*}})'
+// C-NEXT:           |   `-UnaryOperator [[ADDR_53:0x[a-z0-9]*]] <col:11, col:12> 'int (*)({{.*}})' prefix '&' cannot overflow
+// C-NEXT:           |     `-DeclRefExpr [[ADDR_54:0x[a-z0-9]*]] <col:12> 'int ({{.*}})' Function [[ADDR_11]] 'also_before' 'int ({{.*}})'
+// C-NEXT:           `-CallExpr [[ADDR_55:0x[a-z0-9]*]] <line:13:1, line:27:25> 'int'
+// C-NEXT:             `-ImplicitCastExpr [[ADDR_56:0x[a-z0-9]*]] <line:13:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// C-NEXT:               `-DeclRefExpr [[ADDR_13]] <col:1> 'int ({{.*}})' Function [[ADDR_14]] 'also_before.SimpPllv' 'int ({{.*}})'
+
+// CXX:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})'
+// CXX-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] <col:23, line:7:1>
+// CXX-NEXT: |   `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] <line:6:3, col:10>
+// CXX-NEXT: |     `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] <col:10> 'int' 1
+// CXX-NEXT: |-FunctionDecl [[ADDR_4:0x[a-z0-9]*]] <line:10:1, col:20> col:5 used also_after 'int ({{.*}})'
+// CXX-NEXT: | `-OMPDeclareVariantAttr [[ADDR_5:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(llvm)}
+// CXX-NEXT: |   `-DeclRefExpr [[ADDR_6:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_7:0x[a-z0-9]*]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CXX-NEXT: |-FunctionDecl [[ADDR_7]] <col:1, line:12:1> line:10:1 also_after.SimpPllv 'int ({{.*}})'
+// CXX-NEXT: | `-CompoundStmt [[ADDR_8:0x[a-z0-9]*]] <col:22, line:12:1>
+// CXX-NEXT: |   `-ReturnStmt [[ADDR_9:0x[a-z0-9]*]] <line:11:3, col:10>
+// CXX-NEXT: |     `-IntegerLiteral [[ADDR_10:0x[a-z0-9]*]] <col:10> 'int' 0
+// CXX-NEXT: |-FunctionDecl [[CXX:0x[a-z0-9]*]] prev [[ADDR_0]] <line:13:1, col:21> col:5 used also_before 'int ({{.*}})'
+// CXX-NEXT: | `-OMPDeclareVariantAttr [[ADDR_12:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(llvm)}
+// CXX-NEXT: |   `-DeclRefExpr [[ADDR_13:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_14:0x[a-z0-9]*]] 'also_before.SimpPllv' 'int ({{.*}})'
+// CXX-NEXT: |-FunctionDecl [[ADDR_14]] <col:1, line:15:1> line:13:1 also_before.SimpPllv 'int ({{.*}})'
+// CXX-NEXT: | `-CompoundStmt [[ADDR_15:0x[a-z0-9]*]] <col:23, line:15:1>
+// CXX-NEXT: |   `-ReturnStmt [[ADDR_16:0x[a-z0-9]*]] <line:14:3, col:10>
+// CXX-NEXT: |     `-IntegerLiteral [[ADDR_17:0x[a-z0-9]*]] <col:10> 'int' 0
+// CXX-NEXT: |-FunctionDecl [[ADDR_18:0x[a-z0-9]*]] prev [[ADDR_4]] <line:18:1, line:20:1> line:18:5 used also_after 'int ({{.*}})'
+// CXX-NEXT: | |-CompoundStmt [[ADDR_19:0x[a-z0-9]*]] <col:22, line:20:1>
+// CXX-NEXT: | | `-ReturnStmt [[ADDR_20:0x[a-z0-9]*]] <line:19:3, col:10>
+// CXX-NEXT: | |   `-IntegerLiteral [[ADDR_21:0x[a-z0-9]*]] <col:10> 'int' 2
+// CXX-NEXT: | `-OMPDeclareVariantAttr [[ADDR_22:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(llvm)}
+// CXX-NEXT: |   `-DeclRefExpr [[ADDR_6]] <line:10:1> 'int ({{.*}})' Function [[ADDR_7]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CXX-NEXT: `-FunctionDecl [[ADDR_23:0x[a-z0-9]*]] <line:22:1, line:28:1> line:22:5 main 'int ({{.*}})'
+// CXX-NEXT:   `-CompoundStmt [[ADDR_24:0x[a-z0-9]*]] <col:12, line:28:1>
+// CXX-NEXT:     `-ReturnStmt [[ADDR_25:0x[a-z0-9]*]] <line:24:3, line:27:25>
+// CXX-NEXT:       `-BinaryOperator [[ADDR_26:0x[a-z0-9]*]] <line:24:10, line:27:25> 'int' '+'
+// CXX-NEXT:         |-BinaryOperator [[ADDR_27:0x[a-z0-9]*]] <line:24:10, line:26:24> 'int' '+'
+// CXX-NEXT:         | |-BinaryOperator [[ADDR_28:0x[a-z0-9]*]] <line:24:10, line:25:24> 'int' '+'
+// CXX-NEXT:         | | |-PseudoObjectExpr [[ADDR_29:0x[a-z0-9]*]] <line:24:10, col:23> 'int'
+// CXX-NEXT:         | | | |-CallExpr [[ADDR_30:0x[a-z0-9]*]] <col:10, col:23> 'int'
+// CXX-NEXT:         | | | | `-ImplicitCastExpr [[ADDR_31:0x[a-z0-9]*]] <col:10, col:21> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CXX-NEXT:         | | | |   `-ParenExpr [[ADDR_32:0x[a-z0-9]*]] <col:10, col:21> 'int ({{.*}})' lvalue
+// CXX-NEXT:         | | | |     `-DeclRefExpr [[ADDR_33:0x[a-z0-9]*]] <col:11> 'int ({{.*}})' {{.*}}Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// CXX-NEXT:         | | | `-CallExpr [[ADDR_34:0x[a-z0-9]*]] <line:10:1, line:24:23> 'int'
+// CXX-NEXT:         | | |   `-ImplicitCastExpr [[ADDR_35:0x[a-z0-9]*]] <line:10:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CXX-NEXT:         | | |     `-DeclRefExpr [[ADDR_6]] <col:1> 'int ({{.*}})' Function [[ADDR_7]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CXX-NEXT:         | | `-PseudoObjectExpr [[ADDR_36:0x[a-z0-9]*]] <line:25:10, col:24> 'int'
+// CXX-NEXT:         | |   |-CallExpr [[ADDR_37:0x[a-z0-9]*]] <col:10, col:24> 'int'
+// CXX-NEXT:         | |   | `-ImplicitCastExpr [[ADDR_38:0x[a-z0-9]*]] <col:10, col:22> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CXX-NEXT:         | |   |   `-ParenExpr [[ADDR_39:0x[a-z0-9]*]] <col:10, col:22> 'int ({{.*}})' lvalue
+// CXX-NEXT:         | |   |     `-DeclRefExpr [[ADDR_40:0x[a-z0-9]*]] <col:11> 'int ({{.*}})' {{.*}}Function [[CXX]] 'also_before' 'int ({{.*}})'
+// CXX-NEXT:         | |   `-CallExpr [[ADDR_41:0x[a-z0-9]*]] <line:13:1, line:25:24> 'int'
+// CXX-NEXT:         | |     `-ImplicitCastExpr [[ADDR_42:0x[a-z0-9]*]] <line:13:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CXX-NEXT:         | |       `-DeclRefExpr [[ADDR_13]] <col:1> 'int ({{.*}})' Function [[ADDR_14]] 'also_before.SimpPllv' 'int ({{.*}})'
+// CXX-NEXT:         | `-PseudoObjectExpr [[ADDR_43:0x[a-z0-9]*]] <line:26:10, col:24> 'int'
+// CXX-NEXT:         |   |-CallExpr [[ADDR_44:0x[a-z0-9]*]] <col:10, col:24> 'int'
+// CXX-NEXT:         |   | `-ParenExpr [[ADDR_45:0x[a-z0-9]*]] <col:10, col:22> 'int (*)({{.*}})'
+// CXX-NEXT:         |   |   `-UnaryOperator [[ADDR_46:0x[a-z0-9]*]] <col:11, col:12> 'int (*)({{.*}})' prefix '&' cannot overflow
+// CXX-NEXT:         |   |     `-DeclRefExpr [[ADDR_47:0x[a-z0-9]*]] <col:12> 'int ({{.*}})' {{.*}}Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// CXX-NEXT:         |   `-CallExpr [[ADDR_48:0x[a-z0-9]*]] <line:10:1, line:26:24> 'int'
+// CXX-NEXT:         |     `-ImplicitCastExpr [[ADDR_49:0x[a-z0-9]*]] <line:10:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CXX-NEXT:         |       `-DeclRefExpr [[ADDR_6]] <col:1> 'int ({{.*}})' Function [[ADDR_7]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CXX-NEXT:         `-PseudoObjectExpr [[ADDR_50:0x[a-z0-9]*]] <line:27:10, col:25> 'int'
+// CXX-NEXT:           |-CallExpr [[ADDR_51:0x[a-z0-9]*]] <col:10, col:25> 'int'
+// CXX-NEXT:           | `-ParenExpr [[ADDR_52:0x[a-z0-9]*]] <col:10, col:23> 'int (*)({{.*}})'
+// CXX-NEXT:           |   `-UnaryOperator [[ADDR_53:0x[a-z0-9]*]] <col:11, col:12> 'int (*)({{.*}})' prefix '&' cannot overflow
+// CXX-NEXT:           |     `-DeclRefExpr [[ADDR_54:0x[a-z0-9]*]] <col:12> 'int ({{.*}})' {{.*}}Function [[CXX]] 'also_before' 'int ({{.*}})'
+// CXX-NEXT:           `-CallExpr [[ADDR_55:0x[a-z0-9]*]] <line:13:1, line:27:25> 'int'
+// CXX-NEXT:             `-ImplicitCastExpr [[ADDR_56:0x[a-z0-9]*]] <line:13:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CXX-NEXT:               `-DeclRefExpr [[ADDR_13]] <col:1> 'int ({{.*}})' Function [[ADDR_14]] 'also_before.SimpPllv' 'int ({{.*}})'
diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c
new file mode 100644
--- /dev/null
+++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s       | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s
+// expected-no-diagnostics
+
+int also_before(void) {
+  return 0;
+}
+
+#pragma omp begin declare variant match(implementation={vendor(ibm)})
+int also_after(void) {
+  return 1;
+}
+int also_before(void) {
+  return 2;
+}
+#pragma omp end declare variant
+
+int also_after(void) {
+  return 0;
+}
+
+int main() {
+  // Should return 0.
+  return also_after() + also_before();
+}
+
+// Make sure:
+//  - we see the specialization in the AST
+//  - we do use the original pointers for the calls as the variants are not applicable (this is not the ibm compiler).
+
+// CHECK:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] <col:23, line:7:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] <line:6:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: |-FunctionDecl [[ADDR_4:0x[a-z0-9]*]] <line:10:1, col:20> col:5 used also_after 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_5:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(ibm)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_6:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_7:0x[a-z0-9]*]] 'also_after.SimpPibm' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_7]] <col:1, line:12:1> line:10:1 also_after.SimpPibm 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_8:0x[a-z0-9]*]] <col:22, line:12:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_9:0x[a-z0-9]*]] <line:11:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_10:0x[a-z0-9]*]] <col:10> 'int' 1
+// CHECK-NEXT: |-FunctionDecl [[ADDR_11:0x[a-z0-9]*]] prev [[ADDR_0]] <line:13:1, col:21> col:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_12:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(ibm)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_13:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_14:0x[a-z0-9]*]] 'also_before.SimpPibm' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_14]] <col:1, line:15:1> line:13:1 also_before.SimpPibm 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_15:0x[a-z0-9]*]] <col:23, line:15:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_16:0x[a-z0-9]*]] <line:14:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_17:0x[a-z0-9]*]] <col:10> 'int' 2
+// CHECK-NEXT: |-FunctionDecl [[ADDR_18:0x[a-z0-9]*]] prev [[ADDR_4]] <line:18:1, line:20:1> line:18:5 used also_after 'int ({{.*}})'
+// CHECK-NEXT: | |-CompoundStmt [[ADDR_19:0x[a-z0-9]*]] <col:22, line:20:1>
+// CHECK-NEXT: | | `-ReturnStmt [[ADDR_20:0x[a-z0-9]*]] <line:19:3, col:10>
+// CHECK-NEXT: | |   `-IntegerLiteral [[ADDR_21:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_22:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(ibm)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_6]] <line:10:1> 'int ({{.*}})' Function [[ADDR_7]] 'also_after.SimpPibm' 'int ({{.*}})'
+// CHECK-NEXT: `-FunctionDecl [[ADDR_23:0x[a-z0-9]*]] <line:22:1, line:25:1> line:22:5 main 'int ({{.*}})'
+// CHECK-NEXT:   `-CompoundStmt [[ADDR_24:0x[a-z0-9]*]] <col:12, line:25:1>
+// CHECK-NEXT:     `-ReturnStmt [[ADDR_25:0x[a-z0-9]*]] <line:24:3, col:37>
+// CHECK-NEXT:       `-BinaryOperator [[ADDR_26:0x[a-z0-9]*]] <col:10, col:37> 'int' '+'
+// CHECK-NEXT:         |-CallExpr [[ADDR_27:0x[a-z0-9]*]] <col:10, col:21> 'int'
+// CHECK-NEXT:         | `-ImplicitCastExpr [[ADDR_28:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:         |   `-DeclRefExpr [[ADDR_29:0x[a-z0-9]*]] <col:10> 'int ({{.*}})' {{.*}}Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// CHECK-NEXT:         `-CallExpr [[ADDR_30:0x[a-z0-9]*]] <col:25, col:37> 'int'
+// CHECK-NEXT:           `-ImplicitCastExpr [[ADDR_31:0x[a-z0-9]*]] <col:25> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:             `-DeclRefExpr [[ADDR_32:0x[a-z0-9]*]] <col:25> 'int ({{.*}})' {{.*}}Function [[ADDR_11]] 'also_before' 'int ({{.*}})'
diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_7.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_7.c
new file mode 100644
--- /dev/null
+++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_7.c
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s       | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s
+// expected-no-diagnostics
+
+int OK_1(void);
+
+#pragma omp begin declare variant match(implementation={vendor(intel)})
+int OK_1(void) {
+  return 1;
+}
+int OK_2(void) {
+  return 1;
+}
+int not_OK(void) {
+  return 1;
+}
+int OK_3(void) {
+  return 1;
+}
+#pragma omp end declare variant
+
+int OK_3(void);
+
+int test() {
+  // Should cause an error due to not_OK()
+  return OK_1() + not_OK() + OK_3();
+}
+
+// Make sure:
+//  - we see a single error for `not_OK`
+//  - we do not see errors for OK_{1,2,3}
+//  FIXME: We actually do not see there error here.
+//         This case is unlikely to happen in practise and hard to diagnose during SEMA.
+//         We will issue an error during code generation instead. This is similar to the
+//         diagnosis in other multi-versioning schemes.
+
+// CHECK:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, col:14> col:5 used OK_1 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_1:0x[a-z0-9]*]] prev [[ADDR_0]] <line:8:1, col:14> col:5 used OK_1 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_2:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(intel)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_3:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_4:0x[a-z0-9]*]] 'OK_1.SimpPint' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_4]] <col:1, line:10:1> line:8:1 OK_1.SimpPint 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_5:0x[a-z0-9]*]] <col:16, line:10:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_6:0x[a-z0-9]*]] <line:9:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_7:0x[a-z0-9]*]] <col:10> 'int' 1
+// CHECK-NEXT: |-FunctionDecl [[ADDR_8:0x[a-z0-9]*]] <line:11:1, col:14> col:5 OK_2 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_9:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(intel)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_10:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_11:0x[a-z0-9]*]] 'OK_2.SimpPint' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_11]] <col:1, line:13:1> line:11:1 OK_2.SimpPint 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_12:0x[a-z0-9]*]] <col:16, line:13:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_13:0x[a-z0-9]*]] <line:12:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_14:0x[a-z0-9]*]] <col:10> 'int' 1
+// CHECK-NEXT: |-FunctionDecl [[ADDR_15:0x[a-z0-9]*]] <line:14:1, col:16> col:5 used not_OK 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_16:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(intel)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_17:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_18:0x[a-z0-9]*]] 'not_OK.SimpPint' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_18]] <col:1, line:16:1> line:14:1 not_OK.SimpPint 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_19:0x[a-z0-9]*]] <col:18, line:16:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_20:0x[a-z0-9]*]] <line:15:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_21:0x[a-z0-9]*]] <col:10> 'int' 1
+// CHECK-NEXT: |-FunctionDecl [[ADDR_22:0x[a-z0-9]*]] <line:17:1, col:14> col:5 used OK_3 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_23:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(intel)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_24:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_25:0x[a-z0-9]*]] 'OK_3.SimpPint' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_25]] <col:1, line:19:1> line:17:1 OK_3.SimpPint 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_26:0x[a-z0-9]*]] <col:16, line:19:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_27:0x[a-z0-9]*]] <line:18:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_28:0x[a-z0-9]*]] <col:10> 'int' 1
+// CHECK-NEXT: |-FunctionDecl [[ADDR_29:0x[a-z0-9]*]] prev [[ADDR_22]] <line:22:1, col:14> col:5 used OK_3 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_30:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(intel)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_24]] <line:17:1> 'int ({{.*}})' Function [[ADDR_25]] 'OK_3.SimpPint' 'int ({{.*}})'
+// CHECK-NEXT: `-FunctionDecl [[ADDR_31:0x[a-z0-9]*]] <line:24:1, line:27:1> line:24:5 test 'int ({{.*}})'
+// CHECK-NEXT:   `-CompoundStmt [[ADDR_32:0x[a-z0-9]*]] <col:12, line:27:1>
+// CHECK-NEXT:     `-ReturnStmt [[ADDR_33:0x[a-z0-9]*]] <line:26:3, col:35>
+// CHECK-NEXT:       `-BinaryOperator [[ADDR_34:0x[a-z0-9]*]] <col:10, col:35> 'int' '+'
+// CHECK-NEXT:         |-BinaryOperator [[ADDR_35:0x[a-z0-9]*]] <col:10, col:26> 'int' '+'
+// CHECK-NEXT:         | |-CallExpr [[ADDR_36:0x[a-z0-9]*]] <col:10, col:15> 'int'
+// CHECK-NEXT:         | | `-ImplicitCastExpr [[ADDR_37:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:         | |   `-DeclRefExpr [[ADDR_38:0x[a-z0-9]*]] <col:10> 'int ({{.*}})' {{.*}}Function [[ADDR_1]] 'OK_1' 'int ({{.*}})'
+// CHECK-NEXT:         | `-CallExpr [[ADDR_39:0x[a-z0-9]*]] <col:19, col:26> 'int'
+// CHECK-NEXT:         |   `-ImplicitCastExpr [[ADDR_40:0x[a-z0-9]*]] <col:19> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:         |     `-DeclRefExpr [[ADDR_41:0x[a-z0-9]*]] <col:19> 'int ({{.*}})' {{.*}}Function [[ADDR_15]] 'not_OK' 'int ({{.*}})'
+// CHECK-NEXT:         `-CallExpr [[ADDR_42:0x[a-z0-9]*]] <col:30, col:35> 'int'
+// CHECK-NEXT:           `-ImplicitCastExpr [[ADDR_43:0x[a-z0-9]*]] <col:30> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:             `-DeclRefExpr [[ADDR_44:0x[a-z0-9]*]] <col:30> 'int ({{.*}})' {{.*}}Function [[ADDR_29]] 'OK_3' 'int ({{.*}})'
diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_8.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_8.c
new file mode 100644
--- /dev/null
+++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_8.c
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s       | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s
+// expected-no-diagnostics
+
+#pragma omp begin declare variant match(device={kind(cpu)})
+int also_before(void) {
+  return 1;
+}
+#pragma omp end declare variant
+
+#pragma omp begin declare variant match(implementation={vendor(score(0):llvm)})
+int also_after(void) {
+  return 0;
+}
+#pragma omp end declare variant
+#pragma omp begin declare variant match(implementation={vendor(score(100):llvm)})
+int also_before(void) {
+  return 0;
+}
+#pragma omp end declare variant
+
+int also_after(void) {
+  return 2;
+}
+
+int test() {
+  // Should return 0.
+  return also_after() + also_before();
+}
+
+// Make sure:
+//  - we do see the ast nodes for the cpu kind
+//  - we do see the ast nodes for the llvm vendor
+//  - we pick the right callees
+
+// CHECK:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, col:21> col:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_1:0x[a-z0-9]*]] <<invalid sloc>> Implicit device={kind(cpu)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_2:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_3:0x[a-z0-9]*]] 'also_before.SdevPcpu' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_3]] <col:1, line:8:1> line:6:1 also_before.SdevPcpu 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_4:0x[a-z0-9]*]] <col:23, line:8:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_5:0x[a-z0-9]*]] <line:7:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_6:0x[a-z0-9]*]] <col:10> 'int' 1
+// CHECK-NEXT: |-FunctionDecl [[ADDR_7:0x[a-z0-9]*]] <line:12:1, col:20> col:5 used also_after 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_8:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(score(0): llvm)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_9:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_10:0x[a-z0-9]*]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_10]] <col:1, line:14:1> line:12:1 also_after.SimpPllv 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_11:0x[a-z0-9]*]] <col:22, line:14:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_12:0x[a-z0-9]*]] <line:13:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_13:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: |-FunctionDecl [[ADDR_14:0x[a-z0-9]*]] prev [[ADDR_0]] <line:17:1, col:21> col:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: | |-OMPDeclareVariantAttr [[ADDR_15:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit device={kind(cpu)}
+// CHECK-NEXT: | | `-DeclRefExpr [[ADDR_2]] <line:6:1> 'int ({{.*}})' Function [[ADDR_3]] 'also_before.SdevPcpu' 'int ({{.*}})'
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_16:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(score(100): llvm)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_17:0x[a-z0-9]*]] <line:17:1> 'int ({{.*}})' Function [[ADDR_18:0x[a-z0-9]*]] 'also_before.SimpPllv' 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_18]] <col:1, line:19:1> line:17:1 also_before.SimpPllv 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_19:0x[a-z0-9]*]] <col:23, line:19:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_20:0x[a-z0-9]*]] <line:18:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_21:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: |-FunctionDecl [[ADDR_22:0x[a-z0-9]*]] prev [[ADDR_7]] <line:22:1, line:24:1> line:22:5 used also_after 'int ({{.*}})'
+// CHECK-NEXT: | |-CompoundStmt [[ADDR_23:0x[a-z0-9]*]] <col:22, line:24:1>
+// CHECK-NEXT: | | `-ReturnStmt [[ADDR_24:0x[a-z0-9]*]] <line:23:3, col:10>
+// CHECK-NEXT: | |   `-IntegerLiteral [[ADDR_25:0x[a-z0-9]*]] <col:10> 'int' 2
+// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_26:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(score(0): llvm)}
+// CHECK-NEXT: |   `-DeclRefExpr [[ADDR_9]] <line:12:1> 'int ({{.*}})' Function [[ADDR_10]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CHECK-NEXT: `-FunctionDecl [[ADDR_27:0x[a-z0-9]*]] <line:26:1, line:29:1> line:26:5 test 'int ({{.*}})'
+// CHECK-NEXT:   `-CompoundStmt [[ADDR_28:0x[a-z0-9]*]] <col:12, line:29:1>
+// CHECK-NEXT:     `-ReturnStmt [[ADDR_29:0x[a-z0-9]*]] <line:28:3, col:37>
+// CHECK-NEXT:       `-BinaryOperator [[ADDR_30:0x[a-z0-9]*]] <col:10, col:37> 'int' '+'
+// CHECK-NEXT:         |-PseudoObjectExpr [[ADDR_31:0x[a-z0-9]*]] <col:10, col:21> 'int'
+// CHECK-NEXT:         | |-CallExpr [[ADDR_32:0x[a-z0-9]*]] <col:10, col:21> 'int'
+// CHECK-NEXT:         | | `-ImplicitCastExpr [[ADDR_33:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:         | |   `-DeclRefExpr [[ADDR_34:0x[a-z0-9]*]] <col:10> 'int ({{.*}})' {{.*}}Function [[ADDR_22]] 'also_after' 'int ({{.*}})'
+// CHECK-NEXT:         | `-CallExpr [[ADDR_35:0x[a-z0-9]*]] <line:12:1, line:28:21> 'int'
+// CHECK-NEXT:         |   `-ImplicitCastExpr [[ADDR_36:0x[a-z0-9]*]] <line:12:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:         |     `-DeclRefExpr [[ADDR_9]] <col:1> 'int ({{.*}})' Function [[ADDR_10]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CHECK-NEXT:         `-PseudoObjectExpr [[ADDR_37:0x[a-z0-9]*]] <line:28:25, col:37> 'int'
+// CHECK-NEXT:           |-CallExpr [[ADDR_38:0x[a-z0-9]*]] <col:25, col:37> 'int'
+// CHECK-NEXT:           | `-ImplicitCastExpr [[ADDR_39:0x[a-z0-9]*]] <col:25> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:           |   `-DeclRefExpr [[ADDR_40:0x[a-z0-9]*]] <col:25> 'int ({{.*}})' {{.*}}Function [[ADDR_14]] 'also_before' 'int ({{.*}})'
+// CHECK-NEXT:           `-CallExpr [[ADDR_41:0x[a-z0-9]*]] <line:17:1, line:28:37> 'int'
+// CHECK-NEXT:             `-ImplicitCastExpr [[ADDR_42:0x[a-z0-9]*]] <line:17:1> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:               `-DeclRefExpr [[ADDR_17]] <col:1> 'int ({{.*}})' Function [[ADDR_18]] 'also_before.SimpPllv' 'int ({{.*}})'
diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_9.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_9.c
new file mode 100644
--- /dev/null
+++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_9.c
@@ -0,0 +1,184 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s       | FileCheck %s --check-prefix=C
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s --check-prefix=CXX
+// expected-no-diagnostics
+
+int also_before(void) {
+  return 0;
+}
+
+#pragma omp begin declare variant match(implementation={vendor(llvm)})
+int also_after(void) {
+  return 1;
+}
+int also_before(void) {
+  return 2;
+}
+#pragma omp end declare variant
+
+int also_after(void) {
+  return 0;
+}
+
+void foo();
+typedef int(*fd)(void);
+int main() {
+  // Should return 0.
+  fd fns[2];
+  fns[0] = &also_before;
+  fns[1] = also_after;
+  return (foo(), also_after)() +
+         (fns[0])() +
+         (1[fns])();
+}
+
+// Make sure:
+//  - we see the specialization in the AST
+//  - we pick the right callees
+
+// C:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})'
+// C-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] <col:23, line:7:1>
+// C-NEXT: |   `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] <line:6:3, col:10>
+// C-NEXT: |     `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] <col:10> 'int' 0
+// C-NEXT: |-FunctionDecl [[ADDR_4:0x[a-z0-9]*]] <line:10:1, col:20> col:5 used also_after 'int ({{.*}})'
+// C-NEXT: | `-OMPDeclareVariantAttr [[ADDR_5:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(llvm)}
+// C-NEXT: |   `-DeclRefExpr [[ADDR_6:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_7:0x[a-z0-9]*]] 'also_after.SimpPllv' 'int ({{.*}})'
+// C-NEXT: |-FunctionDecl [[ADDR_7]] <col:1, line:12:1> line:10:1 also_after.SimpPllv 'int ({{.*}})'
+// C-NEXT: | `-CompoundStmt [[ADDR_8:0x[a-z0-9]*]] <col:22, line:12:1>
+// C-NEXT: |   `-ReturnStmt [[ADDR_9:0x[a-z0-9]*]] <line:11:3, col:10>
+// C-NEXT: |     `-IntegerLiteral [[ADDR_10:0x[a-z0-9]*]] <col:10> 'int' 1
+// C-NEXT: |-FunctionDecl [[ADDR_11:0x[a-z0-9]*]] prev [[ADDR_0]] <line:13:1, col:21> col:5 used also_before 'int ({{.*}})'
+// C-NEXT: | `-OMPDeclareVariantAttr [[ADDR_12:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(llvm)}
+// C-NEXT: |   `-DeclRefExpr [[ADDR_13:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_14:0x[a-z0-9]*]] 'also_before.SimpPllv' 'int ({{.*}})'
+// C-NEXT: |-FunctionDecl [[ADDR_14]] <col:1, line:15:1> line:13:1 also_before.SimpPllv 'int ({{.*}})'
+// C-NEXT: | `-CompoundStmt [[ADDR_15:0x[a-z0-9]*]] <col:23, line:15:1>
+// C-NEXT: |   `-ReturnStmt [[ADDR_16:0x[a-z0-9]*]] <line:14:3, col:10>
+// C-NEXT: |     `-IntegerLiteral [[ADDR_17:0x[a-z0-9]*]] <col:10> 'int' 2
+// C-NEXT: |-FunctionDecl [[ADDR_18:0x[a-z0-9]*]] prev [[ADDR_4]] <line:18:1, line:20:1> line:18:5 used also_after 'int ({{.*}})'
+// C-NEXT: | |-CompoundStmt [[ADDR_19:0x[a-z0-9]*]] <col:22, line:20:1>
+// C-NEXT: | | `-ReturnStmt [[ADDR_20:0x[a-z0-9]*]] <line:19:3, col:10>
+// C-NEXT: | |   `-IntegerLiteral [[ADDR_21:0x[a-z0-9]*]] <col:10> 'int' 0
+// C-NEXT: | `-OMPDeclareVariantAttr [[ADDR_22:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(llvm)}
+// C-NEXT: |   `-DeclRefExpr [[ADDR_6]] <line:10:1> 'int ({{.*}})' Function [[ADDR_7]] 'also_after.SimpPllv' 'int ({{.*}})'
+// C-NEXT: |-FunctionDecl [[ADDR_23:0x[a-z0-9]*]] <line:22:1, col:10> col:6 used foo 'void ({{.*}})'
+// C-NEXT: |-TypedefDecl [[ADDR_24:0x[a-z0-9]*]] <line:23:1, col:22> col:14 referenced fd 'int (*)({{.*}})'
+// C-NEXT: | `-PointerType [[ADDR_25:0x[a-z0-9]*]] 'int (*)({{.*}})'
+// C-NEXT: |   `-ParenType [[ADDR_26:0x[a-z0-9]*]] 'int ({{.*}})' sugar
+// C-NEXT: |     `-FunctionProtoType [[ADDR_27:0x[a-z0-9]*]] 'int ({{.*}})' cdecl
+// C-NEXT: |       `-BuiltinType [[ADDR_28:0x[a-z0-9]*]] 'int'
+// C-NEXT: `-FunctionDecl [[ADDR_29:0x[a-z0-9]*]] <line:24:1, line:32:1> line:24:5 main 'int ({{.*}})'
+// C-NEXT:   `-CompoundStmt [[ADDR_30:0x[a-z0-9]*]] <col:12, line:32:1>
+// C-NEXT:     |-DeclStmt [[ADDR_31:0x[a-z0-9]*]] <line:26:3, col:12>
+// C-NEXT:     | `-VarDecl [[ADDR_32:0x[a-z0-9]*]] <col:3, col:11> col:6 used fns 'fd [2]'
+// C-NEXT:     |-BinaryOperator [[ADDR_33:0x[a-z0-9]*]] <line:27:3, col:13> 'fd':'int (*)({{.*}})' '='
+// C-NEXT:     | |-ArraySubscriptExpr [[ADDR_34:0x[a-z0-9]*]] <col:3, col:8> 'fd':'int (*)({{.*}})' lvalue
+// C-NEXT:     | | |-ImplicitCastExpr [[ADDR_35:0x[a-z0-9]*]] <col:3> 'fd *' <ArrayToPointerDecay>
+// C-NEXT:     | | | `-DeclRefExpr [[ADDR_36:0x[a-z0-9]*]] <col:3> 'fd [2]' {{.*}}Var [[ADDR_32]] 'fns' 'fd [2]'
+// C-NEXT:     | | `-IntegerLiteral [[ADDR_37:0x[a-z0-9]*]] <col:7> 'int' 0
+// C-NEXT:     | `-UnaryOperator [[ADDR_38:0x[a-z0-9]*]] <col:12, col:13> 'int (*)({{.*}})' prefix '&' cannot overflow
+// C-NEXT:     |   `-DeclRefExpr [[ADDR_39:0x[a-z0-9]*]] <col:13> 'int ({{.*}})' Function [[ADDR_11]] 'also_before' 'int ({{.*}})'
+// C-NEXT:     |-BinaryOperator [[ADDR_40:0x[a-z0-9]*]] <line:28:3, col:12> 'fd':'int (*)({{.*}})' '='
+// C-NEXT:     | |-ArraySubscriptExpr [[ADDR_41:0x[a-z0-9]*]] <col:3, col:8> 'fd':'int (*)({{.*}})' lvalue
+// C-NEXT:     | | |-ImplicitCastExpr [[ADDR_42:0x[a-z0-9]*]] <col:3> 'fd *' <ArrayToPointerDecay>
+// C-NEXT:     | | | `-DeclRefExpr [[ADDR_43:0x[a-z0-9]*]] <col:3> 'fd [2]' {{.*}}Var [[ADDR_32]] 'fns' 'fd [2]'
+// C-NEXT:     | | `-IntegerLiteral [[ADDR_44:0x[a-z0-9]*]] <col:7> 'int' 1
+// C-NEXT:     | `-ImplicitCastExpr [[ADDR_45:0x[a-z0-9]*]] <col:12> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// C-NEXT:     |   `-DeclRefExpr [[ADDR_46:0x[a-z0-9]*]] <col:12> 'int ({{.*}})' Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// C-NEXT:     `-ReturnStmt [[ADDR_47:0x[a-z0-9]*]] <line:29:3, line:31:19>
+// C-NEXT:       `-BinaryOperator [[ADDR_48:0x[a-z0-9]*]] <line:29:10, line:31:19> 'int' '+'
+// C-NEXT:         |-BinaryOperator [[ADDR_49:0x[a-z0-9]*]] <line:29:10, line:30:19> 'int' '+'
+// C-NEXT:         | |-CallExpr [[ADDR_50:0x[a-z0-9]*]] <line:29:10, col:30> 'int'
+// C-NEXT:         | | `-ParenExpr [[ADDR_51:0x[a-z0-9]*]] <col:10, col:28> 'int (*)({{.*}})'
+// C-NEXT:         | |   `-BinaryOperator [[ADDR_52:0x[a-z0-9]*]] <col:11, col:18> 'int (*)({{.*}})' ','
+// C-NEXT:         | |     |-CallExpr [[ADDR_53:0x[a-z0-9]*]] <col:11, col:15> 'void'
+// C-NEXT:         | |     | `-ImplicitCastExpr [[ADDR_54:0x[a-z0-9]*]] <col:11> 'void (*)({{.*}})' <FunctionToPointerDecay>
+// C-NEXT:         | |     |   `-DeclRefExpr [[ADDR_55:0x[a-z0-9]*]] <col:11> 'void ({{.*}})' Function [[ADDR_23]] 'foo' 'void ({{.*}})'
+// C-NEXT:         | |     `-ImplicitCastExpr [[ADDR_56:0x[a-z0-9]*]] <col:18> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// C-NEXT:         | |       `-DeclRefExpr [[ADDR_57:0x[a-z0-9]*]] <col:18> 'int ({{.*}})' Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// C-NEXT:         | `-CallExpr [[ADDR_58:0x[a-z0-9]*]] <line:30:10, col:19> 'int'
+// C-NEXT:         |   `-ImplicitCastExpr [[ADDR_59:0x[a-z0-9]*]] <col:10, col:17> 'fd':'int (*)({{.*}})' <LValueToRValue>
+// C-NEXT:         |     `-ParenExpr [[ADDR_60:0x[a-z0-9]*]] <col:10, col:17> 'fd':'int (*)({{.*}})' lvalue
+// C-NEXT:         |       `-ArraySubscriptExpr [[ADDR_61:0x[a-z0-9]*]] <col:11, col:16> 'fd':'int (*)({{.*}})' lvalue
+// C-NEXT:         |         |-ImplicitCastExpr [[ADDR_62:0x[a-z0-9]*]] <col:11> 'fd *' <ArrayToPointerDecay>
+// C-NEXT:         |         | `-DeclRefExpr [[ADDR_63:0x[a-z0-9]*]] <col:11> 'fd [2]' {{.*}}Var [[ADDR_32]] 'fns' 'fd [2]'
+// C-NEXT:         |         `-IntegerLiteral [[ADDR_64:0x[a-z0-9]*]] <col:15> 'int' 0
+// C-NEXT:         `-CallExpr [[ADDR_65:0x[a-z0-9]*]] <line:31:10, col:19> 'int'
+// C-NEXT:           `-ImplicitCastExpr [[ADDR_66:0x[a-z0-9]*]] <col:10, col:17> 'fd':'int (*)({{.*}})' <LValueToRValue>
+// C-NEXT:             `-ParenExpr [[ADDR_67:0x[a-z0-9]*]] <col:10, col:17> 'fd':'int (*)({{.*}})' lvalue
+// C-NEXT:               `-ArraySubscriptExpr [[ADDR_68:0x[a-z0-9]*]] <col:11, col:16> 'fd':'int (*)({{.*}})' lvalue
+// C-NEXT:                 |-IntegerLiteral [[ADDR_69:0x[a-z0-9]*]] <col:11> 'int' 1
+// C-NEXT:                 `-ImplicitCastExpr [[ADDR_70:0x[a-z0-9]*]] <col:13> 'fd *' <ArrayToPointerDecay>
+// C-NEXT:                   `-DeclRefExpr [[ADDR_71:0x[a-z0-9]*]] <col:13> 'fd [2]' {{.*}}Var [[ADDR_32]] 'fns' 'fd [2]'
+
+// CXX:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})'
+// CXX-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] <col:23, line:7:1>
+// CXX-NEXT: |   `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] <line:6:3, col:10>
+// CXX-NEXT: |     `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] <col:10> 'int' 0
+// CXX-NEXT: |-FunctionDecl [[ADDR_4:0x[a-z0-9]*]] <line:10:1, col:20> col:5 used also_after 'int ({{.*}})'
+// CXX-NEXT: | `-OMPDeclareVariantAttr [[ADDR_5:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(llvm)}
+// CXX-NEXT: |   `-DeclRefExpr [[ADDR_6:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_7:0x[a-z0-9]*]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CXX-NEXT: |-FunctionDecl [[ADDR_7]] <col:1, line:12:1> line:10:1 also_after.SimpPllv 'int ({{.*}})'
+// CXX-NEXT: | `-CompoundStmt [[ADDR_8:0x[a-z0-9]*]] <col:22, line:12:1>
+// CXX-NEXT: |   `-ReturnStmt [[ADDR_9:0x[a-z0-9]*]] <line:11:3, col:10>
+// CXX-NEXT: |     `-IntegerLiteral [[ADDR_10:0x[a-z0-9]*]] <col:10> 'int' 1
+// CXX-NEXT: |-FunctionDecl [[ADDR_11:0x[a-z0-9]*]] prev [[ADDR_0]] <line:13:1, col:21> col:5 used also_before 'int ({{.*}})'
+// CXX-NEXT: | `-OMPDeclareVariantAttr [[ADDR_12:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(llvm)}
+// CXX-NEXT: |   `-DeclRefExpr [[ADDR_13:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_14:0x[a-z0-9]*]] 'also_before.SimpPllv' 'int ({{.*}})'
+// CXX-NEXT: |-FunctionDecl [[ADDR_14]] <col:1, line:15:1> line:13:1 also_before.SimpPllv 'int ({{.*}})'
+// CXX-NEXT: | `-CompoundStmt [[ADDR_15:0x[a-z0-9]*]] <col:23, line:15:1>
+// CXX-NEXT: |   `-ReturnStmt [[ADDR_16:0x[a-z0-9]*]] <line:14:3, col:10>
+// CXX-NEXT: |     `-IntegerLiteral [[ADDR_17:0x[a-z0-9]*]] <col:10> 'int' 2
+// CXX-NEXT: |-FunctionDecl [[ADDR_18:0x[a-z0-9]*]] prev [[ADDR_4]] <line:18:1, line:20:1> line:18:5 used also_after 'int ({{.*}})'
+// CXX-NEXT: | |-CompoundStmt [[ADDR_19:0x[a-z0-9]*]] <col:22, line:20:1>
+// CXX-NEXT: | | `-ReturnStmt [[ADDR_20:0x[a-z0-9]*]] <line:19:3, col:10>
+// CXX-NEXT: | |   `-IntegerLiteral [[ADDR_21:0x[a-z0-9]*]] <col:10> 'int' 0
+// CXX-NEXT: | `-OMPDeclareVariantAttr [[ADDR_22:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(llvm)}
+// CXX-NEXT: |   `-DeclRefExpr [[ADDR_6]] <line:10:1> 'int ({{.*}})' Function [[ADDR_7]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CXX-NEXT: |-FunctionDecl [[ADDR_23:0x[a-z0-9]*]] <line:22:1, col:10> col:6 used foo 'void ({{.*}})'
+// CXX-NEXT: |-TypedefDecl [[ADDR_24:0x[a-z0-9]*]] <line:23:1, col:22> col:14 referenced fd 'int (*)({{.*}})'
+// CXX-NEXT: | `-PointerType [[ADDR_25:0x[a-z0-9]*]] 'int (*)({{.*}})'
+// CXX-NEXT: |   `-ParenType [[ADDR_26:0x[a-z0-9]*]] 'int ({{.*}})' sugar
+// CXX-NEXT: |     `-FunctionProtoType [[ADDR_27:0x[a-z0-9]*]] 'int ({{.*}})' cdecl
+// CXX-NEXT: |       `-BuiltinType [[ADDR_28:0x[a-z0-9]*]] 'int'
+// CXX-NEXT: `-FunctionDecl [[ADDR_29:0x[a-z0-9]*]] <line:24:1, line:32:1> line:24:5 main 'int ({{.*}})'
+// CXX-NEXT:   `-CompoundStmt [[ADDR_30:0x[a-z0-9]*]] <col:12, line:32:1>
+// CXX-NEXT:     |-DeclStmt [[ADDR_31:0x[a-z0-9]*]] <line:26:3, col:12>
+// CXX-NEXT:     | `-VarDecl [[ADDR_32:0x[a-z0-9]*]] <col:3, col:11> col:6 used fns 'fd [2]'
+// CXX-NEXT:     |-BinaryOperator [[ADDR_33:0x[a-z0-9]*]] <line:27:3, col:13> 'fd':'int (*)({{.*}})' {{.*}}'='
+// CXX-NEXT:     | |-ArraySubscriptExpr [[ADDR_34:0x[a-z0-9]*]] <col:3, col:8> 'fd':'int (*)({{.*}})' lvalue
+// CXX-NEXT:     | | |-ImplicitCastExpr [[ADDR_35:0x[a-z0-9]*]] <col:3> 'fd *' <ArrayToPointerDecay>
+// CXX-NEXT:     | | | `-DeclRefExpr [[ADDR_36:0x[a-z0-9]*]] <col:3> 'fd [2]' {{.*}}Var [[ADDR_32]] 'fns' 'fd [2]'
+// CXX-NEXT:     | | `-IntegerLiteral [[ADDR_37:0x[a-z0-9]*]] <col:7> 'int' 0
+// CXX-NEXT:     | `-UnaryOperator [[ADDR_38:0x[a-z0-9]*]] <col:12, col:13> 'int (*)({{.*}})' prefix '&' cannot overflow
+// CXX-NEXT:     |   `-DeclRefExpr [[ADDR_39:0x[a-z0-9]*]] <col:13> 'int ({{.*}})' {{.*}}Function [[ADDR_11]] 'also_before' 'int ({{.*}})'
+// CXX-NEXT:     |-BinaryOperator [[ADDR_40:0x[a-z0-9]*]] <line:28:3, col:12> 'fd':'int (*)({{.*}})' {{.*}}'='
+// CXX-NEXT:     | |-ArraySubscriptExpr [[ADDR_41:0x[a-z0-9]*]] <col:3, col:8> 'fd':'int (*)({{.*}})' lvalue
+// CXX-NEXT:     | | |-ImplicitCastExpr [[ADDR_42:0x[a-z0-9]*]] <col:3> 'fd *' <ArrayToPointerDecay>
+// CXX-NEXT:     | | | `-DeclRefExpr [[ADDR_43:0x[a-z0-9]*]] <col:3> 'fd [2]' {{.*}}Var [[ADDR_32]] 'fns' 'fd [2]'
+// CXX-NEXT:     | | `-IntegerLiteral [[ADDR_44:0x[a-z0-9]*]] <col:7> 'int' 1
+// CXX-NEXT:     | `-ImplicitCastExpr [[ADDR_45:0x[a-z0-9]*]] <col:12> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CXX-NEXT:     |   `-DeclRefExpr [[ADDR_46:0x[a-z0-9]*]] <col:12> 'int ({{.*}})' {{.*}}Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// CXX-NEXT:     `-ReturnStmt [[ADDR_47:0x[a-z0-9]*]] <line:29:3, line:31:19>
+// CXX-NEXT:       `-BinaryOperator [[ADDR_48:0x[a-z0-9]*]] <line:29:10, line:31:19> 'int' '+'
+// CXX-NEXT:         |-BinaryOperator [[ADDR_49:0x[a-z0-9]*]] <line:29:10, line:30:19> 'int' '+'
+// CXX-NEXT:         | |-CallExpr [[ADDR_50:0x[a-z0-9]*]] <line:29:10, col:30> 'int'
+// CXX-NEXT:         | | `-ImplicitCastExpr [[ADDR_51:0x[a-z0-9]*]] <col:10, col:28> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CXX-NEXT:         | |   `-ParenExpr [[ADDR_52:0x[a-z0-9]*]] <col:10, col:28> 'int ({{.*}})' lvalue
+// CXX-NEXT:         | |     `-BinaryOperator [[ADDR_53:0x[a-z0-9]*]] <col:11, col:18> 'int ({{.*}})' {{.*}}','
+// CXX-NEXT:         | |       |-CallExpr [[ADDR_54:0x[a-z0-9]*]] <col:11, col:15> 'void'
+// CXX-NEXT:         | |       | `-ImplicitCastExpr [[ADDR_55:0x[a-z0-9]*]] <col:11> 'void (*)({{.*}})' <FunctionToPointerDecay>
+// CXX-NEXT:         | |       |   `-DeclRefExpr [[ADDR_56:0x[a-z0-9]*]] <col:11> 'void ({{.*}})' {{.*}}Function [[ADDR_23]] 'foo' 'void ({{.*}})'
+// CXX-NEXT:         | |       `-DeclRefExpr [[ADDR_57:0x[a-z0-9]*]] <col:18> 'int ({{.*}})' {{.*}}Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// CXX-NEXT:         | `-CallExpr [[ADDR_58:0x[a-z0-9]*]] <line:30:10, col:19> 'int'
+// CXX-NEXT:         |   `-ImplicitCastExpr [[ADDR_59:0x[a-z0-9]*]] <col:10, col:17> 'fd':'int (*)({{.*}})' <LValueToRValue>
+// CXX-NEXT:         |     `-ParenExpr [[ADDR_60:0x[a-z0-9]*]] <col:10, col:17> 'fd':'int (*)({{.*}})' lvalue
+// CXX-NEXT:         |       `-ArraySubscriptExpr [[ADDR_61:0x[a-z0-9]*]] <col:11, col:16> 'fd':'int (*)({{.*}})' lvalue
+// CXX-NEXT:         |         |-ImplicitCastExpr [[ADDR_62:0x[a-z0-9]*]] <col:11> 'fd *' <ArrayToPointerDecay>
+// CXX-NEXT:         |         | `-DeclRefExpr [[ADDR_63:0x[a-z0-9]*]] <col:11> 'fd [2]' {{.*}}Var [[ADDR_32]] 'fns' 'fd [2]'
+// CXX-NEXT:         |         `-IntegerLiteral [[ADDR_64:0x[a-z0-9]*]] <col:15> 'int' 0
+// CXX-NEXT:         `-CallExpr [[ADDR_65:0x[a-z0-9]*]] <line:31:10, col:19> 'int'
+// CXX-NEXT:           `-ImplicitCastExpr [[ADDR_66:0x[a-z0-9]*]] <col:10, col:17> 'fd':'int (*)({{.*}})' <LValueToRValue>
+// CXX-NEXT:             `-ParenExpr [[ADDR_67:0x[a-z0-9]*]] <col:10, col:17> 'fd':'int (*)({{.*}})' lvalue
+// CXX-NEXT:               `-ArraySubscriptExpr [[ADDR_68:0x[a-z0-9]*]] <col:11, col:16> 'fd':'int (*)({{.*}})' lvalue
+// CXX-NEXT:                 |-IntegerLiteral [[ADDR_69:0x[a-z0-9]*]] <col:11> 'int' 1
+// CXX-NEXT:                 `-ImplicitCastExpr [[ADDR_70:0x[a-z0-9]*]] <col:13> 'fd *' <ArrayToPointerDecay>
+// CXX-NEXT:                   `-DeclRefExpr [[ADDR_71:0x[a-z0-9]*]] <col:13> 'fd [2]' {{.*}}Var [[ADDR_32]] 'fns' 'fd [2]'
diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_addr_1.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_addr_1.c
new file mode 100644
--- /dev/null
+++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_addr_1.c
@@ -0,0 +1,151 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s       | FileCheck %s --check-prefix=C
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s --check-prefix=CXX
+// expected-no-diagnostics
+
+int also_before(void) {
+  return 0;
+}
+
+#pragma omp begin declare variant match(implementation={vendor(llvm)})
+int also_after(void) {
+  return 1;
+}
+int also_before(void) {
+  return 2;
+}
+#pragma omp end declare variant
+
+int also_after(void) {
+  return 0;
+}
+
+int test(int (*fd)(void)) {
+  return fd();
+}
+int main() {
+  // Should return 0.
+  return test(also_after) +
+         test(also_before) +
+         test(&also_after) +
+         test(&also_before);
+}
+
+// Make sure:
+//  - we see the specialization in the AST
+//  - we pick the right callees
+
+// C:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})'
+// C-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] <col:23, line:7:1>
+// C-NEXT: |   `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] <line:6:3, col:10>
+// C-NEXT: |     `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] <col:10> 'int' 0
+// C-NEXT: |-FunctionDecl [[ADDR_4:0x[a-z0-9]*]] <line:10:1, col:20> col:5 used also_after 'int ({{.*}})'
+// C-NEXT: | `-OMPDeclareVariantAttr [[ADDR_5:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(llvm)}
+// C-NEXT: |   `-DeclRefExpr [[ADDR_6:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_7:0x[a-z0-9]*]] 'also_after.SimpPllv' 'int ({{.*}})'
+// C-NEXT: |-FunctionDecl [[ADDR_7]] <col:1, line:12:1> line:10:1 also_after.SimpPllv 'int ({{.*}})'
+// C-NEXT: | `-CompoundStmt [[ADDR_8:0x[a-z0-9]*]] <col:22, line:12:1>
+// C-NEXT: |   `-ReturnStmt [[ADDR_9:0x[a-z0-9]*]] <line:11:3, col:10>
+// C-NEXT: |     `-IntegerLiteral [[ADDR_10:0x[a-z0-9]*]] <col:10> 'int' 1
+// C-NEXT: |-FunctionDecl [[ADDR_11:0x[a-z0-9]*]] prev [[ADDR_0]] <line:13:1, col:21> col:5 used also_before 'int ({{.*}})'
+// C-NEXT: | `-OMPDeclareVariantAttr [[ADDR_12:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(llvm)}
+// C-NEXT: |   `-DeclRefExpr [[ADDR_13:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_14:0x[a-z0-9]*]] 'also_before.SimpPllv' 'int ({{.*}})'
+// C-NEXT: |-FunctionDecl [[ADDR_14]] <col:1, line:15:1> line:13:1 also_before.SimpPllv 'int ({{.*}})'
+// C-NEXT: | `-CompoundStmt [[ADDR_15:0x[a-z0-9]*]] <col:23, line:15:1>
+// C-NEXT: |   `-ReturnStmt [[ADDR_16:0x[a-z0-9]*]] <line:14:3, col:10>
+// C-NEXT: |     `-IntegerLiteral [[ADDR_17:0x[a-z0-9]*]] <col:10> 'int' 2
+// C-NEXT: |-FunctionDecl [[ADDR_18:0x[a-z0-9]*]] prev [[ADDR_4]] <line:18:1, line:20:1> line:18:5 used also_after 'int ({{.*}})'
+// C-NEXT: | |-CompoundStmt [[ADDR_19:0x[a-z0-9]*]] <col:22, line:20:1>
+// C-NEXT: | | `-ReturnStmt [[ADDR_20:0x[a-z0-9]*]] <line:19:3, col:10>
+// C-NEXT: | |   `-IntegerLiteral [[ADDR_21:0x[a-z0-9]*]] <col:10> 'int' 0
+// C-NEXT: | `-OMPDeclareVariantAttr [[ADDR_22:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(llvm)}
+// C-NEXT: |   `-DeclRefExpr [[ADDR_6]] <line:10:1> 'int ({{.*}})' Function [[ADDR_7]] 'also_after.SimpPllv' 'int ({{.*}})'
+// C-NEXT: |-FunctionDecl [[ADDR_23:0x[a-z0-9]*]] <line:22:1, line:24:1> line:22:5 used test 'int (int (*)({{.*}}))'
+// C-NEXT: | |-ParmVarDecl [[ADDR_24:0x[a-z0-9]*]] <col:10, col:24> col:16 used fd 'int (*)({{.*}})'
+// C-NEXT: | `-CompoundStmt [[ADDR_25:0x[a-z0-9]*]] <col:27, line:24:1>
+// C-NEXT: |   `-ReturnStmt [[ADDR_26:0x[a-z0-9]*]] <line:23:3, col:13>
+// C-NEXT: |     `-CallExpr [[ADDR_27:0x[a-z0-9]*]] <col:10, col:13> 'int'
+// C-NEXT: |       `-ImplicitCastExpr [[ADDR_28:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' <LValueToRValue>
+// C-NEXT: |         `-DeclRefExpr [[ADDR_29:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' {{.*}}ParmVar [[ADDR_24]] 'fd' 'int (*)({{.*}})'
+// C-NEXT: `-FunctionDecl [[ADDR_30:0x[a-z0-9]*]] <line:25:1, line:31:1> line:25:5 main 'int ({{.*}})'
+// C-NEXT:   `-CompoundStmt [[ADDR_31:0x[a-z0-9]*]] <col:12, line:31:1>
+// C-NEXT:     `-ReturnStmt [[ADDR_32:0x[a-z0-9]*]] <line:27:3, line:30:27>
+// C-NEXT:       `-BinaryOperator [[ADDR_33:0x[a-z0-9]*]] <line:27:10, line:30:27> 'int' '+'
+// C-NEXT:         |-BinaryOperator [[ADDR_34:0x[a-z0-9]*]] <line:27:10, line:29:26> 'int' '+'
+// C-NEXT:         | |-BinaryOperator [[ADDR_35:0x[a-z0-9]*]] <line:27:10, line:28:26> 'int' '+'
+// C-NEXT:         | | |-CallExpr [[ADDR_36:0x[a-z0-9]*]] <line:27:10, col:25> 'int'
+// C-NEXT:         | | | |-ImplicitCastExpr [[ADDR_37:0x[a-z0-9]*]] <col:10> 'int (*)(int (*)({{.*}}))' <FunctionToPointerDecay>
+// C-NEXT:         | | | | `-DeclRefExpr [[ADDR_38:0x[a-z0-9]*]] <col:10> 'int (int (*)({{.*}}))' Function [[ADDR_23]] 'test' 'int (int (*)({{.*}}))'
+// C-NEXT:         | | | `-ImplicitCastExpr [[ADDR_39:0x[a-z0-9]*]] <col:15> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// C-NEXT:         | | |   `-DeclRefExpr [[ADDR_40:0x[a-z0-9]*]] <col:15> 'int ({{.*}})' Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// C-NEXT:         | | `-CallExpr [[ADDR_41:0x[a-z0-9]*]] <line:28:10, col:26> 'int'
+// C-NEXT:         | |   |-ImplicitCastExpr [[ADDR_42:0x[a-z0-9]*]] <col:10> 'int (*)(int (*)({{.*}}))' <FunctionToPointerDecay>
+// C-NEXT:         | |   | `-DeclRefExpr [[ADDR_43:0x[a-z0-9]*]] <col:10> 'int (int (*)({{.*}}))' Function [[ADDR_23]] 'test' 'int (int (*)({{.*}}))'
+// C-NEXT:         | |   `-ImplicitCastExpr [[ADDR_44:0x[a-z0-9]*]] <col:15> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// C-NEXT:         | |     `-DeclRefExpr [[ADDR_45:0x[a-z0-9]*]] <col:15> 'int ({{.*}})' Function [[ADDR_11]] 'also_before' 'int ({{.*}})'
+// C-NEXT:         | `-CallExpr [[ADDR_46:0x[a-z0-9]*]] <line:29:10, col:26> 'int'
+// C-NEXT:         |   |-ImplicitCastExpr [[ADDR_47:0x[a-z0-9]*]] <col:10> 'int (*)(int (*)({{.*}}))' <FunctionToPointerDecay>
+// C-NEXT:         |   | `-DeclRefExpr [[ADDR_48:0x[a-z0-9]*]] <col:10> 'int (int (*)({{.*}}))' Function [[ADDR_23]] 'test' 'int (int (*)({{.*}}))'
+// C-NEXT:         |   `-UnaryOperator [[ADDR_49:0x[a-z0-9]*]] <col:15, col:16> 'int (*)({{.*}})' prefix '&' cannot overflow
+// C-NEXT:         |     `-DeclRefExpr [[ADDR_50:0x[a-z0-9]*]] <col:16> 'int ({{.*}})' Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// C-NEXT:         `-CallExpr [[ADDR_51:0x[a-z0-9]*]] <line:30:10, col:27> 'int'
+// C-NEXT:           |-ImplicitCastExpr [[ADDR_52:0x[a-z0-9]*]] <col:10> 'int (*)(int (*)({{.*}}))' <FunctionToPointerDecay>
+// C-NEXT:           | `-DeclRefExpr [[ADDR_53:0x[a-z0-9]*]] <col:10> 'int (int (*)({{.*}}))' Function [[ADDR_23]] 'test' 'int (int (*)({{.*}}))'
+// C-NEXT:           `-UnaryOperator [[ADDR_54:0x[a-z0-9]*]] <col:15, col:16> 'int (*)({{.*}})' prefix '&' cannot overflow
+// C-NEXT:             `-DeclRefExpr [[ADDR_55:0x[a-z0-9]*]] <col:16> 'int ({{.*}})' Function [[ADDR_11]] 'also_before' 'int ({{.*}})'
+
+// CXX:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})'
+// CXX-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] <col:23, line:7:1>
+// CXX-NEXT: |   `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] <line:6:3, col:10>
+// CXX-NEXT: |     `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] <col:10> 'int' 0
+// CXX-NEXT: |-FunctionDecl [[ADDR_4:0x[a-z0-9]*]] <line:10:1, col:20> col:5 used also_after 'int ({{.*}})'
+// CXX-NEXT: | `-OMPDeclareVariantAttr [[ADDR_5:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(llvm)}
+// CXX-NEXT: |   `-DeclRefExpr [[ADDR_6:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_7:0x[a-z0-9]*]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CXX-NEXT: |-FunctionDecl [[ADDR_7]] <col:1, line:12:1> line:10:1 also_after.SimpPllv 'int ({{.*}})'
+// CXX-NEXT: | `-CompoundStmt [[ADDR_8:0x[a-z0-9]*]] <col:22, line:12:1>
+// CXX-NEXT: |   `-ReturnStmt [[ADDR_9:0x[a-z0-9]*]] <line:11:3, col:10>
+// CXX-NEXT: |     `-IntegerLiteral [[ADDR_10:0x[a-z0-9]*]] <col:10> 'int' 1
+// CXX-NEXT: |-FunctionDecl [[ADDR_11:0x[a-z0-9]*]] prev [[ADDR_0]] <line:13:1, col:21> col:5 used also_before 'int ({{.*}})'
+// CXX-NEXT: | `-OMPDeclareVariantAttr [[ADDR_12:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={vendor(llvm)}
+// CXX-NEXT: |   `-DeclRefExpr [[ADDR_13:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' Function [[ADDR_14:0x[a-z0-9]*]] 'also_before.SimpPllv' 'int ({{.*}})'
+// CXX-NEXT: |-FunctionDecl [[ADDR_14]] <col:1, line:15:1> line:13:1 also_before.SimpPllv 'int ({{.*}})'
+// CXX-NEXT: | `-CompoundStmt [[ADDR_15:0x[a-z0-9]*]] <col:23, line:15:1>
+// CXX-NEXT: |   `-ReturnStmt [[ADDR_16:0x[a-z0-9]*]] <line:14:3, col:10>
+// CXX-NEXT: |     `-IntegerLiteral [[ADDR_17:0x[a-z0-9]*]] <col:10> 'int' 2
+// CXX-NEXT: |-FunctionDecl [[ADDR_18:0x[a-z0-9]*]] prev [[ADDR_4]] <line:18:1, line:20:1> line:18:5 used also_after 'int ({{.*}})'
+// CXX-NEXT: | |-CompoundStmt [[ADDR_19:0x[a-z0-9]*]] <col:22, line:20:1>
+// CXX-NEXT: | | `-ReturnStmt [[ADDR_20:0x[a-z0-9]*]] <line:19:3, col:10>
+// CXX-NEXT: | |   `-IntegerLiteral [[ADDR_21:0x[a-z0-9]*]] <col:10> 'int' 0
+// CXX-NEXT: | `-OMPDeclareVariantAttr [[ADDR_22:0x[a-z0-9]*]] <<invalid sloc>> Inherited Implicit implementation={vendor(llvm)}
+// CXX-NEXT: |   `-DeclRefExpr [[ADDR_6]] <line:10:1> 'int ({{.*}})' Function [[ADDR_7]] 'also_after.SimpPllv' 'int ({{.*}})'
+// CXX-NEXT: |-FunctionDecl [[ADDR_23:0x[a-z0-9]*]] <line:22:1, line:24:1> line:22:5 used test 'int (int (*)({{.*}}))'
+// CXX-NEXT: | |-ParmVarDecl [[ADDR_24:0x[a-z0-9]*]] <col:10, col:24> col:16 used fd 'int (*)({{.*}})'
+// CXX-NEXT: | `-CompoundStmt [[ADDR_25:0x[a-z0-9]*]] <col:27, line:24:1>
+// CXX-NEXT: |   `-ReturnStmt [[ADDR_26:0x[a-z0-9]*]] <line:23:3, col:13>
+// CXX-NEXT: |     `-CallExpr [[ADDR_27:0x[a-z0-9]*]] <col:10, col:13> 'int'
+// CXX-NEXT: |       `-ImplicitCastExpr [[ADDR_28:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' <LValueToRValue>
+// CXX-NEXT: |         `-DeclRefExpr [[ADDR_29:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' {{.*}}ParmVar [[ADDR_24]] 'fd' 'int (*)({{.*}})'
+// CXX-NEXT: `-FunctionDecl [[ADDR_30:0x[a-z0-9]*]] <line:25:1, line:31:1> line:25:5 main 'int ({{.*}})'
+// CXX-NEXT:   `-CompoundStmt [[ADDR_31:0x[a-z0-9]*]] <col:12, line:31:1>
+// CXX-NEXT:     `-ReturnStmt [[ADDR_32:0x[a-z0-9]*]] <line:27:3, line:30:27>
+// CXX-NEXT:       `-BinaryOperator [[ADDR_33:0x[a-z0-9]*]] <line:27:10, line:30:27> 'int' '+'
+// CXX-NEXT:         |-BinaryOperator [[ADDR_34:0x[a-z0-9]*]] <line:27:10, line:29:26> 'int' '+'
+// CXX-NEXT:         | |-BinaryOperator [[ADDR_35:0x[a-z0-9]*]] <line:27:10, line:28:26> 'int' '+'
+// CXX-NEXT:         | | |-CallExpr [[ADDR_36:0x[a-z0-9]*]] <line:27:10, col:25> 'int'
+// CXX-NEXT:         | | | |-ImplicitCastExpr [[ADDR_37:0x[a-z0-9]*]] <col:10> 'int (*)(int (*)({{.*}}))' <FunctionToPointerDecay>
+// CXX-NEXT:         | | | | `-DeclRefExpr [[ADDR_38:0x[a-z0-9]*]] <col:10> 'int (int (*)({{.*}}))' {{.*}}Function [[ADDR_23]] 'test' 'int (int (*)({{.*}}))'
+// CXX-NEXT:         | | | `-ImplicitCastExpr [[ADDR_39:0x[a-z0-9]*]] <col:15> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CXX-NEXT:         | | |   `-DeclRefExpr [[ADDR_40:0x[a-z0-9]*]] <col:15> 'int ({{.*}})' {{.*}}Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// CXX-NEXT:         | | `-CallExpr [[ADDR_41:0x[a-z0-9]*]] <line:28:10, col:26> 'int'
+// CXX-NEXT:         | |   |-ImplicitCastExpr [[ADDR_42:0x[a-z0-9]*]] <col:10> 'int (*)(int (*)({{.*}}))' <FunctionToPointerDecay>
+// CXX-NEXT:         | |   | `-DeclRefExpr [[ADDR_43:0x[a-z0-9]*]] <col:10> 'int (int (*)({{.*}}))' {{.*}}Function [[ADDR_23]] 'test' 'int (int (*)({{.*}}))'
+// CXX-NEXT:         | |   `-ImplicitCastExpr [[ADDR_44:0x[a-z0-9]*]] <col:15> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CXX-NEXT:         | |     `-DeclRefExpr [[ADDR_45:0x[a-z0-9]*]] <col:15> 'int ({{.*}})' {{.*}}Function [[ADDR_11]] 'also_before' 'int ({{.*}})'
+// CXX-NEXT:         | `-CallExpr [[ADDR_46:0x[a-z0-9]*]] <line:29:10, col:26> 'int'
+// CXX-NEXT:         |   |-ImplicitCastExpr [[ADDR_47:0x[a-z0-9]*]] <col:10> 'int (*)(int (*)({{.*}}))' <FunctionToPointerDecay>
+// CXX-NEXT:         |   | `-DeclRefExpr [[ADDR_48:0x[a-z0-9]*]] <col:10> 'int (int (*)({{.*}}))' {{.*}}Function [[ADDR_23]] 'test' 'int (int (*)({{.*}}))'
+// CXX-NEXT:         |   `-UnaryOperator [[ADDR_49:0x[a-z0-9]*]] <col:15, col:16> 'int (*)({{.*}})' prefix '&' cannot overflow
+// CXX-NEXT:         |     `-DeclRefExpr [[ADDR_50:0x[a-z0-9]*]] <col:16> 'int ({{.*}})' {{.*}}Function [[ADDR_18]] 'also_after' 'int ({{.*}})'
+// CXX-NEXT:         `-CallExpr [[ADDR_51:0x[a-z0-9]*]] <line:30:10, col:27> 'int'
+// CXX-NEXT:           |-ImplicitCastExpr [[ADDR_52:0x[a-z0-9]*]] <col:10> 'int (*)(int (*)({{.*}}))' <FunctionToPointerDecay>
+// CXX-NEXT:           | `-DeclRefExpr [[ADDR_53:0x[a-z0-9]*]] <col:10> 'int (int (*)({{.*}}))' {{.*}}Function [[ADDR_23]] 'test' 'int (int (*)({{.*}}))'
+// CXX-NEXT:           `-UnaryOperator [[ADDR_54:0x[a-z0-9]*]] <col:15, col:16> 'int (*)({{.*}})' prefix '&' cannot overflow
+// CXX-NEXT:             `-DeclRefExpr [[ADDR_55:0x[a-z0-9]*]] <col:16> 'int ({{.*}})' {{.*}}Function [[ADDR_11]] 'also_before' 'int ({{.*}})'
diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_decl_1.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant_decl_1.c
new file mode 100644
--- /dev/null
+++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_decl_1.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s       | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify -ast-dump %s -x c++| FileCheck %s
+// expected-no-diagnostics
+// FIXME: We have to improve the warnings here as nothing is impacted by the declare variant.
+int also_before(void) {
+  return 0;
+}
+
+#pragma omp begin declare variant match(device={kind(cpu)})
+int also_before(void);
+#pragma omp end declare variant
+#pragma omp begin declare variant match(implementation={vendor(score(100):llvm)})
+int also_after(void);
+#pragma omp end declare variant
+#pragma omp begin declare variant match(implementation={vendor(score(0):llvm)})
+int also_before(void);
+#pragma omp end declare variant
+
+int also_after(void) {
+  return 0;
+}
+
+int test() {
+  // Should return 0.
+  return also_after() + also_before();
+}
+
+// Make sure:
+//  - we do see the ast nodes for the cpu kind
+//  - we do see the ast nodes for the llvm vendor
+//  - we pick the right callees
+
+// CHECK:      |-FunctionDecl [[ADDR_0:0x[a-z0-9]*]] <{{.*}}, line:7:1> line:5:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_1:0x[a-z0-9]*]] <col:23, line:7:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_2:0x[a-z0-9]*]] <line:6:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_3:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: |-FunctionDecl [[ADDR_4:0x[a-z0-9]*]] prev [[ADDR_0]] <line:10:1, col:21> col:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_5:0x[a-z0-9]*]] <line:13:1, col:20> col:5 used also_after 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_6:0x[a-z0-9]*]] prev [[ADDR_4]] <line:16:1, col:21> col:5 used also_before 'int ({{.*}})'
+// CHECK-NEXT: |-FunctionDecl [[ADDR_7:0x[a-z0-9]*]] prev [[ADDR_5]] <line:19:1, line:21:1> line:19:5 used also_after 'int ({{.*}})'
+// CHECK-NEXT: | `-CompoundStmt [[ADDR_8:0x[a-z0-9]*]] <col:22, line:21:1>
+// CHECK-NEXT: |   `-ReturnStmt [[ADDR_9:0x[a-z0-9]*]] <line:20:3, col:10>
+// CHECK-NEXT: |     `-IntegerLiteral [[ADDR_10:0x[a-z0-9]*]] <col:10> 'int' 0
+// CHECK-NEXT: `-FunctionDecl [[ADDR_11:0x[a-z0-9]*]] <line:23:1, line:26:1> line:23:5 test 'int ({{.*}})'
+// CHECK-NEXT:   `-CompoundStmt [[ADDR_12:0x[a-z0-9]*]] <col:12, line:26:1>
+// CHECK-NEXT:     `-ReturnStmt [[ADDR_13:0x[a-z0-9]*]] <line:25:3, col:37>
+// CHECK-NEXT:       `-BinaryOperator [[ADDR_14:0x[a-z0-9]*]] <col:10, col:37> 'int' '+'
+// CHECK-NEXT:         |-CallExpr [[ADDR_15:0x[a-z0-9]*]] <col:10, col:21> 'int'
+// CHECK-NEXT:         | `-ImplicitCastExpr [[ADDR_16:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:         |   `-DeclRefExpr [[ADDR_17:0x[a-z0-9]*]] <col:10> 'int ({{.*}})' {{.*}}Function [[ADDR_7]] 'also_after' 'int ({{.*}})'
+// CHECK-NEXT:         `-CallExpr [[ADDR_18:0x[a-z0-9]*]] <col:25, col:37> 'int'
+// CHECK-NEXT:           `-ImplicitCastExpr [[ADDR_19:0x[a-z0-9]*]] <col:25> 'int (*)({{.*}})' <FunctionToPointerDecay>
+// CHECK-NEXT:             `-DeclRefExpr [[ADDR_20:0x[a-z0-9]*]] <col:25> 'int ({{.*}})' {{.*}}Function [[ADDR_6]] 'also_before' 'int ({{.*}})'
diff --git a/clang/test/OpenMP/begin-declare-variant_no_end_for_matching_selector.c b/clang/test/OpenMP/begin_declare_variant_elided_range_withouth_end.c
rename from clang/test/OpenMP/begin-declare-variant_no_end_for_matching_selector.c
rename to clang/test/OpenMP/begin_declare_variant_elided_range_withouth_end.c
--- a/clang/test/OpenMP/begin-declare-variant_no_end_for_matching_selector.c
+++ b/clang/test/OpenMP/begin_declare_variant_elided_range_withouth_end.c
@@ -1,21 +1,19 @@
 // RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -x c -std=c99 -fms-extensions -Wno-pragma-pack %s
 // RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c -std=c99 -fms-extensions -Wno-pragma-pack %s
 
-#pragma omp begin declare variant match(device={kind(cpu)})
+#pragma omp begin declare variant match(device={kind(gpu)}) // expected-note {{to match this '#pragma omp begin declare variant'}}
 int also_before(void) {
   return 0;
 }
-#pragma omp end declare variant
 
-#pragma omp begin declare variant match(device={kind(gpu)}) // expected-note {{to match this '#pragma omp begin declare variant'}}
-// The matching end is missing. Since the device clause is not matching we will
-// cause us to elide the rest of the file and emit and error.
+#pragma omp begin declare variant match(device={kind(gpu)})
 int also_after(void) {
   return 2;
 }
 int also_before(void) {
   return 2;
 }
+#pragma omp end declare variant
 
 
 #pragma omp begin declare variant match(device={kind(fpga)})
diff --git a/clang/test/OpenMP/begin_declare_variant_messages.c b/clang/test/OpenMP/begin_declare_variant_messages.c
--- a/clang/test/OpenMP/begin_declare_variant_messages.c
+++ b/clang/test/OpenMP/begin_declare_variant_messages.c
@@ -4,20 +4,20 @@
 
 
 #pragma omp begin // expected-error {{expected an OpenMP directive}}
-#pragma omp end declare variant
+#pragma omp end declare variant // expected-error {{expected '#pragma omp begin declare variant' to match this stray `#pragma omp end delcare variant`}}
 #pragma omp begin declare // expected-error {{expected an OpenMP directive}}
-#pragma omp end declare variant
+#pragma omp end declare variant // expected-error {{expected '#pragma omp begin declare variant' to match this stray `#pragma omp end delcare variant`}}
 #pragma omp begin variant // expected-error {{expected an OpenMP directive}}
-#pragma omp end declare variant
+#pragma omp end declare variant // expected-error {{expected '#pragma omp begin declare variant' to match this stray `#pragma omp end delcare variant`}}
 #pragma omp variant begin // expected-error {{expected an OpenMP directive}}
 #pragma omp declare variant end // expected-error {{function declaration is expected after 'declare variant' directive}}
 #pragma omp begin declare variant // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
 #pragma omp end declare variant
 // TODO: Issue an error message
-#pragma omp end declare variant
-#pragma omp end declare variant
-#pragma omp end declare variant
-#pragma omp end declare variant
+#pragma omp end declare variant // expected-error {{expected '#pragma omp begin declare variant' to match this stray `#pragma omp end delcare variant`}}
+#pragma omp end declare variant // expected-error {{expected '#pragma omp begin declare variant' to match this stray `#pragma omp end delcare variant`}}
+#pragma omp end declare variant // expected-error {{expected '#pragma omp begin declare variant' to match this stray `#pragma omp end delcare variant`}}
+#pragma omp end declare variant // expected-error {{expected '#pragma omp begin declare variant' to match this stray `#pragma omp end delcare variant`}}
 
 int foo(void);
 const int var;
diff --git a/clang/test/OpenMP/begin-declare-variant_no_end_for_matching_selector.c b/clang/test/OpenMP/begin_declare_variant_no_end_for_matching_selector.c
copy from clang/test/OpenMP/begin-declare-variant_no_end_for_matching_selector.c
copy to clang/test/OpenMP/begin_declare_variant_no_end_for_matching_selector.c
diff --git a/clang/test/OpenMP/begin-declare-variant_no_end_for_matching_selector.c b/clang/test/OpenMP/begin_declare_variant_range_withouth_end.c
rename from clang/test/OpenMP/begin-declare-variant_no_end_for_matching_selector.c
rename to clang/test/OpenMP/begin_declare_variant_range_withouth_end.c
--- a/clang/test/OpenMP/begin-declare-variant_no_end_for_matching_selector.c
+++ b/clang/test/OpenMP/begin_declare_variant_range_withouth_end.c
@@ -1,21 +1,21 @@
 // RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -x c -std=c99 -fms-extensions -Wno-pragma-pack %s
 // RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c -std=c99 -fms-extensions -Wno-pragma-pack %s
 
+// TODO: Issue an eror message as the end is missing
+// expected-no-diagnostics
 #pragma omp begin declare variant match(device={kind(cpu)})
 int also_before(void) {
   return 0;
 }
-#pragma omp end declare variant
 
-#pragma omp begin declare variant match(device={kind(gpu)}) // expected-note {{to match this '#pragma omp begin declare variant'}}
-// The matching end is missing. Since the device clause is not matching we will
-// cause us to elide the rest of the file and emit and error.
+#pragma omp begin declare variant match(device={kind(gpu)})
 int also_after(void) {
   return 2;
 }
 int also_before(void) {
   return 2;
 }
+#pragma omp end declare variant
 
 
 #pragma omp begin declare variant match(device={kind(fpga)})
@@ -30,4 +30,4 @@
 
 int test() {
   return also_after() + also_before();
-} // expected-error {{expected '#pragma omp end declare variant'}}
+}
diff --git a/clang/test/OpenMP/begin_declare_variant_using_messages.cpp b/clang/test/OpenMP/begin_declare_variant_using_messages.cpp
new file mode 100644
--- /dev/null
+++ b/clang/test/OpenMP/begin_declare_variant_using_messages.cpp
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -verify %s
+
+namespace BEFORE_AND_1 {
+void before_and_1();
+}
+namespace AFTER_AND_2 {
+void after_and_2(); // expected-note {{'AFTER_AND_2::after_and_2' declared here}} expected-note {{'AFTER_AND_2::after_and_2' declared here}}
+}
+namespace ONLY_1 {
+void only_1(); // expected-note {{'ONLY_1::only_1' declared here}}
+}
+namespace BEFORE_1_AND_2 {
+void before_1_and_2();
+}
+
+using BEFORE_1_AND_2::before_1_and_2;
+using BEFORE_AND_1::before_and_1;
+
+void test_before() {
+  before_and_1();
+  after_and_2(); // expected-error {{use of undeclared identifier 'after_and_2'; did you mean 'AFTER_AND_2::after_and_2'?}}
+  only_1(); // expected-error {{use of undeclared identifier 'only_1'; did you mean 'ONLY_1::only_1'?}}
+  before_1_and_2();
+}
+
+#pragma omp begin declare variant match(implementation = {vendor(llvm)})
+using BEFORE_1_AND_2::before_1_and_2;
+using BEFORE_AND_1::before_and_1;
+using ONLY_1::only_1;
+void test_1() {
+  before_and_1();
+  after_and_2(); // expected-error {{use of undeclared identifier 'after_and_2'; did you mean 'AFTER_AND_2::after_and_2'?}}
+  only_1();
+  before_1_and_2();
+}
+#pragma omp end declare variant
+
+#pragma omp begin declare variant match(implementation = {vendor(llvm)})
+using AFTER_AND_2::after_and_2;
+using BEFORE_1_AND_2::before_1_and_2;
+void test_2() {
+  before_and_1();
+  after_and_2();
+  only_1();
+  before_1_and_2();
+}
+#pragma omp end declare variant
+
+void test_after() {
+  before_and_1();
+  after_and_2();
+  only_1();
+  before_1_and_2();
+}
+
+using AFTER_AND_2::after_and_2;
+
+// Make sure:
+//  - we do not see the ast nodes for the gpu kind
+//  - we do not choke on the text in the kind(fpga) guarded scopes
+//  - we pick the right cbefore_1_and_2ees
diff --git a/clang/test/OpenMP/declare_variant_ast_print.cpp b/clang/test/OpenMP/declare_variant_ast_print.cpp
--- a/clang/test/OpenMP/declare_variant_ast_print.cpp
+++ b/clang/test/OpenMP/declare_variant_ast_print.cpp
@@ -64,8 +64,7 @@
 // CHECK-NEXT: }
 // CHECK-NEXT: template<> void h_ref<double>(double *hp, double *hp2, double *hq, double *lin) {
 // CHECK-NEXT: }
-// CHECK-NEXT: template<> void h_ref<float>(float *hp, float *hp2, float *hq, float *lin) {
-// CHECK-NEXT: }
+// CHECK-NEXT: template<> void h_ref<float>(float *hp, float *hp2, float *hq, float *lin)
 template <class C>
 void h_ref(C *hp, C *hp2, C *hq, C *lin) {
 }
diff --git a/clang/test/OpenMP/declare_variant_device_kind_codegen.cpp b/clang/test/OpenMP/declare_variant_device_kind_codegen.cpp
--- a/clang/test/OpenMP/declare_variant_device_kind_codegen.cpp
+++ b/clang/test/OpenMP/declare_variant_device_kind_codegen.cpp
@@ -40,20 +40,11 @@
 
 // expected-no-diagnostics
 
+// CHECK-NOT: alias
+
 // CHECK-NOT: ret i32 {{1|4|81|84}}
-// CHECK-DAG: @_Z3barv = {{.*}}alias i32 (), i32 ()* @_Z3foov
-// CHECK-DAG: @_ZN16SpecSpecialFuncs6MethodEv = {{.*}}alias i32 (%struct.SpecSpecialFuncs*), i32 (%struct.SpecSpecialFuncs*)* @_ZN16SpecSpecialFuncs7method_Ev
-// CHECK-DAG: @_ZN16SpecSpecialFuncs6methodEv = linkonce_odr {{.*}}alias i32 (%struct.SpecSpecialFuncs*), i32 (%struct.SpecSpecialFuncs*)* @_ZN16SpecSpecialFuncs7method_Ev
-// CHECK-DAG: @_ZN12SpecialFuncs6methodEv = linkonce_odr {{.*}}alias i32 (%struct.SpecialFuncs*), i32 (%struct.SpecialFuncs*)* @_ZN12SpecialFuncs7method_Ev
-// CHECK-DAG: @_Z5prio_v = {{.*}}alias i32 (), i32 ()* @_Z5prio1v
-// CHECK-DAG: @_ZL6prio1_v = internal alias i32 (), i32 ()* @_ZL5prio2v
-// CHECK-DAG: @_Z4callv = {{.*}}alias i32 (), i32 ()* @_Z4testv
-// CHECK-DAG: @_ZL9stat_usedv = internal alias i32 (), i32 ()* @_ZL10stat_used_v
-// CHECK-DAG: @_ZN12SpecialFuncs6MethodEv = {{.*}}alias i32 (%struct.SpecialFuncs*), i32 (%struct.SpecialFuncs*)* @_ZN12SpecialFuncs7method_Ev
-// CHECK-DAG: @fn_linkage = {{.*}}alias i32 (), i32 ()* @_Z18fn_linkage_variantv
-// CHECK-DAG: @_Z11fn_linkage1v = {{.*}}alias i32 (), i32 ()* @fn_linkage_variant1
 // CHECK-DAG: declare {{.*}}i32 @_Z5bazzzv()
-// CHECK-DAG: declare {{.*}}i32 @_Z3bazv()
+// CHECK-DAG: define {{.*}}i32 @_Z3bazv()
 // CHECK-DAG: ret i32 2
 // CHECK-DAG: ret i32 3
 // CHECK-DAG: ret i32 5
@@ -64,7 +55,7 @@
 // CHECK-DAG: ret i32 85
 // CHECK-DAG: ret i32 86
 // CHECK-DAG: ret i32 87
-// CHECK-NOT: ret i32 {{1|4|81|84}}
+// CHECK-NOT: ret i32 {{4|81|84}}
 
 #ifndef HEADER
 #define HEADER
diff --git a/clang/test/OpenMP/declare_variant_implementation_vendor_codegen.cpp b/clang/test/OpenMP/declare_variant_implementation_vendor_codegen.cpp
--- a/clang/test/OpenMP/declare_variant_implementation_vendor_codegen.cpp
+++ b/clang/test/OpenMP/declare_variant_implementation_vendor_codegen.cpp
@@ -1,33 +1,23 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple %itanium_abi_triple -emit-llvm %s -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple %itanium_abi_triple -emit-llvm %s -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope | FileCheck %s --implicit-check-not='ret i32 {{6|7|8|9|10|12|13|14|15|19|21|22|23|24}}'
 // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t -fopenmp-version=50 %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -fopenmp-version=50 | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -fopenmp-version=50 | FileCheck %s --implicit-check-not='ret i32 {{6|7|8|9|10|12|13|14|15|19|21|22|23|24}}'
 // expected-no-diagnostics
 
-// CHECK-NOT: ret i32 {{1|4|81|84}}
-// CHECK-DAG: @_Z3barv = {{.*}}alias i32 (), i32 ()* @_Z3foov
-// CHECK-DAG: @_ZN16SpecSpecialFuncs6MethodEv = {{.*}}alias i32 (%struct.SpecSpecialFuncs*), i32 (%struct.SpecSpecialFuncs*)* @_ZN16SpecSpecialFuncs7method_Ev
-// CHECK-DAG: @_ZN16SpecSpecialFuncs6methodEv = linkonce_odr {{.*}}alias i32 (%struct.SpecSpecialFuncs*), i32 (%struct.SpecSpecialFuncs*)* @_ZN16SpecSpecialFuncs7method_Ev
-// CHECK-DAG: @_ZN12SpecialFuncs6methodEv = linkonce_odr {{.*}}alias i32 (%struct.SpecialFuncs*), i32 (%struct.SpecialFuncs*)* @_ZN12SpecialFuncs7method_Ev
-// CHECK-DAG: @_Z5prio_v = {{.*}}alias i32 (), i32 ()* @_Z5prio1v
-// CHECK-DAG: @_ZL6prio1_v = internal alias i32 (), i32 ()* @_ZL5prio2v
-// CHECK-DAG: @_Z4callv = {{.*}}alias i32 (), i32 ()* @_Z4testv
-// CHECK-DAG: @_ZL9stat_usedv = internal alias i32 (), i32 ()* @_ZL10stat_used_v
-// CHECK-DAG: @_ZN12SpecialFuncs6MethodEv = {{.*}}alias i32 (%struct.SpecialFuncs*), i32 (%struct.SpecialFuncs*)* @_ZN12SpecialFuncs7method_Ev
-// CHECK-DAG: @fn_linkage = {{.*}}alias i32 (), i32 ()* @_Z18fn_linkage_variantv
-// CHECK-DAG: @_Z11fn_linkage1v = {{.*}}alias i32 (), i32 ()* @fn_linkage_variant1
-// CHECK-DAG: declare {{.*}}i32 @_Z5bazzzv()
-// CHECK-DAG: declare {{.*}}i32 @_Z3bazv()
-// CHECK-DAG: ret i32 2
-// CHECK-DAG: ret i32 3
-// CHECK-DAG: ret i32 5
-// CHECK-DAG: ret i32 6
-// CHECK-DAG: ret i32 7
-// CHECK-DAG: ret i32 82
-// CHECK-DAG: ret i32 83
-// CHECK-DAG: ret i32 85
-// CHECK-DAG: ret i32 86
-// CHECK-DAG: ret i32 87
-// CHECK-NOT: ret i32 {{1|4|81|84}}
+// CHECK-DAG:  ret i32 2
+// CHECK-DAG:  ret i32 3
+// CHECK-DAG:  ret i32 4
+// CHECK-DAG:  ret i32 5
+// CHECK-DAG:  ret i32 11
+// CHECK-DAG:  ret i32 16
+// CHECK-DAG:  ret i32 17
+// CHECK-DAG:  ret i32 18
+// CHECK-DAG:  ret i32 19
+// CHECK-DAG:  ret i32 20
+// CHECK-DAG:  ret i32 25
+// CHECK-DAG:  ret i32 26
+// CHECK-DAG:  ret i32 27
+// CHECK-DAG:  ret i32 28
+// CHECK-DAG:  ret i32 29
 
 #ifndef HEADER
 #define HEADER
@@ -35,45 +25,45 @@
 int foo() { return 2; }
 
 #pragma omp declare variant(foo) match(implementation = {vendor(llvm)})
-int bar() { return 1; }
+int bar() { return 3; }
 
 int bazzz();
 #pragma omp declare variant(bazzz) match(implementation = {vendor(llvm)})
-int baz() { return 1; }
+int baz() { return 4; }
 
 int test();
 #pragma omp declare variant(test) match(implementation = {vendor(llvm)})
-int call() { return 1; }
+int call() { return 5; }
 
 static int stat_unused_();
 #pragma omp declare variant(stat_unused_) match(implementation = {vendor(llvm)})
-static int stat_unused() { return 1; }
+static int stat_unused() { return 6; }
 
 static int stat_used_();
 #pragma omp declare variant(stat_used_) match(implementation = {vendor(llvm)})
-static int stat_used() { return 1; }
+static int stat_used() { return 7; }
 
 int main() { return bar() + baz() + call() + stat_used(); }
 
-int test() { return 3; }
-static int stat_unused_() { return 4; }
-static int stat_used_() { return 5; }
+int test() { return 8; }
+static int stat_unused_() { return 9; }
+static int stat_used_() { return 10; }
 
 struct SpecialFuncs {
   void vd() {}
   SpecialFuncs();
   ~SpecialFuncs();
 
-  int method_() { return 6; }
+  int method_() { return 11; }
 #pragma omp declare variant(SpecialFuncs::method_)                             \
     match(implementation = {vendor(llvm)})
-  int method() { return 1; }
+  int method() { return 12; }
 #pragma omp declare variant(SpecialFuncs::method_)                             \
     match(implementation = {vendor(llvm)})
   int Method();
 } s;
 
-int SpecialFuncs::Method() { return 1; }
+int SpecialFuncs::Method() { return 13; }
 
 struct SpecSpecialFuncs {
   void vd() {}
@@ -83,50 +73,50 @@
   int method_();
 #pragma omp declare variant(SpecSpecialFuncs::method_)                         \
     match(implementation = {vendor(llvm)})
-  int method() { return 1; }
+  int method() { return 14; }
 #pragma omp declare variant(SpecSpecialFuncs::method_)                         \
     match(implementation = {vendor(llvm)})
   int Method();
 } s1;
 
-int SpecSpecialFuncs::method_() { return 7; }
-int SpecSpecialFuncs::Method() { return 1; }
+int SpecSpecialFuncs::method_() { return 15; }
+int SpecSpecialFuncs::Method() { return 16; }
 
 void xxx() {
   (void)s.method();
   (void)s1.method();
 }
 
-int prio() { return 81; }
-int prio1() { return 82; }
+int prio() { return 17; }
+int prio1() { return 18; }
 
 #pragma omp declare variant(prio) match(implementation = {vendor(llvm)})
 #pragma omp declare variant(prio1) match(implementation = {vendor(score(1): llvm)})
-int prio_() { return 1; }
+int prio_() { return 19; }
 
-static int prio2() { return 83; }
-static int prio3() { return 84; }
-static int prio4() { return 84; }
+static int prio2() { return 20; }
+static int prio3() { return 21; }
+static int prio4() { return 22; }
 
 #pragma omp declare variant(prio4) match(implementation = {vendor(score(3): llvm)})
 #pragma omp declare variant(prio2) match(implementation = {vendor(score(5): llvm)})
 #pragma omp declare variant(prio3) match(implementation = {vendor(score(1): llvm)})
-static int prio1_() { return 1; }
+static int prio1_() { return 23; }
 
 int int_fn() { return prio1_(); }
 
-int fn_linkage_variant() { return 85; }
+int fn_linkage_variant() { return 24; }
 extern "C" {
 #pragma omp declare variant(fn_linkage_variant) match(implementation = {vendor(llvm)})
-int fn_linkage() { return 1; }
+int fn_linkage() { return 25; }
 }
 
-extern "C" int fn_linkage_variant1() { return 86; }
+extern "C" int fn_linkage_variant1() { return 26; }
 #pragma omp declare variant(fn_linkage_variant1) match(implementation = {vendor(llvm)})
-int fn_linkage1() { return 1; }
+int fn_linkage1() { return 27; }
 
-int fn_variant2() { return 1; }
+int fn_variant2() { return 28; }
 #pragma omp declare variant(fn_variant2) match(implementation = {vendor(llvm, ibm)})
-int fn2() { return 87; }
+int fn2() { return 29; }
 
 #endif // HEADER
diff --git a/clang/test/OpenMP/declare_variant_messages.c b/clang/test/OpenMP/declare_variant_messages.c
--- a/clang/test/OpenMP/declare_variant_messages.c
+++ b/clang/test/OpenMP/declare_variant_messages.c
@@ -78,8 +78,8 @@
 
 
 
-#pragma omp declare variant(foo) match(xxx={}) // expected-error {{function declaration is expected after 'declare variant' directive}}
-#pragma omp declare variant(foo) match(xxx={}) // expected-error {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant(foo) match(implementation={vendor(llvm)}) // expected-error {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant(foo) match(implementation={vendor(llvm)}) // expected-error {{function declaration is expected after 'declare variant' directive}}
 #pragma init_seg(compiler)
 int main();
 
diff --git a/clang/test/OpenMP/declare_variant_messages.cpp b/clang/test/OpenMP/declare_variant_messages.cpp
--- a/clang/test/OpenMP/declare_variant_messages.cpp
+++ b/clang/test/OpenMP/declare_variant_messages.cpp
@@ -130,10 +130,16 @@
 template <int C>
 int score_and_cond_const_inst();
 
+__attribute__((pure)) int pure() { return 0; }
+
+#pragma omp declare variant(pure) match(user = {condition(1)}) // expected-warning {{ignoring return value of function declared with pure attribute}}
+int unused_warning_after_specialization() { return foo(); }
+
 void score_and_cond_inst() {
   score_and_cond_non_const();
   score_and_cond_non_const_inst<8>(); // expected-note {{in instantiation of function template specialization 'score_and_cond_non_const_inst<8>' requested here}}
   score_and_cond_const_inst<9>();
+  unused_warning_after_specialization();
 }
 
 #pragma omp declare variant(barbar <int>) match(implementation = {}) // expected-warning {{expected identifier or string literal describing a context selector; selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}}
diff --git a/clang/test/OpenMP/declare_variant_mixed_codegen.c b/clang/test/OpenMP/declare_variant_mixed_codegen.c
--- a/clang/test/OpenMP/declare_variant_mixed_codegen.c
+++ b/clang/test/OpenMP/declare_variant_mixed_codegen.c
@@ -7,7 +7,6 @@
 // RUN: %clang_cc1 -verify -fopenmp -x c -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - -fopenmp-version=50 | FileCheck %s --check-prefix GPU
 // expected-no-diagnostics
 
-// HOST: @base = alias i32 (double), i32 (double)* @hst
 #ifndef HEADER
 #define HEADER
 
@@ -20,9 +19,9 @@
 int base();
 
 // HOST-LABEL: define void @foo()
-// HOST: call i32 (double, ...) bitcast (i32 (double)* @base to i32 (double, ...)*)(double -1.000000e+00)
+// HOST: call i32 @hst(double -1.000000e+00)
 // HOST: call i32 @hst(double -2.000000e+00)
-// HOST: call void [[OFFL:@.+_foo_l29]]()
+// HOST: call void [[OFFL:@.+_foo_l28]]()
 void foo() {
   base(-1);
   hst(-2);
@@ -34,15 +33,14 @@
 }
 
 // HOST: define {{.*}}void [[OFFL]]()
-// HOST: call i32 (double, ...) bitcast (i32 (double)* @base to i32 (double, ...)*)(double -3.000000e+00)
+// HOST: call i32 @hst(double -3.000000e+00)
 // HOST: call i32 @dev(double -4.000000e+00)
 
-// GPU: define {{.*}}void @__omp_offloading_{{.+}}_foo_l29()
-// GPU: call i32 @base(double -3.000000e+00)
+// GPU: define {{.*}}void @__omp_offloading_{{.+}}_foo_l28()
+// GPU: call i32 @dev(double -3.000000e+00)
 // GPU: call i32 @dev(double -4.000000e+00)
 
-// GPU: define {{.*}}i32 @base(double
-// GPU: ret i32 0
+// GPU-NOT: @base
 // GPU: define {{.*}}i32 @dev(double
 // GPU: ret i32 0
 
diff --git a/clang/test/OpenMP/declare_variant_mixed_codegen.cpp b/clang/test/OpenMP/declare_variant_mixed_codegen.cpp
--- a/clang/test/OpenMP/declare_variant_mixed_codegen.cpp
+++ b/clang/test/OpenMP/declare_variant_mixed_codegen.cpp
@@ -1,34 +1,30 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-linux -emit-llvm %s -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-linux -emit-llvm %s -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope | FileCheck %s --implicit-check-not='ret i32 {{6|7|8|10|13|15|19|22|23|24}}'
 // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-linux -fexceptions -fcxx-exceptions -emit-pch -o %t -fopenmp-version=50 %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-linux -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -fopenmp-version=50 | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-linux -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -fopenmp-version=50 | FileCheck %s --implicit-check-not='ret i32 {{6|7|8|10|13|15|19|22|23|24}}'
+
 // expected-no-diagnostics
 
-// CHECK-NOT: ret i32 {{1|4|81|84}}
-// CHECK-DAG: @_Z3barv = {{.*}}alias i32 (), i32 ()* @_Z3foov
-// CHECK-DAG: @_ZN16SpecSpecialFuncs6MethodEv = {{.*}}alias i32 (%struct.SpecSpecialFuncs*), i32 (%struct.SpecSpecialFuncs*)* @_ZN16SpecSpecialFuncs7method_Ev
-// CHECK-DAG: @_ZN16SpecSpecialFuncs6methodEv = linkonce_odr {{.*}}alias i32 (%struct.SpecSpecialFuncs*), i32 (%struct.SpecSpecialFuncs*)* @_ZN16SpecSpecialFuncs7method_Ev
-// CHECK-DAG: @_ZN12SpecialFuncs6methodEv = linkonce_odr {{.*}}alias i32 (%struct.SpecialFuncs*), i32 (%struct.SpecialFuncs*)* @_ZN12SpecialFuncs7method_Ev
-// CHECK-DAG: @_Z5prio_v = {{.*}}alias i32 (), i32 ()* @_Z5prio1v
-// CHECK-DAG: @_ZL6prio1_v = internal alias i32 (), i32 ()* @_ZL5prio2v
-// CHECK-DAG: @_Z4callv = {{.*}}alias i32 (), i32 ()* @_Z4testv
-// CHECK-DAG: @_ZL9stat_usedv = internal alias i32 (), i32 ()* @_ZL10stat_used_v
-// CHECK-DAG: @_ZN12SpecialFuncs6MethodEv = {{.*}}alias i32 (%struct.SpecialFuncs*), i32 (%struct.SpecialFuncs*)* @_ZN12SpecialFuncs7method_Ev
-// CHECK-DAG: @fn_linkage = {{.*}}alias i32 (), i32 ()* @_Z18fn_linkage_variantv
-// CHECK-DAG: @_Z11fn_linkage1v = {{.*}}alias i32 (), i32 ()* @fn_linkage_variant1
-// CHECK-DAG: declare {{.*}}i32 @_Z5bazzzv()
-// CHECK-DAG: declare {{.*}}i32 @_Z3bazv()
-// CHECK-DAG: ret i32 2
-// CHECK-DAG: ret i32 3
-// CHECK-DAG: ret i32 5
-// CHECK-DAG: ret i32 6
-// CHECK-DAG: ret i32 7
-// CHECK-DAG: ret i32 82
-// CHECK-DAG: ret i32 83
-// CHECK-DAG: ret i32 85
-// CHECK-DAG: ret i32 86
-// CHECK-DAG: ret i32 87
-// CHECK-DAG: ret i32 88
-// CHECK-NOT: ret i32 {{1|4|81|84}}
+// CHECK-DAG:  ret i32 2
+// CHECK-DAG:  ret i32 3
+// CHECK-DAG:  ret i32 4
+// CHECK-DAG:  ret i32 5
+// CHECK-DAG:  ret i32 9
+// CHECK-DAG:  ret i32 11
+// CHECK-DAG:  ret i32 12
+// CHECK-DAG:  ret i32 14
+// CHECK-DAG:  ret i32 16
+// CHECK-DAG:  ret i32 17
+// CHECK-DAG:  ret i32 18
+// CHECK-DAG:  ret i32 19
+// CHECK-DAG:  ret i32 20
+// CHECK-DAG:  ret i32 21
+// CHECK-DAG:  ret i32 25
+// CHECK-DAG:  ret i32 26
+// CHECK-DAG:  ret i32 27
+// CHECK-DAG:  ret i32 28
+// CHECK-DAG:  ret i32 29
+// CHECK-DAG:  ret i32 30
+// CHECK-DAG:  ret i32 31
 
 #ifndef HEADER
 #define HEADER
@@ -36,47 +32,47 @@
 int foo() { return 2; }
 
 #pragma omp declare variant(foo) match(implementation = {vendor(llvm)}, device={kind(cpu)})
-int bar() { return 1; }
+int bar() { return 3; }
 
 int bazzz();
 #pragma omp declare variant(bazzz) match(implementation = {vendor(llvm)}, device={kind(host)})
-int baz() { return 1; }
+int baz() { return 4; }
 
 int test();
 #pragma omp declare variant(test) match(implementation = {vendor(llvm)}, device={kind(cpu)})
-int call() { return 1; }
+int call() { return 5; }
 
-static int stat_unused_no_emit() { return 1; }
+static int stat_unused_no_emit() { return 6; }
 static int stat_unused_();
 #pragma omp declare variant(stat_unused_) match(implementation = {vendor(llvm)}, device={kind(cpu)})
 #pragma omp declare variant(stat_unused_no_emit) match(implementation = {vendor(unknown)}, device = {kind(gpu)})
-static int stat_unused() { return 1; }
+static int stat_unused() { return 7; }
 
 static int stat_used_();
 #pragma omp declare variant(stat_used_) match(implementation = {vendor(llvm)}, device={kind(host)})
-static int stat_used() { return 1; }
+static int stat_used() { return 8; }
 
 int main() { return bar() + baz() + call() + stat_used(); }
 
-int test() { return 3; }
-static int stat_unused_() { return 4; }
-static int stat_used_() { return 5; }
+int test() { return 9; }
+static int stat_unused_() { return 10; }
+static int stat_used_() { return 11; }
 
 struct SpecialFuncs {
   void vd() {}
   SpecialFuncs();
   ~SpecialFuncs();
 
-  int method_() { return 6; }
+  int method_() { return 12; }
 #pragma omp declare variant(SpecialFuncs::method_)                             \
     match(implementation = {vendor(llvm)}, device={kind(cpu)})
-  int method() { return 1; }
+  int method() { return 13; }
 #pragma omp declare variant(SpecialFuncs::method_)                             \
     match(implementation = {vendor(llvm)}, device={kind(host)})
   int Method();
 } s;
 
-int SpecialFuncs::Method() { return 1; }
+int SpecialFuncs::Method() { return 14; }
 
 struct SpecSpecialFuncs {
   void vd() {}
@@ -86,60 +82,60 @@
   int method_();
 #pragma omp declare variant(SpecSpecialFuncs::method_)                         \
     match(implementation = {vendor(llvm)}, device={kind(cpu)})
-  int method() { return 1; }
+  int method() { return 15; }
 #pragma omp declare variant(SpecSpecialFuncs::method_)                         \
     match(implementation = {vendor(llvm)}, device={kind(host)})
   int Method();
 } s1;
 
-int SpecSpecialFuncs::method_() { return 7; }
-int SpecSpecialFuncs::Method() { return 1; }
+int SpecSpecialFuncs::method_() { return 16; }
+int SpecSpecialFuncs::Method() { return 17; }
 
 void xxx() {
   (void)s.method();
   (void)s1.method();
 }
 
-int prio() { return 81; }
-int prio1() { return 82; }
+int prio() { return 18; }
+int prio1() { return 19; }
 
 #pragma omp declare variant(prio1) match(implementation = {vendor(score(2): llvm)}, device={kind(cpu,host)})
 #pragma omp declare variant(prio) match(implementation = {vendor(score(1): llvm)}, device={kind(cpu)})
-int prio_() { return 1; }
+int prio_() { return 20; }
 
-static int prio2() { return 83; }
-static int prio3() { return 84; }
-static int prio4() { return 84; }
+static int prio2() { return 21; }
+static int prio3() { return 22; }
+static int prio4() { return 23; }
 
 #pragma omp declare variant(prio4) match(implementation = {vendor(score(5): llvm)})
 #pragma omp declare variant(prio2) match(implementation = {vendor(score(8): llvm)}, device={kind(cpu,host)})
 #pragma omp declare variant(prio3) match(implementation = {vendor(score(7): llvm)}, device={kind(cpu)})
-static int prio1_() { return 1; }
+static int prio1_() { return 24; }
 
 int int_fn() { return prio1_(); }
 
-int fn_linkage_variant() { return 85; }
+int fn_linkage_variant() { return 25; }
 extern "C" {
 #pragma omp declare variant(fn_linkage_variant) match(implementation = {vendor(llvm)}, device={kind(cpu)})
-int fn_linkage() { return 1; }
+int fn_linkage() { return 26; }
 }
 
-extern "C" int fn_linkage_variant1() { return 86; }
+extern "C" int fn_linkage_variant1() { return 27; }
 #pragma omp declare variant(fn_linkage_variant1) match(implementation = {vendor(llvm)}, device={kind(host)})
-int fn_linkage1() { return 1; }
+int fn_linkage1() { return 28; }
 
-int fn_variant2() { return 1; }
+int fn_variant2() { return 29; }
 #pragma omp declare variant(fn_variant2) match(implementation = {vendor(llvm, ibm)}, device={kind(cpu)})
 #pragma omp declare variant(fn_variant2) match(implementation = {vendor(llvm)}, device={kind(cpu,gpu)})
 #pragma omp declare variant(fn_variant2) match(implementation = {vendor(llvm)}, device={kind(nohost)})
 #pragma omp declare variant(fn_variant2) match(implementation = {vendor(llvm)}, device={kind(cpu,nohost)})
 #pragma omp declare variant(fn_variant2) match(implementation = {vendor(llvm)}, device={kind(gpu)})
 #pragma omp declare variant(fn_variant2) match(implementation = {vendor(llvm)}, device={kind(fpga)})
-int fn2() { return 87; }
+int fn2() { return 30; }
 
 #pragma omp declare variant(stat_unused_no_emit) match(implementation = {vendor(unknown)}, device = {kind(gpu)})
 template <typename T>
-static T stat_unused_T() { return 88; }
+static T stat_unused_T() { return 31; }
 
 int bazzzzzzzz() {
   return stat_unused_T<int>();
diff --git a/clang/test/OpenMP/nvptx_declare_variant_device_kind_codegen.cpp b/clang/test/OpenMP/nvptx_declare_variant_device_kind_codegen.cpp
--- a/clang/test/OpenMP/nvptx_declare_variant_device_kind_codegen.cpp
+++ b/clang/test/OpenMP/nvptx_declare_variant_device_kind_codegen.cpp
@@ -1,43 +1,28 @@
 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -fopenmp-version=50 -DGPU
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fopenmp-version=50 -DGPU | FileCheck %s --implicit-check-not='ret i32 {{1|81|84}}'
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fopenmp-version=50 -DGPU | FileCheck %s --implicit-check-not='ret i32 {{6|7|9|10|12|14|17|18|20|21|22|23|24|26}}'
 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t -fopenmp-version=50 -DGPU
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - -fopenmp-version=50 -DGPU | FileCheck %s --implicit-check-not='ret i32 {{1|81|84}}'
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - -fopenmp-version=50 -DGPU | FileCheck %s --implicit-check-not='ret i32 {{6|7|9|10|12|14|17|18|20|21|22|23|24|26}}'
 
 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -fopenmp-version=50 -DNOHOST
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fopenmp-version=50 -DNOHOST | FileCheck %s --implicit-check-not='ret i32 {{1|81|84}}'
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fopenmp-version=50 -DNOHOST | FileCheck %s --implicit-check-not='ret i32 {{6|7|9|10|12|14|17|18|20|21|22|23|24|26}}'
 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t -fopenmp-version=50 -DNOHOST
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - -fopenmp-version=50 -DNOHOST | FileCheck %s --implicit-check-not='ret i32 {{1|81|84}}'
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - -fopenmp-version=50 -DNOHOST | FileCheck %s --implicit-check-not='ret i32 {{6|7|9|10|12|14|17|18|20|21|22|23|24|26}}'
 // expected-no-diagnostics
 
-// CHECK-NOT: ret i32 {{1|81|84}}
-// CHECK-DAG: define {{.*}}i32 @_Z3barv()
-// CHECK-DAG: define {{.*}}i32 @_ZN16SpecSpecialFuncs6MethodEv(%struct.SpecSpecialFuncs* %{{.+}})
-// CHECK-DAG: define {{.*}}i32 @_ZN12SpecialFuncs6MethodEv(%struct.SpecialFuncs* %{{.+}})
-// CHECK-DAG: define linkonce_odr {{.*}}i32 @_ZN16SpecSpecialFuncs6methodEv(%struct.SpecSpecialFuncs* %{{.+}})
-// CHECK-DAG: define linkonce_odr {{.*}}i32 @_ZN12SpecialFuncs6methodEv(%struct.SpecialFuncs* %{{.+}})
-// CHECK-DAG: define {{.*}}i32 @_Z5prio_v()
-// CHECK-DAG: define internal i32 @_ZL6prio1_v()
-// CHECK-DAG: define {{.*}}i32 @_Z4callv()
-// CHECK-DAG: define internal i32 @_ZL9stat_usedv()
-// CHECK-DAG: define {{.*}}i32 @fn_linkage()
-// CHECK-DAG: define {{.*}}i32 @_Z11fn_linkage1v()
-
 // CHECK-DAG: ret i32 2
 // CHECK-DAG: ret i32 3
 // CHECK-DAG: ret i32 4
 // CHECK-DAG: ret i32 5
-// CHECK-DAG: ret i32 6
-// CHECK-DAG: ret i32 7
-// CHECK-DAG: ret i32 82
-// CHECK-DAG: ret i32 83
-// CHECK-DAG: ret i32 85
-// CHECK-DAG: ret i32 86
-// CHECK-DAG: ret i32 87
-
-// Outputs for function members
-// CHECK-DAG: ret i32 6
-// CHECK-DAG: ret i32 7
-// CHECK-NOT: ret i32 {{1|81|84}}
+// CHECK-DAG: ret i32 8
+// CHECK-DAG: ret i32 11
+// CHECK-DAG: ret i32 13
+// CHECK-DAG: ret i32 15
+// CHECK-DAG: ret i32 16
+// CHECK-DAG: ret i32 19
+// CHECK-DAG: ret i32 25
+
+// Outputs for function members checked via implicit filecheck flag
+
 
 #ifndef HEADER
 #define HEADER
@@ -62,19 +47,19 @@
 #pragma omp declare target
 
 #pragma omp declare variant(foo) match(device = {kind(CORRECT)})
-int bar() { return 1; }
+int bar() { return 3; }
 
 #pragma omp declare variant(bazzz) match(device = {kind(CORRECT)})
-int baz() { return 1; }
+int baz() { return 4; }
 
 #pragma omp declare variant(test) match(device = {kind(CORRECT)})
-int call() { return 1; }
+int call() { return 5; }
 
 #pragma omp declare variant(stat_unused_) match(device = {kind(CORRECT)})
-static int stat_unused() { return 1; }
+static int stat_unused() { return 6; }
 
 #pragma omp declare variant(stat_used_) match(device = {kind(CORRECT)})
-static int stat_used() { return 1; }
+static int stat_used() { return 7; }
 
 #pragma omp end declare target
 
@@ -86,9 +71,9 @@
   return res;
 }
 
-int test() { return 3; }
-static int stat_unused_() { return 4; }
-static int stat_used_() { return 5; }
+int test() { return 8; }
+static int stat_unused_() { return 9; }
+static int stat_used_() { return 10; }
 
 #pragma omp declare target
 
@@ -96,17 +81,16 @@
   void vd() {}
   SpecialFuncs();
   ~SpecialFuncs();
-
-  int method_() { return 6; }
+  int method_() { return 11; }
 #pragma omp declare variant(SpecialFuncs::method_) \
     match(device = {kind(CORRECT)})
-  int method() { return 1; }
+  int method() { return 12; }
 #pragma omp declare variant(SpecialFuncs::method_) \
     match(device = {kind(CORRECT)})
   int Method();
 } s;
 
-int SpecialFuncs::Method() { return 1; }
+int SpecialFuncs::Method() { return 13; }
 
 struct SpecSpecialFuncs {
   void vd() {}
@@ -116,7 +100,7 @@
   int method_();
 #pragma omp declare variant(SpecSpecialFuncs::method_) \
     match(device = {kind(CORRECT)})
-  int method() { return 1; }
+  int method() { return 14; }
 #pragma omp declare variant(SpecSpecialFuncs::method_) \
     match(device = {kind(CORRECT)})
   int Method();
@@ -124,17 +108,17 @@
 
 #pragma omp end declare target
 
-int SpecSpecialFuncs::method_() { return 7; }
-int SpecSpecialFuncs::Method() { return 1; }
+int SpecSpecialFuncs::method_() { return 15; }
+int SpecSpecialFuncs::Method() { return 16; }
 
-int prio() { return 81; }
-int prio1() { return 82; }
-static int prio2() { return 83; }
-static int prio3() { return 84; }
-static int prio4() { return 84; }
-int fn_linkage_variant() { return 85; }
-extern "C" int fn_linkage_variant1() { return 86; }
-int fn_variant2() { return 1; }
+int prio() { return 17; }
+int prio1() { return 18; }
+static int prio2() { return 19; }
+static int prio3() { return 20; }
+static int prio4() { return 21; }
+int fn_linkage_variant() { return 22; }
+extern "C" int fn_linkage_variant1() { return 23; }
+int fn_variant2() { return 24; }
 
 #pragma omp declare target
 
@@ -145,25 +129,25 @@
 
 #pragma omp declare variant(prio) match(device = {kind(SUBSET)})
 #pragma omp declare variant(prio1) match(device = {kind(CORRECT)})
-int prio_() { return 1; }
+int prio_() { return 25; }
 
 #pragma omp declare variant(prio4) match(device = {kind(SUBSET)})
 #pragma omp declare variant(prio2) match(device = {kind(CORRECT)})
 #pragma omp declare variant(prio3) match(device = {kind(SUBSET)})
-static int prio1_() { return 1; }
+static int prio1_() { return 26; }
 
 int int_fn() { return prio1_(); }
 
 extern "C" {
 #pragma omp declare variant(fn_linkage_variant) match(device = {kind(CORRECT)})
-int fn_linkage() { return 1; }
+int fn_linkage() { return 27; }
 }
 
 #pragma omp declare variant(fn_linkage_variant1) match(device = {kind(CORRECT)})
-int fn_linkage1() { return 1; }
+int fn_linkage1() { return 28; }
 
 #pragma omp declare variant(fn_variant2) match(device = {kind(WRONG)})
-int fn2() { return 87; }
+int fn2() { return 29; }
 
 #pragma omp end declare target
 
diff --git a/clang/test/OpenMP/nvptx_declare_variant_implementation_vendor_codegen.cpp b/clang/test/OpenMP/nvptx_declare_variant_implementation_vendor_codegen.cpp
--- a/clang/test/OpenMP/nvptx_declare_variant_implementation_vendor_codegen.cpp
+++ b/clang/test/OpenMP/nvptx_declare_variant_implementation_vendor_codegen.cpp
@@ -1,38 +1,20 @@
 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -fopenmp-version=50
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fopenmp-version=50 | FileCheck %s --implicit-check-not='ret i32 {{1|81|84}}'
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fopenmp-version=50 | FileCheck %s --implicit-check-not='ret i32 {{6|7|8|9|10|12|13|14|15|17|18|19|20|21|22|23|24|26}}'
 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t -fopenmp-version=50
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - -fopenmp-version=50 | FileCheck %s --implicit-check-not='ret i32 {{1|81|84}}'
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -aux-triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - -fopenmp-version=50 | FileCheck %s --implicit-check-not='ret i32 {{6|7|8|9|10|12|13|14|15|17|18|19|20|21|22|23|24|26}}'
 // expected-no-diagnostics
 
-// CHECK-NOT: ret i32 {{1|81|84}}
-// CHECK-DAG: define {{.*}}i32 @_Z3barv()
-// CHECK-DAG: define {{.*}}i32 @_ZN16SpecSpecialFuncs6MethodEv(%struct.SpecSpecialFuncs* %{{.+}})
-// CHECK-DAG: define {{.*}}i32 @_ZN12SpecialFuncs6MethodEv(%struct.SpecialFuncs* %{{.+}})
-// CHECK-DAG: define linkonce_odr {{.*}}i32 @_ZN16SpecSpecialFuncs6methodEv(%struct.SpecSpecialFuncs* %{{.+}})
-// CHECK-DAG: define linkonce_odr {{.*}}i32 @_ZN12SpecialFuncs6methodEv(%struct.SpecialFuncs* %{{.+}})
-// CHECK-DAG: define {{.*}}i32 @_Z5prio_v()
-// CHECK-DAG: define internal i32 @_ZL6prio1_v()
-// CHECK-DAG: define {{.*}}i32 @_Z4callv()
-// CHECK-DAG: define internal i32 @_ZL9stat_usedv()
-// CHECK-DAG: define {{.*}}i32 @fn_linkage()
-// CHECK-DAG: define {{.*}}i32 @_Z11fn_linkage1v()
-
-// CHECK-DAG: ret i32 2
-// CHECK-DAG: ret i32 3
-// CHECK-DAG: ret i32 4
-// CHECK-DAG: ret i32 5
-// CHECK-DAG: ret i32 6
-// CHECK-DAG: ret i32 7
-// CHECK-DAG: ret i32 82
-// CHECK-DAG: ret i32 83
-// CHECK-DAG: ret i32 85
-// CHECK-DAG: ret i32 86
-// CHECK-DAG: ret i32 87
-
-// Outputs for function members
-// CHECK-DAG: ret i32 6
-// CHECK-DAG: ret i32 7
-// CHECK-NOT: ret i32 {{1|81|84}}
+// CHECK-DAG:  ret i32 2
+// CHECK-DAG:  ret i32 3
+// CHECK-DAG:  ret i32 4
+// CHECK-DAG:  ret i32 5
+// CHECK-DAG:  ret i32 11
+// CHECK-DAG:  ret i32 16
+// CHECK-DAG:  ret i32 19
+// CHECK-DAG:  ret i32 25
+// CHECK-DAG:  ret i32 27
+// CHECK-DAG:  ret i32 28
+// CHECK-DAG:  ret i32 29
 
 #ifndef HEADER
 #define HEADER
@@ -46,19 +28,19 @@
 #pragma omp declare target
 
 #pragma omp declare variant(foo) match(implementation = {vendor(llvm)})
-int bar() { return 1; }
+int bar() { return 3; }
 
 #pragma omp declare variant(bazzz) match(implementation = {vendor(llvm)})
-int baz() { return 1; }
+int baz() { return 4; }
 
 #pragma omp declare variant(test) match(implementation = {vendor(llvm)})
-int call() { return 1; }
+int call() { return 5; }
 
 #pragma omp declare variant(stat_unused_) match(implementation = {vendor(llvm)})
-static int stat_unused() { return 1; }
+static int stat_unused() { return 6; }
 
 #pragma omp declare variant(stat_used_) match(implementation = {vendor(llvm)})
-static int stat_used() { return 1; }
+static int stat_used() { return 7; }
 
 #pragma omp end declare target
 
@@ -70,9 +52,9 @@
   return res;
 }
 
-int test() { return 3; }
-static int stat_unused_() { return 4; }
-static int stat_used_() { return 5; }
+int test() { return 8; }
+static int stat_unused_() { return 9; }
+static int stat_used_() { return 10; }
 
 #pragma omp declare target
 
@@ -81,16 +63,16 @@
   SpecialFuncs();
   ~SpecialFuncs();
 
-  int method_() { return 6; }
+  int method_() { return 11; }
 #pragma omp declare variant(SpecialFuncs::method_) \
     match(implementation = {vendor(llvm)})
-  int method() { return 1; }
+  int method() { return 12; }
 #pragma omp declare variant(SpecialFuncs::method_) \
     match(implementation = {vendor(llvm)})
   int Method();
 } s;
 
-int SpecialFuncs::Method() { return 1; }
+int SpecialFuncs::Method() { return 13; }
 
 struct SpecSpecialFuncs {
   void vd() {}
@@ -100,7 +82,7 @@
   int method_();
 #pragma omp declare variant(SpecSpecialFuncs::method_) \
     match(implementation = {vendor(llvm)})
-  int method() { return 1; }
+  int method() { return 14; }
 #pragma omp declare variant(SpecSpecialFuncs::method_) \
     match(implementation = {vendor(llvm)})
   int Method();
@@ -108,17 +90,17 @@
 
 #pragma omp end declare target
 
-int SpecSpecialFuncs::method_() { return 7; }
-int SpecSpecialFuncs::Method() { return 1; }
+int SpecSpecialFuncs::method_() { return 15; }
+int SpecSpecialFuncs::Method() { return 16; }
 
-int prio() { return 81; }
-int prio1() { return 82; }
-static int prio2() { return 83; }
-static int prio3() { return 84; }
-static int prio4() { return 84; }
-int fn_linkage_variant() { return 85; }
-extern "C" int fn_linkage_variant1() { return 86; }
-int fn_variant2() { return 1; }
+int prio() { return 17; }
+int prio1() { return 18; }
+static int prio2() { return 19; }
+static int prio3() { return 20; }
+static int prio4() { return 21; }
+int fn_linkage_variant() { return 22; }
+extern "C" int fn_linkage_variant1() { return 23; }
+int fn_variant2() { return 24; }
 
 #pragma omp declare target
 
@@ -130,7 +112,7 @@
 #pragma omp declare variant(prio) match(implementation = {vendor(llvm)})
 #pragma omp declare variant(prio1) match(implementation = {vendor(score(1) \
                                                                   : llvm)})
-int prio_() { return 1; }
+int prio_() { return 25; }
 
 #pragma omp declare variant(prio4) match(implementation = {vendor(score(3) \
                                                                   : llvm)})
@@ -138,20 +120,20 @@
                                                                   : llvm)})
 #pragma omp declare variant(prio3) match(implementation = {vendor(score(1) \
                                                                   : llvm)})
-static int prio1_() { return 1; }
+static int prio1_() { return 26; }
 
 int int_fn() { return prio1_(); }
 
 extern "C" {
 #pragma omp declare variant(fn_linkage_variant) match(implementation = {vendor(llvm)})
-int fn_linkage() { return 1; }
+int fn_linkage() { return 27; }
 }
 
 #pragma omp declare variant(fn_linkage_variant1) match(implementation = {vendor(llvm)})
-int fn_linkage1() { return 1; }
+int fn_linkage1() { return 28; }
 
 #pragma omp declare variant(fn_variant2) match(implementation = {vendor(llvm, ibm)})
-int fn2() { return 87; }
+int fn2() { return 29; }
 
 #pragma omp end declare target