[clang] b5be1c5 - [OPENMP50]Basic support for uses_allocators clause.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 30 13:39:28 PDT 2020


Author: Alexey Bataev
Date: 2020-04-30T16:24:36-04:00
New Revision: b5be1c5419e2a38eb60fc7e785567b54b6d9e0e0

URL: https://github.com/llvm/llvm-project/commit/b5be1c5419e2a38eb60fc7e785567b54b6d9e0e0
DIFF: https://github.com/llvm/llvm-project/commit/b5be1c5419e2a38eb60fc7e785567b54b6d9e0e0.diff

LOG: [OPENMP50]Basic support for uses_allocators clause.

Summary: Added parsing/sema/serialization supoprt for uses_allocators clause.

Reviewers: jdoerfert

Subscribers: yaxunl, guansong, arphaman, cfe-commits, caomhin

Tags: #clang

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

Added: 
    clang/test/OpenMP/target_uses_allocators_messages.cpp

Modified: 
    clang/include/clang/AST/OpenMPClause.h
    clang/include/clang/AST/RecursiveASTVisitor.h
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Parse/Parser.h
    clang/include/clang/Sema/Sema.h
    clang/lib/AST/OpenMPClause.cpp
    clang/lib/AST/StmtProfile.cpp
    clang/lib/Basic/OpenMPKinds.cpp
    clang/lib/CodeGen/CGStmtOpenMP.cpp
    clang/lib/Parse/ParseOpenMP.cpp
    clang/lib/Sema/SemaOpenMP.cpp
    clang/lib/Sema/TreeTransform.h
    clang/lib/Serialization/ASTReader.cpp
    clang/lib/Serialization/ASTWriter.cpp
    clang/test/OpenMP/target_ast_print.cpp
    clang/test/OpenMP/target_firstprivate_messages.cpp
    clang/test/OpenMP/target_parallel_ast_print.cpp
    clang/test/OpenMP/target_parallel_firstprivate_messages.cpp
    clang/test/OpenMP/target_parallel_for_ast_print.cpp
    clang/test/OpenMP/target_parallel_for_firstprivate_messages.cpp
    clang/test/OpenMP/target_parallel_for_lastprivate_messages.cpp
    clang/test/OpenMP/target_parallel_for_linear_messages.cpp
    clang/test/OpenMP/target_parallel_for_private_messages.cpp
    clang/test/OpenMP/target_parallel_for_reduction_messages.cpp
    clang/test/OpenMP/target_parallel_for_simd_ast_print.cpp
    clang/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp
    clang/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp
    clang/test/OpenMP/target_parallel_for_simd_linear_messages.cpp
    clang/test/OpenMP/target_parallel_for_simd_private_messages.cpp
    clang/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp
    clang/test/OpenMP/target_parallel_private_messages.cpp
    clang/test/OpenMP/target_parallel_reduction_messages.cpp
    clang/test/OpenMP/target_private_messages.cpp
    clang/test/OpenMP/target_reduction_messages.cpp
    clang/test/OpenMP/target_simd_ast_print.cpp
    clang/test/OpenMP/target_simd_firstprivate_messages.cpp
    clang/test/OpenMP/target_simd_lastprivate_messages.cpp
    clang/test/OpenMP/target_simd_linear_messages.cpp
    clang/test/OpenMP/target_simd_private_messages.cpp
    clang/test/OpenMP/target_simd_reduction_messages.cpp
    clang/test/OpenMP/target_teams_ast_print.cpp
    clang/test/OpenMP/target_teams_distribute_ast_print.cpp
    clang/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp
    clang/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_simd_ast_print.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_messages.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp
    clang/test/OpenMP/target_teams_distribute_private_messages.cpp
    clang/test/OpenMP/target_teams_distribute_reduction_messages.cpp
    clang/test/OpenMP/target_teams_distribute_simd_ast_print.cpp
    clang/test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp
    clang/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp
    clang/test/OpenMP/target_teams_distribute_simd_private_messages.cpp
    clang/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp
    clang/test/OpenMP/target_teams_firstprivate_messages.cpp
    clang/test/OpenMP/target_teams_private_messages.cpp
    clang/test/OpenMP/target_teams_reduction_messages.cpp
    clang/tools/libclang/CIndex.cpp
    llvm/include/llvm/Frontend/OpenMP/OMPKinds.def

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index f276611e3d0c..0b49209fb127 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -7127,6 +7127,131 @@ class OMPExclusiveClause final
   }
 };
 
+/// This represents clause 'uses_allocators' in the '#pragma omp target'-based
+/// directives.
+///
+/// \code
+/// #pragma omp target uses_allocators(default_allocator, my_allocator(traits))
+/// \endcode
+/// In this example directive '#pragma omp target' has clause 'uses_allocators'
+/// with the allocators 'default_allocator' and user-defined 'my_allocator'.
+class OMPUsesAllocatorsClause final
+    : public OMPClause,
+      private llvm::TrailingObjects<OMPUsesAllocatorsClause, Expr *,
+                                    SourceLocation> {
+public:
+  /// Data for list of allocators.
+  struct Data {
+    /// Allocator.
+    Expr *Allocator = nullptr;
+    /// Allocator traits.
+    Expr *AllocatorTraits = nullptr;
+    /// Locations of '(' and ')' symbols.
+    SourceLocation LParenLoc, RParenLoc;
+  };
+
+private:
+  friend class OMPClauseReader;
+  friend TrailingObjects;
+
+  enum class ExprOffsets {
+    Allocator,
+    AllocatorTraits,
+    Total,
+  };
+
+  enum class ParenLocsOffsets {
+    LParen,
+    RParen,
+    Total,
+  };
+
+  /// Location of '('.
+  SourceLocation LParenLoc;
+  /// Total number of allocators in the clause.
+  unsigned NumOfAllocators = 0;
+
+  /// Build clause.
+  ///
+  /// \param StartLoc Starting location of the clause.
+  /// \param LParenLoc Location of '('.
+  /// \param EndLoc Ending location of the clause.
+  /// \param N Number of allocators asssociated with the clause.
+  OMPUsesAllocatorsClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+                          SourceLocation EndLoc, unsigned N)
+      : OMPClause(llvm::omp::OMPC_uses_allocators, StartLoc, EndLoc),
+        LParenLoc(LParenLoc), NumOfAllocators(N) {}
+
+  /// Build an empty clause.
+  /// \param N Number of allocators asssociated with the clause.
+  ///
+  explicit OMPUsesAllocatorsClause(unsigned N)
+      : OMPClause(llvm::omp::OMPC_uses_allocators, SourceLocation(),
+                  SourceLocation()),
+        NumOfAllocators(N) {}
+
+  unsigned numTrailingObjects(OverloadToken<Expr *>) const {
+    return NumOfAllocators * static_cast<int>(ExprOffsets::Total);
+  }
+
+  /// Sets the location of '('.
+  void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
+  /// Sets the allocators data for the clause.
+  void setAllocatorsData(ArrayRef<OMPUsesAllocatorsClause::Data> Data);
+
+public:
+  /// Creates clause with a list of allocators \p Data.
+  ///
+  /// \param C AST context.
+  /// \param StartLoc Starting location of the clause.
+  /// \param LParenLoc Location of '('.
+  /// \param EndLoc Ending location of the clause.
+  /// \param Data List of allocators.
+  static OMPUsesAllocatorsClause *
+  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+         SourceLocation EndLoc, ArrayRef<OMPUsesAllocatorsClause::Data> Data);
+
+  /// Creates an empty clause with the place for \p N allocators.
+  ///
+  /// \param C AST context.
+  /// \param N The number of allocators.
+  static OMPUsesAllocatorsClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+  /// Returns the location of '('.
+  SourceLocation getLParenLoc() const { return LParenLoc; }
+
+  /// Returns number of allocators associated with the clause.
+  unsigned getNumberOfAllocators() const { return NumOfAllocators; }
+
+  /// Returns data for the specified allocator.
+  OMPUsesAllocatorsClause::Data getAllocatorData(unsigned I) const;
+
+  // Iterators
+  child_range children() {
+    Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
+    return child_range(Begin, Begin + NumOfAllocators *
+                                          static_cast<int>(ExprOffsets::Total));
+  }
+  const_child_range children() const {
+    Stmt *const *Begin =
+        reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>());
+    return const_child_range(
+        Begin, Begin + NumOfAllocators * static_cast<int>(ExprOffsets::Total));
+  }
+
+  child_range used_children() {
+    return child_range(child_iterator(), child_iterator());
+  }
+  const_child_range used_children() const {
+    return const_child_range(const_child_iterator(), const_child_iterator());
+  }
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == llvm::omp::OMPC_uses_allocators;
+  }
+};
+
 /// This class implements a simple visitor for OMPClause
 /// subclasses.
 template<class ImplClass, template <typename> class Ptr, typename RetTy>

diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index b71f7994e2fa..0680a8f70212 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -3522,6 +3522,17 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDetachClause(OMPDetachClause *C) {
   return true;
 }
 
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPUsesAllocatorsClause(
+    OMPUsesAllocatorsClause *C) {
+  for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
+    const OMPUsesAllocatorsClause::Data Data = C->getAllocatorData(I);
+    TRY_TO(TraverseStmt(Data.Allocator));
+    TRY_TO(TraverseStmt(Data.AllocatorTraits));
+  }
+  return true;
+}
+
 // FIXME: look at the following tricky-seeming exprs to see if we
 // need to recurse on anything.  These are ones that have methods
 // returning decls or qualtypes or nestednamespecifier -- though I'm

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5e9759493975..154da867d00b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10221,8 +10221,8 @@ def note_omp_flush_order_clause_here : Note<
   "memory order clause '%0' is specified here">;
 def err_omp_non_lvalue_in_map_or_motion_clauses: Error<
   "expected addressable lvalue in '%0' clause">;
-def err_omp_event_var_expected : Error<
-  "expected variable of the 'omp_event_handle_t' type%select{|, not %1}0">;
+def err_omp_var_expected : Error<
+  "expected variable of the '%0' type%select{|, not %2}1">;
 def warn_nested_declare_variant
     : Warning<"nesting `omp begin/end declare variant` is not supported yet; "
               "nested context ignored">,
@@ -10233,6 +10233,19 @@ def err_omp_non_pointer_type_array_shaping_base : Error<
 def err_omp_reduction_task_not_parallel_or_worksharing : Error<
   "'reduction' clause with 'task' modifier allowed only on non-simd parallel or"
   " worksharing constructs">;
+def err_omp_expected_array_alloctraits : Error<
+  "expected constant sized array of 'omp_alloctrait_t' elements, not %0">;
+def err_omp_predefined_allocator_with_traits : Error<
+  "predefined allocator cannot have traits specified">;
+def note_omp_predefined_allocator : Note<
+  "predefined trait '%0' used here">;
+def err_omp_nonpredefined_allocator_without_traits : Error<
+  "non-predefined allocator must have traits specified">;
+def err_omp_allocator_used_in_clauses : Error<
+  "allocators used in 'uses_allocators' clause cannot appear in other "
+  "data-sharing or data-mapping attribute clauses">;
+def err_omp_allocator_not_in_uses_allocators : Error<
+  "allocator must be specified in the 'uses_allocators' clause">;
 } // end of OpenMP category
 
 let CategoryName = "Related Result Type Issue" in {

diff  --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index b4e96a5b85de..d8642996de79 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3111,6 +3111,11 @@ class Parser : public CodeCompletionHandler {
   /// <range-specification> }+ ')'
   ExprResult ParseOpenMPIteratorsExpr();
 
+  /// Parses allocators and traits in the context of the uses_allocator clause.
+  /// Expected format:
+  /// '(' { <allocator> [ '(' <allocator_traits> ')' ] }+ ')'
+  OMPClause *ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind);
+
 public:
   /// Parses simple expression in parens for single-expression clauses of OpenMP
   /// constructs.

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index c3c5533b73ec..0c1241f45ef5 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10766,6 +10766,21 @@ class Sema final {
                                           SourceLocation LParenLoc,
                                           SourceLocation EndLoc);
 
+  /// Data for list of allocators.
+  struct UsesAllocatorsData {
+    /// Allocator.
+    Expr *Allocator = nullptr;
+    /// Allocator traits.
+    Expr *AllocatorTraits = nullptr;
+    /// Locations of '(' and ')' symbols.
+    SourceLocation LParenLoc, RParenLoc;
+  };
+  /// Called on well-formed 'uses_allocators' clause.
+  OMPClause *ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc,
+                                            SourceLocation LParenLoc,
+                                            SourceLocation EndLoc,
+                                            ArrayRef<UsesAllocatorsData> Data);
+
   /// The kind of conversion being performed.
   enum CheckedConversionKind {
     /// An implicit conversion.

diff  --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index bd98728c3e4c..d4d398f43c9d 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -150,6 +150,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
   case OMPC_detach:
   case OMPC_inclusive:
   case OMPC_exclusive:
+  case OMPC_uses_allocators:
     break;
   }
 
@@ -239,6 +240,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
   case OMPC_detach:
   case OMPC_inclusive:
   case OMPC_exclusive:
+  case OMPC_uses_allocators:
     break;
   }
 
@@ -1302,6 +1304,70 @@ OMPExclusiveClause *OMPExclusiveClause::CreateEmpty(const ASTContext &C,
   return new (Mem) OMPExclusiveClause(N);
 }
 
+void OMPUsesAllocatorsClause::setAllocatorsData(
+    ArrayRef<OMPUsesAllocatorsClause::Data> Data) {
+  assert(Data.size() == NumOfAllocators &&
+         "Size of allocators data is not the same as the preallocated buffer.");
+  for (unsigned I = 0, E = Data.size(); I < E; ++I) {
+    const OMPUsesAllocatorsClause::Data &D = Data[I];
+    getTrailingObjects<Expr *>()[I * static_cast<int>(ExprOffsets::Total) +
+                                 static_cast<int>(ExprOffsets::Allocator)] =
+        D.Allocator;
+    getTrailingObjects<Expr *>()[I * static_cast<int>(ExprOffsets::Total) +
+                                 static_cast<int>(
+                                     ExprOffsets::AllocatorTraits)] =
+        D.AllocatorTraits;
+    getTrailingObjects<
+        SourceLocation>()[I * static_cast<int>(ParenLocsOffsets::Total) +
+                          static_cast<int>(ParenLocsOffsets::LParen)] =
+        D.LParenLoc;
+    getTrailingObjects<
+        SourceLocation>()[I * static_cast<int>(ParenLocsOffsets::Total) +
+                          static_cast<int>(ParenLocsOffsets::RParen)] =
+        D.RParenLoc;
+  }
+}
+
+OMPUsesAllocatorsClause::Data
+OMPUsesAllocatorsClause::getAllocatorData(unsigned I) const {
+  OMPUsesAllocatorsClause::Data Data;
+  Data.Allocator =
+      getTrailingObjects<Expr *>()[I * static_cast<int>(ExprOffsets::Total) +
+                                   static_cast<int>(ExprOffsets::Allocator)];
+  Data.AllocatorTraits =
+      getTrailingObjects<Expr *>()[I * static_cast<int>(ExprOffsets::Total) +
+                                   static_cast<int>(
+                                       ExprOffsets::AllocatorTraits)];
+  Data.LParenLoc = getTrailingObjects<
+      SourceLocation>()[I * static_cast<int>(ParenLocsOffsets::Total) +
+                        static_cast<int>(ParenLocsOffsets::LParen)];
+  Data.RParenLoc = getTrailingObjects<
+      SourceLocation>()[I * static_cast<int>(ParenLocsOffsets::Total) +
+                        static_cast<int>(ParenLocsOffsets::RParen)];
+  return Data;
+}
+
+OMPUsesAllocatorsClause *
+OMPUsesAllocatorsClause::Create(const ASTContext &C, SourceLocation StartLoc,
+                                SourceLocation LParenLoc, SourceLocation EndLoc,
+                                ArrayRef<OMPUsesAllocatorsClause::Data> Data) {
+  void *Mem = C.Allocate(totalSizeToAlloc<Expr *, SourceLocation>(
+      static_cast<int>(ExprOffsets::Total) * Data.size(),
+      static_cast<int>(ParenLocsOffsets::Total) * Data.size()));
+  auto *Clause = new (Mem)
+      OMPUsesAllocatorsClause(StartLoc, LParenLoc, EndLoc, Data.size());
+  Clause->setAllocatorsData(Data);
+  return Clause;
+}
+
+OMPUsesAllocatorsClause *
+OMPUsesAllocatorsClause::CreateEmpty(const ASTContext &C, unsigned N) {
+  void *Mem = C.Allocate(totalSizeToAlloc<Expr *, SourceLocation>(
+      static_cast<int>(ExprOffsets::Total) * N,
+      static_cast<int>(ParenLocsOffsets::Total) * N));
+  return new (Mem) OMPUsesAllocatorsClause(N);
+}
+
 //===----------------------------------------------------------------------===//
 //  OpenMP clauses printing methods
 //===----------------------------------------------------------------------===//
@@ -1884,6 +1950,25 @@ void OMPClausePrinter::VisitOMPExclusiveClause(OMPExclusiveClause *Node) {
   }
 }
 
+void OMPClausePrinter::VisitOMPUsesAllocatorsClause(
+    OMPUsesAllocatorsClause *Node) {
+  if (Node->getNumberOfAllocators() == 0)
+    return;
+  OS << "uses_allocators(";
+  for (unsigned I = 0, E = Node->getNumberOfAllocators(); I < E; ++I) {
+    OMPUsesAllocatorsClause::Data Data = Node->getAllocatorData(I);
+    Data.Allocator->printPretty(OS, nullptr, Policy);
+    if (Data.AllocatorTraits) {
+      OS << "(";
+      Data.AllocatorTraits->printPretty(OS, nullptr, Policy);
+      OS << ")";
+    }
+    if (I < E - 1)
+      OS << ",";
+  }
+  OS << ")";
+}
+
 void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx,
                                          VariantMatchInfo &VMI) const {
   for (const OMPTraitSet &Set : Sets) {

diff  --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index be0bc13ccb4d..869d2fa15b25 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -800,6 +800,15 @@ void OMPClauseProfiler::VisitOMPInclusiveClause(const OMPInclusiveClause *C) {
 void OMPClauseProfiler::VisitOMPExclusiveClause(const OMPExclusiveClause *C) {
   VisitOMPClauseList(C);
 }
+void OMPClauseProfiler::VisitOMPUsesAllocatorsClause(
+    const OMPUsesAllocatorsClause *C) {
+  for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
+    OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
+    Profiler->VisitStmt(D.Allocator);
+    if (D.AllocatorTraits)
+      Profiler->VisitStmt(D.AllocatorTraits);
+  }
+}
 void OMPClauseProfiler::VisitOMPOrderClause(const OMPOrderClause *C) {}
 } // namespace
 

diff  --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 888666b30d2e..841d76ba27ed 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -174,6 +174,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
   case OMPC_detach:
   case OMPC_inclusive:
   case OMPC_exclusive:
+  case OMPC_uses_allocators:
     break;
   }
   llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -420,6 +421,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
   case OMPC_detach:
   case OMPC_inclusive:
   case OMPC_exclusive:
+  case OMPC_uses_allocators:
     break;
   }
   llvm_unreachable("Invalid OpenMP simple clause kind");

diff  --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index cbc08ac2efb4..19bbcb83b8db 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -4627,6 +4627,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
   case OMPC_detach:
   case OMPC_inclusive:
   case OMPC_exclusive:
+  case OMPC_uses_allocators:
     llvm_unreachable("Clause is not allowed in 'omp atomic'.");
   }
 }

diff  --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 0c0ef154805c..19acfe1158fb 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -2436,6 +2436,50 @@ bool Parser::ParseOpenMPSimpleVarList(
   return !IsCorrect;
 }
 
+OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
+  SourceLocation Loc = Tok.getLocation();
+  ConsumeAnyToken();
+
+  // Parse '('.
+  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+  if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
+    return nullptr;
+  SmallVector<Sema::UsesAllocatorsData, 4> Data;
+  do {
+    ExprResult Allocator = ParseCXXIdExpression();
+    if (Allocator.isInvalid()) {
+      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+                StopBeforeMatch);
+      break;
+    }
+    Sema::UsesAllocatorsData &D = Data.emplace_back();
+    D.Allocator = Allocator.get();
+    if (Tok.is(tok::l_paren)) {
+      BalancedDelimiterTracker T(*this, tok::l_paren,
+                                 tok::annot_pragma_openmp_end);
+      T.consumeOpen();
+      ExprResult AllocatorTraits = ParseCXXIdExpression();
+      T.consumeClose();
+      if (AllocatorTraits.isInvalid()) {
+        SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+                  StopBeforeMatch);
+        break;
+      }
+      D.AllocatorTraits = AllocatorTraits.get();
+      D.LParenLoc = T.getOpenLocation();
+      D.RParenLoc = T.getCloseLocation();
+    }
+    if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
+      Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
+    // Parse ','
+    if (Tok.is(tok::comma))
+      ConsumeAnyToken();
+  } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
+  T.consumeClose();
+  return Actions.ActOnOpenMPUsesAllocatorClause(Loc, T.getOpenLocation(),
+                                                T.getCloseLocation(), Data);
+}
+
 /// Parsing of OpenMP clauses.
 ///
 ///    clause:
@@ -2453,7 +2497,7 @@ bool Parser::ParseOpenMPSimpleVarList(
 ///       in_reduction-clause | allocator-clause | allocate-clause |
 ///       acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
 ///       depobj-clause | destroy-clause | detach-clause | inclusive-clause |
-///       exclusive-clause
+///       exclusive-clause | uses_allocators-clause
 ///
 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
                                      OpenMPClauseKind CKind, bool FirstClause) {
@@ -2626,6 +2670,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
   case OMPC_exclusive:
     Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
     break;
+  case OMPC_uses_allocators:
+    Clause = ParseOpenMPUsesAllocatorClause(DKind);
+    break;
   case OMPC_device_type:
   case OMPC_unknown:
     skipUntilPragmaOpenMPEnd(DKind);

diff  --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 41bfca9c72f8..7364af70a856 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -170,6 +170,7 @@ class DSAStackTy {
     llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
     /// List of decls used in inclusive/exclusive clauses of the scan directive.
     llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
+    llvm::DenseSet<CanonicalDeclPtr<const Decl>> UsesAllocatorsDecls;
     SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
                  Scope *CurScope, SourceLocation Loc)
         : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
@@ -279,6 +280,8 @@ class DSAStackTy {
   QualType OMPDependT;
   /// omp_event_handle_t type.
   QualType OMPEventHandleT;
+  /// omp_alloctrait_t type.
+  QualType OMPAlloctraitT;
   /// Expression for the predefined allocators.
   Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
       nullptr};
@@ -293,6 +296,10 @@ class DSAStackTy {
   void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
   /// Gets omp_allocator_handle_t type.
   QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
+  /// Sets omp_alloctrait_t type.
+  void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
+  /// Gets omp_alloctrait_t type.
+  QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
   /// Sets the given default allocator.
   void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
                     Expr *Allocator) {
@@ -1006,6 +1013,19 @@ class DSAStackTy {
   bool isImplicitTaskFirstprivate(Decl *D) const {
     return getTopOfStack().ImplicitTaskFirstprivates.count(D) > 0;
   }
+
+  /// Marks decl as used in uses_allocators clause as the allocator.
+  void addUsesAllocatorsDecl(const Decl *D) {
+    getTopOfStack().UsesAllocatorsDecls.insert(D);
+  }
+  /// Checks if specified decl is used in uses allocator clause as the
+  /// allocator.
+  bool isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
+    return getStackElemAtLevel(Level).UsesAllocatorsDecls.count(D) > 0;
+  }
+  bool isUsesAllocatorsDecl(const Decl *D) const {
+    return getTopOfStack().UsesAllocatorsDecls.count(D) > 0;
+  }
 };
 
 bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
@@ -1990,10 +2010,13 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
         ((IsVariableUsedInMapClause &&
           DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
               OMPD_target) ||
-         !DSAStack->hasExplicitDSA(
-             D,
-             [](OpenMPClauseKind K) -> bool { return K == OMPC_firstprivate; },
-             Level, /*NotLastprivate=*/true)) &&
+         !(DSAStack->hasExplicitDSA(
+               D,
+               [](OpenMPClauseKind K) -> bool {
+                 return K == OMPC_firstprivate;
+               },
+               Level, /*NotLastprivate=*/true) ||
+           DSAStack->isUsesAllocatorsDecl(Level, D))) &&
         // If the variable is artificial and must be captured by value - try to
         // capture by value.
         !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
@@ -2435,6 +2458,11 @@ static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
                                  bool WithInit);
 
+static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
+                              const ValueDecl *D,
+                              const DSAStackTy::DSAVarData &DVar,
+                              bool IsLoopIterVar = false);
+
 void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
   // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
   //  A variable of class type (or array thereof) that appears in a lastprivate
@@ -2504,6 +2532,51 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
         Clause->setPrivateRefs(PrivateRefs);
         continue;
       }
+      if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
+        for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
+          OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
+          auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
+          if (!DRE)
+            continue;
+          ValueDecl *VD = DRE->getDecl();
+          if (!VD)
+            continue;
+          DSAStackTy::DSAVarData DVar =
+              DSAStack->getTopDSA(VD, /*FromParent=*/false);
+          // OpenMP [2.12.5, target Construct]
+          // Memory allocators that appear in a uses_allocators clause cannot
+          // appear in other data-sharing attribute clauses or data-mapping
+          // attribute clauses in the same construct.
+          Expr *MapExpr = nullptr;
+          if (DVar.RefExpr ||
+              DSAStack->checkMappableExprComponentListsForDecl(
+                  VD, /*CurrentRegionOnly=*/true,
+                  [VD, &MapExpr](
+                      OMPClauseMappableExprCommon::MappableExprComponentListRef
+                          MapExprComponents,
+                      OpenMPClauseKind C) {
+                    auto MI = MapExprComponents.rbegin();
+                    auto ME = MapExprComponents.rend();
+                    if (MI != ME &&
+                        MI->getAssociatedDeclaration()->getCanonicalDecl() ==
+                            VD->getCanonicalDecl()) {
+                      MapExpr = MI->getAssociatedExpression();
+                      return true;
+                    }
+                    return false;
+                  })) {
+            Diag(D.Allocator->getExprLoc(),
+                 diag::err_omp_allocator_used_in_clauses)
+                << D.Allocator->getSourceRange();
+            if (DVar.RefExpr)
+              reportOriginalDsa(*this, DSAStack, VD, DVar);
+            else
+              Diag(MapExpr->getExprLoc(), diag::note_used_here)
+                  << MapExpr->getSourceRange();
+          }
+        }
+        continue;
+      }
     }
     // Check allocate clauses.
     if (!CurContext->isDependentContext())
@@ -3032,7 +3105,7 @@ OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc,
 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
                               const ValueDecl *D,
                               const DSAStackTy::DSAVarData &DVar,
-                              bool IsLoopIterVar = false) {
+                              bool IsLoopIterVar) {
   if (DVar.RefExpr) {
     SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
         << getOpenMPClauseName(DVar.CKind);
@@ -3187,6 +3260,9 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
       if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
           !Stack->isImplicitTaskFirstprivate(VD))
         return;
+      // Skip allocators in uses_allocators clauses.
+      if (Stack->isUsesAllocatorsDecl(VD))
+        return;
 
       DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
       // Check if the variable has explicit DSA set and stop analysis if it so.
@@ -4640,6 +4716,27 @@ static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
       getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
 }
 
+namespace {
+/// Checks if the allocator is used in uses_allocators clause to be allowed in
+/// target regions.
+class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
+  DSAStackTy *S = nullptr;
+
+public:
+  bool VisitDeclRefExpr(const DeclRefExpr *E) {
+    return !S->isUsesAllocatorsDecl(E->getDecl());
+  }
+  bool VisitStmt(const Stmt *S) {
+    for (const Stmt *Child : S->children()) {
+      if (Child && Visit(Child))
+        return true;
+    }
+    return false;
+  }
+  explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
+};
+} // namespace
+
 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
                                  ArrayRef<OMPClause *> Clauses) {
   assert(!S.CurContext->isDependentContext() &&
@@ -4708,6 +4805,22 @@ static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
   }
   for (OMPClause *C : AllocateRange) {
     auto *AC = cast<OMPAllocateClause>(C);
+    if (S.getLangOpts().OpenMP >= 50 &&
+        !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
+        isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
+        AC->getAllocator()) {
+      Expr *Allocator = AC->getAllocator();
+      // OpenMP, 2.12.5 target Construct
+      // Memory allocators that do not appear in a uses_allocators clause cannot
+      // appear as an allocator in an allocate clause or be used in the target
+      // region unless a requires directive with the dynamic_allocators clause
+      // is present in the same compilation unit.
+      AllocatorChecker Checker(Stack);
+      if (Checker.Visit(Allocator))
+        S.Diag(Allocator->getExprLoc(),
+               diag::err_omp_allocator_not_in_uses_allocators)
+            << Allocator->getSourceRange();
+    }
     OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
         getAllocatorKind(S, Stack, AC->getAllocator());
     // OpenMP, 2.11.4 allocate Clause, Restrictions.
@@ -5239,6 +5352,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
       case OMPC_destroy:
       case OMPC_inclusive:
       case OMPC_exclusive:
+      case OMPC_uses_allocators:
         continue;
       case OMPC_allocator:
       case OMPC_flush:
@@ -11365,6 +11479,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
   case OMPC_destroy:
   case OMPC_inclusive:
   case OMPC_exclusive:
+  case OMPC_uses_allocators:
     llvm_unreachable("Clause is not allowed.");
   }
   return Res;
@@ -12118,6 +12233,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
   case OMPC_detach:
   case OMPC_inclusive:
   case OMPC_exclusive:
+  case OMPC_uses_allocators:
     llvm_unreachable("Unexpected OpenMP clause.");
   }
   return CaptureRegion;
@@ -12557,6 +12673,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
   case OMPC_detach:
   case OMPC_inclusive:
   case OMPC_exclusive:
+  case OMPC_uses_allocators:
     llvm_unreachable("Clause is not allowed.");
   }
   return Res;
@@ -12782,6 +12899,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
   case OMPC_detach:
   case OMPC_inclusive:
   case OMPC_exclusive:
+  case OMPC_uses_allocators:
     llvm_unreachable("Clause is not allowed.");
   }
   return Res;
@@ -13014,6 +13132,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
   case OMPC_detach:
   case OMPC_inclusive:
   case OMPC_exclusive:
+  case OMPC_uses_allocators:
     llvm_unreachable("Clause is not allowed.");
   }
   return Res;
@@ -13279,6 +13398,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
   case OMPC_order:
   case OMPC_destroy:
   case OMPC_detach:
+  case OMPC_uses_allocators:
     llvm_unreachable("Clause is not allowed.");
   }
   return Res;
@@ -17719,21 +17839,22 @@ OMPClause *Sema::ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc,
     // event-handle is a variable of the omp_event_handle_t type.
     auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
     if (!Ref) {
-      Diag(Evt->getExprLoc(), diag::err_omp_event_var_expected)
-          << 0 << Evt->getSourceRange();
+      Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
+          << "omp_event_handle_t" << 0 << Evt->getSourceRange();
       return nullptr;
     }
     auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
     if (!VD) {
-      Diag(Evt->getExprLoc(), diag::err_omp_event_var_expected)
-          << 0 << Evt->getSourceRange();
+      Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
+          << "omp_event_handle_t" << 0 << Evt->getSourceRange();
       return nullptr;
     }
     if (!Context.hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
                                         VD->getType()) ||
         VD->getType().isConstant(Context)) {
-      Diag(Evt->getExprLoc(), diag::err_omp_event_var_expected)
-          << 1 << VD->getType() << Evt->getSourceRange();
+      Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
+          << "omp_event_handle_t" << 1 << VD->getType()
+          << Evt->getSourceRange();
       return nullptr;
     }
     // OpenMP 5.0, 2.10.1 task Construct
@@ -18450,3 +18571,134 @@ OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
 
   return OMPExclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
 }
+
+/// Tries to find omp_alloctrait_t type.
+static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
+  QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
+  if (!OMPAlloctraitT.isNull())
+    return true;
+  IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
+  ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
+  if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
+    S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
+    return false;
+  }
+  Stack->setOMPAlloctraitT(PT.get());
+  return true;
+}
+
+OMPClause *Sema::ActOnOpenMPUsesAllocatorClause(
+    SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
+    ArrayRef<UsesAllocatorsData> Data) {
+  // OpenMP [2.12.5, target Construct]
+  // allocator is an identifier of omp_allocator_handle_t type.
+  if (!findOMPAllocatorHandleT(*this, StartLoc, DSAStack))
+    return nullptr;
+  // OpenMP [2.12.5, target Construct]
+  // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
+  if (llvm::any_of(
+          Data,
+          [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
+      !findOMPAlloctraitT(*this, StartLoc, DSAStack))
+    return nullptr;
+  llvm::SmallSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
+  for (int I = OMPAllocateDeclAttr::OMPDefaultMemAlloc;
+       I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
+    auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
+    StringRef Allocator =
+        OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
+    DeclarationName AllocatorName = &Context.Idents.get(Allocator);
+    PredefinedAllocators.insert(LookupSingleName(
+        TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
+  }
+
+  SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
+  for (const UsesAllocatorsData &D : Data) {
+    Expr *AllocatorExpr = nullptr;
+    // Check allocator expression.
+    if (D.Allocator->isTypeDependent()) {
+      AllocatorExpr = D.Allocator;
+    } else {
+      // Traits were specified - need to assign new allocator to the specified
+      // allocator, so it must be an lvalue.
+      AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
+      auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
+      bool IsPredefinedAllocator = false;
+      if (DRE)
+        IsPredefinedAllocator = PredefinedAllocators.count(DRE->getDecl());
+      if (!DRE ||
+          !(Context.hasSameUnqualifiedType(
+                AllocatorExpr->getType(), DSAStack->getOMPAllocatorHandleT()) ||
+            Context.typesAreCompatible(AllocatorExpr->getType(),
+                                       DSAStack->getOMPAllocatorHandleT(),
+                                       /*CompareUnqualified=*/true)) ||
+          (!IsPredefinedAllocator &&
+           (AllocatorExpr->getType().isConstant(Context) ||
+            !AllocatorExpr->isLValue()))) {
+        Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
+            << "omp_allocator_handle_t" << (DRE ? 1 : 0)
+            << AllocatorExpr->getType() << D.Allocator->getSourceRange();
+        continue;
+      }
+      // OpenMP [2.12.5, target Construct]
+      // Predefined allocators appearing in a uses_allocators clause cannot have
+      // traits specified.
+      if (IsPredefinedAllocator && D.AllocatorTraits) {
+        Diag(D.AllocatorTraits->getExprLoc(),
+             diag::err_omp_predefined_allocator_with_traits)
+            << D.AllocatorTraits->getSourceRange();
+        Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
+            << cast<NamedDecl>(DRE->getDecl())->getName()
+            << D.Allocator->getSourceRange();
+        continue;
+      }
+      // OpenMP [2.12.5, target Construct]
+      // Non-predefined allocators appearing in a uses_allocators clause must
+      // have traits specified.
+      if (!IsPredefinedAllocator && !D.AllocatorTraits) {
+        Diag(D.Allocator->getExprLoc(),
+             diag::err_omp_nonpredefined_allocator_without_traits);
+        continue;
+      }
+      // No allocator traits - just convert it to rvalue.
+      if (!D.AllocatorTraits)
+        AllocatorExpr = DefaultLvalueConversion(AllocatorExpr).get();
+      DSAStack->addUsesAllocatorsDecl(DRE->getDecl());
+    }
+    Expr *AllocatorTraitsExpr = nullptr;
+    if (D.AllocatorTraits) {
+      if (D.AllocatorTraits->isTypeDependent()) {
+        AllocatorTraitsExpr = D.AllocatorTraits;
+      } else {
+        // OpenMP [2.12.5, target Construct]
+        // Arrays that contain allocator traits that appear in a uses_allocators
+        // clause must be constant arrays, have constant values and be defined
+        // in the same scope as the construct in which the clause appears.
+        AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
+        // Check that traits expr is a constant array.
+        QualType TraitTy;
+        if (const ArrayType *Ty =
+                AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
+          if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
+            TraitTy = ConstArrayTy->getElementType();
+        if (TraitTy.isNull() ||
+            !(Context.hasSameUnqualifiedType(TraitTy,
+                                             DSAStack->getOMPAlloctraitT()) ||
+              Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
+                                         /*CompareUnqualified=*/true))) {
+          Diag(D.AllocatorTraits->getExprLoc(),
+               diag::err_omp_expected_array_alloctraits)
+              << AllocatorTraitsExpr->getType();
+          continue;
+        }
+      }
+    }
+    OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
+    NewD.Allocator = AllocatorExpr;
+    NewD.AllocatorTraits = AllocatorTraitsExpr;
+    NewD.LParenLoc = D.LParenLoc;
+    NewD.RParenLoc = D.RParenLoc;
+  }
+  return OMPUsesAllocatorsClause::Create(Context, StartLoc, LParenLoc, EndLoc,
+                                         NewData);
+}

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index da6ff8e5cea8..0987fee29182 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -2086,6 +2086,17 @@ class TreeTransform {
                                                 EndLoc);
   }
 
+  /// Build a new OpenMP 'uses_allocators' clause.
+  ///
+  /// By default, performs semantic analysis to build the new OpenMP clause.
+  /// Subclasses may override this routine to provide 
diff erent behavior.
+  OMPClause *RebuildOMPUsesAllocatorsClause(
+      ArrayRef<Sema::UsesAllocatorsData> Data, SourceLocation StartLoc,
+      SourceLocation LParenLoc, SourceLocation EndLoc) {
+    return getSema().ActOnOpenMPUsesAllocatorClause(StartLoc, LParenLoc, EndLoc,
+                                                    Data);
+  }
+
   /// Build a new OpenMP 'order' clause.
   ///
   /// By default, performs semantic analysis to build the new OpenMP clause.
@@ -9673,8 +9684,33 @@ TreeTransform<Derived>::TransformOMPExclusiveClause(OMPExclusiveClause *C) {
 }
 
 template <typename Derived>
-OMPClause *
-TreeTransform<Derived>::TransformOMPOrderClause(OMPOrderClause *C) {
+OMPClause *TreeTransform<Derived>::TransformOMPUsesAllocatorsClause(
+    OMPUsesAllocatorsClause *C) {
+  SmallVector<Sema::UsesAllocatorsData, 16> Data;
+  Data.reserve(C->getNumberOfAllocators());
+  for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
+    OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
+    ExprResult Allocator = getDerived().TransformExpr(D.Allocator);
+    if (Allocator.isInvalid())
+      continue;
+    ExprResult AllocatorTraits;
+    if (Expr *AT = D.AllocatorTraits) {
+      AllocatorTraits = getDerived().TransformExpr(AT);
+      if (AllocatorTraits.isInvalid())
+        continue;
+    }
+    Sema::UsesAllocatorsData &NewD = Data.emplace_back();
+    NewD.Allocator = Allocator.get();
+    NewD.AllocatorTraits = AllocatorTraits.get();
+    NewD.LParenLoc = D.LParenLoc;
+    NewD.RParenLoc = D.RParenLoc;
+  }
+  return getDerived().RebuildOMPUsesAllocatorsClause(
+      Data, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPOrderClause(OMPOrderClause *C) {
   return getDerived().RebuildOMPOrderClause(C->getKind(), C->getKindKwLoc(),
                                             C->getBeginLoc(), C->getLParenLoc(),
                                             C->getEndLoc());

diff  --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 873115835e5c..3ead713b5e06 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -11882,6 +11882,9 @@ OMPClause *OMPClauseReader::readClause() {
   case llvm::omp::OMPC_detach:
     C = new (Context) OMPDetachClause();
     break;
+  case llvm::omp::OMPC_uses_allocators:
+    C = OMPUsesAllocatorsClause::CreateEmpty(Context, Record.readInt());
+    break;
 #define OMP_CLAUSE_NO_CLASS(Enum, Str)                                         \
   case llvm::omp::Enum:                                                        \
     break;
@@ -12710,6 +12713,21 @@ void OMPClauseReader::VisitOMPExclusiveClause(OMPExclusiveClause *C) {
   C->setVarRefs(Vars);
 }
 
+void OMPClauseReader::VisitOMPUsesAllocatorsClause(OMPUsesAllocatorsClause *C) {
+  C->setLParenLoc(Record.readSourceLocation());
+  unsigned NumOfAllocators = C->getNumberOfAllocators();
+  SmallVector<OMPUsesAllocatorsClause::Data, 4> Data;
+  Data.reserve(NumOfAllocators);
+  for (unsigned I = 0; I != NumOfAllocators; ++I) {
+    OMPUsesAllocatorsClause::Data &D = Data.emplace_back();
+    D.Allocator = Record.readSubExpr();
+    D.AllocatorTraits = Record.readSubExpr();
+    D.LParenLoc = Record.readSourceLocation();
+    D.RParenLoc = Record.readSourceLocation();
+  }
+  C->setAllocatorsData(Data);
+}
+
 void OMPClauseReader::VisitOMPOrderClause(OMPOrderClause *C) {
   C->setKind(Record.readEnum<OpenMPOrderClauseKind>());
   C->setLParenLoc(Record.readSourceLocation());

diff  --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 748ac06c5643..462f27578c0f 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -6651,6 +6651,18 @@ void OMPClauseWriter::VisitOMPOrderClause(OMPOrderClause *C) {
   Record.AddSourceLocation(C->getKindKwLoc());
 }
 
+void OMPClauseWriter::VisitOMPUsesAllocatorsClause(OMPUsesAllocatorsClause *C) {
+  Record.push_back(C->getNumberOfAllocators());
+  Record.AddSourceLocation(C->getLParenLoc());
+  for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
+    OMPUsesAllocatorsClause::Data Data = C->getAllocatorData(I);
+    Record.AddStmt(Data.Allocator);
+    Record.AddStmt(Data.AllocatorTraits);
+    Record.AddSourceLocation(Data.LParenLoc);
+    Record.AddSourceLocation(Data.RParenLoc);
+  }
+}
+
 void ASTRecordWriter::writeOMPTraitInfo(const OMPTraitInfo *TI) {
   writeUInt32(TI->Sets.size());
   for (const auto &Set : TI->Sets) {

diff  --git a/clang/test/OpenMP/target_ast_print.cpp b/clang/test/OpenMP/target_ast_print.cpp
index 1ff0b2bc1e1a..b2125ac3d77c 100644
--- a/clang/test/OpenMP/target_ast_print.cpp
+++ b/clang/test/OpenMP/target_ast_print.cpp
@@ -341,6 +341,16 @@ int main (int argc, char **argv) {
 // RUN: %clang_cc1 -DOMP5 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
 // RUN: %clang_cc1 -DOMP5 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s --check-prefix OMP5
 
+typedef void **omp_allocator_handle_t;
+extern const omp_allocator_handle_t omp_default_mem_alloc;
+extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
+extern const omp_allocator_handle_t omp_const_mem_alloc;
+extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
+extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
+extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
+extern const omp_allocator_handle_t omp_pteam_mem_alloc;
+extern const omp_allocator_handle_t omp_thread_mem_alloc;
+
 void foo() {}
 
 #pragma omp declare target
@@ -1050,8 +1060,12 @@ int main (int argc, char **argv) {
 // OMP5-NEXT: bar();
 #pragma omp target defaultmap(none)
   // OMP5-NEXT: #pragma omp target defaultmap(none)
+  // OMP5-NEXT: bar();
   bar();
+#pragma omp target allocate(omp_default_mem_alloc:argv) uses_allocators(omp_default_mem_alloc,omp_large_cap_mem_alloc) allocate(omp_large_cap_mem_alloc:argc) private(argc, argv)
+  // OMP5-NEXT: #pragma omp target allocate(omp_default_mem_alloc: argv) uses_allocators(omp_default_mem_alloc,omp_large_cap_mem_alloc) allocate(omp_large_cap_mem_alloc: argc) private(argc,argv)
   // OMP5-NEXT: bar();
+  bar();
   return tmain<int, 5>(argc, &argc) + tmain<char, 1>(argv[0][0], argv[0]);
 }
 

diff  --git a/clang/test/OpenMP/target_firstprivate_messages.cpp b/clang/test/OpenMP/target_firstprivate_messages.cpp
index 0a3079bbf83e..ab68501517f9 100644
--- a/clang/test/OpenMP/target_firstprivate_messages.cpp
+++ b/clang/test/OpenMP/target_firstprivate_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 void xxx(int argc) {
   int fp, fp1; // expected-note {{initialize the variable 'fp' to silence this warning}} expected-note {{initialize the variable 'fp1' to silence this warning}}
@@ -128,7 +128,7 @@ int foomain(I argc, C **argv) {
 {}
 #pragma omp target firstprivate(argv[1]) // expected-error {{expected variable name}}
 {}
-#pragma omp target firstprivate(e, g) allocate(omp_thread_mem_alloc: e) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target' directive}}
+#pragma omp target firstprivate(e, g) allocate(omp_thread_mem_alloc: e) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target' directive}} expected-error {{allocator must be specified in the 'uses_allocators' clause}}
 {}
 #pragma omp target firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
 {}

diff  --git a/clang/test/OpenMP/target_parallel_ast_print.cpp b/clang/test/OpenMP/target_parallel_ast_print.cpp
index aa101386b22a..fd3b724cf5ea 100644
--- a/clang/test/OpenMP/target_parallel_ast_print.cpp
+++ b/clang/test/OpenMP/target_parallel_ast_print.cpp
@@ -10,6 +10,16 @@
 #ifndef HEADER
 #define HEADER
 
+typedef void **omp_allocator_handle_t;
+extern const omp_allocator_handle_t omp_default_mem_alloc;
+extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
+extern const omp_allocator_handle_t omp_const_mem_alloc;
+extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
+extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
+extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
+extern const omp_allocator_handle_t omp_pteam_mem_alloc;
+extern const omp_allocator_handle_t omp_thread_mem_alloc;
+
 void foo() {}
 
 template <class T>
@@ -41,7 +51,7 @@ T tmain(T argc, T *argv) {
   T i, j, a[20];
 #pragma omp target parallel
   h=2;
-#pragma omp target parallel allocate(argv) default(none), private(argc,b) firstprivate(argv) shared (d) if (parallel:argc > 0) num_threads(C) proc_bind(master) reduction(+:c, arr1[argc]) reduction(max:e, arr[:C][0:10])
+#pragma omp target parallel allocate(omp_large_cap_mem_alloc:argv) default(none), private(argc,b) firstprivate(argv) shared (d) if (parallel:argc > 0) num_threads(C) proc_bind(master) reduction(+:c, arr1[argc]) reduction(max:e, arr[:C][0:10]) uses_allocators(omp_large_cap_mem_alloc)
   foo();
 #pragma omp target parallel if (C) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:C][:argc]) reduction(&& : g) allocate(g)
   foo();
@@ -76,7 +86,7 @@ T tmain(T argc, T *argv) {
 // CHECK-NEXT: T i, j, a[20]
 // CHECK-NEXT: #pragma omp target parallel{{$}}
 // CHECK-NEXT: h = 2;
-// CHECK-NEXT: #pragma omp target parallel allocate(argv) default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(C) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:C][0:10])
+// CHECK-NEXT: #pragma omp target parallel allocate(omp_large_cap_mem_alloc: argv) default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(C) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:C][0:10]) uses_allocators(omp_large_cap_mem_alloc)
 // CHECK-NEXT: foo()
 // CHECK-NEXT: #pragma omp target parallel if(C) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g) allocate(g)
 // CHECK-NEXT: foo()
@@ -108,7 +118,7 @@ T tmain(T argc, T *argv) {
 // CHECK-NEXT: int i, j, a[20]
 // CHECK-NEXT: #pragma omp target parallel
 // CHECK-NEXT: h = 2;
-// CHECK-NEXT: #pragma omp target parallel allocate(argv) default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10])
+// CHECK-NEXT: #pragma omp target parallel allocate(omp_large_cap_mem_alloc: argv) default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10]) uses_allocators(omp_large_cap_mem_alloc)
 // CHECK-NEXT: foo()
 // CHECK-NEXT: #pragma omp target parallel if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: g) allocate(g)
 // CHECK-NEXT: foo()
@@ -140,7 +150,7 @@ T tmain(T argc, T *argv) {
 // CHECK-NEXT: char i, j, a[20]
 // CHECK-NEXT: #pragma omp target parallel
 // CHECK-NEXT: h = 2;
-// CHECK-NEXT: #pragma omp target parallel allocate(argv) default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(1) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:1][0:10])
+// CHECK-NEXT: #pragma omp target parallel allocate(omp_large_cap_mem_alloc: argv) default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(1) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:1][0:10]) uses_allocators(omp_large_cap_mem_alloc)
 // CHECK-NEXT: foo()
 // CHECK-NEXT: #pragma omp target parallel if(1) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:1][:argc]) reduction(&&: g) allocate(g)
 // CHECK-NEXT: foo()

diff  --git a/clang/test/OpenMP/target_parallel_firstprivate_messages.cpp b/clang/test/OpenMP/target_parallel_firstprivate_messages.cpp
index 11be23cab8dc..be7812ed7147 100644
--- a/clang/test/OpenMP/target_parallel_firstprivate_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_firstprivate_messages.cpp
@@ -2,6 +2,8 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
+
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_parallel_for_ast_print.cpp b/clang/test/OpenMP/target_parallel_for_ast_print.cpp
index 6a5637e2ba74..82f1bf347460 100644
--- a/clang/test/OpenMP/target_parallel_for_ast_print.cpp
+++ b/clang/test/OpenMP/target_parallel_for_ast_print.cpp
@@ -10,6 +10,16 @@
 #ifndef HEADER
 #define HEADER
 
+typedef void **omp_allocator_handle_t;
+extern const omp_allocator_handle_t omp_default_mem_alloc;
+extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
+extern const omp_allocator_handle_t omp_const_mem_alloc;
+extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
+extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
+extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
+extern const omp_allocator_handle_t omp_pteam_mem_alloc;
+extern const omp_allocator_handle_t omp_thread_mem_alloc;
+
 void foo() {}
 
 struct S {
@@ -195,8 +205,8 @@ int main(int argc, char **argv) {
 // CHECK-NEXT: #pragma omp target parallel for default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10])
   // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
   // CHECK-NEXT: }
-#pragma omp target parallel for if (5) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:5][:argc]) reduction(&& : h)
-// CHECK-NEXT: #pragma omp target parallel for if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: h)
+#pragma omp target parallel for if (5) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:5][:argc]) reduction(&& : h) allocate(omp_const_mem_alloc: h) uses_allocators(omp_const_mem_alloc)
+// CHECK-NEXT: #pragma omp target parallel for if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: h) allocate(omp_const_mem_alloc: h) uses_allocators(omp_const_mem_alloc)
   for (int i = 0; i < 2; ++i) {}
   // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
   // CHECK-NEXT: }

diff  --git a/clang/test/OpenMP/target_parallel_for_firstprivate_messages.cpp b/clang/test/OpenMP/target_parallel_for_firstprivate_messages.cpp
index 0a103edc5822..b2744b66bd2a 100644
--- a/clang/test/OpenMP/target_parallel_for_firstprivate_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_firstprivate_messages.cpp
@@ -2,6 +2,7 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_parallel_for_lastprivate_messages.cpp b/clang/test/OpenMP/target_parallel_for_lastprivate_messages.cpp
index 23ee0a6a6be3..73f8ae624703 100644
--- a/clang/test/OpenMP/target_parallel_for_lastprivate_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_lastprivate_messages.cpp
@@ -196,7 +196,7 @@ int main(int argc, char **argv) {
 #pragma omp target parallel for lastprivate(2 * 2) // expected-error {{expected variable name}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp target parallel for lastprivate(ba) allocate(omp_thread_mem_alloc: ba) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel for' directive}}
+#pragma omp target parallel for lastprivate(ba) allocate(omp_thread_mem_alloc: ba) uses_allocators(omp_thread_mem_alloc) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel for' directive}} omp45-error {{unexpected OpenMP clause 'uses_allocators' in directive '#pragma omp target parallel for'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target parallel for lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}

diff  --git a/clang/test/OpenMP/target_parallel_for_linear_messages.cpp b/clang/test/OpenMP/target_parallel_for_linear_messages.cpp
index adb6c786a3b1..abd0b16a1bfc 100644
--- a/clang/test/OpenMP/target_parallel_for_linear_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_linear_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -170,7 +170,7 @@ int foomain(I argc, C **argv) {
 #pragma omp target parallel for linear(argv[1]) // expected-error {{expected variable name}}
   for (int k = 0; k < argc; ++k)
     ++k;
-#pragma omp target parallel for allocate(omp_thread_mem_alloc: e) linear(e, g) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel for' directive}}
+#pragma omp target parallel for allocate(omp_thread_mem_alloc: e) linear(e, g) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel for' directive}} expected-error {{allocator must be specified in the 'uses_allocators' clause}}
   for (int k = 0; k < argc; ++k)
     ++k;
 #pragma omp target parallel for linear(z, h) // expected-error {{threadprivate or thread local variable cannot be linear}}

diff  --git a/clang/test/OpenMP/target_parallel_for_private_messages.cpp b/clang/test/OpenMP/target_parallel_for_private_messages.cpp
index 124eadb61de7..8db615cfa7b3 100644
--- a/clang/test/OpenMP/target_parallel_for_private_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_private_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -138,7 +138,7 @@ int foomain(I argc, C **argv) {
 #pragma omp target parallel for private(argv[1]) // expected-error {{expected variable name}}
   for (int k = 0; k < argc; ++k)
     ++k;
-#pragma omp target parallel for private(e, g) allocate(omp_thread_mem_alloc: e) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel for' directive}}
+#pragma omp target parallel for private(e, g) allocate(omp_thread_mem_alloc: e) uses_allocators(omp_thread_mem_alloc) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel for' directive}}
   for (int k = 0; k < argc; ++k)
     ++k;
 #pragma omp target parallel for private(h) // expected-error {{threadprivate or thread local variable cannot be private}}

diff  --git a/clang/test/OpenMP/target_parallel_for_reduction_messages.cpp b/clang/test/OpenMP/target_parallel_for_reduction_messages.cpp
index b73b2c2d5eec..5019e24593c7 100644
--- a/clang/test/OpenMP/target_parallel_for_reduction_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_reduction_messages.cpp
@@ -341,7 +341,7 @@ int main(int argc, char **argv) {
   for (int i = 0; i < 10; ++i)
     foo();
   static int m;
-#pragma omp target parallel for allocate(omp_thread_mem_alloc: m) reduction(+ : m) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel for' directive}}
+#pragma omp target parallel for allocate(omp_thread_mem_alloc: m) reduction(+ : m) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel for' directive}} omp50-error {{allocator must be specified in the 'uses_allocators' clause}}
   for (int i = 0; i < 10; ++i)
     m++;
 

diff  --git a/clang/test/OpenMP/target_parallel_for_simd_ast_print.cpp b/clang/test/OpenMP/target_parallel_for_simd_ast_print.cpp
index f9a6430880e5..db335f0eddf8 100644
--- a/clang/test/OpenMP/target_parallel_for_simd_ast_print.cpp
+++ b/clang/test/OpenMP/target_parallel_for_simd_ast_print.cpp
@@ -16,6 +16,16 @@
 #ifndef HEADER
 #define HEADER
 
+typedef void **omp_allocator_handle_t;
+extern const omp_allocator_handle_t omp_default_mem_alloc;
+extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
+extern const omp_allocator_handle_t omp_const_mem_alloc;
+extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
+extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
+extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
+extern const omp_allocator_handle_t omp_pteam_mem_alloc;
+extern const omp_allocator_handle_t omp_thread_mem_alloc;
+
 void foo() {}
 
 struct S {
@@ -115,13 +125,13 @@ T tmain(T argc, T *argv) {
   // CHECK-NEXT: }
 
 #ifdef OMP5
-#pragma omp target parallel for simd if(target:argc > 0) if (simd: argc) nontemporal(argc, c, d) order(concurrent)
+#pragma omp target parallel for simd if(target:argc > 0) if (simd: argc) nontemporal(argc, c, d) order(concurrent) allocate(omp_high_bw_mem_alloc:f) private(f) uses_allocators(omp_high_bw_mem_alloc)
 #else
 #pragma omp target parallel for simd if(target:argc > 0)
 #endif // OMP5
   for (T i = 0; i < 2; ++i) {}
   // OMP45: #pragma omp target parallel for simd if(target: argc > 0)
-  // OMP50: #pragma omp target parallel for simd if(target: argc > 0) if(simd: argc) nontemporal(argc,c,d) order(concurrent)
+  // OMP50: #pragma omp target parallel for simd if(target: argc > 0) if(simd: argc) nontemporal(argc,c,d) order(concurrent) allocate(omp_high_bw_mem_alloc: f) private(f) uses_allocators(omp_high_bw_mem_alloc)
   // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
   // CHECK-NEXT: }
 

diff  --git a/clang/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp
index 4a25753ba528..78ef6965e091 100644
--- a/clang/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp
@@ -2,6 +2,8 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
+
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp
index 05dff0e2c9f3..7d179decc1b4 100644
--- a/clang/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp
@@ -101,7 +101,7 @@ int foomain(int argc, char **argv) {
 #pragma omp target parallel for simd lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
   for (int k = 0; k < argc; ++k)
     ++k;
-#pragma omp target parallel for simd allocate(omp_thread_mem_alloc: argc) lastprivate(argc) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel for simd' directive}}
+#pragma omp target parallel for simd allocate(omp_thread_mem_alloc: argc) lastprivate(argc) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel for simd' directive}} omp50-error {{allocator must be specified in the 'uses_allocators' clause}}
   for (int k = 0; k < argc; ++k)
     ++k;
 #pragma omp target parallel for simd lastprivate(conditional: argc,s) lastprivate(conditional: // omp50-error {{expected expression}} omp45-error 2 {{use of undeclared identifier 'conditional'}} expected-error {{expected ')'}} expected-note {{to match this '('}} omp45-error 2 {{calling a private constructor of class 'S6'}} omp50-error {{expected list item of scalar type in 'lastprivate' clause with 'conditional' modifier}}

diff  --git a/clang/test/OpenMP/target_parallel_for_simd_linear_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_linear_messages.cpp
index 56abe2ad85ce..9ef8d501fc58 100644
--- a/clang/test/OpenMP/target_parallel_for_simd_linear_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_simd_linear_messages.cpp
@@ -2,6 +2,8 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
+
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_parallel_for_simd_private_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_private_messages.cpp
index 6a0f40e28539..0ac51b879409 100644
--- a/clang/test/OpenMP/target_parallel_for_simd_private_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_simd_private_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -68,7 +68,7 @@ class S6 {
 
   S6() : a(0) {}
   S6(T v) : a(v) {
-#pragma omp target parallel for simd allocate(omp_thread_mem_alloc: a) private(a) private(this->a) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel for simd' directive}}
+#pragma omp target parallel for simd allocate(omp_thread_mem_alloc: a) private(a) private(this->a) uses_allocators(omp_thread_mem_alloc) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel for simd' directive}}
     for (int k = 0; k < v; ++k)
       ++this->a;
   }

diff  --git a/clang/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp
index f00d9984b6e4..8fa32d96718c 100644
--- a/clang/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp
@@ -12,6 +12,8 @@
 // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -std=c++98 -ferror-limit 150 -o - %s -Wuninitialized
 // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -std=c++11 -ferror-limit 150 -o - %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
+
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_parallel_private_messages.cpp b/clang/test/OpenMP/target_parallel_private_messages.cpp
index a23c2ea2f1ab..a12599017cab 100644
--- a/clang/test/OpenMP/target_parallel_private_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_private_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -96,7 +96,7 @@ int foomain(I argc, C **argv) {
 {}
 #pragma omp target parallel private(argv[1]) // expected-error {{expected variable name}}
 {}
-#pragma omp target parallel allocate(omp_thread_mem_alloc: ba) private(ba) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel' directive}}
+#pragma omp target parallel allocate(omp_thread_mem_alloc: ba) private(ba) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel' directive}} expected-error {{allocator must be specified in the 'uses_allocators' clause}}
 {}
 #pragma omp target parallel private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
 {}

diff  --git a/clang/test/OpenMP/target_parallel_reduction_messages.cpp b/clang/test/OpenMP/target_parallel_reduction_messages.cpp
index 8ecdcfb75dff..eeae218692b6 100644
--- a/clang/test/OpenMP/target_parallel_reduction_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_reduction_messages.cpp
@@ -179,7 +179,7 @@ T tmain(T argc) {
 #pragma omp for private(fl)
   for (int i = 0; i < 10; ++i)
   {}
-#pragma omp target parallel reduction(+ : fl) allocate(omp_thread_mem_alloc: fl) // expected-warning 2 {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel' directive}}
+#pragma omp target parallel reduction(+ : fl) allocate(omp_thread_mem_alloc: fl) uses_allocators(omp_thread_mem_alloc) // expected-warning 2 {{allocator with the 'thread' trait access has unspecified behavior on 'target parallel' directive}} omp45-error {{unexpected OpenMP clause 'uses_allocators' in directive '#pragma omp target parallel'}}
     foo();
 #pragma omp target parallel
 #pragma omp for reduction(- : fl)

diff  --git a/clang/test/OpenMP/target_private_messages.cpp b/clang/test/OpenMP/target_private_messages.cpp
index 2b9fd35c05c6..7b3f928217fe 100644
--- a/clang/test/OpenMP/target_private_messages.cpp
+++ b/clang/test/OpenMP/target_private_messages.cpp
@@ -2,6 +2,7 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_reduction_messages.cpp b/clang/test/OpenMP/target_reduction_messages.cpp
index 92aacfe07065..fff6d90e6f03 100644
--- a/clang/test/OpenMP/target_reduction_messages.cpp
+++ b/clang/test/OpenMP/target_reduction_messages.cpp
@@ -177,7 +177,7 @@ T tmain(T argc) {
 #pragma omp parallel
 #pragma omp for private(fl)
   for (int i = 0; i < 10; ++i)
-#pragma omp target reduction(+ : fl) allocate(omp_thread_mem_alloc: fl) // expected-warning 2 {{allocator with the 'thread' trait access has unspecified behavior on 'target' directive}}
+#pragma omp target reduction(+ : fl) allocate(omp_thread_mem_alloc: fl) // expected-warning 2 {{allocator with the 'thread' trait access has unspecified behavior on 'target' directive}} omp50-error 2 {{allocator must be specified in the 'uses_allocators' clause}}
     foo();
 #pragma omp parallel
 #pragma omp for reduction(- : fl)

diff  --git a/clang/test/OpenMP/target_simd_ast_print.cpp b/clang/test/OpenMP/target_simd_ast_print.cpp
index 0d18131675f2..976eeed7ada1 100644
--- a/clang/test/OpenMP/target_simd_ast_print.cpp
+++ b/clang/test/OpenMP/target_simd_ast_print.cpp
@@ -16,6 +16,16 @@
 #ifndef HEADER
 #define HEADER
 
+typedef void **omp_allocator_handle_t;
+extern const omp_allocator_handle_t omp_default_mem_alloc;
+extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
+extern const omp_allocator_handle_t omp_const_mem_alloc;
+extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
+extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
+extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
+extern const omp_allocator_handle_t omp_pteam_mem_alloc;
+extern const omp_allocator_handle_t omp_thread_mem_alloc;
+
 void foo() {}
 
 struct S {
@@ -116,13 +126,13 @@ T tmain(T argc, T *argv) {
   // CHECK-NEXT: }
 
 #ifdef OMP5
-#pragma omp target simd if(target:argc > 0) if (simd:argc)
+#pragma omp target simd if(target:argc > 0) if (simd:argc) allocate(omp_default_mem_alloc:f) private(f) uses_allocators(omp_default_mem_alloc)
 #else
 #pragma omp target simd if(target:argc > 0)
 #endif // OMP5
   for (T i = 0; i < 2; ++i) {}
   // OMP45: #pragma omp target simd if(target: argc > 0)
-  // OMP50: #pragma omp target simd if(target: argc > 0) if(simd: argc)
+  // OMP50: #pragma omp target simd if(target: argc > 0) if(simd: argc) allocate(omp_default_mem_alloc: f) private(f) uses_allocators(omp_default_mem_alloc)
   // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
   // CHECK-NEXT: }
 

diff  --git a/clang/test/OpenMP/target_simd_firstprivate_messages.cpp b/clang/test/OpenMP/target_simd_firstprivate_messages.cpp
index e5696c9163d1..79243d723106 100644
--- a/clang/test/OpenMP/target_simd_firstprivate_messages.cpp
+++ b/clang/test/OpenMP/target_simd_firstprivate_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -125,7 +125,7 @@ int foomain(int argc, char **argv) {
   {
     int v = 0;
     int i;
-#pragma omp target simd allocate(omp_thread_mem_alloc: i) firstprivate(i) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target simd' directive}}
+#pragma omp target simd allocate(omp_thread_mem_alloc: i) firstprivate(i) uses_allocators(omp_thread_mem_alloc) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target simd' directive}}
     for (int k = 0; k < argc; ++k) {
       i = k;
       v += i;

diff  --git a/clang/test/OpenMP/target_simd_lastprivate_messages.cpp b/clang/test/OpenMP/target_simd_lastprivate_messages.cpp
index f9f77c0658d2..ac343a7d7e6a 100644
--- a/clang/test/OpenMP/target_simd_lastprivate_messages.cpp
+++ b/clang/test/OpenMP/target_simd_lastprivate_messages.cpp
@@ -4,6 +4,7 @@
 // RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-version=45 -fopenmp-simd %s -Wuninitialized
 // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=50 -fopenmp-simd %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_simd_linear_messages.cpp b/clang/test/OpenMP/target_simd_linear_messages.cpp
index 2048029ae371..ad94a0cca42e 100644
--- a/clang/test/OpenMP/target_simd_linear_messages.cpp
+++ b/clang/test/OpenMP/target_simd_linear_messages.cpp
@@ -2,6 +2,7 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_simd_private_messages.cpp b/clang/test/OpenMP/target_simd_private_messages.cpp
index ee0122f2da50..cfed8426d344 100644
--- a/clang/test/OpenMP/target_simd_private_messages.cpp
+++ b/clang/test/OpenMP/target_simd_private_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -68,7 +68,7 @@ class S6 {
 
   S6() : a(0) {}
   S6(T v) : a(v) {
-#pragma omp target simd private(a) private(this->a) allocate(omp_thread_mem_alloc: a) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target simd' directive}}
+#pragma omp target simd private(a) private(this->a) allocate(omp_thread_mem_alloc: a) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target simd' directive}} expected-error {{allocator must be specified in the 'uses_allocators' clause}}
     for (int k = 0; k < v; ++k)
       ++this->a;
   }

diff  --git a/clang/test/OpenMP/target_simd_reduction_messages.cpp b/clang/test/OpenMP/target_simd_reduction_messages.cpp
index 29ada5bb86e7..2e6c5665853c 100644
--- a/clang/test/OpenMP/target_simd_reduction_messages.cpp
+++ b/clang/test/OpenMP/target_simd_reduction_messages.cpp
@@ -37,7 +37,7 @@ bool foobool(int argc) {
 }
 
 void foobar(int &ref) {
-#pragma omp target simd allocate(omp_thread_mem_alloc: ref) reduction(+:ref) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target simd' directive}}
+#pragma omp target simd allocate(omp_thread_mem_alloc: ref) reduction(+:ref) uses_allocators(omp_thread_mem_alloc) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target simd' directive}} omp45-error {{unexpected OpenMP clause 'uses_allocators' in directive '#pragma omp target simd'}}
   for (int i = 0; i < 10; ++i)
     foo();
 }

diff  --git a/clang/test/OpenMP/target_teams_ast_print.cpp b/clang/test/OpenMP/target_teams_ast_print.cpp
index 9bf037e0dbc7..047addb387fa 100644
--- a/clang/test/OpenMP/target_teams_ast_print.cpp
+++ b/clang/test/OpenMP/target_teams_ast_print.cpp
@@ -1,15 +1,27 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
 
-// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
 // expected-no-diagnostics
 
 #ifndef HEADER
 #define HEADER
 
+struct omp_alloctrait_t {};
+
+typedef void **omp_allocator_handle_t;
+extern const omp_allocator_handle_t omp_default_mem_alloc;
+extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
+extern const omp_allocator_handle_t omp_const_mem_alloc;
+extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
+extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
+extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
+extern const omp_allocator_handle_t omp_pteam_mem_alloc;
+extern const omp_allocator_handle_t omp_thread_mem_alloc;
+
 void foo() {}
 
 template <class T>
@@ -37,11 +49,13 @@ T tmain(T argc, T *argv) {
   T b = argc, c, d, e, f, g;
   static T a;
   S<T> s;
+  omp_alloctrait_t traits[10];
+  omp_allocator_handle_t my_allocator;
 #pragma omp target teams
   a=2;
 #pragma omp target teams default(none), private(argc,b) firstprivate(argv) shared (d) reduction(+:c) reduction(max:e) num_teams(C) thread_limit(d*C) allocate(argv)
   foo();
-#pragma omp target teams allocate(f) reduction(^:e, f) reduction(&& : g)
+#pragma omp target teams allocate(my_allocator:f) reduction(^:e, f) reduction(&& : g) uses_allocators(my_allocator(traits))
   foo();
   return 0;
 }
@@ -50,31 +64,37 @@ T tmain(T argc, T *argv) {
 // CHECK-NEXT: T b = argc, c, d, e, f, g;
 // CHECK-NEXT: static T a;
 // CHECK-NEXT: S<T> s;
+// CHECK-NEXT: omp_alloctrait_t traits[10];
+// CHECK-NEXT: omp_allocator_handle_t my_allocator;
 // CHECK-NEXT: #pragma omp target teams{{$}}
 // CHECK-NEXT: a = 2;
 // CHECK-NEXT: #pragma omp target teams default(none) private(argc,b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(C) thread_limit(d * C) allocate(argv)
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target teams allocate(f) reduction(^: e,f) reduction(&&: g)
+// CHECK-NEXT: #pragma omp target teams allocate(my_allocator: f) reduction(^: e,f) reduction(&&: g) uses_allocators(my_allocator(traits))
 // CHECK-NEXT: foo()
 // CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
 // CHECK-NEXT: int b = argc, c, d, e, f, g;
 // CHECK-NEXT: static int a;
 // CHECK-NEXT: S<int> s;
+// CHECK-NEXT: omp_alloctrait_t traits[10];
+// CHECK-NEXT: omp_allocator_handle_t my_allocator;
 // CHECK-NEXT: #pragma omp target teams
 // CHECK-NEXT: a = 2;
 // CHECK-NEXT: #pragma omp target teams default(none) private(argc,b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(5) thread_limit(d * 5) allocate(argv)
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target teams allocate(f) reduction(^: e,f) reduction(&&: g)
+// CHECK-NEXT: #pragma omp target teams allocate(my_allocator: f) reduction(^: e,f) reduction(&&: g) uses_allocators(my_allocator(traits))
 // CHECK-NEXT: foo()
 // CHECK: template<> long tmain<long, 1>(long argc, long *argv) {
 // CHECK-NEXT: long b = argc, c, d, e, f, g;
 // CHECK-NEXT: static long a;
 // CHECK-NEXT: S<long> s;
+// CHECK-NEXT: omp_alloctrait_t traits[10];
+// CHECK-NEXT: omp_allocator_handle_t my_allocator;
 // CHECK-NEXT: #pragma omp target teams
 // CHECK-NEXT: a = 2;
 // CHECK-NEXT: #pragma omp target teams default(none) private(argc,b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(1) thread_limit(d * 1) allocate(argv)
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target teams allocate(f) reduction(^: e,f) reduction(&&: g)
+// CHECK-NEXT: #pragma omp target teams allocate(my_allocator: f) reduction(^: e,f) reduction(&&: g) uses_allocators(my_allocator(traits))
 // CHECK-NEXT: foo()
 
 enum Enum { };

diff  --git a/clang/test/OpenMP/target_teams_distribute_ast_print.cpp b/clang/test/OpenMP/target_teams_distribute_ast_print.cpp
index b7bf1df8d9a8..3a1ec36b8181 100644
--- a/clang/test/OpenMP/target_teams_distribute_ast_print.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_ast_print.cpp
@@ -1,15 +1,25 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s -Wno-openmp-mapping | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-mapping
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-mapping | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ast-print %s -Wno-openmp-mapping | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-mapping
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-mapping | FileCheck %s
 
-// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s -Wno-openmp-mapping | FileCheck %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-mapping
-// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-mapping | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ast-print %s -Wno-openmp-mapping | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s -Wno-openmp-mapping
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-mapping | FileCheck %s
 // expected-no-diagnostics
 
 #ifndef HEADER
 #define HEADER
 
+typedef void **omp_allocator_handle_t;
+extern const omp_allocator_handle_t omp_default_mem_alloc;
+extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
+extern const omp_allocator_handle_t omp_const_mem_alloc;
+extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
+extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
+extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
+extern const omp_allocator_handle_t omp_pteam_mem_alloc;
+extern const omp_allocator_handle_t omp_thread_mem_alloc;
+
 void foo() {}
 
 struct S {
@@ -40,14 +50,14 @@ class S7 : public T {
 
   void foo() {
     int b, argv, d, c, e, f;
-#pragma omp target teams distribute default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+#pragma omp target teams distribute default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d) allocate(omp_low_lat_mem_alloc:b) uses_allocators(omp_low_lat_mem_alloc)
     for (int k = 0; k < a.a; ++k)
       ++a.a;
   }
 };
 // CHECK: #pragma omp target teams distribute private(this->a) private(this->a) private(T::a)
 // CHECK: #pragma omp target teams distribute private(this->a) private(this->a)
-// CHECK: #pragma omp target teams distribute default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK: #pragma omp target teams distribute default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d) allocate(omp_low_lat_mem_alloc: b) uses_allocators(omp_low_lat_mem_alloc)
 // CHECK: #pragma omp target teams distribute private(this->a) private(this->a) private(this->S::a)
 
 class S8 : public S7<S> {

diff  --git a/clang/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp b/clang/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp
index 8b446fe4ccc8..9c4bf5c3d7dc 100644
--- a/clang/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp
@@ -2,6 +2,7 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
@@ -30,7 +31,7 @@ struct S1; // expected-note {{declared here}} expected-note{{forward declaration
 extern S1 a;
 class S2 {
   mutable int a;
-  
+
 public:
   S2() : a(0) {}
   S2(const S2 &s2) : a(s2.a) {}

diff  --git a/clang/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp b/clang/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp
index f76c13fd27d8..92a7f2f18634 100644
--- a/clang/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp
@@ -100,7 +100,7 @@ int foomain(int argc, char **argv) {
 #pragma omp target teams distribute lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
   for (int k = 0; k < argc; ++k) ++k;
 
-#pragma omp target teams distribute allocate(omp_thread_mem_alloc: argc) lastprivate(argc) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute' directive}}
+#pragma omp target teams distribute allocate(omp_thread_mem_alloc: argc) lastprivate(argc) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute' directive}} omp50-error {{allocator must be specified in the 'uses_allocators' clause}}
   for (int k = 0; k < argc; ++k) ++k;
 
 #pragma omp target teams distribute lastprivate(S1) // expected-error {{'S1' does not refer to a value}}

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp
index f9cef77cd7a3..008423ed0746 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp
@@ -10,6 +10,16 @@
 #ifndef HEADER
 #define HEADER
 
+typedef void **omp_allocator_handle_t;
+extern const omp_allocator_handle_t omp_default_mem_alloc;
+extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
+extern const omp_allocator_handle_t omp_const_mem_alloc;
+extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
+extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
+extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
+extern const omp_allocator_handle_t omp_pteam_mem_alloc;
+extern const omp_allocator_handle_t omp_thread_mem_alloc;
+
 void foo() {}
 
 struct S {
@@ -27,7 +37,7 @@ class S7 : public T {
 
 public:
   S7(typename T::type v) : a(v) {
-#pragma omp target teams distribute parallel for private(a) private(this->a) private(T::a)
+#pragma omp target teams distribute parallel for private(a) private(this->a) private(T::a) allocate(omp_cgroup_mem_alloc:a) uses_allocators(omp_cgroup_mem_alloc)
     for (int k = 0; k < a.a; ++k) {
       ++this->a.a;
 #pragma omp cancel for
@@ -48,7 +58,7 @@ class S7 : public T {
       ++a.a;
   }
 };
-// CHECK: #pragma omp target teams distribute parallel for private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp target teams distribute parallel for private(this->a) private(this->a) private(T::a) allocate(omp_cgroup_mem_alloc: this->a) uses_allocators(omp_cgroup_mem_alloc)
 // CHECK: #pragma omp cancel for
 // CHECK: #pragma omp target teams distribute parallel for private(this->a) private(this->a)
 // CHECK: #pragma omp target teams distribute parallel for default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
@@ -58,7 +68,7 @@ class S8 : public S7<S> {
 
 public:
   S8(int v) : S7<S>(v){
-#pragma omp target teams distribute parallel for private(a) private(this->a) private(S7<S>::a) 
+#pragma omp target teams distribute parallel for private(a) private(this->a) private(S7<S>::a)
     for (int k = 0; k < a.a; ++k)
       ++this->a.a;
   }

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp
index b0a7da9c932d..f063c9985d47 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -113,7 +113,7 @@ int main(int argc, char **argv) {
 #pragma omp target teams distribute parallel for firstprivate (argv[1]) // expected-error {{expected variable name}}
   for (i = 0; i < argc; ++i) foo();
 
-#pragma omp target teams distribute parallel for firstprivate(ba) allocate(omp_thread_mem_alloc: ba) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute parallel for' directive}}
+#pragma omp target teams distribute parallel for firstprivate(ba) uses_allocators(omp_thread_mem_alloc) allocate(omp_thread_mem_alloc: ba) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute parallel for' directive}}
   for (i = 0; i < argc; ++i) foo();
 
 #pragma omp target teams distribute parallel for firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}}

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp
index 8f4fd88a0818..173c253f0a59 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp
@@ -6,6 +6,7 @@
 // RUN: %clang_cc1 -verify=expected,le45 -fopenmp-version=45 -fopenmp-simd %s -Wuninitialized
 // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=50 -fopenmp-simd %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp
index eb5a4d63cadf..2d6140f28222 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -116,7 +116,7 @@ int main(int argc, char **argv) {
 #pragma omp target teams distribute parallel for firstprivate(i), private(i) // expected-error {{firstprivate variable cannot be private}} expected-note {{defined as firstprivate}}
   for (int k = 0; k < argc; ++k) ++k;
 
-#pragma omp target teams distribute parallel for allocate(omp_thread_mem_alloc: j) private(j) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute parallel for' directive}}
+#pragma omp target teams distribute parallel for allocate(omp_thread_mem_alloc: j) private(j) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute parallel for' directive}} expected-error {{allocator must be specified in the 'uses_allocators' clause}}
   for (int k = 0; k < argc; ++k) ++k;
 
 #pragma omp target teams distribute parallel for reduction(+:i)

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp
index c77539ecf960..3d5452553123 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp
@@ -169,7 +169,7 @@ T tmain(T argc) {
 #pragma omp parallel reduction(min : i)
 #pragma omp target teams distribute parallel for reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
   for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(+ : fl) allocate(omp_thread_mem_alloc: fl) // expected-warning 2 {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute parallel for' directive}}
+#pragma omp target teams distribute parallel for reduction(+ : fl) allocate(omp_thread_mem_alloc: fl) uses_allocators(omp_thread_mem_alloc)// expected-warning 2 {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute parallel for' directive}} omp45-error {{unexpected OpenMP clause 'uses_allocators' in directive '#pragma omp target teams distribute parallel for'}}
     for (int j=0; j<100; j++) foo();
 
   return T();

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_ast_print.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_ast_print.cpp
index 8e33d43dc2ce..0b21fb6bfbc8 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_ast_print.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_ast_print.cpp
@@ -10,6 +10,16 @@
 #ifndef HEADER
 #define HEADER
 
+typedef void **omp_allocator_handle_t;
+extern const omp_allocator_handle_t omp_default_mem_alloc;
+extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
+extern const omp_allocator_handle_t omp_const_mem_alloc;
+extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
+extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
+extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
+extern const omp_allocator_handle_t omp_pteam_mem_alloc;
+extern const omp_allocator_handle_t omp_thread_mem_alloc;
+
 void foo() {}
 
 struct S {
@@ -33,7 +43,7 @@ class S7 : public T {
   }
   S7 &operator=(S7 &s) {
     int k;
-#pragma omp target teams distribute parallel for simd allocate(a) private(a) private(this->a) linear(k) allocate(k)
+#pragma omp target teams distribute parallel for simd allocate(omp_pteam_mem_alloc: a) private(a) private(this->a) linear(k) allocate(k) uses_allocators(omp_pteam_mem_alloc)
     for (k = 0; k < s.a.a; ++k)
       ++s.a.a;
 
@@ -58,7 +68,7 @@ class S7 : public T {
   }
 };
 // CHECK: #pragma omp target teams distribute parallel for simd private(this->a) private(this->a) private(T::a)
-// CHECK: #pragma omp target teams distribute parallel for simd allocate(this->a) private(this->a) private(this->a) linear(k) allocate(k)
+// CHECK: #pragma omp target teams distribute parallel for simd allocate(omp_pteam_mem_alloc: this->a) private(this->a) private(this->a) linear(k) allocate(k) uses_allocators(omp_pteam_mem_alloc)
 // CHECK: #pragma omp target teams distribute parallel for simd default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
 // CHECK: #pragma omp target teams distribute parallel for simd simdlen(slen1) safelen(slen2) aligned(arr: alen)
 

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_messages.cpp
index 17aa7f488534..f47c5eea9485 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_messages.cpp
@@ -2,6 +2,7 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp
index 0553874cb997..af0fd40524f7 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp
@@ -1,10 +1,10 @@
 // RUN: %clang_cc1 -verify=expected,le45 -fopenmp %s -Wuninitialized
 // RUN: %clang_cc1 -verify=expected,le45 -fopenmp-version=40 -fopenmp %s -Wuninitialized
 // RUN: %clang_cc1 -verify=expected,le45 -fopenmp-version=45 -fopenmp %s -Wuninitialized
-// RUN: %clang_cc1 -verify=expected -fopenmp-version=50 -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le50 -fopenmp-version=50 -fopenmp %s -Wuninitialized
 
 // RUN: %clang_cc1 -verify=expected,le45 -fopenmp-simd %s -Wuninitialized
-// RUN: %clang_cc1 -verify=expected -fopenmp-version=50 -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le50 -fopenmp-version=50 -fopenmp-simd %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -124,7 +124,7 @@ int foomain(int argc, char **argv) {
   for (int k = 0; k < argc; ++k) ++k;
 
   int v = 0;
-#pragma omp target teams distribute parallel for simd lastprivate(i) allocate(omp_thread_mem_alloc: i) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute parallel for simd' directive}}
+#pragma omp target teams distribute parallel for simd lastprivate(i) allocate(omp_thread_mem_alloc: i) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute parallel for simd' directive}} le50-error {{allocator must be specified in the 'uses_allocators' clause}}
   for (int k = 0; k < argc; ++k) {
     i = k;
     v += i;

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp
index 8598fb6663cc..9d70f9f3c635 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -92,7 +92,7 @@ int main(int argc, char **argv) {
   #pragma omp target teams distribute parallel for simd private (argv[1]) // expected-error {{expected variable name}}
   for (int k = 0; k < argc; ++k) ++k;
 
-  #pragma omp target teams distribute parallel for simd private(ba) allocate(omp_thread_mem_alloc: ba) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute parallel for simd' directive}}
+  #pragma omp target teams distribute parallel for simd private(ba) uses_allocators(omp_thread_mem_alloc) allocate(omp_thread_mem_alloc: ba) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute parallel for simd' directive}}
   for (int k = 0; k < argc; ++k) ++k;
 
   #pragma omp target teams distribute parallel for simd private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp
index e6df03de3f7b..fbdf5aa8efe3 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp
@@ -12,6 +12,7 @@
 // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -std=c++98 %s -Wuninitialized
 // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -std=c++11 %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_teams_distribute_private_messages.cpp b/clang/test/OpenMP/target_teams_distribute_private_messages.cpp
index a2233ed07607..264935dfc1e5 100644
--- a/clang/test/OpenMP/target_teams_distribute_private_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_private_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -92,7 +92,7 @@ int main(int argc, char **argv) {
 #pragma omp target teams distribute private (argv[1]) // expected-error {{expected variable name}}
   for (int k = 0; k < argc; ++k) ++k;
 
-#pragma omp target teams distribute private(ba) allocate(omp_thread_mem_alloc: ba) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute' directive}}
+#pragma omp target teams distribute private(ba) allocate(omp_thread_mem_alloc: ba) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute' directive}} expected-error {{allocator must be specified in the 'uses_allocators' clause}}
   for (int k = 0; k < argc; ++k) ++k;
 
 #pragma omp target teams distribute private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}

diff  --git a/clang/test/OpenMP/target_teams_distribute_reduction_messages.cpp b/clang/test/OpenMP/target_teams_distribute_reduction_messages.cpp
index fc636d599be4..7ec60da27da5 100644
--- a/clang/test/OpenMP/target_teams_distribute_reduction_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_reduction_messages.cpp
@@ -174,7 +174,7 @@ T tmain(T argc) {
 #pragma omp parallel reduction(min : i)
 #pragma omp target teams distribute reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
   for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute allocate(omp_thread_mem_alloc: fl) reduction(+ : fl) // expected-warning 2 {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute' directive}}
+#pragma omp target teams distribute uses_allocators(omp_thread_mem_alloc) allocate(omp_thread_mem_alloc: fl) reduction(+ : fl) // expected-warning 2 {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute' directive}} omp45-error {{unexpected OpenMP clause 'uses_allocators' in directive '#pragma omp target teams distribute'}}
     for (int j=0; j<100; j++) foo();
 
   return T();

diff  --git a/clang/test/OpenMP/target_teams_distribute_simd_ast_print.cpp b/clang/test/OpenMP/target_teams_distribute_simd_ast_print.cpp
index 8644ac9c1ad1..5a527464b523 100644
--- a/clang/test/OpenMP/target_teams_distribute_simd_ast_print.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_simd_ast_print.cpp
@@ -16,6 +16,16 @@
 #ifndef HEADER
 #define HEADER
 
+typedef void **omp_allocator_handle_t;
+extern const omp_allocator_handle_t omp_default_mem_alloc;
+extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
+extern const omp_allocator_handle_t omp_const_mem_alloc;
+extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
+extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
+extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
+extern const omp_allocator_handle_t omp_pteam_mem_alloc;
+extern const omp_allocator_handle_t omp_thread_mem_alloc;
+
 void foo() {}
 
 struct S {
@@ -133,7 +143,7 @@ T tmain(T argc) {
     foo();
 // CHECK: #pragma omp target teams distribute simd
 // CHECK-NEXT: for (int i = 0; i < 10; ++i)
-// CHECK-NEXT: foo();  
+// CHECK-NEXT: foo();
 #pragma omp target teams distribute simd private(b), firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
     for (int k = 0; k < 10; ++k)
       e += d + argc;
@@ -198,14 +208,14 @@ int main (int argc, char **argv) {
 // CHECK-NEXT: for (int k = 0; k < 10; ++k)
 // CHECK-NEXT: e += d + argc;
 #ifdef OMP5
-#pragma omp target teams distribute simd safelen(clen-1) aligned(arr:N+6) if(simd:argc) nontemporal(argc, c, d) order(concurrent)
+#pragma omp target teams distribute simd safelen(clen-1) aligned(arr:N+6) if(simd:argc) nontemporal(argc, c, d) order(concurrent) allocate(omp_low_lat_mem_alloc:e) firstprivate(e) uses_allocators(omp_low_lat_mem_alloc)
 #else
 #pragma omp target teams distribute simd safelen(clen-1) aligned(arr:N+6)
 #endif // OMP5
   for (int k = 0; k < 10; ++k)
     e += d + argc + arr[k];
 // OMP45: #pragma omp target teams distribute simd safelen(clen - 1) aligned(arr: N + 6)
-// OMP50: #pragma omp target teams distribute simd safelen(clen - 1) aligned(arr: N + 6) if(simd: argc) nontemporal(argc,c,d) order(concurrent)
+// OMP50: #pragma omp target teams distribute simd safelen(clen - 1) aligned(arr: N + 6) if(simd: argc) nontemporal(argc,c,d) order(concurrent) allocate(omp_low_lat_mem_alloc: e) firstprivate(e) uses_allocators(omp_low_lat_mem_alloc)
 // CHECK-NEXT: for (int k = 0; k < 10; ++k)
 // CHECK-NEXT: e += d + argc + arr[k];
   return (0);

diff  --git a/clang/test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp b/clang/test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp
index 5ea84bf0221f..eb481c449649 100644
--- a/clang/test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_simd_firstprivate_messages.cpp
@@ -5,6 +5,7 @@
 
 // RUN: %clang_cc1 -verify=expected,le45 -fopenmp-simd %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp b/clang/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp
index 09da5e6c75e4..c68b0452328c 100644
--- a/clang/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp
@@ -1,10 +1,10 @@
 // RUN: %clang_cc1 -verify=expected,le45 -fopenmp %s -Wuninitialized
 // RUN: %clang_cc1 -verify=expected,le45 -fopenmp-version=40 -fopenmp %s -Wuninitialized
 // RUN: %clang_cc1 -verify=expected,le45 -fopenmp-version=45 -fopenmp %s -Wuninitialized
-// RUN: %clang_cc1 -verify=expected -fopenmp-version=50 -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le50 -fopenmp-version=50 -fopenmp %s -Wuninitialized
 
 // RUN: %clang_cc1 -verify=expected,le45 -fopenmp-simd %s -Wuninitialized
-// RUN: %clang_cc1 -verify=expected -fopenmp-version=50 -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,le50 -fopenmp-version=50 -fopenmp-simd %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -124,7 +124,7 @@ int foomain(int argc, char **argv) {
   for (int k = 0; k < argc; ++k) ++k;
 
   int v = 0;
-#pragma omp target teams distribute simd allocate(omp_thread_mem_alloc: i) lastprivate(i) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute simd' directive}}
+#pragma omp target teams distribute simd allocate(omp_thread_mem_alloc: i) lastprivate(i) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute simd' directive}} le50-error {{allocator must be specified in the 'uses_allocators' clause}}
   for (int k = 0; k < argc; ++k) {
     i = k;
     v += i;

diff  --git a/clang/test/OpenMP/target_teams_distribute_simd_private_messages.cpp b/clang/test/OpenMP/target_teams_distribute_simd_private_messages.cpp
index 1ed9e7661ed5..d37f38de6483 100644
--- a/clang/test/OpenMP/target_teams_distribute_simd_private_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_simd_private_messages.cpp
@@ -4,6 +4,7 @@
 // RUN: %clang_cc1 -verify=expected -fopenmp-version=50 -fopenmp %s -Wuninitialized
 
 // RUN: %clang_cc1 -verify=expected,le45 -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -95,7 +96,7 @@ int main(int argc, char **argv) {
 #pragma omp target teams distribute simd private (k, argv[1]) // expected-error {{expected variable name}}
   for (int k = 0; k < argc; ++k) ++k;
 
-#pragma omp target teams distribute simd private(ba) allocate(omp_thread_mem_alloc: ba) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute simd' directive}}
+#pragma omp target teams distribute simd private(ba) allocate(omp_thread_mem_alloc: ba) uses_allocators(omp_thread_mem_alloc) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams distribute simd' directive}} le45-error {{unexpected OpenMP clause 'uses_allocators' in directive '#pragma omp target teams distribute simd'}}
   for (int k = 0; k < argc; ++k) ++k;
 
 #pragma omp target teams distribute simd private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}

diff  --git a/clang/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp b/clang/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp
index 4991cb100d65..f97ad593b7b3 100644
--- a/clang/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp
@@ -12,6 +12,7 @@
 // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -std=c++98 %s -Wuninitialized
 // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -std=c++11 %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_teams_firstprivate_messages.cpp b/clang/test/OpenMP/target_teams_firstprivate_messages.cpp
index 1f4f40d67533..6563da08738b 100644
--- a/clang/test/OpenMP/target_teams_firstprivate_messages.cpp
+++ b/clang/test/OpenMP/target_teams_firstprivate_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -103,7 +103,7 @@ int main(int argc, char **argv) {
   foo();
 #pragma omp target teams firstprivate(argv[1]) // expected-error {{expected variable name}}
   foo();
-#pragma omp target teams allocate(omp_thread_mem_alloc: ba) firstprivate(ba) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams' directive}}
+#pragma omp target teams allocate(omp_thread_mem_alloc: ba) uses_allocators(omp_thread_mem_alloc) firstprivate(ba) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams' directive}}
   foo();
 #pragma omp target teams firstprivate(ca, z)
   foo();

diff  --git a/clang/test/OpenMP/target_teams_private_messages.cpp b/clang/test/OpenMP/target_teams_private_messages.cpp
index 85309e953b92..7bab3723473c 100644
--- a/clang/test/OpenMP/target_teams_private_messages.cpp
+++ b/clang/test/OpenMP/target_teams_private_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
 
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
@@ -108,7 +108,7 @@ int main(int argc, char **argv) {
   foo();
 #pragma omp target teams private(j)
   foo();
-#pragma omp target teams firstprivate(i) allocate(omp_thread_mem_alloc: i) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams' directive}}
+#pragma omp target teams firstprivate(i) uses_allocators(omp_thread_mem_alloc) allocate(omp_thread_mem_alloc: i) // expected-warning {{allocator with the 'thread' trait access has unspecified behavior on 'target teams' directive}}
   for (int k = 0; k < 10; ++k) {
 #pragma omp parallel private(i)
     foo();

diff  --git a/clang/test/OpenMP/target_teams_reduction_messages.cpp b/clang/test/OpenMP/target_teams_reduction_messages.cpp
index a52a0e1cb8b8..e775270f4d6a 100644
--- a/clang/test/OpenMP/target_teams_reduction_messages.cpp
+++ b/clang/test/OpenMP/target_teams_reduction_messages.cpp
@@ -12,6 +12,7 @@
 // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -std=c++98 -o - %s -Wuninitialized
 // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -std=c++11 -o - %s -Wuninitialized
 
+#pragma omp requires dynamic_allocators
 typedef void **omp_allocator_handle_t;
 extern const omp_allocator_handle_t omp_default_mem_alloc;
 extern const omp_allocator_handle_t omp_large_cap_mem_alloc;

diff  --git a/clang/test/OpenMP/target_uses_allocators_messages.cpp b/clang/test/OpenMP/target_uses_allocators_messages.cpp
new file mode 100644
index 000000000000..1c1912025a03
--- /dev/null
+++ b/clang/test/OpenMP/target_uses_allocators_messages.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized
+
+struct omp_alloctrait_t {};
+
+typedef void **omp_allocator_handle_t;
+extern const omp_allocator_handle_t omp_default_mem_alloc;
+extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
+extern const omp_allocator_handle_t omp_const_mem_alloc;
+extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
+extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
+extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
+extern const omp_allocator_handle_t omp_pteam_mem_alloc;
+extern const omp_allocator_handle_t omp_thread_mem_alloc;
+
+int main(int argc, char **argv) {
+  omp_alloctrait_t traits[10];
+  omp_alloctrait_t *ptraits;
+  omp_allocator_handle_t my_alloc = nullptr;
+  const omp_allocator_handle_t c_my_alloc = my_alloc;
+#pragma omp target uses_allocators // expected-error {{expected '(' after 'uses_allocator'}}
+{}
+#pragma omp target uses_allocators( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected unqualified-id}}
+{}
+#pragma omp target uses_allocators() // expected-error {{expected unqualified-id}}
+{}
+#pragma omp target uses_allocators(omp_default_mem_alloc // expected-error {{expected ',' or ')' in 'uses_allocators' clause}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+{}
+#pragma omp target uses_allocators(argc, // expected-error {{expected ')'}} expected-error {{expected variable of the 'omp_allocator_handle_t' type, not 'int'}} expected-note {{to match this '('}}
+{}
+#pragma omp target uses_allocators(argc > 0 ? omp_default_mem_alloc : omp_thread_mem_alloc) // expected-error {{expected ',' or ')' in 'uses_allocators' clause}} expected-error {{expected unqualified-id}} expected-error {{expected variable of the 'omp_allocator_handle_t' type, not 'int'}}
+{}
+#pragma omp target uses_allocators(omp_default_mem_alloc, omp_large_cap_mem_alloc, omp_const_mem_alloc, omp_high_bw_mem_alloc, omp_low_lat_mem_alloc, omp_cgroup_mem_alloc, omp_pteam_mem_alloc, omp_thread_mem_alloc)
+{}
+#pragma omp target uses_allocators(omp_default_mem_alloc(traits), omp_large_cap_mem_alloc(traits), omp_const_mem_alloc(traits), omp_high_bw_mem_alloc(traits), omp_low_lat_mem_alloc(traits), omp_cgroup_mem_alloc(traits), omp_pteam_mem_alloc(traits), omp_thread_mem_alloc(traits)) // expected-error 8 {{predefined allocator cannot have traits specified}} expected-note-re 8 {{predefined trait '{{omp_default_mem_alloc|omp_large_cap_mem_alloc|omp_const_mem_alloc|omp_high_bw_mem_alloc|omp_low_lat_mem_alloc|omp_cgroup_mem_alloc|omp_pteam_mem_alloc|omp_thread_mem_alloc}}' used here}}
+{}
+#pragma omp target uses_allocators(my_alloc, c_my_alloc) // expected-error {{non-predefined allocator must have traits specified}} expected-error {{expected variable of the 'omp_allocator_handle_t' type, not 'const omp_allocator_handle_t' (aka 'void **const')}}
+{}
+#pragma omp target uses_allocators(my_alloc() // expected-error {{expected unqualified-id}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{non-predefined allocator must have traits specified}}
+{}
+#pragma omp target uses_allocators(my_alloc()) // expected-error {{expected unqualified-id}} expected-error {{non-predefined allocator must have traits specified}}
+{}
+#pragma omp target uses_allocators(my_alloc(argc > 0 ? argv[0] : argv{1})) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected constant sized array of 'omp_alloctrait_t' elements, not 'int'}}
+{}
+#pragma omp target uses_allocators(my_alloc(ptraits)) // expected-error {{expected constant sized array of 'omp_alloctrait_t' elements, not 'omp_alloctrait_t *'}}
+{}
+#pragma omp target uses_allocators(my_alloc(traits)) private(my_alloc) // expected-error {{allocators used in 'uses_allocators' clause cannot appear in other data-sharing or data-mapping attribute clauses}} expected-note {{defined as private}}
+{}
+#pragma omp target map(my_alloc, traits) uses_allocators(my_alloc(traits)) // expected-error {{allocators used in 'uses_allocators' clause cannot appear in other data-sharing or data-mapping attribute clauses}} expected-note {{used here}}
+{}
+  return 0;
+}
+

diff  --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index e441b19f9a17..f09d40115a74 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2490,6 +2490,14 @@ void OMPClauseEnqueue::VisitOMPNontemporalClause(
     Visitor->AddStmt(E);
 }
 void OMPClauseEnqueue::VisitOMPOrderClause(const OMPOrderClause *C) {}
+void OMPClauseEnqueue::VisitOMPUsesAllocatorsClause(
+    const OMPUsesAllocatorsClause *C) {
+  for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
+    const OMPUsesAllocatorsClause::Data &D = C->getAllocatorData(I);
+    Visitor->AddStmt(D.Allocator);
+    Visitor->AddStmt(D.AllocatorTraits);
+  }
+}
 } // namespace
 
 void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {

diff  --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
index 7599a7c98175..8677b38a9afb 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
@@ -196,6 +196,7 @@ __OMP_CLAUSE(destroy, OMPDestroyClause)
 __OMP_CLAUSE(detach, OMPDetachClause)
 __OMP_CLAUSE(inclusive, OMPInclusiveClause)
 __OMP_CLAUSE(exclusive, OMPExclusiveClause)
+__OMP_CLAUSE(uses_allocators, OMPUsesAllocatorsClause)
 
 __OMP_CLAUSE_NO_CLASS(uniform)
 __OMP_CLAUSE_NO_CLASS(device_type)
@@ -887,6 +888,7 @@ __OMP_DIRECTIVE_CLAUSE(target, 1, ~0, firstprivate)
 __OMP_DIRECTIVE_CLAUSE(target, 1, ~0, is_device_ptr)
 __OMP_DIRECTIVE_CLAUSE(target, 1, ~0, reduction)
 __OMP_DIRECTIVE_CLAUSE(target, 1, ~0, allocate)
+__OMP_DIRECTIVE_CLAUSE(target, 50, ~0, uses_allocators)
 
 __OMP_DIRECTIVE_CLAUSE(requires, 1, ~0, unified_address)
 __OMP_DIRECTIVE_CLAUSE(requires, 1, ~0, unified_shared_memory)
@@ -928,6 +930,7 @@ __OMP_DIRECTIVE_CLAUSE(target_parallel, 1, ~0, shared)
 __OMP_DIRECTIVE_CLAUSE(target_parallel, 1, ~0, reduction)
 __OMP_DIRECTIVE_CLAUSE(target_parallel, 1, ~0, is_device_ptr)
 __OMP_DIRECTIVE_CLAUSE(target_parallel, 1, ~0, allocate)
+__OMP_DIRECTIVE_CLAUSE(target_parallel, 50, ~0, uses_allocators)
 
 __OMP_DIRECTIVE_CLAUSE(target_parallel_for, 1, ~0, if)
 __OMP_DIRECTIVE_CLAUSE(target_parallel_for, 1, ~0, device)
@@ -950,6 +953,7 @@ __OMP_DIRECTIVE_CLAUSE(target_parallel_for, 1, ~0, linear)
 __OMP_DIRECTIVE_CLAUSE(target_parallel_for, 1, ~0, is_device_ptr)
 __OMP_DIRECTIVE_CLAUSE(target_parallel_for, 1, ~0, allocate)
 __OMP_DIRECTIVE_CLAUSE(target_parallel_for, 50, ~0, order)
+__OMP_DIRECTIVE_CLAUSE(target_parallel_for, 50, ~0, uses_allocators)
 
 __OMP_DIRECTIVE_CLAUSE(target_update, 1, ~0, if)
 __OMP_DIRECTIVE_CLAUSE(target_update, 1, ~0, device)
@@ -1187,6 +1191,7 @@ __OMP_DIRECTIVE_CLAUSE(target_parallel_for_simd, 1, ~0, is_device_ptr)
 __OMP_DIRECTIVE_CLAUSE(target_parallel_for_simd, 1, ~0, allocate)
 __OMP_DIRECTIVE_CLAUSE(target_parallel_for_simd, 50, ~0, nontemporal)
 __OMP_DIRECTIVE_CLAUSE(target_parallel_for_simd, 50, ~0, order)
+__OMP_DIRECTIVE_CLAUSE(target_parallel_for_simd, 50, ~0, uses_allocators)
 
 __OMP_DIRECTIVE_CLAUSE(target_simd, 1, ~0, if)
 __OMP_DIRECTIVE_CLAUSE(target_simd, 1, ~0, device)
@@ -1207,6 +1212,7 @@ __OMP_DIRECTIVE_CLAUSE(target_simd, 1, ~0, reduction)
 __OMP_DIRECTIVE_CLAUSE(target_simd, 1, ~0, allocate)
 __OMP_DIRECTIVE_CLAUSE(target_simd, 50, ~0, nontemporal)
 __OMP_DIRECTIVE_CLAUSE(target_simd, 50, ~0, order)
+__OMP_DIRECTIVE_CLAUSE(target_simd, 50, ~0, uses_allocators)
 
 __OMP_DIRECTIVE_CLAUSE(teams_distribute, 1, ~0, default)
 __OMP_DIRECTIVE_CLAUSE(teams_distribute, 1, ~0, private)
@@ -1294,6 +1300,7 @@ __OMP_DIRECTIVE_CLAUSE(target_teams, 1, ~0, reduction)
 __OMP_DIRECTIVE_CLAUSE(target_teams, 1, ~0, num_teams)
 __OMP_DIRECTIVE_CLAUSE(target_teams, 1, ~0, thread_limit)
 __OMP_DIRECTIVE_CLAUSE(target_teams, 1, ~0, allocate)
+__OMP_DIRECTIVE_CLAUSE(target_teams, 50, ~0, uses_allocators)
 
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute, 1, ~0, if)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute, 1, ~0, device)
@@ -1313,6 +1320,7 @@ __OMP_DIRECTIVE_CLAUSE(target_teams_distribute, 1, ~0, lastprivate)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute, 1, ~0, collapse)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute, 1, ~0, dist_schedule)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute, 1, ~0, allocate)
+__OMP_DIRECTIVE_CLAUSE(target_teams_distribute, 50, ~0, uses_allocators)
 
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for, 1, ~0, if)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for, 1, ~0, device)
@@ -1340,6 +1348,8 @@ __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for, 1, ~0, proc_bind)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for, 1, ~0, schedule)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for, 1, ~0, allocate)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for, 50, ~0, order)
+__OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for, 50, ~0,
+                       uses_allocators)
 
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for_simd, 1, ~0, if)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for_simd, 1, ~0, device)
@@ -1387,6 +1397,8 @@ __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for_simd, 1, ~0,
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for_simd, 50, ~0,
                        nontemporal)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for_simd, 50, ~0, order)
+__OMP_DIRECTIVE_CLAUSE(target_teams_distribute_parallel_for_simd, 50, ~0,
+                       uses_allocators)
 
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_simd, 1, ~0, if)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_simd, 1, ~0, device)
@@ -1411,6 +1423,7 @@ __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_simd, 1, ~0, simdlen)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_simd, 1, ~0, allocate)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_simd, 50, ~0, nontemporal)
 __OMP_DIRECTIVE_CLAUSE(target_teams_distribute_simd, 50, ~0, order)
+__OMP_DIRECTIVE_CLAUSE(target_teams_distribute_simd, 50, ~0, uses_allocators)
 
 __OMP_DIRECTIVE_CLAUSE(taskgroup, 1, ~0, task_reduction)
 __OMP_DIRECTIVE_CLAUSE(taskgroup, 1, ~0, allocate)


        


More information about the cfe-commits mailing list