[clang] 0af7835 - [OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 6 09:26:34 PDT 2020


Author: Alexey Bataev
Date: 2020-08-06T12:25:19-04:00
New Revision: 0af7835eae698330f6362220ff1fcbfe92516de8

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

LOG: [OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.

Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.

Reviewers: jdoerfert

Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin

Tags: #clang

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

Added: 
    

Modified: 
    clang/include/clang/AST/DeclOpenMP.h
    clang/include/clang/AST/OpenMPClause.h
    clang/include/clang/AST/StmtOpenMP.h
    clang/include/clang/Sema/Sema.h
    clang/include/clang/Serialization/ASTRecordReader.h
    clang/include/clang/Serialization/ASTRecordWriter.h
    clang/lib/AST/DeclOpenMP.cpp
    clang/lib/AST/StmtOpenMP.cpp
    clang/lib/CodeGen/CGStmtOpenMP.cpp
    clang/lib/Parse/ParseOpenMP.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/lib/Sema/SemaOpenMP.cpp
    clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
    clang/lib/Serialization/ASTReader.cpp
    clang/lib/Serialization/ASTReaderDecl.cpp
    clang/lib/Serialization/ASTReaderStmt.cpp
    clang/lib/Serialization/ASTWriter.cpp
    clang/lib/Serialization/ASTWriterDecl.cpp
    clang/lib/Serialization/ASTWriterStmt.cpp
    clang/test/AST/ast-dump-openmp-ordered.c
    clang/test/OpenMP/declare_mapper_messages.c
    clang/test/OpenMP/declare_mapper_messages.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/DeclOpenMP.h b/clang/include/clang/AST/DeclOpenMP.h
index 154ecb977692c..a035de1e20e20 100644
--- a/clang/include/clang/AST/DeclOpenMP.h
+++ b/clang/include/clang/AST/DeclOpenMP.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_AST_DECLOPENMP_H
 #define LLVM_CLANG_AST_DECLOPENMP_H
 
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExternalASTSource.h"
@@ -24,6 +25,79 @@
 
 namespace clang {
 
+/// This is a basic class for representing single OpenMP declarative directive.
+///
+template <typename U> class OMPDeclarativeDirective : public U {
+  friend class ASTDeclReader;
+  friend class ASTDeclWriter;
+
+  /// Get the clauses storage.
+  MutableArrayRef<OMPClause *> getClauses() {
+    if (!Data)
+      return llvm::None;
+    return Data->getClauses();
+  }
+
+protected:
+  /// Data, associated with the directive.
+  OMPChildren *Data = nullptr;
+
+  /// Build instance of directive.
+  ///
+  /// \param StartLoc Starting location of the directive (directive keyword).
+  ///
+  template <typename... Params>
+  OMPDeclarativeDirective(Params &&... P) : U(std::forward<Params>(P)...) {}
+
+  template <typename T, typename... Params>
+  static T *createDirective(const ASTContext &C, DeclContext *DC,
+                            ArrayRef<OMPClause *> Clauses, unsigned NumChildren,
+                            Params &&... P) {
+    auto *Inst = new (C, DC, size(Clauses.size(), NumChildren))
+        T(DC, std::forward<Params>(P)...);
+    Inst->Data = OMPChildren::Create(Inst + 1, Clauses,
+                                     /*AssociatedStmt=*/nullptr, NumChildren);
+    Inst->Data->setClauses(Clauses);
+    return Inst;
+  }
+
+  template <typename T, typename... Params>
+  static T *createEmptyDirective(const ASTContext &C, unsigned ID,
+                                 unsigned NumClauses, unsigned NumChildren,
+                                 Params &&... P) {
+    auto *Inst = new (C, ID, size(NumClauses, NumChildren))
+        T(nullptr, std::forward<Params>(P)...);
+    Inst->Data = OMPChildren::CreateEmpty(
+        Inst + 1, NumClauses, /*HasAssociatedStmt=*/false, NumChildren);
+    return Inst;
+  }
+
+  static size_t size(unsigned NumClauses, unsigned NumChildren) {
+    return OMPChildren::size(NumClauses, /*HasAssociatedStmt=*/false,
+                             NumChildren);
+  }
+
+public:
+  /// Get number of clauses.
+  unsigned getNumClauses() const {
+    if (!Data)
+      return 0;
+    return Data->getNumClauses();
+  }
+
+  /// Returns specified clause.
+  ///
+  /// \param I Number of clause.
+  ///
+  OMPClause *getClause(unsigned I) const { return clauses()[I]; }
+
+  ArrayRef<OMPClause *> clauses() const {
+    if (!Data)
+      return llvm::None;
+    return Data->getClauses();
+  }
+};
+
 /// This represents '#pragma omp threadprivate ...' directive.
 /// For example, in the following, both 'a' and 'A::b' are threadprivate:
 ///
@@ -36,25 +110,23 @@ namespace clang {
 /// };
 /// \endcode
 ///
-class OMPThreadPrivateDecl final
-    : public Decl,
-      private llvm::TrailingObjects<OMPThreadPrivateDecl, Expr *> {
-  friend class ASTDeclReader;
-  friend TrailingObjects;
-
-  unsigned NumVars;
+class OMPThreadPrivateDecl final : public OMPDeclarativeDirective<Decl> {
+  friend class OMPDeclarativeDirective<Decl>;
 
   virtual void anchor();
 
-  OMPThreadPrivateDecl(Kind DK, DeclContext *DC, SourceLocation L) :
-    Decl(DK, DC, L), NumVars(0) { }
+  OMPThreadPrivateDecl(DeclContext *DC = nullptr,
+                       SourceLocation L = SourceLocation())
+      : OMPDeclarativeDirective<Decl>(OMPThreadPrivate, DC, L) {}
 
   ArrayRef<const Expr *> getVars() const {
-    return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumVars);
+    auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
+    return llvm::makeArrayRef(Storage, Data->getNumChildren());
   }
 
   MutableArrayRef<Expr *> getVars() {
-    return MutableArrayRef<Expr *>(getTrailingObjects<Expr *>(), NumVars);
+    auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
+    return llvm::makeMutableArrayRef(Storage, Data->getNumChildren());
   }
 
   void setVars(ArrayRef<Expr *> VL);
@@ -71,8 +143,8 @@ class OMPThreadPrivateDecl final
   typedef llvm::iterator_range<varlist_iterator> varlist_range;
   typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
 
-  unsigned varlist_size() const { return NumVars; }
-  bool varlist_empty() const { return NumVars == 0; }
+  unsigned varlist_size() const { return Data->getNumChildren(); }
+  bool varlist_empty() const { return Data->getChildren().empty(); }
 
   varlist_range varlists() {
     return varlist_range(varlist_begin(), varlist_end());
@@ -214,11 +286,11 @@ class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext {
 /// \code
 /// #pragma omp declare mapper(mid: struct vec v) map(v.len, v.data[0:N])
 /// \endcode
-class OMPDeclareMapperDecl final : public ValueDecl, public DeclContext {
+class OMPDeclareMapperDecl final : public OMPDeclarativeDirective<ValueDecl>,
+                                   public DeclContext {
+  friend class OMPDeclarativeDirective<ValueDecl>;
   friend class ASTDeclReader;
-
-  /// Clauses associated with this mapper declaration
-  MutableArrayRef<OMPClause *> Clauses;
+  friend class ASTDeclWriter;
 
   /// Mapper variable, which is 'v' in the example above
   Expr *MapperVarRef = nullptr;
@@ -230,42 +302,36 @@ class OMPDeclareMapperDecl final : public ValueDecl, public DeclContext {
 
   void anchor() override;
 
-  OMPDeclareMapperDecl(Kind DK, DeclContext *DC, SourceLocation L,
-                       DeclarationName Name, QualType Ty,
-                       DeclarationName VarName,
+  OMPDeclareMapperDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+                       QualType Ty, DeclarationName VarName,
                        OMPDeclareMapperDecl *PrevDeclInScope)
-      : ValueDecl(DK, DC, L, Name, Ty), DeclContext(DK), VarName(VarName),
+      : OMPDeclarativeDirective<ValueDecl>(OMPDeclareMapper, DC, L, Name, Ty),
+        DeclContext(OMPDeclareMapper), VarName(VarName),
         PrevDeclInScope(PrevDeclInScope) {}
 
   void setPrevDeclInScope(OMPDeclareMapperDecl *Prev) {
     PrevDeclInScope = Prev;
   }
 
-  /// Sets an array of clauses to this mapper declaration
-  void setClauses(ArrayRef<OMPClause *> CL);
-
 public:
   /// Creates declare mapper node.
   static OMPDeclareMapperDecl *Create(ASTContext &C, DeclContext *DC,
                                       SourceLocation L, DeclarationName Name,
                                       QualType T, DeclarationName VarName,
+                                      ArrayRef<OMPClause *> Clauses,
                                       OMPDeclareMapperDecl *PrevDeclInScope);
   /// Creates deserialized declare mapper node.
   static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C, unsigned ID,
                                                   unsigned N);
 
-  /// Creates an array of clauses to this mapper declaration and intializes
-  /// them.
-  void CreateClauses(ASTContext &C, ArrayRef<OMPClause *> CL);
-
   using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
   using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
   using clauselist_range = llvm::iterator_range<clauselist_iterator>;
   using clauselist_const_range =
       llvm::iterator_range<clauselist_const_iterator>;
 
-  unsigned clauselist_size() const { return Clauses.size(); }
-  bool clauselist_empty() const { return Clauses.empty(); }
+  unsigned clauselist_size() const { return Data->getNumClauses(); }
+  bool clauselist_empty() const { return Data->getClauses().empty(); }
 
   clauselist_range clauselists() {
     return clauselist_range(clauselist_begin(), clauselist_end());
@@ -273,16 +339,24 @@ class OMPDeclareMapperDecl final : public ValueDecl, public DeclContext {
   clauselist_const_range clauselists() const {
     return clauselist_const_range(clauselist_begin(), clauselist_end());
   }
-  clauselist_iterator clauselist_begin() { return Clauses.begin(); }
-  clauselist_iterator clauselist_end() { return Clauses.end(); }
-  clauselist_const_iterator clauselist_begin() const { return Clauses.begin(); }
-  clauselist_const_iterator clauselist_end() const { return Clauses.end(); }
+  clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); }
+  clauselist_iterator clauselist_end() { return Data->getClauses().end(); }
+  clauselist_const_iterator clauselist_begin() const {
+    return Data->getClauses().begin();
+  }
+  clauselist_const_iterator clauselist_end() const {
+    return Data->getClauses().end();
+  }
 
   /// Get the variable declared in the mapper
-  Expr *getMapperVarRef() { return MapperVarRef; }
-  const Expr *getMapperVarRef() const { return MapperVarRef; }
+  Expr *getMapperVarRef() { return cast_or_null<Expr>(Data->getChildren()[0]); }
+  const Expr *getMapperVarRef() const {
+    return cast_or_null<Expr>(Data->getChildren()[0]);
+  }
   /// Set the variable declared in the mapper
-  void setMapperVarRef(Expr *MapperVarRefE) { MapperVarRef = MapperVarRefE; }
+  void setMapperVarRef(Expr *MapperVarRefE) {
+    Data->getChildren()[0] = MapperVarRefE;
+  }
 
   /// Get the name of the variable declared in the mapper
   DeclarationName getVarName() { return VarName; }
@@ -342,34 +416,14 @@ class OMPCapturedExprDecl final : public VarDecl {
 /// #pragma omp requires unified_address
 /// \endcode
 ///
-class OMPRequiresDecl final
-    : public Decl,
-      private llvm::TrailingObjects<OMPRequiresDecl, OMPClause *> {
+class OMPRequiresDecl final : public OMPDeclarativeDirective<Decl> {
+  friend class OMPDeclarativeDirective<Decl>;
   friend class ASTDeclReader;
-  friend TrailingObjects;
-
-  // Number of clauses associated with this requires declaration
-  unsigned NumClauses = 0;
 
   virtual void anchor();
 
-  OMPRequiresDecl(Kind DK, DeclContext *DC, SourceLocation L)
-      : Decl(DK, DC, L), NumClauses(0) {}
-
-  /// Returns an array of immutable clauses associated with this requires
-  /// declaration
-  ArrayRef<const OMPClause *> getClauses() const {
-    return llvm::makeArrayRef(getTrailingObjects<OMPClause *>(), NumClauses);
-  }
-
-  /// Returns an array of clauses associated with this requires declaration
-  MutableArrayRef<OMPClause *> getClauses() {
-    return MutableArrayRef<OMPClause *>(getTrailingObjects<OMPClause *>(),
-                                        NumClauses);
-  }
-
-  /// Sets an array of clauses to this requires declaration
-  void setClauses(ArrayRef<OMPClause *> CL);
+  OMPRequiresDecl(DeclContext *DC, SourceLocation L)
+      : OMPDeclarativeDirective<Decl>(OMPRequires, DC, L) {}
 
 public:
   /// Create requires node.
@@ -384,8 +438,8 @@ class OMPRequiresDecl final
   using clauselist_range = llvm::iterator_range<clauselist_iterator>;
   using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>;
 
-  unsigned clauselist_size() const { return NumClauses; }
-  bool clauselist_empty() const { return NumClauses == 0; }
+  unsigned clauselist_size() const { return Data->getNumClauses(); }
+  bool clauselist_empty() const { return Data->getClauses().empty(); }
 
   clauselist_range clauselists() {
     return clauselist_range(clauselist_begin(), clauselist_end());
@@ -393,13 +447,13 @@ class OMPRequiresDecl final
   clauselist_const_range clauselists() const {
     return clauselist_const_range(clauselist_begin(), clauselist_end());
   }
-  clauselist_iterator clauselist_begin() { return getClauses().begin(); }
-  clauselist_iterator clauselist_end() { return getClauses().end(); }
+  clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); }
+  clauselist_iterator clauselist_end() { return Data->getClauses().end(); }
   clauselist_const_iterator clauselist_begin() const {
-    return getClauses().begin();
+    return Data->getClauses().begin();
   }
   clauselist_const_iterator clauselist_end() const {
-    return getClauses().end();
+    return Data->getClauses().end();
   }
 
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -419,53 +473,27 @@ class OMPRequiresDecl final
 /// };
 /// \endcode
 ///
-class OMPAllocateDecl final
-    : public Decl,
-      private llvm::TrailingObjects<OMPAllocateDecl, Expr *, OMPClause *> {
+class OMPAllocateDecl final : public OMPDeclarativeDirective<Decl> {
+  friend class OMPDeclarativeDirective<Decl>;
   friend class ASTDeclReader;
-  friend TrailingObjects;
-
-  /// Number of variable within the allocate directive.
-  unsigned NumVars = 0;
-  /// Number of clauses associated with the allocate directive.
-  unsigned NumClauses = 0;
-
-  size_t numTrailingObjects(OverloadToken<Expr *>) const {
-    return NumVars;
-  }
-  size_t numTrailingObjects(OverloadToken<OMPClause *>) const {
-    return NumClauses;
-  }
 
   virtual void anchor();
 
-  OMPAllocateDecl(Kind DK, DeclContext *DC, SourceLocation L)
-      : Decl(DK, DC, L) {}
+  OMPAllocateDecl(DeclContext *DC, SourceLocation L)
+      : OMPDeclarativeDirective<Decl>(OMPAllocate, DC, L) {}
 
   ArrayRef<const Expr *> getVars() const {
-    return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumVars);
+    auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
+    return llvm::makeArrayRef(Storage, Data->getNumChildren());
   }
 
   MutableArrayRef<Expr *> getVars() {
-    return MutableArrayRef<Expr *>(getTrailingObjects<Expr *>(), NumVars);
+    auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
+    return llvm::makeMutableArrayRef(Storage, Data->getNumChildren());
   }
 
   void setVars(ArrayRef<Expr *> VL);
 
-  /// Returns an array of immutable clauses associated with this directive.
-  ArrayRef<OMPClause *> getClauses() const {
-    return llvm::makeArrayRef(getTrailingObjects<OMPClause *>(), NumClauses);
-  }
-
-  /// Returns an array of clauses associated with this directive.
-  MutableArrayRef<OMPClause *> getClauses() {
-    return MutableArrayRef<OMPClause *>(getTrailingObjects<OMPClause *>(),
-                                        NumClauses);
-  }
-
-  /// Sets an array of clauses to this requires declaration
-  void setClauses(ArrayRef<OMPClause *> CL);
-
 public:
   static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC,
                                  SourceLocation L, ArrayRef<Expr *> VL,
@@ -482,11 +510,10 @@ class OMPAllocateDecl final
   using clauselist_range = llvm::iterator_range<clauselist_iterator>;
   using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>;
 
-
-  unsigned varlist_size() const { return NumVars; }
-  bool varlist_empty() const { return NumVars == 0; }
-  unsigned clauselist_size() const { return NumClauses; }
-  bool clauselist_empty() const { return NumClauses == 0; }
+  unsigned varlist_size() const { return Data->getNumChildren(); }
+  bool varlist_empty() const { return Data->getChildren().empty(); }
+  unsigned clauselist_size() const { return Data->getNumClauses(); }
+  bool clauselist_empty() const { return Data->getClauses().empty(); }
 
   varlist_range varlists() {
     return varlist_range(varlist_begin(), varlist_end());
@@ -505,13 +532,13 @@ class OMPAllocateDecl final
   clauselist_const_range clauselists() const {
     return clauselist_const_range(clauselist_begin(), clauselist_end());
   }
-  clauselist_iterator clauselist_begin() { return getClauses().begin(); }
-  clauselist_iterator clauselist_end() { return getClauses().end(); }
+  clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); }
+  clauselist_iterator clauselist_end() { return Data->getClauses().end(); }
   clauselist_const_iterator clauselist_begin() const {
-    return getClauses().begin();
+    return Data->getClauses().begin();
   }
   clauselist_const_iterator clauselist_end() const {
-    return getClauses().end();
+    return Data->getClauses().end();
   }
 
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }

diff  --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 5b588f4b5740d..01e915d5ce9d6 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -16,6 +16,7 @@
 #ifndef LLVM_CLANG_AST_OPENMPCLAUSE_H
 #define LLVM_CLANG_AST_OPENMPCLAUSE_H
 
+#include "clang/AST/ASTFwd.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/Expr.h"
@@ -7878,6 +7879,150 @@ struct TargetOMPContext final : public llvm::omp::OMPContext {
   llvm::StringMap<bool> FeatureMap;
 };
 
+/// Contains data for OpenMP directives: clauses, children
+/// expressions/statements (helpers for codegen) and associated statement, if
+/// any.
+class OMPChildren final
+    : private llvm::TrailingObjects<OMPChildren, OMPClause *, Stmt *> {
+  friend class OMPClauseReader;
+  friend class TrailingObjects;
+  friend class OMPExecutableDirective;
+  template <typename T> friend class OMPDeclarativeDirective;
+
+  /// Numbers of clauses.
+  unsigned NumClauses = 0;
+  /// Number of child expressions/stmts.
+  unsigned NumChildren = 0;
+  /// true if the directive has associated statement.
+  bool HasAssociatedStmt = false;
+
+  /// Define the sizes of each trailing object array except the last one. This
+  /// is required for TrailingObjects to work properly.
+  size_t numTrailingObjects(OverloadToken<OMPClause *>) const {
+    return NumClauses;
+  }
+
+  OMPChildren() = delete;
+
+  OMPChildren(unsigned NumClauses, unsigned NumChildren, bool HasAssociatedStmt)
+      : NumClauses(NumClauses), NumChildren(NumChildren),
+        HasAssociatedStmt(HasAssociatedStmt) {}
+
+  static size_t size(unsigned NumClauses, bool HasAssociatedStmt,
+                     unsigned NumChildren);
+
+  static OMPChildren *Create(void *Mem, ArrayRef<OMPClause *> Clauses);
+  static OMPChildren *Create(void *Mem, ArrayRef<OMPClause *> Clauses, Stmt *S,
+                             unsigned NumChildren = 0);
+  static OMPChildren *CreateEmpty(void *Mem, unsigned NumClauses,
+                                  bool HasAssociatedStmt = false,
+                                  unsigned NumChildren = 0);
+
+public:
+  unsigned getNumClauses() const { return NumClauses; }
+  unsigned getNumChildren() const { return NumChildren; }
+  bool hasAssociatedStmt() const { return HasAssociatedStmt; }
+
+  /// Set associated statement.
+  void setAssociatedStmt(Stmt *S) {
+    getTrailingObjects<Stmt *>()[NumChildren] = S;
+  }
+
+  void setChildren(ArrayRef<Stmt *> Children);
+
+  /// Sets the list of variables for this clause.
+  ///
+  /// \param Clauses The list of clauses for the directive.
+  ///
+  void setClauses(ArrayRef<OMPClause *> Clauses);
+
+  /// Returns statement associated with the directive.
+  const Stmt *getAssociatedStmt() const {
+    return const_cast<OMPChildren *>(this)->getAssociatedStmt();
+  }
+  Stmt *getAssociatedStmt() {
+    assert(HasAssociatedStmt &&
+           "Expected directive with the associated statement.");
+    return getTrailingObjects<Stmt *>()[NumChildren];
+  }
+
+  /// Get the clauses storage.
+  MutableArrayRef<OMPClause *> getClauses() {
+    return llvm::makeMutableArrayRef(getTrailingObjects<OMPClause *>(),
+                                     NumClauses);
+  }
+  ArrayRef<OMPClause *> getClauses() const {
+    return const_cast<OMPChildren *>(this)->getClauses();
+  }
+
+  /// Returns the captured statement associated with the
+  /// component region within the (combined) directive.
+  ///
+  /// \param RegionKind Component region kind.
+  const CapturedStmt *
+  getCapturedStmt(OpenMPDirectiveKind RegionKind,
+                  ArrayRef<OpenMPDirectiveKind> CaptureRegions) const {
+    assert(llvm::any_of(
+               CaptureRegions,
+               [=](const OpenMPDirectiveKind K) { return K == RegionKind; }) &&
+           "RegionKind not found in OpenMP CaptureRegions.");
+    auto *CS = cast<CapturedStmt>(getAssociatedStmt());
+    for (auto ThisCaptureRegion : CaptureRegions) {
+      if (ThisCaptureRegion == RegionKind)
+        return CS;
+      CS = cast<CapturedStmt>(CS->getCapturedStmt());
+    }
+    llvm_unreachable("Incorrect RegionKind specified for directive.");
+  }
+
+  /// Get innermost captured statement for the construct.
+  CapturedStmt *
+  getInnermostCapturedStmt(ArrayRef<OpenMPDirectiveKind> CaptureRegions) {
+    assert(hasAssociatedStmt() && "Must have associated captured statement.");
+    assert(!CaptureRegions.empty() &&
+           "At least one captured statement must be provided.");
+    auto *CS = cast<CapturedStmt>(getAssociatedStmt());
+    for (unsigned Level = CaptureRegions.size(); Level > 1; --Level)
+      CS = cast<CapturedStmt>(CS->getCapturedStmt());
+    return CS;
+  }
+
+  const CapturedStmt *
+  getInnermostCapturedStmt(ArrayRef<OpenMPDirectiveKind> CaptureRegions) const {
+    return const_cast<OMPChildren *>(this)->getInnermostCapturedStmt(
+        CaptureRegions);
+  }
+
+  MutableArrayRef<Stmt *> getChildren();
+  ArrayRef<Stmt *> getChildren() const {
+    return const_cast<OMPChildren *>(this)->getChildren();
+  }
+
+  Stmt *getRawStmt() {
+    assert(HasAssociatedStmt &&
+           "Expected directive with the associated statement.");
+    if (auto *CS = dyn_cast<CapturedStmt>(getAssociatedStmt())) {
+      Stmt *S = nullptr;
+      do {
+        S = CS->getCapturedStmt();
+        CS = dyn_cast<CapturedStmt>(S);
+      } while (CS);
+      return S;
+    }
+    return getAssociatedStmt();
+  }
+  const Stmt *getRawStmt() const {
+    return const_cast<OMPChildren *>(this)->getRawStmt();
+  }
+
+  Stmt::child_range getAssociatedStmtAsRange() {
+    if (!HasAssociatedStmt)
+      return Stmt::child_range(Stmt::child_iterator(), Stmt::child_iterator());
+    return Stmt::child_range(&getTrailingObjects<Stmt *>()[NumChildren],
+                             &getTrailingObjects<Stmt *>()[NumChildren + 1]);
+  }
+};
+
 } // namespace clang
 
 #endif // LLVM_CLANG_AST_OPENMPCLAUSE_H

diff  --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h
index bd87eafc90348..0bb91a4ec9eca 100644
--- a/clang/include/clang/AST/StmtOpenMP.h
+++ b/clang/include/clang/AST/StmtOpenMP.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_AST_STMTOPENMP_H
 #define LLVM_CLANG_AST_STMTOPENMP_H
 
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/OpenMPClause.h"
 #include "clang/AST/Stmt.h"
@@ -32,30 +33,26 @@ namespace clang {
 ///
 class OMPExecutableDirective : public Stmt {
   friend class ASTStmtReader;
+  friend class ASTStmtWriter;
+
   /// Kind of the directive.
-  OpenMPDirectiveKind Kind;
+  OpenMPDirectiveKind Kind = llvm::omp::OMPD_unknown;
   /// Starting location of the directive (directive keyword).
   SourceLocation StartLoc;
   /// Ending location of the directive.
   SourceLocation EndLoc;
-  /// Numbers of clauses.
-  const unsigned NumClauses;
-  /// Number of child expressions/stmts.
-  const unsigned NumChildren;
-  /// Offset from this to the start of clauses.
-  /// There are NumClauses pointers to clauses, they are followed by
-  /// NumChildren pointers to child stmts/exprs (if the directive type
-  /// requires an associated stmt, then it has to be the first of them).
-  const unsigned ClausesOffset;
 
   /// Get the clauses storage.
   MutableArrayRef<OMPClause *> getClauses() {
-    OMPClause **ClauseStorage = reinterpret_cast<OMPClause **>(
-        reinterpret_cast<char *>(this) + ClausesOffset);
-    return MutableArrayRef<OMPClause *>(ClauseStorage, NumClauses);
+    if (!Data)
+      return llvm::None;
+    return Data->getClauses();
   }
 
 protected:
+  /// Data, associated with the directive.
+  OMPChildren *Data = nullptr;
+
   /// Build instance of directive of class \a K.
   ///
   /// \param SC Statement class.
@@ -63,28 +60,57 @@ class OMPExecutableDirective : public Stmt {
   /// \param StartLoc Starting location of the directive (directive keyword).
   /// \param EndLoc Ending location of the directive.
   ///
-  template <typename T>
-  OMPExecutableDirective(const T *, StmtClass SC, OpenMPDirectiveKind K,
-                         SourceLocation StartLoc, SourceLocation EndLoc,
-                         unsigned NumClauses, unsigned NumChildren)
+  OMPExecutableDirective(StmtClass SC, OpenMPDirectiveKind K,
+                         SourceLocation StartLoc, SourceLocation EndLoc)
       : Stmt(SC), Kind(K), StartLoc(std::move(StartLoc)),
-        EndLoc(std::move(EndLoc)), NumClauses(NumClauses),
-        NumChildren(NumChildren),
-        ClausesOffset(llvm::alignTo(sizeof(T), alignof(OMPClause *))) {}
-
-  /// Sets the list of variables for this clause.
-  ///
-  /// \param Clauses The list of clauses for the directive.
-  ///
-  void setClauses(ArrayRef<OMPClause *> Clauses);
+        EndLoc(std::move(EndLoc)) {}
+
+  template <typename T, typename... Params>
+  static T *createDirective(const ASTContext &C, ArrayRef<OMPClause *> Clauses,
+                            Stmt *AssociatedStmt, unsigned NumChildren,
+                            Params &&... P) {
+    void *Mem =
+        C.Allocate(sizeof(T) + OMPChildren::size(Clauses.size(), AssociatedStmt,
+                                                 NumChildren),
+                   alignof(T));
+
+    auto *Data = OMPChildren::Create(reinterpret_cast<T *>(Mem) + 1, Clauses,
+                                     AssociatedStmt, NumChildren);
+    auto *Inst = new (Mem) T(std::forward<Params>(P)...);
+    Inst->Data = Data;
+    return Inst;
+  }
+
+  template <typename T, typename... Params>
+  static T *createEmptyDirective(const ASTContext &C, unsigned NumClauses,
+                                 bool HasAssociatedStmt, unsigned NumChildren,
+                                 Params &&... P) {
+    void *Mem =
+        C.Allocate(sizeof(T) + OMPChildren::size(NumClauses, HasAssociatedStmt,
+                                                 NumChildren),
+                   alignof(T));
+    auto *Data =
+        OMPChildren::CreateEmpty(reinterpret_cast<T *>(Mem) + 1, NumClauses,
+                                 HasAssociatedStmt, NumChildren);
+    auto *Inst = new (Mem) T(std::forward<Params>(P)...);
+    Inst->Data = Data;
+    return Inst;
+  }
 
-  /// Set the associated statement for the directive.
-  ///
-  /// /param S Associated statement.
-  ///
-  void setAssociatedStmt(Stmt *S) {
-    assert(hasAssociatedStmt() && "no associated statement.");
-    *child_begin() = S;
+  template <typename T>
+  static T *createEmptyDirective(const ASTContext &C, unsigned NumClauses,
+                                 bool HasAssociatedStmt = false,
+                                 unsigned NumChildren = 0) {
+    void *Mem =
+        C.Allocate(sizeof(T) + OMPChildren::size(NumClauses, HasAssociatedStmt,
+                                                 NumChildren),
+                   alignof(T));
+    auto *Data =
+        OMPChildren::CreateEmpty(reinterpret_cast<T *>(Mem) + 1, NumClauses,
+                                 HasAssociatedStmt, NumChildren);
+    auto *Inst = new (Mem) T;
+    Inst->Data = Data;
+    return Inst;
   }
 
 public:
@@ -238,59 +264,50 @@ class OMPExecutableDirective : public Stmt {
   void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
 
   /// Get number of clauses.
-  unsigned getNumClauses() const { return NumClauses; }
+  unsigned getNumClauses() const {
+    if (!Data)
+      return 0;
+    return Data->getNumClauses();
+  }
 
   /// Returns specified clause.
   ///
-  /// \param i Number of clause.
+  /// \param I Number of clause.
   ///
-  OMPClause *getClause(unsigned i) const { return clauses()[i]; }
+  OMPClause *getClause(unsigned I) const { return clauses()[I]; }
 
   /// Returns true if directive has associated statement.
-  bool hasAssociatedStmt() const { return NumChildren > 0; }
+  bool hasAssociatedStmt() const { return Data && Data->hasAssociatedStmt(); }
 
   /// Returns statement associated with the directive.
   const Stmt *getAssociatedStmt() const {
-    assert(hasAssociatedStmt() && "no associated statement.");
-    return *child_begin();
+    return const_cast<OMPExecutableDirective *>(this)->getAssociatedStmt();
   }
   Stmt *getAssociatedStmt() {
-    assert(hasAssociatedStmt() && "no associated statement.");
-    return *child_begin();
+    assert(hasAssociatedStmt() &&
+           "Expected directive with the associated statement.");
+    return Data->getAssociatedStmt();
   }
 
   /// Returns the captured statement associated with the
   /// component region within the (combined) directive.
-  //
-  // \param RegionKind Component region kind.
+  ///
+  /// \param RegionKind Component region kind.
   const CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const {
+    assert(hasAssociatedStmt() &&
+           "Expected directive with the associated statement.");
     SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
     getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
-    assert(std::any_of(
-               CaptureRegions.begin(), CaptureRegions.end(),
-               [=](const OpenMPDirectiveKind K) { return K == RegionKind; }) &&
-           "RegionKind not found in OpenMP CaptureRegions.");
-    auto *CS = cast<CapturedStmt>(getAssociatedStmt());
-    for (auto ThisCaptureRegion : CaptureRegions) {
-      if (ThisCaptureRegion == RegionKind)
-        return CS;
-      CS = cast<CapturedStmt>(CS->getCapturedStmt());
-    }
-    llvm_unreachable("Incorrect RegionKind specified for directive.");
+    return Data->getCapturedStmt(RegionKind, CaptureRegions);
   }
 
   /// Get innermost captured statement for the construct.
   CapturedStmt *getInnermostCapturedStmt() {
-    assert(hasAssociatedStmt() && getAssociatedStmt() &&
-           "Must have associated statement.");
+    assert(hasAssociatedStmt() &&
+           "Expected directive with the associated statement.");
     SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
     getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
-    assert(!CaptureRegions.empty() &&
-           "At least one captured statement must be provided.");
-    auto *CS = cast<CapturedStmt>(getAssociatedStmt());
-    for (unsigned Level = CaptureRegions.size(); Level > 1; --Level)
-      CS = cast<CapturedStmt>(CS->getCapturedStmt());
-    return CS;
+    return Data->getInnermostCapturedStmt(CaptureRegions);
   }
 
   const CapturedStmt *getInnermostCapturedStmt() const {
@@ -306,26 +323,19 @@ class OMPExecutableDirective : public Stmt {
   }
 
   child_range children() {
-    if (!hasAssociatedStmt())
+    if (!Data)
       return child_range(child_iterator(), child_iterator());
-    Stmt **ChildStorage = reinterpret_cast<Stmt **>(getClauses().end());
-    /// Do not mark all the special expression/statements as children, except
-    /// for the associated statement.
-    return child_range(ChildStorage, ChildStorage + 1);
+    return Data->getAssociatedStmtAsRange();
   }
 
   const_child_range children() const {
-    if (!hasAssociatedStmt())
-      return const_child_range(const_child_iterator(), const_child_iterator());
-    Stmt **ChildStorage = reinterpret_cast<Stmt **>(
-        const_cast<OMPExecutableDirective *>(this)->getClauses().end());
-    return const_child_range(ChildStorage, ChildStorage + 1);
+    return const_cast<OMPExecutableDirective *>(this)->children();
   }
 
-  ArrayRef<OMPClause *> clauses() { return getClauses(); }
-
   ArrayRef<OMPClause *> clauses() const {
-    return const_cast<OMPExecutableDirective *>(this)->getClauses();
+    if (!Data)
+      return llvm::None;
+    return Data->getClauses();
   }
 
   /// Returns whether or not this is a Standalone directive.
@@ -337,11 +347,18 @@ class OMPExecutableDirective : public Stmt {
   /// Returns the AST node representing OpenMP structured-block of this
   /// OpenMP executable directive,
   /// Prerequisite: Executable Directive must not be Standalone directive.
-  const Stmt *getStructuredBlock() const;
+  const Stmt *getStructuredBlock() const {
+    return const_cast<OMPExecutableDirective *>(this)->getStructuredBlock();
+  }
+  Stmt *getStructuredBlock();
 
-  Stmt *getStructuredBlock() {
-    return const_cast<Stmt *>(
-        const_cast<const OMPExecutableDirective *>(this)->getStructuredBlock());
+  const Stmt *getRawStmt() const {
+    return const_cast<OMPExecutableDirective *>(this)->getRawStmt();
+  }
+  Stmt *getRawStmt() {
+    assert(hasAssociatedStmt() &&
+           "Expected directive with the associated statement.");
+    return Data->getRawStmt();
   }
 };
 
@@ -356,36 +373,28 @@ class OMPExecutableDirective : public Stmt {
 ///
 class OMPParallelDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
-  /// Special reference expression for handling task reduction. Used to store
-  /// the taskgroup descriptor returned by the runtime functions.
-  Expr *TaskRedRef = nullptr;
+  friend class OMPExecutableDirective;
   /// true if the construct has inner cancel directive.
-  bool HasCancel;
+  bool HasCancel = false;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive (directive keyword).
   /// \param EndLoc Ending Location of the directive.
   ///
-  OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                       unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPParallelDirectiveClass,
-                               llvm::omp::OMPD_parallel, StartLoc, EndLoc,
-                               NumClauses, 1),
-        HasCancel(false) {}
+  OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPParallelDirectiveClass,
+                               llvm::omp::OMPD_parallel, StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPParallelDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPParallelDirectiveClass,
+  explicit OMPParallelDirective()
+      : OMPExecutableDirective(OMPParallelDirectiveClass,
                                llvm::omp::OMPD_parallel, SourceLocation(),
-                               SourceLocation(), NumClauses, 1),
-        HasCancel(false) {}
+                               SourceLocation()) {}
 
   /// Sets special task reduction descriptor.
-  void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
+  void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -416,8 +425,12 @@ class OMPParallelDirective : public OMPExecutableDirective {
                                            unsigned NumClauses, EmptyShell);
 
   /// Returns special task reduction reference expression.
-  Expr *getTaskReductionRefExpr() { return TaskRedRef; }
-  const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
+  Expr *getTaskReductionRefExpr() {
+    return cast_or_null<Expr>(Data->getChildren()[0]);
+  }
+  const Expr *getTaskReductionRefExpr() const {
+    return const_cast<OMPParallelDirective *>(this)->getTaskReductionRefExpr();
+  }
 
   /// Return true if current directive has inner cancel directive.
   bool hasCancel() const { return HasCancel; }
@@ -433,7 +446,7 @@ class OMPParallelDirective : public OMPExecutableDirective {
 class OMPLoopDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
   /// Number of collapsed loops as specified by 'collapse' clause.
-  unsigned CollapsedNum;
+  unsigned CollapsedNum = 0;
 
   /// Offsets to the stored exprs.
   /// This enumeration contains offsets to all the pointers to children
@@ -452,110 +465,110 @@ class OMPLoopDirective : public OMPExecutableDirective {
   /// (e.g. 'distribute parallel for')
   ///
   enum {
-    AssociatedStmtOffset = 0,
-    IterationVariableOffset = 1,
-    LastIterationOffset = 2,
-    CalcLastIterationOffset = 3,
-    PreConditionOffset = 4,
-    CondOffset = 5,
-    InitOffset = 6,
-    IncOffset = 7,
-    PreInitsOffset = 8,
+    IterationVariableOffset = 0,
+    LastIterationOffset = 1,
+    CalcLastIterationOffset = 2,
+    PreConditionOffset = 3,
+    CondOffset = 4,
+    InitOffset = 5,
+    IncOffset = 6,
+    PreInitsOffset = 7,
     // The '...End' enumerators do not correspond to child expressions - they
     // specify the offset to the end (and start of the following counters/
     // updates/finals/dependent_counters/dependent_inits/finals_conditions
     // arrays).
-    DefaultEnd = 9,
+    DefaultEnd = 8,
     // The following 8 exprs are used by worksharing and distribute loops only.
-    IsLastIterVariableOffset = 9,
-    LowerBoundVariableOffset = 10,
-    UpperBoundVariableOffset = 11,
-    StrideVariableOffset = 12,
-    EnsureUpperBoundOffset = 13,
-    NextLowerBoundOffset = 14,
-    NextUpperBoundOffset = 15,
-    NumIterationsOffset = 16,
+    IsLastIterVariableOffset = 8,
+    LowerBoundVariableOffset = 9,
+    UpperBoundVariableOffset = 10,
+    StrideVariableOffset = 11,
+    EnsureUpperBoundOffset = 12,
+    NextLowerBoundOffset = 13,
+    NextUpperBoundOffset = 14,
+    NumIterationsOffset = 15,
     // Offset to the end for worksharing loop directives.
-    WorksharingEnd = 17,
-    PrevLowerBoundVariableOffset = 17,
-    PrevUpperBoundVariableOffset = 18,
-    DistIncOffset = 19,
-    PrevEnsureUpperBoundOffset = 20,
-    CombinedLowerBoundVariableOffset = 21,
-    CombinedUpperBoundVariableOffset = 22,
-    CombinedEnsureUpperBoundOffset = 23,
-    CombinedInitOffset = 24,
-    CombinedConditionOffset = 25,
-    CombinedNextLowerBoundOffset = 26,
-    CombinedNextUpperBoundOffset = 27,
-    CombinedDistConditionOffset = 28,
-    CombinedParForInDistConditionOffset = 29,
+    WorksharingEnd = 16,
+    PrevLowerBoundVariableOffset = 16,
+    PrevUpperBoundVariableOffset = 17,
+    DistIncOffset = 18,
+    PrevEnsureUpperBoundOffset = 19,
+    CombinedLowerBoundVariableOffset = 20,
+    CombinedUpperBoundVariableOffset = 21,
+    CombinedEnsureUpperBoundOffset = 22,
+    CombinedInitOffset = 23,
+    CombinedConditionOffset = 24,
+    CombinedNextLowerBoundOffset = 25,
+    CombinedNextUpperBoundOffset = 26,
+    CombinedDistConditionOffset = 27,
+    CombinedParForInDistConditionOffset = 28,
     // Offset to the end (and start of the following
     // counters/updates/finals/dependent_counters/dependent_inits/finals_conditions
     // arrays) for combined distribute loop directives.
-    CombinedDistributeEnd = 30,
+    CombinedDistributeEnd = 29,
   };
 
   /// Get the counters storage.
   MutableArrayRef<Expr *> getCounters() {
-    Expr **Storage = reinterpret_cast<Expr **>(
-        &(*(std::next(child_begin(), getArraysOffset(getDirectiveKind())))));
-    return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+    auto **Storage = reinterpret_cast<Expr **>(
+        &Data->getChildren()[getArraysOffset(getDirectiveKind())]);
+    return llvm::makeMutableArrayRef(Storage, CollapsedNum);
   }
 
   /// Get the private counters storage.
   MutableArrayRef<Expr *> getPrivateCounters() {
-    Expr **Storage = reinterpret_cast<Expr **>(&*std::next(
-        child_begin(), getArraysOffset(getDirectiveKind()) + CollapsedNum));
-    return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+    auto **Storage = reinterpret_cast<Expr **>(
+        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
+                             CollapsedNum]);
+    return llvm::makeMutableArrayRef(Storage, CollapsedNum);
   }
 
   /// Get the updates storage.
   MutableArrayRef<Expr *> getInits() {
-    Expr **Storage = reinterpret_cast<Expr **>(
-        &*std::next(child_begin(),
-                    getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum));
-    return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+    auto **Storage = reinterpret_cast<Expr **>(
+        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
+                             2 * CollapsedNum]);
+    return llvm::makeMutableArrayRef(Storage, CollapsedNum);
   }
 
   /// Get the updates storage.
   MutableArrayRef<Expr *> getUpdates() {
-    Expr **Storage = reinterpret_cast<Expr **>(
-        &*std::next(child_begin(),
-                    getArraysOffset(getDirectiveKind()) + 3 * CollapsedNum));
-    return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+    auto **Storage = reinterpret_cast<Expr **>(
+        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
+                             3 * CollapsedNum]);
+    return llvm::makeMutableArrayRef(Storage, CollapsedNum);
   }
 
   /// Get the final counter updates storage.
   MutableArrayRef<Expr *> getFinals() {
-    Expr **Storage = reinterpret_cast<Expr **>(
-        &*std::next(child_begin(),
-                    getArraysOffset(getDirectiveKind()) + 4 * CollapsedNum));
-    return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+    auto **Storage = reinterpret_cast<Expr **>(
+        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
+                             4 * CollapsedNum]);
+    return llvm::makeMutableArrayRef(Storage, CollapsedNum);
   }
 
   /// Get the dependent counters storage.
   MutableArrayRef<Expr *> getDependentCounters() {
-    Expr **Storage = reinterpret_cast<Expr **>(
-        &*std::next(child_begin(),
-                    getArraysOffset(getDirectiveKind()) + 5 * CollapsedNum));
-    return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+    auto **Storage = reinterpret_cast<Expr **>(
+        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
+                             5 * CollapsedNum]);
+    return llvm::makeMutableArrayRef(Storage, CollapsedNum);
   }
 
   /// Get the dependent inits storage.
   MutableArrayRef<Expr *> getDependentInits() {
-    Expr **Storage = reinterpret_cast<Expr **>(
-        &*std::next(child_begin(),
-                    getArraysOffset(getDirectiveKind()) + 6 * CollapsedNum));
-    return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+    auto **Storage = reinterpret_cast<Expr **>(
+        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
+                             6 * CollapsedNum]);
+    return llvm::makeMutableArrayRef(Storage, CollapsedNum);
   }
 
   /// Get the finals conditions storage.
   MutableArrayRef<Expr *> getFinalsConditions() {
-    Expr **Storage = reinterpret_cast<Expr **>(
-        &*std::next(child_begin(),
-                    getArraysOffset(getDirectiveKind()) + 7 * CollapsedNum));
-    return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+    auto **Storage = reinterpret_cast<Expr **>(
+        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
+                             7 * CollapsedNum]);
+    return llvm::makeMutableArrayRef(Storage, CollapsedNum);
   }
 
 protected:
@@ -566,17 +579,11 @@ class OMPLoopDirective : public OMPExecutableDirective {
   /// \param StartLoc Starting location of the directive (directive keyword).
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed loops from 'collapse' clause.
-  /// \param NumClauses Number of clauses.
-  /// \param NumSpecialChildren Number of additional directive-specific stmts.
   ///
-  template <typename T>
-  OMPLoopDirective(const T *That, StmtClass SC, OpenMPDirectiveKind Kind,
+  OMPLoopDirective(StmtClass SC, OpenMPDirectiveKind Kind,
                    SourceLocation StartLoc, SourceLocation EndLoc,
-                   unsigned CollapsedNum, unsigned NumClauses,
-                   unsigned NumSpecialChildren = 0)
-      : OMPExecutableDirective(That, SC, Kind, StartLoc, EndLoc, NumClauses,
-                               numLoopChildren(CollapsedNum, Kind) +
-                                   NumSpecialChildren),
+                   unsigned CollapsedNum)
+      : OMPExecutableDirective(SC, Kind, StartLoc, EndLoc),
         CollapsedNum(CollapsedNum) {}
 
   /// Offset to the start of children expression arrays.
@@ -599,146 +606,142 @@ class OMPLoopDirective : public OMPExecutableDirective {
   }
 
   void setIterationVariable(Expr *IV) {
-    *std::next(child_begin(), IterationVariableOffset) = IV;
+    Data->getChildren()[IterationVariableOffset] = IV;
   }
   void setLastIteration(Expr *LI) {
-    *std::next(child_begin(), LastIterationOffset) = LI;
+    Data->getChildren()[LastIterationOffset] = LI;
   }
   void setCalcLastIteration(Expr *CLI) {
-    *std::next(child_begin(), CalcLastIterationOffset) = CLI;
-  }
-  void setPreCond(Expr *PC) {
-    *std::next(child_begin(), PreConditionOffset) = PC;
+    Data->getChildren()[CalcLastIterationOffset] = CLI;
   }
-  void setCond(Expr *Cond) {
-    *std::next(child_begin(), CondOffset) = Cond;
-  }
-  void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; }
-  void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; }
+  void setPreCond(Expr *PC) { Data->getChildren()[PreConditionOffset] = PC; }
+  void setCond(Expr *Cond) { Data->getChildren()[CondOffset] = Cond; }
+  void setInit(Expr *Init) { Data->getChildren()[InitOffset] = Init; }
+  void setInc(Expr *Inc) { Data->getChildren()[IncOffset] = Inc; }
   void setPreInits(Stmt *PreInits) {
-    *std::next(child_begin(), PreInitsOffset) = PreInits;
+    Data->getChildren()[PreInitsOffset] = PreInits;
   }
   void setIsLastIterVariable(Expr *IL) {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    *std::next(child_begin(), IsLastIterVariableOffset) = IL;
+    Data->getChildren()[IsLastIterVariableOffset] = IL;
   }
   void setLowerBoundVariable(Expr *LB) {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    *std::next(child_begin(), LowerBoundVariableOffset) = LB;
+    Data->getChildren()[LowerBoundVariableOffset] = LB;
   }
   void setUpperBoundVariable(Expr *UB) {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    *std::next(child_begin(), UpperBoundVariableOffset) = UB;
+    Data->getChildren()[UpperBoundVariableOffset] = UB;
   }
   void setStrideVariable(Expr *ST) {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    *std::next(child_begin(), StrideVariableOffset) = ST;
+    Data->getChildren()[StrideVariableOffset] = ST;
   }
   void setEnsureUpperBound(Expr *EUB) {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    *std::next(child_begin(), EnsureUpperBoundOffset) = EUB;
+    Data->getChildren()[EnsureUpperBoundOffset] = EUB;
   }
   void setNextLowerBound(Expr *NLB) {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    *std::next(child_begin(), NextLowerBoundOffset) = NLB;
+    Data->getChildren()[NextLowerBoundOffset] = NLB;
   }
   void setNextUpperBound(Expr *NUB) {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    *std::next(child_begin(), NextUpperBoundOffset) = NUB;
+    Data->getChildren()[NextUpperBoundOffset] = NUB;
   }
   void setNumIterations(Expr *NI) {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    *std::next(child_begin(), NumIterationsOffset) = NI;
+    Data->getChildren()[NumIterationsOffset] = NI;
   }
   void setPrevLowerBoundVariable(Expr *PrevLB) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    *std::next(child_begin(), PrevLowerBoundVariableOffset) = PrevLB;
+    Data->getChildren()[PrevLowerBoundVariableOffset] = PrevLB;
   }
   void setPrevUpperBoundVariable(Expr *PrevUB) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    *std::next(child_begin(), PrevUpperBoundVariableOffset) = PrevUB;
+    Data->getChildren()[PrevUpperBoundVariableOffset] = PrevUB;
   }
   void setDistInc(Expr *DistInc) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    *std::next(child_begin(), DistIncOffset) = DistInc;
+    Data->getChildren()[DistIncOffset] = DistInc;
   }
   void setPrevEnsureUpperBound(Expr *PrevEUB) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    *std::next(child_begin(), PrevEnsureUpperBoundOffset) = PrevEUB;
+    Data->getChildren()[PrevEnsureUpperBoundOffset] = PrevEUB;
   }
   void setCombinedLowerBoundVariable(Expr *CombLB) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    *std::next(child_begin(), CombinedLowerBoundVariableOffset) = CombLB;
+    Data->getChildren()[CombinedLowerBoundVariableOffset] = CombLB;
   }
   void setCombinedUpperBoundVariable(Expr *CombUB) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    *std::next(child_begin(), CombinedUpperBoundVariableOffset) = CombUB;
+    Data->getChildren()[CombinedUpperBoundVariableOffset] = CombUB;
   }
   void setCombinedEnsureUpperBound(Expr *CombEUB) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    *std::next(child_begin(), CombinedEnsureUpperBoundOffset) = CombEUB;
+    Data->getChildren()[CombinedEnsureUpperBoundOffset] = CombEUB;
   }
   void setCombinedInit(Expr *CombInit) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    *std::next(child_begin(), CombinedInitOffset) = CombInit;
+    Data->getChildren()[CombinedInitOffset] = CombInit;
   }
   void setCombinedCond(Expr *CombCond) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    *std::next(child_begin(), CombinedConditionOffset) = CombCond;
+    Data->getChildren()[CombinedConditionOffset] = CombCond;
   }
   void setCombinedNextLowerBound(Expr *CombNLB) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    *std::next(child_begin(), CombinedNextLowerBoundOffset) = CombNLB;
+    Data->getChildren()[CombinedNextLowerBoundOffset] = CombNLB;
   }
   void setCombinedNextUpperBound(Expr *CombNUB) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    *std::next(child_begin(), CombinedNextUpperBoundOffset) = CombNUB;
+    Data->getChildren()[CombinedNextUpperBoundOffset] = CombNUB;
   }
   void setCombinedDistCond(Expr *CombDistCond) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound distribute sharing directive");
-    *std::next(child_begin(), CombinedDistConditionOffset) = CombDistCond;
+    Data->getChildren()[CombinedDistConditionOffset] = CombDistCond;
   }
   void setCombinedParForInDistCond(Expr *CombParForInDistCond) {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound distribute sharing directive");
-    *std::next(child_begin(),
-               CombinedParForInDistConditionOffset) = CombParForInDistCond;
+    Data->getChildren()[CombinedParForInDistConditionOffset] =
+        CombParForInDistCond;
   }
   void setCounters(ArrayRef<Expr *> A);
   void setPrivateCounters(ArrayRef<Expr *> A);
@@ -925,178 +928,144 @@ class OMPLoopDirective : public OMPExecutableDirective {
   unsigned getCollapsedNumber() const { return CollapsedNum; }
 
   Expr *getIterationVariable() const {
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), IterationVariableOffset)));
+    return cast<Expr>(Data->getChildren()[IterationVariableOffset]);
   }
   Expr *getLastIteration() const {
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), LastIterationOffset)));
+    return cast<Expr>(Data->getChildren()[LastIterationOffset]);
   }
   Expr *getCalcLastIteration() const {
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), CalcLastIterationOffset)));
+    return cast<Expr>(Data->getChildren()[CalcLastIterationOffset]);
   }
   Expr *getPreCond() const {
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), PreConditionOffset)));
-  }
-  Expr *getCond() const {
-    return const_cast<Expr *>(
-        reinterpret_cast<const Expr *>(*std::next(child_begin(), CondOffset)));
-  }
-  Expr *getInit() const {
-    return const_cast<Expr *>(
-        reinterpret_cast<const Expr *>(*std::next(child_begin(), InitOffset)));
-  }
-  Expr *getInc() const {
-    return const_cast<Expr *>(
-        reinterpret_cast<const Expr *>(*std::next(child_begin(), IncOffset)));
+    return cast<Expr>(Data->getChildren()[PreConditionOffset]);
   }
+  Expr *getCond() const { return cast<Expr>(Data->getChildren()[CondOffset]); }
+  Expr *getInit() const { return cast<Expr>(Data->getChildren()[InitOffset]); }
+  Expr *getInc() const { return cast<Expr>(Data->getChildren()[IncOffset]); }
   const Stmt *getPreInits() const {
-    return *std::next(child_begin(), PreInitsOffset);
+    return Data->getChildren()[PreInitsOffset];
   }
-  Stmt *getPreInits() { return *std::next(child_begin(), PreInitsOffset); }
+  Stmt *getPreInits() { return Data->getChildren()[PreInitsOffset]; }
   Expr *getIsLastIterVariable() const {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), IsLastIterVariableOffset)));
+    return cast<Expr>(Data->getChildren()[IsLastIterVariableOffset]);
   }
   Expr *getLowerBoundVariable() const {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), LowerBoundVariableOffset)));
+    return cast<Expr>(Data->getChildren()[LowerBoundVariableOffset]);
   }
   Expr *getUpperBoundVariable() const {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), UpperBoundVariableOffset)));
+    return cast<Expr>(Data->getChildren()[UpperBoundVariableOffset]);
   }
   Expr *getStrideVariable() const {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), StrideVariableOffset)));
+    return cast<Expr>(Data->getChildren()[StrideVariableOffset]);
   }
   Expr *getEnsureUpperBound() const {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), EnsureUpperBoundOffset)));
+    return cast<Expr>(Data->getChildren()[EnsureUpperBoundOffset]);
   }
   Expr *getNextLowerBound() const {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), NextLowerBoundOffset)));
+    return cast<Expr>(Data->getChildren()[NextLowerBoundOffset]);
   }
   Expr *getNextUpperBound() const {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), NextUpperBoundOffset)));
+    return cast<Expr>(Data->getChildren()[NextUpperBoundOffset]);
   }
   Expr *getNumIterations() const {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
             isOpenMPDistributeDirective(getDirectiveKind())) &&
            "expected worksharing loop directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), NumIterationsOffset)));
+    return cast<Expr>(Data->getChildren()[NumIterationsOffset]);
   }
   Expr *getPrevLowerBoundVariable() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), PrevLowerBoundVariableOffset)));
+    return cast<Expr>(Data->getChildren()[PrevLowerBoundVariableOffset]);
   }
   Expr *getPrevUpperBoundVariable() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), PrevUpperBoundVariableOffset)));
+    return cast<Expr>(Data->getChildren()[PrevUpperBoundVariableOffset]);
   }
   Expr *getDistInc() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), DistIncOffset)));
+    return cast<Expr>(Data->getChildren()[DistIncOffset]);
   }
   Expr *getPrevEnsureUpperBound() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), PrevEnsureUpperBoundOffset)));
+    return cast<Expr>(Data->getChildren()[PrevEnsureUpperBoundOffset]);
   }
   Expr *getCombinedLowerBoundVariable() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), CombinedLowerBoundVariableOffset)));
+    return cast<Expr>(Data->getChildren()[CombinedLowerBoundVariableOffset]);
   }
   Expr *getCombinedUpperBoundVariable() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), CombinedUpperBoundVariableOffset)));
+    return cast<Expr>(Data->getChildren()[CombinedUpperBoundVariableOffset]);
   }
   Expr *getCombinedEnsureUpperBound() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), CombinedEnsureUpperBoundOffset)));
+    return cast<Expr>(Data->getChildren()[CombinedEnsureUpperBoundOffset]);
   }
   Expr *getCombinedInit() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), CombinedInitOffset)));
+    return cast<Expr>(Data->getChildren()[CombinedInitOffset]);
   }
   Expr *getCombinedCond() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), CombinedConditionOffset)));
+    return cast<Expr>(Data->getChildren()[CombinedConditionOffset]);
   }
   Expr *getCombinedNextLowerBound() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), CombinedNextLowerBoundOffset)));
+    return cast<Expr>(Data->getChildren()[CombinedNextLowerBoundOffset]);
   }
   Expr *getCombinedNextUpperBound() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), CombinedNextUpperBoundOffset)));
+    return cast<Expr>(Data->getChildren()[CombinedNextUpperBoundOffset]);
   }
   Expr *getCombinedDistCond() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound distribute sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), CombinedDistConditionOffset)));
+    return cast<Expr>(Data->getChildren()[CombinedDistConditionOffset]);
   }
   Expr *getCombinedParForInDistCond() const {
     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
            "expected loop bound distribute sharing directive");
-    return const_cast<Expr *>(reinterpret_cast<const Expr *>(
-        *std::next(child_begin(), CombinedParForInDistConditionOffset)));
+    return cast<Expr>(Data->getChildren()[CombinedParForInDistConditionOffset]);
   }
   /// Try to find the next loop sub-statement in the specified statement \p
   /// CurStmt.
@@ -1206,27 +1175,25 @@ class OMPLoopDirective : public OMPExecutableDirective {
 ///
 class OMPSimdDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                   unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPSimdDirectiveClass, llvm::omp::OMPD_simd,
-                         StartLoc, EndLoc, CollapsedNum, NumClauses) {}
+                   unsigned CollapsedNum)
+      : OMPLoopDirective(OMPSimdDirectiveClass, llvm::omp::OMPD_simd, StartLoc,
+                         EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPSimdDirectiveClass, llvm::omp::OMPD_simd,
-                         SourceLocation(), SourceLocation(), CollapsedNum,
-                         NumClauses) {}
+  explicit OMPSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPSimdDirectiveClass, llvm::omp::OMPD_simd,
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -1271,38 +1238,34 @@ class OMPSimdDirective : public OMPLoopDirective {
 ///
 class OMPForDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
-  /// Special reference expression for handling task reduction. Used to store
-  /// the taskgroup descriptor returned by the runtime functions.
-  Expr *TaskRedRef = nullptr;
+  friend class OMPExecutableDirective;
   /// true if current directive has inner cancel directive.
-  bool HasCancel;
+  bool HasCancel = false;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                  unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPForDirectiveClass, llvm::omp::OMPD_for,
-                         StartLoc, EndLoc, CollapsedNum, NumClauses),
-        HasCancel(false) {}
+                  unsigned CollapsedNum)
+      : OMPLoopDirective(OMPForDirectiveClass, llvm::omp::OMPD_for, StartLoc,
+                         EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPForDirectiveClass, llvm::omp::OMPD_for,
-                         SourceLocation(), SourceLocation(), CollapsedNum,
-                         NumClauses),
-        HasCancel(false) {}
+  explicit OMPForDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPForDirectiveClass, llvm::omp::OMPD_for,
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
   /// Sets special task reduction descriptor.
-  void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
+  void setTaskReductionRefExpr(Expr *E) {
+    Data->getChildren()[numLoopChildren(getCollapsedNumber(),
+                                        llvm::omp::OMPD_for)] = E;
+  }
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -1338,8 +1301,13 @@ class OMPForDirective : public OMPLoopDirective {
                                       unsigned CollapsedNum, EmptyShell);
 
   /// Returns special task reduction reference expression.
-  Expr *getTaskReductionRefExpr() { return TaskRedRef; }
-  const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
+  Expr *getTaskReductionRefExpr() {
+    return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
+        getCollapsedNumber(), llvm::omp::OMPD_for)]);
+  }
+  const Expr *getTaskReductionRefExpr() const {
+    return const_cast<OMPForDirective *>(this)->getTaskReductionRefExpr();
+  }
 
   /// Return true if current directive has inner cancel directive.
   bool hasCancel() const { return HasCancel; }
@@ -1360,28 +1328,25 @@ class OMPForDirective : public OMPLoopDirective {
 ///
 class OMPForSimdDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                      unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPForSimdDirectiveClass,
-                         llvm::omp::OMPD_for_simd, StartLoc, EndLoc,
-                         CollapsedNum, NumClauses) {}
+                      unsigned CollapsedNum)
+      : OMPLoopDirective(OMPForSimdDirectiveClass, llvm::omp::OMPD_for_simd,
+                         StartLoc, EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPForSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPForSimdDirectiveClass,
-                         llvm::omp::OMPD_for_simd, SourceLocation(),
-                         SourceLocation(), CollapsedNum, NumClauses) {}
+  explicit OMPForSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPForSimdDirectiveClass, llvm::omp::OMPD_for_simd,
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -1426,38 +1391,29 @@ class OMPForSimdDirective : public OMPLoopDirective {
 ///
 class OMPSectionsDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
-  /// Special reference expression for handling task reduction. Used to store
-  /// the taskgroup descriptor returned by the runtime functions.
-  Expr *TaskRedRef = nullptr;
   /// true if current directive has inner cancel directive.
-  bool HasCancel;
+  bool HasCancel = false;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                       unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPSectionsDirectiveClass,
-                               llvm::omp::OMPD_sections, StartLoc, EndLoc,
-                               NumClauses, 1),
-        HasCancel(false) {}
+  OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPSectionsDirectiveClass,
+                               llvm::omp::OMPD_sections, StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPSectionsDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPSectionsDirectiveClass,
+  explicit OMPSectionsDirective()
+      : OMPExecutableDirective(OMPSectionsDirectiveClass,
                                llvm::omp::OMPD_sections, SourceLocation(),
-                               SourceLocation(), NumClauses, 1),
-        HasCancel(false) {}
+                               SourceLocation()) {}
 
   /// Sets special task reduction descriptor.
-  void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
+  void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -1489,8 +1445,12 @@ class OMPSectionsDirective : public OMPExecutableDirective {
                                            unsigned NumClauses, EmptyShell);
 
   /// Returns special task reduction reference expression.
-  Expr *getTaskReductionRefExpr() { return TaskRedRef; }
-  const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
+  Expr *getTaskReductionRefExpr() {
+    return cast_or_null<Expr>(Data->getChildren()[0]);
+  }
+  const Expr *getTaskReductionRefExpr() const {
+    return const_cast<OMPSectionsDirective *>(this)->getTaskReductionRefExpr();
+  }
 
   /// Return true if current directive has inner cancel directive.
   bool hasCancel() const { return HasCancel; }
@@ -1508,9 +1468,10 @@ class OMPSectionsDirective : public OMPExecutableDirective {
 ///
 class OMPSectionDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// true if current directive has inner cancel directive.
-  bool HasCancel;
+  bool HasCancel = false;
 
   /// Build directive with the given start and end location.
   ///
@@ -1518,17 +1479,15 @@ class OMPSectionDirective : public OMPExecutableDirective {
   /// \param EndLoc Ending location of the directive.
   ///
   OMPSectionDirective(SourceLocation StartLoc, SourceLocation EndLoc)
-      : OMPExecutableDirective(this, OMPSectionDirectiveClass,
-                               llvm::omp::OMPD_section, StartLoc, EndLoc, 0, 1),
-        HasCancel(false) {}
+      : OMPExecutableDirective(OMPSectionDirectiveClass,
+                               llvm::omp::OMPD_section, StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
   explicit OMPSectionDirective()
-      : OMPExecutableDirective(this, OMPSectionDirectiveClass,
+      : OMPExecutableDirective(OMPSectionDirectiveClass,
                                llvm::omp::OMPD_section, SourceLocation(),
-                               SourceLocation(), 0, 1),
-        HasCancel(false) {}
+                               SourceLocation()) {}
 
 public:
   /// Creates directive.
@@ -1571,26 +1530,21 @@ class OMPSectionDirective : public OMPExecutableDirective {
 ///
 class OMPSingleDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPSingleDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                     unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPSingleDirectiveClass,
-                               llvm::omp::OMPD_single, StartLoc, EndLoc,
-                               NumClauses, 1) {}
+  OMPSingleDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPSingleDirectiveClass, llvm::omp::OMPD_single,
+                               StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPSingleDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPSingleDirectiveClass,
-                               llvm::omp::OMPD_single, SourceLocation(),
-                               SourceLocation(), NumClauses, 1) {}
+  explicit OMPSingleDirective()
+      : OMPExecutableDirective(OMPSingleDirectiveClass, llvm::omp::OMPD_single,
+                               SourceLocation(), SourceLocation()) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -1627,22 +1581,21 @@ class OMPSingleDirective : public OMPExecutableDirective {
 ///
 class OMPMasterDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   ///
   OMPMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc)
-      : OMPExecutableDirective(this, OMPMasterDirectiveClass,
-                               llvm::omp::OMPD_master, StartLoc, EndLoc, 0, 1) {
-  }
+      : OMPExecutableDirective(OMPMasterDirectiveClass, llvm::omp::OMPD_master,
+                               StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
   explicit OMPMasterDirective()
-      : OMPExecutableDirective(this, OMPMasterDirectiveClass,
-                               llvm::omp::OMPD_master, SourceLocation(),
-                               SourceLocation(), 0, 1) {}
+      : OMPExecutableDirective(OMPMasterDirectiveClass, llvm::omp::OMPD_master,
+                               SourceLocation(), SourceLocation()) {}
 
 public:
   /// Creates directive.
@@ -1676,6 +1629,7 @@ class OMPMasterDirective : public OMPExecutableDirective {
 ///
 class OMPCriticalDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Name of the directive.
   DeclarationNameInfo DirName;
   /// Build directive with the given start and end location.
@@ -1683,24 +1637,19 @@ class OMPCriticalDirective : public OMPExecutableDirective {
   /// \param Name Name of the directive.
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
   OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc,
-                       SourceLocation EndLoc, unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPCriticalDirectiveClass,
-                               llvm::omp::OMPD_critical, StartLoc, EndLoc,
-                               NumClauses, 1),
+                       SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPCriticalDirectiveClass,
+                               llvm::omp::OMPD_critical, StartLoc, EndLoc),
         DirName(Name) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPCriticalDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPCriticalDirectiveClass,
+  explicit OMPCriticalDirective()
+      : OMPExecutableDirective(OMPCriticalDirectiveClass,
                                llvm::omp::OMPD_critical, SourceLocation(),
-                               SourceLocation(), NumClauses, 1),
-        DirName() {}
+                               SourceLocation()) {}
 
   /// Set name of the directive.
   ///
@@ -1751,40 +1700,37 @@ class OMPCriticalDirective : public OMPExecutableDirective {
 ///
 class OMPParallelForDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
-  /// Special reference expression for handling task reduction. Used to store
-  /// the taskgroup descriptor returned by the runtime functions.
-  Expr *TaskRedRef = nullptr;
   /// true if current region has inner cancel directive.
-  bool HasCancel;
+  bool HasCancel = false;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                          unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPParallelForDirectiveClass,
+                          unsigned CollapsedNum)
+      : OMPLoopDirective(OMPParallelForDirectiveClass,
                          llvm::omp::OMPD_parallel_for, StartLoc, EndLoc,
-                         CollapsedNum, NumClauses),
-        HasCancel(false) {}
+                         CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPParallelForDirectiveClass,
+  explicit OMPParallelForDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPParallelForDirectiveClass,
                          llvm::omp::OMPD_parallel_for, SourceLocation(),
-                         SourceLocation(), CollapsedNum, NumClauses),
-        HasCancel(false) {}
+                         SourceLocation(), CollapsedNum) {}
 
   /// Sets special task reduction descriptor.
-  void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
+  void setTaskReductionRefExpr(Expr *E) {
+    Data->getChildren()[numLoopChildren(getCollapsedNumber(),
+                                        llvm::omp::OMPD_parallel_for)] = E;
+  }
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -1822,8 +1768,14 @@ class OMPParallelForDirective : public OMPLoopDirective {
                                               EmptyShell);
 
   /// Returns special task reduction reference expression.
-  Expr *getTaskReductionRefExpr() { return TaskRedRef; }
-  const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
+  Expr *getTaskReductionRefExpr() {
+    return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
+        getCollapsedNumber(), llvm::omp::OMPD_parallel_for)]);
+  }
+  const Expr *getTaskReductionRefExpr() const {
+    return const_cast<OMPParallelForDirective *>(this)
+        ->getTaskReductionRefExpr();
+  }
 
   /// Return true if current directive has inner cancel directive.
   bool hasCancel() const { return HasCancel; }
@@ -1845,29 +1797,27 @@ class OMPParallelForDirective : public OMPLoopDirective {
 ///
 class OMPParallelForSimdDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                              unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass,
+                              unsigned CollapsedNum)
+      : OMPLoopDirective(OMPParallelForSimdDirectiveClass,
                          llvm::omp::OMPD_parallel_for_simd, StartLoc, EndLoc,
-                         CollapsedNum, NumClauses) {}
+                         CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPParallelForSimdDirective(unsigned CollapsedNum,
-                                       unsigned NumClauses)
-      : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass,
+  explicit OMPParallelForSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPParallelForSimdDirectiveClass,
                          llvm::omp::OMPD_parallel_for_simd, SourceLocation(),
-                         SourceLocation(), CollapsedNum, NumClauses) {}
+                         SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -1912,25 +1862,20 @@ class OMPParallelForSimdDirective : public OMPLoopDirective {
 ///
 class OMPParallelMasterDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
-  /// Special reference expression for handling task reduction. Used to store
-  /// the taskgroup descriptor returned by the runtime functions.
-  Expr *TaskRedRef = nullptr;
-
-  OMPParallelMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                             unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPParallelMasterDirectiveClass,
+  OMPParallelMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPParallelMasterDirectiveClass,
                                llvm::omp::OMPD_parallel_master, StartLoc,
-                               EndLoc, NumClauses, 1) {}
+                               EndLoc) {}
 
-  explicit OMPParallelMasterDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPParallelMasterDirectiveClass,
+  explicit OMPParallelMasterDirective()
+      : OMPExecutableDirective(OMPParallelMasterDirectiveClass,
                                llvm::omp::OMPD_parallel_master,
-                               SourceLocation(), SourceLocation(), NumClauses,
-                               1) {}
+                               SourceLocation(), SourceLocation()) {}
 
   /// Sets special task reduction descriptor.
-  void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
+  void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -1957,8 +1902,13 @@ class OMPParallelMasterDirective : public OMPExecutableDirective {
   CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
 
   /// Returns special task reduction reference expression.
-  Expr *getTaskReductionRefExpr() { return TaskRedRef; }
-  const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
+  Expr *getTaskReductionRefExpr() {
+    return cast_or_null<Expr>(Data->getChildren()[0]);
+  }
+  const Expr *getTaskReductionRefExpr() const {
+    return const_cast<OMPParallelMasterDirective *>(this)
+        ->getTaskReductionRefExpr();
+  }
 
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == OMPParallelMasterDirectiveClass;
@@ -1976,39 +1926,30 @@ class OMPParallelMasterDirective : public OMPExecutableDirective {
 ///
 class OMPParallelSectionsDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
-  /// Special reference expression for handling task reduction. Used to store
-  /// the taskgroup descriptor returned by the runtime functions.
-  Expr *TaskRedRef = nullptr;
   /// true if current directive has inner cancel directive.
-  bool HasCancel;
+  bool HasCancel = false;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPParallelSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                               unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass,
+  OMPParallelSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPParallelSectionsDirectiveClass,
                                llvm::omp::OMPD_parallel_sections, StartLoc,
-                               EndLoc, NumClauses, 1),
-        HasCancel(false) {}
+                               EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPParallelSectionsDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass,
+  explicit OMPParallelSectionsDirective()
+      : OMPExecutableDirective(OMPParallelSectionsDirectiveClass,
                                llvm::omp::OMPD_parallel_sections,
-                               SourceLocation(), SourceLocation(), NumClauses,
-                               1),
-        HasCancel(false) {}
+                               SourceLocation(), SourceLocation()) {}
 
   /// Sets special task reduction descriptor.
-  void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
+  void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -2040,8 +1981,13 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective {
   CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
 
   /// Returns special task reduction reference expression.
-  Expr *getTaskReductionRefExpr() { return TaskRedRef; }
-  const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
+  Expr *getTaskReductionRefExpr() {
+    return cast_or_null<Expr>(Data->getChildren()[0]);
+  }
+  const Expr *getTaskReductionRefExpr() const {
+    return const_cast<OMPParallelSectionsDirective *>(this)
+        ->getTaskReductionRefExpr();
+  }
 
   /// Return true if current directive has inner cancel directive.
   bool hasCancel() const { return HasCancel; }
@@ -2061,31 +2007,24 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective {
 ///
 class OMPTaskDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// true if this directive has inner cancel directive.
-  bool HasCancel;
+  bool HasCancel = false;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                   unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTaskDirectiveClass,
-                               llvm::omp::OMPD_task, StartLoc, EndLoc,
-                               NumClauses, 1),
-        HasCancel(false) {}
+  OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPTaskDirectiveClass, llvm::omp::OMPD_task,
+                               StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPTaskDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTaskDirectiveClass,
-                               llvm::omp::OMPD_task, SourceLocation(),
-                               SourceLocation(), NumClauses, 1),
-        HasCancel(false) {}
+  explicit OMPTaskDirective()
+      : OMPExecutableDirective(OMPTaskDirectiveClass, llvm::omp::OMPD_task,
+                               SourceLocation(), SourceLocation()) {}
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -2130,22 +2069,22 @@ class OMPTaskDirective : public OMPExecutableDirective {
 ///
 class OMPTaskyieldDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   ///
   OMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
-      : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass,
-                               llvm::omp::OMPD_taskyield, StartLoc, EndLoc, 0,
-                               0) {}
+      : OMPExecutableDirective(OMPTaskyieldDirectiveClass,
+                               llvm::omp::OMPD_taskyield, StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
   explicit OMPTaskyieldDirective()
-      : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass,
+      : OMPExecutableDirective(OMPTaskyieldDirectiveClass,
                                llvm::omp::OMPD_taskyield, SourceLocation(),
-                               SourceLocation(), 0, 0) {}
+                               SourceLocation()) {}
 
 public:
   /// Creates directive.
@@ -2176,22 +2115,22 @@ class OMPTaskyieldDirective : public OMPExecutableDirective {
 ///
 class OMPBarrierDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   ///
   OMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
-      : OMPExecutableDirective(this, OMPBarrierDirectiveClass,
-                               llvm::omp::OMPD_barrier, StartLoc, EndLoc, 0,
-                               0) {}
+      : OMPExecutableDirective(OMPBarrierDirectiveClass,
+                               llvm::omp::OMPD_barrier, StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
   explicit OMPBarrierDirective()
-      : OMPExecutableDirective(this, OMPBarrierDirectiveClass,
+      : OMPExecutableDirective(OMPBarrierDirectiveClass,
                                llvm::omp::OMPD_barrier, SourceLocation(),
-                               SourceLocation(), 0, 0) {}
+                               SourceLocation()) {}
 
 public:
   /// Creates directive.
@@ -2222,22 +2161,22 @@ class OMPBarrierDirective : public OMPExecutableDirective {
 ///
 class OMPTaskwaitDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   ///
   OMPTaskwaitDirective(SourceLocation StartLoc, SourceLocation EndLoc)
-      : OMPExecutableDirective(this, OMPTaskwaitDirectiveClass,
-                               llvm::omp::OMPD_taskwait, StartLoc, EndLoc, 0,
-                               0) {}
+      : OMPExecutableDirective(OMPTaskwaitDirectiveClass,
+                               llvm::omp::OMPD_taskwait, StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
   explicit OMPTaskwaitDirective()
-      : OMPExecutableDirective(this, OMPTaskwaitDirectiveClass,
+      : OMPExecutableDirective(OMPTaskwaitDirectiveClass,
                                llvm::omp::OMPD_taskwait, SourceLocation(),
-                               SourceLocation(), 0, 0) {}
+                               SourceLocation()) {}
 
 public:
   /// Creates directive.
@@ -2268,30 +2207,25 @@ class OMPTaskwaitDirective : public OMPExecutableDirective {
 ///
 class OMPTaskgroupDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                        unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTaskgroupDirectiveClass,
-                               llvm::omp::OMPD_taskgroup, StartLoc, EndLoc,
-                               NumClauses, 2) {}
+  OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPTaskgroupDirectiveClass,
+                               llvm::omp::OMPD_taskgroup, StartLoc, EndLoc) {}
 
   /// Build an empty directive.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTaskgroupDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTaskgroupDirectiveClass,
+  explicit OMPTaskgroupDirective()
+      : OMPExecutableDirective(OMPTaskgroupDirectiveClass,
                                llvm::omp::OMPD_taskgroup, SourceLocation(),
-                               SourceLocation(), NumClauses, 2) {}
+                               SourceLocation()) {}
 
   /// Sets the task_reduction return variable.
-  void setReductionRef(Expr *RR) {
-    *std::next(child_begin(), 1) = RR;
-  }
+  void setReductionRef(Expr *RR) { Data->getChildren()[0] = RR; }
 
 public:
   /// Creates directive.
@@ -2319,11 +2253,9 @@ class OMPTaskgroupDirective : public OMPExecutableDirective {
 
   /// Returns reference to the task_reduction return variable.
   const Expr *getReductionRef() const {
-    return static_cast<const Expr *>(*std::next(child_begin(), 1));
-  }
-  Expr *getReductionRef() {
-    return static_cast<Expr *>(*std::next(child_begin(), 1));
+    return const_cast<OMPTaskgroupDirective *>(this)->getReductionRef();
   }
+  Expr *getReductionRef() { return cast_or_null<Expr>(Data->getChildren()[0]); }
 
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == OMPTaskgroupDirectiveClass;
@@ -2342,26 +2274,21 @@ class OMPTaskgroupDirective : public OMPExecutableDirective {
 /// FlushClause.
 class OMPFlushDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPFlushDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                    unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPFlushDirectiveClass,
-                               llvm::omp::OMPD_flush, StartLoc, EndLoc,
-                               NumClauses, 0) {}
+  OMPFlushDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPFlushDirectiveClass, llvm::omp::OMPD_flush,
+                               StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPFlushDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPFlushDirectiveClass,
-                               llvm::omp::OMPD_flush, SourceLocation(),
-                               SourceLocation(), NumClauses, 0) {}
+  explicit OMPFlushDirective()
+      : OMPExecutableDirective(OMPFlushDirectiveClass, llvm::omp::OMPD_flush,
+                               SourceLocation(), SourceLocation()) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -2399,27 +2326,22 @@ class OMPFlushDirective : public OMPExecutableDirective {
 /// 'a' with dependence type 'in' and a list with 'x' and 'y' locators.
 class OMPDepobjDirective final : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPDepobjDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                     unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPDepobjDirectiveClass,
-                               llvm::omp::OMPD_depobj, StartLoc, EndLoc,
-                               NumClauses, 0) {}
+  OMPDepobjDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPDepobjDirectiveClass, llvm::omp::OMPD_depobj,
+                               StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPDepobjDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPDepobjDirectiveClass,
-                               llvm::omp::OMPD_depobj, SourceLocation(),
-                               SourceLocation(), NumClauses, 0) {}
+  explicit OMPDepobjDirective()
+      : OMPExecutableDirective(OMPDepobjDirectiveClass, llvm::omp::OMPD_depobj,
+                               SourceLocation(), SourceLocation()) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -2456,26 +2378,22 @@ class OMPDepobjDirective final : public OMPExecutableDirective {
 ///
 class OMPOrderedDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                      unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPOrderedDirectiveClass,
-                               llvm::omp::OMPD_ordered, StartLoc, EndLoc,
-                               NumClauses, 1) {}
+  OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPOrderedDirectiveClass,
+                               llvm::omp::OMPD_ordered, StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPOrderedDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPOrderedDirectiveClass,
+  explicit OMPOrderedDirective()
+      : OMPExecutableDirective(OMPOrderedDirectiveClass,
                                llvm::omp::OMPD_ordered, SourceLocation(),
-                               SourceLocation(), NumClauses, 1) {}
+                               SourceLocation()) {}
 
 public:
   /// Creates directive.
@@ -2494,9 +2412,11 @@ class OMPOrderedDirective : public OMPExecutableDirective {
   ///
   /// \param C AST context.
   /// \param NumClauses Number of clauses.
+  /// \param IsStandalone true, if the the standalone directive is created.
   ///
   static OMPOrderedDirective *CreateEmpty(const ASTContext &C,
-                                          unsigned NumClauses, EmptyShell);
+                                          unsigned NumClauses,
+                                          bool IsStandalone, EmptyShell);
 
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == OMPOrderedDirectiveClass;
@@ -2512,6 +2432,7 @@ class OMPOrderedDirective : public OMPExecutableDirective {
 ///
 class OMPAtomicDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Used for 'atomic update' or 'atomic capture' constructs. They may
   /// have atomic expressions of forms
   /// \code
@@ -2521,7 +2442,7 @@ class OMPAtomicDirective : public OMPExecutableDirective {
   /// This field is true for the first form of the expression and false for the
   /// second. Required for correct codegen of non-associative operations (like
   /// << or >>).
-  bool IsXLHSInRHSPart;
+  bool IsXLHSInRHSPart = false;
   /// Used for 'atomic update' or 'atomic capture' constructs. They may
   /// have atomic expressions of forms
   /// \code
@@ -2530,41 +2451,33 @@ class OMPAtomicDirective : public OMPExecutableDirective {
   /// \endcode
   /// This field is true for the first(postfix) form of the expression and false
   /// otherwise.
-  bool IsPostfixUpdate;
+  bool IsPostfixUpdate = false;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                     unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPAtomicDirectiveClass,
-                               llvm::omp::OMPD_atomic, StartLoc, EndLoc,
-                               NumClauses, 5),
-        IsXLHSInRHSPart(false), IsPostfixUpdate(false) {}
+  OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic,
+                               StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPAtomicDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPAtomicDirectiveClass,
-                               llvm::omp::OMPD_atomic, SourceLocation(),
-                               SourceLocation(), NumClauses, 5),
-        IsXLHSInRHSPart(false), IsPostfixUpdate(false) {}
+  explicit OMPAtomicDirective()
+      : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic,
+                               SourceLocation(), SourceLocation()) {}
 
   /// Set 'x' part of the associated expression/statement.
-  void setX(Expr *X) { *std::next(child_begin()) = X; }
+  void setX(Expr *X) { Data->getChildren()[0] = X; }
   /// Set helper expression of the form
   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
-  void setUpdateExpr(Expr *UE) { *std::next(child_begin(), 2) = UE; }
+  void setUpdateExpr(Expr *UE) { Data->getChildren()[1] = UE; }
   /// Set 'v' part of the associated expression/statement.
-  void setV(Expr *V) { *std::next(child_begin(), 3) = V; }
+  void setV(Expr *V) { Data->getChildren()[2] = V; }
   /// Set 'expr' part of the associated expression/statement.
-  void setExpr(Expr *E) { *std::next(child_begin(), 4) = E; }
+  void setExpr(Expr *E) { Data->getChildren()[3] = E; }
 
 public:
   /// Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
@@ -2601,18 +2514,16 @@ class OMPAtomicDirective : public OMPExecutableDirective {
                                          unsigned NumClauses, EmptyShell);
 
   /// Get 'x' part of the associated expression/statement.
-  Expr *getX() { return cast_or_null<Expr>(*std::next(child_begin())); }
+  Expr *getX() { return cast_or_null<Expr>(Data->getChildren()[0]); }
   const Expr *getX() const {
-    return cast_or_null<Expr>(*std::next(child_begin()));
+    return cast_or_null<Expr>(Data->getChildren()[0]);
   }
   /// Get helper expression of the form
   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
-  Expr *getUpdateExpr() {
-    return cast_or_null<Expr>(*std::next(child_begin(), 2));
-  }
+  Expr *getUpdateExpr() { return cast_or_null<Expr>(Data->getChildren()[1]); }
   const Expr *getUpdateExpr() const {
-    return cast_or_null<Expr>(*std::next(child_begin(), 2));
+    return cast_or_null<Expr>(Data->getChildren()[1]);
   }
   /// Return true if helper update expression has form
   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form
@@ -2622,14 +2533,14 @@ class OMPAtomicDirective : public OMPExecutableDirective {
   /// 'x', false if 'v' must be updated to the new value of 'x'.
   bool isPostfixUpdate() const { return IsPostfixUpdate; }
   /// Get 'v' part of the associated expression/statement.
-  Expr *getV() { return cast_or_null<Expr>(*std::next(child_begin(), 3)); }
+  Expr *getV() { return cast_or_null<Expr>(Data->getChildren()[2]); }
   const Expr *getV() const {
-    return cast_or_null<Expr>(*std::next(child_begin(), 3));
+    return cast_or_null<Expr>(Data->getChildren()[2]);
   }
   /// Get 'expr' part of the associated expression/statement.
-  Expr *getExpr() { return cast_or_null<Expr>(*std::next(child_begin(), 4)); }
+  Expr *getExpr() { return cast_or_null<Expr>(Data->getChildren()[3]); }
   const Expr *getExpr() const {
-    return cast_or_null<Expr>(*std::next(child_begin(), 4));
+    return cast_or_null<Expr>(Data->getChildren()[3]);
   }
 
   static bool classof(const Stmt *T) {
@@ -2647,26 +2558,21 @@ class OMPAtomicDirective : public OMPExecutableDirective {
 ///
 class OMPTargetDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                     unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetDirectiveClass,
-                               llvm::omp::OMPD_target, StartLoc, EndLoc,
-                               NumClauses, 1) {}
+  OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPTargetDirectiveClass, llvm::omp::OMPD_target,
+                               StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPTargetDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetDirectiveClass,
-                               llvm::omp::OMPD_target, SourceLocation(),
-                               SourceLocation(), NumClauses, 1) {}
+  explicit OMPTargetDirective()
+      : OMPExecutableDirective(OMPTargetDirectiveClass, llvm::omp::OMPD_target,
+                               SourceLocation(), SourceLocation()) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -2706,26 +2612,22 @@ class OMPTargetDirective : public OMPExecutableDirective {
 ///
 class OMPTargetDataDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending Location of the directive.
-  /// \param NumClauses The number of clauses.
   ///
-  OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                         unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetDataDirectiveClass,
-                               llvm::omp::OMPD_target_data, StartLoc, EndLoc,
-                               NumClauses, 1) {}
+  OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPTargetDataDirectiveClass,
+                               llvm::omp::OMPD_target_data, StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPTargetDataDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetDataDirectiveClass,
+  explicit OMPTargetDataDirective()
+      : OMPExecutableDirective(OMPTargetDataDirectiveClass,
                                llvm::omp::OMPD_target_data, SourceLocation(),
-                               SourceLocation(), NumClauses, 1) {}
+                               SourceLocation()) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -2764,27 +2666,23 @@ class OMPTargetDataDirective : public OMPExecutableDirective {
 ///
 class OMPTargetEnterDataDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending Location of the directive.
-  /// \param NumClauses The number of clauses.
   ///
-  OMPTargetEnterDataDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                              unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetEnterDataDirectiveClass,
+  OMPTargetEnterDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPTargetEnterDataDirectiveClass,
                                llvm::omp::OMPD_target_enter_data, StartLoc,
-                               EndLoc, NumClauses, /*NumChildren=*/1) {}
+                               EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPTargetEnterDataDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetEnterDataDirectiveClass,
+  explicit OMPTargetEnterDataDirective()
+      : OMPExecutableDirective(OMPTargetEnterDataDirectiveClass,
                                llvm::omp::OMPD_target_enter_data,
-                               SourceLocation(), SourceLocation(), NumClauses,
-                               /*NumChildren=*/1) {}
+                               SourceLocation(), SourceLocation()) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -2823,27 +2721,23 @@ class OMPTargetEnterDataDirective : public OMPExecutableDirective {
 ///
 class OMPTargetExitDataDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending Location of the directive.
-  /// \param NumClauses The number of clauses.
   ///
-  OMPTargetExitDataDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                             unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetExitDataDirectiveClass,
+  OMPTargetExitDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPTargetExitDataDirectiveClass,
                                llvm::omp::OMPD_target_exit_data, StartLoc,
-                               EndLoc, NumClauses, /*NumChildren=*/1) {}
+                               EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPTargetExitDataDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetExitDataDirectiveClass,
+  explicit OMPTargetExitDataDirective()
+      : OMPExecutableDirective(OMPTargetExitDataDirectiveClass,
                                llvm::omp::OMPD_target_exit_data,
-                               SourceLocation(), SourceLocation(), NumClauses,
-                               /*NumChildren=*/1) {}
+                               SourceLocation(), SourceLocation()) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -2881,9 +2775,7 @@ class OMPTargetExitDataDirective : public OMPExecutableDirective {
 ///
 class OMPTargetParallelDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
-  /// Special reference expression for handling task reduction. Used to store
-  /// the taskgroup descriptor returned by the runtime functions.
-  Expr *TaskRedRef = nullptr;
+  friend class OMPExecutableDirective;
   /// true if the construct has inner cancel directive.
   bool HasCancel = false;
 
@@ -2891,26 +2783,21 @@ class OMPTargetParallelDirective : public OMPExecutableDirective {
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPTargetParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                             unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetParallelDirectiveClass,
+  OMPTargetParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPTargetParallelDirectiveClass,
                                llvm::omp::OMPD_target_parallel, StartLoc,
-                               EndLoc, NumClauses, /*NumChildren=*/1) {}
+                               EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPTargetParallelDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetParallelDirectiveClass,
+  explicit OMPTargetParallelDirective()
+      : OMPExecutableDirective(OMPTargetParallelDirectiveClass,
                                llvm::omp::OMPD_target_parallel,
-                               SourceLocation(), SourceLocation(), NumClauses,
-                               /*NumChildren=*/1) {}
+                               SourceLocation(), SourceLocation()) {}
 
   /// Sets special task reduction descriptor.
-  void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
+  void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
 
@@ -2941,8 +2828,13 @@ class OMPTargetParallelDirective : public OMPExecutableDirective {
   CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
 
   /// Returns special task reduction reference expression.
-  Expr *getTaskReductionRefExpr() { return TaskRedRef; }
-  const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
+  Expr *getTaskReductionRefExpr() {
+    return cast_or_null<Expr>(Data->getChildren()[0]);
+  }
+  const Expr *getTaskReductionRefExpr() const {
+    return const_cast<OMPTargetParallelDirective *>(this)
+        ->getTaskReductionRefExpr();
+  }
 
   /// Return true if current directive has inner cancel directive.
   bool hasCancel() const { return HasCancel; }
@@ -2963,41 +2855,37 @@ class OMPTargetParallelDirective : public OMPExecutableDirective {
 ///
 class OMPTargetParallelForDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
-  /// Special reference expression for handling task reduction. Used to store
-  /// the taskgroup descriptor returned by the runtime functions.
-  Expr *TaskRedRef = nullptr;
   /// true if current region has inner cancel directive.
-  bool HasCancel;
+  bool HasCancel = false;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTargetParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                                unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTargetParallelForDirectiveClass,
+                                unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTargetParallelForDirectiveClass,
                          llvm::omp::OMPD_target_parallel_for, StartLoc, EndLoc,
-                         CollapsedNum, NumClauses),
-        HasCancel(false) {}
+                         CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTargetParallelForDirective(unsigned CollapsedNum,
-                                         unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTargetParallelForDirectiveClass,
+  explicit OMPTargetParallelForDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTargetParallelForDirectiveClass,
                          llvm::omp::OMPD_target_parallel_for, SourceLocation(),
-                         SourceLocation(), CollapsedNum, NumClauses),
-        HasCancel(false) {}
+                         SourceLocation(), CollapsedNum) {}
 
   /// Sets special task reduction descriptor.
-  void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
+  void setTaskReductionRefExpr(Expr *E) {
+    Data->getChildren()[numLoopChildren(
+        getCollapsedNumber(), llvm::omp::OMPD_target_parallel_for)] = E;
+  }
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -3035,8 +2923,14 @@ class OMPTargetParallelForDirective : public OMPLoopDirective {
                                                     EmptyShell);
 
   /// Returns special task reduction reference expression.
-  Expr *getTaskReductionRefExpr() { return TaskRedRef; }
-  const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
+  Expr *getTaskReductionRefExpr() {
+    return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
+        getCollapsedNumber(), llvm::omp::OMPD_target_parallel_for)]);
+  }
+  const Expr *getTaskReductionRefExpr() const {
+    return const_cast<OMPTargetParallelForDirective *>(this)
+        ->getTaskReductionRefExpr();
+  }
 
   /// Return true if current directive has inner cancel directive.
   bool hasCancel() const { return HasCancel; }
@@ -3056,26 +2950,21 @@ class OMPTargetParallelForDirective : public OMPLoopDirective {
 ///
 class OMPTeamsDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                    unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTeamsDirectiveClass,
-                               llvm::omp::OMPD_teams, StartLoc, EndLoc,
-                               NumClauses, 1) {}
+  OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPTeamsDirectiveClass, llvm::omp::OMPD_teams,
+                               StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPTeamsDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTeamsDirectiveClass,
-                               llvm::omp::OMPD_teams, SourceLocation(),
-                               SourceLocation(), NumClauses, 1) {}
+  explicit OMPTeamsDirective()
+      : OMPExecutableDirective(OMPTeamsDirectiveClass, llvm::omp::OMPD_teams,
+                               SourceLocation(), SourceLocation()) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -3114,25 +3003,28 @@ class OMPTeamsDirective : public OMPExecutableDirective {
 /// In this example a cancellation point is created for innermost 'for' region.
 class OMPCancellationPointDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
-  OpenMPDirectiveKind CancelRegion;
+  friend class OMPExecutableDirective;
+  OpenMPDirectiveKind CancelRegion = llvm::omp::OMPD_unknown;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
+  /// \param Data Data storage, containing info about associated clauses,
+  /// statements and child expressions.
   ///
   OMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc)
-      : OMPExecutableDirective(this, OMPCancellationPointDirectiveClass,
+      : OMPExecutableDirective(OMPCancellationPointDirectiveClass,
                                llvm::omp::OMPD_cancellation_point, StartLoc,
-                               EndLoc, 0, 0),
-        CancelRegion(llvm::omp::OMPD_unknown) {}
+                               EndLoc) {}
 
   /// Build an empty directive.
+  /// \param Data Data storage, containing info about associated clauses,
+  /// statements and child expressions.
   ///
   explicit OMPCancellationPointDirective()
-      : OMPExecutableDirective(this, OMPCancellationPointDirectiveClass,
+      : OMPExecutableDirective(OMPCancellationPointDirectiveClass,
                                llvm::omp::OMPD_cancellation_point,
-                               SourceLocation(), SourceLocation(), 0, 0),
-        CancelRegion(llvm::omp::OMPD_unknown) {}
+                               SourceLocation(), SourceLocation()) {}
 
   /// Set cancel region for current cancellation point.
   /// \param CR Cancellation region.
@@ -3173,28 +3065,22 @@ class OMPCancellationPointDirective : public OMPExecutableDirective {
 /// In this example a cancel is created for innermost 'for' region.
 class OMPCancelDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
-  OpenMPDirectiveKind CancelRegion;
+  friend class OMPExecutableDirective;
+  OpenMPDirectiveKind CancelRegion = llvm::omp::OMPD_unknown;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                     unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPCancelDirectiveClass,
-                               llvm::omp::OMPD_cancel, StartLoc, EndLoc,
-                               NumClauses, 0),
-        CancelRegion(llvm::omp::OMPD_unknown) {}
+  OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPCancelDirectiveClass, llvm::omp::OMPD_cancel,
+                               StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  explicit OMPCancelDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPCancelDirectiveClass,
-                               llvm::omp::OMPD_cancel, SourceLocation(),
-                               SourceLocation(), NumClauses, 0),
-        CancelRegion(llvm::omp::OMPD_unknown) {}
+  explicit OMPCancelDirective()
+      : OMPExecutableDirective(OMPCancelDirectiveClass, llvm::omp::OMPD_cancel,
+                               SourceLocation(), SourceLocation()) {}
 
   /// Set cancel region for current cancellation point.
   /// \param CR Cancellation region.
@@ -3239,33 +3125,28 @@ class OMPCancelDirective : public OMPExecutableDirective {
 ///
 class OMPTaskLoopDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// true if the construct has inner cancel directive.
-  bool HasCancel;
+  bool HasCancel = false;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                       unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTaskLoopDirectiveClass,
-                         llvm::omp::OMPD_taskloop, StartLoc, EndLoc,
-                         CollapsedNum, NumClauses),
-        HasCancel(false) {}
+                       unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTaskLoopDirectiveClass, llvm::omp::OMPD_taskloop,
+                         StartLoc, EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTaskLoopDirective(unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTaskLoopDirectiveClass,
-                         llvm::omp::OMPD_taskloop, SourceLocation(),
-                         SourceLocation(), CollapsedNum, NumClauses),
-        HasCancel(false) {}
+  explicit OMPTaskLoopDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTaskLoopDirectiveClass, llvm::omp::OMPD_taskloop,
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -3317,28 +3198,27 @@ class OMPTaskLoopDirective : public OMPLoopDirective {
 ///
 class OMPTaskLoopSimdDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                           unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTaskLoopSimdDirectiveClass,
+                           unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTaskLoopSimdDirectiveClass,
                          llvm::omp::OMPD_taskloop_simd, StartLoc, EndLoc,
-                         CollapsedNum, NumClauses) {}
+                         CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTaskLoopSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTaskLoopSimdDirectiveClass,
+  explicit OMPTaskLoopSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTaskLoopSimdDirectiveClass,
                          llvm::omp::OMPD_taskloop_simd, SourceLocation(),
-                         SourceLocation(), CollapsedNum, NumClauses) {}
+                         SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -3384,34 +3264,30 @@ class OMPTaskLoopSimdDirective : public OMPLoopDirective {
 ///
 class OMPMasterTaskLoopDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// true if the construct has inner cancel directive.
-  bool HasCancel;
+  bool HasCancel = false;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPMasterTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                             unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPMasterTaskLoopDirectiveClass,
+                             unsigned CollapsedNum)
+      : OMPLoopDirective(OMPMasterTaskLoopDirectiveClass,
                          llvm::omp::OMPD_master_taskloop, StartLoc, EndLoc,
-                         CollapsedNum, NumClauses),
-        HasCancel(false) {}
+                         CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPMasterTaskLoopDirective(unsigned CollapsedNum,
-                                      unsigned NumClauses)
-      : OMPLoopDirective(this, OMPMasterTaskLoopDirectiveClass,
+  explicit OMPMasterTaskLoopDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPMasterTaskLoopDirectiveClass,
                          llvm::omp::OMPD_master_taskloop, SourceLocation(),
-                         SourceLocation(), CollapsedNum, NumClauses),
-        HasCancel(false) {}
+                         SourceLocation(), CollapsedNum) {}
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -3464,29 +3340,27 @@ class OMPMasterTaskLoopDirective : public OMPLoopDirective {
 ///
 class OMPMasterTaskLoopSimdDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPMasterTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                                 unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPMasterTaskLoopSimdDirectiveClass,
+                                 unsigned CollapsedNum)
+      : OMPLoopDirective(OMPMasterTaskLoopSimdDirectiveClass,
                          llvm::omp::OMPD_master_taskloop_simd, StartLoc, EndLoc,
-                         CollapsedNum, NumClauses) {}
+                         CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPMasterTaskLoopSimdDirective(unsigned CollapsedNum,
-                                          unsigned NumClauses)
-      : OMPLoopDirective(this, OMPMasterTaskLoopSimdDirectiveClass,
+  explicit OMPMasterTaskLoopSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPMasterTaskLoopSimdDirectiveClass,
                          llvm::omp::OMPD_master_taskloop_simd, SourceLocation(),
-                         SourceLocation(), CollapsedNum, NumClauses) {}
+                         SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \p Clauses.
@@ -3532,36 +3406,31 @@ class OMPMasterTaskLoopSimdDirective : public OMPLoopDirective {
 ///
 class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// true if the construct has inner cancel directive.
-  bool HasCancel;
+  bool HasCancel = false;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPParallelMasterTaskLoopDirective(SourceLocation StartLoc,
                                      SourceLocation EndLoc,
-                                     unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPParallelMasterTaskLoopDirectiveClass,
+                                     unsigned CollapsedNum)
+      : OMPLoopDirective(OMPParallelMasterTaskLoopDirectiveClass,
                          llvm::omp::OMPD_parallel_master_taskloop, StartLoc,
-                         EndLoc, CollapsedNum, NumClauses),
-        HasCancel(false) {}
+                         EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPParallelMasterTaskLoopDirective(unsigned CollapsedNum,
-                                              unsigned NumClauses)
-      : OMPLoopDirective(this, OMPParallelMasterTaskLoopDirectiveClass,
+  explicit OMPParallelMasterTaskLoopDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPParallelMasterTaskLoopDirectiveClass,
                          llvm::omp::OMPD_parallel_master_taskloop,
-                         SourceLocation(), SourceLocation(), CollapsedNum,
-                         NumClauses),
-        HasCancel(false) {}
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -3615,32 +3484,28 @@ class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective {
 ///
 class OMPParallelMasterTaskLoopSimdDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPParallelMasterTaskLoopSimdDirective(SourceLocation StartLoc,
                                          SourceLocation EndLoc,
-                                         unsigned CollapsedNum,
-                                         unsigned NumClauses)
-      : OMPLoopDirective(this, OMPParallelMasterTaskLoopSimdDirectiveClass,
+                                         unsigned CollapsedNum)
+      : OMPLoopDirective(OMPParallelMasterTaskLoopSimdDirectiveClass,
                          llvm::omp::OMPD_parallel_master_taskloop_simd,
-                         StartLoc, EndLoc, CollapsedNum, NumClauses) {}
+                         StartLoc, EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPParallelMasterTaskLoopSimdDirective(unsigned CollapsedNum,
-                                                  unsigned NumClauses)
-      : OMPLoopDirective(this, OMPParallelMasterTaskLoopSimdDirectiveClass,
+  explicit OMPParallelMasterTaskLoopSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPParallelMasterTaskLoopSimdDirectiveClass,
                          llvm::omp::OMPD_parallel_master_taskloop_simd,
-                         SourceLocation(), SourceLocation(), CollapsedNum,
-                         NumClauses) {}
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \p Clauses.
@@ -3684,29 +3549,28 @@ class OMPParallelMasterTaskLoopSimdDirective : public OMPLoopDirective {
 ///
 class OMPDistributeDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                         unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPDistributeDirectiveClass,
+                         unsigned CollapsedNum)
+      : OMPLoopDirective(OMPDistributeDirectiveClass,
                          llvm::omp::OMPD_distribute, StartLoc, EndLoc,
-                         CollapsedNum, NumClauses) {}
+                         CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPDistributeDirective(unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPDistributeDirectiveClass,
+  explicit OMPDistributeDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPDistributeDirectiveClass,
                          llvm::omp::OMPD_distribute, SourceLocation(),
-                         SourceLocation(), CollapsedNum, NumClauses) {}
+                         SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -3751,26 +3615,23 @@ class OMPDistributeDirective : public OMPLoopDirective {
 ///
 class OMPTargetUpdateDirective : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending Location of the directive.
-  /// \param NumClauses The number of clauses.
   ///
-  OMPTargetUpdateDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                           unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetUpdateDirectiveClass,
-                               llvm::omp::OMPD_target_update, StartLoc, EndLoc,
-                               NumClauses, 1) {}
+  OMPTargetUpdateDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPTargetUpdateDirectiveClass,
+                               llvm::omp::OMPD_target_update, StartLoc,
+                               EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPTargetUpdateDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetUpdateDirectiveClass,
+  explicit OMPTargetUpdateDirective()
+      : OMPExecutableDirective(OMPTargetUpdateDirectiveClass,
                                llvm::omp::OMPD_target_update, SourceLocation(),
-                               SourceLocation(), NumClauses, 1) {}
+                               SourceLocation()) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -3810,9 +3671,7 @@ class OMPTargetUpdateDirective : public OMPExecutableDirective {
 ///
 class OMPDistributeParallelForDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
-  /// Special reference expression for handling task reduction. Used to store
-  /// the taskgroup descriptor returned by the runtime functions.
-  Expr *TaskRedRef = nullptr;
+  friend class OMPExecutableDirective;
   /// true if the construct has inner cancel directive.
   bool HasCancel = false;
 
@@ -3821,31 +3680,28 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective {
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPDistributeParallelForDirective(SourceLocation StartLoc,
                                     SourceLocation EndLoc,
-                                    unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPDistributeParallelForDirectiveClass,
+                                    unsigned CollapsedNum)
+      : OMPLoopDirective(OMPDistributeParallelForDirectiveClass,
                          llvm::omp::OMPD_distribute_parallel_for, StartLoc,
-                         EndLoc, CollapsedNum, NumClauses),
-        HasCancel(false) {}
+                         EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPDistributeParallelForDirective(unsigned CollapsedNum,
-                                             unsigned NumClauses)
-      : OMPLoopDirective(this, OMPDistributeParallelForDirectiveClass,
+  explicit OMPDistributeParallelForDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPDistributeParallelForDirectiveClass,
                          llvm::omp::OMPD_distribute_parallel_for,
-                         SourceLocation(), SourceLocation(), CollapsedNum,
-                         NumClauses),
-        HasCancel(false) {}
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
   /// Sets special task reduction descriptor.
-  void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
+  void setTaskReductionRefExpr(Expr *E) {
+    Data->getChildren()[numLoopChildren(
+        getCollapsedNumber(), llvm::omp::OMPD_distribute_parallel_for)] = E;
+  }
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -3883,8 +3739,14 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective {
                                                         EmptyShell);
 
   /// Returns special task reduction reference expression.
-  Expr *getTaskReductionRefExpr() { return TaskRedRef; }
-  const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
+  Expr *getTaskReductionRefExpr() {
+    return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
+        getCollapsedNumber(), llvm::omp::OMPD_distribute_parallel_for)]);
+  }
+  const Expr *getTaskReductionRefExpr() const {
+    return const_cast<OMPDistributeParallelForDirective *>(this)
+        ->getTaskReductionRefExpr();
+  }
 
   /// Return true if current directive has inner cancel directive.
   bool hasCancel() const { return HasCancel; }
@@ -3905,33 +3767,29 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective {
 ///
 class OMPDistributeParallelForSimdDirective final : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPDistributeParallelForSimdDirective(SourceLocation StartLoc,
                                         SourceLocation EndLoc,
-                                        unsigned CollapsedNum,
-                                        unsigned NumClauses)
-      : OMPLoopDirective(this, OMPDistributeParallelForSimdDirectiveClass,
+                                        unsigned CollapsedNum)
+      : OMPLoopDirective(OMPDistributeParallelForSimdDirectiveClass,
                          llvm::omp::OMPD_distribute_parallel_for_simd, StartLoc,
-                         EndLoc, CollapsedNum, NumClauses) {}
+                         EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPDistributeParallelForSimdDirective(unsigned CollapsedNum,
-                                                 unsigned NumClauses)
-      : OMPLoopDirective(this, OMPDistributeParallelForSimdDirectiveClass,
+  explicit OMPDistributeParallelForSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPDistributeParallelForSimdDirectiveClass,
                          llvm::omp::OMPD_distribute_parallel_for_simd,
-                         SourceLocation(), SourceLocation(), CollapsedNum,
-                         NumClauses) {}
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -3974,30 +3832,28 @@ class OMPDistributeParallelForSimdDirective final : public OMPLoopDirective {
 ///
 class OMPDistributeSimdDirective final : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPDistributeSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                             unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPDistributeSimdDirectiveClass,
+                             unsigned CollapsedNum)
+      : OMPLoopDirective(OMPDistributeSimdDirectiveClass,
                          llvm::omp::OMPD_distribute_simd, StartLoc, EndLoc,
-                         CollapsedNum, NumClauses) {}
+                         CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPDistributeSimdDirective(unsigned CollapsedNum,
-                                      unsigned NumClauses)
-      : OMPLoopDirective(this, OMPDistributeSimdDirectiveClass,
+  explicit OMPDistributeSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPDistributeSimdDirectiveClass,
                          llvm::omp::OMPD_distribute_simd, SourceLocation(),
-                         SourceLocation(), CollapsedNum, NumClauses) {}
+                         SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -4042,32 +3898,29 @@ class OMPDistributeSimdDirective final : public OMPLoopDirective {
 ///
 class OMPTargetParallelForSimdDirective final : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTargetParallelForSimdDirective(SourceLocation StartLoc,
                                     SourceLocation EndLoc,
-                                    unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTargetParallelForSimdDirectiveClass,
+                                    unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTargetParallelForSimdDirectiveClass,
                          llvm::omp::OMPD_target_parallel_for_simd, StartLoc,
-                         EndLoc, CollapsedNum, NumClauses) {}
+                         EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTargetParallelForSimdDirective(unsigned CollapsedNum,
-                                             unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTargetParallelForSimdDirectiveClass,
+  explicit OMPTargetParallelForSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTargetParallelForSimdDirectiveClass,
                          llvm::omp::OMPD_target_parallel_for_simd,
-                         SourceLocation(), SourceLocation(), CollapsedNum,
-                         NumClauses) {}
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -4112,29 +3965,28 @@ class OMPTargetParallelForSimdDirective final : public OMPLoopDirective {
 ///
 class OMPTargetSimdDirective final : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTargetSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                         unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTargetSimdDirectiveClass,
+                         unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTargetSimdDirectiveClass,
                          llvm::omp::OMPD_target_simd, StartLoc, EndLoc,
-                         CollapsedNum, NumClauses) {}
+                         CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTargetSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTargetSimdDirectiveClass,
+  explicit OMPTargetSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTargetSimdDirectiveClass,
                          llvm::omp::OMPD_target_simd, SourceLocation(),
-                         SourceLocation(), CollapsedNum, NumClauses) {}
+                         SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -4178,30 +4030,28 @@ class OMPTargetSimdDirective final : public OMPLoopDirective {
 ///
 class OMPTeamsDistributeDirective final : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTeamsDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                              unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTeamsDistributeDirectiveClass,
+                              unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTeamsDistributeDirectiveClass,
                          llvm::omp::OMPD_teams_distribute, StartLoc, EndLoc,
-                         CollapsedNum, NumClauses) {}
+                         CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTeamsDistributeDirective(unsigned CollapsedNum,
-                                       unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTeamsDistributeDirectiveClass,
+  explicit OMPTeamsDistributeDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTeamsDistributeDirectiveClass,
                          llvm::omp::OMPD_teams_distribute, SourceLocation(),
-                         SourceLocation(), CollapsedNum, NumClauses) {}
+                         SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -4246,32 +4096,28 @@ class OMPTeamsDistributeDirective final : public OMPLoopDirective {
 ///
 class OMPTeamsDistributeSimdDirective final : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTeamsDistributeSimdDirective(SourceLocation StartLoc,
-                                  SourceLocation EndLoc, unsigned CollapsedNum,
-                                  unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTeamsDistributeSimdDirectiveClass,
+                                  SourceLocation EndLoc, unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTeamsDistributeSimdDirectiveClass,
                          llvm::omp::OMPD_teams_distribute_simd, StartLoc,
-                         EndLoc, CollapsedNum, NumClauses) {}
+                         EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTeamsDistributeSimdDirective(unsigned CollapsedNum,
-                                           unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTeamsDistributeSimdDirectiveClass,
+  explicit OMPTeamsDistributeSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTeamsDistributeSimdDirectiveClass,
                          llvm::omp::OMPD_teams_distribute_simd,
-                         SourceLocation(), SourceLocation(), CollapsedNum,
-                         NumClauses) {}
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -4318,33 +4164,29 @@ class OMPTeamsDistributeSimdDirective final : public OMPLoopDirective {
 class OMPTeamsDistributeParallelForSimdDirective final
     : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,
                                              SourceLocation EndLoc,
-                                             unsigned CollapsedNum,
-                                             unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTeamsDistributeParallelForSimdDirectiveClass,
+                                             unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTeamsDistributeParallelForSimdDirectiveClass,
                          llvm::omp::OMPD_teams_distribute_parallel_for_simd,
-                         StartLoc, EndLoc, CollapsedNum, NumClauses) {}
+                         StartLoc, EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTeamsDistributeParallelForSimdDirective(unsigned CollapsedNum,
-                                                      unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTeamsDistributeParallelForSimdDirectiveClass,
+  explicit OMPTeamsDistributeParallelForSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTeamsDistributeParallelForSimdDirectiveClass,
                          llvm::omp::OMPD_teams_distribute_parallel_for_simd,
-                         SourceLocation(), SourceLocation(), CollapsedNum,
-                         NumClauses) {}
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -4388,9 +4230,7 @@ class OMPTeamsDistributeParallelForSimdDirective final
 ///
 class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
   friend class ASTStmtReader;
-  /// Special reference expression for handling task reduction. Used to store
-  /// the taskgroup descriptor returned by the runtime functions.
-  Expr *TaskRedRef = nullptr;
+  friend class OMPExecutableDirective;
   /// true if the construct has inner cancel directive.
   bool HasCancel = false;
 
@@ -4399,32 +4239,29 @@ class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTeamsDistributeParallelForDirective(SourceLocation StartLoc,
                                          SourceLocation EndLoc,
-                                         unsigned CollapsedNum,
-                                         unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTeamsDistributeParallelForDirectiveClass,
+                                         unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTeamsDistributeParallelForDirectiveClass,
                          llvm::omp::OMPD_teams_distribute_parallel_for,
-                         StartLoc, EndLoc, CollapsedNum, NumClauses),
-        HasCancel(false) {}
+                         StartLoc, EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTeamsDistributeParallelForDirective(unsigned CollapsedNum,
-                                                  unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTeamsDistributeParallelForDirectiveClass,
+  explicit OMPTeamsDistributeParallelForDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTeamsDistributeParallelForDirectiveClass,
                          llvm::omp::OMPD_teams_distribute_parallel_for,
-                         SourceLocation(), SourceLocation(), CollapsedNum,
-                         NumClauses),
-        HasCancel(false) {}
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
   /// Sets special task reduction descriptor.
-  void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
+  void setTaskReductionRefExpr(Expr *E) {
+    Data->getChildren()[numLoopChildren(
+        getCollapsedNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)] =
+        E;
+  }
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -4460,8 +4297,14 @@ class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
               EmptyShell);
 
   /// Returns special task reduction reference expression.
-  Expr *getTaskReductionRefExpr() { return TaskRedRef; }
-  const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
+  Expr *getTaskReductionRefExpr() {
+    return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
+        getCollapsedNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)]);
+  }
+  const Expr *getTaskReductionRefExpr() const {
+    return const_cast<OMPTeamsDistributeParallelForDirective *>(this)
+        ->getTaskReductionRefExpr();
+  }
 
   /// Return true if current directive has inner cancel directive.
   bool hasCancel() const { return HasCancel; }
@@ -4481,26 +4324,23 @@ class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
 ///
 class OMPTargetTeamsDirective final : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPTargetTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                          unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetTeamsDirectiveClass,
-                               llvm::omp::OMPD_target_teams, StartLoc, EndLoc,
-                               NumClauses, 1) {}
+  OMPTargetTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPTargetTeamsDirectiveClass,
+                               llvm::omp::OMPD_target_teams, StartLoc, EndLoc) {
+  }
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPTargetTeamsDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPTargetTeamsDirectiveClass,
+  explicit OMPTargetTeamsDirective()
+      : OMPExecutableDirective(OMPTargetTeamsDirectiveClass,
                                llvm::omp::OMPD_target_teams, SourceLocation(),
-                               SourceLocation(), NumClauses, 1) {}
+                               SourceLocation()) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -4540,32 +4380,29 @@ class OMPTargetTeamsDirective final : public OMPExecutableDirective {
 ///
 class OMPTargetTeamsDistributeDirective final : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTargetTeamsDistributeDirective(SourceLocation StartLoc,
                                     SourceLocation EndLoc,
-                                    unsigned CollapsedNum, unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTargetTeamsDistributeDirectiveClass,
+                                    unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTargetTeamsDistributeDirectiveClass,
                          llvm::omp::OMPD_target_teams_distribute, StartLoc,
-                         EndLoc, CollapsedNum, NumClauses) {}
+                         EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTargetTeamsDistributeDirective(unsigned CollapsedNum,
-                                             unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTargetTeamsDistributeDirectiveClass,
+  explicit OMPTargetTeamsDistributeDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTargetTeamsDistributeDirectiveClass,
                          llvm::omp::OMPD_target_teams_distribute,
-                         SourceLocation(), SourceLocation(), CollapsedNum,
-                         NumClauses) {}
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -4610,9 +4447,7 @@ class OMPTargetTeamsDistributeDirective final : public OMPLoopDirective {
 class OMPTargetTeamsDistributeParallelForDirective final
     : public OMPLoopDirective {
   friend class ASTStmtReader;
-  /// Special reference expression for handling task reduction. Used to store
-  /// the taskgroup descriptor returned by the runtime functions.
-  Expr *TaskRedRef = nullptr;
+  friend class OMPExecutableDirective;
   /// true if the construct has inner cancel directive.
   bool HasCancel = false;
 
@@ -4621,33 +4456,29 @@ class OMPTargetTeamsDistributeParallelForDirective final
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTargetTeamsDistributeParallelForDirective(SourceLocation StartLoc,
                                                SourceLocation EndLoc,
-                                               unsigned CollapsedNum,
-                                               unsigned NumClauses)
-      : OMPLoopDirective(this,
-                         OMPTargetTeamsDistributeParallelForDirectiveClass,
+                                               unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTargetTeamsDistributeParallelForDirectiveClass,
                          llvm::omp::OMPD_target_teams_distribute_parallel_for,
-                         StartLoc, EndLoc, CollapsedNum, NumClauses),
-        HasCancel(false) {}
+                         StartLoc, EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTargetTeamsDistributeParallelForDirective(unsigned CollapsedNum,
-                                                        unsigned NumClauses)
-      : OMPLoopDirective(
-            this, OMPTargetTeamsDistributeParallelForDirectiveClass,
-            llvm::omp::OMPD_target_teams_distribute_parallel_for,
-            SourceLocation(), SourceLocation(), CollapsedNum, NumClauses),
-        HasCancel(false) {}
+  explicit OMPTargetTeamsDistributeParallelForDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTargetTeamsDistributeParallelForDirectiveClass,
+                         llvm::omp::OMPD_target_teams_distribute_parallel_for,
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
   /// Sets special task reduction descriptor.
-  void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
+  void setTaskReductionRefExpr(Expr *E) {
+    Data->getChildren()[numLoopChildren(
+        getCollapsedNumber(),
+        llvm::omp::OMPD_target_teams_distribute_parallel_for)] = E;
+  }
 
   /// Set cancel state.
   void setHasCancel(bool Has) { HasCancel = Has; }
@@ -4683,8 +4514,15 @@ class OMPTargetTeamsDistributeParallelForDirective final
               EmptyShell);
 
   /// Returns special task reduction reference expression.
-  Expr *getTaskReductionRefExpr() { return TaskRedRef; }
-  const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
+  Expr *getTaskReductionRefExpr() {
+    return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
+        getCollapsedNumber(),
+        llvm::omp::OMPD_target_teams_distribute_parallel_for)]);
+  }
+  const Expr *getTaskReductionRefExpr() const {
+    return const_cast<OMPTargetTeamsDistributeParallelForDirective *>(this)
+        ->getTaskReductionRefExpr();
+  }
 
   /// Return true if current directive has inner cancel directive.
   bool hasCancel() const { return HasCancel; }
@@ -4707,34 +4545,32 @@ class OMPTargetTeamsDistributeParallelForDirective final
 class OMPTargetTeamsDistributeParallelForSimdDirective final
     : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTargetTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,
                                                    SourceLocation EndLoc,
-                                                   unsigned CollapsedNum,
-                                                   unsigned NumClauses)
+                                                   unsigned CollapsedNum)
       : OMPLoopDirective(
-            this, OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
+            OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
             llvm::omp::OMPD_target_teams_distribute_parallel_for_simd, StartLoc,
-            EndLoc, CollapsedNum, NumClauses) {}
+            EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   explicit OMPTargetTeamsDistributeParallelForSimdDirective(
-      unsigned CollapsedNum, unsigned NumClauses)
+      unsigned CollapsedNum)
       : OMPLoopDirective(
-            this, OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
+            OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
             llvm::omp::OMPD_target_teams_distribute_parallel_for_simd,
-            SourceLocation(), SourceLocation(), CollapsedNum, NumClauses) {}
+            SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -4779,33 +4615,29 @@ class OMPTargetTeamsDistributeParallelForSimdDirective final
 ///
 class OMPTargetTeamsDistributeSimdDirective final : public OMPLoopDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
 
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
   OMPTargetTeamsDistributeSimdDirective(SourceLocation StartLoc,
                                         SourceLocation EndLoc,
-                                        unsigned CollapsedNum,
-                                        unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTargetTeamsDistributeSimdDirectiveClass,
+                                        unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTargetTeamsDistributeSimdDirectiveClass,
                          llvm::omp::OMPD_target_teams_distribute_simd, StartLoc,
-                         EndLoc, CollapsedNum, NumClauses) {}
+                         EndLoc, CollapsedNum) {}
 
   /// Build an empty directive.
   ///
   /// \param CollapsedNum Number of collapsed nested loops.
-  /// \param NumClauses Number of clauses.
   ///
-  explicit OMPTargetTeamsDistributeSimdDirective(unsigned CollapsedNum,
-                                                 unsigned NumClauses)
-      : OMPLoopDirective(this, OMPTargetTeamsDistributeSimdDirectiveClass,
+  explicit OMPTargetTeamsDistributeSimdDirective(unsigned CollapsedNum)
+      : OMPLoopDirective(OMPTargetTeamsDistributeSimdDirectiveClass,
                          llvm::omp::OMPD_target_teams_distribute_simd,
-                         SourceLocation(), SourceLocation(), CollapsedNum,
-                         NumClauses) {}
+                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 public:
   /// Creates directive with a list of \a Clauses.
@@ -4847,26 +4679,21 @@ class OMPTargetTeamsDistributeSimdDirective final : public OMPLoopDirective {
 /// list item 'a'.
 class OMPScanDirective final : public OMPExecutableDirective {
   friend class ASTStmtReader;
+  friend class OMPExecutableDirective;
   /// Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
   /// \param EndLoc Ending location of the directive.
-  /// \param NumClauses Number of clauses.
   ///
-  OMPScanDirective(SourceLocation StartLoc, SourceLocation EndLoc,
-                   unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPScanDirectiveClass,
-                               llvm::omp::OMPD_scan, StartLoc, EndLoc,
-                               NumClauses, 0) {}
+  OMPScanDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(OMPScanDirectiveClass, llvm::omp::OMPD_scan,
+                               StartLoc, EndLoc) {}
 
   /// Build an empty directive.
   ///
-  /// \param NumClauses Number of clauses.
-  ///
-  explicit OMPScanDirective(unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPScanDirectiveClass,
-                               llvm::omp::OMPD_scan, SourceLocation(),
-                               SourceLocation(), NumClauses, 0) {}
+  explicit OMPScanDirective()
+      : OMPExecutableDirective(OMPScanDirectiveClass, llvm::omp::OMPD_scan,
+                               SourceLocation(), SourceLocation()) {}
 
 public:
   /// Creates directive with a list of \a Clauses.

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 4721ccdf14590..7a83e03166185 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10167,19 +10167,18 @@ class Sema final {
   QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
                                         TypeResult ParsedType);
   /// Called on start of '#pragma omp declare mapper'.
-  OMPDeclareMapperDecl *ActOnOpenMPDeclareMapperDirectiveStart(
+  DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(
       Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
       SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
+      Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses,
       Decl *PrevDeclInScope = nullptr);
   /// Build the mapper variable of '#pragma omp declare mapper'.
-  void ActOnOpenMPDeclareMapperDirectiveVarDecl(OMPDeclareMapperDecl *DMD,
-                                                Scope *S, QualType MapperType,
-                                                SourceLocation StartLoc,
-                                                DeclarationName VN);
-  /// Called at the end of '#pragma omp declare mapper'.
-  DeclGroupPtrTy
-  ActOnOpenMPDeclareMapperDirectiveEnd(OMPDeclareMapperDecl *D, Scope *S,
-                                       ArrayRef<OMPClause *> ClauseList);
+  ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S,
+                                                      QualType MapperType,
+                                                      SourceLocation StartLoc,
+                                                      DeclarationName VN);
+  bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const;
+  const ValueDecl *getOpenMPDeclareMapperVarName() const;
 
   /// Called on the start of target region i.e. '#pragma omp declare target'.
   bool ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc);

diff  --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h
index 7248e6fa6c21d..3912ffe5e6b91 100644
--- a/clang/include/clang/Serialization/ASTRecordReader.h
+++ b/clang/include/clang/Serialization/ASTRecordReader.h
@@ -24,6 +24,7 @@
 
 namespace clang {
 class OMPTraitInfo;
+class OMPChildren;
 
 /// An object for streaming information from a record.
 class ASTRecordReader
@@ -266,6 +267,9 @@ class ASTRecordReader
   /// Read an OpenMP clause, advancing Idx.
   OMPClause *readOMPClause();
 
+  /// Read an OpenMP children, advancing Idx.
+  void readOMPChildren(OMPChildren *Data);
+
   /// Read a source location, advancing Idx.
   SourceLocation readSourceLocation() {
     return Reader->ReadSourceLocation(*F, Record, Idx);

diff  --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h
index 491207c9de906..edfcd9c52e2e9 100644
--- a/clang/include/clang/Serialization/ASTRecordWriter.h
+++ b/clang/include/clang/Serialization/ASTRecordWriter.h
@@ -271,6 +271,9 @@ class ASTRecordWriter
 
   void writeOMPClause(OMPClause *C);
 
+  /// Writes data related to the OpenMP directives.
+  void writeOMPChildren(OMPChildren *Data);
+
   /// Emit a string.
   void AddString(StringRef Str) {
     return Writer->AddString(Str, *Record);

diff  --git a/clang/lib/AST/DeclOpenMP.cpp b/clang/lib/AST/DeclOpenMP.cpp
index af321280d417a..867ef31656f75 100644
--- a/clang/lib/AST/DeclOpenMP.cpp
+++ b/clang/lib/AST/DeclOpenMP.cpp
@@ -23,16 +23,14 @@ using namespace clang;
 // OMPThreadPrivateDecl Implementation.
 //===----------------------------------------------------------------------===//
 
-void OMPThreadPrivateDecl::anchor() { }
+void OMPThreadPrivateDecl::anchor() {}
 
 OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C,
                                                    DeclContext *DC,
                                                    SourceLocation L,
                                                    ArrayRef<Expr *> VL) {
-  OMPThreadPrivateDecl *D =
-      new (C, DC, additionalSizeToAlloc<Expr *>(VL.size()))
-          OMPThreadPrivateDecl(OMPThreadPrivate, DC, L);
-  D->NumVars = VL.size();
+  auto *D = OMPDeclarativeDirective::createDirective<OMPThreadPrivateDecl>(
+      C, DC, llvm::None, VL.size(), L);
   D->setVars(VL);
   return D;
 }
@@ -40,16 +38,14 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C,
 OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C,
                                                                unsigned ID,
                                                                unsigned N) {
-  OMPThreadPrivateDecl *D = new (C, ID, additionalSizeToAlloc<Expr *>(N))
-      OMPThreadPrivateDecl(OMPThreadPrivate, nullptr, SourceLocation());
-  D->NumVars = N;
-  return D;
+  return OMPDeclarativeDirective::createEmptyDirective<OMPThreadPrivateDecl>(
+      C, ID, 0, N);
 }
 
 void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) {
-  assert(VL.size() == NumVars &&
+  assert(VL.size() == Data->getNumChildren() &&
          "Number of variables is not the same as the preallocated buffer");
-  std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects<Expr *>());
+  llvm::copy(VL, getVars().begin());
 }
 
 //===----------------------------------------------------------------------===//
@@ -61,38 +57,23 @@ void OMPAllocateDecl::anchor() { }
 OMPAllocateDecl *OMPAllocateDecl::Create(ASTContext &C, DeclContext *DC,
                                          SourceLocation L, ArrayRef<Expr *> VL,
                                          ArrayRef<OMPClause *> CL) {
-  OMPAllocateDecl *D = new (
-      C, DC, additionalSizeToAlloc<Expr *, OMPClause *>(VL.size(), CL.size()))
-      OMPAllocateDecl(OMPAllocate, DC, L);
-  D->NumVars = VL.size();
+  auto *D = OMPDeclarativeDirective::createDirective<OMPAllocateDecl>(
+      C, DC, CL, VL.size(), L);
   D->setVars(VL);
-  D->NumClauses = CL.size();
-  D->setClauses(CL);
   return D;
 }
 
 OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C, unsigned ID,
                                                      unsigned NVars,
                                                      unsigned NClauses) {
-  OMPAllocateDecl *D =
-      new (C, ID, additionalSizeToAlloc<Expr *, OMPClause *>(NVars, NClauses))
-          OMPAllocateDecl(OMPAllocate, nullptr, SourceLocation());
-  D->NumVars = NVars;
-  D->NumClauses = NClauses;
-  return D;
+  return OMPDeclarativeDirective::createEmptyDirective<OMPAllocateDecl>(
+      C, ID, NClauses, NVars, SourceLocation());
 }
 
 void OMPAllocateDecl::setVars(ArrayRef<Expr *> VL) {
-  assert(VL.size() == NumVars &&
+  assert(VL.size() == Data->getNumChildren() &&
          "Number of variables is not the same as the preallocated buffer");
-  std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects<Expr *>());
-}
-
-void OMPAllocateDecl::setClauses(ArrayRef<OMPClause *> CL) {
-  assert(CL.size() == NumClauses &&
-         "Number of variables is not the same as the preallocated buffer");
-  std::uninitialized_copy(CL.begin(), CL.end(),
-                          getTrailingObjects<OMPClause *>());
+  llvm::copy(VL, getVars().begin());
 }
 
 //===----------------------------------------------------------------------===//
@@ -104,27 +85,14 @@ void OMPRequiresDecl::anchor() {}
 OMPRequiresDecl *OMPRequiresDecl::Create(ASTContext &C, DeclContext *DC,
                                          SourceLocation L,
                                          ArrayRef<OMPClause *> CL) {
-  OMPRequiresDecl *D =
-      new (C, DC, additionalSizeToAlloc<OMPClause *>(CL.size()))
-      OMPRequiresDecl(OMPRequires, DC, L);
-  D->NumClauses = CL.size();
-  D->setClauses(CL);
-  return D;
+  return OMPDeclarativeDirective::createDirective<OMPRequiresDecl>(C, DC, CL, 0,
+                                                                   L);
 }
 
 OMPRequiresDecl *OMPRequiresDecl::CreateDeserialized(ASTContext &C, unsigned ID,
                                                      unsigned N) {
-  OMPRequiresDecl *D = new (C, ID, additionalSizeToAlloc<OMPClause *>(N))
-      OMPRequiresDecl(OMPRequires, nullptr, SourceLocation());
-  D->NumClauses = N;
-  return D;
-}
-
-void OMPRequiresDecl::setClauses(ArrayRef<OMPClause *> CL) {
-  assert(CL.size() == NumClauses &&
-         "Number of clauses is not the same as the preallocated buffer");
-  std::uninitialized_copy(CL.begin(), CL.end(),
-                          getTrailingObjects<OMPClause *>());
+  return OMPDeclarativeDirective::createEmptyDirective<OMPRequiresDecl>(
+      C, ID, N, 0, SourceLocation());
 }
 
 //===----------------------------------------------------------------------===//
@@ -171,48 +139,20 @@ OMPDeclareReductionDecl::getPrevDeclInScope() const {
 
 void OMPDeclareMapperDecl::anchor() {}
 
-OMPDeclareMapperDecl *
-OMPDeclareMapperDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
-                             DeclarationName Name, QualType T,
-                             DeclarationName VarName,
-                             OMPDeclareMapperDecl *PrevDeclInScope) {
-  return new (C, DC) OMPDeclareMapperDecl(OMPDeclareMapper, DC, L, Name, T,
-                                          VarName, PrevDeclInScope);
+OMPDeclareMapperDecl *OMPDeclareMapperDecl::Create(
+    ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name,
+    QualType T, DeclarationName VarName, ArrayRef<OMPClause *> Clauses,
+    OMPDeclareMapperDecl *PrevDeclInScope) {
+  return OMPDeclarativeDirective::createDirective<OMPDeclareMapperDecl>(
+      C, DC, Clauses, 1, L, Name, T, VarName, PrevDeclInScope);
 }
 
 OMPDeclareMapperDecl *OMPDeclareMapperDecl::CreateDeserialized(ASTContext &C,
                                                                unsigned ID,
                                                                unsigned N) {
-  auto *D = new (C, ID)
-      OMPDeclareMapperDecl(OMPDeclareMapper, /*DC=*/nullptr, SourceLocation(),
-                           DeclarationName(), QualType(), DeclarationName(),
-                           /*PrevDeclInScope=*/nullptr);
-  if (N) {
-    auto **ClauseStorage = C.Allocate<OMPClause *>(N);
-    D->Clauses = llvm::makeMutableArrayRef<OMPClause *>(ClauseStorage, N);
-  }
-  return D;
-}
-
-/// Creates an array of clauses to this mapper declaration and intializes
-/// them. The space used to store clause pointers is dynamically allocated,
-/// because we do not know the number of clauses when creating
-/// OMPDeclareMapperDecl
-void OMPDeclareMapperDecl::CreateClauses(ASTContext &C,
-                                         ArrayRef<OMPClause *> CL) {
-  assert(Clauses.empty() && "Number of clauses should be 0 on initialization");
-  size_t NumClauses = CL.size();
-  if (NumClauses) {
-    auto **ClauseStorage = C.Allocate<OMPClause *>(NumClauses);
-    Clauses = llvm::makeMutableArrayRef<OMPClause *>(ClauseStorage, NumClauses);
-    setClauses(CL);
-  }
-}
-
-void OMPDeclareMapperDecl::setClauses(ArrayRef<OMPClause *> CL) {
-  assert(CL.size() == Clauses.size() &&
-         "Number of clauses is not the same as the preallocated buffer");
-  std::uninitialized_copy(CL.begin(), CL.end(), Clauses.data());
+  return OMPDeclarativeDirective::createEmptyDirective<OMPDeclareMapperDecl>(
+      C, ID, N, 1, SourceLocation(), DeclarationName(), QualType(),
+      DeclarationName(), /*PrevDeclInScope=*/nullptr);
 }
 
 OMPDeclareMapperDecl *OMPDeclareMapperDecl::getPrevDeclInScope() {

diff  --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp
index 788fac789270f..c858261f23877 100644
--- a/clang/lib/AST/StmtOpenMP.cpp
+++ b/clang/lib/AST/StmtOpenMP.cpp
@@ -16,10 +16,43 @@
 using namespace clang;
 using namespace llvm::omp;
 
-void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) {
-  assert(Clauses.size() == getNumClauses() &&
+size_t OMPChildren::size(unsigned NumClauses, bool HasAssociatedStmt,
+                         unsigned NumChildren) {
+  return llvm::alignTo(
+      totalSizeToAlloc<OMPClause *, Stmt *>(
+          NumClauses, NumChildren + (HasAssociatedStmt ? 1 : 0)),
+      alignof(OMPChildren));
+}
+
+void OMPChildren::setClauses(ArrayRef<OMPClause *> Clauses) {
+  assert(Clauses.size() == NumClauses &&
          "Number of clauses is not the same as the preallocated buffer");
-  std::copy(Clauses.begin(), Clauses.end(), getClauses().begin());
+  llvm::copy(Clauses, getTrailingObjects<OMPClause *>());
+}
+
+MutableArrayRef<Stmt *> OMPChildren::getChildren() {
+  return llvm::makeMutableArrayRef(getTrailingObjects<Stmt *>(), NumChildren);
+}
+
+OMPChildren *OMPChildren::Create(void *Mem, ArrayRef<OMPClause *> Clauses) {
+  auto *Data = CreateEmpty(Mem, Clauses.size());
+  Data->setClauses(Clauses);
+  return Data;
+}
+
+OMPChildren *OMPChildren::Create(void *Mem, ArrayRef<OMPClause *> Clauses,
+                                 Stmt *S, unsigned NumChildren) {
+  auto *Data = CreateEmpty(Mem, Clauses.size(), S, NumChildren);
+  Data->setClauses(Clauses);
+  if (S)
+    Data->setAssociatedStmt(S);
+  return Data;
+}
+
+OMPChildren *OMPChildren::CreateEmpty(void *Mem, unsigned NumClauses,
+                                      bool HasAssociatedStmt,
+                                      unsigned NumChildren) {
+  return new (Mem) OMPChildren(NumClauses, NumChildren, HasAssociatedStmt);
 }
 
 bool OMPExecutableDirective::isStandaloneDirective() const {
@@ -30,15 +63,15 @@ bool OMPExecutableDirective::isStandaloneDirective() const {
       isa<OMPTargetExitDataDirective>(this) ||
       isa<OMPTargetUpdateDirective>(this))
     return true;
-  return !hasAssociatedStmt() || !getAssociatedStmt();
+  return !hasAssociatedStmt();
 }
 
-const Stmt *OMPExecutableDirective::getStructuredBlock() const {
+Stmt *OMPExecutableDirective::getStructuredBlock() {
   assert(!isStandaloneDirective() &&
          "Standalone Executable Directives don't have Structured Blocks.");
   if (auto *LD = dyn_cast<OMPLoopDirective>(this))
     return LD->getBody();
-  return getInnermostCapturedStmt()->getCapturedStmt();
+  return getRawStmt();
 }
 
 Stmt *OMPLoopDirective::tryToFindNextInnerLoop(Stmt *CurStmt,
@@ -87,8 +120,7 @@ Stmt *OMPLoopDirective::tryToFindNextInnerLoop(Stmt *CurStmt,
 
 Stmt *OMPLoopDirective::getBody() {
   // This relies on the loop form is already checked by Sema.
-  Stmt *Body =
-      getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
+  Stmt *Body = Data->getRawStmt()->IgnoreContainers();
   if (auto *For = dyn_cast<ForStmt>(Body)) {
     Body = For->getBody();
   } else {
@@ -112,32 +144,32 @@ Stmt *OMPLoopDirective::getBody() {
 void OMPLoopDirective::setCounters(ArrayRef<Expr *> A) {
   assert(A.size() == getCollapsedNumber() &&
          "Number of loop counters is not the same as the collapsed number");
-  std::copy(A.begin(), A.end(), getCounters().begin());
+  llvm::copy(A, getCounters().begin());
 }
 
 void OMPLoopDirective::setPrivateCounters(ArrayRef<Expr *> A) {
   assert(A.size() == getCollapsedNumber() && "Number of loop private counters "
                                              "is not the same as the collapsed "
                                              "number");
-  std::copy(A.begin(), A.end(), getPrivateCounters().begin());
+  llvm::copy(A, getPrivateCounters().begin());
 }
 
 void OMPLoopDirective::setInits(ArrayRef<Expr *> A) {
   assert(A.size() == getCollapsedNumber() &&
          "Number of counter inits is not the same as the collapsed number");
-  std::copy(A.begin(), A.end(), getInits().begin());
+  llvm::copy(A, getInits().begin());
 }
 
 void OMPLoopDirective::setUpdates(ArrayRef<Expr *> A) {
   assert(A.size() == getCollapsedNumber() &&
          "Number of counter updates is not the same as the collapsed number");
-  std::copy(A.begin(), A.end(), getUpdates().begin());
+  llvm::copy(A, getUpdates().begin());
 }
 
 void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) {
   assert(A.size() == getCollapsedNumber() &&
          "Number of counter finals is not the same as the collapsed number");
-  std::copy(A.begin(), A.end(), getFinals().begin());
+  llvm::copy(A, getFinals().begin());
 }
 
 void OMPLoopDirective::setDependentCounters(ArrayRef<Expr *> A) {
@@ -163,14 +195,8 @@ OMPParallelDirective *OMPParallelDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
     bool HasCancel) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPParallelDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPParallelDirective *Dir =
-      new (Mem) OMPParallelDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPParallelDirective>(
+      C, Clauses, AssociatedStmt, /*NumChildren=*/1, StartLoc, EndLoc);
   Dir->setTaskReductionRefExpr(TaskRedRef);
   Dir->setHasCancel(HasCancel);
   return Dir;
@@ -179,11 +205,9 @@ OMPParallelDirective *OMPParallelDirective::Create(
 OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C,
                                                         unsigned NumClauses,
                                                         EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPParallelDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
-  return new (Mem) OMPParallelDirective(NumClauses);
+  return createEmptyDirective<OMPParallelDirective>(C, NumClauses,
+                                                    /*HasAssociatedStmt=*/true,
+                                                    /*NumChildren=*/1);
 }
 
 OMPSimdDirective *
@@ -191,14 +215,9 @@ OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
                          SourceLocation EndLoc, unsigned CollapsedNum,
                          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
                          const HelperExprs &Exprs) {
-  unsigned Size = llvm::alignTo(sizeof(OMPSimdDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
-                 sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd));
-  OMPSimdDirective *Dir = new (Mem)
-      OMPSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPSimdDirective>(
+      C, Clauses, AssociatedStmt, numLoopChildren(CollapsedNum, OMPD_simd),
+      StartLoc, EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -222,25 +241,18 @@ OMPSimdDirective *OMPSimdDirective::CreateEmpty(const ASTContext &C,
                                                 unsigned NumClauses,
                                                 unsigned CollapsedNum,
                                                 EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPSimdDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
-                 sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd));
-  return new (Mem) OMPSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_simd), CollapsedNum);
 }
 
 OMPForDirective *OMPForDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel) {
-  unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
-                 sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for));
-  OMPForDirective *Dir =
-      new (Mem) OMPForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPForDirective>(
+      C, Clauses, AssociatedStmt, numLoopChildren(CollapsedNum, OMPD_for) + 1,
+      StartLoc, EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -274,11 +286,9 @@ OMPForDirective *OMPForDirective::CreateEmpty(const ASTContext &C,
                                               unsigned NumClauses,
                                               unsigned CollapsedNum,
                                               EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
-                 sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for));
-  return new (Mem) OMPForDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPForDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_for) + 1, CollapsedNum);
 }
 
 OMPForSimdDirective *
@@ -286,15 +296,9 @@ OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
                             SourceLocation EndLoc, unsigned CollapsedNum,
                             ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
                             const HelperExprs &Exprs) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPForSimdDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
-                 sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd));
-  OMPForSimdDirective *Dir = new (Mem)
-      OMPForSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPForSimdDirective>(
+      C, Clauses, AssociatedStmt, numLoopChildren(CollapsedNum, OMPD_for_simd),
+      StartLoc, EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -326,26 +330,18 @@ OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C,
                                                       unsigned NumClauses,
                                                       unsigned CollapsedNum,
                                                       EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPForSimdDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
-                 sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd));
-  return new (Mem) OMPForSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPForSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_for_simd), CollapsedNum);
 }
 
 OMPSectionsDirective *OMPSectionsDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
     bool HasCancel) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPSectionsDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPSectionsDirective *Dir =
-      new (Mem) OMPSectionsDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPSectionsDirective>(C, Clauses, AssociatedStmt,
+                                                    /*NumChildren=*/1, StartLoc,
+                                                    EndLoc);
   Dir->setTaskReductionRefExpr(TaskRedRef);
   Dir->setHasCancel(HasCancel);
   return Dir;
@@ -354,11 +350,9 @@ OMPSectionsDirective *OMPSectionsDirective::Create(
 OMPSectionsDirective *OMPSectionsDirective::CreateEmpty(const ASTContext &C,
                                                         unsigned NumClauses,
                                                         EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPSectionsDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
-  return new (Mem) OMPSectionsDirective(NumClauses);
+  return createEmptyDirective<OMPSectionsDirective>(C, NumClauses,
+                                                    /*HasAssociatedStmt=*/true,
+                                                    /*NumChildren=*/1);
 }
 
 OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C,
@@ -366,19 +360,17 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C,
                                                  SourceLocation EndLoc,
                                                  Stmt *AssociatedStmt,
                                                  bool HasCancel) {
-  unsigned Size = llvm::alignTo(sizeof(OMPSectionDirective), alignof(Stmt *));
-  void *Mem = C.Allocate(Size + sizeof(Stmt *));
-  OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir =
+      createDirective<OMPSectionDirective>(C, llvm::None, AssociatedStmt,
+                                           /*NumChildre=*/0, StartLoc, EndLoc);
   Dir->setHasCancel(HasCancel);
   return Dir;
 }
 
 OMPSectionDirective *OMPSectionDirective::CreateEmpty(const ASTContext &C,
                                                       EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPSectionDirective), alignof(Stmt *));
-  void *Mem = C.Allocate(Size + sizeof(Stmt *));
-  return new (Mem) OMPSectionDirective();
+  return createEmptyDirective<OMPSectionDirective>(C, /*NumClauses=*/0,
+                                                   /*HasAssociatedStmt=*/true);
 }
 
 OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C,
@@ -386,83 +378,57 @@ OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C,
                                                SourceLocation EndLoc,
                                                ArrayRef<OMPClause *> Clauses,
                                                Stmt *AssociatedStmt) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPSingleDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPSingleDirective *Dir =
-      new (Mem) OMPSingleDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
-  return Dir;
+  return createDirective<OMPSingleDirective>(C, Clauses, AssociatedStmt,
+                                             /*NumChildren=*/0, StartLoc,
+                                             EndLoc);
 }
 
 OMPSingleDirective *OMPSingleDirective::CreateEmpty(const ASTContext &C,
                                                     unsigned NumClauses,
                                                     EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPSingleDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
-  return new (Mem) OMPSingleDirective(NumClauses);
+  return createEmptyDirective<OMPSingleDirective>(C, NumClauses,
+                                                  /*HasAssociatedStmt=*/true);
 }
 
 OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C,
                                                SourceLocation StartLoc,
                                                SourceLocation EndLoc,
                                                Stmt *AssociatedStmt) {
-  unsigned Size = llvm::alignTo(sizeof(OMPMasterDirective), alignof(Stmt *));
-  void *Mem = C.Allocate(Size + sizeof(Stmt *));
-  OMPMasterDirective *Dir = new (Mem) OMPMasterDirective(StartLoc, EndLoc);
-  Dir->setAssociatedStmt(AssociatedStmt);
-  return Dir;
+  return createDirective<OMPMasterDirective>(C, llvm::None, AssociatedStmt,
+                                             /*NumChildren=*/0, StartLoc,
+                                             EndLoc);
 }
 
 OMPMasterDirective *OMPMasterDirective::CreateEmpty(const ASTContext &C,
                                                     EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPMasterDirective), alignof(Stmt *));
-  void *Mem = C.Allocate(Size + sizeof(Stmt *));
-  return new (Mem) OMPMasterDirective();
+  return createEmptyDirective<OMPMasterDirective>(C, /*NumClauses=*/0,
+                                                  /*HasAssociatedStmt=*/true);
 }
 
 OMPCriticalDirective *OMPCriticalDirective::Create(
     const ASTContext &C, const DeclarationNameInfo &Name,
     SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPCriticalDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPCriticalDirective *Dir =
-      new (Mem) OMPCriticalDirective(Name, StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
-  return Dir;
+  return createDirective<OMPCriticalDirective>(C, Clauses, AssociatedStmt,
+                                               /*NumChildren=*/0, Name,
+                                               StartLoc, EndLoc);
 }
 
 OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C,
                                                         unsigned NumClauses,
                                                         EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPCriticalDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
-  return new (Mem) OMPCriticalDirective(NumClauses);
+  return createEmptyDirective<OMPCriticalDirective>(C, NumClauses,
+                                                    /*HasAssociatedStmt=*/true);
 }
 
 OMPParallelForDirective *OMPParallelForDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPParallelForDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
-                         sizeof(Stmt *) *
-                             numLoopChildren(CollapsedNum, OMPD_parallel_for));
-  OMPParallelForDirective *Dir = new (Mem)
-      OMPParallelForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPParallelForDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_parallel_for) + 1, StartLoc, EndLoc,
+      CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -495,27 +461,19 @@ OMPParallelForDirective *OMPParallelForDirective::Create(
 OMPParallelForDirective *
 OMPParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
                                      unsigned CollapsedNum, EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPParallelForDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
-                         sizeof(Stmt *) *
-                             numLoopChildren(CollapsedNum, OMPD_parallel_for));
-  return new (Mem) OMPParallelForDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPParallelForDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_parallel_for) + 1, CollapsedNum);
 }
 
 OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPParallelForSimdDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd));
-  OMPParallelForSimdDirective *Dir = new (Mem) OMPParallelForSimdDirective(
-      StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPParallelForSimdDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_parallel_for_simd), StartLoc, EndLoc,
+      CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -547,51 +505,33 @@ OMPParallelForSimdDirective *
 OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C,
                                          unsigned NumClauses,
                                          unsigned CollapsedNum, EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPParallelForSimdDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd));
-  return new (Mem) OMPParallelForSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPParallelForSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_parallel_for_simd), CollapsedNum);
 }
 
 OMPParallelMasterDirective *OMPParallelMasterDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPParallelMasterDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  auto *Dir =
-      new (Mem) OMPParallelMasterDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPParallelMasterDirective>(
+      C, Clauses, AssociatedStmt, /*NumChildren=*/1, StartLoc, EndLoc);
   Dir->setTaskReductionRefExpr(TaskRedRef);
   return Dir;
 }
 
-OMPParallelMasterDirective *OMPParallelMasterDirective::CreateEmpty(const ASTContext &C,
-                                                        unsigned NumClauses,
-                                                        EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPParallelMasterDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
-  return new (Mem) OMPParallelMasterDirective(NumClauses);
+OMPParallelMasterDirective *
+OMPParallelMasterDirective::CreateEmpty(const ASTContext &C,
+                                        unsigned NumClauses, EmptyShell) {
+  return createEmptyDirective<OMPParallelMasterDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/1);
 }
 
 OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
     bool HasCancel) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPParallelSectionsDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPParallelSectionsDirective *Dir =
-      new (Mem) OMPParallelSectionsDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPParallelSectionsDirective>(
+      C, Clauses, AssociatedStmt, /*NumChildren=*/1, StartLoc, EndLoc);
   Dir->setTaskReductionRefExpr(TaskRedRef);
   Dir->setHasCancel(HasCancel);
   return Dir;
@@ -600,24 +540,16 @@ OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create(
 OMPParallelSectionsDirective *
 OMPParallelSectionsDirective::CreateEmpty(const ASTContext &C,
                                           unsigned NumClauses, EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPParallelSectionsDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
-  return new (Mem) OMPParallelSectionsDirective(NumClauses);
+  return createEmptyDirective<OMPParallelSectionsDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/1);
 }
 
 OMPTaskDirective *
 OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc,
                          SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
                          Stmt *AssociatedStmt, bool HasCancel) {
-  unsigned Size = llvm::alignTo(sizeof(OMPTaskDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPTaskDirective *Dir =
-      new (Mem) OMPTaskDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTaskDirective>(
+      C, Clauses, AssociatedStmt, /*NumChildren=*/0, StartLoc, EndLoc);
   Dir->setHasCancel(HasCancel);
   return Dir;
 }
@@ -625,111 +557,79 @@ OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc,
 OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C,
                                                 unsigned NumClauses,
                                                 EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPTaskDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
-  return new (Mem) OMPTaskDirective(NumClauses);
+  return createEmptyDirective<OMPTaskDirective>(C, NumClauses,
+                                                /*HasAssociatedStmt=*/true);
 }
 
 OMPTaskyieldDirective *OMPTaskyieldDirective::Create(const ASTContext &C,
                                                      SourceLocation StartLoc,
                                                      SourceLocation EndLoc) {
-  void *Mem = C.Allocate(sizeof(OMPTaskyieldDirective));
-  OMPTaskyieldDirective *Dir =
-      new (Mem) OMPTaskyieldDirective(StartLoc, EndLoc);
-  return Dir;
+  return new (C) OMPTaskyieldDirective(StartLoc, EndLoc);
 }
 
 OMPTaskyieldDirective *OMPTaskyieldDirective::CreateEmpty(const ASTContext &C,
                                                           EmptyShell) {
-  void *Mem = C.Allocate(sizeof(OMPTaskyieldDirective));
-  return new (Mem) OMPTaskyieldDirective();
+  return new (C) OMPTaskyieldDirective();
 }
 
 OMPBarrierDirective *OMPBarrierDirective::Create(const ASTContext &C,
                                                  SourceLocation StartLoc,
                                                  SourceLocation EndLoc) {
-  void *Mem = C.Allocate(sizeof(OMPBarrierDirective));
-  OMPBarrierDirective *Dir = new (Mem) OMPBarrierDirective(StartLoc, EndLoc);
-  return Dir;
+  return new (C) OMPBarrierDirective(StartLoc, EndLoc);
 }
 
 OMPBarrierDirective *OMPBarrierDirective::CreateEmpty(const ASTContext &C,
                                                       EmptyShell) {
-  void *Mem = C.Allocate(sizeof(OMPBarrierDirective));
-  return new (Mem) OMPBarrierDirective();
+  return new (C) OMPBarrierDirective();
 }
 
 OMPTaskwaitDirective *OMPTaskwaitDirective::Create(const ASTContext &C,
                                                    SourceLocation StartLoc,
                                                    SourceLocation EndLoc) {
-  void *Mem = C.Allocate(sizeof(OMPTaskwaitDirective));
-  OMPTaskwaitDirective *Dir = new (Mem) OMPTaskwaitDirective(StartLoc, EndLoc);
-  return Dir;
+  return new (C) OMPTaskwaitDirective(StartLoc, EndLoc);
 }
 
 OMPTaskwaitDirective *OMPTaskwaitDirective::CreateEmpty(const ASTContext &C,
                                                         EmptyShell) {
-  void *Mem = C.Allocate(sizeof(OMPTaskwaitDirective));
-  return new (Mem) OMPTaskwaitDirective();
+  return new (C) OMPTaskwaitDirective();
 }
 
 OMPTaskgroupDirective *OMPTaskgroupDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *ReductionRef) {
-  unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective) +
-                                    sizeof(OMPClause *) * Clauses.size(),
-                                alignof(Stmt *));
-  void *Mem = C.Allocate(Size + sizeof(Stmt *) + sizeof(Expr *));
-  OMPTaskgroupDirective *Dir =
-      new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTaskgroupDirective>(
+      C, Clauses, AssociatedStmt, /*NumChildren=*/1, StartLoc, EndLoc);
   Dir->setReductionRef(ReductionRef);
-  Dir->setClauses(Clauses);
   return Dir;
 }
 
 OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C,
                                                           unsigned NumClauses,
                                                           EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective) +
-                                    sizeof(OMPClause *) * NumClauses,
-                                alignof(Stmt *));
-  void *Mem = C.Allocate(Size + sizeof(Stmt *) + sizeof(Expr *));
-  return new (Mem) OMPTaskgroupDirective(NumClauses);
+  return createEmptyDirective<OMPTaskgroupDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/1);
 }
 
 OMPCancellationPointDirective *OMPCancellationPointDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     OpenMPDirectiveKind CancelRegion) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPCancellationPointDirective), alignof(Stmt *));
-  void *Mem = C.Allocate(Size);
-  OMPCancellationPointDirective *Dir =
-      new (Mem) OMPCancellationPointDirective(StartLoc, EndLoc);
+  auto *Dir = new (C) OMPCancellationPointDirective(StartLoc, EndLoc);
   Dir->setCancelRegion(CancelRegion);
   return Dir;
 }
 
 OMPCancellationPointDirective *
 OMPCancellationPointDirective::CreateEmpty(const ASTContext &C, EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPCancellationPointDirective), alignof(Stmt *));
-  void *Mem = C.Allocate(Size);
-  return new (Mem) OMPCancellationPointDirective();
+  return new (C) OMPCancellationPointDirective();
 }
 
 OMPCancelDirective *
 OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc,
                            SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
                            OpenMPDirectiveKind CancelRegion) {
-  unsigned Size = llvm::alignTo(sizeof(OMPCancelDirective) +
-                                    sizeof(OMPClause *) * Clauses.size(),
-                                alignof(Stmt *));
-  void *Mem = C.Allocate(Size);
-  OMPCancelDirective *Dir =
-      new (Mem) OMPCancelDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
+  auto *Dir = createDirective<OMPCancelDirective>(
+      C, Clauses, /*AssociatedStmt=*/nullptr, /*NumChildren=*/0, StartLoc,
+      EndLoc);
   Dir->setCancelRegion(CancelRegion);
   return Dir;
 }
@@ -737,77 +637,52 @@ OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc,
 OMPCancelDirective *OMPCancelDirective::CreateEmpty(const ASTContext &C,
                                                     unsigned NumClauses,
                                                     EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPCancelDirective) +
-                                    sizeof(OMPClause *) * NumClauses,
-                                alignof(Stmt *));
-  void *Mem = C.Allocate(Size);
-  return new (Mem) OMPCancelDirective(NumClauses);
+  return createEmptyDirective<OMPCancelDirective>(C, NumClauses);
 }
 
 OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C,
                                              SourceLocation StartLoc,
                                              SourceLocation EndLoc,
                                              ArrayRef<OMPClause *> Clauses) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPFlushDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size());
-  OMPFlushDirective *Dir =
-      new (Mem) OMPFlushDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  return Dir;
+  return createDirective<OMPFlushDirective>(
+      C, Clauses, /*AssociatedStmt=*/nullptr, /*NumChildren=*/0, StartLoc,
+      EndLoc);
 }
 
 OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C,
                                                   unsigned NumClauses,
                                                   EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPFlushDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses);
-  return new (Mem) OMPFlushDirective(NumClauses);
+  return createEmptyDirective<OMPFlushDirective>(C, NumClauses);
 }
 
 OMPDepobjDirective *OMPDepobjDirective::Create(const ASTContext &C,
                                                SourceLocation StartLoc,
                                                SourceLocation EndLoc,
                                                ArrayRef<OMPClause *> Clauses) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPDepobjDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size(),
-                         alignof(OMPDepobjDirective));
-  auto *Dir = new (Mem) OMPDepobjDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  return Dir;
+  return createDirective<OMPDepobjDirective>(
+      C, Clauses, /*AssociatedStmt=*/nullptr,
+      /*NumChildren=*/0, StartLoc, EndLoc);
 }
 
 OMPDepobjDirective *OMPDepobjDirective::CreateEmpty(const ASTContext &C,
                                                     unsigned NumClauses,
                                                     EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPDepobjDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses,
-                         alignof(OMPDepobjDirective));
-  return new (Mem) OMPDepobjDirective(NumClauses);
+  return createEmptyDirective<OMPDepobjDirective>(C, NumClauses);
 }
 
 OMPScanDirective *OMPScanDirective::Create(const ASTContext &C,
                                            SourceLocation StartLoc,
                                            SourceLocation EndLoc,
                                            ArrayRef<OMPClause *> Clauses) {
-  unsigned Size = llvm::alignTo(sizeof(OMPScanDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size(),
-                         alignof(OMPScanDirective));
-  auto *Dir = new (Mem) OMPScanDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  return Dir;
+  return createDirective<OMPScanDirective>(C, Clauses,
+                                           /*AssociatedStmt=*/nullptr,
+                                           /*NumChildren=*/0, StartLoc, EndLoc);
 }
 
 OMPScanDirective *OMPScanDirective::CreateEmpty(const ASTContext &C,
                                                 unsigned NumClauses,
                                                 EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPScanDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses,
-                         alignof(OMPScanDirective));
-  return new (Mem) OMPScanDirective(NumClauses);
+  return createEmptyDirective<OMPScanDirective>(C, NumClauses);
 }
 
 OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C,
@@ -815,39 +690,25 @@ OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C,
                                                  SourceLocation EndLoc,
                                                  ArrayRef<OMPClause *> Clauses,
                                                  Stmt *AssociatedStmt) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPOrderedDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * Clauses.size());
-  OMPOrderedDirective *Dir =
-      new (Mem) OMPOrderedDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
-  return Dir;
+  return createDirective<OMPOrderedDirective>(
+      C, Clauses, cast_or_null<CapturedStmt>(AssociatedStmt),
+      /*NumChildren=*/0, StartLoc, EndLoc);
 }
 
 OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C,
                                                       unsigned NumClauses,
+                                                      bool IsStandalone,
                                                       EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPOrderedDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * NumClauses);
-  return new (Mem) OMPOrderedDirective(NumClauses);
+  return createEmptyDirective<OMPOrderedDirective>(C, NumClauses,
+                                                   !IsStandalone);
 }
 
 OMPAtomicDirective *OMPAtomicDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
     Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPAtomicDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
-                         5 * sizeof(Stmt *));
-  OMPAtomicDirective *Dir =
-      new (Mem) OMPAtomicDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPAtomicDirective>(
+      C, Clauses, AssociatedStmt, /*NumChildren=*/4, StartLoc, EndLoc);
   Dir->setX(X);
   Dir->setV(V);
   Dir->setExpr(E);
@@ -860,11 +721,8 @@ OMPAtomicDirective *OMPAtomicDirective::Create(
 OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C,
                                                     unsigned NumClauses,
                                                     EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPAtomicDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *));
-  return new (Mem) OMPAtomicDirective(NumClauses);
+  return createEmptyDirective<OMPAtomicDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/4);
 }
 
 OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C,
@@ -872,39 +730,23 @@ OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C,
                                                SourceLocation EndLoc,
                                                ArrayRef<OMPClause *> Clauses,
                                                Stmt *AssociatedStmt) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTargetDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPTargetDirective *Dir =
-      new (Mem) OMPTargetDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
-  return Dir;
+  return createDirective<OMPTargetDirective>(
+      C, Clauses, AssociatedStmt, /*NumChildren=*/0, StartLoc, EndLoc);
 }
 
 OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C,
                                                     unsigned NumClauses,
                                                     EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTargetDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
-  return new (Mem) OMPTargetDirective(NumClauses);
+  return createEmptyDirective<OMPTargetDirective>(C, NumClauses,
+                                                  /*HasAssociatedStmt=*/true);
 }
 
 OMPTargetParallelDirective *OMPTargetParallelDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
     bool HasCancel) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTargetParallelDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPTargetParallelDirective *Dir =
-      new (Mem) OMPTargetParallelDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTargetParallelDirective>(
+      C, Clauses, AssociatedStmt, /*NumChildren=*/1, StartLoc, EndLoc);
   Dir->setTaskReductionRefExpr(TaskRedRef);
   Dir->setHasCancel(HasCancel);
   return Dir;
@@ -913,26 +755,18 @@ OMPTargetParallelDirective *OMPTargetParallelDirective::Create(
 OMPTargetParallelDirective *
 OMPTargetParallelDirective::CreateEmpty(const ASTContext &C,
                                         unsigned NumClauses, EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTargetParallelDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
-  return new (Mem) OMPTargetParallelDirective(NumClauses);
+  return createEmptyDirective<OMPTargetParallelDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/1);
 }
 
 OMPTargetParallelForDirective *OMPTargetParallelForDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel) {
-  unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective),
-                                alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for));
-  OMPTargetParallelForDirective *Dir = new (Mem) OMPTargetParallelForDirective(
-      StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTargetParallelForDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_target_parallel_for) + 1, StartLoc,
+      EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -966,78 +800,52 @@ OMPTargetParallelForDirective *
 OMPTargetParallelForDirective::CreateEmpty(const ASTContext &C,
                                            unsigned NumClauses,
                                            unsigned CollapsedNum, EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective),
-                                alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for));
-  return new (Mem) OMPTargetParallelForDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTargetParallelForDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_target_parallel_for) + 1,
+      CollapsedNum);
 }
 
 OMPTargetDataDirective *OMPTargetDataDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
-  void *Mem = C.Allocate(
-      llvm::alignTo(sizeof(OMPTargetDataDirective), alignof(OMPClause *)) +
-      sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPTargetDataDirective *Dir =
-      new (Mem) OMPTargetDataDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
-  return Dir;
+  return createDirective<OMPTargetDataDirective>(
+      C, Clauses, AssociatedStmt, /*NumChildren=*/0, StartLoc, EndLoc);
 }
 
 OMPTargetDataDirective *OMPTargetDataDirective::CreateEmpty(const ASTContext &C,
                                                             unsigned N,
                                                             EmptyShell) {
-  void *Mem = C.Allocate(
-      llvm::alignTo(sizeof(OMPTargetDataDirective), alignof(OMPClause *)) +
-      sizeof(OMPClause *) * N + sizeof(Stmt *));
-  return new (Mem) OMPTargetDataDirective(N);
+  return createEmptyDirective<OMPTargetDataDirective>(
+      C, N, /*HasAssociatedStmt=*/true);
 }
 
 OMPTargetEnterDataDirective *OMPTargetEnterDataDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
-  void *Mem = C.Allocate(
-      llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) +
-      sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPTargetEnterDataDirective *Dir =
-      new (Mem) OMPTargetEnterDataDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
-  return Dir;
+  return createDirective<OMPTargetEnterDataDirective>(
+      C, Clauses, AssociatedStmt, /*NumChildren=*/0, StartLoc, EndLoc);
 }
 
 OMPTargetEnterDataDirective *
 OMPTargetEnterDataDirective::CreateEmpty(const ASTContext &C, unsigned N,
                                          EmptyShell) {
-  void *Mem = C.Allocate(
-      llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) +
-      sizeof(OMPClause *) * N + sizeof(Stmt *));
-  return new (Mem) OMPTargetEnterDataDirective(N);
+  return createEmptyDirective<OMPTargetEnterDataDirective>(
+      C, N, /*HasAssociatedStmt=*/true);
 }
 
 OMPTargetExitDataDirective *OMPTargetExitDataDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
-  void *Mem = C.Allocate(
-      llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) +
-      sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPTargetExitDataDirective *Dir =
-      new (Mem) OMPTargetExitDataDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
-  return Dir;
+  return createDirective<OMPTargetExitDataDirective>(
+      C, Clauses, AssociatedStmt, /*NumChildren=*/0, StartLoc, EndLoc);
 }
 
 OMPTargetExitDataDirective *
 OMPTargetExitDataDirective::CreateEmpty(const ASTContext &C, unsigned N,
                                         EmptyShell) {
-  void *Mem = C.Allocate(
-      llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) +
-      sizeof(OMPClause *) * N + sizeof(Stmt *));
-  return new (Mem) OMPTargetExitDataDirective(N);
+  return createEmptyDirective<OMPTargetExitDataDirective>(
+      C, N, /*HasAssociatedStmt=*/true);
 }
 
 OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C,
@@ -1045,40 +853,24 @@ OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C,
                                              SourceLocation EndLoc,
                                              ArrayRef<OMPClause *> Clauses,
                                              Stmt *AssociatedStmt) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTeamsDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPTeamsDirective *Dir =
-      new (Mem) OMPTeamsDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
-  return Dir;
+  return createDirective<OMPTeamsDirective>(
+      C, Clauses, AssociatedStmt, /*NumChildren=*/0, StartLoc, EndLoc);
 }
 
 OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C,
                                                   unsigned NumClauses,
                                                   EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTeamsDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
-  return new (Mem) OMPTeamsDirective(NumClauses);
+  return createEmptyDirective<OMPTeamsDirective>(C, NumClauses,
+                                                 /*HasAssociatedStmt=*/true);
 }
 
 OMPTaskLoopDirective *OMPTaskLoopDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs, bool HasCancel) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTaskLoopDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
-                 sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop));
-  OMPTaskLoopDirective *Dir = new (Mem)
-      OMPTaskLoopDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTaskLoopDirective>(
+      C, Clauses, AssociatedStmt, numLoopChildren(CollapsedNum, OMPD_taskloop),
+      StartLoc, EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1111,27 +903,19 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::CreateEmpty(const ASTContext &C,
                                                         unsigned NumClauses,
                                                         unsigned CollapsedNum,
                                                         EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTaskLoopDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
-                 sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop));
-  return new (Mem) OMPTaskLoopDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTaskLoopDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_taskloop), CollapsedNum);
 }
 
 OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
-                         sizeof(Stmt *) *
-                             numLoopChildren(CollapsedNum, OMPD_taskloop_simd));
-  OMPTaskLoopSimdDirective *Dir = new (Mem)
-      OMPTaskLoopSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTaskLoopSimdDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_taskloop_simd), StartLoc, EndLoc,
+      CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1162,27 +946,19 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create(
 OMPTaskLoopSimdDirective *
 OMPTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
                                       unsigned CollapsedNum, EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
-                         sizeof(Stmt *) *
-                             numLoopChildren(CollapsedNum, OMPD_taskloop_simd));
-  return new (Mem) OMPTaskLoopSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTaskLoopSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_taskloop_simd), CollapsedNum);
 }
 
 OMPMasterTaskLoopDirective *OMPMasterTaskLoopDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs, bool HasCancel) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPMasterTaskLoopDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_master_taskloop));
-  OMPMasterTaskLoopDirective *Dir = new (Mem) OMPMasterTaskLoopDirective(
-      StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPMasterTaskLoopDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_master_taskloop), StartLoc, EndLoc,
+      CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1215,28 +991,19 @@ OMPMasterTaskLoopDirective *
 OMPMasterTaskLoopDirective::CreateEmpty(const ASTContext &C,
                                         unsigned NumClauses,
                                         unsigned CollapsedNum, EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPMasterTaskLoopDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_master_taskloop));
-  return new (Mem) OMPMasterTaskLoopDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPMasterTaskLoopDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_master_taskloop), CollapsedNum);
 }
 
 OMPMasterTaskLoopSimdDirective *OMPMasterTaskLoopSimdDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  unsigned Size = llvm::alignTo(sizeof(OMPMasterTaskLoopSimdDirective),
-                                alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
-                 sizeof(Stmt *) *
-                     numLoopChildren(CollapsedNum, OMPD_master_taskloop_simd));
-  auto *Dir = new (Mem) OMPMasterTaskLoopSimdDirective(
-      StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPMasterTaskLoopSimdDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_master_taskloop_simd), StartLoc,
+      EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1268,29 +1035,19 @@ OMPMasterTaskLoopSimdDirective *
 OMPMasterTaskLoopSimdDirective::CreateEmpty(const ASTContext &C,
                                             unsigned NumClauses,
                                             unsigned CollapsedNum, EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPMasterTaskLoopSimdDirective),
-                                alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
-                 sizeof(Stmt *) *
-                     numLoopChildren(CollapsedNum, OMPD_master_taskloop_simd));
-  return new (Mem) OMPMasterTaskLoopSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPMasterTaskLoopSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_master_taskloop_simd), CollapsedNum);
 }
 
 OMPParallelMasterTaskLoopDirective *OMPParallelMasterTaskLoopDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs, bool HasCancel) {
-  unsigned Size = llvm::alignTo(sizeof(OMPParallelMasterTaskLoopDirective),
-                                alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_parallel_master_taskloop));
-  auto *Dir = new (Mem) OMPParallelMasterTaskLoopDirective(
-      StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPParallelMasterTaskLoopDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_parallel_master_taskloop), StartLoc,
+      EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1324,13 +1081,10 @@ OMPParallelMasterTaskLoopDirective::CreateEmpty(const ASTContext &C,
                                                 unsigned NumClauses,
                                                 unsigned CollapsedNum,
                                                 EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPParallelMasterTaskLoopDirective),
-                                alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_parallel_master_taskloop));
-  return new (Mem) OMPParallelMasterTaskLoopDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPParallelMasterTaskLoopDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_parallel_master_taskloop),
+      CollapsedNum);
 }
 
 OMPParallelMasterTaskLoopSimdDirective *
@@ -1338,16 +1092,10 @@ OMPParallelMasterTaskLoopSimdDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  unsigned Size = llvm::alignTo(sizeof(OMPParallelMasterTaskLoopSimdDirective),
-                                alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_parallel_master_taskloop_simd));
-  auto *Dir = new (Mem) OMPParallelMasterTaskLoopSimdDirective(
-      StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPParallelMasterTaskLoopSimdDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_parallel_master_taskloop_simd),
+      StartLoc, EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1380,29 +1128,20 @@ OMPParallelMasterTaskLoopSimdDirective::CreateEmpty(const ASTContext &C,
                                                     unsigned NumClauses,
                                                     unsigned CollapsedNum,
                                                     EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPParallelMasterTaskLoopSimdDirective),
-                                alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_parallel_master_taskloop_simd));
-  return new (Mem)
-      OMPParallelMasterTaskLoopSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPParallelMasterTaskLoopSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_parallel_master_taskloop_simd),
+      CollapsedNum);
 }
 
 OMPDistributeDirective *OMPDistributeDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPDistributeDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
-                         sizeof(Stmt *) *
-                             numLoopChildren(CollapsedNum, OMPD_distribute));
-  OMPDistributeDirective *Dir = new (Mem)
-      OMPDistributeDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPDistributeDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_distribute), StartLoc, EndLoc,
+      CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1433,53 +1172,34 @@ OMPDistributeDirective *OMPDistributeDirective::Create(
 OMPDistributeDirective *
 OMPDistributeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
                                     unsigned CollapsedNum, EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPDistributeDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
-                         sizeof(Stmt *) *
-                             numLoopChildren(CollapsedNum, OMPD_distribute));
-  return new (Mem) OMPDistributeDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPDistributeDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_distribute), CollapsedNum);
 }
 
 OMPTargetUpdateDirective *OMPTargetUpdateDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPTargetUpdateDirective *Dir =
-      new (Mem) OMPTargetUpdateDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
-  return Dir;
+  return createDirective<OMPTargetUpdateDirective>(C, Clauses, AssociatedStmt,
+                                                   /*NumChildren=*/0, StartLoc,
+                                                   EndLoc);
 }
 
 OMPTargetUpdateDirective *
 OMPTargetUpdateDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
                                       EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
-  return new (Mem) OMPTargetUpdateDirective(NumClauses);
+  return createEmptyDirective<OMPTargetUpdateDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true);
 }
 
 OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel) {
-  unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective),
-                                alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_distribute_parallel_for));
-  OMPDistributeParallelForDirective *Dir =
-      new (Mem) OMPDistributeParallelForDirective(StartLoc, EndLoc,
-                                                  CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPDistributeParallelForDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_distribute_parallel_for) + 1, StartLoc,
+      EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1527,13 +1247,10 @@ OMPDistributeParallelForDirective::CreateEmpty(const ASTContext &C,
                                                unsigned NumClauses,
                                                unsigned CollapsedNum,
                                                EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective),
-                                alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_distribute_parallel_for));
-  return new (Mem) OMPDistributeParallelForDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPDistributeParallelForDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_distribute_parallel_for) + 1,
+      CollapsedNum);
 }
 
 OMPDistributeParallelForSimdDirective *
@@ -1541,17 +1258,10 @@ OMPDistributeParallelForSimdDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForSimdDirective),
-                                alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_distribute_parallel_for_simd));
-  OMPDistributeParallelForSimdDirective *Dir = new (Mem)
-      OMPDistributeParallelForSimdDirective(StartLoc, EndLoc, CollapsedNum,
-                                            Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPDistributeParallelForSimdDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_distribute_parallel_for_simd),
+      StartLoc, EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1597,30 +1307,20 @@ OMPDistributeParallelForSimdDirective::CreateEmpty(const ASTContext &C,
                                                    unsigned NumClauses,
                                                    unsigned CollapsedNum,
                                                    EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForSimdDirective),
-                                alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_distribute_parallel_for_simd));
-  return new (Mem)
-      OMPDistributeParallelForSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPDistributeParallelForSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_distribute_parallel_for_simd),
+      CollapsedNum);
 }
 
 OMPDistributeSimdDirective *OMPDistributeSimdDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPDistributeSimdDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_distribute_simd));
-  OMPDistributeSimdDirective *Dir = new (Mem) OMPDistributeSimdDirective(
-      StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPDistributeSimdDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_distribute_simd), StartLoc, EndLoc,
+      CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1652,30 +1352,19 @@ OMPDistributeSimdDirective *
 OMPDistributeSimdDirective::CreateEmpty(const ASTContext &C,
                                         unsigned NumClauses,
                                         unsigned CollapsedNum, EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPDistributeSimdDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_distribute_simd));
-  return new (Mem) OMPDistributeSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPDistributeSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_distribute_simd), CollapsedNum);
 }
 
 OMPTargetParallelForSimdDirective *OMPTargetParallelForSimdDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForSimdDirective),
-                                alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_target_parallel_for_simd));
-  OMPTargetParallelForSimdDirective *Dir =
-      new (Mem) OMPTargetParallelForSimdDirective(StartLoc, EndLoc,
-                                                  CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTargetParallelForSimdDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_target_parallel_for_simd), StartLoc,
+      EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1708,13 +1397,10 @@ OMPTargetParallelForSimdDirective::CreateEmpty(const ASTContext &C,
                                                unsigned NumClauses,
                                                unsigned CollapsedNum,
                                                EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForSimdDirective),
-                                alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_target_parallel_for_simd));
-  return new (Mem) OMPTargetParallelForSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTargetParallelForSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_target_parallel_for_simd),
+      CollapsedNum);
 }
 
 OMPTargetSimdDirective *
@@ -1722,15 +1408,10 @@ OMPTargetSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
                                SourceLocation EndLoc, unsigned CollapsedNum,
                                ArrayRef<OMPClause *> Clauses,
                                Stmt *AssociatedStmt, const HelperExprs &Exprs) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTargetSimdDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
-                         sizeof(Stmt *) *
-                             numLoopChildren(CollapsedNum, OMPD_target_simd));
-  OMPTargetSimdDirective *Dir = new (Mem)
-      OMPTargetSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTargetSimdDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_target_simd), StartLoc, EndLoc,
+      CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1753,27 +1434,19 @@ OMPTargetSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
 OMPTargetSimdDirective *
 OMPTargetSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
                                     unsigned CollapsedNum, EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTargetSimdDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
-                         sizeof(Stmt *) *
-                             numLoopChildren(CollapsedNum, OMPD_target_simd));
-  return new (Mem) OMPTargetSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTargetSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_target_simd), CollapsedNum);
 }
 
 OMPTeamsDistributeDirective *OMPTeamsDistributeDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTeamsDistributeDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_teams_distribute));
-  OMPTeamsDistributeDirective *Dir = new (Mem) OMPTeamsDistributeDirective(
-      StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTeamsDistributeDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_teams_distribute), StartLoc, EndLoc,
+      CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1805,29 +1478,19 @@ OMPTeamsDistributeDirective *
 OMPTeamsDistributeDirective::CreateEmpty(const ASTContext &C,
                                          unsigned NumClauses,
                                          unsigned CollapsedNum, EmptyShell) {
-  unsigned Size =
-      llvm::alignTo(sizeof(OMPTeamsDistributeDirective), alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_teams_distribute));
-  return new (Mem) OMPTeamsDistributeDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTeamsDistributeDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_teams_distribute), CollapsedNum);
 }
 
 OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  unsigned Size = llvm::alignTo(sizeof(OMPTeamsDistributeSimdDirective),
-                                alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
-                 sizeof(Stmt *) *
-                     numLoopChildren(CollapsedNum, OMPD_teams_distribute_simd));
-  OMPTeamsDistributeSimdDirective *Dir =
-      new (Mem) OMPTeamsDistributeSimdDirective(StartLoc, EndLoc, CollapsedNum,
-                                                Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTeamsDistributeSimdDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_teams_distribute_simd), StartLoc,
+      EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1858,13 +1521,9 @@ OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::Create(
 OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::CreateEmpty(
     const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
     EmptyShell) {
-  unsigned Size = llvm::alignTo(sizeof(OMPTeamsDistributeSimdDirective),
-                                alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
-                 sizeof(Stmt *) *
-                     numLoopChildren(CollapsedNum, OMPD_teams_distribute_simd));
-  return new (Mem) OMPTeamsDistributeSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTeamsDistributeSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_teams_distribute_simd), CollapsedNum);
 }
 
 OMPTeamsDistributeParallelForSimdDirective *
@@ -1872,18 +1531,10 @@ OMPTeamsDistributeParallelForSimdDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForSimdDirective),
-                            alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
-                 sizeof(Stmt *) *
-                     numLoopChildren(CollapsedNum,
-                                     OMPD_teams_distribute_parallel_for_simd));
-  OMPTeamsDistributeParallelForSimdDirective *Dir = new (Mem)
-      OMPTeamsDistributeParallelForSimdDirective(StartLoc, EndLoc, CollapsedNum,
-                                                 Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTeamsDistributeParallelForSimdDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for_simd),
+      StartLoc, EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -1929,15 +1580,10 @@ OMPTeamsDistributeParallelForSimdDirective::CreateEmpty(const ASTContext &C,
                                                         unsigned NumClauses,
                                                         unsigned CollapsedNum,
                                                         EmptyShell) {
-  auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForSimdDirective),
-                            alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
-                 sizeof(Stmt *) *
-                     numLoopChildren(CollapsedNum,
-                                     OMPD_teams_distribute_parallel_for_simd));
-  return new (Mem)
-      OMPTeamsDistributeParallelForSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTeamsDistributeParallelForSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for_simd),
+      CollapsedNum);
 }
 
 OMPTeamsDistributeParallelForDirective *
@@ -1945,17 +1591,10 @@ OMPTeamsDistributeParallelForDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel) {
-  auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective),
-                            alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for));
-  OMPTeamsDistributeParallelForDirective *Dir = new (Mem)
-      OMPTeamsDistributeParallelForDirective(StartLoc, EndLoc, CollapsedNum,
-                                             Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTeamsDistributeParallelForDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for) + 1,
+      StartLoc, EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -2003,55 +1642,35 @@ OMPTeamsDistributeParallelForDirective::CreateEmpty(const ASTContext &C,
                                                     unsigned NumClauses,
                                                     unsigned CollapsedNum,
                                                     EmptyShell) {
-  auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective),
-                            alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for));
-  return new (Mem)
-      OMPTeamsDistributeParallelForDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTeamsDistributeParallelForDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for) + 1,
+      CollapsedNum);
 }
 
 OMPTargetTeamsDirective *OMPTargetTeamsDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
-  auto Size =
-      llvm::alignTo(sizeof(OMPTargetTeamsDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
-  OMPTargetTeamsDirective *Dir =
-      new (Mem) OMPTargetTeamsDirective(StartLoc, EndLoc, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
-  return Dir;
+  return createDirective<OMPTargetTeamsDirective>(C, Clauses, AssociatedStmt,
+                                                  /*NumChildren=*/0, StartLoc,
+                                                  EndLoc);
 }
 
 OMPTargetTeamsDirective *
 OMPTargetTeamsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
                                      EmptyShell) {
-  auto Size =
-      llvm::alignTo(sizeof(OMPTargetTeamsDirective), alignof(OMPClause *));
-  void *Mem =
-      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
-  return new (Mem) OMPTargetTeamsDirective(NumClauses);
+  return createEmptyDirective<OMPTargetTeamsDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true);
 }
 
 OMPTargetTeamsDistributeDirective *OMPTargetTeamsDistributeDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeDirective),
-                            alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_target_teams_distribute));
-  OMPTargetTeamsDistributeDirective *Dir =
-      new (Mem) OMPTargetTeamsDistributeDirective(StartLoc, EndLoc, CollapsedNum,
-                                                  Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTargetTeamsDistributeDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_target_teams_distribute), StartLoc,
+      EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -2084,13 +1703,10 @@ OMPTargetTeamsDistributeDirective::CreateEmpty(const ASTContext &C,
                                                unsigned NumClauses,
                                                unsigned CollapsedNum,
                                                EmptyShell) {
-  auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeDirective),
-                            alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) *
-           numLoopChildren(CollapsedNum, OMPD_target_teams_distribute));
-  return new (Mem) OMPTargetTeamsDistributeDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTargetTeamsDistributeDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_target_teams_distribute),
+      CollapsedNum);
 }
 
 OMPTargetTeamsDistributeParallelForDirective *
@@ -2098,19 +1714,11 @@ OMPTargetTeamsDistributeParallelForDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel) {
-  auto Size =
-      llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective),
-                    alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum,
-                          OMPD_target_teams_distribute_parallel_for));
-  OMPTargetTeamsDistributeParallelForDirective *Dir =
-      new (Mem) OMPTargetTeamsDistributeParallelForDirective(
-           StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTargetTeamsDistributeParallelForDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_parallel_for) +
+          1,
+      StartLoc, EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -2158,16 +1766,11 @@ OMPTargetTeamsDistributeParallelForDirective::CreateEmpty(const ASTContext &C,
                                                           unsigned NumClauses,
                                                           unsigned CollapsedNum,
                                                           EmptyShell) {
-  auto Size =
-      llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective),
-                    alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) *
-           numLoopChildren(CollapsedNum,
-                           OMPD_target_teams_distribute_parallel_for));
-  return new (Mem)
-      OMPTargetTeamsDistributeParallelForDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTargetTeamsDistributeParallelForDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_parallel_for) +
+          1,
+      CollapsedNum);
 }
 
 OMPTargetTeamsDistributeParallelForSimdDirective *
@@ -2175,19 +1778,11 @@ OMPTargetTeamsDistributeParallelForSimdDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  auto Size =
-      llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForSimdDirective),
-                    alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum,
-                          OMPD_target_teams_distribute_parallel_for_simd));
-  OMPTargetTeamsDistributeParallelForSimdDirective *Dir =
-      new (Mem) OMPTargetTeamsDistributeParallelForSimdDirective(
-           StartLoc, EndLoc, CollapsedNum, Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTargetTeamsDistributeParallelForSimdDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum,
+                      OMPD_target_teams_distribute_parallel_for_simd),
+      StartLoc, EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -2232,16 +1827,11 @@ OMPTargetTeamsDistributeParallelForSimdDirective *
 OMPTargetTeamsDistributeParallelForSimdDirective::CreateEmpty(
     const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
     EmptyShell) {
-  auto Size =
-      llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForSimdDirective),
-                    alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum,
-                          OMPD_target_teams_distribute_parallel_for_simd));
-  return new (Mem) OMPTargetTeamsDistributeParallelForSimdDirective(
-      CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTargetTeamsDistributeParallelForSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum,
+                      OMPD_target_teams_distribute_parallel_for_simd),
+      CollapsedNum);
 }
 
 OMPTargetTeamsDistributeSimdDirective *
@@ -2249,17 +1839,10 @@ OMPTargetTeamsDistributeSimdDirective::Create(
     const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
     unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
     const HelperExprs &Exprs) {
-  auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeSimdDirective),
-                            alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * Clauses.size() +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_simd));
-  OMPTargetTeamsDistributeSimdDirective *Dir = new (Mem)
-      OMPTargetTeamsDistributeSimdDirective(StartLoc, EndLoc, CollapsedNum,
-                                            Clauses.size());
-  Dir->setClauses(Clauses);
-  Dir->setAssociatedStmt(AssociatedStmt);
+  auto *Dir = createDirective<OMPTargetTeamsDistributeSimdDirective>(
+      C, Clauses, AssociatedStmt,
+      numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_simd),
+      StartLoc, EndLoc, CollapsedNum);
   Dir->setIterationVariable(Exprs.IterationVarRef);
   Dir->setLastIteration(Exprs.LastIteration);
   Dir->setCalcLastIteration(Exprs.CalcLastIteration);
@@ -2292,12 +1875,8 @@ OMPTargetTeamsDistributeSimdDirective::CreateEmpty(const ASTContext &C,
                                                    unsigned NumClauses,
                                                    unsigned CollapsedNum,
                                                    EmptyShell) {
-  auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeSimdDirective),
-                            alignof(OMPClause *));
-  void *Mem = C.Allocate(
-      Size + sizeof(OMPClause *) * NumClauses +
-      sizeof(Stmt *) *
-          numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_simd));
-  return new (Mem)
-      OMPTargetTeamsDistributeSimdDirective(CollapsedNum, NumClauses);
+  return createEmptyDirective<OMPTargetTeamsDistributeSimdDirective>(
+      C, NumClauses, /*HasAssociatedStmt=*/true,
+      numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_simd),
+      CollapsedNum);
 }

diff  --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 0bb57171db446..4d88b39175ac4 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -4778,7 +4778,7 @@ static llvm::Function *emitOutlinedOrderedFunction(CodeGenModule &CGM,
 
 void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
   if (S.hasClausesOfKind<OMPDependClause>()) {
-    assert(!S.getAssociatedStmt() &&
+    assert(!S.hasAssociatedStmt() &&
            "No associated statement must be in ordered depend construct.");
     for (const auto *DC : S.getClausesOfKind<OMPDependClause>())
       CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC);

diff  --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index f24cb3d3f0b7d..ceb91dce186c7 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -568,9 +568,6 @@ Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
   }
 
   // Enter scope.
-  OMPDeclareMapperDecl *DMD = Actions.ActOnOpenMPDeclareMapperDirectiveStart(
-      getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
-      Range.getBegin(), VName, AS);
   DeclarationNameInfo DirName;
   SourceLocation Loc = Tok.getLocation();
   unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
@@ -579,8 +576,8 @@ Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
   Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc);
 
   // Add the mapper variable declaration.
-  Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
-      DMD, getCurScope(), MapperType, Range.getBegin(), VName);
+  ExprResult MapperVarRef = Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
+      getCurScope(), MapperType, Range.getBegin(), VName);
 
   // Parse map clauses.
   SmallVector<OMPClause *, 6> Clauses;
@@ -590,7 +587,7 @@ Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
     Actions.StartOpenMPClause(CKind);
     OMPClause *Clause =
-        ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0);
+        ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());
     if (Clause)
       Clauses.push_back(Clause);
     else
@@ -609,12 +606,13 @@ Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
   // Exit scope.
   Actions.EndOpenMPDSABlock(nullptr);
   OMPDirectiveScope.Exit();
-
-  DeclGroupPtrTy DGP =
-      Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses);
+  DeclGroupPtrTy DG = Actions.ActOnOpenMPDeclareMapperDirective(
+      getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
+      Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses);
   if (!IsCorrect)
     return DeclGroupPtrTy();
-  return DGP;
+
+  return DG;
 }
 
 TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index dc867ba8f165d..eec057b303e0d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -339,11 +339,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
   //  List-items in map clauses on this construct may only refer to the declared
   //  variable var and entities that could be referenced by a procedure defined
   //  at the same location
-  auto *DMD = dyn_cast<OMPDeclareMapperDecl>(CurContext);
-  if (LangOpts.OpenMP && DMD && !CurContext->containsDecl(D) &&
-      isa<VarDecl>(D)) {
+  if (LangOpts.OpenMP && isa<VarDecl>(D) &&
+      !isOpenMPDeclareMapperVarDeclAllowed(cast<VarDecl>(D))) {
     Diag(Loc, diag::err_omp_declare_mapper_wrong_var)
-        << DMD->getVarName().getAsString();
+        << getOpenMPDeclareMapperVarName();
     Diag(D->getLocation(), diag::note_entity_declared_at) << D;
     return true;
   }

diff  --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 0367d5c8c6016..21f52e09b39b4 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -184,6 +184,7 @@ class DSAStackTy {
     llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
     llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
         UsesAllocatorsDecls;
+    Expr *DeclareMapperVar = nullptr;
     SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
                  Scope *CurScope, SourceLocation Loc)
         : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
@@ -1072,6 +1073,15 @@ class DSAStackTy {
       return None;
     return I->getSecond();
   }
+
+  void addDeclareMapperVarRef(Expr *Ref) {
+    SharingMapTy &StackElem = getTopOfStack();
+    StackElem.DeclareMapperVar = Ref;
+  }
+  const Expr *getDeclareMapperVarRef() const {
+    const SharingMapTy *Top = getTopOfStackOrNull();
+    return Top ? Top->DeclareMapperVar : nullptr;
+  }
 };
 
 bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
@@ -17978,10 +17988,10 @@ QualType Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
   return MapperType;
 }
 
-OMPDeclareMapperDecl *Sema::ActOnOpenMPDeclareMapperDirectiveStart(
+Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareMapperDirective(
     Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
     SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
-    Decl *PrevDeclInScope) {
+    Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
   LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName,
                       forRedeclarationInCurContext());
   // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
@@ -18041,48 +18051,51 @@ OMPDeclareMapperDecl *Sema::ActOnOpenMPDeclareMapperDirectiveStart(
     Invalid = true;
   }
   auto *DMD = OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name,
-                                           MapperType, VN, PrevDMD);
-  DC->addDecl(DMD);
+                                           MapperType, VN, Clauses, PrevDMD);
+  if (S)
+    PushOnScopeChains(DMD, S);
+  else
+    DC->addDecl(DMD);
   DMD->setAccess(AS);
   if (Invalid)
     DMD->setInvalidDecl();
 
-  // Enter new function scope.
-  PushFunctionScope();
-  setFunctionHasBranchProtectedScope();
-
-  CurContext = DMD;
+  auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
+  VD->setDeclContext(DMD);
+  VD->setLexicalDeclContext(DMD);
+  DMD->addDecl(VD);
+  DMD->setMapperVarRef(MapperVarRef);
 
-  return DMD;
+  return DeclGroupPtrTy::make(DeclGroupRef(DMD));
 }
 
-void Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(OMPDeclareMapperDecl *DMD,
-                                                    Scope *S,
-                                                    QualType MapperType,
-                                                    SourceLocation StartLoc,
-                                                    DeclarationName VN) {
-  VarDecl *VD = buildVarDecl(*this, StartLoc, MapperType, VN.getAsString());
+ExprResult
+Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType,
+                                               SourceLocation StartLoc,
+                                               DeclarationName VN) {
+  TypeSourceInfo *TInfo =
+      Context.getTrivialTypeSourceInfo(MapperType, StartLoc);
+  auto *VD = VarDecl::Create(Context, Context.getTranslationUnitDecl(),
+                             StartLoc, StartLoc, VN.getAsIdentifierInfo(),
+                             MapperType, TInfo, SC_None);
   if (S)
-    PushOnScopeChains(VD, S);
-  else
-    DMD->addDecl(VD);
-  Expr *MapperVarRefExpr = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
-  DMD->setMapperVarRef(MapperVarRefExpr);
+    PushOnScopeChains(VD, S, /*AddToContext=*/false);
+  Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
+  DSAStack->addDeclareMapperVarRef(E);
+  return E;
 }
 
-Sema::DeclGroupPtrTy
-Sema::ActOnOpenMPDeclareMapperDirectiveEnd(OMPDeclareMapperDecl *D, Scope *S,
-                                           ArrayRef<OMPClause *> ClauseList) {
-  PopDeclContext();
-  PopFunctionScopeInfo();
-
-  if (D) {
-    if (S)
-      PushOnScopeChains(D, S, /*AddToContext=*/false);
-    D->CreateClauses(Context, ClauseList);
-  }
+bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
+  assert(LangOpts.OpenMP && "Expected OpenMP mode.");
+  const Expr *Ref = DSAStack->getDeclareMapperVarRef();
+  if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref))
+    return VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl();
+  return true;
+}
 
-  return DeclGroupPtrTy::make(DeclGroupRef(D));
+const ValueDecl *Sema::getOpenMPDeclareMapperVarName() const {
+  assert(LangOpts.OpenMP && "Expected OpenMP mode.");
+  return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
 }
 
 OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,

diff  --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 2efb7acb97245..81c53b06420f0 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3326,67 +3326,58 @@ TemplateDeclInstantiator::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
         SemaRef.CurrentInstantiationScope->findInstantiationOf(PrevDeclInScope)
             ->get<Decl *>());
   }
-  OMPDeclareMapperDecl *NewDMD = SemaRef.ActOnOpenMPDeclareMapperDirectiveStart(
-      /*S=*/nullptr, Owner, D->getDeclName(), SubstMapperTy, D->getLocation(),
-      VN, D->getAccess(), PrevDeclInScope);
-  SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDMD);
-  SmallVector<OMPClause *, 6> Clauses;
   bool IsCorrect = true;
-  if (!RequiresInstantiation) {
-    // Copy the mapper variable.
-    NewDMD->setMapperVarRef(D->getMapperVarRef());
-    // Copy map clauses from the original mapper.
-    for (OMPClause *C : D->clauselists())
-      Clauses.push_back(C);
-  } else {
-    // Instantiate the mapper variable.
-    DeclarationNameInfo DirName;
-    SemaRef.StartOpenMPDSABlock(llvm::omp::OMPD_declare_mapper, DirName,
-                                /*S=*/nullptr,
-                                (*D->clauselist_begin())->getBeginLoc());
-    SemaRef.ActOnOpenMPDeclareMapperDirectiveVarDecl(
-        NewDMD, /*S=*/nullptr, SubstMapperTy, D->getLocation(), VN);
-    SemaRef.CurrentInstantiationScope->InstantiatedLocal(
-        cast<DeclRefExpr>(D->getMapperVarRef())->getDecl(),
-        cast<DeclRefExpr>(NewDMD->getMapperVarRef())->getDecl());
-    auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner);
-    Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(),
-                                     ThisContext);
-    // Instantiate map clauses.
-    for (OMPClause *C : D->clauselists()) {
-      auto *OldC = cast<OMPMapClause>(C);
-      SmallVector<Expr *, 4> NewVars;
-      for (Expr *OE : OldC->varlists()) {
-        Expr *NE = SemaRef.SubstExpr(OE, TemplateArgs).get();
-        if (!NE) {
-          IsCorrect = false;
-          break;
-        }
-        NewVars.push_back(NE);
-      }
-      if (!IsCorrect)
+  SmallVector<OMPClause *, 6> Clauses;
+  // Instantiate the mapper variable.
+  DeclarationNameInfo DirName;
+  SemaRef.StartOpenMPDSABlock(llvm::omp::OMPD_declare_mapper, DirName,
+                              /*S=*/nullptr,
+                              (*D->clauselist_begin())->getBeginLoc());
+  ExprResult MapperVarRef = SemaRef.ActOnOpenMPDeclareMapperDirectiveVarDecl(
+      /*S=*/nullptr, SubstMapperTy, D->getLocation(), VN);
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(
+      cast<DeclRefExpr>(D->getMapperVarRef())->getDecl(),
+      cast<DeclRefExpr>(MapperVarRef.get())->getDecl());
+  auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner);
+  Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(),
+                                   ThisContext);
+  // Instantiate map clauses.
+  for (OMPClause *C : D->clauselists()) {
+    auto *OldC = cast<OMPMapClause>(C);
+    SmallVector<Expr *, 4> NewVars;
+    for (Expr *OE : OldC->varlists()) {
+      Expr *NE = SemaRef.SubstExpr(OE, TemplateArgs).get();
+      if (!NE) {
+        IsCorrect = false;
         break;
-      NestedNameSpecifierLoc NewQualifierLoc =
-          SemaRef.SubstNestedNameSpecifierLoc(OldC->getMapperQualifierLoc(),
-                                              TemplateArgs);
-      CXXScopeSpec SS;
-      SS.Adopt(NewQualifierLoc);
-      DeclarationNameInfo NewNameInfo = SemaRef.SubstDeclarationNameInfo(
-          OldC->getMapperIdInfo(), TemplateArgs);
-      OMPVarListLocTy Locs(OldC->getBeginLoc(), OldC->getLParenLoc(),
-                           OldC->getEndLoc());
-      OMPClause *NewC = SemaRef.ActOnOpenMPMapClause(
-          OldC->getMapTypeModifiers(), OldC->getMapTypeModifiersLoc(), SS,
-          NewNameInfo, OldC->getMapType(), OldC->isImplicitMapType(),
-          OldC->getMapLoc(), OldC->getColonLoc(), NewVars, Locs);
-      Clauses.push_back(NewC);
+      }
+      NewVars.push_back(NE);
     }
-    SemaRef.EndOpenMPDSABlock(nullptr);
-  }
-  (void)SemaRef.ActOnOpenMPDeclareMapperDirectiveEnd(NewDMD, /*S=*/nullptr,
-                                                     Clauses);
+    if (!IsCorrect)
+      break;
+    NestedNameSpecifierLoc NewQualifierLoc =
+        SemaRef.SubstNestedNameSpecifierLoc(OldC->getMapperQualifierLoc(),
+                                            TemplateArgs);
+    CXXScopeSpec SS;
+    SS.Adopt(NewQualifierLoc);
+    DeclarationNameInfo NewNameInfo =
+        SemaRef.SubstDeclarationNameInfo(OldC->getMapperIdInfo(), TemplateArgs);
+    OMPVarListLocTy Locs(OldC->getBeginLoc(), OldC->getLParenLoc(),
+                         OldC->getEndLoc());
+    OMPClause *NewC = SemaRef.ActOnOpenMPMapClause(
+        OldC->getMapTypeModifiers(), OldC->getMapTypeModifiersLoc(), SS,
+        NewNameInfo, OldC->getMapType(), OldC->isImplicitMapType(),
+        OldC->getMapLoc(), OldC->getColonLoc(), NewVars, Locs);
+    Clauses.push_back(NewC);
+  }
+  SemaRef.EndOpenMPDSABlock(nullptr);
   if (!IsCorrect)
     return nullptr;
+  Sema::DeclGroupPtrTy DG = SemaRef.ActOnOpenMPDeclareMapperDirective(
+      /*S=*/nullptr, Owner, D->getDeclName(), SubstMapperTy, D->getLocation(),
+      VN, D->getAccess(), MapperVarRef.get(), Clauses, PrevDeclInScope);
+  Decl *NewDMD = DG.get().getSingleDecl();
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDMD);
   return NewDMD;
 }
 

diff  --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index a27c36420fdbc..0b3389c4e082f 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -12932,3 +12932,20 @@ OMPTraitInfo *ASTRecordReader::readOMPTraitInfo() {
   }
   return &TI;
 }
+
+void ASTRecordReader::readOMPChildren(OMPChildren *Data) {
+  if (!Data)
+    return;
+  if (Reader->ReadingKind == ASTReader::Read_Stmt) {
+    // Skip NumClauses, NumChildren and HasAssociatedStmt fields.
+    skipInts(3);
+  }
+  SmallVector<OMPClause *, 4> Clauses(Data->getNumClauses());
+  for (unsigned I = 0, E = Data->getNumClauses(); I < E; ++I)
+    Clauses[I] = readOMPClause();
+  Data->setClauses(Clauses);
+  if (Data->hasAssociatedStmt())
+    Data->setAssociatedStmt(readStmt());
+  for (unsigned I = 0, E = Data->getNumChildren(); I < E; ++I)
+    Data->getChildren()[I] = readStmt();
+}

diff  --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 5413b28ffde25..d76182847e9de 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2652,41 +2652,18 @@ void ASTDeclReader::mergeMergeable(Mergeable<T> *D) {
 }
 
 void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
+  Record.readOMPChildren(D->Data);
   VisitDecl(D);
-  unsigned NumVars = D->varlist_size();
-  SmallVector<Expr *, 16> Vars;
-  Vars.reserve(NumVars);
-  for (unsigned i = 0; i != NumVars; ++i) {
-    Vars.push_back(Record.readExpr());
-  }
-  D->setVars(Vars);
 }
 
 void ASTDeclReader::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
+  Record.readOMPChildren(D->Data);
   VisitDecl(D);
-  unsigned NumVars = D->varlist_size();
-  unsigned NumClauses = D->clauselist_size();
-  SmallVector<Expr *, 16> Vars;
-  Vars.reserve(NumVars);
-  for (unsigned i = 0; i != NumVars; ++i) {
-    Vars.push_back(Record.readExpr());
-  }
-  D->setVars(Vars);
-  SmallVector<OMPClause *, 8> Clauses;
-  Clauses.reserve(NumClauses);
-  for (unsigned I = 0; I != NumClauses; ++I)
-    Clauses.push_back(Record.readOMPClause());
-  D->setClauses(Clauses);
 }
 
 void ASTDeclReader::VisitOMPRequiresDecl(OMPRequiresDecl * D) {
+  Record.readOMPChildren(D->Data);
   VisitDecl(D);
-  unsigned NumClauses = D->clauselist_size();
-  SmallVector<OMPClause *, 8> Clauses;
-  Clauses.reserve(NumClauses);
-  for (unsigned I = 0; I != NumClauses; ++I)
-    Clauses.push_back(Record.readOMPClause());
-  D->setClauses(Clauses);
 }
 
 void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
@@ -2707,18 +2684,10 @@ void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
 }
 
 void ASTDeclReader::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
+  Record.readOMPChildren(D->Data);
   VisitValueDecl(D);
-  D->setLocation(readSourceLocation());
-  Expr *MapperVarRefE = Record.readExpr();
-  D->setMapperVarRef(MapperVarRefE);
   D->VarName = Record.readDeclarationName();
   D->PrevDeclInScope = readDeclID();
-  unsigned NumClauses = D->clauselist_size();
-  SmallVector<OMPClause *, 8> Clauses;
-  Clauses.reserve(NumClauses);
-  for (unsigned I = 0; I != NumClauses; ++I)
-    Clauses.push_back(Record.readOMPClause());
-  D->setClauses(Clauses);
 }
 
 void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
@@ -4007,24 +3976,35 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
     // locations.
     D = ImportDecl::CreateDeserialized(Context, ID, Record.back());
     break;
-  case DECL_OMP_THREADPRIVATE:
-    D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, Record.readInt());
+  case DECL_OMP_THREADPRIVATE: {
+    Record.skipInts(1);
+    unsigned NumChildren = Record.readInt();
+    Record.skipInts(1);
+    D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, NumChildren);
     break;
+  }
   case DECL_OMP_ALLOCATE: {
-    unsigned NumVars = Record.readInt();
     unsigned NumClauses = Record.readInt();
+    unsigned NumVars = Record.readInt();
+    Record.skipInts(1);
     D = OMPAllocateDecl::CreateDeserialized(Context, ID, NumVars, NumClauses);
     break;
   }
-  case DECL_OMP_REQUIRES:
-    D = OMPRequiresDecl::CreateDeserialized(Context, ID, Record.readInt());
+  case DECL_OMP_REQUIRES: {
+    unsigned NumClauses = Record.readInt();
+    Record.skipInts(2);
+    D = OMPRequiresDecl::CreateDeserialized(Context, ID, NumClauses);
     break;
+  }
   case DECL_OMP_DECLARE_REDUCTION:
     D = OMPDeclareReductionDecl::CreateDeserialized(Context, ID);
     break;
-  case DECL_OMP_DECLARE_MAPPER:
-    D = OMPDeclareMapperDecl::CreateDeserialized(Context, ID, Record.readInt());
+  case DECL_OMP_DECLARE_MAPPER: {
+    unsigned NumClauses = Record.readInt();
+    Record.skipInts(2);
+    D = OMPDeclareMapperDecl::CreateDeserialized(Context, ID, NumClauses);
     break;
+  }
   case DECL_OMP_CAPTUREDEXPR:
     D = OMPCapturedExprDecl::CreateDeserialized(Context, ID);
     break;

diff  --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 8a7beed229c87..2715c7f3f191b 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2260,99 +2260,22 @@ void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) {
 //===----------------------------------------------------------------------===//
 
 void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
+  Record.readOMPChildren(E->Data);
   E->setLocStart(readSourceLocation());
   E->setLocEnd(readSourceLocation());
-  SmallVector<OMPClause *, 5> Clauses;
-  for (unsigned i = 0; i < E->getNumClauses(); ++i)
-    Clauses.push_back(Record.readOMPClause());
-  E->setClauses(Clauses);
-  if (E->hasAssociatedStmt())
-    E->setAssociatedStmt(Record.readSubStmt());
 }
 
 void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) {
   VisitStmt(D);
-  // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream.
-  Record.skipInts(2);
+  // Field CollapsedNum was read in ReadStmtFromStream.
+  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
-  D->setIterationVariable(Record.readSubExpr());
-  D->setLastIteration(Record.readSubExpr());
-  D->setCalcLastIteration(Record.readSubExpr());
-  D->setPreCond(Record.readSubExpr());
-  D->setCond(Record.readSubExpr());
-  D->setInit(Record.readSubExpr());
-  D->setInc(Record.readSubExpr());
-  D->setPreInits(Record.readSubStmt());
-  if (isOpenMPWorksharingDirective(D->getDirectiveKind()) ||
-      isOpenMPTaskLoopDirective(D->getDirectiveKind()) ||
-      isOpenMPDistributeDirective(D->getDirectiveKind())) {
-    D->setIsLastIterVariable(Record.readSubExpr());
-    D->setLowerBoundVariable(Record.readSubExpr());
-    D->setUpperBoundVariable(Record.readSubExpr());
-    D->setStrideVariable(Record.readSubExpr());
-    D->setEnsureUpperBound(Record.readSubExpr());
-    D->setNextLowerBound(Record.readSubExpr());
-    D->setNextUpperBound(Record.readSubExpr());
-    D->setNumIterations(Record.readSubExpr());
-  }
-  if (isOpenMPLoopBoundSharingDirective(D->getDirectiveKind())) {
-    D->setPrevLowerBoundVariable(Record.readSubExpr());
-    D->setPrevUpperBoundVariable(Record.readSubExpr());
-    D->setDistInc(Record.readSubExpr());
-    D->setPrevEnsureUpperBound(Record.readSubExpr());
-    D->setCombinedLowerBoundVariable(Record.readSubExpr());
-    D->setCombinedUpperBoundVariable(Record.readSubExpr());
-    D->setCombinedEnsureUpperBound(Record.readSubExpr());
-    D->setCombinedInit(Record.readSubExpr());
-    D->setCombinedCond(Record.readSubExpr());
-    D->setCombinedNextLowerBound(Record.readSubExpr());
-    D->setCombinedNextUpperBound(Record.readSubExpr());
-    D->setCombinedDistCond(Record.readSubExpr());
-    D->setCombinedParForInDistCond(Record.readSubExpr());
-  }
-  SmallVector<Expr *, 4> Sub;
-  unsigned CollapsedNum = D->getCollapsedNumber();
-  Sub.reserve(CollapsedNum);
-  for (unsigned i = 0; i < CollapsedNum; ++i)
-    Sub.push_back(Record.readSubExpr());
-  D->setCounters(Sub);
-  Sub.clear();
-  for (unsigned i = 0; i < CollapsedNum; ++i)
-    Sub.push_back(Record.readSubExpr());
-  D->setPrivateCounters(Sub);
-  Sub.clear();
-  for (unsigned i = 0; i < CollapsedNum; ++i)
-    Sub.push_back(Record.readSubExpr());
-  D->setInits(Sub);
-  Sub.clear();
-  for (unsigned i = 0; i < CollapsedNum; ++i)
-    Sub.push_back(Record.readSubExpr());
-  D->setUpdates(Sub);
-  Sub.clear();
-  for (unsigned i = 0; i < CollapsedNum; ++i)
-    Sub.push_back(Record.readSubExpr());
-  D->setFinals(Sub);
-  Sub.clear();
-  for (unsigned i = 0; i < CollapsedNum; ++i)
-    Sub.push_back(Record.readSubExpr());
-  D->setDependentCounters(Sub);
-  Sub.clear();
-  for (unsigned i = 0; i < CollapsedNum; ++i)
-    Sub.push_back(Record.readSubExpr());
-  D->setDependentInits(Sub);
-  Sub.clear();
-  for (unsigned i = 0; i < CollapsedNum; ++i)
-    Sub.push_back(Record.readSubExpr());
-  D->setFinalsConditions(Sub);
 }
 
 void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
-  D->setTaskReductionRefExpr(Record.readSubExpr());
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) {
@@ -2361,8 +2284,7 @@ void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) {
 
 void ASTStmtReader::VisitOMPForDirective(OMPForDirective *D) {
   VisitOMPLoopDirective(D);
-  D->setTaskReductionRefExpr(Record.readSubExpr());
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPForSimdDirective(OMPForSimdDirective *D) {
@@ -2371,23 +2293,18 @@ void ASTStmtReader::VisitOMPForSimdDirective(OMPForSimdDirective *D) {
 
 void ASTStmtReader::VisitOMPSectionsDirective(OMPSectionsDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
-  D->setTaskReductionRefExpr(Record.readSubExpr());
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPSectionDirective(OMPSectionDirective *D) {
   VisitStmt(D);
   VisitOMPExecutableDirective(D);
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPSingleDirective(OMPSingleDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
 }
 
@@ -2398,16 +2315,13 @@ void ASTStmtReader::VisitOMPMasterDirective(OMPMasterDirective *D) {
 
 void ASTStmtReader::VisitOMPCriticalDirective(OMPCriticalDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
   D->DirName = Record.readDeclarationNameInfo();
 }
 
 void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) {
   VisitOMPLoopDirective(D);
-  D->setTaskReductionRefExpr(Record.readSubExpr());
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPParallelForSimdDirective(
@@ -2418,28 +2332,20 @@ void ASTStmtReader::VisitOMPParallelForSimdDirective(
 void ASTStmtReader::VisitOMPParallelMasterDirective(
     OMPParallelMasterDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
-  D->setTaskReductionRefExpr(Record.readSubExpr());
 }
 
 void ASTStmtReader::VisitOMPParallelSectionsDirective(
     OMPParallelSectionsDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
-  D->setTaskReductionRefExpr(Record.readSubExpr());
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) {
@@ -2459,100 +2365,73 @@ void ASTStmtReader::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
 
 void ASTStmtReader::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
-  D->setReductionRef(Record.readSubExpr());
 }
 
 void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
 }
 
 void ASTStmtReader::VisitOMPDepobjDirective(OMPDepobjDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
 }
 
 void ASTStmtReader::VisitOMPScanDirective(OMPScanDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
 }
 
 void ASTStmtReader::VisitOMPOrderedDirective(OMPOrderedDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
 }
 
 void ASTStmtReader::VisitOMPAtomicDirective(OMPAtomicDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
-  D->setX(Record.readSubExpr());
-  D->setV(Record.readSubExpr());
-  D->setExpr(Record.readSubExpr());
-  D->setUpdateExpr(Record.readSubExpr());
-  D->IsXLHSInRHSPart = Record.readInt() != 0;
-  D->IsPostfixUpdate = Record.readInt() != 0;
+  D->IsXLHSInRHSPart = Record.readBool();
+  D->IsPostfixUpdate = Record.readBool();
 }
 
 void ASTStmtReader::VisitOMPTargetDirective(OMPTargetDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
 }
 
 void ASTStmtReader::VisitOMPTargetDataDirective(OMPTargetDataDirective *D) {
   VisitStmt(D);
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
 }
 
 void ASTStmtReader::VisitOMPTargetEnterDataDirective(
     OMPTargetEnterDataDirective *D) {
   VisitStmt(D);
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
 }
 
 void ASTStmtReader::VisitOMPTargetExitDataDirective(
     OMPTargetExitDataDirective *D) {
   VisitStmt(D);
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
 }
 
 void ASTStmtReader::VisitOMPTargetParallelDirective(
     OMPTargetParallelDirective *D) {
   VisitStmt(D);
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
-  D->setTaskReductionRefExpr(Record.readSubExpr());
   D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPTargetParallelForDirective(
     OMPTargetParallelForDirective *D) {
   VisitOMPLoopDirective(D);
-  D->setTaskReductionRefExpr(Record.readSubExpr());
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPTeamsDirective(OMPTeamsDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
 }
 
@@ -2560,20 +2439,18 @@ void ASTStmtReader::VisitOMPCancellationPointDirective(
     OMPCancellationPointDirective *D) {
   VisitStmt(D);
   VisitOMPExecutableDirective(D);
-  D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record.readInt()));
+  D->setCancelRegion(Record.readEnum<OpenMPDirectiveKind>());
 }
 
 void ASTStmtReader::VisitOMPCancelDirective(OMPCancelDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
-  D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record.readInt()));
+  D->setCancelRegion(Record.readEnum<OpenMPDirectiveKind>());
 }
 
 void ASTStmtReader::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *D) {
   VisitOMPLoopDirective(D);
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPTaskLoopSimdDirective(OMPTaskLoopSimdDirective *D) {
@@ -2583,7 +2460,7 @@ void ASTStmtReader::VisitOMPTaskLoopSimdDirective(OMPTaskLoopSimdDirective *D) {
 void ASTStmtReader::VisitOMPMasterTaskLoopDirective(
     OMPMasterTaskLoopDirective *D) {
   VisitOMPLoopDirective(D);
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPMasterTaskLoopSimdDirective(
@@ -2594,7 +2471,7 @@ void ASTStmtReader::VisitOMPMasterTaskLoopSimdDirective(
 void ASTStmtReader::VisitOMPParallelMasterTaskLoopDirective(
     OMPParallelMasterTaskLoopDirective *D) {
   VisitOMPLoopDirective(D);
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPParallelMasterTaskLoopSimdDirective(
@@ -2608,15 +2485,13 @@ void ASTStmtReader::VisitOMPDistributeDirective(OMPDistributeDirective *D) {
 
 void ASTStmtReader::VisitOMPTargetUpdateDirective(OMPTargetUpdateDirective *D) {
   VisitStmt(D);
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
 }
 
 void ASTStmtReader::VisitOMPDistributeParallelForDirective(
     OMPDistributeParallelForDirective *D) {
   VisitOMPLoopDirective(D);
-  D->setTaskReductionRefExpr(Record.readSubExpr());
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPDistributeParallelForSimdDirective(
@@ -2656,14 +2531,11 @@ void ASTStmtReader::VisitOMPTeamsDistributeParallelForSimdDirective(
 void ASTStmtReader::VisitOMPTeamsDistributeParallelForDirective(
     OMPTeamsDistributeParallelForDirective *D) {
   VisitOMPLoopDirective(D);
-  D->setTaskReductionRefExpr(Record.readSubExpr());
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *D) {
   VisitStmt(D);
-  // The NumClauses field was read in ReadStmtFromStream.
-  Record.skipInts(1);
   VisitOMPExecutableDirective(D);
 }
 
@@ -2675,8 +2547,7 @@ void ASTStmtReader::VisitOMPTargetTeamsDistributeDirective(
 void ASTStmtReader::VisitOMPTargetTeamsDistributeParallelForDirective(
     OMPTargetTeamsDistributeParallelForDirective *D) {
   VisitOMPLoopDirective(D);
-  D->setTaskReductionRefExpr(Record.readSubExpr());
-  D->setHasCancel(Record.readInt());
+  D->setHasCancel(Record.readBool());
 }
 
 void ASTStmtReader::VisitOMPTargetTeamsDistributeParallelForSimdDirective(
@@ -3249,24 +3120,24 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
       break;
 
     case STMT_OMP_SIMD_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPSimdDirective::CreateEmpty(Context, NumClauses,
                                         CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_FOR_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPForDirective::CreateEmpty(Context, NumClauses, CollapsedNum,
                                        Empty);
       break;
     }
 
     case STMT_OMP_FOR_SIMD_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPForSimdDirective::CreateEmpty(Context, NumClauses, CollapsedNum,
                                            Empty);
       break;
@@ -3296,16 +3167,16 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
       break;
 
     case STMT_OMP_PARALLEL_FOR_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPParallelForDirective::CreateEmpty(Context, NumClauses,
                                                CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPParallelForSimdDirective::CreateEmpty(Context, NumClauses,
                                                    CollapsedNum, Empty);
       break;
@@ -3358,10 +3229,13 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
           Context, Record[ASTStmtReader::NumStmtFields], Empty);
       break;
 
-    case STMT_OMP_ORDERED_DIRECTIVE:
-      S = OMPOrderedDirective::CreateEmpty(
-          Context, Record[ASTStmtReader::NumStmtFields], Empty);
+    case STMT_OMP_ORDERED_DIRECTIVE: {
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+      bool HasAssociatedStmt = Record[ASTStmtReader::NumStmtFields + 2];
+      S = OMPOrderedDirective::CreateEmpty(Context, NumClauses,
+                                           !HasAssociatedStmt, Empty);
       break;
+    }
 
     case STMT_OMP_ATOMIC_DIRECTIVE:
       S = OMPAtomicDirective::CreateEmpty(
@@ -3394,8 +3268,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
       break;
 
     case STMT_OMP_TARGET_PARALLEL_FOR_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPTargetParallelForDirective::CreateEmpty(Context, NumClauses,
                                                      CollapsedNum, Empty);
       break;
@@ -3421,72 +3295,72 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
       break;
 
     case STMT_OMP_TASKLOOP_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPTaskLoopDirective::CreateEmpty(Context, NumClauses, CollapsedNum,
                                             Empty);
       break;
     }
 
     case STMT_OMP_TASKLOOP_SIMD_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPTaskLoopSimdDirective::CreateEmpty(Context, NumClauses,
                                                 CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_MASTER_TASKLOOP_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPMasterTaskLoopDirective::CreateEmpty(Context, NumClauses,
                                                   CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_MASTER_TASKLOOP_SIMD_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPMasterTaskLoopSimdDirective::CreateEmpty(Context, NumClauses,
                                                       CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_PARALLEL_MASTER_TASKLOOP_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPParallelMasterTaskLoopDirective::CreateEmpty(Context, NumClauses,
                                                           CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_PARALLEL_MASTER_TASKLOOP_SIMD_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPParallelMasterTaskLoopSimdDirective::CreateEmpty(
           Context, NumClauses, CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_DISTRIBUTE_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPDistributeDirective::CreateEmpty(Context, NumClauses, CollapsedNum,
                                               Empty);
       break;
     }
 
     case STMT_OMP_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPDistributeParallelForDirective::CreateEmpty(Context, NumClauses,
                                                          CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPDistributeParallelForSimdDirective::CreateEmpty(Context, NumClauses,
                                                              CollapsedNum,
                                                              Empty);
@@ -3494,56 +3368,56 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
     }
 
     case STMT_OMP_DISTRIBUTE_SIMD_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPDistributeSimdDirective::CreateEmpty(Context, NumClauses,
                                                   CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_TARGET_PARALLEL_FOR_SIMD_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPTargetParallelForSimdDirective::CreateEmpty(Context, NumClauses,
                                                          CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_TARGET_SIMD_DIRECTIVE: {
-      auto NumClauses = Record[ASTStmtReader::NumStmtFields];
-      auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPTargetSimdDirective::CreateEmpty(Context, NumClauses, CollapsedNum,
                                               Empty);
       break;
     }
 
      case STMT_OMP_TEAMS_DISTRIBUTE_DIRECTIVE: {
-      auto NumClauses = Record[ASTStmtReader::NumStmtFields];
-      auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
-      S = OMPTeamsDistributeDirective::CreateEmpty(Context, NumClauses,
-                                                   CollapsedNum, Empty);
-      break;
+       unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+       unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
+       S = OMPTeamsDistributeDirective::CreateEmpty(Context, NumClauses,
+                                                    CollapsedNum, Empty);
+       break;
     }
 
     case STMT_OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE: {
-      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
-      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPTeamsDistributeSimdDirective::CreateEmpty(Context, NumClauses,
                                                        CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE: {
-      auto NumClauses = Record[ASTStmtReader::NumStmtFields];
-      auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPTeamsDistributeParallelForSimdDirective::CreateEmpty(
           Context, NumClauses, CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE: {
-      auto NumClauses = Record[ASTStmtReader::NumStmtFields];
-      auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPTeamsDistributeParallelForDirective::CreateEmpty(
           Context, NumClauses, CollapsedNum, Empty);
       break;
@@ -3555,32 +3429,32 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
       break;
 
     case STMT_OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE: {
-      auto NumClauses = Record[ASTStmtReader::NumStmtFields];
-      auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPTargetTeamsDistributeDirective::CreateEmpty(Context, NumClauses,
                                                          CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE: {
-      auto NumClauses = Record[ASTStmtReader::NumStmtFields];
-      auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPTargetTeamsDistributeParallelForDirective::CreateEmpty(
           Context, NumClauses, CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE: {
-      auto NumClauses = Record[ASTStmtReader::NumStmtFields];
-      auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPTargetTeamsDistributeParallelForSimdDirective::CreateEmpty(
           Context, NumClauses, CollapsedNum, Empty);
       break;
     }
 
     case STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE: {
-      auto NumClauses = Record[ASTStmtReader::NumStmtFields];
-      auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+      unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
+      unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
       S = OMPTargetTeamsDistributeSimdDirective::CreateEmpty(
           Context, NumClauses, CollapsedNum, Empty);
       break;

diff  --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 8c693b7d34fdd..8352bae32137e 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -6781,3 +6781,17 @@ void ASTRecordWriter::writeOMPTraitInfo(const OMPTraitInfo *TI) {
     }
   }
 }
+
+void ASTRecordWriter::writeOMPChildren(OMPChildren *Data) {
+  if (!Data)
+    return;
+  writeUInt32(Data->getNumClauses());
+  writeUInt32(Data->getNumChildren());
+  writeBool(Data->hasAssociatedStmt());
+  for (unsigned I = 0, E = Data->getNumClauses(); I < E; ++I)
+    writeOMPClause(Data->getClauses()[I]);
+  if (Data->hasAssociatedStmt())
+    AddStmt(Data->getAssociatedStmt());
+  for (unsigned I = 0, E = Data->getNumChildren(); I < E; ++I)
+    AddStmt(Data->getChildren()[I]);
+}

diff  --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index ec05ab772d933..2d250674057c3 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1843,29 +1843,20 @@ void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
 }
 
 void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
-  Record.push_back(D->varlist_size());
+  Record.writeOMPChildren(D->Data);
   VisitDecl(D);
-  for (auto *I : D->varlists())
-    Record.AddStmt(I);
   Code = serialization::DECL_OMP_THREADPRIVATE;
 }
 
 void ASTDeclWriter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
-  Record.push_back(D->varlist_size());
-  Record.push_back(D->clauselist_size());
+  Record.writeOMPChildren(D->Data);
   VisitDecl(D);
-  for (auto *I : D->varlists())
-    Record.AddStmt(I);
-  for (OMPClause *C : D->clauselists())
-    Record.writeOMPClause(C);
   Code = serialization::DECL_OMP_ALLOCATE;
 }
 
 void ASTDeclWriter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
-  Record.push_back(D->clauselist_size());
+  Record.writeOMPChildren(D->Data);
   VisitDecl(D);
-  for (OMPClause *C : D->clauselists())
-    Record.writeOMPClause(C);
   Code = serialization::DECL_OMP_REQUIRES;
 }
 
@@ -1884,14 +1875,10 @@ void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
 }
 
 void ASTDeclWriter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
-  Record.push_back(D->clauselist_size());
+  Record.writeOMPChildren(D->Data);
   VisitValueDecl(D);
-  Record.AddSourceLocation(D->getBeginLoc());
-  Record.AddStmt(D->getMapperVarRef());
   Record.AddDeclarationName(D->getVarName());
   Record.AddDeclRef(D->getPrevDeclInScope());
-  for (OMPClause *C : D->clauselists())
-    Record.writeOMPClause(C);
   Code = serialization::DECL_OMP_DECLARE_MAPPER;
 }
 

diff  --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index d2e5d6e44d781..d977c4e535351 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2159,85 +2159,23 @@ void ASTStmtWriter::VisitSEHLeaveStmt(SEHLeaveStmt *S) {
 //===----------------------------------------------------------------------===//
 // OpenMP Directives.
 //===----------------------------------------------------------------------===//
+
 void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
+  Record.writeOMPChildren(E->Data);
   Record.AddSourceLocation(E->getBeginLoc());
   Record.AddSourceLocation(E->getEndLoc());
-  for (unsigned i = 0; i < E->getNumClauses(); ++i) {
-    Record.writeOMPClause(E->getClause(i));
-  }
-  if (E->hasAssociatedStmt())
-    Record.AddStmt(E->getAssociatedStmt());
 }
 
 void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
-  Record.push_back(D->getCollapsedNumber());
+  Record.writeUInt32(D->getCollapsedNumber());
   VisitOMPExecutableDirective(D);
-  Record.AddStmt(D->getIterationVariable());
-  Record.AddStmt(D->getLastIteration());
-  Record.AddStmt(D->getCalcLastIteration());
-  Record.AddStmt(D->getPreCond());
-  Record.AddStmt(D->getCond());
-  Record.AddStmt(D->getInit());
-  Record.AddStmt(D->getInc());
-  Record.AddStmt(D->getPreInits());
-  if (isOpenMPWorksharingDirective(D->getDirectiveKind()) ||
-      isOpenMPTaskLoopDirective(D->getDirectiveKind()) ||
-      isOpenMPDistributeDirective(D->getDirectiveKind())) {
-    Record.AddStmt(D->getIsLastIterVariable());
-    Record.AddStmt(D->getLowerBoundVariable());
-    Record.AddStmt(D->getUpperBoundVariable());
-    Record.AddStmt(D->getStrideVariable());
-    Record.AddStmt(D->getEnsureUpperBound());
-    Record.AddStmt(D->getNextLowerBound());
-    Record.AddStmt(D->getNextUpperBound());
-    Record.AddStmt(D->getNumIterations());
-  }
-  if (isOpenMPLoopBoundSharingDirective(D->getDirectiveKind())) {
-    Record.AddStmt(D->getPrevLowerBoundVariable());
-    Record.AddStmt(D->getPrevUpperBoundVariable());
-    Record.AddStmt(D->getDistInc());
-    Record.AddStmt(D->getPrevEnsureUpperBound());
-    Record.AddStmt(D->getCombinedLowerBoundVariable());
-    Record.AddStmt(D->getCombinedUpperBoundVariable());
-    Record.AddStmt(D->getCombinedEnsureUpperBound());
-    Record.AddStmt(D->getCombinedInit());
-    Record.AddStmt(D->getCombinedCond());
-    Record.AddStmt(D->getCombinedNextLowerBound());
-    Record.AddStmt(D->getCombinedNextUpperBound());
-    Record.AddStmt(D->getCombinedDistCond());
-    Record.AddStmt(D->getCombinedParForInDistCond());
-  }
-  for (auto I : D->counters()) {
-    Record.AddStmt(I);
-  }
-  for (auto I : D->private_counters()) {
-    Record.AddStmt(I);
-  }
-  for (auto I : D->inits()) {
-    Record.AddStmt(I);
-  }
-  for (auto I : D->updates()) {
-    Record.AddStmt(I);
-  }
-  for (auto I : D->finals()) {
-    Record.AddStmt(I);
-  }
-  for (Stmt *S : D->dependent_counters())
-    Record.AddStmt(S);
-  for (Stmt *S : D->dependent_inits())
-    Record.AddStmt(S);
-  for (Stmt *S : D->finals_conditions())
-    Record.AddStmt(S);
 }
 
 void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
-  Record.AddStmt(D->getTaskReductionRefExpr());
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_PARALLEL_DIRECTIVE;
 }
 
@@ -2248,8 +2186,7 @@ void ASTStmtWriter::VisitOMPSimdDirective(OMPSimdDirective *D) {
 
 void ASTStmtWriter::VisitOMPForDirective(OMPForDirective *D) {
   VisitOMPLoopDirective(D);
-  Record.AddStmt(D->getTaskReductionRefExpr());
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_FOR_DIRECTIVE;
 }
 
@@ -2260,23 +2197,20 @@ void ASTStmtWriter::VisitOMPForSimdDirective(OMPForSimdDirective *D) {
 
 void ASTStmtWriter::VisitOMPSectionsDirective(OMPSectionsDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
-  Record.AddStmt(D->getTaskReductionRefExpr());
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_SECTIONS_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPSectionDirective(OMPSectionDirective *D) {
   VisitStmt(D);
   VisitOMPExecutableDirective(D);
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_SECTION_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPSingleDirective(OMPSingleDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Code = serialization::STMT_OMP_SINGLE_DIRECTIVE;
 }
@@ -2289,7 +2223,6 @@ void ASTStmtWriter::VisitOMPMasterDirective(OMPMasterDirective *D) {
 
 void ASTStmtWriter::VisitOMPCriticalDirective(OMPCriticalDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Record.AddDeclarationNameInfo(D->getDirectiveName());
   Code = serialization::STMT_OMP_CRITICAL_DIRECTIVE;
@@ -2297,8 +2230,7 @@ void ASTStmtWriter::VisitOMPCriticalDirective(OMPCriticalDirective *D) {
 
 void ASTStmtWriter::VisitOMPParallelForDirective(OMPParallelForDirective *D) {
   VisitOMPLoopDirective(D);
-  Record.AddStmt(D->getTaskReductionRefExpr());
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_PARALLEL_FOR_DIRECTIVE;
 }
 
@@ -2311,53 +2243,41 @@ void ASTStmtWriter::VisitOMPParallelForSimdDirective(
 void ASTStmtWriter::VisitOMPParallelMasterDirective(
     OMPParallelMasterDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
-  Record.AddStmt(D->getTaskReductionRefExpr());
   Code = serialization::STMT_OMP_PARALLEL_MASTER_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPParallelSectionsDirective(
     OMPParallelSectionsDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
-  Record.AddStmt(D->getTaskReductionRefExpr());
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPTaskDirective(OMPTaskDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_TASK_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPAtomicDirective(OMPAtomicDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
-  Record.AddStmt(D->getX());
-  Record.AddStmt(D->getV());
-  Record.AddStmt(D->getExpr());
-  Record.AddStmt(D->getUpdateExpr());
-  Record.push_back(D->isXLHSInRHSPart() ? 1 : 0);
-  Record.push_back(D->isPostfixUpdate() ? 1 : 0);
+  Record.writeBool(D->isXLHSInRHSPart());
+  Record.writeBool(D->isPostfixUpdate());
   Code = serialization::STMT_OMP_ATOMIC_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPTargetDirective(OMPTargetDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Code = serialization::STMT_OMP_TARGET_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPTargetDataDirective(OMPTargetDataDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Code = serialization::STMT_OMP_TARGET_DATA_DIRECTIVE;
 }
@@ -2365,7 +2285,6 @@ void ASTStmtWriter::VisitOMPTargetDataDirective(OMPTargetDataDirective *D) {
 void ASTStmtWriter::VisitOMPTargetEnterDataDirective(
     OMPTargetEnterDataDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Code = serialization::STMT_OMP_TARGET_ENTER_DATA_DIRECTIVE;
 }
@@ -2373,7 +2292,6 @@ void ASTStmtWriter::VisitOMPTargetEnterDataDirective(
 void ASTStmtWriter::VisitOMPTargetExitDataDirective(
     OMPTargetExitDataDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Code = serialization::STMT_OMP_TARGET_EXIT_DATA_DIRECTIVE;
 }
@@ -2381,9 +2299,7 @@ void ASTStmtWriter::VisitOMPTargetExitDataDirective(
 void ASTStmtWriter::VisitOMPTargetParallelDirective(
     OMPTargetParallelDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
-  Record.AddStmt(D->getTaskReductionRefExpr());
   Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_TARGET_PARALLEL_DIRECTIVE;
 }
@@ -2391,8 +2307,7 @@ void ASTStmtWriter::VisitOMPTargetParallelDirective(
 void ASTStmtWriter::VisitOMPTargetParallelForDirective(
     OMPTargetParallelForDirective *D) {
   VisitOMPLoopDirective(D);
-  Record.AddStmt(D->getTaskReductionRefExpr());
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_TARGET_PARALLEL_FOR_DIRECTIVE;
 }
 
@@ -2416,43 +2331,36 @@ void ASTStmtWriter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
 
 void ASTStmtWriter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
-  Record.AddStmt(D->getReductionRef());
   Code = serialization::STMT_OMP_TASKGROUP_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPFlushDirective(OMPFlushDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Code = serialization::STMT_OMP_FLUSH_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPDepobjDirective(OMPDepobjDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Code = serialization::STMT_OMP_DEPOBJ_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPScanDirective(OMPScanDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Code = serialization::STMT_OMP_SCAN_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPOrderedDirective(OMPOrderedDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Code = serialization::STMT_OMP_ORDERED_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPTeamsDirective(OMPTeamsDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Code = serialization::STMT_OMP_TEAMS_DIRECTIVE;
 }
@@ -2461,21 +2369,20 @@ void ASTStmtWriter::VisitOMPCancellationPointDirective(
     OMPCancellationPointDirective *D) {
   VisitStmt(D);
   VisitOMPExecutableDirective(D);
-  Record.push_back(uint64_t(D->getCancelRegion()));
+  Record.writeEnum(D->getCancelRegion());
   Code = serialization::STMT_OMP_CANCELLATION_POINT_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPCancelDirective(OMPCancelDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
-  Record.push_back(uint64_t(D->getCancelRegion()));
+  Record.writeEnum(D->getCancelRegion());
   Code = serialization::STMT_OMP_CANCEL_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *D) {
   VisitOMPLoopDirective(D);
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_TASKLOOP_DIRECTIVE;
 }
 
@@ -2487,7 +2394,7 @@ void ASTStmtWriter::VisitOMPTaskLoopSimdDirective(OMPTaskLoopSimdDirective *D) {
 void ASTStmtWriter::VisitOMPMasterTaskLoopDirective(
     OMPMasterTaskLoopDirective *D) {
   VisitOMPLoopDirective(D);
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_MASTER_TASKLOOP_DIRECTIVE;
 }
 
@@ -2500,7 +2407,7 @@ void ASTStmtWriter::VisitOMPMasterTaskLoopSimdDirective(
 void ASTStmtWriter::VisitOMPParallelMasterTaskLoopDirective(
     OMPParallelMasterTaskLoopDirective *D) {
   VisitOMPLoopDirective(D);
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_PARALLEL_MASTER_TASKLOOP_DIRECTIVE;
 }
 
@@ -2517,7 +2424,6 @@ void ASTStmtWriter::VisitOMPDistributeDirective(OMPDistributeDirective *D) {
 
 void ASTStmtWriter::VisitOMPTargetUpdateDirective(OMPTargetUpdateDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Code = serialization::STMT_OMP_TARGET_UPDATE_DIRECTIVE;
 }
@@ -2525,8 +2431,7 @@ void ASTStmtWriter::VisitOMPTargetUpdateDirective(OMPTargetUpdateDirective *D) {
 void ASTStmtWriter::VisitOMPDistributeParallelForDirective(
     OMPDistributeParallelForDirective *D) {
   VisitOMPLoopDirective(D);
-  Record.AddStmt(D->getTaskReductionRefExpr());
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE;
 }
 
@@ -2574,14 +2479,12 @@ void ASTStmtWriter::VisitOMPTeamsDistributeParallelForSimdDirective(
 void ASTStmtWriter::VisitOMPTeamsDistributeParallelForDirective(
     OMPTeamsDistributeParallelForDirective *D) {
   VisitOMPLoopDirective(D);
-  Record.AddStmt(D->getTaskReductionRefExpr());
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE;
 }
 
 void ASTStmtWriter::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *D) {
   VisitStmt(D);
-  Record.push_back(D->getNumClauses());
   VisitOMPExecutableDirective(D);
   Code = serialization::STMT_OMP_TARGET_TEAMS_DIRECTIVE;
 }
@@ -2595,8 +2498,7 @@ void ASTStmtWriter::VisitOMPTargetTeamsDistributeDirective(
 void ASTStmtWriter::VisitOMPTargetTeamsDistributeParallelForDirective(
     OMPTargetTeamsDistributeParallelForDirective *D) {
   VisitOMPLoopDirective(D);
-  Record.AddStmt(D->getTaskReductionRefExpr());
-  Record.push_back(D->hasCancel() ? 1 : 0);
+  Record.writeBool(D->hasCancel());
   Code = serialization::STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE;
 }
 

diff  --git a/clang/test/AST/ast-dump-openmp-ordered.c b/clang/test/AST/ast-dump-openmp-ordered.c
index cd08393e2ce81..ec397eb58ee12 100644
--- a/clang/test/AST/ast-dump-openmp-ordered.c
+++ b/clang/test/AST/ast-dump-openmp-ordered.c
@@ -74,8 +74,7 @@ void test_three(int x) {
 // CHECK-NEXT:         | | | `-DeclRefExpr {{.*}} <col:26> 'int' lvalue Var {{.*}} 'i' 'int'
 // CHECK-NEXT:         | | `-CompoundStmt {{.*}} <col:31, line:18:3>
 // CHECK-NEXT:         | |   `-OMPOrderedDirective {{.*}} <line:17:1, col:35> openmp_standalone_directive
-// CHECK-NEXT:         | |     |-OMPDependClause {{.*}} <col:21, <invalid sloc>>
-// CHECK-NEXT:         | |     `-<<<NULL>>>
+// CHECK-NEXT:         | |     `-OMPDependClause {{.*}} <col:21, <invalid sloc>>
 // CHECK-NEXT:         | |-ImplicitParamDecl {{.*}} <line:15:1> col:1 implicit __context 'struct (anonymous at {{.*}}ast-dump-openmp-ordered.c:15:1) *const restrict'
 // CHECK-NEXT:         | `-VarDecl {{.*}} <line:16:8, col:16> col:12 used i 'int' cinit
 // CHECK-NEXT:         |   `-IntegerLiteral {{.*}} <col:16> 'int' 0

diff  --git a/clang/test/OpenMP/declare_mapper_messages.c b/clang/test/OpenMP/declare_mapper_messages.c
index a7400b682f8ae..accb3d0dace11 100644
--- a/clang/test/OpenMP/declare_mapper_messages.c
+++ b/clang/test/OpenMP/declare_mapper_messages.c
@@ -23,7 +23,7 @@ struct vec {                                                            // expec
 #pragma omp declare mapper(cc:struct vec v) map(v) (                    // expected-warning {{extra tokens at the end of '#pragma omp declare mapper' are ignored}}
 
 #pragma omp declare mapper(++: struct vec v) map(v.len)                 // expected-error {{illegal OpenMP user-defined mapper identifier}}
-#pragma omp declare mapper(id1: struct vec v) map(v.len, temp)          // expected-error {{only variable v is allowed in map clauses of this 'omp declare mapper' directive}}
+#pragma omp declare mapper(id1: struct vec v) map(v.len, temp)          // expected-error {{only variable 'v' is allowed in map clauses of this 'omp declare mapper' directive}}
 #pragma omp declare mapper(default : struct vec kk) map(kk.data[0:2])   // expected-note {{previous definition is here}}
 #pragma omp declare mapper(struct vec v) map(v.len)                     // expected-error {{redefinition of user-defined mapper for type 'struct vec' with name 'default'}}
 #pragma omp declare mapper(int v) map(v)                                // expected-error {{mapper type must be of struct, union or class type}}

diff  --git a/clang/test/OpenMP/declare_mapper_messages.cpp b/clang/test/OpenMP/declare_mapper_messages.cpp
index bd91cdad8f40d..c50df694f70a3 100644
--- a/clang/test/OpenMP/declare_mapper_messages.cpp
+++ b/clang/test/OpenMP/declare_mapper_messages.cpp
@@ -30,7 +30,7 @@ class vec {
 #pragma omp declare mapper(cc: vec v) map(v) (                          // expected-warning {{extra tokens at the end of '#pragma omp declare mapper' are ignored}}
 
 #pragma omp declare mapper(++: vec v) map(v.len)                        // expected-error {{illegal OpenMP user-defined mapper identifier}}
-#pragma omp declare mapper(id1: vec v) map(v.len, temp)                 // expected-error {{only variable v is allowed in map clauses of this 'omp declare mapper' directive}}
+#pragma omp declare mapper(id1: vec v) map(v.len, temp)                 // expected-error {{only variable 'v' is allowed in map clauses of this 'omp declare mapper' directive}}
 #pragma omp declare mapper(default : vec kk) map(kk.data[0:2])          // expected-note {{previous definition is here}}
 #pragma omp declare mapper(vec v) map(v.len)                            // expected-error {{redefinition of user-defined mapper for type 'vec' with name 'default'}}
 #pragma omp declare mapper(int v) map(v)                                // expected-error {{mapper type must be of struct, union or class type}}


        


More information about the cfe-commits mailing list