[llvm] b119120 - [clang][OpenMP] Use OpenMPIRBuilder for workshare loops.

Michael Kruse via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 4 20:53:10 PST 2021


Author: Michael Kruse
Date: 2021-03-04T22:52:59-06:00
New Revision: b119120673407d87bd03c87211eec2dacd422f02

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

LOG: [clang][OpenMP] Use OpenMPIRBuilder for workshare loops.

Initial support for using the OpenMPIRBuilder by clang to generate loops using the OpenMPIRBuilder. This initial support is intentionally limited to:
 * Only the worksharing-loop directive.
 * Recognizes only the nowait clause.
 * No loop nests with more than one loop.
 * Untested with templates, exceptions.
 * Semantic checking left to the existing infrastructure.

This patch introduces a new AST node, OMPCanonicalLoop, which becomes parent of any loop that has to adheres to the restrictions as specified by the OpenMP standard. These restrictions allow OMPCanonicalLoop to provide the following additional information that depends on base language semantics:
 * The distance function: How many loop iterations there will be before entering the loop nest.
 * The loop variable function: Conversion from a logical iteration number to the loop variable.

These allow the OpenMPIRBuilder to act solely using logical iteration numbers without needing to be concerned with iterator semantics between calling the distance function and determining what the value of the loop variable ought to be. Any OpenMP logical should be done by the OpenMPIRBuilder such that it can be reused MLIR OpenMP dialect and thus by flang.

The distance and loop variable function are implemented using lambdas (or more exactly: CapturedStmt because lambda implementation is more interviewed with the parser). It is up to the OpenMPIRBuilder how they are called which depends on what is done with the loop. By default, these are emitted as outlined functions but we might think about emitting them inline as the OpenMPRuntime does.

For compatibility with the current OpenMP implementation, even though not necessary for the OpenMPIRBuilder, OMPCanonicalLoop can still be nested within OMPLoopDirectives' CapturedStmt. Although OMPCanonicalLoop's are not currently generated when the OpenMPIRBuilder is not enabled, these can just be skipped when not using the OpenMPIRBuilder in case we don't want to make the AST dependent on the EnableOMPBuilder setting.

Loop nests with more than one loop require support by the OpenMPIRBuilder (D93268). A simple implementation of non-rectangular loop nests would add another lambda function that returns whether a loop iteration of the rectangular overapproximation is also within its non-rectangular subset.

Reviewed By: jdenny

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

Added: 
    clang/test/OpenMP/irbuilder_for_iterator.cpp
    clang/test/OpenMP/irbuilder_for_rangefor.cpp
    clang/test/OpenMP/irbuilder_for_unsigned.c

Modified: 
    clang/include/clang-c/Index.h
    clang/include/clang/AST/RecursiveASTVisitor.h
    clang/include/clang/AST/StmtOpenMP.h
    clang/include/clang/Basic/StmtNodes.td
    clang/include/clang/Sema/Sema.h
    clang/include/clang/Serialization/ASTBitCodes.h
    clang/lib/AST/Stmt.cpp
    clang/lib/AST/StmtOpenMP.cpp
    clang/lib/AST/StmtPrinter.cpp
    clang/lib/AST/StmtProfile.cpp
    clang/lib/CodeGen/CGStmt.cpp
    clang/lib/CodeGen/CGStmtOpenMP.cpp
    clang/lib/CodeGen/CodeGenFunction.cpp
    clang/lib/CodeGen/CodeGenFunction.h
    clang/lib/Parse/ParseOpenMP.cpp
    clang/lib/Sema/SemaExceptionSpec.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/lib/Sema/SemaOpenMP.cpp
    clang/lib/Sema/TreeTransform.h
    clang/lib/Serialization/ASTReaderStmt.cpp
    clang/lib/Serialization/ASTWriterStmt.cpp
    clang/test/OpenMP/irbuilder_nested_parallel_for.c
    clang/tools/libclang/CIndex.cpp
    clang/tools/libclang/CXCursor.cpp
    llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
    llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
    llvm/lib/Transforms/IPO/OpenMPOpt.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 6e599f17b974..b052501c6b24 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2572,7 +2572,11 @@ enum CXCursorKind {
    */
   CXCursor_OMPTileDirective = 288,
 
-  CXCursor_LastStmt = CXCursor_OMPTileDirective,
+  /** OpenMP canonical loop.
+   */
+  CXCursor_OMPCanonicalLoop = 289,
+
+  CXCursor_LastStmt = CXCursor_OMPCanonicalLoop,
 
   /**
    * Cursor that represents the translation unit itself.

diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 78878e2eb6c5..8ec2c882a9f2 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2787,6 +2787,14 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective(
   return true;
 }
 
+DEF_TRAVERSE_STMT(OMPCanonicalLoop, {
+  if (!getDerived().shouldVisitImplicitCode()) {
+    // Visit only the syntactical loop.
+    TRY_TO(TraverseStmt(S->getLoopStmt()));
+    ShouldVisitChildren = false;
+  }
+})
+
 template <typename Derived>
 bool
 RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) {

diff  --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h
index 392fd82f51de..32b7778aa487 100644
--- a/clang/include/clang/AST/StmtOpenMP.h
+++ b/clang/include/clang/AST/StmtOpenMP.h
@@ -28,6 +28,238 @@ namespace clang {
 // AST classes for directives.
 //===----------------------------------------------------------------------===//
 
+/// Representation of an OpenMP canonical loop.
+///
+/// OpenMP 1.0 C/C++, section 2.4.1 for Construct; canonical-shape
+/// OpenMP 2.0 C/C++, section 2.4.1 for Construct; canonical-shape
+/// OpenMP 2.5, section 2.5.1 Loop Construct; canonical form
+/// OpenMP 3.1, section 2.5.1 Loop Construct; canonical form
+/// OpenMP 4.0, section 2.6 Canonical Loop Form
+/// OpenMP 4.5, section 2.6 Canonical Loop Form
+/// OpenMP 5.0, section 2.9.1 Canonical Loop Form
+/// OpenMP 5.1, section 2.11.1 Canonical Loop Nest Form
+///
+/// An OpenMP canonical loop is a for-statement or range-based for-statement
+/// with additional requirements that ensure that the number of iterations is
+/// known before entering the loop and allow skipping to an arbitrary iteration.
+/// The OMPCanonicalLoop AST node wraps a ForStmt or CXXForRangeStmt that is
+/// known to fulfill OpenMP's canonical loop requirements because of being
+/// associated to an OMPLoopBasedDirective. That is, the general structure is:
+///
+///  OMPLoopBasedDirective
+/// [`- CapturedStmt   ]
+/// [   `- CapturedDecl]
+///        ` OMPCanonicalLoop
+///          `- ForStmt/CXXForRangeStmt
+///             `- Stmt
+///
+/// One or multiple CapturedStmt/CapturedDecl pairs may be inserted by some
+/// directives such as OMPParallelForDirective, but others do not need them
+/// (such as OMPTileDirective). In  The OMPCanonicalLoop and
+/// ForStmt/CXXForRangeStmt pair is repeated for loop associated with the
+/// directive. A OMPCanonicalLoop must not appear in the AST unless associated
+/// with a OMPLoopBasedDirective. In an imperfectly nested loop nest, the
+/// OMPCanonicalLoop may also be wrapped in a CompoundStmt:
+///
+/// [...]
+///  ` OMPCanonicalLoop
+///    `- ForStmt/CXXForRangeStmt
+///       `- CompoundStmt
+///          |- Leading in-between code (if any)
+///          |- OMPCanonicalLoop
+///          |  `- ForStmt/CXXForRangeStmt
+///          |     `- ...
+///          `- Trailing in-between code (if any)
+///
+/// The leading/trailing in-between code must not itself be a OMPCanonicalLoop
+/// to avoid confusion which loop belongs to the nesting.
+///
+/// There are three 
diff erent kinds of iteration variables for 
diff erent
+/// purposes:
+/// * Loop user variable: The user-accessible variable with 
diff erent value for
+///   each iteration.
+/// * Loop iteration variable: The variable used to identify a loop iteration;
+///   for range-based for-statement, this is the hidden iterator '__begin'. For
+///   other loops, it is identical to the loop user variable. Must be a
+///   random-access iterator, pointer or integer type.
+/// * Logical iteration counter: Normalized loop counter starting at 0 and
+///   incrementing by one at each iteration. Allows abstracting over the type
+///   of the loop iteration variable and is always an unsigned integer type
+///   appropriate to represent the range of the loop iteration variable. Its
+///   value corresponds to the logical iteration number in the OpenMP
+///   specification.
+///
+/// This AST node provides two captured statements:
+/// * The distance function which computes the number of iterations.
+/// * The loop user variable function that computes the loop user variable when
+///   given a logical iteration number.
+///
+/// These captured statements provide the link between C/C++ semantics and the
+/// logical iteration counters used by the OpenMPIRBuilder which is
+/// language-agnostic and therefore does not know e.g. how to advance a
+/// random-access iterator. The OpenMPIRBuilder will use this information to
+/// apply simd, workshare-loop, distribute, taskloop and loop directives to the
+/// loop. For compatibility with the non-OpenMPIRBuilder codegen path, an
+/// OMPCanonicalLoop can itself also be wrapped into the CapturedStmts of an
+/// OMPLoopDirective and skipped when searching for the associated syntactical
+/// loop.
+///
+/// Example:
+/// <code>
+///   std::vector<std::string> Container{1,2,3};
+///   for (std::string Str : Container)
+///      Body(Str);
+/// </code>
+/// which is syntactic sugar for approximately:
+/// <code>
+///   auto &&__range = Container;
+///   auto __begin = std::begin(__range);
+///   auto __end = std::end(__range);
+///   for (; __begin != __end; ++__begin) {
+///     std::String Str = *__begin;
+///     Body(Str);
+///   }
+/// </code>
+/// In this example, the loop user variable is `Str`, the loop iteration
+/// variable is `__begin` of type `std::vector<std::string>::iterator` and the
+/// logical iteration number type is `size_t` (unsigned version of
+/// `std::vector<std::string>::iterator::
diff erence_type` aka `ptr
diff _t`).
+/// Therefore, the distance function will be
+/// <code>
+///   [&](size_t &Result) { Result = __end - __begin; }
+/// </code>
+/// and the loop variable function is
+/// <code>
+///   [&,__begin](std::vector<std::string>::iterator &Result, size_t Logical) {
+///     Result = __begin + Logical;
+///   }
+/// </code>
+/// The variable `__begin`, aka the loop iteration variable, is captured by
+/// value because it is modified in the loop body, but both functions require
+/// the initial value. The OpenMP specification explicitly leaves unspecified
+/// when the loop expressions are evaluated such that a capture by reference is
+/// sufficient.
+class OMPCanonicalLoop : public Stmt {
+  friend class ASTStmtReader;
+  friend class ASTStmtWriter;
+
+  /// Children of this AST node.
+  enum {
+    LOOP_STMT,
+    DISTANCE_FUNC,
+    LOOPVAR_FUNC,
+    LOOPVAR_REF,
+    LastSubStmt = LOOPVAR_REF
+  };
+
+private:
+  /// This AST node's children.
+  Stmt *SubStmts[LastSubStmt + 1] = {};
+
+  OMPCanonicalLoop() : Stmt(StmtClass::OMPCanonicalLoopClass) {}
+
+public:
+  /// Create a new OMPCanonicalLoop.
+  static OMPCanonicalLoop *create(const ASTContext &Ctx, Stmt *LoopStmt,
+                                  CapturedStmt *DistanceFunc,
+                                  CapturedStmt *LoopVarFunc,
+                                  DeclRefExpr *LoopVarRef) {
+    OMPCanonicalLoop *S = new (Ctx) OMPCanonicalLoop();
+    S->setLoopStmt(LoopStmt);
+    S->setDistanceFunc(DistanceFunc);
+    S->setLoopVarFunc(LoopVarFunc);
+    S->setLoopVarRef(LoopVarRef);
+    return S;
+  }
+
+  /// Create an empty OMPCanonicalLoop for deserialization.
+  static OMPCanonicalLoop *createEmpty(const ASTContext &Ctx) {
+    return new (Ctx) OMPCanonicalLoop();
+  }
+
+  static bool classof(const Stmt *S) {
+    return S->getStmtClass() == StmtClass::OMPCanonicalLoopClass;
+  }
+
+  SourceLocation getBeginLoc() const { return getLoopStmt()->getBeginLoc(); }
+  SourceLocation getEndLoc() const { return getLoopStmt()->getEndLoc(); }
+
+  /// Return this AST node's children.
+  /// @{
+  child_range children() {
+    return child_range(&SubStmts[0], &SubStmts[0] + LastSubStmt + 1);
+  }
+  const_child_range children() const {
+    return const_child_range(&SubStmts[0], &SubStmts[0] + LastSubStmt + 1);
+  }
+  /// @}
+
+  /// The wrapped syntactic loop statement (ForStmt or CXXForRangeStmt).
+  /// @{
+  Stmt *getLoopStmt() { return SubStmts[LOOP_STMT]; }
+  const Stmt *getLoopStmt() const { return SubStmts[LOOP_STMT]; }
+  void setLoopStmt(Stmt *S) {
+    assert((isa<ForStmt>(S) || isa<CXXForRangeStmt>(S)) &&
+           "Canonical loop must be a for loop (range-based or otherwise)");
+    SubStmts[LOOP_STMT] = S;
+  }
+  /// @}
+
+  /// The function that computes the number of loop iterations. Can be evaluated
+  /// before entering the loop but after the syntactical loop's init
+  /// statement(s).
+  ///
+  /// Function signature: void(LogicalTy &Result)
+  /// Any values necessary to compute the distance are captures of the closure.
+  /// @{
+  CapturedStmt *getDistanceFunc() {
+    return cast<CapturedStmt>(SubStmts[DISTANCE_FUNC]);
+  }
+  const CapturedStmt *getDistanceFunc() const {
+    return cast<CapturedStmt>(SubStmts[DISTANCE_FUNC]);
+  }
+  void setDistanceFunc(CapturedStmt *S) {
+    assert(S && "Expected non-null captured statement");
+    SubStmts[DISTANCE_FUNC] = S;
+  }
+  /// @}
+
+  /// The function that computes the loop user variable from a logical iteration
+  /// counter. Can be evaluated as first statement in the loop.
+  ///
+  /// Function signature: void(LoopVarTy &Result, LogicalTy Number)
+  /// Any other values required to compute the loop user variable (such as start
+  /// value, step size) are captured by the closure. In particular, the initial
+  /// value of loop iteration variable is captured by value to be unaffected by
+  /// previous iterations.
+  /// @{
+  CapturedStmt *getLoopVarFunc() {
+    return cast<CapturedStmt>(SubStmts[LOOPVAR_FUNC]);
+  }
+  const CapturedStmt *getLoopVarFunc() const {
+    return cast<CapturedStmt>(SubStmts[LOOPVAR_FUNC]);
+  }
+  void setLoopVarFunc(CapturedStmt *S) {
+    assert(S && "Expected non-null captured statement");
+    SubStmts[LOOPVAR_FUNC] = S;
+  }
+  /// @}
+
+  /// Reference to the loop user variable as accessed in the loop body.
+  /// @{
+  DeclRefExpr *getLoopVarRef() {
+    return cast<DeclRefExpr>(SubStmts[LOOPVAR_REF]);
+  }
+  const DeclRefExpr *getLoopVarRef() const {
+    return cast<DeclRefExpr>(SubStmts[LOOPVAR_REF]);
+  }
+  void setLoopVarRef(DeclRefExpr *E) {
+    assert(E && "Expected non-null loop variable");
+    SubStmts[LOOPVAR_REF] = E;
+  }
+  /// @}
+};
+
 /// This is a basic class for representing single OpenMP executable
 /// directive.
 ///

diff  --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index 40bad92b01e9..66df4d363e0e 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -216,6 +216,7 @@ def MSDependentExistsStmt : StmtNode<Stmt>;
 def AsTypeExpr : StmtNode<Expr>;
 
 // OpenMP Directives.
+def OMPCanonicalLoop : StmtNode<Stmt>;
 def OMPExecutableDirective : StmtNode<Stmt, 1>;
 def OMPLoopBasedDirective : StmtNode<OMPExecutableDirective, 1>;
 def OMPLoopDirective : StmtNode<OMPLoopBasedDirective, 1>;

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 44eaa7948a7e..f44b6e33e8f9 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10486,6 +10486,11 @@ class Sema final {
 
   /// Initialization of captured region for OpenMP region.
   void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
+
+  /// Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to
+  /// an OpenMP loop directive.
+  StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt);
+
   /// End of OpenMP region.
   ///
   /// \param S Statement associated with the current OpenMP region.

diff  --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 0f8c14e36e63..03ec8da289de 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -109,2021 +109,2015 @@ class TypeIdx {
   }
 };
 
-    /// A structure for putting "fast"-unqualified QualTypes into a
-    /// DenseMap.  This uses the standard pointer hash function.
-    struct UnsafeQualTypeDenseMapInfo {
-      static bool isEqual(QualType A, QualType B) { return A == B; }
-
-      static QualType getEmptyKey() {
-        return QualType::getFromOpaquePtr((void*) 1);
-      }
-
-      static QualType getTombstoneKey() {
-        return QualType::getFromOpaquePtr((void*) 2);
-      }
-
-      static unsigned getHashValue(QualType T) {
-        assert(!T.getLocalFastQualifiers() &&
-               "hash invalid for types with fast quals");
-        uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
-        return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
-      }
-    };
-
-    /// An ID number that refers to an identifier in an AST file.
-    using IdentID = uint32_t;
-
-    /// The number of predefined identifier IDs.
-    const unsigned int NUM_PREDEF_IDENT_IDS = 1;
-
-    /// An ID number that refers to a macro in an AST file.
-    using MacroID = uint32_t;
-
-    /// A global ID number that refers to a macro in an AST file.
-    using GlobalMacroID = uint32_t;
-
-    /// A local to a module ID number that refers to a macro in an
-    /// AST file.
-    using LocalMacroID = uint32_t;
-
-    /// The number of predefined macro IDs.
-    const unsigned int NUM_PREDEF_MACRO_IDS = 1;
-
-    /// An ID number that refers to an ObjC selector in an AST file.
-    using SelectorID = uint32_t;
-
-    /// The number of predefined selector IDs.
-    const unsigned int NUM_PREDEF_SELECTOR_IDS = 1;
-
-    /// An ID number that refers to a set of CXXBaseSpecifiers in an
-    /// AST file.
-    using CXXBaseSpecifiersID = uint32_t;
-
-    /// An ID number that refers to a list of CXXCtorInitializers in an
-    /// AST file.
-    using CXXCtorInitializersID = uint32_t;
-
-    /// An ID number that refers to an entity in the detailed
-    /// preprocessing record.
-    using PreprocessedEntityID = uint32_t;
-
-    /// An ID number that refers to a submodule in a module file.
-    using SubmoduleID = uint32_t;
-
-    /// The number of predefined submodule IDs.
-    const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1;
-
-    /// Source range/offset of a preprocessed entity.
-    struct PPEntityOffset {
-      /// Raw source location of beginning of range.
-      unsigned Begin;
-
-      /// Raw source location of end of range.
-      unsigned End;
-
-      /// Offset in the AST file relative to ModuleFile::MacroOffsetsBase.
-      uint32_t BitOffset;
-
-      PPEntityOffset(SourceRange R, uint32_t BitOffset)
-        : Begin(R.getBegin().getRawEncoding()),
-          End(R.getEnd().getRawEncoding()), BitOffset(BitOffset) {}
-
-      SourceLocation getBegin() const {
-        return SourceLocation::getFromRawEncoding(Begin);
-      }
-
-      SourceLocation getEnd() const {
-        return SourceLocation::getFromRawEncoding(End);
-      }
-    };
-
-    /// Source range of a skipped preprocessor region
-    struct PPSkippedRange {
-      /// Raw source location of beginning of range.
-      unsigned Begin;
-      /// Raw source location of end of range.
-      unsigned End;
-
-      PPSkippedRange(SourceRange R)
-        : Begin(R.getBegin().getRawEncoding()),
-          End(R.getEnd().getRawEncoding()) { }
-
-      SourceLocation getBegin() const {
-        return SourceLocation::getFromRawEncoding(Begin);
-      }
-      SourceLocation getEnd() const {
-        return SourceLocation::getFromRawEncoding(End);
-      }
-    };
-
-    /// Offset in the AST file. Use splitted 64-bit integer into low/high
-    /// parts to keep structure alignment 32-bit (it is important because
-    /// blobs in bitstream are 32-bit aligned). This structure is serialized
-    /// "as is" to the AST file.
-    struct UnderalignedInt64 {
-      uint32_t BitOffsetLow = 0;
-      uint32_t BitOffsetHigh = 0;
-
-      UnderalignedInt64() = default;
-      UnderalignedInt64(uint64_t BitOffset) { setBitOffset(BitOffset); }
-
-      void setBitOffset(uint64_t Offset) {
-        BitOffsetLow = Offset;
-        BitOffsetHigh = Offset >> 32;
-      }
-
-      uint64_t getBitOffset() const {
-        return BitOffsetLow | (uint64_t(BitOffsetHigh) << 32);
-      }
-    };
-
-    /// Source location and bit offset of a declaration.
-    struct DeclOffset {
-      /// Raw source location.
-      unsigned Loc = 0;
-
-      /// Offset relative to the start of the DECLTYPES_BLOCK block. Keep
-      /// structure alignment 32-bit and avoid padding gap because undefined
-      /// value in the padding affects AST hash.
-      UnderalignedInt64 BitOffset;
-
-      DeclOffset() = default;
-      DeclOffset(SourceLocation Loc, uint64_t BitOffset,
-                 uint64_t DeclTypesBlockStartOffset) {
-        setLocation(Loc);
-        setBitOffset(BitOffset, DeclTypesBlockStartOffset);
-      }
-
-      void setLocation(SourceLocation L) {
-        Loc = L.getRawEncoding();
-      }
-
-      SourceLocation getLocation() const {
-        return SourceLocation::getFromRawEncoding(Loc);
-      }
-
-      void setBitOffset(uint64_t Offset,
-                        const uint64_t DeclTypesBlockStartOffset) {
-        BitOffset.setBitOffset(Offset - DeclTypesBlockStartOffset);
-      }
-
-      uint64_t getBitOffset(const uint64_t DeclTypesBlockStartOffset) const {
-        return BitOffset.getBitOffset() + DeclTypesBlockStartOffset;
-      }
-    };
-
-    /// The number of predefined preprocessed entity IDs.
-    const unsigned int NUM_PREDEF_PP_ENTITY_IDS = 1;
-
-    /// Describes the various kinds of blocks that occur within
-    /// an AST file.
-    enum BlockIDs {
-      /// The AST block, which acts as a container around the
-      /// full AST block.
-      AST_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
-
-      /// The block containing information about the source
-      /// manager.
-      SOURCE_MANAGER_BLOCK_ID,
-
-      /// The block containing information about the
-      /// preprocessor.
-      PREPROCESSOR_BLOCK_ID,
-
-      /// The block containing the definitions of all of the
-      /// types and decls used within the AST file.
-      DECLTYPES_BLOCK_ID,
-
-      /// The block containing the detailed preprocessing record.
-      PREPROCESSOR_DETAIL_BLOCK_ID,
-
-      /// The block containing the submodule structure.
-      SUBMODULE_BLOCK_ID,
-
-      /// The block containing comments.
-      COMMENTS_BLOCK_ID,
-
-      /// The control block, which contains all of the
-      /// information that needs to be validated prior to committing
-      /// to loading the AST file.
-      CONTROL_BLOCK_ID,
-
-      /// The block of input files, which were used as inputs
-      /// to create this AST file.
-      ///
-      /// This block is part of the control block.
-      INPUT_FILES_BLOCK_ID,
-
-      /// The block of configuration options, used to check that
-      /// a module is being used in a configuration compatible with the
-      /// configuration in which it was built.
-      ///
-      /// This block is part of the control block.
-      OPTIONS_BLOCK_ID,
-
-      /// A block containing a module file extension.
-      EXTENSION_BLOCK_ID,
-
-      /// A block with unhashed content.
-      ///
-      /// These records should not change the \a ASTFileSignature.  See \a
-      /// UnhashedControlBlockRecordTypes for the list of records.
-      UNHASHED_CONTROL_BLOCK_ID,
-    };
-
-    /// Record types that occur within the control block.
-    enum ControlRecordTypes {
-      /// AST file metadata, including the AST file version number
-      /// and information about the compiler used to build this AST file.
-      METADATA = 1,
-
-      /// Record code for the list of other AST files imported by
-      /// this AST file.
-      IMPORTS,
-
-      /// Record code for the original file that was used to
-      /// generate the AST file, including both its file ID and its
-      /// name.
-      ORIGINAL_FILE,
-
-      /// The directory that the PCH was originally created in.
-      ORIGINAL_PCH_DIR,
-
-      /// Record code for file ID of the file or buffer that was used to
-      /// generate the AST file.
-      ORIGINAL_FILE_ID,
-
-      /// Offsets into the input-files block where input files
-      /// reside.
-      INPUT_FILE_OFFSETS,
-
-      /// Record code for the module name.
-      MODULE_NAME,
-
-      /// Record code for the module map file that was used to build this
-      /// AST file.
-      MODULE_MAP_FILE,
-
-      /// Record code for the module build directory.
-      MODULE_DIRECTORY,
-    };
-
-    /// Record types that occur within the options block inside
-    /// the control block.
-    enum OptionsRecordTypes {
-      /// Record code for the language options table.
-      ///
-      /// The record with this code contains the contents of the
-      /// LangOptions structure. We serialize the entire contents of
-      /// the structure, and let the reader decide which options are
-      /// actually important to check.
-      LANGUAGE_OPTIONS = 1,
-
-      /// Record code for the target options table.
-      TARGET_OPTIONS,
-
-      /// Record code for the filesystem options table.
-      FILE_SYSTEM_OPTIONS,
-
-      /// Record code for the headers search options table.
-      HEADER_SEARCH_OPTIONS,
-
-      /// Record code for the preprocessor options table.
-      PREPROCESSOR_OPTIONS,
-    };
-
-    /// Record codes for the unhashed control block.
-    enum UnhashedControlBlockRecordTypes {
-      /// Record code for the signature that identifiers this AST file.
-      SIGNATURE = 1,
-
-      /// Record code for the content hash of the AST block.
-      AST_BLOCK_HASH,
-
-      /// Record code for the diagnostic options table.
-      DIAGNOSTIC_OPTIONS,
-
-      /// Record code for \#pragma diagnostic mappings.
-      DIAG_PRAGMA_MAPPINGS,
-    };
-
-    /// Record code for extension blocks.
-    enum ExtensionBlockRecordTypes {
-      /// Metadata describing this particular extension.
-      EXTENSION_METADATA = 1,
-
-      /// The first record ID allocated to the extensions themselves.
-      FIRST_EXTENSION_RECORD_ID = 4
-    };
-
-    /// Record types that occur within the input-files block
-    /// inside the control block.
-    enum InputFileRecordTypes {
-      /// An input file.
-      INPUT_FILE = 1,
-
-      /// The input file content hash
-      INPUT_FILE_HASH
-    };
-
-    /// Record types that occur within the AST block itself.
-    enum ASTRecordTypes {
-      /// Record code for the offsets of each type.
-      ///
-      /// The TYPE_OFFSET constant describes the record that occurs
-      /// within the AST block. The record itself is an array of offsets that
-      /// point into the declarations and types block (identified by
-      /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID
-      /// of a type. For a given type ID @c T, the lower three bits of
-      /// @c T are its qualifiers (const, volatile, restrict), as in
-      /// the QualType class. The upper bits, after being shifted and
-      /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the
-      /// TYPE_OFFSET block to determine the offset of that type's
-      /// corresponding record within the DECLTYPES_BLOCK_ID block.
-      TYPE_OFFSET = 1,
-
-      /// Record code for the offsets of each decl.
-      ///
-      /// The DECL_OFFSET constant describes the record that occurs
-      /// within the block identified by DECL_OFFSETS_BLOCK_ID within
-      /// the AST block. The record itself is an array of offsets that
-      /// point into the declarations and types block (identified by
-      /// DECLTYPES_BLOCK_ID). The declaration ID is an index into this
-      /// record, after subtracting one to account for the use of
-      /// declaration ID 0 for a NULL declaration pointer. Index 0 is
-      /// reserved for the translation unit declaration.
-      DECL_OFFSET = 2,
-
-      /// Record code for the table of offsets of each
-      /// identifier ID.
-      ///
-      /// The offset table contains offsets into the blob stored in
-      /// the IDENTIFIER_TABLE record. Each offset points to the
-      /// NULL-terminated string that corresponds to that identifier.
-      IDENTIFIER_OFFSET = 3,
-
-      /// This is so that older clang versions, before the introduction
-      /// of the control block, can read and reject the newer PCH format.
-      /// *DON'T CHANGE THIS NUMBER*.
-      METADATA_OLD_FORMAT = 4,
-
-      /// Record code for the identifier table.
-      ///
-      /// The identifier table is a simple blob that contains
-      /// NULL-terminated strings for all of the identifiers
-      /// referenced by the AST file. The IDENTIFIER_OFFSET table
-      /// contains the mapping from identifier IDs to the characters
-      /// in this blob. Note that the starting offsets of all of the
-      /// identifiers are odd, so that, when the identifier offset
-      /// table is loaded in, we can use the low bit to distinguish
-      /// between offsets (for unresolved identifier IDs) and
-      /// IdentifierInfo pointers (for already-resolved identifier
-      /// IDs).
-      IDENTIFIER_TABLE = 5,
-
-      /// Record code for the array of eagerly deserialized decls.
-      ///
-      /// The AST file contains a list of all of the declarations that should be
-      /// eagerly deserialized present within the parsed headers, stored as an
-      /// array of declaration IDs. These declarations will be
-      /// reported to the AST consumer after the AST file has been
-      /// read, since their presence can affect the semantics of the
-      /// program (e.g., for code generation).
-      EAGERLY_DESERIALIZED_DECLS = 6,
-
-      /// Record code for the set of non-builtin, special
-      /// types.
-      ///
-      /// This record contains the type IDs for the various type nodes
-      /// that are constructed during semantic analysis (e.g.,
-      /// __builtin_va_list). The SPECIAL_TYPE_* constants provide
-      /// offsets into this record.
-      SPECIAL_TYPES = 7,
-
-      /// Record code for the extra statistics we gather while
-      /// generating an AST file.
-      STATISTICS = 8,
-
-      /// Record code for the array of tentative definitions.
-      TENTATIVE_DEFINITIONS = 9,
-
-      // ID 10 used to be for a list of extern "C" declarations.
-
-      /// Record code for the table of offsets into the
-      /// Objective-C method pool.
-      SELECTOR_OFFSETS = 11,
-
-      /// Record code for the Objective-C method pool,
-      METHOD_POOL = 12,
-
-      /// The value of the next __COUNTER__ to dispense.
-      /// [PP_COUNTER_VALUE, Val]
-      PP_COUNTER_VALUE = 13,
-
-      /// Record code for the table of offsets into the block
-      /// of source-location information.
-      SOURCE_LOCATION_OFFSETS = 14,
-
-      /// Record code for the set of source location entries
-      /// that need to be preloaded by the AST reader.
-      ///
-      /// This set contains the source location entry for the
-      /// predefines buffer and for any file entries that need to be
-      /// preloaded.
-      SOURCE_LOCATION_PRELOADS = 15,
-
-      /// Record code for the set of ext_vector type names.
-      EXT_VECTOR_DECLS = 16,
-
-      /// Record code for the array of unused file scoped decls.
-      UNUSED_FILESCOPED_DECLS = 17,
-
-      /// Record code for the table of offsets to entries in the
-      /// preprocessing record.
-      PPD_ENTITIES_OFFSETS = 18,
-
-      /// Record code for the array of VTable uses.
-      VTABLE_USES = 19,
-
-      // ID 20 used to be for a list of dynamic classes.
-
-      /// Record code for referenced selector pool.
-      REFERENCED_SELECTOR_POOL = 21,
-
-      /// Record code for an update to the TU's lexically contained
-      /// declarations.
-      TU_UPDATE_LEXICAL = 22,
-
-      // ID 23 used to be for a list of local redeclarations.
-
-      /// Record code for declarations that Sema keeps references of.
-      SEMA_DECL_REFS = 24,
-
-      /// Record code for weak undeclared identifiers.
-      WEAK_UNDECLARED_IDENTIFIERS = 25,
+/// A structure for putting "fast"-unqualified QualTypes into a
+/// DenseMap.  This uses the standard pointer hash function.
+struct UnsafeQualTypeDenseMapInfo {
+  static bool isEqual(QualType A, QualType B) { return A == B; }
 
-      /// Record code for pending implicit instantiations.
-      PENDING_IMPLICIT_INSTANTIATIONS = 26,
+  static QualType getEmptyKey() {
+    return QualType::getFromOpaquePtr((void *)1);
+  }
+
+  static QualType getTombstoneKey() {
+    return QualType::getFromOpaquePtr((void *)2);
+  }
+
+  static unsigned getHashValue(QualType T) {
+    assert(!T.getLocalFastQualifiers() &&
+           "hash invalid for types with fast quals");
+    uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+    return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
+  }
+};
+
+/// An ID number that refers to an identifier in an AST file.
+using IdentID = uint32_t;
+
+/// The number of predefined identifier IDs.
+const unsigned int NUM_PREDEF_IDENT_IDS = 1;
+
+/// An ID number that refers to a macro in an AST file.
+using MacroID = uint32_t;
+
+/// A global ID number that refers to a macro in an AST file.
+using GlobalMacroID = uint32_t;
+
+/// A local to a module ID number that refers to a macro in an
+/// AST file.
+using LocalMacroID = uint32_t;
+
+/// The number of predefined macro IDs.
+const unsigned int NUM_PREDEF_MACRO_IDS = 1;
+
+/// An ID number that refers to an ObjC selector in an AST file.
+using SelectorID = uint32_t;
+
+/// The number of predefined selector IDs.
+const unsigned int NUM_PREDEF_SELECTOR_IDS = 1;
+
+/// An ID number that refers to a set of CXXBaseSpecifiers in an
+/// AST file.
+using CXXBaseSpecifiersID = uint32_t;
+
+/// An ID number that refers to a list of CXXCtorInitializers in an
+/// AST file.
+using CXXCtorInitializersID = uint32_t;
+
+/// An ID number that refers to an entity in the detailed
+/// preprocessing record.
+using PreprocessedEntityID = uint32_t;
+
+/// An ID number that refers to a submodule in a module file.
+using SubmoduleID = uint32_t;
+
+/// The number of predefined submodule IDs.
+const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1;
+
+/// Source range/offset of a preprocessed entity.
+struct PPEntityOffset {
+  /// Raw source location of beginning of range.
+  unsigned Begin;
+
+  /// Raw source location of end of range.
+  unsigned End;
+
+  /// Offset in the AST file relative to ModuleFile::MacroOffsetsBase.
+  uint32_t BitOffset;
+
+  PPEntityOffset(SourceRange R, uint32_t BitOffset)
+      : Begin(R.getBegin().getRawEncoding()), End(R.getEnd().getRawEncoding()),
+        BitOffset(BitOffset) {}
+
+  SourceLocation getBegin() const {
+    return SourceLocation::getFromRawEncoding(Begin);
+  }
+
+  SourceLocation getEnd() const {
+    return SourceLocation::getFromRawEncoding(End);
+  }
+};
+
+/// Source range of a skipped preprocessor region
+struct PPSkippedRange {
+  /// Raw source location of beginning of range.
+  unsigned Begin;
+  /// Raw source location of end of range.
+  unsigned End;
+
+  PPSkippedRange(SourceRange R)
+      : Begin(R.getBegin().getRawEncoding()), End(R.getEnd().getRawEncoding()) {
+  }
+
+  SourceLocation getBegin() const {
+    return SourceLocation::getFromRawEncoding(Begin);
+  }
+  SourceLocation getEnd() const {
+    return SourceLocation::getFromRawEncoding(End);
+  }
+};
+
+/// Offset in the AST file. Use splitted 64-bit integer into low/high
+/// parts to keep structure alignment 32-bit (it is important because
+/// blobs in bitstream are 32-bit aligned). This structure is serialized
+/// "as is" to the AST file.
+struct UnderalignedInt64 {
+  uint32_t BitOffsetLow = 0;
+  uint32_t BitOffsetHigh = 0;
+
+  UnderalignedInt64() = default;
+  UnderalignedInt64(uint64_t BitOffset) { setBitOffset(BitOffset); }
+
+  void setBitOffset(uint64_t Offset) {
+    BitOffsetLow = Offset;
+    BitOffsetHigh = Offset >> 32;
+  }
+
+  uint64_t getBitOffset() const {
+    return BitOffsetLow | (uint64_t(BitOffsetHigh) << 32);
+  }
+};
+
+/// Source location and bit offset of a declaration.
+struct DeclOffset {
+  /// Raw source location.
+  unsigned Loc = 0;
+
+  /// Offset relative to the start of the DECLTYPES_BLOCK block. Keep
+  /// structure alignment 32-bit and avoid padding gap because undefined
+  /// value in the padding affects AST hash.
+  UnderalignedInt64 BitOffset;
+
+  DeclOffset() = default;
+  DeclOffset(SourceLocation Loc, uint64_t BitOffset,
+             uint64_t DeclTypesBlockStartOffset) {
+    setLocation(Loc);
+    setBitOffset(BitOffset, DeclTypesBlockStartOffset);
+  }
+
+  void setLocation(SourceLocation L) { Loc = L.getRawEncoding(); }
+
+  SourceLocation getLocation() const {
+    return SourceLocation::getFromRawEncoding(Loc);
+  }
+
+  void setBitOffset(uint64_t Offset, const uint64_t DeclTypesBlockStartOffset) {
+    BitOffset.setBitOffset(Offset - DeclTypesBlockStartOffset);
+  }
+
+  uint64_t getBitOffset(const uint64_t DeclTypesBlockStartOffset) const {
+    return BitOffset.getBitOffset() + DeclTypesBlockStartOffset;
+  }
+};
+
+/// The number of predefined preprocessed entity IDs.
+const unsigned int NUM_PREDEF_PP_ENTITY_IDS = 1;
+
+/// Describes the various kinds of blocks that occur within
+/// an AST file.
+enum BlockIDs {
+  /// The AST block, which acts as a container around the
+  /// full AST block.
+  AST_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
+
+  /// The block containing information about the source
+  /// manager.
+  SOURCE_MANAGER_BLOCK_ID,
+
+  /// The block containing information about the
+  /// preprocessor.
+  PREPROCESSOR_BLOCK_ID,
+
+  /// The block containing the definitions of all of the
+  /// types and decls used within the AST file.
+  DECLTYPES_BLOCK_ID,
+
+  /// The block containing the detailed preprocessing record.
+  PREPROCESSOR_DETAIL_BLOCK_ID,
+
+  /// The block containing the submodule structure.
+  SUBMODULE_BLOCK_ID,
+
+  /// The block containing comments.
+  COMMENTS_BLOCK_ID,
+
+  /// The control block, which contains all of the
+  /// information that needs to be validated prior to committing
+  /// to loading the AST file.
+  CONTROL_BLOCK_ID,
+
+  /// The block of input files, which were used as inputs
+  /// to create this AST file.
+  ///
+  /// This block is part of the control block.
+  INPUT_FILES_BLOCK_ID,
+
+  /// The block of configuration options, used to check that
+  /// a module is being used in a configuration compatible with the
+  /// configuration in which it was built.
+  ///
+  /// This block is part of the control block.
+  OPTIONS_BLOCK_ID,
+
+  /// A block containing a module file extension.
+  EXTENSION_BLOCK_ID,
+
+  /// A block with unhashed content.
+  ///
+  /// These records should not change the \a ASTFileSignature.  See \a
+  /// UnhashedControlBlockRecordTypes for the list of records.
+  UNHASHED_CONTROL_BLOCK_ID,
+};
+
+/// Record types that occur within the control block.
+enum ControlRecordTypes {
+  /// AST file metadata, including the AST file version number
+  /// and information about the compiler used to build this AST file.
+  METADATA = 1,
+
+  /// Record code for the list of other AST files imported by
+  /// this AST file.
+  IMPORTS,
+
+  /// Record code for the original file that was used to
+  /// generate the AST file, including both its file ID and its
+  /// name.
+  ORIGINAL_FILE,
+
+  /// The directory that the PCH was originally created in.
+  ORIGINAL_PCH_DIR,
+
+  /// Record code for file ID of the file or buffer that was used to
+  /// generate the AST file.
+  ORIGINAL_FILE_ID,
+
+  /// Offsets into the input-files block where input files
+  /// reside.
+  INPUT_FILE_OFFSETS,
+
+  /// Record code for the module name.
+  MODULE_NAME,
+
+  /// Record code for the module map file that was used to build this
+  /// AST file.
+  MODULE_MAP_FILE,
+
+  /// Record code for the module build directory.
+  MODULE_DIRECTORY,
+};
+
+/// Record types that occur within the options block inside
+/// the control block.
+enum OptionsRecordTypes {
+  /// Record code for the language options table.
+  ///
+  /// The record with this code contains the contents of the
+  /// LangOptions structure. We serialize the entire contents of
+  /// the structure, and let the reader decide which options are
+  /// actually important to check.
+  LANGUAGE_OPTIONS = 1,
+
+  /// Record code for the target options table.
+  TARGET_OPTIONS,
+
+  /// Record code for the filesystem options table.
+  FILE_SYSTEM_OPTIONS,
+
+  /// Record code for the headers search options table.
+  HEADER_SEARCH_OPTIONS,
+
+  /// Record code for the preprocessor options table.
+  PREPROCESSOR_OPTIONS,
+};
+
+/// Record codes for the unhashed control block.
+enum UnhashedControlBlockRecordTypes {
+  /// Record code for the signature that identifiers this AST file.
+  SIGNATURE = 1,
+
+  /// Record code for the content hash of the AST block.
+  AST_BLOCK_HASH,
+
+  /// Record code for the diagnostic options table.
+  DIAGNOSTIC_OPTIONS,
+
+  /// Record code for \#pragma diagnostic mappings.
+  DIAG_PRAGMA_MAPPINGS,
+};
+
+/// Record code for extension blocks.
+enum ExtensionBlockRecordTypes {
+  /// Metadata describing this particular extension.
+  EXTENSION_METADATA = 1,
+
+  /// The first record ID allocated to the extensions themselves.
+  FIRST_EXTENSION_RECORD_ID = 4
+};
 
-      // ID 27 used to be for a list of replacement decls.
+/// Record types that occur within the input-files block
+/// inside the control block.
+enum InputFileRecordTypes {
+  /// An input file.
+  INPUT_FILE = 1,
 
-      /// Record code for an update to a decl context's lookup table.
-      ///
-      /// In practice, this should only be used for the TU and namespaces.
-      UPDATE_VISIBLE = 28,
+  /// The input file content hash
+  INPUT_FILE_HASH
+};
 
-      /// Record for offsets of DECL_UPDATES records for declarations
-      /// that were modified after being deserialized and need updates.
-      DECL_UPDATE_OFFSETS = 29,
+/// Record types that occur within the AST block itself.
+enum ASTRecordTypes {
+  /// Record code for the offsets of each type.
+  ///
+  /// The TYPE_OFFSET constant describes the record that occurs
+  /// within the AST block. The record itself is an array of offsets that
+  /// point into the declarations and types block (identified by
+  /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID
+  /// of a type. For a given type ID @c T, the lower three bits of
+  /// @c T are its qualifiers (const, volatile, restrict), as in
+  /// the QualType class. The upper bits, after being shifted and
+  /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the
+  /// TYPE_OFFSET block to determine the offset of that type's
+  /// corresponding record within the DECLTYPES_BLOCK_ID block.
+  TYPE_OFFSET = 1,
+
+  /// Record code for the offsets of each decl.
+  ///
+  /// The DECL_OFFSET constant describes the record that occurs
+  /// within the block identified by DECL_OFFSETS_BLOCK_ID within
+  /// the AST block. The record itself is an array of offsets that
+  /// point into the declarations and types block (identified by
+  /// DECLTYPES_BLOCK_ID). The declaration ID is an index into this
+  /// record, after subtracting one to account for the use of
+  /// declaration ID 0 for a NULL declaration pointer. Index 0 is
+  /// reserved for the translation unit declaration.
+  DECL_OFFSET = 2,
+
+  /// Record code for the table of offsets of each
+  /// identifier ID.
+  ///
+  /// The offset table contains offsets into the blob stored in
+  /// the IDENTIFIER_TABLE record. Each offset points to the
+  /// NULL-terminated string that corresponds to that identifier.
+  IDENTIFIER_OFFSET = 3,
+
+  /// This is so that older clang versions, before the introduction
+  /// of the control block, can read and reject the newer PCH format.
+  /// *DON'T CHANGE THIS NUMBER*.
+  METADATA_OLD_FORMAT = 4,
+
+  /// Record code for the identifier table.
+  ///
+  /// The identifier table is a simple blob that contains
+  /// NULL-terminated strings for all of the identifiers
+  /// referenced by the AST file. The IDENTIFIER_OFFSET table
+  /// contains the mapping from identifier IDs to the characters
+  /// in this blob. Note that the starting offsets of all of the
+  /// identifiers are odd, so that, when the identifier offset
+  /// table is loaded in, we can use the low bit to distinguish
+  /// between offsets (for unresolved identifier IDs) and
+  /// IdentifierInfo pointers (for already-resolved identifier
+  /// IDs).
+  IDENTIFIER_TABLE = 5,
+
+  /// Record code for the array of eagerly deserialized decls.
+  ///
+  /// The AST file contains a list of all of the declarations that should be
+  /// eagerly deserialized present within the parsed headers, stored as an
+  /// array of declaration IDs. These declarations will be
+  /// reported to the AST consumer after the AST file has been
+  /// read, since their presence can affect the semantics of the
+  /// program (e.g., for code generation).
+  EAGERLY_DESERIALIZED_DECLS = 6,
+
+  /// Record code for the set of non-builtin, special
+  /// types.
+  ///
+  /// This record contains the type IDs for the various type nodes
+  /// that are constructed during semantic analysis (e.g.,
+  /// __builtin_va_list). The SPECIAL_TYPE_* constants provide
+  /// offsets into this record.
+  SPECIAL_TYPES = 7,
+
+  /// Record code for the extra statistics we gather while
+  /// generating an AST file.
+  STATISTICS = 8,
+
+  /// Record code for the array of tentative definitions.
+  TENTATIVE_DEFINITIONS = 9,
+
+  // ID 10 used to be for a list of extern "C" declarations.
+
+  /// Record code for the table of offsets into the
+  /// Objective-C method pool.
+  SELECTOR_OFFSETS = 11,
+
+  /// Record code for the Objective-C method pool,
+  METHOD_POOL = 12,
+
+  /// The value of the next __COUNTER__ to dispense.
+  /// [PP_COUNTER_VALUE, Val]
+  PP_COUNTER_VALUE = 13,
+
+  /// Record code for the table of offsets into the block
+  /// of source-location information.
+  SOURCE_LOCATION_OFFSETS = 14,
+
+  /// Record code for the set of source location entries
+  /// that need to be preloaded by the AST reader.
+  ///
+  /// This set contains the source location entry for the
+  /// predefines buffer and for any file entries that need to be
+  /// preloaded.
+  SOURCE_LOCATION_PRELOADS = 15,
+
+  /// Record code for the set of ext_vector type names.
+  EXT_VECTOR_DECLS = 16,
+
+  /// Record code for the array of unused file scoped decls.
+  UNUSED_FILESCOPED_DECLS = 17,
+
+  /// Record code for the table of offsets to entries in the
+  /// preprocessing record.
+  PPD_ENTITIES_OFFSETS = 18,
+
+  /// Record code for the array of VTable uses.
+  VTABLE_USES = 19,
+
+  // ID 20 used to be for a list of dynamic classes.
+
+  /// Record code for referenced selector pool.
+  REFERENCED_SELECTOR_POOL = 21,
+
+  /// Record code for an update to the TU's lexically contained
+  /// declarations.
+  TU_UPDATE_LEXICAL = 22,
+
+  // ID 23 used to be for a list of local redeclarations.
+
+  /// Record code for declarations that Sema keeps references of.
+  SEMA_DECL_REFS = 24,
+
+  /// Record code for weak undeclared identifiers.
+  WEAK_UNDECLARED_IDENTIFIERS = 25,
 
-      // ID 30 used to be a decl update record. These are now in the DECLTYPES
-      // block.
+  /// Record code for pending implicit instantiations.
+  PENDING_IMPLICIT_INSTANTIATIONS = 26,
 
-      // ID 31 used to be a list of offsets to DECL_CXX_BASE_SPECIFIERS records.
+  // ID 27 used to be for a list of replacement decls.
 
-      // ID 32 used to be the code for \#pragma diagnostic mappings.
+  /// Record code for an update to a decl context's lookup table.
+  ///
+  /// In practice, this should only be used for the TU and namespaces.
+  UPDATE_VISIBLE = 28,
 
-      /// Record code for special CUDA declarations.
-      CUDA_SPECIAL_DECL_REFS = 33,
+  /// Record for offsets of DECL_UPDATES records for declarations
+  /// that were modified after being deserialized and need updates.
+  DECL_UPDATE_OFFSETS = 29,
 
-      /// Record code for header search information.
-      HEADER_SEARCH_TABLE = 34,
+  // ID 30 used to be a decl update record. These are now in the DECLTYPES
+  // block.
 
-      /// Record code for floating point \#pragma options.
-      FP_PRAGMA_OPTIONS = 35,
+  // ID 31 used to be a list of offsets to DECL_CXX_BASE_SPECIFIERS records.
 
-      /// Record code for enabled OpenCL extensions.
-      OPENCL_EXTENSIONS = 36,
+  // ID 32 used to be the code for \#pragma diagnostic mappings.
 
-      /// The list of delegating constructor declarations.
-      DELEGATING_CTORS = 37,
+  /// Record code for special CUDA declarations.
+  CUDA_SPECIAL_DECL_REFS = 33,
 
-      /// Record code for the set of known namespaces, which are used
-      /// for typo correction.
-      KNOWN_NAMESPACES = 38,
+  /// Record code for header search information.
+  HEADER_SEARCH_TABLE = 34,
 
-      /// Record code for the remapping information used to relate
-      /// loaded modules to the various offsets and IDs(e.g., source location
-      /// offests, declaration and type IDs) that are used in that module to
-      /// refer to other modules.
-      MODULE_OFFSET_MAP = 39,
+  /// Record code for floating point \#pragma options.
+  FP_PRAGMA_OPTIONS = 35,
 
-      /// Record code for the source manager line table information,
-      /// which stores information about \#line directives.
-      SOURCE_MANAGER_LINE_TABLE = 40,
+  /// Record code for enabled OpenCL extensions.
+  OPENCL_EXTENSIONS = 36,
 
-      /// Record code for map of Objective-C class definition IDs to the
-      /// ObjC categories in a module that are attached to that class.
-      OBJC_CATEGORIES_MAP = 41,
+  /// The list of delegating constructor declarations.
+  DELEGATING_CTORS = 37,
 
-      /// Record code for a file sorted array of DeclIDs in a module.
-      FILE_SORTED_DECLS = 42,
+  /// Record code for the set of known namespaces, which are used
+  /// for typo correction.
+  KNOWN_NAMESPACES = 38,
 
-      /// Record code for an array of all of the (sub)modules that were
-      /// imported by the AST file.
-      IMPORTED_MODULES = 43,
+  /// Record code for the remapping information used to relate
+  /// loaded modules to the various offsets and IDs(e.g., source location
+  /// offests, declaration and type IDs) that are used in that module to
+  /// refer to other modules.
+  MODULE_OFFSET_MAP = 39,
 
-      // ID 44 used to be a table of merged canonical declarations.
-      // ID 45 used to be a list of declaration IDs of local redeclarations.
+  /// Record code for the source manager line table information,
+  /// which stores information about \#line directives.
+  SOURCE_MANAGER_LINE_TABLE = 40,
 
-      /// Record code for the array of Objective-C categories (including
-      /// extensions).
-      ///
-      /// This array can only be interpreted properly using the Objective-C
-      /// categories map.
-      OBJC_CATEGORIES = 46,
+  /// Record code for map of Objective-C class definition IDs to the
+  /// ObjC categories in a module that are attached to that class.
+  OBJC_CATEGORIES_MAP = 41,
 
-      /// Record code for the table of offsets of each macro ID.
-      ///
-      /// The offset table contains offsets into the blob stored in
-      /// the preprocessor block. Each offset points to the corresponding
-      /// macro definition.
-      MACRO_OFFSET = 47,
+  /// Record code for a file sorted array of DeclIDs in a module.
+  FILE_SORTED_DECLS = 42,
 
-      /// A list of "interesting" identifiers. Only used in C++ (where we
-      /// don't normally do lookups into the serialized identifier table). These
-      /// are eagerly deserialized.
-      INTERESTING_IDENTIFIERS = 48,
+  /// Record code for an array of all of the (sub)modules that were
+  /// imported by the AST file.
+  IMPORTED_MODULES = 43,
 
-      /// Record code for undefined but used functions and variables that
-      /// need a definition in this TU.
-      UNDEFINED_BUT_USED = 49,
+  // ID 44 used to be a table of merged canonical declarations.
+  // ID 45 used to be a list of declaration IDs of local redeclarations.
 
-      /// Record code for late parsed template functions.
-      LATE_PARSED_TEMPLATE = 50,
+  /// Record code for the array of Objective-C categories (including
+  /// extensions).
+  ///
+  /// This array can only be interpreted properly using the Objective-C
+  /// categories map.
+  OBJC_CATEGORIES = 46,
 
-      /// Record code for \#pragma optimize options.
-      OPTIMIZE_PRAGMA_OPTIONS = 51,
+  /// Record code for the table of offsets of each macro ID.
+  ///
+  /// The offset table contains offsets into the blob stored in
+  /// the preprocessor block. Each offset points to the corresponding
+  /// macro definition.
+  MACRO_OFFSET = 47,
 
-      /// Record code for potentially unused local typedef names.
-      UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES = 52,
+  /// A list of "interesting" identifiers. Only used in C++ (where we
+  /// don't normally do lookups into the serialized identifier table). These
+  /// are eagerly deserialized.
+  INTERESTING_IDENTIFIERS = 48,
 
-      // ID 53 used to be a table of constructor initializer records.
+  /// Record code for undefined but used functions and variables that
+  /// need a definition in this TU.
+  UNDEFINED_BUT_USED = 49,
 
-      /// Delete expressions that will be analyzed later.
-      DELETE_EXPRS_TO_ANALYZE = 54,
+  /// Record code for late parsed template functions.
+  LATE_PARSED_TEMPLATE = 50,
 
-      /// Record code for \#pragma ms_struct options.
-      MSSTRUCT_PRAGMA_OPTIONS = 55,
+  /// Record code for \#pragma optimize options.
+  OPTIMIZE_PRAGMA_OPTIONS = 51,
 
-      /// Record code for \#pragma ms_struct options.
-      POINTERS_TO_MEMBERS_PRAGMA_OPTIONS = 56,
+  /// Record code for potentially unused local typedef names.
+  UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES = 52,
 
-      /// Number of unmatched #pragma clang cuda_force_host_device begin
-      /// directives we've seen.
-      CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH = 57,
+  // ID 53 used to be a table of constructor initializer records.
 
-      /// Record code for types associated with OpenCL extensions.
-      OPENCL_EXTENSION_TYPES = 58,
+  /// Delete expressions that will be analyzed later.
+  DELETE_EXPRS_TO_ANALYZE = 54,
 
-      /// Record code for declarations associated with OpenCL extensions.
-      OPENCL_EXTENSION_DECLS = 59,
+  /// Record code for \#pragma ms_struct options.
+  MSSTRUCT_PRAGMA_OPTIONS = 55,
 
-      MODULAR_CODEGEN_DECLS = 60,
+  /// Record code for \#pragma ms_struct options.
+  POINTERS_TO_MEMBERS_PRAGMA_OPTIONS = 56,
 
-      /// Record code for \#pragma align/pack options.
-      ALIGN_PACK_PRAGMA_OPTIONS = 61,
+  /// Number of unmatched #pragma clang cuda_force_host_device begin
+  /// directives we've seen.
+  CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH = 57,
 
-      /// The stack of open #ifs/#ifdefs recorded in a preamble.
-      PP_CONDITIONAL_STACK = 62,
+  /// Record code for types associated with OpenCL extensions.
+  OPENCL_EXTENSION_TYPES = 58,
 
-      /// A table of skipped ranges within the preprocessing record.
-      PPD_SKIPPED_RANGES = 63,
+  /// Record code for declarations associated with OpenCL extensions.
+  OPENCL_EXTENSION_DECLS = 59,
 
-      /// Record code for the Decls to be checked for deferred diags.
-      DECLS_TO_CHECK_FOR_DEFERRED_DIAGS = 64,
+  MODULAR_CODEGEN_DECLS = 60,
 
-      /// Record code for \#pragma float_control options.
-      FLOAT_CONTROL_PRAGMA_OPTIONS = 65,
-    };
+  /// Record code for \#pragma align/pack options.
+  ALIGN_PACK_PRAGMA_OPTIONS = 61,
 
-    /// Record types used within a source manager block.
-    enum SourceManagerRecordTypes {
-      /// Describes a source location entry (SLocEntry) for a
-      /// file.
-      SM_SLOC_FILE_ENTRY = 1,
+  /// The stack of open #ifs/#ifdefs recorded in a preamble.
+  PP_CONDITIONAL_STACK = 62,
 
-      /// Describes a source location entry (SLocEntry) for a
-      /// buffer.
-      SM_SLOC_BUFFER_ENTRY = 2,
+  /// A table of skipped ranges within the preprocessing record.
+  PPD_SKIPPED_RANGES = 63,
 
-      /// Describes a blob that contains the data for a buffer
-      /// entry. This kind of record always directly follows a
-      /// SM_SLOC_BUFFER_ENTRY record or a SM_SLOC_FILE_ENTRY with an
-      /// overridden buffer.
-      SM_SLOC_BUFFER_BLOB = 3,
+  /// Record code for the Decls to be checked for deferred diags.
+  DECLS_TO_CHECK_FOR_DEFERRED_DIAGS = 64,
 
-      /// Describes a zlib-compressed blob that contains the data for
-      /// a buffer entry.
-      SM_SLOC_BUFFER_BLOB_COMPRESSED = 4,
+  /// Record code for \#pragma float_control options.
+  FLOAT_CONTROL_PRAGMA_OPTIONS = 65,
+};
 
-      /// Describes a source location entry (SLocEntry) for a
-      /// macro expansion.
-      SM_SLOC_EXPANSION_ENTRY = 5
-    };
+/// Record types used within a source manager block.
+enum SourceManagerRecordTypes {
+  /// Describes a source location entry (SLocEntry) for a
+  /// file.
+  SM_SLOC_FILE_ENTRY = 1,
+
+  /// Describes a source location entry (SLocEntry) for a
+  /// buffer.
+  SM_SLOC_BUFFER_ENTRY = 2,
+
+  /// Describes a blob that contains the data for a buffer
+  /// entry. This kind of record always directly follows a
+  /// SM_SLOC_BUFFER_ENTRY record or a SM_SLOC_FILE_ENTRY with an
+  /// overridden buffer.
+  SM_SLOC_BUFFER_BLOB = 3,
+
+  /// Describes a zlib-compressed blob that contains the data for
+  /// a buffer entry.
+  SM_SLOC_BUFFER_BLOB_COMPRESSED = 4,
+
+  /// Describes a source location entry (SLocEntry) for a
+  /// macro expansion.
+  SM_SLOC_EXPANSION_ENTRY = 5
+};
 
-    /// Record types used within a preprocessor block.
-    enum PreprocessorRecordTypes {
-      // The macros in the PP section are a PP_MACRO_* instance followed by a
-      // list of PP_TOKEN instances for each token in the definition.
+/// Record types used within a preprocessor block.
+enum PreprocessorRecordTypes {
+  // The macros in the PP section are a PP_MACRO_* instance followed by a
+  // list of PP_TOKEN instances for each token in the definition.
 
-      /// An object-like macro definition.
-      /// [PP_MACRO_OBJECT_LIKE, IdentInfoID, SLoc, IsUsed]
-      PP_MACRO_OBJECT_LIKE = 1,
+  /// An object-like macro definition.
+  /// [PP_MACRO_OBJECT_LIKE, IdentInfoID, SLoc, IsUsed]
+  PP_MACRO_OBJECT_LIKE = 1,
 
-      /// A function-like macro definition.
-      /// [PP_MACRO_FUNCTION_LIKE, \<ObjectLikeStuff>, IsC99Varargs,
-      /// IsGNUVarars, NumArgs, ArgIdentInfoID* ]
-      PP_MACRO_FUNCTION_LIKE = 2,
+  /// A function-like macro definition.
+  /// [PP_MACRO_FUNCTION_LIKE, \<ObjectLikeStuff>, IsC99Varargs,
+  /// IsGNUVarars, NumArgs, ArgIdentInfoID* ]
+  PP_MACRO_FUNCTION_LIKE = 2,
 
-      /// Describes one token.
-      /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]
-      PP_TOKEN = 3,
+  /// Describes one token.
+  /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]
+  PP_TOKEN = 3,
 
-      /// The macro directives history for a particular identifier.
-      PP_MACRO_DIRECTIVE_HISTORY = 4,
+  /// The macro directives history for a particular identifier.
+  PP_MACRO_DIRECTIVE_HISTORY = 4,
 
-      /// A macro directive exported by a module.
-      /// [PP_MODULE_MACRO, SubmoduleID, MacroID, (Overridden SubmoduleID)*]
-      PP_MODULE_MACRO = 5,
-    };
+  /// A macro directive exported by a module.
+  /// [PP_MODULE_MACRO, SubmoduleID, MacroID, (Overridden SubmoduleID)*]
+  PP_MODULE_MACRO = 5,
+};
 
-    /// Record types used within a preprocessor detail block.
-    enum PreprocessorDetailRecordTypes {
-      /// Describes a macro expansion within the preprocessing record.
-      PPD_MACRO_EXPANSION = 0,
+/// Record types used within a preprocessor detail block.
+enum PreprocessorDetailRecordTypes {
+  /// Describes a macro expansion within the preprocessing record.
+  PPD_MACRO_EXPANSION = 0,
 
-      /// Describes a macro definition within the preprocessing record.
-      PPD_MACRO_DEFINITION = 1,
+  /// Describes a macro definition within the preprocessing record.
+  PPD_MACRO_DEFINITION = 1,
 
-      /// Describes an inclusion directive within the preprocessing
-      /// record.
-      PPD_INCLUSION_DIRECTIVE = 2
-    };
+  /// Describes an inclusion directive within the preprocessing
+  /// record.
+  PPD_INCLUSION_DIRECTIVE = 2
+};
 
-    /// Record types used within a submodule description block.
-    enum SubmoduleRecordTypes {
-      /// Metadata for submodules as a whole.
-      SUBMODULE_METADATA = 0,
+/// Record types used within a submodule description block.
+enum SubmoduleRecordTypes {
+  /// Metadata for submodules as a whole.
+  SUBMODULE_METADATA = 0,
 
-      /// Defines the major attributes of a submodule, including its
-      /// name and parent.
-      SUBMODULE_DEFINITION = 1,
+  /// Defines the major attributes of a submodule, including its
+  /// name and parent.
+  SUBMODULE_DEFINITION = 1,
 
-      /// Specifies the umbrella header used to create this module,
-      /// if any.
-      SUBMODULE_UMBRELLA_HEADER = 2,
+  /// Specifies the umbrella header used to create this module,
+  /// if any.
+  SUBMODULE_UMBRELLA_HEADER = 2,
 
-      /// Specifies a header that falls into this (sub)module.
-      SUBMODULE_HEADER = 3,
+  /// Specifies a header that falls into this (sub)module.
+  SUBMODULE_HEADER = 3,
 
-      /// Specifies a top-level header that falls into this (sub)module.
-      SUBMODULE_TOPHEADER = 4,
+  /// Specifies a top-level header that falls into this (sub)module.
+  SUBMODULE_TOPHEADER = 4,
 
-      /// Specifies an umbrella directory.
-      SUBMODULE_UMBRELLA_DIR = 5,
+  /// Specifies an umbrella directory.
+  SUBMODULE_UMBRELLA_DIR = 5,
 
-      /// Specifies the submodules that are imported by this
-      /// submodule.
-      SUBMODULE_IMPORTS = 6,
+  /// Specifies the submodules that are imported by this
+  /// submodule.
+  SUBMODULE_IMPORTS = 6,
 
-      /// Specifies the submodules that are re-exported from this
-      /// submodule.
-      SUBMODULE_EXPORTS = 7,
+  /// Specifies the submodules that are re-exported from this
+  /// submodule.
+  SUBMODULE_EXPORTS = 7,
 
-      /// Specifies a required feature.
-      SUBMODULE_REQUIRES = 8,
+  /// Specifies a required feature.
+  SUBMODULE_REQUIRES = 8,
 
-      /// Specifies a header that has been explicitly excluded
-      /// from this submodule.
-      SUBMODULE_EXCLUDED_HEADER = 9,
+  /// Specifies a header that has been explicitly excluded
+  /// from this submodule.
+  SUBMODULE_EXCLUDED_HEADER = 9,
 
-      /// Specifies a library or framework to link against.
-      SUBMODULE_LINK_LIBRARY = 10,
+  /// Specifies a library or framework to link against.
+  SUBMODULE_LINK_LIBRARY = 10,
 
-      /// Specifies a configuration macro for this module.
-      SUBMODULE_CONFIG_MACRO = 11,
+  /// Specifies a configuration macro for this module.
+  SUBMODULE_CONFIG_MACRO = 11,
 
-      /// Specifies a conflict with another module.
-      SUBMODULE_CONFLICT = 12,
+  /// Specifies a conflict with another module.
+  SUBMODULE_CONFLICT = 12,
 
-      /// Specifies a header that is private to this submodule.
-      SUBMODULE_PRIVATE_HEADER = 13,
+  /// Specifies a header that is private to this submodule.
+  SUBMODULE_PRIVATE_HEADER = 13,
 
-      /// Specifies a header that is part of the module but must be
-      /// textually included.
-      SUBMODULE_TEXTUAL_HEADER = 14,
+  /// Specifies a header that is part of the module but must be
+  /// textually included.
+  SUBMODULE_TEXTUAL_HEADER = 14,
 
-      /// Specifies a header that is private to this submodule but
-      /// must be textually included.
-      SUBMODULE_PRIVATE_TEXTUAL_HEADER = 15,
+  /// Specifies a header that is private to this submodule but
+  /// must be textually included.
+  SUBMODULE_PRIVATE_TEXTUAL_HEADER = 15,
 
-      /// Specifies some declarations with initializers that must be
-      /// emitted to initialize the module.
-      SUBMODULE_INITIALIZERS = 16,
+  /// Specifies some declarations with initializers that must be
+  /// emitted to initialize the module.
+  SUBMODULE_INITIALIZERS = 16,
 
-      /// Specifies the name of the module that will eventually
-      /// re-export the entities in this module.
-      SUBMODULE_EXPORT_AS = 17,
-    };
+  /// Specifies the name of the module that will eventually
+  /// re-export the entities in this module.
+  SUBMODULE_EXPORT_AS = 17,
+};
 
-    /// Record types used within a comments block.
-    enum CommentRecordTypes {
-      COMMENTS_RAW_COMMENT = 0
-    };
+/// Record types used within a comments block.
+enum CommentRecordTypes { COMMENTS_RAW_COMMENT = 0 };
 
-    /// \defgroup ASTAST AST file AST constants
-    ///
-    /// The constants in this group describe various components of the
-    /// abstract syntax tree within an AST file.
-    ///
-    /// @{
+/// \defgroup ASTAST AST file AST constants
+///
+/// The constants in this group describe various components of the
+/// abstract syntax tree within an AST file.
+///
+/// @{
 
-    /// Predefined type IDs.
-    ///
-    /// These type IDs correspond to predefined types in the AST
-    /// context, such as built-in types (int) and special place-holder
-    /// types (the \<overload> and \<dependent> type markers). Such
-    /// types are never actually serialized, since they will be built
-    /// by the AST context when it is created.
-    enum PredefinedTypeIDs {
-      /// The NULL type.
-      PREDEF_TYPE_NULL_ID       = 0,
+/// Predefined type IDs.
+///
+/// These type IDs correspond to predefined types in the AST
+/// context, such as built-in types (int) and special place-holder
+/// types (the \<overload> and \<dependent> type markers). Such
+/// types are never actually serialized, since they will be built
+/// by the AST context when it is created.
+enum PredefinedTypeIDs {
+  /// The NULL type.
+  PREDEF_TYPE_NULL_ID = 0,
 
-      /// The void type.
-      PREDEF_TYPE_VOID_ID       = 1,
+  /// The void type.
+  PREDEF_TYPE_VOID_ID = 1,
 
-      /// The 'bool' or '_Bool' type.
-      PREDEF_TYPE_BOOL_ID       = 2,
+  /// The 'bool' or '_Bool' type.
+  PREDEF_TYPE_BOOL_ID = 2,
 
-      /// The 'char' type, when it is unsigned.
-      PREDEF_TYPE_CHAR_U_ID     = 3,
+  /// The 'char' type, when it is unsigned.
+  PREDEF_TYPE_CHAR_U_ID = 3,
 
-      /// The 'unsigned char' type.
-      PREDEF_TYPE_UCHAR_ID      = 4,
+  /// The 'unsigned char' type.
+  PREDEF_TYPE_UCHAR_ID = 4,
 
-      /// The 'unsigned short' type.
-      PREDEF_TYPE_USHORT_ID     = 5,
+  /// The 'unsigned short' type.
+  PREDEF_TYPE_USHORT_ID = 5,
 
-      /// The 'unsigned int' type.
-      PREDEF_TYPE_UINT_ID       = 6,
+  /// The 'unsigned int' type.
+  PREDEF_TYPE_UINT_ID = 6,
 
-      /// The 'unsigned long' type.
-      PREDEF_TYPE_ULONG_ID      = 7,
+  /// The 'unsigned long' type.
+  PREDEF_TYPE_ULONG_ID = 7,
 
-      /// The 'unsigned long long' type.
-      PREDEF_TYPE_ULONGLONG_ID  = 8,
+  /// The 'unsigned long long' type.
+  PREDEF_TYPE_ULONGLONG_ID = 8,
 
-      /// The 'char' type, when it is signed.
-      PREDEF_TYPE_CHAR_S_ID     = 9,
+  /// The 'char' type, when it is signed.
+  PREDEF_TYPE_CHAR_S_ID = 9,
 
-      /// The 'signed char' type.
-      PREDEF_TYPE_SCHAR_ID      = 10,
+  /// The 'signed char' type.
+  PREDEF_TYPE_SCHAR_ID = 10,
 
-      /// The C++ 'wchar_t' type.
-      PREDEF_TYPE_WCHAR_ID      = 11,
+  /// The C++ 'wchar_t' type.
+  PREDEF_TYPE_WCHAR_ID = 11,
 
-      /// The (signed) 'short' type.
-      PREDEF_TYPE_SHORT_ID      = 12,
+  /// The (signed) 'short' type.
+  PREDEF_TYPE_SHORT_ID = 12,
 
-      /// The (signed) 'int' type.
-      PREDEF_TYPE_INT_ID        = 13,
+  /// The (signed) 'int' type.
+  PREDEF_TYPE_INT_ID = 13,
 
-      /// The (signed) 'long' type.
-      PREDEF_TYPE_LONG_ID       = 14,
+  /// The (signed) 'long' type.
+  PREDEF_TYPE_LONG_ID = 14,
 
-      /// The (signed) 'long long' type.
-      PREDEF_TYPE_LONGLONG_ID   = 15,
+  /// The (signed) 'long long' type.
+  PREDEF_TYPE_LONGLONG_ID = 15,
 
-      /// The 'float' type.
-      PREDEF_TYPE_FLOAT_ID      = 16,
+  /// The 'float' type.
+  PREDEF_TYPE_FLOAT_ID = 16,
 
-      /// The 'double' type.
-      PREDEF_TYPE_DOUBLE_ID     = 17,
+  /// The 'double' type.
+  PREDEF_TYPE_DOUBLE_ID = 17,
 
-      /// The 'long double' type.
-      PREDEF_TYPE_LONGDOUBLE_ID = 18,
+  /// The 'long double' type.
+  PREDEF_TYPE_LONGDOUBLE_ID = 18,
 
-      /// The placeholder type for overloaded function sets.
-      PREDEF_TYPE_OVERLOAD_ID   = 19,
+  /// The placeholder type for overloaded function sets.
+  PREDEF_TYPE_OVERLOAD_ID = 19,
 
-      /// The placeholder type for dependent types.
-      PREDEF_TYPE_DEPENDENT_ID  = 20,
+  /// The placeholder type for dependent types.
+  PREDEF_TYPE_DEPENDENT_ID = 20,
 
-      /// The '__uint128_t' type.
-      PREDEF_TYPE_UINT128_ID    = 21,
+  /// The '__uint128_t' type.
+  PREDEF_TYPE_UINT128_ID = 21,
 
-      /// The '__int128_t' type.
-      PREDEF_TYPE_INT128_ID     = 22,
+  /// The '__int128_t' type.
+  PREDEF_TYPE_INT128_ID = 22,
 
-      /// The type of 'nullptr'.
-      PREDEF_TYPE_NULLPTR_ID    = 23,
+  /// The type of 'nullptr'.
+  PREDEF_TYPE_NULLPTR_ID = 23,
 
-      /// The C++ 'char16_t' type.
-      PREDEF_TYPE_CHAR16_ID     = 24,
+  /// The C++ 'char16_t' type.
+  PREDEF_TYPE_CHAR16_ID = 24,
 
-      /// The C++ 'char32_t' type.
-      PREDEF_TYPE_CHAR32_ID     = 25,
+  /// The C++ 'char32_t' type.
+  PREDEF_TYPE_CHAR32_ID = 25,
 
-      /// The ObjC 'id' type.
-      PREDEF_TYPE_OBJC_ID       = 26,
+  /// The ObjC 'id' type.
+  PREDEF_TYPE_OBJC_ID = 26,
 
-      /// The ObjC 'Class' type.
-      PREDEF_TYPE_OBJC_CLASS    = 27,
+  /// The ObjC 'Class' type.
+  PREDEF_TYPE_OBJC_CLASS = 27,
 
-      /// The ObjC 'SEL' type.
-      PREDEF_TYPE_OBJC_SEL      = 28,
+  /// The ObjC 'SEL' type.
+  PREDEF_TYPE_OBJC_SEL = 28,
 
-      /// The 'unknown any' placeholder type.
-      PREDEF_TYPE_UNKNOWN_ANY   = 29,
+  /// The 'unknown any' placeholder type.
+  PREDEF_TYPE_UNKNOWN_ANY = 29,
 
-      /// The placeholder type for bound member functions.
-      PREDEF_TYPE_BOUND_MEMBER  = 30,
+  /// The placeholder type for bound member functions.
+  PREDEF_TYPE_BOUND_MEMBER = 30,
 
-      /// The "auto" deduction type.
-      PREDEF_TYPE_AUTO_DEDUCT   = 31,
+  /// The "auto" deduction type.
+  PREDEF_TYPE_AUTO_DEDUCT = 31,
 
-      /// The "auto &&" deduction type.
-      PREDEF_TYPE_AUTO_RREF_DEDUCT = 32,
+  /// The "auto &&" deduction type.
+  PREDEF_TYPE_AUTO_RREF_DEDUCT = 32,
 
-      /// The OpenCL 'half' / ARM NEON __fp16 type.
-      PREDEF_TYPE_HALF_ID       = 33,
+  /// The OpenCL 'half' / ARM NEON __fp16 type.
+  PREDEF_TYPE_HALF_ID = 33,
 
-      /// ARC's unbridged-cast placeholder type.
-      PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34,
+  /// ARC's unbridged-cast placeholder type.
+  PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34,
 
-      /// The pseudo-object placeholder type.
-      PREDEF_TYPE_PSEUDO_OBJECT = 35,
+  /// The pseudo-object placeholder type.
+  PREDEF_TYPE_PSEUDO_OBJECT = 35,
 
-      /// The placeholder type for builtin functions.
-      PREDEF_TYPE_BUILTIN_FN = 36,
+  /// The placeholder type for builtin functions.
+  PREDEF_TYPE_BUILTIN_FN = 36,
 
-      /// OpenCL event type.
-      PREDEF_TYPE_EVENT_ID      = 37,
+  /// OpenCL event type.
+  PREDEF_TYPE_EVENT_ID = 37,
 
-      /// OpenCL clk event type.
-      PREDEF_TYPE_CLK_EVENT_ID  = 38,
+  /// OpenCL clk event type.
+  PREDEF_TYPE_CLK_EVENT_ID = 38,
 
-      /// OpenCL sampler type.
-      PREDEF_TYPE_SAMPLER_ID    = 39,
+  /// OpenCL sampler type.
+  PREDEF_TYPE_SAMPLER_ID = 39,
 
-      /// OpenCL queue type.
-      PREDEF_TYPE_QUEUE_ID      = 40,
+  /// OpenCL queue type.
+  PREDEF_TYPE_QUEUE_ID = 40,
 
-      /// OpenCL reserve_id type.
-      PREDEF_TYPE_RESERVE_ID_ID = 41,
+  /// OpenCL reserve_id type.
+  PREDEF_TYPE_RESERVE_ID_ID = 41,
 
-      /// The placeholder type for OpenMP array section.
-      PREDEF_TYPE_OMP_ARRAY_SECTION = 42,
+  /// The placeholder type for OpenMP array section.
+  PREDEF_TYPE_OMP_ARRAY_SECTION = 42,
 
-      /// The '__float128' type
-      PREDEF_TYPE_FLOAT128_ID = 43,
+  /// The '__float128' type
+  PREDEF_TYPE_FLOAT128_ID = 43,
 
-      /// The '_Float16' type
-      PREDEF_TYPE_FLOAT16_ID = 44,
+  /// The '_Float16' type
+  PREDEF_TYPE_FLOAT16_ID = 44,
 
-      /// The C++ 'char8_t' type.
-      PREDEF_TYPE_CHAR8_ID = 45,
+  /// The C++ 'char8_t' type.
+  PREDEF_TYPE_CHAR8_ID = 45,
 
-      /// \brief The 'short _Accum' type
-      PREDEF_TYPE_SHORT_ACCUM_ID    = 46,
+  /// \brief The 'short _Accum' type
+  PREDEF_TYPE_SHORT_ACCUM_ID = 46,
 
-      /// \brief The '_Accum' type
-      PREDEF_TYPE_ACCUM_ID      = 47,
+  /// \brief The '_Accum' type
+  PREDEF_TYPE_ACCUM_ID = 47,
 
-      /// \brief The 'long _Accum' type
-      PREDEF_TYPE_LONG_ACCUM_ID = 48,
+  /// \brief The 'long _Accum' type
+  PREDEF_TYPE_LONG_ACCUM_ID = 48,
 
-      /// \brief The 'unsigned short _Accum' type
-      PREDEF_TYPE_USHORT_ACCUM_ID   = 49,
+  /// \brief The 'unsigned short _Accum' type
+  PREDEF_TYPE_USHORT_ACCUM_ID = 49,
 
-      /// \brief The 'unsigned _Accum' type
-      PREDEF_TYPE_UACCUM_ID     = 50,
+  /// \brief The 'unsigned _Accum' type
+  PREDEF_TYPE_UACCUM_ID = 50,
 
-      /// \brief The 'unsigned long _Accum' type
-      PREDEF_TYPE_ULONG_ACCUM_ID    = 51,
+  /// \brief The 'unsigned long _Accum' type
+  PREDEF_TYPE_ULONG_ACCUM_ID = 51,
 
-      /// \brief The 'short _Fract' type
-      PREDEF_TYPE_SHORT_FRACT_ID = 52,
+  /// \brief The 'short _Fract' type
+  PREDEF_TYPE_SHORT_FRACT_ID = 52,
 
-      /// \brief The '_Fract' type
-      PREDEF_TYPE_FRACT_ID = 53,
+  /// \brief The '_Fract' type
+  PREDEF_TYPE_FRACT_ID = 53,
 
-      /// \brief The 'long _Fract' type
-      PREDEF_TYPE_LONG_FRACT_ID = 54,
+  /// \brief The 'long _Fract' type
+  PREDEF_TYPE_LONG_FRACT_ID = 54,
 
-      /// \brief The 'unsigned short _Fract' type
-      PREDEF_TYPE_USHORT_FRACT_ID = 55,
+  /// \brief The 'unsigned short _Fract' type
+  PREDEF_TYPE_USHORT_FRACT_ID = 55,
 
-      /// \brief The 'unsigned _Fract' type
-      PREDEF_TYPE_UFRACT_ID = 56,
+  /// \brief The 'unsigned _Fract' type
+  PREDEF_TYPE_UFRACT_ID = 56,
 
-      /// \brief The 'unsigned long _Fract' type
-      PREDEF_TYPE_ULONG_FRACT_ID = 57,
+  /// \brief The 'unsigned long _Fract' type
+  PREDEF_TYPE_ULONG_FRACT_ID = 57,
 
-      /// \brief The '_Sat short _Accum' type
-      PREDEF_TYPE_SAT_SHORT_ACCUM_ID = 58,
+  /// \brief The '_Sat short _Accum' type
+  PREDEF_TYPE_SAT_SHORT_ACCUM_ID = 58,
 
-      /// \brief The '_Sat _Accum' type
-      PREDEF_TYPE_SAT_ACCUM_ID = 59,
+  /// \brief The '_Sat _Accum' type
+  PREDEF_TYPE_SAT_ACCUM_ID = 59,
 
-      /// \brief The '_Sat long _Accum' type
-      PREDEF_TYPE_SAT_LONG_ACCUM_ID = 60,
+  /// \brief The '_Sat long _Accum' type
+  PREDEF_TYPE_SAT_LONG_ACCUM_ID = 60,
 
-      /// \brief The '_Sat unsigned short _Accum' type
-      PREDEF_TYPE_SAT_USHORT_ACCUM_ID = 61,
+  /// \brief The '_Sat unsigned short _Accum' type
+  PREDEF_TYPE_SAT_USHORT_ACCUM_ID = 61,
 
-      /// \brief The '_Sat unsigned _Accum' type
-      PREDEF_TYPE_SAT_UACCUM_ID = 62,
+  /// \brief The '_Sat unsigned _Accum' type
+  PREDEF_TYPE_SAT_UACCUM_ID = 62,
 
-      /// \brief The '_Sat unsigned long _Accum' type
-      PREDEF_TYPE_SAT_ULONG_ACCUM_ID = 63,
+  /// \brief The '_Sat unsigned long _Accum' type
+  PREDEF_TYPE_SAT_ULONG_ACCUM_ID = 63,
 
-      /// \brief The '_Sat short _Fract' type
-      PREDEF_TYPE_SAT_SHORT_FRACT_ID = 64,
+  /// \brief The '_Sat short _Fract' type
+  PREDEF_TYPE_SAT_SHORT_FRACT_ID = 64,
 
-      /// \brief The '_Sat _Fract' type
-      PREDEF_TYPE_SAT_FRACT_ID = 65,
+  /// \brief The '_Sat _Fract' type
+  PREDEF_TYPE_SAT_FRACT_ID = 65,
 
-      /// \brief The '_Sat long _Fract' type
-      PREDEF_TYPE_SAT_LONG_FRACT_ID = 66,
+  /// \brief The '_Sat long _Fract' type
+  PREDEF_TYPE_SAT_LONG_FRACT_ID = 66,
 
-      /// \brief The '_Sat unsigned short _Fract' type
-      PREDEF_TYPE_SAT_USHORT_FRACT_ID = 67,
+  /// \brief The '_Sat unsigned short _Fract' type
+  PREDEF_TYPE_SAT_USHORT_FRACT_ID = 67,
 
-      /// \brief The '_Sat unsigned _Fract' type
-      PREDEF_TYPE_SAT_UFRACT_ID = 68,
+  /// \brief The '_Sat unsigned _Fract' type
+  PREDEF_TYPE_SAT_UFRACT_ID = 68,
 
-      /// \brief The '_Sat unsigned long _Fract' type
-      PREDEF_TYPE_SAT_ULONG_FRACT_ID = 69,
+  /// \brief The '_Sat unsigned long _Fract' type
+  PREDEF_TYPE_SAT_ULONG_FRACT_ID = 69,
 
-      /// The placeholder type for OpenMP array shaping operation.
-      PREDEF_TYPE_OMP_ARRAY_SHAPING = 70,
+  /// The placeholder type for OpenMP array shaping operation.
+  PREDEF_TYPE_OMP_ARRAY_SHAPING = 70,
 
-      /// The placeholder type for OpenMP iterator expression.
-      PREDEF_TYPE_OMP_ITERATOR = 71,
+  /// The placeholder type for OpenMP iterator expression.
+  PREDEF_TYPE_OMP_ITERATOR = 71,
 
-      /// A placeholder type for incomplete matrix index operations.
-      PREDEF_TYPE_INCOMPLETE_MATRIX_IDX = 72,
+  /// A placeholder type for incomplete matrix index operations.
+  PREDEF_TYPE_INCOMPLETE_MATRIX_IDX = 72,
 
-      /// \brief The '__bf16' type
-      PREDEF_TYPE_BFLOAT16_ID = 73,
+  /// \brief The '__bf16' type
+  PREDEF_TYPE_BFLOAT16_ID = 73,
 
-      /// OpenCL image types with auto numeration
-#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
-      PREDEF_TYPE_##Id##_ID,
+/// OpenCL image types with auto numeration
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix)                   \
+  PREDEF_TYPE_##Id##_ID,
 #include "clang/Basic/OpenCLImageTypes.def"
-      /// \brief OpenCL extension types with auto numeration
-#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
-      PREDEF_TYPE_##Id##_ID,
+/// \brief OpenCL extension types with auto numeration
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) PREDEF_TYPE_##Id##_ID,
 #include "clang/Basic/OpenCLExtensionTypes.def"
-      // \brief SVE types with auto numeration
+// \brief SVE types with auto numeration
 #define SVE_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID,
 #include "clang/Basic/AArch64SVEACLETypes.def"
-      // \brief  PowerPC MMA types with auto numeration
+// \brief  PowerPC MMA types with auto numeration
 #define PPC_VECTOR_TYPE(Name, Id, Size) PREDEF_TYPE_##Id##_ID,
 #include "clang/Basic/PPCTypes.def"
-      // \brief RISC-V V types with auto numeration
+// \brief RISC-V V types with auto numeration
 #define RVV_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID,
 #include "clang/Basic/RISCVVTypes.def"
-    };
-
-    /// The number of predefined type IDs that are reserved for
-    /// the PREDEF_TYPE_* constants.
-    ///
-    /// Type IDs for non-predefined types will start at
-    /// NUM_PREDEF_TYPE_IDs.
-    const unsigned NUM_PREDEF_TYPE_IDS = 300;
-
-    /// Record codes for each kind of type.
-    ///
-    /// These constants describe the type records that can occur within a
-    /// block identified by DECLTYPES_BLOCK_ID in the AST file. Each
-    /// constant describes a record for a specific type class in the
-    /// AST. Note that DeclCode values share this code space.
-    enum TypeCode {
-#define TYPE_BIT_CODE(CLASS_ID, CODE_ID, CODE_VALUE) \
-      TYPE_##CODE_ID = CODE_VALUE,
+};
+
+/// The number of predefined type IDs that are reserved for
+/// the PREDEF_TYPE_* constants.
+///
+/// Type IDs for non-predefined types will start at
+/// NUM_PREDEF_TYPE_IDs.
+const unsigned NUM_PREDEF_TYPE_IDS = 300;
+
+/// Record codes for each kind of type.
+///
+/// These constants describe the type records that can occur within a
+/// block identified by DECLTYPES_BLOCK_ID in the AST file. Each
+/// constant describes a record for a specific type class in the
+/// AST. Note that DeclCode values share this code space.
+enum TypeCode {
+#define TYPE_BIT_CODE(CLASS_ID, CODE_ID, CODE_VALUE)                           \
+  TYPE_##CODE_ID = CODE_VALUE,
 #include "clang/Serialization/TypeBitCodes.def"
 
-      /// An ExtQualType record.
-      TYPE_EXT_QUAL = 1
-    };
+  /// An ExtQualType record.
+  TYPE_EXT_QUAL = 1
+};
+
+/// The type IDs for special types constructed by semantic
+/// analysis.
+///
+/// The constants in this enumeration are indices into the
+/// SPECIAL_TYPES record.
+enum SpecialTypeIDs {
+  /// CFConstantString type
+  SPECIAL_TYPE_CF_CONSTANT_STRING = 0,
+
+  /// C FILE typedef type
+  SPECIAL_TYPE_FILE = 1,
+
+  /// C jmp_buf typedef type
+  SPECIAL_TYPE_JMP_BUF = 2,
+
+  /// C sigjmp_buf typedef type
+  SPECIAL_TYPE_SIGJMP_BUF = 3,
 
-    /// The type IDs for special types constructed by semantic
-    /// analysis.
-    ///
-    /// The constants in this enumeration are indices into the
-    /// SPECIAL_TYPES record.
-    enum SpecialTypeIDs {
-      /// CFConstantString type
-      SPECIAL_TYPE_CF_CONSTANT_STRING          = 0,
+  /// Objective-C "id" redefinition type
+  SPECIAL_TYPE_OBJC_ID_REDEFINITION = 4,
 
-      /// C FILE typedef type
-      SPECIAL_TYPE_FILE                        = 1,
+  /// Objective-C "Class" redefinition type
+  SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 5,
 
-      /// C jmp_buf typedef type
-      SPECIAL_TYPE_JMP_BUF                     = 2,
+  /// Objective-C "SEL" redefinition type
+  SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 6,
 
-      /// C sigjmp_buf typedef type
-      SPECIAL_TYPE_SIGJMP_BUF                  = 3,
+  /// C ucontext_t typedef type
+  SPECIAL_TYPE_UCONTEXT_T = 7
+};
+
+/// The number of special type IDs.
+const unsigned NumSpecialTypeIDs = 8;
+
+/// Predefined declaration IDs.
+///
+/// These declaration IDs correspond to predefined declarations in the AST
+/// context, such as the NULL declaration ID. Such declarations are never
+/// actually serialized, since they will be built by the AST context when
+/// it is created.
+enum PredefinedDeclIDs {
+  /// The NULL declaration.
+  PREDEF_DECL_NULL_ID = 0,
+
+  /// The translation unit.
+  PREDEF_DECL_TRANSLATION_UNIT_ID = 1,
 
-      /// Objective-C "id" redefinition type
-      SPECIAL_TYPE_OBJC_ID_REDEFINITION        = 4,
+  /// The Objective-C 'id' type.
+  PREDEF_DECL_OBJC_ID_ID = 2,
 
-      /// Objective-C "Class" redefinition type
-      SPECIAL_TYPE_OBJC_CLASS_REDEFINITION     = 5,
+  /// The Objective-C 'SEL' type.
+  PREDEF_DECL_OBJC_SEL_ID = 3,
 
-      /// Objective-C "SEL" redefinition type
-      SPECIAL_TYPE_OBJC_SEL_REDEFINITION       = 6,
+  /// The Objective-C 'Class' type.
+  PREDEF_DECL_OBJC_CLASS_ID = 4,
 
-      /// C ucontext_t typedef type
-      SPECIAL_TYPE_UCONTEXT_T                  = 7
-    };
+  /// The Objective-C 'Protocol' type.
+  PREDEF_DECL_OBJC_PROTOCOL_ID = 5,
 
-    /// The number of special type IDs.
-    const unsigned NumSpecialTypeIDs = 8;
+  /// The signed 128-bit integer type.
+  PREDEF_DECL_INT_128_ID = 6,
 
-    /// Predefined declaration IDs.
-    ///
-    /// These declaration IDs correspond to predefined declarations in the AST
-    /// context, such as the NULL declaration ID. Such declarations are never
-    /// actually serialized, since they will be built by the AST context when
-    /// it is created.
-    enum PredefinedDeclIDs {
-      /// The NULL declaration.
-      PREDEF_DECL_NULL_ID = 0,
+  /// The unsigned 128-bit integer type.
+  PREDEF_DECL_UNSIGNED_INT_128_ID = 7,
 
-      /// The translation unit.
-      PREDEF_DECL_TRANSLATION_UNIT_ID = 1,
+  /// The internal 'instancetype' typedef.
+  PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,
 
-      /// The Objective-C 'id' type.
-      PREDEF_DECL_OBJC_ID_ID = 2,
+  /// The internal '__builtin_va_list' typedef.
+  PREDEF_DECL_BUILTIN_VA_LIST_ID = 9,
 
-      /// The Objective-C 'SEL' type.
-      PREDEF_DECL_OBJC_SEL_ID = 3,
+  /// The internal '__va_list_tag' struct, if any.
+  PREDEF_DECL_VA_LIST_TAG = 10,
 
-      /// The Objective-C 'Class' type.
-      PREDEF_DECL_OBJC_CLASS_ID = 4,
+  /// The internal '__builtin_ms_va_list' typedef.
+  PREDEF_DECL_BUILTIN_MS_VA_LIST_ID = 11,
 
-      /// The Objective-C 'Protocol' type.
-      PREDEF_DECL_OBJC_PROTOCOL_ID = 5,
+  /// The predeclared '_GUID' struct.
+  PREDEF_DECL_BUILTIN_MS_GUID_ID = 12,
 
-      /// The signed 128-bit integer type.
-      PREDEF_DECL_INT_128_ID = 6,
+  /// The extern "C" context.
+  PREDEF_DECL_EXTERN_C_CONTEXT_ID = 13,
+
+  /// The internal '__make_integer_seq' template.
+  PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 14,
+
+  /// The internal '__NSConstantString' typedef.
+  PREDEF_DECL_CF_CONSTANT_STRING_ID = 15,
+
+  /// The internal '__NSConstantString' tag type.
+  PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID = 16,
+
+  /// The internal '__type_pack_element' template.
+  PREDEF_DECL_TYPE_PACK_ELEMENT_ID = 17,
+};
 
-      /// The unsigned 128-bit integer type.
-      PREDEF_DECL_UNSIGNED_INT_128_ID = 7,
+/// The number of declaration IDs that are predefined.
+///
+/// For more information about predefined declarations, see the
+/// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
+const unsigned int NUM_PREDEF_DECL_IDS = 18;
 
-      /// The internal 'instancetype' typedef.
-      PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,
+/// Record of updates for a declaration that was modified after
+/// being deserialized. This can occur within DECLTYPES_BLOCK_ID.
+const unsigned int DECL_UPDATES = 49;
 
-      /// The internal '__builtin_va_list' typedef.
-      PREDEF_DECL_BUILTIN_VA_LIST_ID = 9,
+/// Record code for a list of local redeclarations of a declaration.
+/// This can occur within DECLTYPES_BLOCK_ID.
+const unsigned int LOCAL_REDECLARATIONS = 50;
 
-      /// The internal '__va_list_tag' struct, if any.
-      PREDEF_DECL_VA_LIST_TAG = 10,
+/// Record codes for each kind of declaration.
+///
+/// These constants describe the declaration records that can occur within
+/// a declarations block (identified by DECLTYPES_BLOCK_ID). Each
+/// constant describes a record for a specific declaration class
+/// in the AST. Note that TypeCode values share this code space.
+enum DeclCode {
+  /// A TypedefDecl record.
+  DECL_TYPEDEF = 51,
+  /// A TypeAliasDecl record.
 
-      /// The internal '__builtin_ms_va_list' typedef.
-      PREDEF_DECL_BUILTIN_MS_VA_LIST_ID = 11,
+  DECL_TYPEALIAS,
 
-      /// The predeclared '_GUID' struct.
-      PREDEF_DECL_BUILTIN_MS_GUID_ID = 12,
+  /// An EnumDecl record.
+  DECL_ENUM,
 
-      /// The extern "C" context.
-      PREDEF_DECL_EXTERN_C_CONTEXT_ID = 13,
+  /// A RecordDecl record.
+  DECL_RECORD,
 
-      /// The internal '__make_integer_seq' template.
-      PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 14,
+  /// An EnumConstantDecl record.
+  DECL_ENUM_CONSTANT,
 
-      /// The internal '__NSConstantString' typedef.
-      PREDEF_DECL_CF_CONSTANT_STRING_ID = 15,
+  /// A FunctionDecl record.
+  DECL_FUNCTION,
 
-      /// The internal '__NSConstantString' tag type.
-      PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID = 16,
+  /// A ObjCMethodDecl record.
+  DECL_OBJC_METHOD,
 
-      /// The internal '__type_pack_element' template.
-      PREDEF_DECL_TYPE_PACK_ELEMENT_ID = 17,
-    };
+  /// A ObjCInterfaceDecl record.
+  DECL_OBJC_INTERFACE,
 
-    /// The number of declaration IDs that are predefined.
-    ///
-    /// For more information about predefined declarations, see the
-    /// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
-    const unsigned int NUM_PREDEF_DECL_IDS = 18;
+  /// A ObjCProtocolDecl record.
+  DECL_OBJC_PROTOCOL,
 
-    /// Record of updates for a declaration that was modified after
-    /// being deserialized. This can occur within DECLTYPES_BLOCK_ID.
-    const unsigned int DECL_UPDATES = 49;
+  /// A ObjCIvarDecl record.
+  DECL_OBJC_IVAR,
 
-    /// Record code for a list of local redeclarations of a declaration.
-    /// This can occur within DECLTYPES_BLOCK_ID.
-    const unsigned int LOCAL_REDECLARATIONS = 50;
+  /// A ObjCAtDefsFieldDecl record.
+  DECL_OBJC_AT_DEFS_FIELD,
 
-    /// Record codes for each kind of declaration.
-    ///
-    /// These constants describe the declaration records that can occur within
-    /// a declarations block (identified by DECLTYPES_BLOCK_ID). Each
-    /// constant describes a record for a specific declaration class
-    /// in the AST. Note that TypeCode values share this code space.
-    enum DeclCode {
-      /// A TypedefDecl record.
-      DECL_TYPEDEF = 51,
-      /// A TypeAliasDecl record.
+  /// A ObjCCategoryDecl record.
+  DECL_OBJC_CATEGORY,
 
-      DECL_TYPEALIAS,
+  /// A ObjCCategoryImplDecl record.
+  DECL_OBJC_CATEGORY_IMPL,
 
-      /// An EnumDecl record.
-      DECL_ENUM,
+  /// A ObjCImplementationDecl record.
+  DECL_OBJC_IMPLEMENTATION,
 
-      /// A RecordDecl record.
-      DECL_RECORD,
+  /// A ObjCCompatibleAliasDecl record.
+  DECL_OBJC_COMPATIBLE_ALIAS,
 
-      /// An EnumConstantDecl record.
-      DECL_ENUM_CONSTANT,
+  /// A ObjCPropertyDecl record.
+  DECL_OBJC_PROPERTY,
 
-      /// A FunctionDecl record.
-      DECL_FUNCTION,
+  /// A ObjCPropertyImplDecl record.
+  DECL_OBJC_PROPERTY_IMPL,
 
-      /// A ObjCMethodDecl record.
-      DECL_OBJC_METHOD,
+  /// A FieldDecl record.
+  DECL_FIELD,
 
-      /// A ObjCInterfaceDecl record.
-      DECL_OBJC_INTERFACE,
+  /// A MSPropertyDecl record.
+  DECL_MS_PROPERTY,
 
-      /// A ObjCProtocolDecl record.
-      DECL_OBJC_PROTOCOL,
+  /// A MSGuidDecl record.
+  DECL_MS_GUID,
 
-      /// A ObjCIvarDecl record.
-      DECL_OBJC_IVAR,
+  /// A TemplateParamObjectDecl record.
+  DECL_TEMPLATE_PARAM_OBJECT,
 
-      /// A ObjCAtDefsFieldDecl record.
-      DECL_OBJC_AT_DEFS_FIELD,
+  /// A VarDecl record.
+  DECL_VAR,
 
-      /// A ObjCCategoryDecl record.
-      DECL_OBJC_CATEGORY,
+  /// An ImplicitParamDecl record.
+  DECL_IMPLICIT_PARAM,
 
-      /// A ObjCCategoryImplDecl record.
-      DECL_OBJC_CATEGORY_IMPL,
+  /// A ParmVarDecl record.
+  DECL_PARM_VAR,
 
-      /// A ObjCImplementationDecl record.
-      DECL_OBJC_IMPLEMENTATION,
+  /// A DecompositionDecl record.
+  DECL_DECOMPOSITION,
 
-      /// A ObjCCompatibleAliasDecl record.
-      DECL_OBJC_COMPATIBLE_ALIAS,
+  /// A BindingDecl record.
+  DECL_BINDING,
 
-      /// A ObjCPropertyDecl record.
-      DECL_OBJC_PROPERTY,
+  /// A FileScopeAsmDecl record.
+  DECL_FILE_SCOPE_ASM,
 
-      /// A ObjCPropertyImplDecl record.
-      DECL_OBJC_PROPERTY_IMPL,
+  /// A BlockDecl record.
+  DECL_BLOCK,
 
-      /// A FieldDecl record.
-      DECL_FIELD,
+  /// A CapturedDecl record.
+  DECL_CAPTURED,
 
-      /// A MSPropertyDecl record.
-      DECL_MS_PROPERTY,
+  /// A record that stores the set of declarations that are
+  /// lexically stored within a given DeclContext.
+  ///
+  /// The record itself is a blob that is an array of declaration IDs,
+  /// in the order in which those declarations were added to the
+  /// declaration context. This data is used when iterating over
+  /// the contents of a DeclContext, e.g., via
+  /// DeclContext::decls_begin() and DeclContext::decls_end().
+  DECL_CONTEXT_LEXICAL,
 
-      /// A MSGuidDecl record.
-      DECL_MS_GUID,
+  /// A record that stores the set of declarations that are
+  /// visible from a given DeclContext.
+  ///
+  /// The record itself stores a set of mappings, each of which
+  /// associates a declaration name with one or more declaration
+  /// IDs. This data is used when performing qualified name lookup
+  /// into a DeclContext via DeclContext::lookup.
+  DECL_CONTEXT_VISIBLE,
 
-      /// A TemplateParamObjectDecl record.
-      DECL_TEMPLATE_PARAM_OBJECT,
+  /// A LabelDecl record.
+  DECL_LABEL,
 
-      /// A VarDecl record.
-      DECL_VAR,
+  /// A NamespaceDecl record.
+  DECL_NAMESPACE,
 
-      /// An ImplicitParamDecl record.
-      DECL_IMPLICIT_PARAM,
+  /// A NamespaceAliasDecl record.
+  DECL_NAMESPACE_ALIAS,
 
-      /// A ParmVarDecl record.
-      DECL_PARM_VAR,
+  /// A UsingDecl record.
+  DECL_USING,
 
-      /// A DecompositionDecl record.
-      DECL_DECOMPOSITION,
+  /// A UsingPackDecl record.
+  DECL_USING_PACK,
 
-      /// A BindingDecl record.
-      DECL_BINDING,
+  /// A UsingShadowDecl record.
+  DECL_USING_SHADOW,
 
-      /// A FileScopeAsmDecl record.
-      DECL_FILE_SCOPE_ASM,
+  /// A ConstructorUsingShadowDecl record.
+  DECL_CONSTRUCTOR_USING_SHADOW,
 
-      /// A BlockDecl record.
-      DECL_BLOCK,
+  /// A UsingDirecitveDecl record.
+  DECL_USING_DIRECTIVE,
 
-      /// A CapturedDecl record.
-      DECL_CAPTURED,
+  /// An UnresolvedUsingValueDecl record.
+  DECL_UNRESOLVED_USING_VALUE,
 
-      /// A record that stores the set of declarations that are
-      /// lexically stored within a given DeclContext.
-      ///
-      /// The record itself is a blob that is an array of declaration IDs,
-      /// in the order in which those declarations were added to the
-      /// declaration context. This data is used when iterating over
-      /// the contents of a DeclContext, e.g., via
-      /// DeclContext::decls_begin() and DeclContext::decls_end().
-      DECL_CONTEXT_LEXICAL,
+  /// An UnresolvedUsingTypenameDecl record.
+  DECL_UNRESOLVED_USING_TYPENAME,
 
-      /// A record that stores the set of declarations that are
-      /// visible from a given DeclContext.
-      ///
-      /// The record itself stores a set of mappings, each of which
-      /// associates a declaration name with one or more declaration
-      /// IDs. This data is used when performing qualified name lookup
-      /// into a DeclContext via DeclContext::lookup.
-      DECL_CONTEXT_VISIBLE,
+  /// A LinkageSpecDecl record.
+  DECL_LINKAGE_SPEC,
 
-      /// A LabelDecl record.
-      DECL_LABEL,
+  /// An ExportDecl record.
+  DECL_EXPORT,
 
-      /// A NamespaceDecl record.
-      DECL_NAMESPACE,
+  /// A CXXRecordDecl record.
+  DECL_CXX_RECORD,
 
-      /// A NamespaceAliasDecl record.
-      DECL_NAMESPACE_ALIAS,
+  /// A CXXDeductionGuideDecl record.
+  DECL_CXX_DEDUCTION_GUIDE,
 
-      /// A UsingDecl record.
-      DECL_USING,
+  /// A CXXMethodDecl record.
+  DECL_CXX_METHOD,
 
-      /// A UsingPackDecl record.
-      DECL_USING_PACK,
+  /// A CXXConstructorDecl record.
+  DECL_CXX_CONSTRUCTOR,
 
-      /// A UsingShadowDecl record.
-      DECL_USING_SHADOW,
+  /// A CXXDestructorDecl record.
+  DECL_CXX_DESTRUCTOR,
 
-      /// A ConstructorUsingShadowDecl record.
-      DECL_CONSTRUCTOR_USING_SHADOW,
+  /// A CXXConversionDecl record.
+  DECL_CXX_CONVERSION,
 
-      /// A UsingDirecitveDecl record.
-      DECL_USING_DIRECTIVE,
+  /// An AccessSpecDecl record.
+  DECL_ACCESS_SPEC,
 
-      /// An UnresolvedUsingValueDecl record.
-      DECL_UNRESOLVED_USING_VALUE,
+  /// A FriendDecl record.
+  DECL_FRIEND,
 
-      /// An UnresolvedUsingTypenameDecl record.
-      DECL_UNRESOLVED_USING_TYPENAME,
+  /// A FriendTemplateDecl record.
+  DECL_FRIEND_TEMPLATE,
 
-      /// A LinkageSpecDecl record.
-      DECL_LINKAGE_SPEC,
+  /// A ClassTemplateDecl record.
+  DECL_CLASS_TEMPLATE,
 
-      /// An ExportDecl record.
-      DECL_EXPORT,
+  /// A ClassTemplateSpecializationDecl record.
+  DECL_CLASS_TEMPLATE_SPECIALIZATION,
 
-      /// A CXXRecordDecl record.
-      DECL_CXX_RECORD,
+  /// A ClassTemplatePartialSpecializationDecl record.
+  DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,
 
-      /// A CXXDeductionGuideDecl record.
-      DECL_CXX_DEDUCTION_GUIDE,
+  /// A VarTemplateDecl record.
+  DECL_VAR_TEMPLATE,
 
-      /// A CXXMethodDecl record.
-      DECL_CXX_METHOD,
+  /// A VarTemplateSpecializationDecl record.
+  DECL_VAR_TEMPLATE_SPECIALIZATION,
 
-      /// A CXXConstructorDecl record.
-      DECL_CXX_CONSTRUCTOR,
+  /// A VarTemplatePartialSpecializationDecl record.
+  DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION,
 
-      /// A CXXDestructorDecl record.
-      DECL_CXX_DESTRUCTOR,
+  /// A FunctionTemplateDecl record.
+  DECL_FUNCTION_TEMPLATE,
 
-      /// A CXXConversionDecl record.
-      DECL_CXX_CONVERSION,
+  /// A TemplateTypeParmDecl record.
+  DECL_TEMPLATE_TYPE_PARM,
 
-      /// An AccessSpecDecl record.
-      DECL_ACCESS_SPEC,
+  /// A NonTypeTemplateParmDecl record.
+  DECL_NON_TYPE_TEMPLATE_PARM,
 
-      /// A FriendDecl record.
-      DECL_FRIEND,
+  /// A TemplateTemplateParmDecl record.
+  DECL_TEMPLATE_TEMPLATE_PARM,
 
-      /// A FriendTemplateDecl record.
-      DECL_FRIEND_TEMPLATE,
+  /// A TypeAliasTemplateDecl record.
+  DECL_TYPE_ALIAS_TEMPLATE,
 
-      /// A ClassTemplateDecl record.
-      DECL_CLASS_TEMPLATE,
+  /// \brief A ConceptDecl record.
+  DECL_CONCEPT,
 
-      /// A ClassTemplateSpecializationDecl record.
-      DECL_CLASS_TEMPLATE_SPECIALIZATION,
+  /// \brief A StaticAssertDecl record.
+  DECL_STATIC_ASSERT,
 
-      /// A ClassTemplatePartialSpecializationDecl record.
-      DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,
+  /// A record containing CXXBaseSpecifiers.
+  DECL_CXX_BASE_SPECIFIERS,
 
-      /// A VarTemplateDecl record.
-      DECL_VAR_TEMPLATE,
+  /// A record containing CXXCtorInitializers.
+  DECL_CXX_CTOR_INITIALIZERS,
 
-      /// A VarTemplateSpecializationDecl record.
-      DECL_VAR_TEMPLATE_SPECIALIZATION,
+  /// A IndirectFieldDecl record.
+  DECL_INDIRECTFIELD,
 
-      /// A VarTemplatePartialSpecializationDecl record.
-      DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION,
+  /// A NonTypeTemplateParmDecl record that stores an expanded
+  /// non-type template parameter pack.
+  DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK,
 
-      /// A FunctionTemplateDecl record.
-      DECL_FUNCTION_TEMPLATE,
+  /// A TemplateTemplateParmDecl record that stores an expanded
+  /// template template parameter pack.
+  DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK,
 
-      /// A TemplateTypeParmDecl record.
-      DECL_TEMPLATE_TYPE_PARM,
+  /// A ClassScopeFunctionSpecializationDecl record a class scope
+  /// function specialization. (Microsoft extension).
+  DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
 
-      /// A NonTypeTemplateParmDecl record.
-      DECL_NON_TYPE_TEMPLATE_PARM,
+  /// An ImportDecl recording a module import.
+  DECL_IMPORT,
 
-      /// A TemplateTemplateParmDecl record.
-      DECL_TEMPLATE_TEMPLATE_PARM,
+  /// An OMPThreadPrivateDecl record.
+  DECL_OMP_THREADPRIVATE,
 
-      /// A TypeAliasTemplateDecl record.
-      DECL_TYPE_ALIAS_TEMPLATE,
+  /// An OMPRequiresDecl record.
+  DECL_OMP_REQUIRES,
 
-      /// \brief A ConceptDecl record.
-      DECL_CONCEPT,
+  /// An OMPAllocateDcl record.
+  DECL_OMP_ALLOCATE,
 
-      /// \brief A StaticAssertDecl record.
-      DECL_STATIC_ASSERT,
+  /// An EmptyDecl record.
+  DECL_EMPTY,
 
-      /// A record containing CXXBaseSpecifiers.
-      DECL_CXX_BASE_SPECIFIERS,
+  /// An LifetimeExtendedTemporaryDecl record.
+  DECL_LIFETIME_EXTENDED_TEMPORARY,
 
-      /// A record containing CXXCtorInitializers.
-      DECL_CXX_CTOR_INITIALIZERS,
+  /// A RequiresExprBodyDecl record.
+  DECL_REQUIRES_EXPR_BODY,
 
-      /// A IndirectFieldDecl record.
-      DECL_INDIRECTFIELD,
+  /// An ObjCTypeParamDecl record.
+  DECL_OBJC_TYPE_PARAM,
 
-      /// A NonTypeTemplateParmDecl record that stores an expanded
-      /// non-type template parameter pack.
-      DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK,
+  /// An OMPCapturedExprDecl record.
+  DECL_OMP_CAPTUREDEXPR,
 
-      /// A TemplateTemplateParmDecl record that stores an expanded
-      /// template template parameter pack.
-      DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK,
+  /// A PragmaCommentDecl record.
+  DECL_PRAGMA_COMMENT,
 
-      /// A ClassScopeFunctionSpecializationDecl record a class scope
-      /// function specialization. (Microsoft extension).
-      DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
+  /// A PragmaDetectMismatchDecl record.
+  DECL_PRAGMA_DETECT_MISMATCH,
 
-      /// An ImportDecl recording a module import.
-      DECL_IMPORT,
+  /// An OMPDeclareMapperDecl record.
+  DECL_OMP_DECLARE_MAPPER,
 
-      /// An OMPThreadPrivateDecl record.
-      DECL_OMP_THREADPRIVATE,
+  /// An OMPDeclareReductionDecl record.
+  DECL_OMP_DECLARE_REDUCTION,
 
-      /// An OMPRequiresDecl record.
-      DECL_OMP_REQUIRES,
+  DECL_LAST = DECL_OMP_DECLARE_REDUCTION
+};
 
-      /// An OMPAllocateDcl record.
-      DECL_OMP_ALLOCATE,
+/// Record codes for each kind of statement or expression.
+///
+/// These constants describe the records that describe statements
+/// or expressions. These records  occur within type and declarations
+/// block, so they begin with record values of 128.  Each constant
+/// describes a record for a specific statement or expression class in the
+/// AST.
+enum StmtCode {
+  /// A marker record that indicates that we are at the end
+  /// of an expression.
+  STMT_STOP = DECL_LAST + 1,
 
-      /// An EmptyDecl record.
-      DECL_EMPTY,
+  /// A NULL expression.
+  STMT_NULL_PTR,
 
-      /// An LifetimeExtendedTemporaryDecl record.
-      DECL_LIFETIME_EXTENDED_TEMPORARY,
+  /// A reference to a previously [de]serialized Stmt record.
+  STMT_REF_PTR,
 
-      /// A RequiresExprBodyDecl record.
-      DECL_REQUIRES_EXPR_BODY,
+  /// A NullStmt record.
+  STMT_NULL,
 
-      /// An ObjCTypeParamDecl record.
-      DECL_OBJC_TYPE_PARAM,
+  /// A CompoundStmt record.
+  STMT_COMPOUND,
 
-      /// An OMPCapturedExprDecl record.
-      DECL_OMP_CAPTUREDEXPR,
+  /// A CaseStmt record.
+  STMT_CASE,
 
-      /// A PragmaCommentDecl record.
-      DECL_PRAGMA_COMMENT,
+  /// A DefaultStmt record.
+  STMT_DEFAULT,
 
-      /// A PragmaDetectMismatchDecl record.
-      DECL_PRAGMA_DETECT_MISMATCH,
+  /// A LabelStmt record.
+  STMT_LABEL,
 
-      /// An OMPDeclareMapperDecl record.
-      DECL_OMP_DECLARE_MAPPER,
+  /// An AttributedStmt record.
+  STMT_ATTRIBUTED,
 
-      /// An OMPDeclareReductionDecl record.
-      DECL_OMP_DECLARE_REDUCTION,
+  /// An IfStmt record.
+  STMT_IF,
 
-      DECL_LAST = DECL_OMP_DECLARE_REDUCTION
-    };
+  /// A SwitchStmt record.
+  STMT_SWITCH,
 
-    /// Record codes for each kind of statement or expression.
-    ///
-    /// These constants describe the records that describe statements
-    /// or expressions. These records  occur within type and declarations
-    /// block, so they begin with record values of 128.  Each constant
-    /// describes a record for a specific statement or expression class in the
-    /// AST.
-    enum StmtCode {
-      /// A marker record that indicates that we are at the end
-      /// of an expression.
-      STMT_STOP = DECL_LAST + 1,
+  /// A WhileStmt record.
+  STMT_WHILE,
 
-      /// A NULL expression.
-      STMT_NULL_PTR,
+  /// A DoStmt record.
+  STMT_DO,
 
-      /// A reference to a previously [de]serialized Stmt record.
-      STMT_REF_PTR,
+  /// A ForStmt record.
+  STMT_FOR,
 
-      /// A NullStmt record.
-      STMT_NULL,
+  /// A GotoStmt record.
+  STMT_GOTO,
 
-      /// A CompoundStmt record.
-      STMT_COMPOUND,
+  /// An IndirectGotoStmt record.
+  STMT_INDIRECT_GOTO,
 
-      /// A CaseStmt record.
-      STMT_CASE,
+  /// A ContinueStmt record.
+  STMT_CONTINUE,
 
-      /// A DefaultStmt record.
-      STMT_DEFAULT,
+  /// A BreakStmt record.
+  STMT_BREAK,
 
-      /// A LabelStmt record.
-      STMT_LABEL,
+  /// A ReturnStmt record.
+  STMT_RETURN,
 
-      /// An AttributedStmt record.
-      STMT_ATTRIBUTED,
+  /// A DeclStmt record.
+  STMT_DECL,
 
-      /// An IfStmt record.
-      STMT_IF,
+  /// A CapturedStmt record.
+  STMT_CAPTURED,
 
-      /// A SwitchStmt record.
-      STMT_SWITCH,
+  /// A GCC-style AsmStmt record.
+  STMT_GCCASM,
 
-      /// A WhileStmt record.
-      STMT_WHILE,
+  /// A MS-style AsmStmt record.
+  STMT_MSASM,
 
-      /// A DoStmt record.
-      STMT_DO,
+  /// A constant expression context.
+  EXPR_CONSTANT,
 
-      /// A ForStmt record.
-      STMT_FOR,
+  /// A PredefinedExpr record.
+  EXPR_PREDEFINED,
 
-      /// A GotoStmt record.
-      STMT_GOTO,
+  /// A DeclRefExpr record.
+  EXPR_DECL_REF,
 
-      /// An IndirectGotoStmt record.
-      STMT_INDIRECT_GOTO,
+  /// An IntegerLiteral record.
+  EXPR_INTEGER_LITERAL,
 
-      /// A ContinueStmt record.
-      STMT_CONTINUE,
+  /// A FloatingLiteral record.
+  EXPR_FLOATING_LITERAL,
 
-      /// A BreakStmt record.
-      STMT_BREAK,
+  /// An ImaginaryLiteral record.
+  EXPR_IMAGINARY_LITERAL,
 
-      /// A ReturnStmt record.
-      STMT_RETURN,
+  /// A StringLiteral record.
+  EXPR_STRING_LITERAL,
 
-      /// A DeclStmt record.
-      STMT_DECL,
+  /// A CharacterLiteral record.
+  EXPR_CHARACTER_LITERAL,
 
-      /// A CapturedStmt record.
-      STMT_CAPTURED,
+  /// A ParenExpr record.
+  EXPR_PAREN,
 
-      /// A GCC-style AsmStmt record.
-      STMT_GCCASM,
+  /// A ParenListExpr record.
+  EXPR_PAREN_LIST,
 
-      /// A MS-style AsmStmt record.
-      STMT_MSASM,
+  /// A UnaryOperator record.
+  EXPR_UNARY_OPERATOR,
 
-      /// A constant expression context.
-      EXPR_CONSTANT,
+  /// An OffsetOfExpr record.
+  EXPR_OFFSETOF,
 
-      /// A PredefinedExpr record.
-      EXPR_PREDEFINED,
+  /// A SizefAlignOfExpr record.
+  EXPR_SIZEOF_ALIGN_OF,
 
-      /// A DeclRefExpr record.
-      EXPR_DECL_REF,
+  /// An ArraySubscriptExpr record.
+  EXPR_ARRAY_SUBSCRIPT,
 
-      /// An IntegerLiteral record.
-      EXPR_INTEGER_LITERAL,
+  /// An MatrixSubscriptExpr record.
+  EXPR_MATRIX_SUBSCRIPT,
 
-      /// A FloatingLiteral record.
-      EXPR_FLOATING_LITERAL,
+  /// A CallExpr record.
+  EXPR_CALL,
 
-      /// An ImaginaryLiteral record.
-      EXPR_IMAGINARY_LITERAL,
+  /// A MemberExpr record.
+  EXPR_MEMBER,
 
-      /// A StringLiteral record.
-      EXPR_STRING_LITERAL,
+  /// A BinaryOperator record.
+  EXPR_BINARY_OPERATOR,
 
-      /// A CharacterLiteral record.
-      EXPR_CHARACTER_LITERAL,
+  /// A CompoundAssignOperator record.
+  EXPR_COMPOUND_ASSIGN_OPERATOR,
 
-      /// A ParenExpr record.
-      EXPR_PAREN,
+  /// A ConditionOperator record.
+  EXPR_CONDITIONAL_OPERATOR,
 
-      /// A ParenListExpr record.
-      EXPR_PAREN_LIST,
+  /// An ImplicitCastExpr record.
+  EXPR_IMPLICIT_CAST,
 
-      /// A UnaryOperator record.
-      EXPR_UNARY_OPERATOR,
+  /// A CStyleCastExpr record.
+  EXPR_CSTYLE_CAST,
 
-      /// An OffsetOfExpr record.
-      EXPR_OFFSETOF,
+  /// A CompoundLiteralExpr record.
+  EXPR_COMPOUND_LITERAL,
 
-      /// A SizefAlignOfExpr record.
-      EXPR_SIZEOF_ALIGN_OF,
+  /// An ExtVectorElementExpr record.
+  EXPR_EXT_VECTOR_ELEMENT,
 
-      /// An ArraySubscriptExpr record.
-      EXPR_ARRAY_SUBSCRIPT,
+  /// An InitListExpr record.
+  EXPR_INIT_LIST,
 
-      /// An MatrixSubscriptExpr record.
-      EXPR_MATRIX_SUBSCRIPT,
+  /// A DesignatedInitExpr record.
+  EXPR_DESIGNATED_INIT,
 
-      /// A CallExpr record.
-      EXPR_CALL,
+  /// A DesignatedInitUpdateExpr record.
+  EXPR_DESIGNATED_INIT_UPDATE,
 
-      /// A MemberExpr record.
-      EXPR_MEMBER,
+  /// An NoInitExpr record.
+  EXPR_NO_INIT,
 
-      /// A BinaryOperator record.
-      EXPR_BINARY_OPERATOR,
+  /// An ArrayInitLoopExpr record.
+  EXPR_ARRAY_INIT_LOOP,
 
-      /// A CompoundAssignOperator record.
-      EXPR_COMPOUND_ASSIGN_OPERATOR,
+  /// An ArrayInitIndexExpr record.
+  EXPR_ARRAY_INIT_INDEX,
 
-      /// A ConditionOperator record.
-      EXPR_CONDITIONAL_OPERATOR,
+  /// An ImplicitValueInitExpr record.
+  EXPR_IMPLICIT_VALUE_INIT,
 
-      /// An ImplicitCastExpr record.
-      EXPR_IMPLICIT_CAST,
+  /// A VAArgExpr record.
+  EXPR_VA_ARG,
 
-      /// A CStyleCastExpr record.
-      EXPR_CSTYLE_CAST,
+  /// An AddrLabelExpr record.
+  EXPR_ADDR_LABEL,
 
-      /// A CompoundLiteralExpr record.
-      EXPR_COMPOUND_LITERAL,
+  /// A StmtExpr record.
+  EXPR_STMT,
 
-      /// An ExtVectorElementExpr record.
-      EXPR_EXT_VECTOR_ELEMENT,
+  /// A ChooseExpr record.
+  EXPR_CHOOSE,
 
-      /// An InitListExpr record.
-      EXPR_INIT_LIST,
+  /// A GNUNullExpr record.
+  EXPR_GNU_NULL,
 
-      /// A DesignatedInitExpr record.
-      EXPR_DESIGNATED_INIT,
+  /// A SourceLocExpr record.
+  EXPR_SOURCE_LOC,
 
-      /// A DesignatedInitUpdateExpr record.
-      EXPR_DESIGNATED_INIT_UPDATE,
+  /// A ShuffleVectorExpr record.
+  EXPR_SHUFFLE_VECTOR,
 
-      /// An NoInitExpr record.
-      EXPR_NO_INIT,
+  /// A ConvertVectorExpr record.
+  EXPR_CONVERT_VECTOR,
 
-      /// An ArrayInitLoopExpr record.
-      EXPR_ARRAY_INIT_LOOP,
+  /// BlockExpr
+  EXPR_BLOCK,
 
-      /// An ArrayInitIndexExpr record.
-      EXPR_ARRAY_INIT_INDEX,
+  /// A GenericSelectionExpr record.
+  EXPR_GENERIC_SELECTION,
 
-      /// An ImplicitValueInitExpr record.
-      EXPR_IMPLICIT_VALUE_INIT,
+  /// A PseudoObjectExpr record.
+  EXPR_PSEUDO_OBJECT,
 
-      /// A VAArgExpr record.
-      EXPR_VA_ARG,
+  /// An AtomicExpr record.
+  EXPR_ATOMIC,
 
-      /// An AddrLabelExpr record.
-      EXPR_ADDR_LABEL,
+  /// A RecoveryExpr record.
+  EXPR_RECOVERY,
 
-      /// A StmtExpr record.
-      EXPR_STMT,
+  // Objective-C
 
-      /// A ChooseExpr record.
-      EXPR_CHOOSE,
+  /// An ObjCStringLiteral record.
+  EXPR_OBJC_STRING_LITERAL,
 
-      /// A GNUNullExpr record.
-      EXPR_GNU_NULL,
+  EXPR_OBJC_BOXED_EXPRESSION,
+  EXPR_OBJC_ARRAY_LITERAL,
+  EXPR_OBJC_DICTIONARY_LITERAL,
 
-      /// A SourceLocExpr record.
-      EXPR_SOURCE_LOC,
+  /// An ObjCEncodeExpr record.
+  EXPR_OBJC_ENCODE,
 
-      /// A ShuffleVectorExpr record.
-      EXPR_SHUFFLE_VECTOR,
+  /// An ObjCSelectorExpr record.
+  EXPR_OBJC_SELECTOR_EXPR,
 
-      /// A ConvertVectorExpr record.
-      EXPR_CONVERT_VECTOR,
+  /// An ObjCProtocolExpr record.
+  EXPR_OBJC_PROTOCOL_EXPR,
 
-      /// BlockExpr
-      EXPR_BLOCK,
+  /// An ObjCIvarRefExpr record.
+  EXPR_OBJC_IVAR_REF_EXPR,
 
-      /// A GenericSelectionExpr record.
-      EXPR_GENERIC_SELECTION,
+  /// An ObjCPropertyRefExpr record.
+  EXPR_OBJC_PROPERTY_REF_EXPR,
 
-      /// A PseudoObjectExpr record.
-      EXPR_PSEUDO_OBJECT,
+  /// An ObjCSubscriptRefExpr record.
+  EXPR_OBJC_SUBSCRIPT_REF_EXPR,
 
-      /// An AtomicExpr record.
-      EXPR_ATOMIC,
+  /// UNUSED
+  EXPR_OBJC_KVC_REF_EXPR,
 
-      /// A RecoveryExpr record.
-      EXPR_RECOVERY,
+  /// An ObjCMessageExpr record.
+  EXPR_OBJC_MESSAGE_EXPR,
 
-      // Objective-C
+  /// An ObjCIsa Expr record.
+  EXPR_OBJC_ISA,
 
-      /// An ObjCStringLiteral record.
-      EXPR_OBJC_STRING_LITERAL,
+  /// An ObjCIndirectCopyRestoreExpr record.
+  EXPR_OBJC_INDIRECT_COPY_RESTORE,
 
-      EXPR_OBJC_BOXED_EXPRESSION,
-      EXPR_OBJC_ARRAY_LITERAL,
-      EXPR_OBJC_DICTIONARY_LITERAL,
+  /// An ObjCForCollectionStmt record.
+  STMT_OBJC_FOR_COLLECTION,
 
-      /// An ObjCEncodeExpr record.
-      EXPR_OBJC_ENCODE,
+  /// An ObjCAtCatchStmt record.
+  STMT_OBJC_CATCH,
 
-      /// An ObjCSelectorExpr record.
-      EXPR_OBJC_SELECTOR_EXPR,
+  /// An ObjCAtFinallyStmt record.
+  STMT_OBJC_FINALLY,
 
-      /// An ObjCProtocolExpr record.
-      EXPR_OBJC_PROTOCOL_EXPR,
+  /// An ObjCAtTryStmt record.
+  STMT_OBJC_AT_TRY,
 
-      /// An ObjCIvarRefExpr record.
-      EXPR_OBJC_IVAR_REF_EXPR,
+  /// An ObjCAtSynchronizedStmt record.
+  STMT_OBJC_AT_SYNCHRONIZED,
 
-      /// An ObjCPropertyRefExpr record.
-      EXPR_OBJC_PROPERTY_REF_EXPR,
+  /// An ObjCAtThrowStmt record.
+  STMT_OBJC_AT_THROW,
 
-      /// An ObjCSubscriptRefExpr record.
-      EXPR_OBJC_SUBSCRIPT_REF_EXPR,
+  /// An ObjCAutoreleasePoolStmt record.
+  STMT_OBJC_AUTORELEASE_POOL,
 
-      /// UNUSED
-      EXPR_OBJC_KVC_REF_EXPR,
+  /// An ObjCBoolLiteralExpr record.
+  EXPR_OBJC_BOOL_LITERAL,
 
-      /// An ObjCMessageExpr record.
-      EXPR_OBJC_MESSAGE_EXPR,
+  /// An ObjCAvailabilityCheckExpr record.
+  EXPR_OBJC_AVAILABILITY_CHECK,
 
-      /// An ObjCIsa Expr record.
-      EXPR_OBJC_ISA,
+  // C++
 
-      /// An ObjCIndirectCopyRestoreExpr record.
-      EXPR_OBJC_INDIRECT_COPY_RESTORE,
+  /// A CXXCatchStmt record.
+  STMT_CXX_CATCH,
 
-      /// An ObjCForCollectionStmt record.
-      STMT_OBJC_FOR_COLLECTION,
+  /// A CXXTryStmt record.
+  STMT_CXX_TRY,
+  /// A CXXForRangeStmt record.
 
-      /// An ObjCAtCatchStmt record.
-      STMT_OBJC_CATCH,
+  STMT_CXX_FOR_RANGE,
 
-      /// An ObjCAtFinallyStmt record.
-      STMT_OBJC_FINALLY,
+  /// A CXXOperatorCallExpr record.
+  EXPR_CXX_OPERATOR_CALL,
 
-      /// An ObjCAtTryStmt record.
-      STMT_OBJC_AT_TRY,
+  /// A CXXMemberCallExpr record.
+  EXPR_CXX_MEMBER_CALL,
 
-      /// An ObjCAtSynchronizedStmt record.
-      STMT_OBJC_AT_SYNCHRONIZED,
+  /// A CXXRewrittenBinaryOperator record.
+  EXPR_CXX_REWRITTEN_BINARY_OPERATOR,
 
-      /// An ObjCAtThrowStmt record.
-      STMT_OBJC_AT_THROW,
+  /// A CXXConstructExpr record.
+  EXPR_CXX_CONSTRUCT,
 
-      /// An ObjCAutoreleasePoolStmt record.
-      STMT_OBJC_AUTORELEASE_POOL,
+  /// A CXXInheritedCtorInitExpr record.
+  EXPR_CXX_INHERITED_CTOR_INIT,
 
-      /// An ObjCBoolLiteralExpr record.
-      EXPR_OBJC_BOOL_LITERAL,
+  /// A CXXTemporaryObjectExpr record.
+  EXPR_CXX_TEMPORARY_OBJECT,
 
-      /// An ObjCAvailabilityCheckExpr record.
-      EXPR_OBJC_AVAILABILITY_CHECK,
+  /// A CXXStaticCastExpr record.
+  EXPR_CXX_STATIC_CAST,
 
-      // C++
+  /// A CXXDynamicCastExpr record.
+  EXPR_CXX_DYNAMIC_CAST,
 
-      /// A CXXCatchStmt record.
-      STMT_CXX_CATCH,
+  /// A CXXReinterpretCastExpr record.
+  EXPR_CXX_REINTERPRET_CAST,
 
-      /// A CXXTryStmt record.
-      STMT_CXX_TRY,
-      /// A CXXForRangeStmt record.
+  /// A CXXConstCastExpr record.
+  EXPR_CXX_CONST_CAST,
 
-      STMT_CXX_FOR_RANGE,
+  /// A CXXAddrspaceCastExpr record.
+  EXPR_CXX_ADDRSPACE_CAST,
+
+  /// A CXXFunctionalCastExpr record.
+  EXPR_CXX_FUNCTIONAL_CAST,
+
+  /// A BuiltinBitCastExpr record.
+  EXPR_BUILTIN_BIT_CAST,
+
+  /// A UserDefinedLiteral record.
+  EXPR_USER_DEFINED_LITERAL,
+
+  /// A CXXStdInitializerListExpr record.
+  EXPR_CXX_STD_INITIALIZER_LIST,
+
+  /// A CXXBoolLiteralExpr record.
+  EXPR_CXX_BOOL_LITERAL,
+
+  EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
+  EXPR_CXX_TYPEID_EXPR,      // CXXTypeidExpr (of expr).
+  EXPR_CXX_TYPEID_TYPE,      // CXXTypeidExpr (of type).
+  EXPR_CXX_THIS,             // CXXThisExpr
+  EXPR_CXX_THROW,            // CXXThrowExpr
+  EXPR_CXX_DEFAULT_ARG,      // CXXDefaultArgExpr
+  EXPR_CXX_DEFAULT_INIT,     // CXXDefaultInitExpr
+  EXPR_CXX_BIND_TEMPORARY,   // CXXBindTemporaryExpr
+
+  EXPR_CXX_SCALAR_VALUE_INIT, // CXXScalarValueInitExpr
+  EXPR_CXX_NEW,               // CXXNewExpr
+  EXPR_CXX_DELETE,            // CXXDeleteExpr
+  EXPR_CXX_PSEUDO_DESTRUCTOR, // CXXPseudoDestructorExpr
+
+  EXPR_EXPR_WITH_CLEANUPS, // ExprWithCleanups
+
+  EXPR_CXX_DEPENDENT_SCOPE_MEMBER,   // CXXDependentScopeMemberExpr
+  EXPR_CXX_DEPENDENT_SCOPE_DECL_REF, // DependentScopeDeclRefExpr
+  EXPR_CXX_UNRESOLVED_CONSTRUCT,     // CXXUnresolvedConstructExpr
+  EXPR_CXX_UNRESOLVED_MEMBER,        // UnresolvedMemberExpr
+  EXPR_CXX_UNRESOLVED_LOOKUP,        // UnresolvedLookupExpr
+
+  EXPR_CXX_EXPRESSION_TRAIT, // ExpressionTraitExpr
+  EXPR_CXX_NOEXCEPT,         // CXXNoexceptExpr
+
+  EXPR_OPAQUE_VALUE,                // OpaqueValueExpr
+  EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator
+  EXPR_TYPE_TRAIT,                  // TypeTraitExpr
+  EXPR_ARRAY_TYPE_TRAIT,            // ArrayTypeTraitIntExpr
+
+  EXPR_PACK_EXPANSION,                    // PackExpansionExpr
+  EXPR_SIZEOF_PACK,                       // SizeOfPackExpr
+  EXPR_SUBST_NON_TYPE_TEMPLATE_PARM,      // SubstNonTypeTemplateParmExpr
+  EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK, // SubstNonTypeTemplateParmPackExpr
+  EXPR_FUNCTION_PARM_PACK,                // FunctionParmPackExpr
+  EXPR_MATERIALIZE_TEMPORARY,             // MaterializeTemporaryExpr
+  EXPR_CXX_FOLD,                          // CXXFoldExpr
+  EXPR_CONCEPT_SPECIALIZATION,            // ConceptSpecializationExpr
+  EXPR_REQUIRES,                          // RequiresExpr
+
+  // CUDA
+  EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
+
+  // OpenCL
+  EXPR_ASTYPE, // AsTypeExpr
+
+  // Microsoft
+  EXPR_CXX_PROPERTY_REF_EXPR,       // MSPropertyRefExpr
+  EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR, // MSPropertySubscriptExpr
+  EXPR_CXX_UUIDOF_EXPR,             // CXXUuidofExpr (of expr).
+  EXPR_CXX_UUIDOF_TYPE,             // CXXUuidofExpr (of type).
+  STMT_SEH_LEAVE,                   // SEHLeaveStmt
+  STMT_SEH_EXCEPT,                  // SEHExceptStmt
+  STMT_SEH_FINALLY,                 // SEHFinallyStmt
+  STMT_SEH_TRY,                     // SEHTryStmt
+
+  // OpenMP directives
+  STMT_OMP_CANONICAL_LOOP,
+  STMT_OMP_PARALLEL_DIRECTIVE,
+  STMT_OMP_SIMD_DIRECTIVE,
+  STMT_OMP_TILE_DIRECTIVE,
+  STMT_OMP_FOR_DIRECTIVE,
+  STMT_OMP_FOR_SIMD_DIRECTIVE,
+  STMT_OMP_SECTIONS_DIRECTIVE,
+  STMT_OMP_SECTION_DIRECTIVE,
+  STMT_OMP_SINGLE_DIRECTIVE,
+  STMT_OMP_MASTER_DIRECTIVE,
+  STMT_OMP_CRITICAL_DIRECTIVE,
+  STMT_OMP_PARALLEL_FOR_DIRECTIVE,
+  STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE,
+  STMT_OMP_PARALLEL_MASTER_DIRECTIVE,
+  STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE,
+  STMT_OMP_TASK_DIRECTIVE,
+  STMT_OMP_TASKYIELD_DIRECTIVE,
+  STMT_OMP_BARRIER_DIRECTIVE,
+  STMT_OMP_TASKWAIT_DIRECTIVE,
+  STMT_OMP_FLUSH_DIRECTIVE,
+  STMT_OMP_DEPOBJ_DIRECTIVE,
+  STMT_OMP_SCAN_DIRECTIVE,
+  STMT_OMP_ORDERED_DIRECTIVE,
+  STMT_OMP_ATOMIC_DIRECTIVE,
+  STMT_OMP_TARGET_DIRECTIVE,
+  STMT_OMP_TARGET_DATA_DIRECTIVE,
+  STMT_OMP_TARGET_ENTER_DATA_DIRECTIVE,
+  STMT_OMP_TARGET_EXIT_DATA_DIRECTIVE,
+  STMT_OMP_TARGET_PARALLEL_DIRECTIVE,
+  STMT_OMP_TARGET_PARALLEL_FOR_DIRECTIVE,
+  STMT_OMP_TEAMS_DIRECTIVE,
+  STMT_OMP_TASKGROUP_DIRECTIVE,
+  STMT_OMP_CANCELLATION_POINT_DIRECTIVE,
+  STMT_OMP_CANCEL_DIRECTIVE,
+  STMT_OMP_TASKLOOP_DIRECTIVE,
+  STMT_OMP_TASKLOOP_SIMD_DIRECTIVE,
+  STMT_OMP_MASTER_TASKLOOP_DIRECTIVE,
+  STMT_OMP_MASTER_TASKLOOP_SIMD_DIRECTIVE,
+  STMT_OMP_PARALLEL_MASTER_TASKLOOP_DIRECTIVE,
+  STMT_OMP_PARALLEL_MASTER_TASKLOOP_SIMD_DIRECTIVE,
+  STMT_OMP_DISTRIBUTE_DIRECTIVE,
+  STMT_OMP_TARGET_UPDATE_DIRECTIVE,
+  STMT_OMP_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
+  STMT_OMP_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
+  STMT_OMP_DISTRIBUTE_SIMD_DIRECTIVE,
+  STMT_OMP_TARGET_PARALLEL_FOR_SIMD_DIRECTIVE,
+  STMT_OMP_TARGET_SIMD_DIRECTIVE,
+  STMT_OMP_TEAMS_DISTRIBUTE_DIRECTIVE,
+  STMT_OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE,
+  STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
+  STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
+  STMT_OMP_TARGET_TEAMS_DIRECTIVE,
+  STMT_OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE,
+  STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
+  STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
+  STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE,
+  EXPR_OMP_ARRAY_SECTION,
+  EXPR_OMP_ARRAY_SHAPING,
+  EXPR_OMP_ITERATOR,
+
+  // ARC
+  EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
+
+  STMT_MS_DEPENDENT_EXISTS, // MSDependentExistsStmt
+  EXPR_LAMBDA,              // LambdaExpr
+  STMT_COROUTINE_BODY,
+  STMT_CORETURN,
+  EXPR_COAWAIT,
+  EXPR_COYIELD,
+  EXPR_DEPENDENT_COAWAIT,
+
+  // FixedPointLiteral
+  EXPR_FIXEDPOINT_LITERAL,
+};
 
-      /// A CXXOperatorCallExpr record.
-      EXPR_CXX_OPERATOR_CALL,
+/// The kinds of designators that can occur in a
+/// DesignatedInitExpr.
+enum DesignatorTypes {
+  /// Field designator where only the field name is known.
+  DESIG_FIELD_NAME = 0,
 
-      /// A CXXMemberCallExpr record.
-      EXPR_CXX_MEMBER_CALL,
+  /// Field designator where the field has been resolved to
+  /// a declaration.
+  DESIG_FIELD_DECL = 1,
 
-      /// A CXXRewrittenBinaryOperator record.
-      EXPR_CXX_REWRITTEN_BINARY_OPERATOR,
+  /// Array designator.
+  DESIG_ARRAY = 2,
 
-      /// A CXXConstructExpr record.
-      EXPR_CXX_CONSTRUCT,
+  /// GNU array range designator.
+  DESIG_ARRAY_RANGE = 3
+};
 
-      /// A CXXInheritedCtorInitExpr record.
-      EXPR_CXX_INHERITED_CTOR_INIT,
+/// The 
diff erent kinds of data that can occur in a
+/// CtorInitializer.
+enum CtorInitializerType {
+  CTOR_INITIALIZER_BASE,
+  CTOR_INITIALIZER_DELEGATING,
+  CTOR_INITIALIZER_MEMBER,
+  CTOR_INITIALIZER_INDIRECT_MEMBER
+};
 
-      /// A CXXTemporaryObjectExpr record.
-      EXPR_CXX_TEMPORARY_OBJECT,
+/// Kinds of cleanup objects owned by ExprWithCleanups.
+enum CleanupObjectKind { COK_Block, COK_CompoundLiteral };
 
-      /// A CXXStaticCastExpr record.
-      EXPR_CXX_STATIC_CAST,
+/// Describes the redeclarations of a declaration.
+struct LocalRedeclarationsInfo {
+  // The ID of the first declaration
+  DeclID FirstID;
 
-      /// A CXXDynamicCastExpr record.
-      EXPR_CXX_DYNAMIC_CAST,
+  // Offset into the array of redeclaration chains.
+  unsigned Offset;
 
-      /// A CXXReinterpretCastExpr record.
-      EXPR_CXX_REINTERPRET_CAST,
+  friend bool operator<(const LocalRedeclarationsInfo &X,
+                        const LocalRedeclarationsInfo &Y) {
+    return X.FirstID < Y.FirstID;
+  }
 
-      /// A CXXConstCastExpr record.
-      EXPR_CXX_CONST_CAST,
+  friend bool operator>(const LocalRedeclarationsInfo &X,
+                        const LocalRedeclarationsInfo &Y) {
+    return X.FirstID > Y.FirstID;
+  }
 
-      /// A CXXAddrspaceCastExpr record.
-      EXPR_CXX_ADDRSPACE_CAST,
-
-      /// A CXXFunctionalCastExpr record.
-      EXPR_CXX_FUNCTIONAL_CAST,
-
-      /// A BuiltinBitCastExpr record.
-      EXPR_BUILTIN_BIT_CAST,
-
-      /// A UserDefinedLiteral record.
-      EXPR_USER_DEFINED_LITERAL,
-
-      /// A CXXStdInitializerListExpr record.
-      EXPR_CXX_STD_INITIALIZER_LIST,
-
-      /// A CXXBoolLiteralExpr record.
-      EXPR_CXX_BOOL_LITERAL,
-
-      EXPR_CXX_NULL_PTR_LITERAL,  // CXXNullPtrLiteralExpr
-      EXPR_CXX_TYPEID_EXPR,       // CXXTypeidExpr (of expr).
-      EXPR_CXX_TYPEID_TYPE,       // CXXTypeidExpr (of type).
-      EXPR_CXX_THIS,              // CXXThisExpr
-      EXPR_CXX_THROW,             // CXXThrowExpr
-      EXPR_CXX_DEFAULT_ARG,       // CXXDefaultArgExpr
-      EXPR_CXX_DEFAULT_INIT,      // CXXDefaultInitExpr
-      EXPR_CXX_BIND_TEMPORARY,    // CXXBindTemporaryExpr
-
-      EXPR_CXX_SCALAR_VALUE_INIT, // CXXScalarValueInitExpr
-      EXPR_CXX_NEW,               // CXXNewExpr
-      EXPR_CXX_DELETE,            // CXXDeleteExpr
-      EXPR_CXX_PSEUDO_DESTRUCTOR, // CXXPseudoDestructorExpr
-
-      EXPR_EXPR_WITH_CLEANUPS,    // ExprWithCleanups
-
-      EXPR_CXX_DEPENDENT_SCOPE_MEMBER,   // CXXDependentScopeMemberExpr
-      EXPR_CXX_DEPENDENT_SCOPE_DECL_REF, // DependentScopeDeclRefExpr
-      EXPR_CXX_UNRESOLVED_CONSTRUCT,     // CXXUnresolvedConstructExpr
-      EXPR_CXX_UNRESOLVED_MEMBER,        // UnresolvedMemberExpr
-      EXPR_CXX_UNRESOLVED_LOOKUP,        // UnresolvedLookupExpr
-
-      EXPR_CXX_EXPRESSION_TRAIT,  // ExpressionTraitExpr
-      EXPR_CXX_NOEXCEPT,          // CXXNoexceptExpr
-
-      EXPR_OPAQUE_VALUE,          // OpaqueValueExpr
-      EXPR_BINARY_CONDITIONAL_OPERATOR,  // BinaryConditionalOperator
-      EXPR_TYPE_TRAIT,            // TypeTraitExpr
-      EXPR_ARRAY_TYPE_TRAIT,      // ArrayTypeTraitIntExpr
-
-      EXPR_PACK_EXPANSION,        // PackExpansionExpr
-      EXPR_SIZEOF_PACK,           // SizeOfPackExpr
-      EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, // SubstNonTypeTemplateParmExpr
-      EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr
-      EXPR_FUNCTION_PARM_PACK,    // FunctionParmPackExpr
-      EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
-      EXPR_CXX_FOLD,              // CXXFoldExpr
-      EXPR_CONCEPT_SPECIALIZATION,// ConceptSpecializationExpr
-      EXPR_REQUIRES,              // RequiresExpr
-
-      // CUDA
-      EXPR_CUDA_KERNEL_CALL,       // CUDAKernelCallExpr
-
-      // OpenCL
-      EXPR_ASTYPE,                 // AsTypeExpr
-
-      // Microsoft
-      EXPR_CXX_PROPERTY_REF_EXPR, // MSPropertyRefExpr
-      EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR, // MSPropertySubscriptExpr
-      EXPR_CXX_UUIDOF_EXPR,       // CXXUuidofExpr (of expr).
-      EXPR_CXX_UUIDOF_TYPE,       // CXXUuidofExpr (of type).
-      STMT_SEH_LEAVE,             // SEHLeaveStmt
-      STMT_SEH_EXCEPT,            // SEHExceptStmt
-      STMT_SEH_FINALLY,           // SEHFinallyStmt
-      STMT_SEH_TRY,               // SEHTryStmt
-
-      // OpenMP directives
-      STMT_OMP_PARALLEL_DIRECTIVE,
-      STMT_OMP_SIMD_DIRECTIVE,
-      STMT_OMP_TILE_DIRECTIVE,
-      STMT_OMP_FOR_DIRECTIVE,
-      STMT_OMP_FOR_SIMD_DIRECTIVE,
-      STMT_OMP_SECTIONS_DIRECTIVE,
-      STMT_OMP_SECTION_DIRECTIVE,
-      STMT_OMP_SINGLE_DIRECTIVE,
-      STMT_OMP_MASTER_DIRECTIVE,
-      STMT_OMP_CRITICAL_DIRECTIVE,
-      STMT_OMP_PARALLEL_FOR_DIRECTIVE,
-      STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE,
-      STMT_OMP_PARALLEL_MASTER_DIRECTIVE,
-      STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE,
-      STMT_OMP_TASK_DIRECTIVE,
-      STMT_OMP_TASKYIELD_DIRECTIVE,
-      STMT_OMP_BARRIER_DIRECTIVE,
-      STMT_OMP_TASKWAIT_DIRECTIVE,
-      STMT_OMP_FLUSH_DIRECTIVE,
-      STMT_OMP_DEPOBJ_DIRECTIVE,
-      STMT_OMP_SCAN_DIRECTIVE,
-      STMT_OMP_ORDERED_DIRECTIVE,
-      STMT_OMP_ATOMIC_DIRECTIVE,
-      STMT_OMP_TARGET_DIRECTIVE,
-      STMT_OMP_TARGET_DATA_DIRECTIVE,
-      STMT_OMP_TARGET_ENTER_DATA_DIRECTIVE,
-      STMT_OMP_TARGET_EXIT_DATA_DIRECTIVE,
-      STMT_OMP_TARGET_PARALLEL_DIRECTIVE,
-      STMT_OMP_TARGET_PARALLEL_FOR_DIRECTIVE,
-      STMT_OMP_TEAMS_DIRECTIVE,
-      STMT_OMP_TASKGROUP_DIRECTIVE,
-      STMT_OMP_CANCELLATION_POINT_DIRECTIVE,
-      STMT_OMP_CANCEL_DIRECTIVE,
-      STMT_OMP_TASKLOOP_DIRECTIVE,
-      STMT_OMP_TASKLOOP_SIMD_DIRECTIVE,
-      STMT_OMP_MASTER_TASKLOOP_DIRECTIVE,
-      STMT_OMP_MASTER_TASKLOOP_SIMD_DIRECTIVE,
-      STMT_OMP_PARALLEL_MASTER_TASKLOOP_DIRECTIVE,
-      STMT_OMP_PARALLEL_MASTER_TASKLOOP_SIMD_DIRECTIVE,
-      STMT_OMP_DISTRIBUTE_DIRECTIVE,
-      STMT_OMP_TARGET_UPDATE_DIRECTIVE,
-      STMT_OMP_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
-      STMT_OMP_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
-      STMT_OMP_DISTRIBUTE_SIMD_DIRECTIVE,
-      STMT_OMP_TARGET_PARALLEL_FOR_SIMD_DIRECTIVE,
-      STMT_OMP_TARGET_SIMD_DIRECTIVE,
-      STMT_OMP_TEAMS_DISTRIBUTE_DIRECTIVE,
-      STMT_OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE,
-      STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
-      STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
-      STMT_OMP_TARGET_TEAMS_DIRECTIVE,
-      STMT_OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE,
-      STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
-      STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
-      STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE,
-      EXPR_OMP_ARRAY_SECTION,
-      EXPR_OMP_ARRAY_SHAPING,
-      EXPR_OMP_ITERATOR,
-
-      // ARC
-      EXPR_OBJC_BRIDGED_CAST,     // ObjCBridgedCastExpr
-
-      STMT_MS_DEPENDENT_EXISTS,   // MSDependentExistsStmt
-      EXPR_LAMBDA,                // LambdaExpr
-      STMT_COROUTINE_BODY,
-      STMT_CORETURN,
-      EXPR_COAWAIT,
-      EXPR_COYIELD,
-      EXPR_DEPENDENT_COAWAIT,
-
-      // FixedPointLiteral
-      EXPR_FIXEDPOINT_LITERAL,
-    };
-
-    /// The kinds of designators that can occur in a
-    /// DesignatedInitExpr.
-    enum DesignatorTypes {
-      /// Field designator where only the field name is known.
-      DESIG_FIELD_NAME  = 0,
-
-      /// Field designator where the field has been resolved to
-      /// a declaration.
-      DESIG_FIELD_DECL  = 1,
-
-      /// Array designator.
-      DESIG_ARRAY       = 2,
-
-      /// GNU array range designator.
-      DESIG_ARRAY_RANGE = 3
-    };
-
-    /// The 
diff erent kinds of data that can occur in a
-    /// CtorInitializer.
-    enum CtorInitializerType {
-      CTOR_INITIALIZER_BASE,
-      CTOR_INITIALIZER_DELEGATING,
-      CTOR_INITIALIZER_MEMBER,
-      CTOR_INITIALIZER_INDIRECT_MEMBER
-    };
-
-    /// Kinds of cleanup objects owned by ExprWithCleanups.
-    enum CleanupObjectKind { COK_Block, COK_CompoundLiteral };
-
-    /// Describes the redeclarations of a declaration.
-    struct LocalRedeclarationsInfo {
-      // The ID of the first declaration
-      DeclID FirstID;
-
-      // Offset into the array of redeclaration chains.
-      unsigned Offset;
-
-      friend bool operator<(const LocalRedeclarationsInfo &X,
-                            const LocalRedeclarationsInfo &Y) {
-        return X.FirstID < Y.FirstID;
-      }
-
-      friend bool operator>(const LocalRedeclarationsInfo &X,
-                            const LocalRedeclarationsInfo &Y) {
-        return X.FirstID > Y.FirstID;
-      }
-
-      friend bool operator<=(const LocalRedeclarationsInfo &X,
-                             const LocalRedeclarationsInfo &Y) {
-        return X.FirstID <= Y.FirstID;
-      }
-
-      friend bool operator>=(const LocalRedeclarationsInfo &X,
-                             const LocalRedeclarationsInfo &Y) {
-        return X.FirstID >= Y.FirstID;
-      }
-    };
-
-    /// Describes the categories of an Objective-C class.
-    struct ObjCCategoriesInfo {
-      // The ID of the definition
-      DeclID DefinitionID;
-
-      // Offset into the array of category lists.
-      unsigned Offset;
-
-      friend bool operator<(const ObjCCategoriesInfo &X,
-                            const ObjCCategoriesInfo &Y) {
-        return X.DefinitionID < Y.DefinitionID;
-      }
-
-      friend bool operator>(const ObjCCategoriesInfo &X,
-                            const ObjCCategoriesInfo &Y) {
-        return X.DefinitionID > Y.DefinitionID;
-      }
-
-      friend bool operator<=(const ObjCCategoriesInfo &X,
-                             const ObjCCategoriesInfo &Y) {
-        return X.DefinitionID <= Y.DefinitionID;
-      }
-
-      friend bool operator>=(const ObjCCategoriesInfo &X,
-                             const ObjCCategoriesInfo &Y) {
-        return X.DefinitionID >= Y.DefinitionID;
-      }
-    };
-
-    /// A key used when looking up entities by \ref DeclarationName.
-    ///
-    /// Different \ref DeclarationNames are mapped to 
diff erent keys, but the
-    /// same key can occasionally represent multiple names (for names that
-    /// contain types, in particular).
-    class DeclarationNameKey {
-      using NameKind = unsigned;
-
-      NameKind Kind = 0;
-      uint64_t Data = 0;
-
-    public:
-      DeclarationNameKey() = default;
-      DeclarationNameKey(DeclarationName Name);
-      DeclarationNameKey(NameKind Kind, uint64_t Data)
-          : Kind(Kind), Data(Data) {}
-
-      NameKind getKind() const { return Kind; }
-
-      IdentifierInfo *getIdentifier() const {
-        assert(Kind == DeclarationName::Identifier ||
-               Kind == DeclarationName::CXXLiteralOperatorName ||
-               Kind == DeclarationName::CXXDeductionGuideName);
-        return (IdentifierInfo *)Data;
-      }
-
-      Selector getSelector() const {
-        assert(Kind == DeclarationName::ObjCZeroArgSelector ||
-               Kind == DeclarationName::ObjCOneArgSelector ||
-               Kind == DeclarationName::ObjCMultiArgSelector);
-        return Selector(Data);
-      }
-
-      OverloadedOperatorKind getOperatorKind() const {
-        assert(Kind == DeclarationName::CXXOperatorName);
-        return (OverloadedOperatorKind)Data;
-      }
-
-      /// Compute a fingerprint of this key for use in on-disk hash table.
-      unsigned getHash() const;
-
-      friend bool operator==(const DeclarationNameKey &A,
-                             const DeclarationNameKey &B) {
-        return A.Kind == B.Kind && A.Data == B.Data;
-      }
-    };
-
-    /// @}
+  friend bool operator<=(const LocalRedeclarationsInfo &X,
+                         const LocalRedeclarationsInfo &Y) {
+    return X.FirstID <= Y.FirstID;
+  }
+
+  friend bool operator>=(const LocalRedeclarationsInfo &X,
+                         const LocalRedeclarationsInfo &Y) {
+    return X.FirstID >= Y.FirstID;
+  }
+};
+
+/// Describes the categories of an Objective-C class.
+struct ObjCCategoriesInfo {
+  // The ID of the definition
+  DeclID DefinitionID;
+
+  // Offset into the array of category lists.
+  unsigned Offset;
+
+  friend bool operator<(const ObjCCategoriesInfo &X,
+                        const ObjCCategoriesInfo &Y) {
+    return X.DefinitionID < Y.DefinitionID;
+  }
+
+  friend bool operator>(const ObjCCategoriesInfo &X,
+                        const ObjCCategoriesInfo &Y) {
+    return X.DefinitionID > Y.DefinitionID;
+  }
+
+  friend bool operator<=(const ObjCCategoriesInfo &X,
+                         const ObjCCategoriesInfo &Y) {
+    return X.DefinitionID <= Y.DefinitionID;
+  }
+
+  friend bool operator>=(const ObjCCategoriesInfo &X,
+                         const ObjCCategoriesInfo &Y) {
+    return X.DefinitionID >= Y.DefinitionID;
+  }
+};
+
+/// A key used when looking up entities by \ref DeclarationName.
+///
+/// Different \ref DeclarationNames are mapped to 
diff erent keys, but the
+/// same key can occasionally represent multiple names (for names that
+/// contain types, in particular).
+class DeclarationNameKey {
+  using NameKind = unsigned;
+
+  NameKind Kind = 0;
+  uint64_t Data = 0;
+
+public:
+  DeclarationNameKey() = default;
+  DeclarationNameKey(DeclarationName Name);
+  DeclarationNameKey(NameKind Kind, uint64_t Data) : Kind(Kind), Data(Data) {}
+
+  NameKind getKind() const { return Kind; }
+
+  IdentifierInfo *getIdentifier() const {
+    assert(Kind == DeclarationName::Identifier ||
+           Kind == DeclarationName::CXXLiteralOperatorName ||
+           Kind == DeclarationName::CXXDeductionGuideName);
+    return (IdentifierInfo *)Data;
+  }
+
+  Selector getSelector() const {
+    assert(Kind == DeclarationName::ObjCZeroArgSelector ||
+           Kind == DeclarationName::ObjCOneArgSelector ||
+           Kind == DeclarationName::ObjCMultiArgSelector);
+    return Selector(Data);
+  }
+
+  OverloadedOperatorKind getOperatorKind() const {
+    assert(Kind == DeclarationName::CXXOperatorName);
+    return (OverloadedOperatorKind)Data;
+  }
+
+  /// Compute a fingerprint of this key for use in on-disk hash table.
+  unsigned getHash() const;
+
+  friend bool operator==(const DeclarationNameKey &A,
+                         const DeclarationNameKey &B) {
+    return A.Kind == B.Kind && A.Data == B.Data;
+  }
+};
+
+/// @}
 
 } // namespace serialization
 } // namespace clang
 
 namespace llvm {
 
-  template <> struct DenseMapInfo<clang::serialization::DeclarationNameKey> {
-    static clang::serialization::DeclarationNameKey getEmptyKey() {
-      return clang::serialization::DeclarationNameKey(-1, 1);
-    }
-
-    static clang::serialization::DeclarationNameKey getTombstoneKey() {
-      return clang::serialization::DeclarationNameKey(-1, 2);
-    }
-
-    static unsigned
-    getHashValue(const clang::serialization::DeclarationNameKey &Key) {
-      return Key.getHash();
-    }
-
-    static bool isEqual(const clang::serialization::DeclarationNameKey &L,
-                        const clang::serialization::DeclarationNameKey &R) {
-      return L == R;
-    }
-  };
+template <> struct DenseMapInfo<clang::serialization::DeclarationNameKey> {
+  static clang::serialization::DeclarationNameKey getEmptyKey() {
+    return clang::serialization::DeclarationNameKey(-1, 1);
+  }
+
+  static clang::serialization::DeclarationNameKey getTombstoneKey() {
+    return clang::serialization::DeclarationNameKey(-1, 2);
+  }
+
+  static unsigned
+  getHashValue(const clang::serialization::DeclarationNameKey &Key) {
+    return Key.getHash();
+  }
+
+  static bool isEqual(const clang::serialization::DeclarationNameKey &L,
+                      const clang::serialization::DeclarationNameKey &R) {
+    return L == R;
+  }
+};
 
 } // namespace llvm
 

diff  --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp
index 83821ea6f5fc..2ceee614cf98 100644
--- a/clang/lib/AST/Stmt.cpp
+++ b/clang/lib/AST/Stmt.cpp
@@ -1266,13 +1266,6 @@ CapturedStmt::Capture::Capture(SourceLocation Loc, VariableCaptureKind Kind,
     break;
   case VCK_ByCopy:
     assert(Var && "capturing by copy must have a variable!");
-    assert(
-        (Var->getType()->isScalarType() || (Var->getType()->isReferenceType() &&
-                                            Var->getType()
-                                                ->castAs<ReferenceType>()
-                                                ->getPointeeType()
-                                                ->isScalarType())) &&
-        "captures by copy are expected to have a scalar type!");
     break;
   case VCK_VLAType:
     assert(!Var &&

diff  --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp
index a3814255133b..5a6b31bae624 100644
--- a/clang/lib/AST/StmtOpenMP.cpp
+++ b/clang/lib/AST/StmtOpenMP.cpp
@@ -92,6 +92,8 @@ OMPLoopBasedDirective::tryToFindNextInnerLoop(Stmt *CurStmt,
         for (Stmt *S : CS->body()) {
           if (!S)
             continue;
+          if (auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S))
+            S = CanonLoop->getLoopStmt();
           if (isa<ForStmt>(S) || isa<CXXForRangeStmt>(S) ||
               (isa<OMPLoopBasedDirective>(S) && !isa<OMPLoopDirective>(S))) {
             // Only single loop construct is allowed.
@@ -127,6 +129,8 @@ bool OMPLoopBasedDirective::doForAllLoops(
   for (unsigned Cnt = 0; Cnt < NumLoops; ++Cnt) {
     if (auto *Dir = dyn_cast<OMPTileDirective>(CurStmt))
       CurStmt = Dir->getTransformedStmt();
+    if (auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(CurStmt))
+      CurStmt = CanonLoop->getLoopStmt();
     if (Callback(Cnt, CurStmt))
       return false;
     // Move on to the next nested for loop, or to the loop body.
@@ -161,6 +165,8 @@ void OMPLoopBasedDirective::doForAllLoopsBodies(
                  "Expected canonical for or range-based for loops.");
           Body = cast<CXXForRangeStmt>(Loop)->getBody();
         }
+        if (auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(Body))
+          Body = CanonLoop->getLoopStmt();
         Callback(Cnt, Loop, Body);
         return false;
       });

diff  --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 03ef536b1858..82071f5d7aaa 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -636,6 +636,10 @@ void StmtPrinter::VisitSEHLeaveStmt(SEHLeaveStmt *Node) {
 //  OpenMP directives printing methods
 //===----------------------------------------------------------------------===//
 
+void StmtPrinter::VisitOMPCanonicalLoop(OMPCanonicalLoop *Node) {
+  PrintStmt(Node->getLoopStmt());
+}
+
 void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S,
                                               bool ForceNoStmt) {
   OMPClausePrinter Printer(OS, Policy);

diff  --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 482371d91e87..761d027b3378 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -854,6 +854,10 @@ StmtProfiler::VisitOMPExecutableDirective(const OMPExecutableDirective *S) {
       P.Visit(*I);
 }
 
+void StmtProfiler::VisitOMPCanonicalLoop(const OMPCanonicalLoop *L) {
+  VisitStmt(L);
+}
+
 void StmtProfiler::VisitOMPLoopBasedDirective(const OMPLoopBasedDirective *S) {
   VisitOMPExecutableDirective(S);
 }

diff  --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index f36dd1b03130..021eda31ee71 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -194,6 +194,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
   case Stmt::SEHTryStmtClass:
     EmitSEHTryStmt(cast<SEHTryStmt>(*S));
     break;
+  case Stmt::OMPCanonicalLoopClass:
+    EmitOMPCanonicalLoop(cast<OMPCanonicalLoop>(S));
+    break;
   case Stmt::OMPParallelDirectiveClass:
     EmitOMPParallelDirective(cast<OMPParallelDirective>(*S));
     break;

diff  --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 4fe2ae11cb15..2eaa481cd911 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -1803,6 +1803,8 @@ static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop,
                                                                    SimplifiedS);
     if (auto *Dir = dyn_cast<OMPTileDirective>(SimplifiedS))
       SimplifiedS = Dir->getTransformedStmt();
+    if (const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
+      SimplifiedS = CanonLoop->getLoopStmt();
     if (const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
       S = For->getBody();
     } else {
@@ -1890,6 +1892,121 @@ void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
   BreakContinueStack.pop_back();
 }
 
+using EmittedClosureTy = std::pair<llvm::Function *, llvm::Value *>;
+
+/// Emit a captured statement and return the function as well as its captured
+/// closure context.
+static EmittedClosureTy emitCapturedStmtFunc(CodeGenFunction &ParentCGF,
+                                             const CapturedStmt *S) {
+  LValue CapStruct = ParentCGF.InitCapturedStruct(*S);
+  CodeGenFunction CGF(ParentCGF.CGM, /*suppressNewContext=*/true);
+  std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
+      std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
+  CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, CSI.get());
+  llvm::Function *F = CGF.GenerateCapturedStmtFunction(*S);
+
+  return {F, CapStruct.getPointer(ParentCGF)};
+}
+
+/// Emit a call to a previously captured closure.
+static llvm::CallInst *
+emitCapturedStmtCall(CodeGenFunction &ParentCGF, EmittedClosureTy Cap,
+                     llvm::ArrayRef<llvm::Value *> Args) {
+  // Append the closure context to the argument.
+  SmallVector<llvm::Value *> EffectiveArgs;
+  EffectiveArgs.reserve(Args.size() + 1);
+  llvm::append_range(EffectiveArgs, Args);
+  EffectiveArgs.push_back(Cap.second);
+
+  return ParentCGF.Builder.CreateCall(Cap.first, EffectiveArgs);
+}
+
+llvm::CanonicalLoopInfo *
+CodeGenFunction::EmitOMPCollapsedCanonicalLoopNest(const Stmt *S, int Depth) {
+  assert(Depth == 1 && "Nested loops with OpenMPIRBuilder not yet implemented");
+
+  EmitStmt(S);
+  assert(OMPLoopNestStack.size() >= (size_t)Depth && "Found too few loops");
+
+  // The last added loop is the outermost one.
+  return OMPLoopNestStack.back();
+}
+
+void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) {
+  const Stmt *SyntacticalLoop = S->getLoopStmt();
+  if (!getLangOpts().OpenMPIRBuilder) {
+    // Ignore if OpenMPIRBuilder is not enabled.
+    EmitStmt(SyntacticalLoop);
+    return;
+  }
+
+  LexicalScope ForScope(*this, S->getSourceRange());
+
+  // Emit init statements. The Distance/LoopVar funcs may reference variable
+  // declarations they contain.
+  const Stmt *BodyStmt;
+  if (const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
+    if (const Stmt *InitStmt = For->getInit())
+      EmitStmt(InitStmt);
+    BodyStmt = For->getBody();
+  } else if (const auto *RangeFor =
+                 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
+    if (const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
+      EmitStmt(RangeStmt);
+    if (const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
+      EmitStmt(BeginStmt);
+    if (const DeclStmt *EndStmt = RangeFor->getEndStmt())
+      EmitStmt(EndStmt);
+    if (const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
+      EmitStmt(LoopVarStmt);
+    BodyStmt = RangeFor->getBody();
+  } else
+    llvm_unreachable("Expected for-stmt or range-based for-stmt");
+
+  // Emit closure for later use. By-value captures will be captured here.
+  const CapturedStmt *DistanceFunc = S->getDistanceFunc();
+  EmittedClosureTy DistanceClosure = emitCapturedStmtFunc(*this, DistanceFunc);
+  const CapturedStmt *LoopVarFunc = S->getLoopVarFunc();
+  EmittedClosureTy LoopVarClosure = emitCapturedStmtFunc(*this, LoopVarFunc);
+
+  // Call the distance function to get the number of iterations of the loop to
+  // come.
+  QualType LogicalTy = DistanceFunc->getCapturedDecl()
+                           ->getParam(0)
+                           ->getType()
+                           .getNonReferenceType();
+  Address CountAddr = CreateMemTemp(LogicalTy, ".count.addr");
+  emitCapturedStmtCall(*this, DistanceClosure, {CountAddr.getPointer()});
+  llvm::Value *DistVal = Builder.CreateLoad(CountAddr, ".count");
+
+  // Emit the loop structure.
+  llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
+  auto BodyGen = [&, this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
+                           llvm::Value *IndVar) {
+    Builder.restoreIP(CodeGenIP);
+
+    // Emit the loop body: Convert the logical iteration number to the loop
+    // variable and emit the body.
+    const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
+    LValue LCVal = EmitLValue(LoopVarRef);
+    Address LoopVarAddress = LCVal.getAddress(*this);
+    emitCapturedStmtCall(*this, LoopVarClosure,
+                         {LoopVarAddress.getPointer(), IndVar});
+
+    RunCleanupsScope BodyScope(*this);
+    EmitStmt(BodyStmt);
+  };
+  llvm::CanonicalLoopInfo *CL =
+      OMPBuilder.createCanonicalLoop(Builder, BodyGen, DistVal);
+
+  // Finish up the loop.
+  Builder.restoreIP(CL->getAfterIP());
+  ForScope.ForceCleanup();
+
+  // Remember the CanonicalLoopInfo for parent AST nodes consuming it.
+  OMPLoopNestStack.push_back(CL);
+}
+
 void CodeGenFunction::EmitOMPInnerLoop(
     const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond,
     const Expr *IncExpr,
@@ -1907,6 +2024,7 @@ void CodeGenFunction::EmitOMPInnerLoop(
   const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
   const Stmt *SS = ICS->getCapturedStmt();
   const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(SS);
+  OMPLoopNestStack.clear();
   if (AS)
     LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(),
                    AS->getAttrs(), SourceLocToDebugLoc(R.getBegin()),
@@ -2461,6 +2579,7 @@ void CodeGenFunction::EmitOMPOuterLoop(
   llvm::BasicBlock *CondBlock = createBasicBlock("omp.dispatch.cond");
   EmitBlock(CondBlock);
   const SourceRange R = S.getSourceRange();
+  OMPLoopNestStack.clear();
   LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
                  SourceLocToDebugLoc(R.getEnd()));
 
@@ -2544,6 +2663,7 @@ void CodeGenFunction::EmitOMPOuterLoop(
   }
 
   EmitBranch(CondBlock);
+  OMPLoopNestStack.clear();
   LoopStack.pop();
   // Emit the fall-through block.
   EmitBlock(LoopExit.getBlock());
@@ -3386,10 +3506,38 @@ static bool emitWorksharingDirective(CodeGenFunction &CGF,
   return HasLastprivates;
 }
 
+static bool isSupportedByOpenMPIRBuilder(const OMPForDirective &S) {
+  if (S.hasCancel())
+    return false;
+  for (OMPClause *C : S.clauses())
+    if (!isa<OMPNowaitClause>(C))
+      return false;
+
+  return true;
+}
+
 void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
   bool HasLastprivates = false;
-  auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
-                                          PrePostActionTy &) {
+  bool UseOMPIRBuilder =
+      CGM.getLangOpts().OpenMPIRBuilder && isSupportedByOpenMPIRBuilder(S);
+  auto &&CodeGen = [this, &S, &HasLastprivates,
+                    UseOMPIRBuilder](CodeGenFunction &CGF, PrePostActionTy &) {
+    // Use the OpenMPIRBuilder if enabled.
+    if (UseOMPIRBuilder) {
+      // Emit the associated statement and get its loop representation.
+      const Stmt *Inner = S.getRawStmt();
+      llvm::CanonicalLoopInfo *CLI =
+          EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
+
+      bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
+      llvm::OpenMPIRBuilder &OMPBuilder =
+          CGM.getOpenMPRuntime().getOMPBuilder();
+      llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
+          AllocaInsertPt->getParent(), AllocaInsertPt->getIterator());
+      OMPBuilder.createWorkshareLoop(Builder, CLI, AllocaIP, NeedsBarrier);
+      return;
+    }
+
     HasLastprivates = emitWorksharingDirective(CGF, S, S.hasCancel());
   };
   {
@@ -3400,9 +3548,11 @@ void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
                                                 S.hasCancel());
   }
 
-  // Emit an implicit barrier at the end.
-  if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
-    CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
+  if (!UseOMPIRBuilder) {
+    // Emit an implicit barrier at the end.
+    if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
+      CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
+  }
   // Check for outer lastprivate conditional update.
   checkForLastprivateConditionalUpdate(*this, S);
 }

diff  --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 53bf69f8f86d..f03208fa62eb 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -91,8 +91,8 @@ CodeGenFunction::~CodeGenFunction() {
   // seems to be a reasonable spot. We do it here, as opposed to the deletion
   // time of the CodeGenModule, because we have to ensure the IR has not yet
   // been "emitted" to the outside, thus, modifications are still sensible.
-  if (CGM.getLangOpts().OpenMPIRBuilder)
-    CGM.getOpenMPRuntime().getOMPBuilder().finalize();
+  if (CGM.getLangOpts().OpenMPIRBuilder && CurFn)
+    CGM.getOpenMPRuntime().getOMPBuilder().finalize(CurFn);
 }
 
 // Map the LangOption for exception behavior into

diff  --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 2ce87ac7c8e3..98e8d5bb9efa 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -50,6 +50,7 @@ class Module;
 class SwitchInst;
 class Twine;
 class Value;
+class CanonicalLoopInfo;
 }
 
 namespace clang {
@@ -276,6 +277,20 @@ class CodeGenFunction : public CodeGenTypeCache {
   // because of jumps.
   VarBypassDetector Bypasses;
 
+  /// List of recently emitted OMPCanonicalLoops.
+  ///
+  /// Since OMPCanonicalLoops are nested inside other statements (in particular
+  /// CapturedStmt generated by OMPExecutableDirective and non-perfectly nested
+  /// loops), we cannot directly call OMPEmitOMPCanonicalLoop and receive its
+  /// llvm::CanonicalLoopInfo. Instead, we call EmitStmt and any
+  /// OMPEmitOMPCanonicalLoop called by it will add its CanonicalLoopInfo to
+  /// this stack when done. Entering a new loop requires clearing this list; it
+  /// either means we start parsing a new loop nest (in which case the previous
+  /// loop nest goes out of scope) or a second loop in the same level in which
+  /// case it would be ambiguous into which of the two (or more) loops the loop
+  /// nest would extend.
+  SmallVector<llvm::CanonicalLoopInfo *, 4> OMPLoopNestStack;
+
   // CodeGen lambda for loops and support for ordered clause
   typedef llvm::function_ref<void(CodeGenFunction &, const OMPLoopDirective &,
                                   JumpDest)>
@@ -3511,6 +3526,18 @@ class CodeGenFunction : public CodeGenTypeCache {
   static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
       CodeGenModule &CGM, StringRef ParentName,
       const OMPTargetTeamsDistributeParallelForDirective &S);
+
+  /// Emit the Stmt \p S and return its topmost canonical loop, if any.
+  /// TODO: The \p Depth paramter is not yet implemented and must be 1. In the
+  /// future it is meant to be the number of loops expected in the loop nests
+  /// (usually specified by the "collapse" clause) that are collapsed to a
+  /// single loop by this function.
+  llvm::CanonicalLoopInfo *EmitOMPCollapsedCanonicalLoopNest(const Stmt *S,
+                                                             int Depth);
+
+  /// Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
+  void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S);
+
   /// Emit inner loop of the worksharing/simd construct.
   ///
   /// \param S Directive, for which the inner loop must be emitted.

diff  --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 48954cee6f93..3de01be0db87 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -2536,7 +2536,15 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
       // the captured region. Code elsewhere assumes that any FunctionScopeInfo
       // should have at least one compound statement scope within it.
       ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
-      AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
+      {
+        Sema::CompoundScopeRAII Scope(Actions);
+        AssociatedStmt = ParseStatement();
+
+        if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
+            getLangOpts().OpenMPIRBuilder)
+          AssociatedStmt =
+              Actions.ActOnOpenMPCanonicalLoop(AssociatedStmt.get());
+      }
       AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
     } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
                DKind == OMPD_target_exit_data) {

diff  --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 0e73f60847fe..3ada5729c27a 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1448,6 +1448,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
   case Stmt::OMPMasterTaskLoopDirectiveClass:
   case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
   case Stmt::OMPOrderedDirectiveClass:
+  case Stmt::OMPCanonicalLoopClass:
   case Stmt::OMPParallelDirectiveClass:
   case Stmt::OMPParallelForDirectiveClass:
   case Stmt::OMPParallelForSimdDirectiveClass:

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 79dd3c0c1184..5896a7c0bb7b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -17284,18 +17284,17 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
 
 
 /// Capture the given variable in the captured region.
-static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
-                                    VarDecl *Var,
-                                    SourceLocation Loc,
-                                    const bool BuildAndDiagnose,
-                                    QualType &CaptureType,
-                                    QualType &DeclRefType,
-                                    const bool RefersToCapturedVariable,
-                                    Sema &S, bool Invalid) {
+static bool captureInCapturedRegion(
+    CapturedRegionScopeInfo *RSI, VarDecl *Var, SourceLocation Loc,
+    const bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType,
+    const bool RefersToCapturedVariable, Sema::TryCaptureKind Kind,
+    bool IsTopScope, Sema &S, bool Invalid) {
   // By default, capture variables by reference.
   bool ByRef = true;
-  // Using an LValue reference type is consistent with Lambdas (see below).
-  if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) {
+  if (IsTopScope && Kind != Sema::TryCapture_Implicit) {
+    ByRef = (Kind == Sema::TryCapture_ExplicitByRef);
+  } else if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) {
+    // Using an LValue reference type is consistent with Lambdas (see below).
     if (S.isOpenMPCapturedDecl(Var)) {
       bool HasConst = DeclRefType.isConstQualified();
       DeclRefType = DeclRefType.getUnqualifiedType();
@@ -17641,9 +17640,9 @@ bool Sema::tryCaptureVariable(
                                DeclRefType, Nested, *this, Invalid);
       Nested = true;
     } else if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
-      Invalid = !captureInCapturedRegion(RSI, Var, ExprLoc, BuildAndDiagnose,
-                                         CaptureType, DeclRefType, Nested,
-                                         *this, Invalid);
+      Invalid = !captureInCapturedRegion(
+          RSI, Var, ExprLoc, BuildAndDiagnose, CaptureType, DeclRefType, Nested,
+          Kind, /*IsTopScope*/ I == N - 1, *this, Invalid);
       Nested = true;
     } else {
       LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);

diff  --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 0bb9554bcab8..6fcb472cd60c 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -5151,6 +5151,393 @@ static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
   }
 }
 
+namespace {
+/// Rewrite statements and expressions for Sema \p Actions CurContext.
+///
+/// Used to wrap already parsed statements/expressions into a new CapturedStmt
+/// context. DeclRefExpr used inside the new context are changed to refer to the
+/// captured variable instead.
+class CaptureVars : public TreeTransform<CaptureVars> {
+  using BaseTransform = TreeTransform<CaptureVars>;
+
+public:
+  CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
+
+  bool AlwaysRebuild() { return true; }
+};
+} // namespace
+
+static VarDecl *precomputeExpr(Sema &Actions,
+                               SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
+                               StringRef Name) {
+  Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
+  VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
+                                 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
+  auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
+      Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
+  Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
+  BodyStmts.push_back(NewDeclStmt);
+  return NewVar;
+}
+
+/// Create a closure that computes the number of iterations of a loop.
+///
+/// \param Actions   The Sema object.
+/// \param LogicalTy Type for the logical iteration number.
+/// \param Rel       Comparison operator of the loop condition.
+/// \param StartExpr Value of the loop counter at the first iteration.
+/// \param StopExpr  Expression the loop counter is compared against in the loop
+/// condition. \param Step      Amount of increment after each iteration.
+///
+/// \return Closure (CapturedStmt) of the distance calculation.
+static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
+                                       BinaryOperator::Opcode Rel,
+                                       Expr *StartExpr, Expr *StopExpr,
+                                       Expr *StepExpr) {
+  ASTContext &Ctx = Actions.getASTContext();
+  TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
+
+  // Captured regions currently don't support return values, we use an
+  // out-parameter instead. All inputs are implicit captures.
+  // TODO: Instead of capturing each DeclRefExpr occurring in
+  // StartExpr/StopExpr/Step, these could also be passed as a value capture.
+  QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
+  Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
+                                          {StringRef(), QualType()}};
+  Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
+
+  Stmt *Body;
+  {
+    Sema::CompoundScopeRAII CompoundScope(Actions);
+    CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
+
+    // Get the LValue expression for the result.
+    ImplicitParamDecl *DistParam = CS->getParam(0);
+    DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
+        DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
+
+    SmallVector<Stmt *, 4> BodyStmts;
+
+    // Capture all referenced variable references.
+    // TODO: Instead of computing NewStart/NewStop/NewStep inside the
+    // CapturedStmt, we could compute them before and capture the result, to be
+    // used jointly with the LoopVar function.
+    VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
+    VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
+    VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
+    auto BuildVarRef = [&](VarDecl *VD) {
+      return buildDeclRefExpr(Actions, VD, VD->getType(), {});
+    };
+
+    IntegerLiteral *Zero = IntegerLiteral::Create(
+        Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
+    Expr *Dist;
+    if (Rel == BO_NE) {
+      // When using a != comparison, the increment can be +1 or -1. This can be
+      // dynamic at runtime, so we need to check for the direction.
+      Expr *IsNegStep = AssertSuccess(
+          Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
+
+      // Positive increment.
+      Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
+          nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
+      ForwardRange = AssertSuccess(
+          Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
+      Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
+          nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
+
+      // Negative increment.
+      Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
+          nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
+      BackwardRange = AssertSuccess(
+          Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
+      Expr *NegIncAmount = AssertSuccess(
+          Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
+      Expr *BackwardDist = AssertSuccess(
+          Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
+
+      // Use the appropriate case.
+      Dist = AssertSuccess(Actions.ActOnConditionalOp(
+          {}, {}, IsNegStep, BackwardDist, ForwardDist));
+    } else {
+      assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
+             "Expected one of these relational operators");
+
+      // We can derive the direction from any other comparison operator. It is
+      // non well-formed OpenMP if Step increments/decrements in the other
+      // directions. Whether at least the first iteration passes the loop
+      // condition.
+      Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
+          nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
+
+      // Compute the range between first and last counter value.
+      Expr *Range;
+      if (Rel == BO_GE || Rel == BO_GT)
+        Range = AssertSuccess(Actions.BuildBinOp(
+            nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
+      else
+        Range = AssertSuccess(Actions.BuildBinOp(
+            nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
+
+      // Ensure unsigned range space.
+      Range =
+          AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
+
+      if (Rel == BO_LE || Rel == BO_GE) {
+        // Add one to the range if the relational operator is inclusive.
+        Range =
+            AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_PreInc, Range));
+      }
+
+      // Divide by the absolute step amount.
+      Expr *Divisor = BuildVarRef(NewStep);
+      if (Rel == BO_GE || Rel == BO_GT)
+        Divisor =
+            AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
+      Dist = AssertSuccess(
+          Actions.BuildBinOp(nullptr, {}, BO_Div, Range, Divisor));
+
+      // If there is not at least one iteration, the range contains garbage. Fix
+      // to zero in this case.
+      Dist = AssertSuccess(
+          Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
+    }
+
+    // Assign the result to the out-parameter.
+    Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
+        Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
+    BodyStmts.push_back(ResultAssign);
+
+    Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
+  }
+
+  return cast<CapturedStmt>(
+      AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
+}
+
+/// Create a closure that computes the loop variable from the logical iteration
+/// number.
+///
+/// \param Actions   The Sema object.
+/// \param LoopVarTy Type for the loop variable used for result value.
+/// \param LogicalTy Type for the logical iteration number.
+/// \param StartExpr Value of the loop counter at the first iteration.
+/// \param Step      Amount of increment after each iteration.
+/// \param Deref     Whether the loop variable is a dereference of the loop
+/// counter variable.
+///
+/// \return Closure (CapturedStmt) of the loop value calculation.
+static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
+                                      QualType LogicalTy,
+                                      DeclRefExpr *StartExpr, Expr *Step,
+                                      bool Deref) {
+  ASTContext &Ctx = Actions.getASTContext();
+
+  // Pass the result as an out-parameter. Passing as return value would require
+  // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
+  // invoke a copy constructor.
+  QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
+  Sema::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
+                                          {"Logical", LogicalTy},
+                                          {StringRef(), QualType()}};
+  Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
+
+  // Capture the initial iterator which represents the LoopVar value at the
+  // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
+  // it in every iteration, capture it by value before it is modified.
+  VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
+  bool Invalid = Actions.tryCaptureVariable(StartVar, {},
+                                            Sema::TryCapture_ExplicitByVal, {});
+  (void)Invalid;
+  assert(!Invalid && "Expecting capture-by-value to work.");
+
+  Expr *Body;
+  {
+    Sema::CompoundScopeRAII CompoundScope(Actions);
+    auto *CS = cast<CapturedDecl>(Actions.CurContext);
+
+    ImplicitParamDecl *TargetParam = CS->getParam(0);
+    DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
+        TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
+    ImplicitParamDecl *IndvarParam = CS->getParam(1);
+    DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
+        IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
+
+    // Capture the Start expression.
+    CaptureVars Recap(Actions);
+    Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
+    Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
+
+    Expr *Skip = AssertSuccess(
+        Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
+    // TODO: Explicitly cast to the iterator's 
diff erence_type instead of
+    // relying on implicit conversion.
+    Expr *Advanced =
+        AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
+
+    if (Deref) {
+      // For range-based for-loops convert the loop counter value to a concrete
+      // loop variable value by dereferencing the iterator.
+      Advanced =
+          AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
+    }
+
+    // Assign the result to the output parameter.
+    Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
+                                            BO_Assign, TargetRef, Advanced));
+  }
+  return cast<CapturedStmt>(
+      AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
+}
+
+StmtResult Sema::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
+  ASTContext &Ctx = getASTContext();
+
+  // Extract the common elements of ForStmt and CXXForRangeStmt:
+  // Loop variable, repeat condition, increment
+  Expr *Cond, *Inc;
+  VarDecl *LIVDecl, *LUVDecl;
+  if (auto *For = dyn_cast<ForStmt>(AStmt)) {
+    Stmt *Init = For->getInit();
+    if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
+      // For statement declares loop variable.
+      LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
+    } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
+      // For statement reuses variable.
+      assert(LCAssign->getOpcode() == BO_Assign &&
+             "init part must be a loop variable assignment");
+      auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
+      LIVDecl = cast<VarDecl>(CounterRef->getDecl());
+    } else
+      llvm_unreachable("Cannot determine loop variable");
+    LUVDecl = LIVDecl;
+
+    Cond = For->getCond();
+    Inc = For->getInc();
+  } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
+    DeclStmt *BeginStmt = RangeFor->getBeginStmt();
+    LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
+    LUVDecl = RangeFor->getLoopVariable();
+
+    Cond = RangeFor->getCond();
+    Inc = RangeFor->getInc();
+  } else
+    llvm_unreachable("unhandled kind of loop");
+
+  QualType CounterTy = LIVDecl->getType();
+  QualType LVTy = LUVDecl->getType();
+
+  // Analyze the loop condition.
+  Expr *LHS, *RHS;
+  BinaryOperator::Opcode CondRel;
+  Cond = Cond->IgnoreImplicit();
+  if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
+    LHS = CondBinExpr->getLHS();
+    RHS = CondBinExpr->getRHS();
+    CondRel = CondBinExpr->getOpcode();
+  } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
+    assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
+    LHS = CondCXXOp->getArg(0);
+    RHS = CondCXXOp->getArg(1);
+    switch (CondCXXOp->getOperator()) {
+    case OO_ExclaimEqual:
+      CondRel = BO_NE;
+      break;
+    case OO_Less:
+      CondRel = BO_LT;
+      break;
+    case OO_LessEqual:
+      CondRel = BO_LE;
+      break;
+    case OO_Greater:
+      CondRel = BO_GT;
+      break;
+    case OO_GreaterEqual:
+      CondRel = BO_GE;
+      break;
+    default:
+      llvm_unreachable("unexpected iterator operator");
+    }
+  } else
+    llvm_unreachable("unexpected loop condition");
+
+  // Normalize such that the loop counter is on the LHS.
+  if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
+      cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
+    std::swap(LHS, RHS);
+    CondRel = BinaryOperator::reverseComparisonOp(CondRel);
+  }
+  auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
+
+  // Decide the bit width for the logical iteration counter. By default use the
+  // unsigned ptr
diff _t integer size (for iterators and pointers).
+  // TODO: For iterators, use iterator::
diff erence_type,
+  // std::iterator_traits<>::
diff erence_type or decltype(it - end).
+  QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
+  if (CounterTy->isIntegerType()) {
+    unsigned BitWidth = Ctx.getIntWidth(CounterTy);
+    LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
+  }
+
+  // Analyze the loop increment.
+  Expr *Step;
+  if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
+    int Direction;
+    switch (IncUn->getOpcode()) {
+    case UO_PreInc:
+    case UO_PostInc:
+      Direction = 1;
+      break;
+    case UO_PreDec:
+    case UO_PostDec:
+      Direction = -1;
+      break;
+    default:
+      llvm_unreachable("unhandled unary increment operator");
+    }
+    Step = IntegerLiteral::Create(
+        Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
+  } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
+    if (IncBin->getOpcode() == BO_AddAssign) {
+      Step = IncBin->getRHS();
+    } else if (IncBin->getOpcode() == BO_SubAssign) {
+      Step =
+          AssertSuccess(BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
+    } else
+      llvm_unreachable("unhandled binary increment operator");
+  } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
+    switch (CondCXXOp->getOperator()) {
+    case OO_PlusPlus:
+      Step = IntegerLiteral::Create(
+          Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
+      break;
+    case OO_MinusMinus:
+      Step = IntegerLiteral::Create(
+          Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
+      break;
+    case OO_PlusEqual:
+      Step = CondCXXOp->getArg(1);
+      break;
+    case OO_MinusEqual:
+      Step = AssertSuccess(
+          BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
+      break;
+    default:
+      llvm_unreachable("unhandled overloaded increment operator");
+    }
+  } else
+    llvm_unreachable("unknown increment expression");
+
+  CapturedStmt *DistanceFunc =
+      buildDistanceFunc(*this, LogicalTy, CondRel, LHS, RHS, Step);
+  CapturedStmt *LoopVarFunc = buildLoopVarFunc(
+      *this, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
+  DeclRefExpr *LVRef = BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue,
+                                        {}, nullptr, nullptr, {}, nullptr);
+  return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
+                                  LoopVarFunc, LVRef);
+}
+
 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
                                             CXXScopeSpec &MapperIdScopeSpec,
                                             const DeclarationNameInfo &MapperId,
@@ -8130,6 +8517,8 @@ static bool checkOpenMPIterationSpace(
   // OpenMP [2.9.1, Canonical Loop Form]
   //   for (init-expr; test-expr; incr-expr) structured-block
   //   for (range-decl: range-expr) structured-block
+  if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
+    S = CanonLoop->getLoopStmt();
   auto *For = dyn_cast_or_null<ForStmt>(S);
   auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
   // Ranged for is supported only in OpenMP 5.0.

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 01ffdcc9fbff..5f88775226ae 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1546,6 +1546,14 @@ class TreeTransform {
     return getSema().BuildObjCAtThrowStmt(AtLoc, Operand);
   }
 
+  /// Build a new OpenMP Canonical loop.
+  ///
+  /// Ensures that the outermost loop in @p LoopStmt is wrapped by a
+  /// OMPCanonicalLoop.
+  StmtResult RebuildOMPCanonicalLoop(Stmt *LoopStmt) {
+    return getSema().ActOnOpenMPCanonicalLoop(LoopStmt);
+  }
+
   /// Build a new OpenMP executable directive.
   ///
   /// By default, performs semantic analysis to build the new statement.
@@ -8321,6 +8329,16 @@ TreeTransform<Derived>::TransformSEHLeaveStmt(SEHLeaveStmt *S) {
 //===----------------------------------------------------------------------===//
 // OpenMP directive transformation
 //===----------------------------------------------------------------------===//
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPCanonicalLoop(OMPCanonicalLoop *L) {
+  // OMPCanonicalLoops are eliminated during transformation, since they will be
+  // recomputed by semantic analysis of the associated OMPLoopBasedDirective
+  // after transformation.
+  return getDerived().TransformStmt(L->getLoopStmt());
+}
+
 template <typename Derived>
 StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
     OMPExecutableDirective *D) {
@@ -8357,6 +8375,9 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
       else
         CS = D->getRawStmt();
       Body = getDerived().TransformStmt(CS);
+      if (Body.isUsable() && isOpenMPLoopDirective(D->getDirectiveKind()) &&
+          getSema().getLangOpts().OpenMPIRBuilder)
+        Body = getDerived().RebuildOMPCanonicalLoop(Body.get());
     }
     AssociatedStmt =
         getDerived().getSema().ActOnOpenMPRegionEnd(Body, TClauses);

diff  --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 7c55fdaf54c9..24513b70edd7 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2273,6 +2273,12 @@ void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) {
 // OpenMP Directives.
 //===----------------------------------------------------------------------===//
 
+void ASTStmtReader::VisitOMPCanonicalLoop(OMPCanonicalLoop *S) {
+  VisitStmt(S);
+  for (Stmt *&SubStmt : S->SubStmts)
+    SubStmt = Record.readSubStmt();
+}
+
 void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
   Record.readOMPChildren(E->Data);
   E->setLocStart(readSourceLocation());
@@ -3138,6 +3144,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
                                               nullptr);
       break;
 
+    case STMT_OMP_CANONICAL_LOOP:
+      S = OMPCanonicalLoop::createEmpty(Context);
+      break;
+
     case STMT_OMP_PARALLEL_DIRECTIVE:
       S =
         OMPParallelDirective::CreateEmpty(Context,

diff  --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 3bdec7007afd..58fb11e70d14 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2170,6 +2170,13 @@ void ASTStmtWriter::VisitSEHLeaveStmt(SEHLeaveStmt *S) {
 // OpenMP Directives.
 //===----------------------------------------------------------------------===//
 
+void ASTStmtWriter::VisitOMPCanonicalLoop(OMPCanonicalLoop *S) {
+  VisitStmt(S);
+  for (Stmt *SubStmt : S->SubStmts)
+    Record.AddStmt(SubStmt);
+  Code = serialization::STMT_OMP_CANONICAL_LOOP;
+}
+
 void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
   Record.writeOMPChildren(E->Data);
   Record.AddSourceLocation(E->getBeginLoc());

diff  --git a/clang/test/OpenMP/irbuilder_for_iterator.cpp b/clang/test/OpenMP/irbuilder_for_iterator.cpp
new file mode 100644
index 000000000000..a85e3003a8f0
--- /dev/null
+++ b/clang/test/OpenMP/irbuilder_for_iterator.cpp
@@ -0,0 +1,166 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs
+// RUN: %clang_cc1 -fopenmp-enable-irbuilder -verify -fopenmp -fopenmp-version=50 -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+struct MyIterator {
+  MyIterator(unsigned pos);
+  MyIterator(const MyIterator &other);
+  const MyIterator &operator=(const MyIterator &that);
+  MyIterator &operator++();
+  int operator-(const MyIterator &that) const;
+  MyIterator &operator+=(unsigned a);
+  MyIterator operator+(unsigned a) const;
+  bool operator==(const MyIterator &that) const;
+  bool operator!=(const MyIterator &that) const;
+  unsigned operator*() const;
+};
+
+extern "C" void workshareloop_iterator(float *a, float *b, float *c) {
+#pragma omp for
+  for (MyIterator it = MyIterator(7); it != MyIterator(41); ++it) {
+    unsigned i = *it;
+    a[i] = b[i] * c[i];
+  }
+}
+
+#endif // HEADER
+// CHECK-LABEL: define {{[^@]+}}@workshareloop_iterator
+// CHECK-SAME: (float* [[A:%.*]], float* [[B:%.*]], float* [[C:%.*]]) [[ATTR0:#.*]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca float*, align 8
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca float*, align 8
+// CHECK-NEXT:    [[C_ADDR:%.*]] = alloca float*, align 8
+// CHECK-NEXT:    [[IT:%.*]] = alloca [[STRUCT_MYITERATOR:%.*]], align 1
+// CHECK-NEXT:    [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON:%.*]], align 8
+// CHECK-NEXT:    [[AGG_CAPTURED1:%.*]] = alloca [[STRUCT_ANON_0:%.*]], align 1
+// CHECK-NEXT:    [[DOTCOUNT_ADDR:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    [[I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[P_LASTITER:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[P_LOWERBOUND:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    [[P_UPPERBOUND:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    [[P_STRIDE:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    store float* [[A]], float** [[A_ADDR]], align 8
+// CHECK-NEXT:    store float* [[B]], float** [[B_ADDR]], align 8
+// CHECK-NEXT:    store float* [[C]], float** [[C_ADDR]], align 8
+// CHECK-NEXT:    call void @_ZN10MyIteratorC1Ej(%struct.MyIterator* nonnull dereferenceable(1) [[IT]], i32 7)
+// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[AGG_CAPTURED]], i32 0, i32 0
+// CHECK-NEXT:    store %struct.MyIterator* [[IT]], %struct.MyIterator** [[TMP0]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], %struct.anon.0* [[AGG_CAPTURED1]], i32 0, i32 0
+// CHECK-NEXT:    call void @_ZN10MyIteratorC1ERKS_(%struct.MyIterator* nonnull dereferenceable(1) [[TMP1]], %struct.MyIterator* nonnull align 1 dereferenceable(1) [[IT]])
+// CHECK-NEXT:    call void @__captured_stmt(i64* [[DOTCOUNT_ADDR]], %struct.anon* [[AGG_CAPTURED]])
+// CHECK-NEXT:    [[DOTCOUNT:%.*]] = load i64, i64* [[DOTCOUNT_ADDR]], align 8
+// CHECK-NEXT:    br label [[OMP_LOOP_PREHEADER:%.*]]
+// CHECK:       omp_loop.preheader:
+// CHECK-NEXT:    store i64 0, i64* [[P_LOWERBOUND]], align 8
+// CHECK-NEXT:    [[TMP2:%.*]] = sub i64 [[DOTCOUNT]], 1
+// CHECK-NEXT:    store i64 [[TMP2]], i64* [[P_UPPERBOUND]], align 8
+// CHECK-NEXT:    store i64 1, i64* [[P_STRIDE]], align 8
+// CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1:@.*]])
+// CHECK-NEXT:    call void @__kmpc_for_static_init_8u(%struct.ident_t* [[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM]], i32 34, i32* [[P_LASTITER]], i64* [[P_LOWERBOUND]], i64* [[P_UPPERBOUND]], i64* [[P_STRIDE]], i64 1, i64 1)
+// CHECK-NEXT:    [[TMP3:%.*]] = load i64, i64* [[P_LOWERBOUND]], align 8
+// CHECK-NEXT:    [[TMP4:%.*]] = load i64, i64* [[P_UPPERBOUND]], align 8
+// CHECK-NEXT:    [[TMP5:%.*]] = sub i64 [[TMP4]], [[TMP3]]
+// CHECK-NEXT:    [[TMP6:%.*]] = add i64 [[TMP5]], 1
+// CHECK-NEXT:    br label [[OMP_LOOP_HEADER:%.*]]
+// CHECK:       omp_loop.header:
+// CHECK-NEXT:    [[OMP_LOOP_IV:%.*]] = phi i64 [ 0, [[OMP_LOOP_PREHEADER]] ], [ [[OMP_LOOP_NEXT:%.*]], [[OMP_LOOP_INC:%.*]] ]
+// CHECK-NEXT:    br label [[OMP_LOOP_COND:%.*]]
+// CHECK:       omp_loop.cond:
+// CHECK-NEXT:    [[OMP_LOOP_CMP:%.*]] = icmp ult i64 [[OMP_LOOP_IV]], [[TMP6]]
+// CHECK-NEXT:    br i1 [[OMP_LOOP_CMP]], label [[OMP_LOOP_BODY:%.*]], label [[OMP_LOOP_EXIT:%.*]]
+// CHECK:       omp_loop.body:
+// CHECK-NEXT:    [[TMP7:%.*]] = add i64 [[OMP_LOOP_IV]], [[TMP3]]
+// CHECK-NEXT:    call void @__captured_stmt.1(%struct.MyIterator* [[IT]], i64 [[TMP7]], %struct.anon.0* [[AGG_CAPTURED1]])
+// CHECK-NEXT:    [[CALL:%.*]] = call i32 @_ZNK10MyIteratordeEv(%struct.MyIterator* nonnull dereferenceable(1) [[IT]])
+// CHECK-NEXT:    store i32 [[CALL]], i32* [[I]], align 4
+// CHECK-NEXT:    [[TMP8:%.*]] = load float*, float** [[B_ADDR]], align 8
+// CHECK-NEXT:    [[TMP9:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[TMP9]] to i64
+// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[TMP8]], i64 [[IDXPROM]]
+// CHECK-NEXT:    [[TMP10:%.*]] = load float, float* [[ARRAYIDX]], align 4
+// CHECK-NEXT:    [[TMP11:%.*]] = load float*, float** [[C_ADDR]], align 8
+// CHECK-NEXT:    [[TMP12:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    [[IDXPROM2:%.*]] = zext i32 [[TMP12]] to i64
+// CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds float, float* [[TMP11]], i64 [[IDXPROM2]]
+// CHECK-NEXT:    [[TMP13:%.*]] = load float, float* [[ARRAYIDX3]], align 4
+// CHECK-NEXT:    [[MUL:%.*]] = fmul float [[TMP10]], [[TMP13]]
+// CHECK-NEXT:    [[TMP14:%.*]] = load float*, float** [[A_ADDR]], align 8
+// CHECK-NEXT:    [[TMP15:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    [[IDXPROM4:%.*]] = zext i32 [[TMP15]] to i64
+// CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds float, float* [[TMP14]], i64 [[IDXPROM4]]
+// CHECK-NEXT:    store float [[MUL]], float* [[ARRAYIDX5]], align 4
+// CHECK-NEXT:    br label [[OMP_LOOP_INC]]
+// CHECK:       omp_loop.inc:
+// CHECK-NEXT:    [[OMP_LOOP_NEXT]] = add nuw i64 [[OMP_LOOP_IV]], 1
+// CHECK-NEXT:    br label [[OMP_LOOP_HEADER]]
+// CHECK:       omp_loop.exit:
+// CHECK-NEXT:    call void @__kmpc_for_static_fini(%struct.ident_t* [[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM]])
+// CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM6:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1]])
+// CHECK-NEXT:    call void @__kmpc_barrier(%struct.ident_t* [[GLOB2:@.*]], i32 [[OMP_GLOBAL_THREAD_NUM6]])
+// CHECK-NEXT:    br label [[OMP_LOOP_AFTER:%.*]]
+// CHECK:       omp_loop.after:
+// CHECK-NEXT:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@__captured_stmt
+// CHECK-SAME: (i64* nonnull align 8 dereferenceable(8) [[DISTANCE:%.*]], %struct.anon* noalias [[__CONTEXT:%.*]]) [[ATTR2:#.*]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[DISTANCE_ADDR:%.*]] = alloca i64*, align 8
+// CHECK-NEXT:    [[__CONTEXT_ADDR:%.*]] = alloca %struct.anon*, align 8
+// CHECK-NEXT:    [[DOTSTART:%.*]] = alloca [[STRUCT_MYITERATOR:%.*]], align 1
+// CHECK-NEXT:    [[DOTSTOP:%.*]] = alloca [[STRUCT_MYITERATOR]], align 1
+// CHECK-NEXT:    [[DOTSTEP:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    store i64* [[DISTANCE]], i64** [[DISTANCE_ADDR]], align 8
+// CHECK-NEXT:    store %struct.anon* [[__CONTEXT]], %struct.anon** [[__CONTEXT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load %struct.anon*, %struct.anon** [[__CONTEXT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], %struct.anon* [[TMP0]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP2:%.*]] = load %struct.MyIterator*, %struct.MyIterator** [[TMP1]], align 8
+// CHECK-NEXT:    call void @_ZN10MyIteratorC1ERKS_(%struct.MyIterator* nonnull dereferenceable(1) [[DOTSTART]], %struct.MyIterator* nonnull align 1 dereferenceable(1) [[TMP2]])
+// CHECK-NEXT:    call void @_ZN10MyIteratorC1Ej(%struct.MyIterator* nonnull dereferenceable(1) [[DOTSTOP]], i32 41)
+// CHECK-NEXT:    store i64 1, i64* [[DOTSTEP]], align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = load i64, i64* [[DOTSTEP]], align 8
+// CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[TMP3]], 0
+// CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
+// CHECK:       cond.true:
+// CHECK-NEXT:    [[CALL:%.*]] = call i32 @_ZNK10MyIteratormiERKS_(%struct.MyIterator* nonnull dereferenceable(1) [[DOTSTART]], %struct.MyIterator* nonnull align 1 dereferenceable(1) [[DOTSTOP]])
+// CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[CALL]] to i64
+// CHECK-NEXT:    [[TMP4:%.*]] = load i64, i64* [[DOTSTEP]], align 8
+// CHECK-NEXT:    [[SUB:%.*]] = sub i64 0, [[TMP4]]
+// CHECK-NEXT:    [[DIV:%.*]] = udiv i64 [[CONV]], [[SUB]]
+// CHECK-NEXT:    br label [[COND_END:%.*]]
+// CHECK:       cond.false:
+// CHECK-NEXT:    [[CALL1:%.*]] = call i32 @_ZNK10MyIteratormiERKS_(%struct.MyIterator* nonnull dereferenceable(1) [[DOTSTOP]], %struct.MyIterator* nonnull align 1 dereferenceable(1) [[DOTSTART]])
+// CHECK-NEXT:    [[CONV2:%.*]] = sext i32 [[CALL1]] to i64
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, i64* [[DOTSTEP]], align 8
+// CHECK-NEXT:    [[DIV3:%.*]] = udiv i64 [[CONV2]], [[TMP5]]
+// CHECK-NEXT:    br label [[COND_END]]
+// CHECK:       cond.end:
+// CHECK-NEXT:    [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ [[DIV3]], [[COND_FALSE]] ]
+// CHECK-NEXT:    [[TMP6:%.*]] = load i64*, i64** [[DISTANCE_ADDR]], align 8
+// CHECK-NEXT:    store i64 [[COND]], i64* [[TMP6]], align 8
+// CHECK-NEXT:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@__captured_stmt.1
+// CHECK-SAME: (%struct.MyIterator* nonnull align 1 dereferenceable(1) [[LOOPVAR:%.*]], i64 [[LOGICAL:%.*]], %struct.anon.0* noalias [[__CONTEXT:%.*]]) [[ATTR2]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[LOOPVAR_ADDR:%.*]] = alloca %struct.MyIterator*, align 8
+// CHECK-NEXT:    [[LOGICAL_ADDR:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    [[__CONTEXT_ADDR:%.*]] = alloca %struct.anon.0*, align 8
+// CHECK-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_MYITERATOR:%.*]], align 1
+// CHECK-NEXT:    store %struct.MyIterator* [[LOOPVAR]], %struct.MyIterator** [[LOOPVAR_ADDR]], align 8
+// CHECK-NEXT:    store i64 [[LOGICAL]], i64* [[LOGICAL_ADDR]], align 8
+// CHECK-NEXT:    store %struct.anon.0* [[__CONTEXT]], %struct.anon.0** [[__CONTEXT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load %struct.anon.0*, %struct.anon.0** [[__CONTEXT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0:%.*]], %struct.anon.0* [[TMP0]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64* [[LOGICAL_ADDR]], align 8
+// CHECK-NEXT:    [[MUL:%.*]] = mul i64 1, [[TMP2]]
+// CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[MUL]] to i32
+// CHECK-NEXT:    call void @_ZNK10MyIteratorplEj(%struct.MyIterator* sret(%struct.MyIterator) align 1 [[REF_TMP]], %struct.MyIterator* nonnull dereferenceable(1) [[TMP1]], i32 [[CONV]])
+// CHECK-NEXT:    [[TMP3:%.*]] = load %struct.MyIterator*, %struct.MyIterator** [[LOOPVAR_ADDR]], align 8
+// CHECK-NEXT:    [[CALL:%.*]] = call nonnull align 1 dereferenceable(1) %struct.MyIterator* @_ZN10MyIteratoraSERKS_(%struct.MyIterator* nonnull dereferenceable(1) [[TMP3]], %struct.MyIterator* nonnull align 1 dereferenceable(1) [[REF_TMP]])
+// CHECK-NEXT:    ret void
+//

diff  --git a/clang/test/OpenMP/irbuilder_for_rangefor.cpp b/clang/test/OpenMP/irbuilder_for_rangefor.cpp
new file mode 100644
index 000000000000..6924354a1b6d
--- /dev/null
+++ b/clang/test/OpenMP/irbuilder_for_rangefor.cpp
@@ -0,0 +1,185 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs
+// RUN: %clang_cc1 -fopenmp-enable-irbuilder -verify -fopenmp -fopenmp-version=50 -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+struct MyIterator {
+  MyIterator(unsigned pos);
+  MyIterator(const MyIterator &other);
+  const MyIterator &operator=(const MyIterator &that);
+  MyIterator &operator++();
+  int operator-(const MyIterator &that) const;
+  MyIterator &operator+=(unsigned a);
+  MyIterator operator+(unsigned a) const;
+  bool operator==(const MyIterator &that) const;
+  bool operator!=(const MyIterator &that) const;
+  unsigned operator*() const;
+};
+
+struct MyRange {
+  MyRange(int n);
+
+  MyIterator begin();
+  MyIterator end();
+};
+
+extern "C" void workshareloop_rangefor(float *a, float *b, float *c) {
+#pragma omp for
+  for (unsigned i : MyRange(42)) {
+    a[i] = b[i] * c[i];
+  }
+}
+
+#endif // HEADER
+// CHECK-LABEL: define {{[^@]+}}@workshareloop_rangefor
+// CHECK-SAME: (float* [[A:%.*]], float* [[B:%.*]], float* [[C:%.*]]) [[ATTR0:#.*]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca float*, align 8
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca float*, align 8
+// CHECK-NEXT:    [[C_ADDR:%.*]] = alloca float*, align 8
+// CHECK-NEXT:    [[__RANGE2:%.*]] = alloca %struct.MyRange*, align 8
+// CHECK-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_MYRANGE:%.*]], align 1
+// CHECK-NEXT:    [[__BEGIN2:%.*]] = alloca [[STRUCT_MYITERATOR:%.*]], align 1
+// CHECK-NEXT:    [[__END2:%.*]] = alloca [[STRUCT_MYITERATOR]], align 1
+// CHECK-NEXT:    [[I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON:%.*]], align 8
+// CHECK-NEXT:    [[AGG_CAPTURED1:%.*]] = alloca [[STRUCT_ANON_0:%.*]], align 1
+// CHECK-NEXT:    [[DOTCOUNT_ADDR:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    [[P_LASTITER:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[P_LOWERBOUND:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    [[P_UPPERBOUND:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    [[P_STRIDE:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    store float* [[A]], float** [[A_ADDR]], align 8
+// CHECK-NEXT:    store float* [[B]], float** [[B_ADDR]], align 8
+// CHECK-NEXT:    store float* [[C]], float** [[C_ADDR]], align 8
+// CHECK-NEXT:    call void @_ZN7MyRangeC1Ei(%struct.MyRange* nonnull dereferenceable(1) [[REF_TMP]], i32 42)
+// CHECK-NEXT:    store %struct.MyRange* [[REF_TMP]], %struct.MyRange** [[__RANGE2]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load %struct.MyRange*, %struct.MyRange** [[__RANGE2]], align 8
+// CHECK-NEXT:    call void @_ZN7MyRange5beginEv(%struct.MyIterator* sret(%struct.MyIterator) align 1 [[__BEGIN2]], %struct.MyRange* nonnull dereferenceable(1) [[TMP0]])
+// CHECK-NEXT:    [[TMP1:%.*]] = load %struct.MyRange*, %struct.MyRange** [[__RANGE2]], align 8
+// CHECK-NEXT:    call void @_ZN7MyRange3endEv(%struct.MyIterator* sret(%struct.MyIterator) align 1 [[__END2]], %struct.MyRange* nonnull dereferenceable(1) [[TMP1]])
+// CHECK-NEXT:    [[CALL:%.*]] = call i32 @_ZNK10MyIteratordeEv(%struct.MyIterator* nonnull dereferenceable(1) [[__BEGIN2]])
+// CHECK-NEXT:    store i32 [[CALL]], i32* [[I]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[AGG_CAPTURED]], i32 0, i32 0
+// CHECK-NEXT:    store %struct.MyIterator* [[__BEGIN2]], %struct.MyIterator** [[TMP2]], align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[AGG_CAPTURED]], i32 0, i32 1
+// CHECK-NEXT:    store %struct.MyIterator* [[__END2]], %struct.MyIterator** [[TMP3]], align 8
+// CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], %struct.anon.0* [[AGG_CAPTURED1]], i32 0, i32 0
+// CHECK-NEXT:    call void @_ZN10MyIteratorC1ERKS_(%struct.MyIterator* nonnull dereferenceable(1) [[TMP4]], %struct.MyIterator* nonnull align 1 dereferenceable(1) [[__BEGIN2]])
+// CHECK-NEXT:    call void @__captured_stmt(i64* [[DOTCOUNT_ADDR]], %struct.anon* [[AGG_CAPTURED]])
+// CHECK-NEXT:    [[DOTCOUNT:%.*]] = load i64, i64* [[DOTCOUNT_ADDR]], align 8
+// CHECK-NEXT:    br label [[OMP_LOOP_PREHEADER:%.*]]
+// CHECK:       omp_loop.preheader:
+// CHECK-NEXT:    store i64 0, i64* [[P_LOWERBOUND]], align 8
+// CHECK-NEXT:    [[TMP5:%.*]] = sub i64 [[DOTCOUNT]], 1
+// CHECK-NEXT:    store i64 [[TMP5]], i64* [[P_UPPERBOUND]], align 8
+// CHECK-NEXT:    store i64 1, i64* [[P_STRIDE]], align 8
+// CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1:@.*]])
+// CHECK-NEXT:    call void @__kmpc_for_static_init_8u(%struct.ident_t* [[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM]], i32 34, i32* [[P_LASTITER]], i64* [[P_LOWERBOUND]], i64* [[P_UPPERBOUND]], i64* [[P_STRIDE]], i64 1, i64 1)
+// CHECK-NEXT:    [[TMP6:%.*]] = load i64, i64* [[P_LOWERBOUND]], align 8
+// CHECK-NEXT:    [[TMP7:%.*]] = load i64, i64* [[P_UPPERBOUND]], align 8
+// CHECK-NEXT:    [[TMP8:%.*]] = sub i64 [[TMP7]], [[TMP6]]
+// CHECK-NEXT:    [[TMP9:%.*]] = add i64 [[TMP8]], 1
+// CHECK-NEXT:    br label [[OMP_LOOP_HEADER:%.*]]
+// CHECK:       omp_loop.header:
+// CHECK-NEXT:    [[OMP_LOOP_IV:%.*]] = phi i64 [ 0, [[OMP_LOOP_PREHEADER]] ], [ [[OMP_LOOP_NEXT:%.*]], [[OMP_LOOP_INC:%.*]] ]
+// CHECK-NEXT:    br label [[OMP_LOOP_COND:%.*]]
+// CHECK:       omp_loop.cond:
+// CHECK-NEXT:    [[OMP_LOOP_CMP:%.*]] = icmp ult i64 [[OMP_LOOP_IV]], [[TMP9]]
+// CHECK-NEXT:    br i1 [[OMP_LOOP_CMP]], label [[OMP_LOOP_BODY:%.*]], label [[OMP_LOOP_EXIT:%.*]]
+// CHECK:       omp_loop.body:
+// CHECK-NEXT:    [[TMP10:%.*]] = add i64 [[OMP_LOOP_IV]], [[TMP6]]
+// CHECK-NEXT:    call void @__captured_stmt.1(i32* [[I]], i64 [[TMP10]], %struct.anon.0* [[AGG_CAPTURED1]])
+// CHECK-NEXT:    [[TMP11:%.*]] = load float*, float** [[B_ADDR]], align 8
+// CHECK-NEXT:    [[TMP12:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[TMP12]] to i64
+// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[TMP11]], i64 [[IDXPROM]]
+// CHECK-NEXT:    [[TMP13:%.*]] = load float, float* [[ARRAYIDX]], align 4
+// CHECK-NEXT:    [[TMP14:%.*]] = load float*, float** [[C_ADDR]], align 8
+// CHECK-NEXT:    [[TMP15:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    [[IDXPROM2:%.*]] = zext i32 [[TMP15]] to i64
+// CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds float, float* [[TMP14]], i64 [[IDXPROM2]]
+// CHECK-NEXT:    [[TMP16:%.*]] = load float, float* [[ARRAYIDX3]], align 4
+// CHECK-NEXT:    [[MUL:%.*]] = fmul float [[TMP13]], [[TMP16]]
+// CHECK-NEXT:    [[TMP17:%.*]] = load float*, float** [[A_ADDR]], align 8
+// CHECK-NEXT:    [[TMP18:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    [[IDXPROM4:%.*]] = zext i32 [[TMP18]] to i64
+// CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds float, float* [[TMP17]], i64 [[IDXPROM4]]
+// CHECK-NEXT:    store float [[MUL]], float* [[ARRAYIDX5]], align 4
+// CHECK-NEXT:    br label [[OMP_LOOP_INC]]
+// CHECK:       omp_loop.inc:
+// CHECK-NEXT:    [[OMP_LOOP_NEXT]] = add nuw i64 [[OMP_LOOP_IV]], 1
+// CHECK-NEXT:    br label [[OMP_LOOP_HEADER]]
+// CHECK:       omp_loop.exit:
+// CHECK-NEXT:    call void @__kmpc_for_static_fini(%struct.ident_t* [[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM]])
+// CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM6:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1]])
+// CHECK-NEXT:    call void @__kmpc_barrier(%struct.ident_t* [[GLOB2:@.*]], i32 [[OMP_GLOBAL_THREAD_NUM6]])
+// CHECK-NEXT:    br label [[OMP_LOOP_AFTER:%.*]]
+// CHECK:       omp_loop.after:
+// CHECK-NEXT:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@__captured_stmt
+// CHECK-SAME: (i64* nonnull align 8 dereferenceable(8) [[DISTANCE:%.*]], %struct.anon* noalias [[__CONTEXT:%.*]]) [[ATTR2:#.*]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[DISTANCE_ADDR:%.*]] = alloca i64*, align 8
+// CHECK-NEXT:    [[__CONTEXT_ADDR:%.*]] = alloca %struct.anon*, align 8
+// CHECK-NEXT:    [[DOTSTART:%.*]] = alloca [[STRUCT_MYITERATOR:%.*]], align 1
+// CHECK-NEXT:    [[DOTSTOP:%.*]] = alloca [[STRUCT_MYITERATOR]], align 1
+// CHECK-NEXT:    [[DOTSTEP:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    store i64* [[DISTANCE]], i64** [[DISTANCE_ADDR]], align 8
+// CHECK-NEXT:    store %struct.anon* [[__CONTEXT]], %struct.anon** [[__CONTEXT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load %struct.anon*, %struct.anon** [[__CONTEXT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], %struct.anon* [[TMP0]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP2:%.*]] = load %struct.MyIterator*, %struct.MyIterator** [[TMP1]], align 8
+// CHECK-NEXT:    call void @_ZN10MyIteratorC1ERKS_(%struct.MyIterator* nonnull dereferenceable(1) [[DOTSTART]], %struct.MyIterator* nonnull align 1 dereferenceable(1) [[TMP2]])
+// CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[TMP0]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP4:%.*]] = load %struct.MyIterator*, %struct.MyIterator** [[TMP3]], align 8
+// CHECK-NEXT:    call void @_ZN10MyIteratorC1ERKS_(%struct.MyIterator* nonnull dereferenceable(1) [[DOTSTOP]], %struct.MyIterator* nonnull align 1 dereferenceable(1) [[TMP4]])
+// CHECK-NEXT:    store i64 1, i64* [[DOTSTEP]], align 8
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, i64* [[DOTSTEP]], align 8
+// CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[TMP5]], 0
+// CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
+// CHECK:       cond.true:
+// CHECK-NEXT:    [[CALL:%.*]] = call i32 @_ZNK10MyIteratormiERKS_(%struct.MyIterator* nonnull dereferenceable(1) [[DOTSTART]], %struct.MyIterator* nonnull align 1 dereferenceable(1) [[DOTSTOP]])
+// CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[CALL]] to i64
+// CHECK-NEXT:    [[TMP6:%.*]] = load i64, i64* [[DOTSTEP]], align 8
+// CHECK-NEXT:    [[SUB:%.*]] = sub i64 0, [[TMP6]]
+// CHECK-NEXT:    [[DIV:%.*]] = udiv i64 [[CONV]], [[SUB]]
+// CHECK-NEXT:    br label [[COND_END:%.*]]
+// CHECK:       cond.false:
+// CHECK-NEXT:    [[CALL1:%.*]] = call i32 @_ZNK10MyIteratormiERKS_(%struct.MyIterator* nonnull dereferenceable(1) [[DOTSTOP]], %struct.MyIterator* nonnull align 1 dereferenceable(1) [[DOTSTART]])
+// CHECK-NEXT:    [[CONV2:%.*]] = sext i32 [[CALL1]] to i64
+// CHECK-NEXT:    [[TMP7:%.*]] = load i64, i64* [[DOTSTEP]], align 8
+// CHECK-NEXT:    [[DIV3:%.*]] = udiv i64 [[CONV2]], [[TMP7]]
+// CHECK-NEXT:    br label [[COND_END]]
+// CHECK:       cond.end:
+// CHECK-NEXT:    [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ [[DIV3]], [[COND_FALSE]] ]
+// CHECK-NEXT:    [[TMP8:%.*]] = load i64*, i64** [[DISTANCE_ADDR]], align 8
+// CHECK-NEXT:    store i64 [[COND]], i64* [[TMP8]], align 8
+// CHECK-NEXT:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@__captured_stmt.1
+// CHECK-SAME: (i32* nonnull align 4 dereferenceable(4) [[LOOPVAR:%.*]], i64 [[LOGICAL:%.*]], %struct.anon.0* noalias [[__CONTEXT:%.*]]) [[ATTR2]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[LOOPVAR_ADDR:%.*]] = alloca i32*, align 8
+// CHECK-NEXT:    [[LOGICAL_ADDR:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    [[__CONTEXT_ADDR:%.*]] = alloca %struct.anon.0*, align 8
+// CHECK-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_MYITERATOR:%.*]], align 1
+// CHECK-NEXT:    store i32* [[LOOPVAR]], i32** [[LOOPVAR_ADDR]], align 8
+// CHECK-NEXT:    store i64 [[LOGICAL]], i64* [[LOGICAL_ADDR]], align 8
+// CHECK-NEXT:    store %struct.anon.0* [[__CONTEXT]], %struct.anon.0** [[__CONTEXT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load %struct.anon.0*, %struct.anon.0** [[__CONTEXT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0:%.*]], %struct.anon.0* [[TMP0]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64* [[LOGICAL_ADDR]], align 8
+// CHECK-NEXT:    [[MUL:%.*]] = mul i64 1, [[TMP2]]
+// CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[MUL]] to i32
+// CHECK-NEXT:    call void @_ZNK10MyIteratorplEj(%struct.MyIterator* sret(%struct.MyIterator) align 1 [[REF_TMP]], %struct.MyIterator* nonnull dereferenceable(1) [[TMP1]], i32 [[CONV]])
+// CHECK-NEXT:    [[CALL:%.*]] = call i32 @_ZNK10MyIteratordeEv(%struct.MyIterator* nonnull dereferenceable(1) [[REF_TMP]])
+// CHECK-NEXT:    [[TMP3:%.*]] = load i32*, i32** [[LOOPVAR_ADDR]], align 8
+// CHECK-NEXT:    store i32 [[CALL]], i32* [[TMP3]], align 4
+// CHECK-NEXT:    ret void
+//

diff  --git a/clang/test/OpenMP/irbuilder_for_unsigned.c b/clang/test/OpenMP/irbuilder_for_unsigned.c
new file mode 100644
index 000000000000..031b329e14df
--- /dev/null
+++ b/clang/test/OpenMP/irbuilder_for_unsigned.c
@@ -0,0 +1,155 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs
+// RUN: %clang_cc1 -fopenmp-enable-irbuilder -verify -fopenmp -fopenmp-version=45 -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+extern "C" void workshareloop_unsigned(float *a, float *b, float *c, float *d) {
+#pragma omp for
+  for (unsigned i = 33; i < 32000000; i += 7) {
+    a[i] = b[i] * c[i] * d[i];
+  }
+}
+
+#endif // HEADER
+// CHECK-LABEL: define {{[^@]+}}@workshareloop_unsigned
+// CHECK-SAME: (float* [[A:%.*]], float* [[B:%.*]], float* [[C:%.*]], float* [[D:%.*]]) [[ATTR0:#.*]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca float*, align 8
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca float*, align 8
+// CHECK-NEXT:    [[C_ADDR:%.*]] = alloca float*, align 8
+// CHECK-NEXT:    [[D_ADDR:%.*]] = alloca float*, align 8
+// CHECK-NEXT:    [[I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON:%.*]], align 8
+// CHECK-NEXT:    [[AGG_CAPTURED1:%.*]] = alloca [[STRUCT_ANON_0:%.*]], align 4
+// CHECK-NEXT:    [[DOTCOUNT_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[P_LASTITER:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[P_LOWERBOUND:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[P_UPPERBOUND:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[P_STRIDE:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store float* [[A]], float** [[A_ADDR]], align 8
+// CHECK-NEXT:    store float* [[B]], float** [[B_ADDR]], align 8
+// CHECK-NEXT:    store float* [[C]], float** [[C_ADDR]], align 8
+// CHECK-NEXT:    store float* [[D]], float** [[D_ADDR]], align 8
+// CHECK-NEXT:    store i32 33, i32* [[I]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[AGG_CAPTURED]], i32 0, i32 0
+// CHECK-NEXT:    store i32* [[I]], i32** [[TMP0]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], %struct.anon.0* [[AGG_CAPTURED1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    store i32 [[TMP2]], i32* [[TMP1]], align 4
+// CHECK-NEXT:    call void @__captured_stmt(i32* [[DOTCOUNT_ADDR]], %struct.anon* [[AGG_CAPTURED]])
+// CHECK-NEXT:    [[DOTCOUNT:%.*]] = load i32, i32* [[DOTCOUNT_ADDR]], align 4
+// CHECK-NEXT:    br label [[OMP_LOOP_PREHEADER:%.*]]
+// CHECK:       omp_loop.preheader:
+// CHECK-NEXT:    store i32 0, i32* [[P_LOWERBOUND]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = sub i32 [[DOTCOUNT]], 1
+// CHECK-NEXT:    store i32 [[TMP3]], i32* [[P_UPPERBOUND]], align 4
+// CHECK-NEXT:    store i32 1, i32* [[P_STRIDE]], align 4
+// CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1:@.*]])
+// CHECK-NEXT:    call void @__kmpc_for_static_init_4u(%struct.ident_t* [[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM]], i32 34, i32* [[P_LASTITER]], i32* [[P_LOWERBOUND]], i32* [[P_UPPERBOUND]], i32* [[P_STRIDE]], i32 1, i32 1)
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, i32* [[P_LOWERBOUND]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* [[P_UPPERBOUND]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = sub i32 [[TMP5]], [[TMP4]]
+// CHECK-NEXT:    [[TMP7:%.*]] = add i32 [[TMP6]], 1
+// CHECK-NEXT:    br label [[OMP_LOOP_HEADER:%.*]]
+// CHECK:       omp_loop.header:
+// CHECK-NEXT:    [[OMP_LOOP_IV:%.*]] = phi i32 [ 0, [[OMP_LOOP_PREHEADER]] ], [ [[OMP_LOOP_NEXT:%.*]], [[OMP_LOOP_INC:%.*]] ]
+// CHECK-NEXT:    br label [[OMP_LOOP_COND:%.*]]
+// CHECK:       omp_loop.cond:
+// CHECK-NEXT:    [[OMP_LOOP_CMP:%.*]] = icmp ult i32 [[OMP_LOOP_IV]], [[TMP7]]
+// CHECK-NEXT:    br i1 [[OMP_LOOP_CMP]], label [[OMP_LOOP_BODY:%.*]], label [[OMP_LOOP_EXIT:%.*]]
+// CHECK:       omp_loop.body:
+// CHECK-NEXT:    [[TMP8:%.*]] = add i32 [[OMP_LOOP_IV]], [[TMP4]]
+// CHECK-NEXT:    call void @__captured_stmt.1(i32* [[I]], i32 [[TMP8]], %struct.anon.0* [[AGG_CAPTURED1]])
+// CHECK-NEXT:    [[TMP9:%.*]] = load float*, float** [[B_ADDR]], align 8
+// CHECK-NEXT:    [[TMP10:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[TMP10]] to i64
+// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[TMP9]], i64 [[IDXPROM]]
+// CHECK-NEXT:    [[TMP11:%.*]] = load float, float* [[ARRAYIDX]], align 4
+// CHECK-NEXT:    [[TMP12:%.*]] = load float*, float** [[C_ADDR]], align 8
+// CHECK-NEXT:    [[TMP13:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    [[IDXPROM2:%.*]] = zext i32 [[TMP13]] to i64
+// CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds float, float* [[TMP12]], i64 [[IDXPROM2]]
+// CHECK-NEXT:    [[TMP14:%.*]] = load float, float* [[ARRAYIDX3]], align 4
+// CHECK-NEXT:    [[MUL:%.*]] = fmul float [[TMP11]], [[TMP14]]
+// CHECK-NEXT:    [[TMP15:%.*]] = load float*, float** [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP16:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    [[IDXPROM4:%.*]] = zext i32 [[TMP16]] to i64
+// CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds float, float* [[TMP15]], i64 [[IDXPROM4]]
+// CHECK-NEXT:    [[TMP17:%.*]] = load float, float* [[ARRAYIDX5]], align 4
+// CHECK-NEXT:    [[MUL6:%.*]] = fmul float [[MUL]], [[TMP17]]
+// CHECK-NEXT:    [[TMP18:%.*]] = load float*, float** [[A_ADDR]], align 8
+// CHECK-NEXT:    [[TMP19:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    [[IDXPROM7:%.*]] = zext i32 [[TMP19]] to i64
+// CHECK-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds float, float* [[TMP18]], i64 [[IDXPROM7]]
+// CHECK-NEXT:    store float [[MUL6]], float* [[ARRAYIDX8]], align 4
+// CHECK-NEXT:    br label [[OMP_LOOP_INC]]
+// CHECK:       omp_loop.inc:
+// CHECK-NEXT:    [[OMP_LOOP_NEXT]] = add nuw i32 [[OMP_LOOP_IV]], 1
+// CHECK-NEXT:    br label [[OMP_LOOP_HEADER]]
+// CHECK:       omp_loop.exit:
+// CHECK-NEXT:    call void @__kmpc_for_static_fini(%struct.ident_t* [[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM]])
+// CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM9:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1]])
+// CHECK-NEXT:    call void @__kmpc_barrier(%struct.ident_t* [[GLOB2:@.*]], i32 [[OMP_GLOBAL_THREAD_NUM9]])
+// CHECK-NEXT:    br label [[OMP_LOOP_AFTER:%.*]]
+// CHECK:       omp_loop.after:
+// CHECK-NEXT:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@__captured_stmt
+// CHECK-SAME: (i32* nonnull align 4 dereferenceable(4) [[DISTANCE:%.*]], %struct.anon* noalias [[__CONTEXT:%.*]]) [[ATTR1:#.*]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[DISTANCE_ADDR:%.*]] = alloca i32*, align 8
+// CHECK-NEXT:    [[__CONTEXT_ADDR:%.*]] = alloca %struct.anon*, align 8
+// CHECK-NEXT:    [[DOTSTART:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[DOTSTOP:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[DOTSTEP:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32* [[DISTANCE]], i32** [[DISTANCE_ADDR]], align 8
+// CHECK-NEXT:    store %struct.anon* [[__CONTEXT]], %struct.anon** [[__CONTEXT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load %struct.anon*, %struct.anon** [[__CONTEXT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], %struct.anon* [[TMP0]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32*, i32** [[TMP1]], align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
+// CHECK-NEXT:    store i32 [[TMP3]], i32* [[DOTSTART]], align 4
+// CHECK-NEXT:    store i32 32000000, i32* [[DOTSTOP]], align 4
+// CHECK-NEXT:    store i32 7, i32* [[DOTSTEP]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, i32* [[DOTSTART]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* [[DOTSTOP]], align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[TMP4]], [[TMP5]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
+// CHECK:       cond.true:
+// CHECK-NEXT:    [[TMP6:%.*]] = load i32, i32* [[DOTSTOP]], align 4
+// CHECK-NEXT:    [[TMP7:%.*]] = load i32, i32* [[DOTSTART]], align 4
+// CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[TMP6]], [[TMP7]]
+// CHECK-NEXT:    [[TMP8:%.*]] = load i32, i32* [[DOTSTEP]], align 4
+// CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[SUB]], [[TMP8]]
+// CHECK-NEXT:    br label [[COND_END:%.*]]
+// CHECK:       cond.false:
+// CHECK-NEXT:    br label [[COND_END]]
+// CHECK:       cond.end:
+// CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[DIV]], [[COND_TRUE]] ], [ 0, [[COND_FALSE]] ]
+// CHECK-NEXT:    [[TMP9:%.*]] = load i32*, i32** [[DISTANCE_ADDR]], align 8
+// CHECK-NEXT:    store i32 [[COND]], i32* [[TMP9]], align 4
+// CHECK-NEXT:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@__captured_stmt.1
+// CHECK-SAME: (i32* nonnull align 4 dereferenceable(4) [[LOOPVAR:%.*]], i32 [[LOGICAL:%.*]], %struct.anon.0* noalias [[__CONTEXT:%.*]]) [[ATTR1]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[LOOPVAR_ADDR:%.*]] = alloca i32*, align 8
+// CHECK-NEXT:    [[LOGICAL_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[__CONTEXT_ADDR:%.*]] = alloca %struct.anon.0*, align 8
+// CHECK-NEXT:    store i32* [[LOOPVAR]], i32** [[LOOPVAR_ADDR]], align 8
+// CHECK-NEXT:    store i32 [[LOGICAL]], i32* [[LOGICAL_ADDR]], align 4
+// CHECK-NEXT:    store %struct.anon.0* [[__CONTEXT]], %struct.anon.0** [[__CONTEXT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load %struct.anon.0*, %struct.anon.0** [[__CONTEXT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0:%.*]], %struct.anon.0* [[TMP0]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[LOGICAL_ADDR]], align 4
+// CHECK-NEXT:    [[MUL:%.*]] = mul i32 7, [[TMP3]]
+// CHECK-NEXT:    [[ADD:%.*]] = add i32 [[TMP2]], [[MUL]]
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32*, i32** [[LOOPVAR_ADDR]], align 8
+// CHECK-NEXT:    store i32 [[ADD]], i32* [[TMP4]], align 4
+// CHECK-NEXT:    ret void
+//

diff  --git a/clang/test/OpenMP/irbuilder_nested_parallel_for.c b/clang/test/OpenMP/irbuilder_nested_parallel_for.c
index 2ca6fe711e28..9a603027f845 100644
--- a/clang/test/OpenMP/irbuilder_nested_parallel_for.c
+++ b/clang/test/OpenMP/irbuilder_nested_parallel_for.c
@@ -23,15 +23,15 @@
 //
 // CHECK-DEBUG-LABEL: @_Z14parallel_for_0v(
 // CHECK-DEBUG-NEXT:  entry:
-// CHECK-DEBUG-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1:@.*]]), [[DBG10:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1:@.*]]), [[DBG12:!dbg !.*]]
 // CHECK-DEBUG-NEXT:    br label [[OMP_PARALLEL:%.*]]
 // CHECK-DEBUG:       omp_parallel:
-// CHECK-DEBUG-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @_Z14parallel_for_0v..omp_par to void (i32*, i32*, ...)*)), [[DBG11:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @_Z14parallel_for_0v..omp_par to void (i32*, i32*, ...)*)), [[DBG13:!dbg !.*]]
 // CHECK-DEBUG-NEXT:    br label [[OMP_PAR_OUTLINED_EXIT:%.*]]
 // CHECK-DEBUG:       omp.par.outlined.exit:
 // CHECK-DEBUG-NEXT:    br label [[OMP_PAR_EXIT_SPLIT:%.*]]
 // CHECK-DEBUG:       omp.par.exit.split:
-// CHECK-DEBUG-NEXT:    ret void, [[DBG14:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    ret void, [[DBG17:!dbg !.*]]
 //
 void parallel_for_0(void) {
 #pragma omp parallel
@@ -53,9 +53,9 @@ void parallel_for_0(void) {
 // CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1]])
 // CHECK-NEXT:    br label [[OMP_PARALLEL:%.*]]
 // CHECK:       omp_parallel:
-// CHECK-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB1]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, double*, float**)* @_Z14parallel_for_1Pfid..omp_par.1 to void (i32*, i32*, ...)*), i32* [[A_ADDR]], double* [[B_ADDR]], float** [[R_ADDR]])
-// CHECK-NEXT:    br label [[OMP_PAR_OUTLINED_EXIT19:%.*]]
-// CHECK:       omp.par.outlined.exit19:
+// CHECK-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB1]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, double*, float**)* @_Z14parallel_for_1Pfid..omp_par.4 to void (i32*, i32*, ...)*), i32* [[A_ADDR]], double* [[B_ADDR]], float** [[R_ADDR]])
+// CHECK-NEXT:    br label [[OMP_PAR_OUTLINED_EXIT16:%.*]]
+// CHECK:       omp.par.outlined.exit16:
 // CHECK-NEXT:    br label [[OMP_PAR_EXIT_SPLIT:%.*]]
 // CHECK:       omp.par.exit.split:
 // CHECK-NEXT:    ret void
@@ -66,20 +66,20 @@ void parallel_for_0(void) {
 // CHECK-DEBUG-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
 // CHECK-DEBUG-NEXT:    [[B_ADDR:%.*]] = alloca double, align 8
 // CHECK-DEBUG-NEXT:    store float* [[R:%.*]], float** [[R_ADDR]], align 8
-// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata float** [[R_ADDR]], [[META41:metadata !.*]], metadata !DIExpression()), [[DBG42:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata float** [[R_ADDR]], [[META72:metadata !.*]], metadata !DIExpression()), [[DBG73:!dbg !.*]]
 // CHECK-DEBUG-NEXT:    store i32 [[A:%.*]], i32* [[A_ADDR]], align 4
-// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata i32* [[A_ADDR]], [[META43:metadata !.*]], metadata !DIExpression()), [[DBG44:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata i32* [[A_ADDR]], [[META74:metadata !.*]], metadata !DIExpression()), [[DBG75:!dbg !.*]]
 // CHECK-DEBUG-NEXT:    store double [[B:%.*]], double* [[B_ADDR]], align 8
-// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata double* [[B_ADDR]], [[META45:metadata !.*]], metadata !DIExpression()), [[DBG46:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB10:@.*]]), [[DBG47:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata double* [[B_ADDR]], [[META76:metadata !.*]], metadata !DIExpression()), [[DBG77:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB6:@.*]]), [[DBG78:!dbg !.*]]
 // CHECK-DEBUG-NEXT:    br label [[OMP_PARALLEL:%.*]]
 // CHECK-DEBUG:       omp_parallel:
-// CHECK-DEBUG-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB10]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, double*, float**)* @_Z14parallel_for_1Pfid..omp_par.1 to void (i32*, i32*, ...)*), i32* [[A_ADDR]], double* [[B_ADDR]], float** [[R_ADDR]]), [[DBG48:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    br label [[OMP_PAR_OUTLINED_EXIT19:%.*]]
-// CHECK-DEBUG:       omp.par.outlined.exit19:
+// CHECK-DEBUG-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB6]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, double*, float**)* @_Z14parallel_for_1Pfid..omp_par.4 to void (i32*, i32*, ...)*), i32* [[A_ADDR]], double* [[B_ADDR]], float** [[R_ADDR]]), [[DBG79:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    br label [[OMP_PAR_OUTLINED_EXIT16:%.*]]
+// CHECK-DEBUG:       omp.par.outlined.exit16:
 // CHECK-DEBUG-NEXT:    br label [[OMP_PAR_EXIT_SPLIT:%.*]]
 // CHECK-DEBUG:       omp.par.exit.split:
-// CHECK-DEBUG-NEXT:    ret void, [[DBG50:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    ret void, [[DBG81:!dbg !.*]]
 //
 void parallel_for_1(float *r, int a, double b) {
 #pragma omp parallel
@@ -99,76 +99,72 @@ void parallel_for_1(float *r, int a, double b) {
 // CHECK-NEXT:    [[R_ADDR:%.*]] = alloca float*, align 8
 // CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
 // CHECK-NEXT:    [[B_ADDR:%.*]] = alloca double, align 8
-// CHECK-NEXT:    [[DOTOMP_IV212:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[TMP213:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[DOTOMP_LB214:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[DOTOMP_UB215:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[DOTOMP_STRIDE216:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[DOTOMP_IS_LAST217:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[I218:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[I185:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[AGG_CAPTURED186:%.*]] = alloca [[STRUCT_ANON_17:%.*]], align 8
+// CHECK-NEXT:    [[AGG_CAPTURED187:%.*]] = alloca [[STRUCT_ANON_18:%.*]], align 4
+// CHECK-NEXT:    [[DOTCOUNT_ADDR188:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[P_LASTITER203:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[P_LOWERBOUND204:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[P_UPPERBOUND205:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[P_STRIDE206:%.*]] = alloca i32, align 4
 // CHECK-NEXT:    store float* [[R:%.*]], float** [[R_ADDR]], align 8
 // CHECK-NEXT:    store i32 [[A:%.*]], i32* [[A_ADDR]], align 4
 // CHECK-NEXT:    store double [[B:%.*]], double* [[B_ADDR]], align 8
 // CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1]])
 // CHECK-NEXT:    br label [[OMP_PARALLEL:%.*]]
 // CHECK:       omp_parallel:
-// CHECK-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB1]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, double*, float**)* @_Z14parallel_for_2Pfid..omp_par.4 to void (i32*, i32*, ...)*), i32* [[A_ADDR]], double* [[B_ADDR]], float** [[R_ADDR]])
-// CHECK-NEXT:    br label [[OMP_PAR_OUTLINED_EXIT211:%.*]]
-// CHECK:       omp.par.outlined.exit211:
+// CHECK-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB1]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, double*, float**)* @_Z14parallel_for_2Pfid..omp_par.23 to void (i32*, i32*, ...)*), i32* [[A_ADDR]], double* [[B_ADDR]], float** [[R_ADDR]])
+// CHECK-NEXT:    br label [[OMP_PAR_OUTLINED_EXIT184:%.*]]
+// CHECK:       omp.par.outlined.exit184:
 // CHECK-NEXT:    br label [[OMP_PAR_EXIT_SPLIT:%.*]]
 // CHECK:       omp.par.exit.split:
-// CHECK-NEXT:    store i32 0, i32* [[DOTOMP_LB214]], align 4
-// CHECK-NEXT:    store i32 99, i32* [[DOTOMP_UB215]], align 4
-// CHECK-NEXT:    store i32 1, i32* [[DOTOMP_STRIDE216]], align 4
-// CHECK-NEXT:    store i32 0, i32* [[DOTOMP_IS_LAST217]], align 4
-// CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM219:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB41:@.*]])
-// CHECK-NEXT:    call void @__kmpc_for_static_init_4(%struct.ident_t* [[GLOB2:@.*]], i32 [[OMP_GLOBAL_THREAD_NUM219]], i32 34, i32* [[DOTOMP_IS_LAST217]], i32* [[DOTOMP_LB214]], i32* [[DOTOMP_UB215]], i32* [[DOTOMP_STRIDE216]], i32 1, i32 1)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[DOTOMP_UB215]], align 4
-// CHECK-NEXT:    [[CMP220:%.*]] = icmp sgt i32 [[TMP0]], 99
-// CHECK-NEXT:    br i1 [[CMP220]], label [[COND_TRUE221:%.*]], label [[COND_FALSE222:%.*]]
-// CHECK:       cond.true221:
-// CHECK-NEXT:    br label [[COND_END223:%.*]]
-// CHECK:       cond.false222:
-// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[DOTOMP_UB215]], align 4
-// CHECK-NEXT:    br label [[COND_END223]]
-// CHECK:       cond.end223:
-// CHECK-NEXT:    [[COND224:%.*]] = phi i32 [ 99, [[COND_TRUE221]] ], [ [[TMP1]], [[COND_FALSE222]] ]
-// CHECK-NEXT:    store i32 [[COND224]], i32* [[DOTOMP_UB215]], align 4
-// CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[DOTOMP_LB214]], align 4
-// CHECK-NEXT:    store i32 [[TMP2]], i32* [[DOTOMP_IV212]], align 4
-// CHECK-NEXT:    br label [[OMP_INNER_FOR_COND225:%.*]]
-// CHECK:       omp.inner.for.cond225:
-// CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[DOTOMP_IV212]], align 4
-// CHECK-NEXT:    [[TMP4:%.*]] = load i32, i32* [[DOTOMP_UB215]], align 4
-// CHECK-NEXT:    [[CMP226:%.*]] = icmp sle i32 [[TMP3]], [[TMP4]]
-// CHECK-NEXT:    br i1 [[CMP226]], label [[OMP_INNER_FOR_BODY227:%.*]], label [[OMP_INNER_FOR_END236:%.*]]
-// CHECK:       omp.inner.for.body227:
-// CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* [[DOTOMP_IV212]], align 4
-// CHECK-NEXT:    [[MUL228:%.*]] = mul nsw i32 [[TMP5]], 1
-// CHECK-NEXT:    [[ADD229:%.*]] = add nsw i32 0, [[MUL228]]
-// CHECK-NEXT:    store i32 [[ADD229]], i32* [[I218]], align 4
-// CHECK-NEXT:    [[TMP6:%.*]] = load i32, i32* [[A_ADDR]], align 4
-// CHECK-NEXT:    [[CONV230:%.*]] = sitofp i32 [[TMP6]] to double
-// CHECK-NEXT:    [[TMP7:%.*]] = load double, double* [[B_ADDR]], align 8
-// CHECK-NEXT:    [[ADD231:%.*]] = fadd double [[CONV230]], [[TMP7]]
-// CHECK-NEXT:    [[CONV232:%.*]] = fptrunc double [[ADD231]] to float
-// CHECK-NEXT:    [[TMP8:%.*]] = load float*, float** [[R_ADDR]], align 8
-// CHECK-NEXT:    store float [[CONV232]], float* [[TMP8]], align 4
-// CHECK-NEXT:    br label [[OMP_BODY_CONTINUE233:%.*]]
-// CHECK:       omp.body.continue233:
-// CHECK-NEXT:    br label [[OMP_INNER_FOR_INC234:%.*]]
-// CHECK:       omp.inner.for.inc234:
-// CHECK-NEXT:    [[TMP9:%.*]] = load i32, i32* [[DOTOMP_IV212]], align 4
-// CHECK-NEXT:    [[ADD235:%.*]] = add nsw i32 [[TMP9]], 1
-// CHECK-NEXT:    store i32 [[ADD235]], i32* [[DOTOMP_IV212]], align 4
-// CHECK-NEXT:    br label [[OMP_INNER_FOR_COND225]]
-// CHECK:       omp.inner.for.end236:
-// CHECK-NEXT:    br label [[OMP_LOOP_EXIT237:%.*]]
-// CHECK:       omp.loop.exit237:
-// CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM238:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB43:@.*]])
-// CHECK-NEXT:    call void @__kmpc_for_static_fini(%struct.ident_t* [[GLOB2]], i32 [[OMP_GLOBAL_THREAD_NUM238]])
-// CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM239:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1]])
-// CHECK-NEXT:    call void @__kmpc_barrier(%struct.ident_t* [[GLOB7:@.*]], i32 [[OMP_GLOBAL_THREAD_NUM239]])
+// CHECK-NEXT:    store i32 0, i32* [[I185]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_ANON_17]], %struct.anon.17* [[AGG_CAPTURED186]], i32 0, i32 0
+// CHECK-NEXT:    store i32* [[I185]], i32** [[TMP0]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_18]], %struct.anon.18* [[AGG_CAPTURED187]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[I185]], align 4
+// CHECK-NEXT:    store i32 [[TMP2]], i32* [[TMP1]], align 4
+// CHECK-NEXT:    call void @__captured_stmt.19(i32* [[DOTCOUNT_ADDR188]], %struct.anon.17* [[AGG_CAPTURED186]])
+// CHECK-NEXT:    [[DOTCOUNT189:%.*]] = load i32, i32* [[DOTCOUNT_ADDR188]], align 4
+// CHECK-NEXT:    br label [[OMP_LOOP_PREHEADER190:%.*]]
+// CHECK:       omp_loop.preheader190:
+// CHECK-NEXT:    store i32 0, i32* [[P_LOWERBOUND204]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = sub i32 [[DOTCOUNT189]], 1
+// CHECK-NEXT:    store i32 [[TMP3]], i32* [[P_UPPERBOUND205]], align 4
+// CHECK-NEXT:    store i32 1, i32* [[P_STRIDE206]], align 4
+// CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM207:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1]])
+// CHECK-NEXT:    call void @__kmpc_for_static_init_4u(%struct.ident_t* [[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM207]], i32 34, i32* [[P_LASTITER203]], i32* [[P_LOWERBOUND204]], i32* [[P_UPPERBOUND205]], i32* [[P_STRIDE206]], i32 1, i32 1)
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, i32* [[P_LOWERBOUND204]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* [[P_UPPERBOUND205]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = sub i32 [[TMP5]], [[TMP4]]
+// CHECK-NEXT:    [[TMP7:%.*]] = add i32 [[TMP6]], 1
+// CHECK-NEXT:    br label [[OMP_LOOP_HEADER191:%.*]]
+// CHECK:       omp_loop.header191:
+// CHECK-NEXT:    [[OMP_LOOP_IV197:%.*]] = phi i32 [ 0, [[OMP_LOOP_PREHEADER190]] ], [ [[OMP_LOOP_NEXT199:%.*]], [[OMP_LOOP_INC194:%.*]] ]
+// CHECK-NEXT:    br label [[OMP_LOOP_COND192:%.*]]
+// CHECK:       omp_loop.cond192:
+// CHECK-NEXT:    [[OMP_LOOP_CMP198:%.*]] = icmp ult i32 [[OMP_LOOP_IV197]], [[TMP7]]
+// CHECK-NEXT:    br i1 [[OMP_LOOP_CMP198]], label [[OMP_LOOP_BODY193:%.*]], label [[OMP_LOOP_EXIT195:%.*]]
+// CHECK:       omp_loop.body193:
+// CHECK-NEXT:    [[TMP8:%.*]] = add i32 [[OMP_LOOP_IV197]], [[TMP4]]
+// CHECK-NEXT:    call void @__captured_stmt.20(i32* [[I185]], i32 [[TMP8]], %struct.anon.18* [[AGG_CAPTURED187]])
+// CHECK-NEXT:    [[TMP9:%.*]] = load i32, i32* [[A_ADDR]], align 4
+// CHECK-NEXT:    [[CONV200:%.*]] = sitofp i32 [[TMP9]] to double
+// CHECK-NEXT:    [[TMP10:%.*]] = load double, double* [[B_ADDR]], align 8
+// CHECK-NEXT:    [[ADD201:%.*]] = fadd double [[CONV200]], [[TMP10]]
+// CHECK-NEXT:    [[CONV202:%.*]] = fptrunc double [[ADD201]] to float
+// CHECK-NEXT:    [[TMP11:%.*]] = load float*, float** [[R_ADDR]], align 8
+// CHECK-NEXT:    store float [[CONV202]], float* [[TMP11]], align 4
+// CHECK-NEXT:    br label [[OMP_LOOP_INC194]]
+// CHECK:       omp_loop.inc194:
+// CHECK-NEXT:    [[OMP_LOOP_NEXT199]] = add nuw i32 [[OMP_LOOP_IV197]], 1
+// CHECK-NEXT:    br label [[OMP_LOOP_HEADER191]]
+// CHECK:       omp_loop.exit195:
+// CHECK-NEXT:    call void @__kmpc_for_static_fini(%struct.ident_t* [[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM207]])
+// CHECK-NEXT:    [[OMP_GLOBAL_THREAD_NUM208:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1]])
+// CHECK-NEXT:    call void @__kmpc_barrier(%struct.ident_t* [[GLOB2:@.*]], i32 [[OMP_GLOBAL_THREAD_NUM208]])
+// CHECK-NEXT:    br label [[OMP_LOOP_AFTER196:%.*]]
+// CHECK:       omp_loop.after196:
 // CHECK-NEXT:    ret void
 //
 // CHECK-DEBUG-LABEL: @_Z14parallel_for_2Pfid(
@@ -176,86 +172,77 @@ void parallel_for_1(float *r, int a, double b) {
 // CHECK-DEBUG-NEXT:    [[R_ADDR:%.*]] = alloca float*, align 8
 // CHECK-DEBUG-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
 // CHECK-DEBUG-NEXT:    [[B_ADDR:%.*]] = alloca double, align 8
-// CHECK-DEBUG-NEXT:    [[DOTOMP_IV212:%.*]] = alloca i32, align 4
-// CHECK-DEBUG-NEXT:    [[TMP213:%.*]] = alloca i32, align 4
-// CHECK-DEBUG-NEXT:    [[DOTOMP_LB214:%.*]] = alloca i32, align 4
-// CHECK-DEBUG-NEXT:    [[DOTOMP_UB215:%.*]] = alloca i32, align 4
-// CHECK-DEBUG-NEXT:    [[DOTOMP_STRIDE216:%.*]] = alloca i32, align 4
-// CHECK-DEBUG-NEXT:    [[DOTOMP_IS_LAST217:%.*]] = alloca i32, align 4
-// CHECK-DEBUG-NEXT:    [[I218:%.*]] = alloca i32, align 4
+// CHECK-DEBUG-NEXT:    [[I185:%.*]] = alloca i32, align 4
+// CHECK-DEBUG-NEXT:    [[AGG_CAPTURED186:%.*]] = alloca [[STRUCT_ANON_17:%.*]], align 8
+// CHECK-DEBUG-NEXT:    [[AGG_CAPTURED187:%.*]] = alloca [[STRUCT_ANON_18:%.*]], align 4
+// CHECK-DEBUG-NEXT:    [[DOTCOUNT_ADDR188:%.*]] = alloca i32, align 4
+// CHECK-DEBUG-NEXT:    [[P_LASTITER203:%.*]] = alloca i32, align 4
+// CHECK-DEBUG-NEXT:    [[P_LOWERBOUND204:%.*]] = alloca i32, align 4
+// CHECK-DEBUG-NEXT:    [[P_UPPERBOUND205:%.*]] = alloca i32, align 4
+// CHECK-DEBUG-NEXT:    [[P_STRIDE206:%.*]] = alloca i32, align 4
 // CHECK-DEBUG-NEXT:    store float* [[R:%.*]], float** [[R_ADDR]], align 8
-// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata float** [[R_ADDR]], [[META77:metadata !.*]], metadata !DIExpression()), [[DBG78:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata float** [[R_ADDR]], [[META133:metadata !.*]], metadata !DIExpression()), [[DBG134:!dbg !.*]]
 // CHECK-DEBUG-NEXT:    store i32 [[A:%.*]], i32* [[A_ADDR]], align 4
-// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata i32* [[A_ADDR]], [[META79:metadata !.*]], metadata !DIExpression()), [[DBG80:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata i32* [[A_ADDR]], [[META135:metadata !.*]], metadata !DIExpression()), [[DBG136:!dbg !.*]]
 // CHECK-DEBUG-NEXT:    store double [[B:%.*]], double* [[B_ADDR]], align 8
-// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata double* [[B_ADDR]], [[META81:metadata !.*]], metadata !DIExpression()), [[DBG82:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB21:@.*]]), [[DBG83:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata double* [[B_ADDR]], [[META137:metadata !.*]], metadata !DIExpression()), [[DBG138:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB13:@.*]]), [[DBG139:!dbg !.*]]
 // CHECK-DEBUG-NEXT:    br label [[OMP_PARALLEL:%.*]]
 // CHECK-DEBUG:       omp_parallel:
-// CHECK-DEBUG-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB21]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, double*, float**)* @_Z14parallel_for_2Pfid..omp_par.4 to void (i32*, i32*, ...)*), i32* [[A_ADDR]], double* [[B_ADDR]], float** [[R_ADDR]]), [[DBG84:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    br label [[OMP_PAR_OUTLINED_EXIT211:%.*]]
-// CHECK-DEBUG:       omp.par.outlined.exit211:
+// CHECK-DEBUG-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB13]], i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, double*, float**)* @_Z14parallel_for_2Pfid..omp_par.23 to void (i32*, i32*, ...)*), i32* [[A_ADDR]], double* [[B_ADDR]], float** [[R_ADDR]]), [[DBG140:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    br label [[OMP_PAR_OUTLINED_EXIT184:%.*]]
+// CHECK-DEBUG:       omp.par.outlined.exit184:
 // CHECK-DEBUG-NEXT:    br label [[OMP_PAR_EXIT_SPLIT:%.*]]
 // CHECK-DEBUG:       omp.par.exit.split:
-// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata i32* [[DOTOMP_IV212]], [[META87:metadata !.*]], metadata !DIExpression()), [[DBG89:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata i32* [[DOTOMP_LB214]], [[META90:metadata !.*]], metadata !DIExpression()), [[DBG89]]
-// CHECK-DEBUG-NEXT:    store i32 0, i32* [[DOTOMP_LB214]], align 4, [[DBG91:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata i32* [[DOTOMP_UB215]], [[META92:metadata !.*]], metadata !DIExpression()), [[DBG89]]
-// CHECK-DEBUG-NEXT:    store i32 99, i32* [[DOTOMP_UB215]], align 4, [[DBG91]]
-// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata i32* [[DOTOMP_STRIDE216]], [[META93:metadata !.*]], metadata !DIExpression()), [[DBG89]]
-// CHECK-DEBUG-NEXT:    store i32 1, i32* [[DOTOMP_STRIDE216]], align 4, [[DBG91]]
-// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata i32* [[DOTOMP_IS_LAST217]], [[META94:metadata !.*]], metadata !DIExpression()), [[DBG89]]
-// CHECK-DEBUG-NEXT:    store i32 0, i32* [[DOTOMP_IS_LAST217]], align 4, [[DBG91]]
-// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata i32* [[I218]], [[META95:metadata !.*]], metadata !DIExpression()), [[DBG89]]
-// CHECK-DEBUG-NEXT:    [[OMP_GLOBAL_THREAD_NUM219:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB79:@.*]])
-// CHECK-DEBUG-NEXT:    call void @__kmpc_for_static_init_4(%struct.ident_t* [[GLOB78:@.*]], i32 [[OMP_GLOBAL_THREAD_NUM219]], i32 34, i32* [[DOTOMP_IS_LAST217]], i32* [[DOTOMP_LB214]], i32* [[DOTOMP_UB215]], i32* [[DOTOMP_STRIDE216]], i32 1, i32 1), [[DBG96:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    [[TMP0:%.*]] = load i32, i32* [[DOTOMP_UB215]], align 4, [[DBG91]]
-// CHECK-DEBUG-NEXT:    [[CMP220:%.*]] = icmp sgt i32 [[TMP0]], 99, [[DBG91]]
-// CHECK-DEBUG-NEXT:    br i1 [[CMP220]], label [[COND_TRUE221:%.*]], label [[COND_FALSE222:%.*]], [[DBG91]]
-// CHECK-DEBUG:       cond.true221:
-// CHECK-DEBUG-NEXT:    br label [[COND_END223:%.*]], [[DBG91]]
-// CHECK-DEBUG:       cond.false222:
-// CHECK-DEBUG-NEXT:    [[TMP1:%.*]] = load i32, i32* [[DOTOMP_UB215]], align 4, [[DBG91]]
-// CHECK-DEBUG-NEXT:    br label [[COND_END223]], [[DBG91]]
-// CHECK-DEBUG:       cond.end223:
-// CHECK-DEBUG-NEXT:    [[COND224:%.*]] = phi i32 [ 99, [[COND_TRUE221]] ], [ [[TMP1]], [[COND_FALSE222]] ], [[DBG91]]
-// CHECK-DEBUG-NEXT:    store i32 [[COND224]], i32* [[DOTOMP_UB215]], align 4, [[DBG91]]
-// CHECK-DEBUG-NEXT:    [[TMP2:%.*]] = load i32, i32* [[DOTOMP_LB214]], align 4, [[DBG91]]
-// CHECK-DEBUG-NEXT:    store i32 [[TMP2]], i32* [[DOTOMP_IV212]], align 4, [[DBG91]]
-// CHECK-DEBUG-NEXT:    br label [[OMP_INNER_FOR_COND225:%.*]], [[DBG97:!dbg !.*]]
-// CHECK-DEBUG:       omp.inner.for.cond225:
-// CHECK-DEBUG-NEXT:    [[TMP3:%.*]] = load i32, i32* [[DOTOMP_IV212]], align 4, [[DBG91]]
-// CHECK-DEBUG-NEXT:    [[TMP4:%.*]] = load i32, i32* [[DOTOMP_UB215]], align 4, [[DBG91]]
-// CHECK-DEBUG-NEXT:    [[CMP226:%.*]] = icmp sle i32 [[TMP3]], [[TMP4]], [[DBG98:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    br i1 [[CMP226]], label [[OMP_INNER_FOR_BODY227:%.*]], label [[OMP_INNER_FOR_END236:%.*]], [[DBG97]]
-// CHECK-DEBUG:       omp.inner.for.body227:
-// CHECK-DEBUG-NEXT:    [[TMP5:%.*]] = load i32, i32* [[DOTOMP_IV212]], align 4, [[DBG91]]
-// CHECK-DEBUG-NEXT:    [[MUL228:%.*]] = mul nsw i32 [[TMP5]], 1, [[DBG99:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    [[ADD229:%.*]] = add nsw i32 0, [[MUL228]], [[DBG99]]
-// CHECK-DEBUG-NEXT:    store i32 [[ADD229]], i32* [[I218]], align 4, [[DBG99]]
-// CHECK-DEBUG-NEXT:    [[TMP6:%.*]] = load i32, i32* [[A_ADDR]], align 4, [[DBG100:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    [[CONV230:%.*]] = sitofp i32 [[TMP6]] to double, [[DBG100]]
-// CHECK-DEBUG-NEXT:    [[TMP7:%.*]] = load double, double* [[B_ADDR]], align 8, [[DBG101:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    [[ADD231:%.*]] = fadd double [[CONV230]], [[TMP7]], [[DBG102:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    [[CONV232:%.*]] = fptrunc double [[ADD231]] to float, [[DBG100]]
-// CHECK-DEBUG-NEXT:    [[TMP8:%.*]] = load float*, float** [[R_ADDR]], align 8, [[DBG103:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    store float [[CONV232]], float* [[TMP8]], align 4, [[DBG104:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    br label [[OMP_BODY_CONTINUE233:%.*]], [[DBG105:!dbg !.*]]
-// CHECK-DEBUG:       omp.body.continue233:
-// CHECK-DEBUG-NEXT:    br label [[OMP_INNER_FOR_INC234:%.*]], [[DBG96]]
-// CHECK-DEBUG:       omp.inner.for.inc234:
-// CHECK-DEBUG-NEXT:    [[TMP9:%.*]] = load i32, i32* [[DOTOMP_IV212]], align 4, [[DBG91]]
-// CHECK-DEBUG-NEXT:    [[ADD235:%.*]] = add nsw i32 [[TMP9]], 1, [[DBG98]]
-// CHECK-DEBUG-NEXT:    store i32 [[ADD235]], i32* [[DOTOMP_IV212]], align 4, [[DBG98]]
-// CHECK-DEBUG-NEXT:    br label [[OMP_INNER_FOR_COND225]], [[DBG96]], [[LOOP106:!llvm.loop !.*]]
-// CHECK-DEBUG:       omp.inner.for.end236:
-// CHECK-DEBUG-NEXT:    br label [[OMP_LOOP_EXIT237:%.*]], [[DBG96]]
-// CHECK-DEBUG:       omp.loop.exit237:
-// CHECK-DEBUG-NEXT:    [[OMP_GLOBAL_THREAD_NUM238:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB82:@.*]])
-// CHECK-DEBUG-NEXT:    call void @__kmpc_for_static_fini(%struct.ident_t* [[GLOB81:@.*]], i32 [[OMP_GLOBAL_THREAD_NUM238]]), [[DBG107:!dbg !.*]]
-// CHECK-DEBUG-NEXT:    [[OMP_GLOBAL_THREAD_NUM239:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB82]]), [[DBG107]]
-// CHECK-DEBUG-NEXT:    call void @__kmpc_barrier(%struct.ident_t* [[GLOB83:@.*]], i32 [[OMP_GLOBAL_THREAD_NUM239]]), [[DBG107]]
-// CHECK-DEBUG-NEXT:    ret void, [[DBG108:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    call void @llvm.dbg.declare(metadata i32* [[I185]], [[META144:metadata !.*]], metadata !DIExpression()), [[DBG147:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    store i32 0, i32* [[I185]], align 4, [[DBG147]]
+// CHECK-DEBUG-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_ANON_17]], %struct.anon.17* [[AGG_CAPTURED186]], i32 0, i32 0, [[DBG148:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    store i32* [[I185]], i32** [[TMP0]], align 8, [[DBG148]]
+// CHECK-DEBUG-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_18]], %struct.anon.18* [[AGG_CAPTURED187]], i32 0, i32 0, [[DBG148]]
+// CHECK-DEBUG-NEXT:    [[TMP2:%.*]] = load i32, i32* [[I185]], align 4, [[DBG149:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    store i32 [[TMP2]], i32* [[TMP1]], align 4, [[DBG148]]
+// CHECK-DEBUG-NEXT:    call void @__captured_stmt.19(i32* [[DOTCOUNT_ADDR188]], %struct.anon.17* [[AGG_CAPTURED186]]), [[DBG148]]
+// CHECK-DEBUG-NEXT:    [[DOTCOUNT189:%.*]] = load i32, i32* [[DOTCOUNT_ADDR188]], align 4, [[DBG148]]
+// CHECK-DEBUG-NEXT:    br label [[OMP_LOOP_PREHEADER190:%.*]], [[DBG148]]
+// CHECK-DEBUG:       omp_loop.preheader190:
+// CHECK-DEBUG-NEXT:    store i32 0, i32* [[P_LOWERBOUND204]], align 4, [[DBG148]]
+// CHECK-DEBUG-NEXT:    [[TMP3:%.*]] = sub i32 [[DOTCOUNT189]], 1, [[DBG148]]
+// CHECK-DEBUG-NEXT:    store i32 [[TMP3]], i32* [[P_UPPERBOUND205]], align 4, [[DBG148]]
+// CHECK-DEBUG-NEXT:    store i32 1, i32* [[P_STRIDE206]], align 4, [[DBG148]]
+// CHECK-DEBUG-NEXT:    [[OMP_GLOBAL_THREAD_NUM207:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB42:@.*]]), [[DBG148]]
+// CHECK-DEBUG-NEXT:    call void @__kmpc_for_static_init_4u(%struct.ident_t* [[GLOB42]], i32 [[OMP_GLOBAL_THREAD_NUM207]], i32 34, i32* [[P_LASTITER203]], i32* [[P_LOWERBOUND204]], i32* [[P_UPPERBOUND205]], i32* [[P_STRIDE206]], i32 1, i32 1), [[DBG148]]
+// CHECK-DEBUG-NEXT:    [[TMP4:%.*]] = load i32, i32* [[P_LOWERBOUND204]], align 4, [[DBG148]]
+// CHECK-DEBUG-NEXT:    [[TMP5:%.*]] = load i32, i32* [[P_UPPERBOUND205]], align 4, [[DBG148]]
+// CHECK-DEBUG-NEXT:    [[TMP6:%.*]] = sub i32 [[TMP5]], [[TMP4]], [[DBG148]]
+// CHECK-DEBUG-NEXT:    [[TMP7:%.*]] = add i32 [[TMP6]], 1, [[DBG148]]
+// CHECK-DEBUG-NEXT:    br label [[OMP_LOOP_HEADER191:%.*]], [[DBG148]]
+// CHECK-DEBUG:       omp_loop.header191:
+// CHECK-DEBUG-NEXT:    [[OMP_LOOP_IV197:%.*]] = phi i32 [ 0, [[OMP_LOOP_PREHEADER190]] ], [ [[OMP_LOOP_NEXT199:%.*]], [[OMP_LOOP_INC194:%.*]] ], [[DBG148]]
+// CHECK-DEBUG-NEXT:    br label [[OMP_LOOP_COND192:%.*]], [[DBG148]]
+// CHECK-DEBUG:       omp_loop.cond192:
+// CHECK-DEBUG-NEXT:    [[OMP_LOOP_CMP198:%.*]] = icmp ult i32 [[OMP_LOOP_IV197]], [[TMP7]], [[DBG148]]
+// CHECK-DEBUG-NEXT:    br i1 [[OMP_LOOP_CMP198]], label [[OMP_LOOP_BODY193:%.*]], label [[OMP_LOOP_EXIT195:%.*]], [[DBG148]]
+// CHECK-DEBUG:       omp_loop.body193:
+// CHECK-DEBUG-NEXT:    [[TMP8:%.*]] = add i32 [[OMP_LOOP_IV197]], [[TMP4]], [[DBG148]]
+// CHECK-DEBUG-NEXT:    call void @__captured_stmt.20(i32* [[I185]], i32 [[TMP8]], %struct.anon.18* [[AGG_CAPTURED187]]), [[DBG148]]
+// CHECK-DEBUG-NEXT:    [[TMP9:%.*]] = load i32, i32* [[A_ADDR]], align 4, [[DBG150:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    [[CONV200:%.*]] = sitofp i32 [[TMP9]] to double, [[DBG150]]
+// CHECK-DEBUG-NEXT:    [[TMP10:%.*]] = load double, double* [[B_ADDR]], align 8, [[DBG151:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    [[ADD201:%.*]] = fadd double [[CONV200]], [[TMP10]], [[DBG152:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    [[CONV202:%.*]] = fptrunc double [[ADD201]] to float, [[DBG150]]
+// CHECK-DEBUG-NEXT:    [[TMP11:%.*]] = load float*, float** [[R_ADDR]], align 8, [[DBG153:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    store float [[CONV202]], float* [[TMP11]], align 4, [[DBG154:!dbg !.*]]
+// CHECK-DEBUG-NEXT:    br label [[OMP_LOOP_INC194]], [[DBG148]]
+// CHECK-DEBUG:       omp_loop.inc194:
+// CHECK-DEBUG-NEXT:    [[OMP_LOOP_NEXT199]] = add nuw i32 [[OMP_LOOP_IV197]], 1, [[DBG148]]
+// CHECK-DEBUG-NEXT:    br label [[OMP_LOOP_HEADER191]], [[DBG148]]
+// CHECK-DEBUG:       omp_loop.exit195:
+// CHECK-DEBUG-NEXT:    call void @__kmpc_for_static_fini(%struct.ident_t* [[GLOB42]], i32 [[OMP_GLOBAL_THREAD_NUM207]]), [[DBG148]]
+// CHECK-DEBUG-NEXT:    [[OMP_GLOBAL_THREAD_NUM208:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB42]]), [[DBG151]]
+// CHECK-DEBUG-NEXT:    call void @__kmpc_barrier(%struct.ident_t* [[GLOB43:@.*]], i32 [[OMP_GLOBAL_THREAD_NUM208]]), [[DBG151]]
+// CHECK-DEBUG-NEXT:    br label [[OMP_LOOP_AFTER196:%.*]], [[DBG148]]
+// CHECK-DEBUG:       omp_loop.after196:
+// CHECK-DEBUG-NEXT:    ret void, [[DBG155:!dbg !.*]]
 //
 void parallel_for_2(float *r, int a, double b) {
 #pragma omp parallel

diff  --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 1aaf69548efb..e949b8513535 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -5542,6 +5542,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
     return cxstring::createRef("CXXAccessSpecifier");
   case CXCursor_ModuleImportDecl:
     return cxstring::createRef("ModuleImport");
+  case CXCursor_OMPCanonicalLoop:
+    return cxstring::createRef("OMPCanonicalLoop");
   case CXCursor_OMPParallelDirective:
     return cxstring::createRef("OMPParallelDirective");
   case CXCursor_OMPSimdDirective:

diff  --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index a5a9c6926eaa..0811b0bcdb88 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -639,6 +639,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
   case Stmt::MSDependentExistsStmtClass:
     K = CXCursor_UnexposedStmt;
     break;
+  case Stmt::OMPCanonicalLoopClass:
+    K = CXCursor_OMPCanonicalLoop;
+    break;
   case Stmt::OMPParallelDirectiveClass:
     K = CXCursor_OMPParallelDirective;
     break;

diff  --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index 6c6468b1acc6..bb4a9aa22cbc 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -31,6 +31,7 @@ class OpenMPIRBuilder {
   /// Create a new OpenMPIRBuilder operating on the given module \p M. This will
   /// not have an effect on \p M (see initialize).
   OpenMPIRBuilder(Module &M) : M(M), Builder(M.getContext()) {}
+  ~OpenMPIRBuilder();
 
   /// Initialize the internal state, this will put structures types and
   /// potentially other helpers into the underlying module. Must be called
@@ -38,10 +39,12 @@ class OpenMPIRBuilder {
   void initialize();
 
   /// Finalize the underlying module, e.g., by outlining regions.
+  /// \param Fn                    The function to be finalized. If not used,
+  ///                              all functions are finalized.
   /// \param AllowExtractorSinking Flag to include sinking instructions,
   ///                              emitted by CodeExtractor, in the
   ///                              outlined region. Default is false.
-  void finalize(bool AllowExtractorSinking = false);
+  void finalize(Function *Fn = nullptr, bool AllowExtractorSinking = false);
 
   /// Add attributes known for \p FnID to \p Fn.
   void addAttributes(omp::RuntimeFunction FnID, Function &Fn);
@@ -364,6 +367,31 @@ class OpenMPIRBuilder {
                                                bool NeedsBarrier,
                                                Value *Chunk = nullptr);
 
+  /// Modifies the canonical loop to be a workshare loop.
+  ///
+  /// This takes a \p LoopInfo representing a canonical loop, such as the one
+  /// created by \p createCanonicalLoop and emits additional instructions to
+  /// turn it into a workshare loop. In particular, it calls to an OpenMP
+  /// runtime function in the preheader to obtain the loop bounds to be used in
+  /// the current thread, updates the relevant instructions in the canonical
+  /// loop and calls to an OpenMP runtime finalization function after the loop.
+  ///
+  /// \param Loc      The source location description, the insertion location
+  ///                 is not used.
+  /// \param CLI      A descriptor of the canonical loop to workshare.
+  /// \param AllocaIP An insertion point for Alloca instructions usable in the
+  ///                 preheader of the loop.
+  /// \param NeedsBarrier Indicates whether a barrier must be insterted after
+  ///                     the loop.
+  /// \param Chunk    The size of loop chunk considered as a unit when
+  ///                 scheduling. If \p nullptr, defaults to 1.
+  ///
+  /// \returns Updated CanonicalLoopInfo.
+  CanonicalLoopInfo *createWorkshareLoop(const LocationDescription &Loc,
+                                         CanonicalLoopInfo *CLI,
+                                         InsertPointTy AllocaIP,
+                                         bool NeedsBarrier);
+
   /// Tile a loop nest.
   ///
   /// Tiles the loops of \p Loops by the tile sizes in \p TileSizes. Loops in
@@ -543,6 +571,9 @@ class OpenMPIRBuilder {
     /// vector and set.
     void collectBlocks(SmallPtrSetImpl<BasicBlock *> &BlockSet,
                        SmallVectorImpl<BasicBlock *> &BlockVector);
+
+    /// Return the function that contains the region to be outlined.
+    Function *getFunction() const { return EntryBB->getParent(); }
   };
 
   /// Collection of regions that need to be outlined during finalization.
@@ -916,6 +947,8 @@ class CanonicalLoopInfo {
     return {After, After->begin()};
   };
 
+  Function *getFunction() const { return Header->getParent(); }
+
   /// Consistency self-check.
   void assertOK() const;
 };

diff  --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 9286394fe8c7..a1d7a53c3617 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -126,15 +126,23 @@ Function *OpenMPIRBuilder::getOrCreateRuntimeFunctionPtr(RuntimeFunction FnID) {
 
 void OpenMPIRBuilder::initialize() { initializeTypes(M); }
 
-void OpenMPIRBuilder::finalize(bool AllowExtractorSinking) {
+void OpenMPIRBuilder::finalize(Function *Fn, bool AllowExtractorSinking) {
   SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
   SmallVector<BasicBlock *, 32> Blocks;
+  SmallVector<OutlineInfo, 16> DeferredOutlines;
   for (OutlineInfo &OI : OutlineInfos) {
+    // Skip functions that have not finalized yet; may happen with nested
+    // function generation.
+    if (Fn && OI.getFunction() != Fn) {
+      DeferredOutlines.push_back(OI);
+      continue;
+    }
+
     ParallelRegionBlockSet.clear();
     Blocks.clear();
     OI.collectBlocks(ParallelRegionBlockSet, Blocks);
 
-    Function *OuterFn = OI.EntryBB->getParent();
+    Function *OuterFn = OI.getFunction();
     CodeExtractorAnalysisCache CEAC(*OuterFn);
     CodeExtractor Extractor(Blocks, /* DominatorTree */ nullptr,
                             /* AggregateArgs */ false,
@@ -199,8 +207,12 @@ void OpenMPIRBuilder::finalize(bool AllowExtractorSinking) {
       OI.PostOutlineCB(*OutlinedFn);
   }
 
-  // Allow finalize to be called multiple times.
-  OutlineInfos.clear();
+  // Remove work items that have been completed.
+  OutlineInfos = std::move(DeferredOutlines);
+}
+
+OpenMPIRBuilder::~OpenMPIRBuilder() {
+  assert(OutlineInfos.empty() && "There must be no outstanding outlinings");
 }
 
 Value *OpenMPIRBuilder::getOrCreateIdent(Constant *SrcLocStr,
@@ -1164,6 +1176,13 @@ CanonicalLoopInfo *OpenMPIRBuilder::createStaticWorkshareLoop(
   return CLI;
 }
 
+CanonicalLoopInfo *OpenMPIRBuilder::createWorkshareLoop(
+    const LocationDescription &Loc, CanonicalLoopInfo *CLI,
+    InsertPointTy AllocaIP, bool NeedsBarrier) {
+  // Currently only supports static schedules.
+  return createStaticWorkshareLoop(Loc, CLI, AllocaIP, NeedsBarrier);
+}
+
 /// Make \p Source branch to \p Target.
 ///
 /// Handles two situations:

diff  --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
index 8950517c7928..1f5afc781b36 100644
--- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
+++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
@@ -794,7 +794,8 @@ struct OpenMPOpt {
       BranchInst::Create(AfterBB, AfterIP.getBlock());
 
       // Perform the actual outlining.
-      OMPInfoCache.OMPBuilder.finalize(/* AllowExtractorSinking */ true);
+      OMPInfoCache.OMPBuilder.finalize(OriginalFn,
+                                       /* AllowExtractorSinking */ true);
 
       Function *OutlinedFn = MergableCIs.front()->getCaller();
 


        


More information about the llvm-commits mailing list