[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 8: Codegen) (PR #169687)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Nov 26 10:05:15 PST 2025


https://github.com/Sirraide updated https://github.com/llvm/llvm-project/pull/169687

>From 162351a655bcc71ad6c76710c30518b032231ab4 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 26 Nov 2025 17:15:21 +0100
Subject: [PATCH 1/2] [Clang] [C++26] Expansion Statements (Part 8)

---
 clang/lib/CodeGen/CGStmt.cpp                  |   41 +-
 clang/lib/CodeGen/CodeGenFunction.h           |    3 +
 .../cxx2c-destructuring-expansion-stmt.cpp    |  471 +++++
 ...cxx2c-enumerating-expansion-statements.cpp | 1518 +++++++++++++++++
 .../cxx2c-expansion-stmts-control-flow.cpp    |  429 +++++
 .../cxx2c-expansion-stmts-templates.cpp       |  208 +++
 .../cxx2c-iterating-expansion-stmt.cpp        |  474 +++++
 7 files changed, 3143 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CodeGenCXX/cxx2c-destructuring-expansion-stmt.cpp
 create mode 100644 clang/test/CodeGenCXX/cxx2c-enumerating-expansion-statements.cpp
 create mode 100644 clang/test/CodeGenCXX/cxx2c-expansion-stmts-control-flow.cpp
 create mode 100644 clang/test/CodeGenCXX/cxx2c-expansion-stmts-templates.cpp
 create mode 100644 clang/test/CodeGenCXX/cxx2c-iterating-expansion-stmt.cpp

diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 40c92035008ae..d6c6d159a5438 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -210,7 +210,8 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
   case Stmt::CXXDependentExpansionStmtPatternClass:
     llvm_unreachable("unexpanded expansion statements should not be emitted");
   case Stmt::CXXExpansionStmtInstantiationClass:
-    llvm_unreachable("Todo");
+    EmitCXXExpansionStmtInstantiation(cast<CXXExpansionStmtInstantiation>(*S));
+    break;
   case Stmt::SEHTryStmtClass:
     EmitSEHTryStmt(cast<SEHTryStmt>(*S));
     break;
@@ -1563,6 +1564,44 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
   }
 }
 
+void CodeGenFunction::EmitCXXExpansionStmtInstantiation(
+    const CXXExpansionStmtInstantiation &S) {
+  // FIXME: For reasons beyond my understanding, two scopes are required to emit
+  // the destructors of lifetime-extended temporaries in the right place, but
+  // only in some templates. There are some other issues with lifetime-extended
+  // temporaries currently (https://github.com/llvm/llvm-project/issues/165182);
+  // perhaps resolving those will allow us to remove the second scope here
+  // because there really ought to be a better way of doing this.
+  LexicalScope Scope(*this, S.getSourceRange());
+  LexicalScope Scope2(*this, S.getSourceRange());
+
+  for (const Stmt *DS : S.getSharedStmts())
+    EmitStmt(DS);
+
+  if (S.getInstantiations().empty() || !HaveInsertPoint())
+    return;
+
+  JumpDest ExpandExit = getJumpDestInCurrentScope("expand.end");
+  JumpDest ContinueDest;
+  for (auto [N, Inst] : enumerate(S.getInstantiations())) {
+    if (!HaveInsertPoint()) {
+      EmitBlock(ExpandExit.getBlock(), true);
+      return;
+    }
+
+    if (N == S.getInstantiations().size() - 1)
+      ContinueDest = ExpandExit;
+    else
+      ContinueDest = getJumpDestInCurrentScope("expand.next");
+
+    LexicalScope ExpansionScope(*this, S.getSourceRange());
+    BreakContinueStack.push_back(BreakContinue(S, ExpandExit, ContinueDest));
+    EmitStmt(Inst);
+    BreakContinueStack.pop_back();
+    EmitBlock(ContinueDest.getBlock(), true);
+  }
+}
+
 void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
   if (RV.isScalar()) {
     Builder.CreateStore(RV.getScalarVal(), ReturnValue);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 8c4c1c8c2dc95..a895f187f3946 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -3690,6 +3690,9 @@ class CodeGenFunction : public CodeGenTypeCache {
   void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
                            ArrayRef<const Attr *> Attrs = {});
 
+  void
+  EmitCXXExpansionStmtInstantiation(const CXXExpansionStmtInstantiation &S);
+
   /// Controls insertion of cancellation exit blocks in worksharing constructs.
   class OMPCancelStackRAII {
     CodeGenFunction &CGF;
diff --git a/clang/test/CodeGenCXX/cxx2c-destructuring-expansion-stmt.cpp b/clang/test/CodeGenCXX/cxx2c-destructuring-expansion-stmt.cpp
new file mode 100644
index 0000000000000..16d8c370a9d3f
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx2c-destructuring-expansion-stmt.cpp
@@ -0,0 +1,471 @@
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+struct A {};
+struct B { int x = 1; };
+struct C { int a = 1, b = 2, c = 3; };
+
+void g(int);
+
+int references_destructuring() {
+  C c;
+  template for (auto& x : c) { ++x; }
+  template for (auto&& x : c) { ++x; }
+  return c.a + c.b + c.c;
+}
+
+template <auto v>
+int destructure() {
+  int sum = 0;
+  template for (auto x : v) sum += x;
+  template for (constexpr auto x : v) sum += x;
+  return sum;
+}
+
+void f() {
+  destructure<B{10}>();
+  destructure<C{}>();
+  destructure<C{3, 4, 5}>();
+}
+
+void empty() {
+  static constexpr A a;
+  template for (auto x : A()) g(x);
+  template for (auto& x : a) g(x);
+  template for (auto&& x : A()) g(x);
+  template for (constexpr auto x : a) g(x);
+}
+
+namespace apply_lifetime_extension {
+struct T {
+  int& x;
+  T(int& x) noexcept : x(x) {}
+  ~T() noexcept { x = 42; }
+};
+
+const T& f(const T& t) noexcept { return t; }
+T g(int& x) noexcept { return T(x); }
+
+// CWG 3043:
+//
+// Lifetime extension only applies to destructuring expansion statements
+// (enumerating statements don't have a range variable, and the range variable
+// of iterating statements is constexpr).
+int lifetime_extension() {
+  int x = 5;
+  int sum  = 0;
+  template for (auto e : f(g(x))) {
+    sum += x;
+  }
+  return sum + x;
+}
+
+template <typename T>
+int lifetime_extension_instantiate_expansions() {
+  int x = 5;
+  int sum  = 0;
+  template for (T e : f(g(x))) {
+    sum += x;
+  }
+  return sum + x;
+}
+
+template <typename T>
+int lifetime_extension_dependent_expansion_stmt() {
+  int x = 5;
+  int sum  = 0;
+  template for (int e : f(g((T&)x))) {
+    sum += x;
+  }
+  return sum + x;
+}
+
+template <typename U>
+struct foo {
+  template <typename T>
+  int lifetime_extension_multiple_instantiations() {
+    int x = 5;
+    int sum  = 0;
+    template for (T e : f(g((U&)x))) {
+      sum += x;
+    }
+    return sum + x;
+  }
+};
+
+void instantiate() {
+  lifetime_extension_instantiate_expansions<int>();
+  lifetime_extension_dependent_expansion_stmt<int>();
+  foo<int>().lifetime_extension_multiple_instantiations<int>();
+}
+}
+
+// CHECK: @_ZZ5emptyvE1a = internal constant %struct.A zeroinitializer, align 1
+// CHECK: @_ZTAXtl1BLi10EEE = {{.*}} constant %struct.B { i32 10 }, comdat
+// CHECK: @_ZTAXtl1CLi1ELi2ELi3EEE = {{.*}} constant %struct.C { i32 1, i32 2, i32 3 }, comdat
+// CHECK: @_ZTAXtl1CLi3ELi4ELi5EEE = {{.*}} constant %struct.C { i32 3, i32 4, i32 5 }, comdat
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z24references_destructuringv()
+// CHECK: entry:
+// CHECK-NEXT:   %c = alloca %struct.C, align 4
+// CHECK-NEXT:   %0 = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca ptr, align 8
+// CHECK-NEXT:   %x1 = alloca ptr, align 8
+// CHECK-NEXT:   %x4 = alloca ptr, align 8
+// CHECK-NEXT:   %1 = alloca ptr, align 8
+// CHECK-NEXT:   %x7 = alloca ptr, align 8
+// CHECK-NEXT:   %x11 = alloca ptr, align 8
+// CHECK-NEXT:   %x15 = alloca ptr, align 8
+// CHECK-NEXT:   call void @_ZN1CC1Ev(ptr {{.*}} %c)
+// CHECK-NEXT:   store ptr %c, ptr %0, align 8
+// CHECK-NEXT:   %2 = load ptr, ptr %0, align 8
+// CHECK-NEXT:   %a = getelementptr inbounds nuw %struct.C, ptr %2, i32 0, i32 0
+// CHECK-NEXT:   store ptr %a, ptr %x, align 8
+// CHECK-NEXT:   %3 = load ptr, ptr %x, align 8
+// CHECK-NEXT:   %4 = load i32, ptr %3, align 4
+// CHECK-NEXT:   %inc = add nsw i32 %4, 1
+// CHECK-NEXT:   store i32 %inc, ptr %3, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   %5 = load ptr, ptr %0, align 8
+// CHECK-NEXT:   %b = getelementptr inbounds nuw %struct.C, ptr %5, i32 0, i32 1
+// CHECK-NEXT:   store ptr %b, ptr %x1, align 8
+// CHECK-NEXT:   %6 = load ptr, ptr %x1, align 8
+// CHECK-NEXT:   %7 = load i32, ptr %6, align 4
+// CHECK-NEXT:   %inc2 = add nsw i32 %7, 1
+// CHECK-NEXT:   store i32 %inc2, ptr %6, align 4
+// CHECK-NEXT:   br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT:   %8 = load ptr, ptr %0, align 8
+// CHECK-NEXT:   %c5 = getelementptr inbounds nuw %struct.C, ptr %8, i32 0, i32 2
+// CHECK-NEXT:   store ptr %c5, ptr %x4, align 8
+// CHECK-NEXT:   %9 = load ptr, ptr %x4, align 8
+// CHECK-NEXT:   %10 = load i32, ptr %9, align 4
+// CHECK-NEXT:   %inc6 = add nsw i32 %10, 1
+// CHECK-NEXT:   store i32 %inc6, ptr %9, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store ptr %c, ptr %1, align 8
+// CHECK-NEXT:   %11 = load ptr, ptr %1, align 8
+// CHECK-NEXT:   %a8 = getelementptr inbounds nuw %struct.C, ptr %11, i32 0, i32 0
+// CHECK-NEXT:   store ptr %a8, ptr %x7, align 8
+// CHECK-NEXT:   %12 = load ptr, ptr %x7, align 8
+// CHECK-NEXT:   %13 = load i32, ptr %12, align 4
+// CHECK-NEXT:   %inc9 = add nsw i32 %13, 1
+// CHECK-NEXT:   store i32 %inc9, ptr %12, align 4
+// CHECK-NEXT:   br label %expand.next10
+// CHECK: expand.next10:
+// CHECK-NEXT:   %14 = load ptr, ptr %1, align 8
+// CHECK-NEXT:   %b12 = getelementptr inbounds nuw %struct.C, ptr %14, i32 0, i32 1
+// CHECK-NEXT:   store ptr %b12, ptr %x11, align 8
+// CHECK-NEXT:   %15 = load ptr, ptr %x11, align 8
+// CHECK-NEXT:   %16 = load i32, ptr %15, align 4
+// CHECK-NEXT:   %inc13 = add nsw i32 %16, 1
+// CHECK-NEXT:   store i32 %inc13, ptr %15, align 4
+// CHECK-NEXT:   br label %expand.next14
+// CHECK: expand.next14:
+// CHECK-NEXT:   %17 = load ptr, ptr %1, align 8
+// CHECK-NEXT:   %c16 = getelementptr inbounds nuw %struct.C, ptr %17, i32 0, i32 2
+// CHECK-NEXT:   store ptr %c16, ptr %x15, align 8
+// CHECK-NEXT:   %18 = load ptr, ptr %x15, align 8
+// CHECK-NEXT:   %19 = load i32, ptr %18, align 4
+// CHECK-NEXT:   %inc17 = add nsw i32 %19, 1
+// CHECK-NEXT:   store i32 %inc17, ptr %18, align 4
+// CHECK-NEXT:   br label %expand.end18
+// CHECK: expand.end18:
+// CHECK-NEXT:   %a19 = getelementptr inbounds nuw %struct.C, ptr %c, i32 0, i32 0
+// CHECK-NEXT:   %20 = load i32, ptr %a19, align 4
+// CHECK-NEXT:   %b20 = getelementptr inbounds nuw %struct.C, ptr %c, i32 0, i32 1
+// CHECK-NEXT:   %21 = load i32, ptr %b20, align 4
+// CHECK-NEXT:   %add = add nsw i32 %20, %21
+// CHECK-NEXT:   %c21 = getelementptr inbounds nuw %struct.C, ptr %c, i32 0, i32 2
+// CHECK-NEXT:   %22 = load i32, ptr %c21, align 4
+// CHECK-NEXT:   %add22 = add nsw i32 %add, %22
+// CHECK-NEXT:   ret i32 %add22
+
+
+// CHECK-LABEL: define {{.*}} void @_Z1fv()
+// CHECK: entry:
+// CHECK-NEXT:   %call = call {{.*}} i32 @_Z11destructureITnDaXtl1BLi10EEEEiv()
+// CHECK-NEXT:   %call1 = call {{.*}} i32 @_Z11destructureITnDaXtl1CLi1ELi2ELi3EEEEiv()
+// CHECK-NEXT:   %call2 = call {{.*}} i32 @_Z11destructureITnDaXtl1CLi3ELi4ELi5EEEEiv()
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z11destructureITnDaXtl1BLi10EEEEiv()
+// CHECK: entry:
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %0 = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %1 = alloca ptr, align 8
+// CHECK-NEXT:   %x1 = alloca i32, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK-NEXT:   store ptr @_ZTAXtl1BLi10EEE, ptr %0, align 8
+// CHECK-NEXT:   store i32 10, ptr %x, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add = add nsw i32 %3, %2
+// CHECK-NEXT:   store i32 %add, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store ptr @_ZTAXtl1BLi10EEE, ptr %1, align 8
+// CHECK-NEXT:   store i32 10, ptr %x1, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add2 = add nsw i32 %4, 10
+// CHECK-NEXT:   store i32 %add2, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end3
+// CHECK: expand.end3:
+// CHECK-NEXT:   %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   ret i32 %5
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z11destructureITnDaXtl1CLi1ELi2ELi3EEEEiv()
+// CHECK: entry:
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %0 = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x1 = alloca i32, align 4
+// CHECK-NEXT:   %x4 = alloca i32, align 4
+// CHECK-NEXT:   %1 = alloca ptr, align 8
+// CHECK-NEXT:   %x6 = alloca i32, align 4
+// CHECK-NEXT:   %x9 = alloca i32, align 4
+// CHECK-NEXT:   %x12 = alloca i32, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK-NEXT:   store ptr @_ZTAXtl1CLi1ELi2ELi3EEE, ptr %0, align 8
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add = add nsw i32 %3, %2
+// CHECK-NEXT:   store i32 %add, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 2, ptr %x1, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x1, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add2 = add nsw i32 %5, %4
+// CHECK-NEXT:   store i32 %add2, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT:   store i32 3, ptr %x4, align 4
+// CHECK-NEXT:   %6 = load i32, ptr %x4, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add5 = add nsw i32 %7, %6
+// CHECK-NEXT:   store i32 %add5, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store ptr @_ZTAXtl1CLi1ELi2ELi3EEE, ptr %1, align 8
+// CHECK-NEXT:   store i32 1, ptr %x6, align 4
+// CHECK-NEXT:   %8 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add7 = add nsw i32 %8, 1
+// CHECK-NEXT:   store i32 %add7, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT:   store i32 2, ptr %x9, align 4
+// CHECK-NEXT:   %9 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add10 = add nsw i32 %9, 2
+// CHECK-NEXT:   store i32 %add10, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT:   store i32 3, ptr %x12, align 4
+// CHECK-NEXT:   %10 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add13 = add nsw i32 %10, 3
+// CHECK-NEXT:   store i32 %add13, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT:   %11 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   ret i32 %11
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z11destructureITnDaXtl1CLi3ELi4ELi5EEEEiv()
+// CHECK: entry:
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %0 = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x1 = alloca i32, align 4
+// CHECK-NEXT:   %x4 = alloca i32, align 4
+// CHECK-NEXT:   %1 = alloca ptr, align 8
+// CHECK-NEXT:   %x6 = alloca i32, align 4
+// CHECK-NEXT:   %x9 = alloca i32, align 4
+// CHECK-NEXT:   %x12 = alloca i32, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK-NEXT:   store ptr @_ZTAXtl1CLi3ELi4ELi5EEE, ptr %0, align 8
+// CHECK-NEXT:   store i32 3, ptr %x, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add = add nsw i32 %3, %2
+// CHECK-NEXT:   store i32 %add, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 4, ptr %x1, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x1, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add2 = add nsw i32 %5, %4
+// CHECK-NEXT:   store i32 %add2, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT:   store i32 5, ptr %x4, align 4
+// CHECK-NEXT:   %6 = load i32, ptr %x4, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add5 = add nsw i32 %7, %6
+// CHECK-NEXT:   store i32 %add5, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store ptr @_ZTAXtl1CLi3ELi4ELi5EEE, ptr %1, align 8
+// CHECK-NEXT:   store i32 3, ptr %x6, align 4
+// CHECK-NEXT:   %8 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add7 = add nsw i32 %8, 3
+// CHECK-NEXT:   store i32 %add7, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT:   store i32 4, ptr %x9, align 4
+// CHECK-NEXT:   %9 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add10 = add nsw i32 %9, 4
+// CHECK-NEXT:   store i32 %add10, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT:   store i32 5, ptr %x12, align 4
+// CHECK-NEXT:   %10 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add13 = add nsw i32 %10, 5
+// CHECK-NEXT:   store i32 %add13, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT:   %11 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   ret i32 %11
+
+
+// CHECK-LABEL: define {{.*}} void @_Z5emptyv()
+// CHECK: entry:
+// CHECK-NEXT:   %0 = alloca ptr, align 8
+// CHECK-NEXT:   %ref.tmp = alloca %struct.A, align 1
+// CHECK-NEXT:   %1 = alloca ptr, align 8
+// CHECK-NEXT:   %2 = alloca ptr, align 8
+// CHECK-NEXT:   %ref.tmp1 = alloca %struct.A, align 1
+// CHECK-NEXT:   %3 = alloca ptr, align 8
+// CHECK-NEXT:   store ptr %ref.tmp, ptr %0, align 8
+// CHECK-NEXT:   store ptr @_ZZ5emptyvE1a, ptr %1, align 8
+// CHECK-NEXT:   store ptr %ref.tmp1, ptr %2, align 8
+// CHECK-NEXT:   store ptr @_ZZ5emptyvE1a, ptr %3, align 8
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} i32 @_ZN24apply_lifetime_extension18lifetime_extensionEv()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %0 = alloca ptr, align 8
+// CHECK: %ref.tmp = alloca %"struct.apply_lifetime_extension::T", align 8
+// CHECK-NEXT:   %e = alloca i32, align 4
+// CHECK-NEXT:   store i32 5, ptr %x, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK: call void @_ZN24apply_lifetime_extension1gERi(ptr dead_on_unwind writable sret(%"struct.apply_lifetime_extension::T") align 8 %ref.tmp, ptr {{.*}} %x)
+// CHECK-NEXT:   %call = call {{.*}} ptr @_ZN24apply_lifetime_extension1fERKNS_1TE(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   store ptr %call, ptr %0, align 8
+// CHECK-NEXT:   %1 = load ptr, ptr %0, align 8
+// CHECK: %x1 = getelementptr inbounds nuw %"struct.apply_lifetime_extension::T", ptr %1, i32 0, i32 0
+// CHECK-NEXT:   %2 = load ptr, ptr %x1, align 8
+// CHECK-NEXT:   %3 = load i32, ptr %2, align 4
+// CHECK-NEXT:   store i32 %3, ptr %e, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add = add nsw i32 %5, %4
+// CHECK-NEXT:   store i32 %add, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   call void @_ZN24apply_lifetime_extension1TD1Ev(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   %6 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %add2 = add nsw i32 %6, %7
+// CHECK-NEXT:   ret i32 %add2
+
+
+// CHECK-LABEL: define {{.*}} i32 @_ZN24apply_lifetime_extension41lifetime_extension_instantiate_expansionsIiEEiv()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %0 = alloca ptr, align 8
+// CHECK: %ref.tmp = alloca %"struct.apply_lifetime_extension::T", align 8
+// CHECK-NEXT:   %e = alloca i32, align 4
+// CHECK-NEXT:   store i32 5, ptr %x, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK: call void @_ZN24apply_lifetime_extension1gERi(ptr dead_on_unwind writable sret(%"struct.apply_lifetime_extension::T") align 8 %ref.tmp, ptr {{.*}} %x)
+// CHECK-NEXT:   %call = call {{.*}} ptr @_ZN24apply_lifetime_extension1fERKNS_1TE(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   store ptr %call, ptr %0, align 8
+// CHECK-NEXT:   %1 = load ptr, ptr %0, align 8
+// CHECK: %x1 = getelementptr inbounds nuw %"struct.apply_lifetime_extension::T", ptr %1, i32 0, i32 0
+// CHECK-NEXT:   %2 = load ptr, ptr %x1, align 8
+// CHECK-NEXT:   %3 = load i32, ptr %2, align 4
+// CHECK-NEXT:   store i32 %3, ptr %e, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add = add nsw i32 %5, %4
+// CHECK-NEXT:   store i32 %add, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   call void @_ZN24apply_lifetime_extension1TD1Ev(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   %6 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %add2 = add nsw i32 %6, %7
+// CHECK-NEXT:   ret i32 %add2
+
+
+// CHECK-LABEL: define {{.*}} i32 @_ZN24apply_lifetime_extension43lifetime_extension_dependent_expansion_stmtIiEEiv()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %0 = alloca ptr, align 8
+// CHECK: %ref.tmp = alloca %"struct.apply_lifetime_extension::T", align 8
+// CHECK-NEXT:   %e = alloca i32, align 4
+// CHECK-NEXT:   store i32 5, ptr %x, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK: call void @_ZN24apply_lifetime_extension1gERi(ptr dead_on_unwind writable sret(%"struct.apply_lifetime_extension::T") align 8 %ref.tmp, ptr {{.*}} %x)
+// CHECK-NEXT:   %call = call {{.*}} ptr @_ZN24apply_lifetime_extension1fERKNS_1TE(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   store ptr %call, ptr %0, align 8
+// CHECK-NEXT:   %1 = load ptr, ptr %0, align 8
+// CHECK: %x1 = getelementptr inbounds nuw %"struct.apply_lifetime_extension::T", ptr %1, i32 0, i32 0
+// CHECK-NEXT:   %2 = load ptr, ptr %x1, align 8
+// CHECK-NEXT:   %3 = load i32, ptr %2, align 4
+// CHECK-NEXT:   store i32 %3, ptr %e, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add = add nsw i32 %5, %4
+// CHECK-NEXT:   store i32 %add, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   call void @_ZN24apply_lifetime_extension1TD1Ev(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   %6 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %add2 = add nsw i32 %6, %7
+// CHECK-NEXT:   ret i32 %add2
+
+
+// CHECK-LABEL: define {{.*}} i32 @_ZN24apply_lifetime_extension3fooIiE42lifetime_extension_multiple_instantiationsIiEEiv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT:   %this.addr = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %0 = alloca ptr, align 8
+// CHECK: %ref.tmp = alloca %"struct.apply_lifetime_extension::T", align 8
+// CHECK-NEXT:   %e = alloca i32, align 4
+// CHECK-NEXT:   store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT:   %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT:   store i32 5, ptr %x, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK: call void @_ZN24apply_lifetime_extension1gERi(ptr dead_on_unwind writable sret(%"struct.apply_lifetime_extension::T") align 8 %ref.tmp, ptr {{.*}} %x)
+// CHECK-NEXT:   %call = call {{.*}} ptr @_ZN24apply_lifetime_extension1fERKNS_1TE(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   store ptr %call, ptr %0, align 8
+// CHECK-NEXT:   %1 = load ptr, ptr %0, align 8
+// CHECK: %x2 = getelementptr inbounds nuw %"struct.apply_lifetime_extension::T", ptr %1, i32 0, i32 0
+// CHECK-NEXT:   %2 = load ptr, ptr %x2, align 8
+// CHECK-NEXT:   %3 = load i32, ptr %2, align 4
+// CHECK-NEXT:   store i32 %3, ptr %e, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add = add nsw i32 %5, %4
+// CHECK-NEXT:   store i32 %add, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   call void @_ZN24apply_lifetime_extension1TD1Ev(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   %6 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %add3 = add nsw i32 %6, %7
+// CHECK-NEXT:   ret i32 %add3
diff --git a/clang/test/CodeGenCXX/cxx2c-enumerating-expansion-statements.cpp b/clang/test/CodeGenCXX/cxx2c-enumerating-expansion-statements.cpp
new file mode 100644
index 0000000000000..c82b345de206b
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx2c-enumerating-expansion-statements.cpp
@@ -0,0 +1,1518 @@
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+struct S {
+  int x;
+  constexpr S(int x) : x{x} {}
+};
+
+void g(int);
+void g(long);
+void g(const char*);
+void g(S);
+
+template <int n> constexpr int tg() { return n; }
+
+void h(int, int);
+
+void f1() {
+  template for (auto x : {1, 2, 3}) g(x);
+}
+
+void f2() {
+  template for (auto x : {1, "123", S(45)}) g(x);
+}
+
+void f3() {
+  template for (auto x : {}) g(x);
+}
+
+void f4() {
+  template for (auto x : {1, 2})
+    template for (auto y : {3, 4})
+      h(x, y);
+}
+
+void f5() {
+  template for (auto x : {}) static_assert(false, "discarded");
+  template for (constexpr auto x : {}) static_assert(false, "discarded");
+  template for (auto x : {1}) g(x);
+  template for (auto x : {2, 3, 4}) g(x);
+  template for (constexpr auto x : {5}) g(x);
+  template for (constexpr auto x : {6, 7, 8}) g(x);
+  template for (constexpr auto x : {9}) tg<x>();
+  template for (constexpr auto x : {10, 11, 12})
+    static_assert(tg<x>());
+
+  template for (int x : {13, 14, 15}) g(x);
+  template for (S x : {16, 17, 18}) g(x.x);
+  template for (constexpr S x : {19, 20, 21}) tg<x.x>();
+}
+
+template <typename T>
+void t1() {
+  template for (T x : {}) g(x);
+  template for (constexpr T x : {}) g(x);
+  template for (auto x : {}) g(x);
+  template for (constexpr auto x : {}) g(x);
+  template for (T x : {1, 2}) g(x);
+  template for (T x : {T(3), T(4)}) g(x);
+  template for (auto x : {T(5), T(6)}) g(x);
+  template for (constexpr T x : {T(7), T(8)}) static_assert(tg<x>());
+  template for (constexpr auto x : {T(9), T(10)}) static_assert(tg<x>());
+}
+
+template <typename U>
+struct s1 {
+  template <typename T>
+  void tf() {
+    template for (T x : {}) g(x);
+    template for (constexpr T x : {}) g(x);
+    template for (U x : {}) g(x);
+    template for (constexpr U x : {}) g(x);
+    template for (auto x : {}) g(x);
+    template for (constexpr auto x : {}) g(x);
+    template for (T x : {1, 2}) g(x);
+    template for (U x : {3, 4}) g(x);
+    template for (U x : {T(5), T(6)}) g(x);
+    template for (T x : {U(7), U(8)}) g(x);
+    template for (auto x : {T(9), T(10)}) g(x);
+    template for (auto x : {U(11), T(12)}) g(x);
+    template for (constexpr U x : {T(13), T(14)}) static_assert(tg<x>());
+    template for (constexpr T x : {U(15), U(16)}) static_assert(tg<x>());
+    template for (constexpr auto x : {T(17), U(18)}) static_assert(tg<x>());
+  }
+};
+
+template <typename T>
+void t2() {
+  template for (T x : {}) g(x);
+}
+
+void f6() {
+  t1<int>();
+  t1<long>();
+  s1<long>().tf<long>();
+  s1<int>().tf<int>();
+  s1<int>().tf<long>();
+  s1<long>().tf<int>();
+  t2<S>();
+  t2<S[1231]>();
+  t2<S***>();
+}
+
+struct X {
+  int a, b, c;
+};
+
+template <typename ...Ts>
+void t3(Ts... ts) {
+  template for (auto x : {ts...}) g(x);
+  template for (auto x : {1, ts..., 2, ts..., 3}) g(x);
+  template for (auto x : {4, ts..., ts..., 5}) g(x);
+  template for (X x : {{ts...}, {ts...}, {6, 7, 8}}) g(x.a);
+  template for (X x : {X{ts...}}) g(x.a);
+}
+
+template <int ...is>
+void t4() {
+  template for (constexpr auto x : {is...}) {
+    g(x);
+    tg<x>();
+  }
+
+  template for (constexpr auto x : {1, is..., 2, is..., 3}) {
+    g(x);
+    tg<x>();
+  }
+
+  template for (constexpr auto x : {4, is..., is..., 5}) {
+    g(x);
+    tg<x>();
+  }
+
+  template for (constexpr X x : {{is...}, {is...}, {6, 7, 8}}) {
+    g(x.a);
+    tg<x.a>();
+  }
+
+  template for (constexpr X x : {X{is...}}) {
+    g(x.a);
+    tg<x.a>();
+  }
+}
+
+template <int ...is>
+struct s2 {
+  template <int ...js>
+  void tf() {
+    template for (auto x : {is..., js...}) g(x);
+    template for (X x : {{is...}, {js...}}) g(x.a);
+    template for (constexpr auto x : {is..., js...}) tg<x>();
+    template for (constexpr X x : {{is...}, {js...}}) tg<x.a>();
+  }
+};
+
+void f7() {
+  t3(42, 43, 44);
+  t4<42, 43, 44>();
+  s2<1, 2, 3>().tf<4, 5, 6>();
+}
+
+template <int ...is>
+void t5() {
+  ([] {
+    template for (constexpr auto x : {is}) {
+      g(x);
+      tg<x>();
+    }
+  }(), ...);
+}
+
+void f8() {
+  t5<1, 2, 3>();
+}
+
+int references_enumerating() {
+  int x = 1, y = 2, z = 3;
+  template for (auto& v : {x, y, z}) { ++v; }
+  template for (auto&& v : {x, y, z}) { ++v; }
+  return x + y + z;
+}
+
+// CHECK-LABEL: define {{.*}} void @_Z2f1v()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x1 = alloca i32, align 4
+// CHECK-NEXT:   %x3 = alloca i32, align 4
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 2, ptr %x1, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %x1, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT:   br label %expand.next2
+// CHECK: expand.next2:
+// CHECK-NEXT:   store i32 3, ptr %x3, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x3, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %2)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f2v()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x1 = alloca ptr, align 8
+// CHECK-NEXT:   %x3 = alloca %struct.S, align 4
+// CHECK-NEXT:   %agg.tmp = alloca %struct.S, align 4
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store ptr @.str, ptr %x1, align 8
+// CHECK-NEXT:   %1 = load ptr, ptr %x1, align 8
+// CHECK-NEXT:   call void @_Z1gPKc(ptr {{.*}} %1)
+// CHECK-NEXT:   br label %expand.next2
+// CHECK: expand.next2:
+// CHECK-NEXT:   call void @_ZN1SC1Ei(ptr {{.*}} %x3, i32 {{.*}} 45)
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %x3, i64 4, i1 false)
+// CHECK-NEXT:   %coerce.dive = getelementptr inbounds nuw %struct.S, ptr %agg.tmp, i32 0, i32 0
+// CHECK-NEXT:   %2 = load i32, ptr %coerce.dive, align 4
+// CHECK-NEXT:   call void @_Z1g1S(i32 %2)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f3v()
+// CHECK: entry:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f4v()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %y = alloca i32, align 4
+// CHECK-NEXT:   %y1 = alloca i32, align 4
+// CHECK-NEXT:   %x3 = alloca i32, align 4
+// CHECK-NEXT:   %y4 = alloca i32, align 4
+// CHECK-NEXT:   %y6 = alloca i32, align 4
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   store i32 3, ptr %y, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %y, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} %0, i32 {{.*}} %1)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 4, ptr %y1, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %y1, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} %2, i32 {{.*}} %3)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   br label %expand.next2
+// CHECK: expand.next2:
+// CHECK-NEXT:   store i32 2, ptr %x3, align 4
+// CHECK-NEXT:   store i32 3, ptr %y4, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x3, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %y4, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} %4, i32 {{.*}} %5)
+// CHECK-NEXT:   br label %expand.next5
+// CHECK: expand.next5:
+// CHECK-NEXT:   store i32 4, ptr %y6, align 4
+// CHECK-NEXT:   %6 = load i32, ptr %x3, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %y6, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} %6, i32 {{.*}} %7)
+// CHECK-NEXT:   br label %expand.end7
+// CHECK: expand.end7:
+// CHECK-NEXT:   br label %expand.end8
+// CHECK: expand.end8:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f5v()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x1 = alloca i32, align 4
+// CHECK-NEXT:   %x2 = alloca i32, align 4
+// CHECK-NEXT:   %x4 = alloca i32, align 4
+// CHECK-NEXT:   %x6 = alloca i32, align 4
+// CHECK-NEXT:   %x8 = alloca i32, align 4
+// CHECK-NEXT:   %x10 = alloca i32, align 4
+// CHECK-NEXT:   %x12 = alloca i32, align 4
+// CHECK-NEXT:   %x14 = alloca i32, align 4
+// CHECK-NEXT:   %x16 = alloca i32, align 4
+// CHECK-NEXT:   %x18 = alloca i32, align 4
+// CHECK-NEXT:   %x20 = alloca i32, align 4
+// CHECK-NEXT:   %x22 = alloca i32, align 4
+// CHECK-NEXT:   %x24 = alloca i32, align 4
+// CHECK-NEXT:   %x26 = alloca i32, align 4
+// CHECK-NEXT:   %x28 = alloca %struct.S, align 4
+// CHECK-NEXT:   %x31 = alloca %struct.S, align 4
+// CHECK-NEXT:   %x34 = alloca %struct.S, align 4
+// CHECK-NEXT:   %x37 = alloca %struct.S, align 4
+// CHECK-NEXT:   %x40 = alloca %struct.S, align 4
+// CHECK-NEXT:   %x43 = alloca %struct.S, align 4
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store i32 2, ptr %x1, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %x1, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 3, ptr %x2, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x2, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %2)
+// CHECK-NEXT:   br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT:   store i32 4, ptr %x4, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %x4, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %3)
+// CHECK-NEXT:   br label %expand.end5
+// CHECK: expand.end5:
+// CHECK-NEXT:   store i32 5, ptr %x6, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 5)
+// CHECK-NEXT:   br label %expand.end7
+// CHECK: expand.end7:
+// CHECK-NEXT:   store i32 6, ptr %x8, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 6)
+// CHECK-NEXT:   br label %expand.next9
+// CHECK: expand.next9:
+// CHECK-NEXT:   store i32 7, ptr %x10, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 7)
+// CHECK-NEXT:   br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT:   store i32 8, ptr %x12, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 8)
+// CHECK-NEXT:   br label %expand.end13
+// CHECK: expand.end13:
+// CHECK-NEXT:   store i32 9, ptr %x14, align 4
+// CHECK-NEXT:   %call = call {{.*}} i32 @_Z2tgILi9EEiv()
+// CHECK-NEXT:   br label %expand.end15
+// CHECK: expand.end15:
+// CHECK-NEXT:   store i32 10, ptr %x16, align 4
+// CHECK-NEXT:   br label %expand.next17
+// CHECK: expand.next17:
+// CHECK-NEXT:   store i32 11, ptr %x18, align 4
+// CHECK-NEXT:   br label %expand.next19
+// CHECK: expand.next19:
+// CHECK-NEXT:   store i32 12, ptr %x20, align 4
+// CHECK-NEXT:   br label %expand.end21
+// CHECK: expand.end21:
+// CHECK-NEXT:   store i32 13, ptr %x22, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x22, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %4)
+// CHECK-NEXT:   br label %expand.next23
+// CHECK: expand.next23:
+// CHECK-NEXT:   store i32 14, ptr %x24, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %x24, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %5)
+// CHECK-NEXT:   br label %expand.next25
+// CHECK: expand.next25:
+// CHECK-NEXT:   store i32 15, ptr %x26, align 4
+// CHECK-NEXT:   %6 = load i32, ptr %x26, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %6)
+// CHECK-NEXT:   br label %expand.end27
+// CHECK: expand.end27:
+// CHECK-NEXT:   call void @_ZN1SC1Ei(ptr {{.*}} %x28, i32 {{.*}} 16)
+// CHECK-NEXT:   %x29 = getelementptr inbounds nuw %struct.S, ptr %x28, i32 0, i32 0
+// CHECK-NEXT:   %7 = load i32, ptr %x29, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %7)
+// CHECK-NEXT:   br label %expand.next30
+// CHECK: expand.next30:
+// CHECK-NEXT:   call void @_ZN1SC1Ei(ptr {{.*}} %x31, i32 {{.*}} 17)
+// CHECK-NEXT:   %x32 = getelementptr inbounds nuw %struct.S, ptr %x31, i32 0, i32 0
+// CHECK-NEXT:   %8 = load i32, ptr %x32, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %8)
+// CHECK-NEXT:   br label %expand.next33
+// CHECK: expand.next33:
+// CHECK-NEXT:   call void @_ZN1SC1Ei(ptr {{.*}} %x34, i32 {{.*}} 18)
+// CHECK-NEXT:   %x35 = getelementptr inbounds nuw %struct.S, ptr %x34, i32 0, i32 0
+// CHECK-NEXT:   %9 = load i32, ptr %x35, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %9)
+// CHECK-NEXT:   br label %expand.end36
+// CHECK: expand.end36:
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x37, ptr align 4 @__const._Z2f5v.x, i64 4, i1 false)
+// CHECK-NEXT:   %call38 = call {{.*}} i32 @_Z2tgILi19EEiv()
+// CHECK-NEXT:   br label %expand.next39
+// CHECK: expand.next39:
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x40, ptr align 4 @__const._Z2f5v.x.1, i64 4, i1 false)
+// CHECK-NEXT:   %call41 = call {{.*}} i32 @_Z2tgILi20EEiv()
+// CHECK-NEXT:   br label %expand.next42
+// CHECK: expand.next42:
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x43, ptr align 4 @__const._Z2f5v.x.2, i64 4, i1 false)
+// CHECK-NEXT:   %call44 = call {{.*}} i32 @_Z2tgILi21EEiv()
+// CHECK-NEXT:   br label %expand.end45
+// CHECK: expand.end45:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f6v()
+// CHECK: entry:
+// CHECK-NEXT:   %ref.tmp = alloca %struct.s1, align 1
+// CHECK-NEXT:   %ref.tmp1 = alloca %struct.s1.0, align 1
+// CHECK-NEXT:   %ref.tmp2 = alloca %struct.s1.0, align 1
+// CHECK-NEXT:   %ref.tmp3 = alloca %struct.s1, align 1
+// CHECK-NEXT:   call void @_Z2t1IiEvv()
+// CHECK-NEXT:   call void @_Z2t1IlEvv()
+// CHECK-NEXT:   call void @_ZN2s1IlE2tfIlEEvv(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   call void @_ZN2s1IiE2tfIiEEvv(ptr {{.*}} %ref.tmp1)
+// CHECK-NEXT:   call void @_ZN2s1IiE2tfIlEEvv(ptr {{.*}} %ref.tmp2)
+// CHECK-NEXT:   call void @_ZN2s1IlE2tfIiEEvv(ptr {{.*}} %ref.tmp3)
+// CHECK-NEXT:   call void @_Z2t2I1SEvv()
+// CHECK-NEXT:   call void @_Z2t2IA1231_1SEvv()
+// CHECK-NEXT:   call void @_Z2t2IPPP1SEvv()
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2t1IiEvv()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x1 = alloca i32, align 4
+// CHECK-NEXT:   %x2 = alloca i32, align 4
+// CHECK-NEXT:   %x4 = alloca i32, align 4
+// CHECK-NEXT:   %x6 = alloca i32, align 4
+// CHECK-NEXT:   %x8 = alloca i32, align 4
+// CHECK-NEXT:   %x10 = alloca i32, align 4
+// CHECK-NEXT:   %x12 = alloca i32, align 4
+// CHECK-NEXT:   %x14 = alloca i32, align 4
+// CHECK-NEXT:   %x16 = alloca i32, align 4
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 2, ptr %x1, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %x1, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store i32 3, ptr %x2, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x2, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %2)
+// CHECK-NEXT:   br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT:   store i32 4, ptr %x4, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %x4, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %3)
+// CHECK-NEXT:   br label %expand.end5
+// CHECK: expand.end5:
+// CHECK-NEXT:   store i32 5, ptr %x6, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x6, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %4)
+// CHECK-NEXT:   br label %expand.next7
+// CHECK: expand.next7:
+// CHECK-NEXT:   store i32 6, ptr %x8, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %x8, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %5)
+// CHECK-NEXT:   br label %expand.end9
+// CHECK: expand.end9:
+// CHECK-NEXT:   store i32 7, ptr %x10, align 4
+// CHECK-NEXT:   br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT:   store i32 8, ptr %x12, align 4
+// CHECK-NEXT:   br label %expand.end13
+// CHECK: expand.end13:
+// CHECK-NEXT:   store i32 9, ptr %x14, align 4
+// CHECK-NEXT:   br label %expand.next15
+// CHECK: expand.next15:
+// CHECK-NEXT:   store i32 10, ptr %x16, align 4
+// CHECK-NEXT:   br label %expand.end17
+// CHECK: expand.end17:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2t1IlEvv()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i64, align 8
+// CHECK-NEXT:   %x1 = alloca i64, align 8
+// CHECK-NEXT:   %x2 = alloca i64, align 8
+// CHECK-NEXT:   %x4 = alloca i64, align 8
+// CHECK-NEXT:   %x6 = alloca i64, align 8
+// CHECK-NEXT:   %x8 = alloca i64, align 8
+// CHECK-NEXT:   %x10 = alloca i64, align 8
+// CHECK-NEXT:   %x12 = alloca i64, align 8
+// CHECK-NEXT:   %x14 = alloca i64, align 8
+// CHECK-NEXT:   %x16 = alloca i64, align 8
+// CHECK-NEXT:   store i64 1, ptr %x, align 8
+// CHECK-NEXT:   %0 = load i64, ptr %x, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %0)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i64 2, ptr %x1, align 8
+// CHECK-NEXT:   %1 = load i64, ptr %x1, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %1)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store i64 3, ptr %x2, align 8
+// CHECK-NEXT:   %2 = load i64, ptr %x2, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %2)
+// CHECK-NEXT:   br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT:   store i64 4, ptr %x4, align 8
+// CHECK-NEXT:   %3 = load i64, ptr %x4, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %3)
+// CHECK-NEXT:   br label %expand.end5
+// CHECK: expand.end5:
+// CHECK-NEXT:   store i64 5, ptr %x6, align 8
+// CHECK-NEXT:   %4 = load i64, ptr %x6, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %4)
+// CHECK-NEXT:   br label %expand.next7
+// CHECK: expand.next7:
+// CHECK-NEXT:   store i64 6, ptr %x8, align 8
+// CHECK-NEXT:   %5 = load i64, ptr %x8, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %5)
+// CHECK-NEXT:   br label %expand.end9
+// CHECK: expand.end9:
+// CHECK-NEXT:   store i64 7, ptr %x10, align 8
+// CHECK-NEXT:   br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT:   store i64 8, ptr %x12, align 8
+// CHECK-NEXT:   br label %expand.end13
+// CHECK: expand.end13:
+// CHECK-NEXT:   store i64 9, ptr %x14, align 8
+// CHECK-NEXT:   br label %expand.next15
+// CHECK: expand.next15:
+// CHECK-NEXT:   store i64 10, ptr %x16, align 8
+// CHECK-NEXT:   br label %expand.end17
+// CHECK: expand.end17:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZN2s1IlE2tfIlEEvv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT:   %this.addr = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i64, align 8
+// CHECK-NEXT:   %x2 = alloca i64, align 8
+// CHECK-NEXT:   %x3 = alloca i64, align 8
+// CHECK-NEXT:   %x5 = alloca i64, align 8
+// CHECK-NEXT:   %x7 = alloca i64, align 8
+// CHECK-NEXT:   %x9 = alloca i64, align 8
+// CHECK-NEXT:   %x11 = alloca i64, align 8
+// CHECK-NEXT:   %x13 = alloca i64, align 8
+// CHECK-NEXT:   %x15 = alloca i64, align 8
+// CHECK-NEXT:   %x17 = alloca i64, align 8
+// CHECK-NEXT:   %x19 = alloca i64, align 8
+// CHECK-NEXT:   %x21 = alloca i64, align 8
+// CHECK-NEXT:   %x23 = alloca i64, align 8
+// CHECK-NEXT:   %x25 = alloca i64, align 8
+// CHECK-NEXT:   %x27 = alloca i64, align 8
+// CHECK-NEXT:   %x29 = alloca i64, align 8
+// CHECK-NEXT:   %x31 = alloca i64, align 8
+// CHECK-NEXT:   %x33 = alloca i64, align 8
+// CHECK-NEXT:   store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT:   %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT:   store i64 1, ptr %x, align 8
+// CHECK-NEXT:   %0 = load i64, ptr %x, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %0)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i64 2, ptr %x2, align 8
+// CHECK-NEXT:   %1 = load i64, ptr %x2, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %1)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store i64 3, ptr %x3, align 8
+// CHECK-NEXT:   %2 = load i64, ptr %x3, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %2)
+// CHECK-NEXT:   br label %expand.next4
+// CHECK: expand.next4:
+// CHECK-NEXT:   store i64 4, ptr %x5, align 8
+// CHECK-NEXT:   %3 = load i64, ptr %x5, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %3)
+// CHECK-NEXT:   br label %expand.end6
+// CHECK: expand.end6:
+// CHECK-NEXT:   store i64 5, ptr %x7, align 8
+// CHECK-NEXT:   %4 = load i64, ptr %x7, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %4)
+// CHECK-NEXT:   br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT:   store i64 6, ptr %x9, align 8
+// CHECK-NEXT:   %5 = load i64, ptr %x9, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %5)
+// CHECK-NEXT:   br label %expand.end10
+// CHECK: expand.end10:
+// CHECK-NEXT:   store i64 7, ptr %x11, align 8
+// CHECK-NEXT:   %6 = load i64, ptr %x11, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %6)
+// CHECK-NEXT:   br label %expand.next12
+// CHECK: expand.next12:
+// CHECK-NEXT:   store i64 8, ptr %x13, align 8
+// CHECK-NEXT:   %7 = load i64, ptr %x13, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %7)
+// CHECK-NEXT:   br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT:   store i64 9, ptr %x15, align 8
+// CHECK-NEXT:   %8 = load i64, ptr %x15, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %8)
+// CHECK-NEXT:   br label %expand.next16
+// CHECK: expand.next16:
+// CHECK-NEXT:   store i64 10, ptr %x17, align 8
+// CHECK-NEXT:   %9 = load i64, ptr %x17, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %9)
+// CHECK-NEXT:   br label %expand.end18
+// CHECK: expand.end18:
+// CHECK-NEXT:   store i64 11, ptr %x19, align 8
+// CHECK-NEXT:   %10 = load i64, ptr %x19, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %10)
+// CHECK-NEXT:   br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT:   store i64 12, ptr %x21, align 8
+// CHECK-NEXT:   %11 = load i64, ptr %x21, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %11)
+// CHECK-NEXT:   br label %expand.end22
+// CHECK: expand.end22:
+// CHECK-NEXT:   store i64 13, ptr %x23, align 8
+// CHECK-NEXT:   br label %expand.next24
+// CHECK: expand.next24:
+// CHECK-NEXT:   store i64 14, ptr %x25, align 8
+// CHECK-NEXT:   br label %expand.end26
+// CHECK: expand.end26:
+// CHECK-NEXT:   store i64 15, ptr %x27, align 8
+// CHECK-NEXT:   br label %expand.next28
+// CHECK: expand.next28:
+// CHECK-NEXT:   store i64 16, ptr %x29, align 8
+// CHECK-NEXT:   br label %expand.end30
+// CHECK: expand.end30:
+// CHECK-NEXT:   store i64 17, ptr %x31, align 8
+// CHECK-NEXT:   br label %expand.next32
+// CHECK: expand.next32:
+// CHECK-NEXT:   store i64 18, ptr %x33, align 8
+// CHECK-NEXT:   br label %expand.end34
+// CHECK: expand.end34:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZN2s1IiE2tfIiEEvv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT:   %this.addr = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x2 = alloca i32, align 4
+// CHECK-NEXT:   %x3 = alloca i32, align 4
+// CHECK-NEXT:   %x5 = alloca i32, align 4
+// CHECK-NEXT:   %x7 = alloca i32, align 4
+// CHECK-NEXT:   %x9 = alloca i32, align 4
+// CHECK-NEXT:   %x11 = alloca i32, align 4
+// CHECK-NEXT:   %x13 = alloca i32, align 4
+// CHECK-NEXT:   %x15 = alloca i32, align 4
+// CHECK-NEXT:   %x17 = alloca i32, align 4
+// CHECK-NEXT:   %x19 = alloca i32, align 4
+// CHECK-NEXT:   %x21 = alloca i32, align 4
+// CHECK-NEXT:   %x23 = alloca i32, align 4
+// CHECK-NEXT:   %x25 = alloca i32, align 4
+// CHECK-NEXT:   %x27 = alloca i32, align 4
+// CHECK-NEXT:   %x29 = alloca i32, align 4
+// CHECK-NEXT:   %x31 = alloca i32, align 4
+// CHECK-NEXT:   %x33 = alloca i32, align 4
+// CHECK-NEXT:   store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT:   %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 2, ptr %x2, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %x2, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store i32 3, ptr %x3, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x3, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %2)
+// CHECK-NEXT:   br label %expand.next4
+// CHECK: expand.next4:
+// CHECK-NEXT:   store i32 4, ptr %x5, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %x5, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %3)
+// CHECK-NEXT:   br label %expand.end6
+// CHECK: expand.end6:
+// CHECK-NEXT:   store i32 5, ptr %x7, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x7, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %4)
+// CHECK-NEXT:   br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT:   store i32 6, ptr %x9, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %x9, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %5)
+// CHECK-NEXT:   br label %expand.end10
+// CHECK: expand.end10:
+// CHECK-NEXT:   store i32 7, ptr %x11, align 4
+// CHECK-NEXT:   %6 = load i32, ptr %x11, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %6)
+// CHECK-NEXT:   br label %expand.next12
+// CHECK: expand.next12:
+// CHECK-NEXT:   store i32 8, ptr %x13, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %x13, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %7)
+// CHECK-NEXT:   br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT:   store i32 9, ptr %x15, align 4
+// CHECK-NEXT:   %8 = load i32, ptr %x15, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %8)
+// CHECK-NEXT:   br label %expand.next16
+// CHECK: expand.next16:
+// CHECK-NEXT:   store i32 10, ptr %x17, align 4
+// CHECK-NEXT:   %9 = load i32, ptr %x17, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %9)
+// CHECK-NEXT:   br label %expand.end18
+// CHECK: expand.end18:
+// CHECK-NEXT:   store i32 11, ptr %x19, align 4
+// CHECK-NEXT:   %10 = load i32, ptr %x19, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %10)
+// CHECK-NEXT:   br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT:   store i32 12, ptr %x21, align 4
+// CHECK-NEXT:   %11 = load i32, ptr %x21, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %11)
+// CHECK-NEXT:   br label %expand.end22
+// CHECK: expand.end22:
+// CHECK-NEXT:   store i32 13, ptr %x23, align 4
+// CHECK-NEXT:   br label %expand.next24
+// CHECK: expand.next24:
+// CHECK-NEXT:   store i32 14, ptr %x25, align 4
+// CHECK-NEXT:   br label %expand.end26
+// CHECK: expand.end26:
+// CHECK-NEXT:   store i32 15, ptr %x27, align 4
+// CHECK-NEXT:   br label %expand.next28
+// CHECK: expand.next28:
+// CHECK-NEXT:   store i32 16, ptr %x29, align 4
+// CHECK-NEXT:   br label %expand.end30
+// CHECK: expand.end30:
+// CHECK-NEXT:   store i32 17, ptr %x31, align 4
+// CHECK-NEXT:   br label %expand.next32
+// CHECK: expand.next32:
+// CHECK-NEXT:   store i32 18, ptr %x33, align 4
+// CHECK-NEXT:   br label %expand.end34
+// CHECK: expand.end34:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZN2s1IiE2tfIlEEvv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT:   %this.addr = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i64, align 8
+// CHECK-NEXT:   %x2 = alloca i64, align 8
+// CHECK-NEXT:   %x3 = alloca i32, align 4
+// CHECK-NEXT:   %x5 = alloca i32, align 4
+// CHECK-NEXT:   %x7 = alloca i32, align 4
+// CHECK-NEXT:   %x9 = alloca i32, align 4
+// CHECK-NEXT:   %x11 = alloca i64, align 8
+// CHECK-NEXT:   %x13 = alloca i64, align 8
+// CHECK-NEXT:   %x15 = alloca i64, align 8
+// CHECK-NEXT:   %x17 = alloca i64, align 8
+// CHECK-NEXT:   %x19 = alloca i32, align 4
+// CHECK-NEXT:   %x21 = alloca i64, align 8
+// CHECK-NEXT:   %x23 = alloca i32, align 4
+// CHECK-NEXT:   %x25 = alloca i32, align 4
+// CHECK-NEXT:   %x27 = alloca i64, align 8
+// CHECK-NEXT:   %x29 = alloca i64, align 8
+// CHECK-NEXT:   %x31 = alloca i64, align 8
+// CHECK-NEXT:   %x33 = alloca i32, align 4
+// CHECK-NEXT:   store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT:   %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT:   store i64 1, ptr %x, align 8
+// CHECK-NEXT:   %0 = load i64, ptr %x, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %0)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i64 2, ptr %x2, align 8
+// CHECK-NEXT:   %1 = load i64, ptr %x2, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %1)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store i32 3, ptr %x3, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x3, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %2)
+// CHECK-NEXT:   br label %expand.next4
+// CHECK: expand.next4:
+// CHECK-NEXT:   store i32 4, ptr %x5, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %x5, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %3)
+// CHECK-NEXT:   br label %expand.end6
+// CHECK: expand.end6:
+// CHECK-NEXT:   store i32 5, ptr %x7, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x7, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %4)
+// CHECK-NEXT:   br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT:   store i32 6, ptr %x9, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %x9, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %5)
+// CHECK-NEXT:   br label %expand.end10
+// CHECK: expand.end10:
+// CHECK-NEXT:   store i64 7, ptr %x11, align 8
+// CHECK-NEXT:   %6 = load i64, ptr %x11, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %6)
+// CHECK-NEXT:   br label %expand.next12
+// CHECK: expand.next12:
+// CHECK-NEXT:   store i64 8, ptr %x13, align 8
+// CHECK-NEXT:   %7 = load i64, ptr %x13, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %7)
+// CHECK-NEXT:   br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT:   store i64 9, ptr %x15, align 8
+// CHECK-NEXT:   %8 = load i64, ptr %x15, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %8)
+// CHECK-NEXT:   br label %expand.next16
+// CHECK: expand.next16:
+// CHECK-NEXT:   store i64 10, ptr %x17, align 8
+// CHECK-NEXT:   %9 = load i64, ptr %x17, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %9)
+// CHECK-NEXT:   br label %expand.end18
+// CHECK: expand.end18:
+// CHECK-NEXT:   store i32 11, ptr %x19, align 4
+// CHECK-NEXT:   %10 = load i32, ptr %x19, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %10)
+// CHECK-NEXT:   br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT:   store i64 12, ptr %x21, align 8
+// CHECK-NEXT:   %11 = load i64, ptr %x21, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %11)
+// CHECK-NEXT:   br label %expand.end22
+// CHECK: expand.end22:
+// CHECK-NEXT:   store i32 13, ptr %x23, align 4
+// CHECK-NEXT:   br label %expand.next24
+// CHECK: expand.next24:
+// CHECK-NEXT:   store i32 14, ptr %x25, align 4
+// CHECK-NEXT:   br label %expand.end26
+// CHECK: expand.end26:
+// CHECK-NEXT:   store i64 15, ptr %x27, align 8
+// CHECK-NEXT:   br label %expand.next28
+// CHECK: expand.next28:
+// CHECK-NEXT:   store i64 16, ptr %x29, align 8
+// CHECK-NEXT:   br label %expand.end30
+// CHECK: expand.end30:
+// CHECK-NEXT:   store i64 17, ptr %x31, align 8
+// CHECK-NEXT:   br label %expand.next32
+// CHECK: expand.next32:
+// CHECK-NEXT:   store i32 18, ptr %x33, align 4
+// CHECK-NEXT:   br label %expand.end34
+// CHECK: expand.end34:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZN2s1IlE2tfIiEEvv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT:   %this.addr = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x2 = alloca i32, align 4
+// CHECK-NEXT:   %x3 = alloca i64, align 8
+// CHECK-NEXT:   %x5 = alloca i64, align 8
+// CHECK-NEXT:   %x7 = alloca i64, align 8
+// CHECK-NEXT:   %x9 = alloca i64, align 8
+// CHECK-NEXT:   %x11 = alloca i32, align 4
+// CHECK-NEXT:   %x13 = alloca i32, align 4
+// CHECK-NEXT:   %x15 = alloca i32, align 4
+// CHECK-NEXT:   %x17 = alloca i32, align 4
+// CHECK-NEXT:   %x19 = alloca i64, align 8
+// CHECK-NEXT:   %x21 = alloca i32, align 4
+// CHECK-NEXT:   %x23 = alloca i64, align 8
+// CHECK-NEXT:   %x25 = alloca i64, align 8
+// CHECK-NEXT:   %x27 = alloca i32, align 4
+// CHECK-NEXT:   %x29 = alloca i32, align 4
+// CHECK-NEXT:   %x31 = alloca i32, align 4
+// CHECK-NEXT:   %x33 = alloca i64, align 8
+// CHECK-NEXT:   store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT:   %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 2, ptr %x2, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %x2, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store i64 3, ptr %x3, align 8
+// CHECK-NEXT:   %2 = load i64, ptr %x3, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %2)
+// CHECK-NEXT:   br label %expand.next4
+// CHECK: expand.next4:
+// CHECK-NEXT:   store i64 4, ptr %x5, align 8
+// CHECK-NEXT:   %3 = load i64, ptr %x5, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %3)
+// CHECK-NEXT:   br label %expand.end6
+// CHECK: expand.end6:
+// CHECK-NEXT:   store i64 5, ptr %x7, align 8
+// CHECK-NEXT:   %4 = load i64, ptr %x7, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %4)
+// CHECK-NEXT:   br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT:   store i64 6, ptr %x9, align 8
+// CHECK-NEXT:   %5 = load i64, ptr %x9, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %5)
+// CHECK-NEXT:   br label %expand.end10
+// CHECK: expand.end10:
+// CHECK-NEXT:   store i32 7, ptr %x11, align 4
+// CHECK-NEXT:   %6 = load i32, ptr %x11, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %6)
+// CHECK-NEXT:   br label %expand.next12
+// CHECK: expand.next12:
+// CHECK-NEXT:   store i32 8, ptr %x13, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %x13, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %7)
+// CHECK-NEXT:   br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT:   store i32 9, ptr %x15, align 4
+// CHECK-NEXT:   %8 = load i32, ptr %x15, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %8)
+// CHECK-NEXT:   br label %expand.next16
+// CHECK: expand.next16:
+// CHECK-NEXT:   store i32 10, ptr %x17, align 4
+// CHECK-NEXT:   %9 = load i32, ptr %x17, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %9)
+// CHECK-NEXT:   br label %expand.end18
+// CHECK: expand.end18:
+// CHECK-NEXT:   store i64 11, ptr %x19, align 8
+// CHECK-NEXT:   %10 = load i64, ptr %x19, align 8
+// CHECK-NEXT:   call void @_Z1gl(i64 {{.*}} %10)
+// CHECK-NEXT:   br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT:   store i32 12, ptr %x21, align 4
+// CHECK-NEXT:   %11 = load i32, ptr %x21, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %11)
+// CHECK-NEXT:   br label %expand.end22
+// CHECK: expand.end22:
+// CHECK-NEXT:   store i64 13, ptr %x23, align 8
+// CHECK-NEXT:   br label %expand.next24
+// CHECK: expand.next24:
+// CHECK-NEXT:   store i64 14, ptr %x25, align 8
+// CHECK-NEXT:   br label %expand.end26
+// CHECK: expand.end26:
+// CHECK-NEXT:   store i32 15, ptr %x27, align 4
+// CHECK-NEXT:   br label %expand.next28
+// CHECK: expand.next28:
+// CHECK-NEXT:   store i32 16, ptr %x29, align 4
+// CHECK-NEXT:   br label %expand.end30
+// CHECK: expand.end30:
+// CHECK-NEXT:   store i32 17, ptr %x31, align 4
+// CHECK-NEXT:   br label %expand.next32
+// CHECK: expand.next32:
+// CHECK-NEXT:   store i64 18, ptr %x33, align 8
+// CHECK-NEXT:   br label %expand.end34
+// CHECK: expand.end34:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f7v()
+// CHECK: entry:
+// CHECK-NEXT:   %ref.tmp = alloca %struct.s2, align 1
+// CHECK-NEXT:   call void @_Z2t3IJiiiEEvDpT_(i32 {{.*}} 42, i32 {{.*}} 43, i32 {{.*}} 44)
+// CHECK-NEXT:   call void @_Z2t4IJLi42ELi43ELi44EEEvv()
+// CHECK-NEXT:   call void @_ZN2s2IJLi1ELi2ELi3EEE2tfIJLi4ELi5ELi6EEEEvv(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   ret void
+
+// CHECK-LABEL: define {{.*}} void @_Z2t3IJiiiEEvDpT_(i32 {{.*}} %ts, i32 {{.*}} %ts1, i32 {{.*}} %ts3)
+// CHECK: entry:
+// CHECK-NEXT:   %ts.addr = alloca i32, align 4
+// CHECK-NEXT:   %ts.addr2 = alloca i32, align 4
+// CHECK-NEXT:   %ts.addr4 = alloca i32, align 4
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x5 = alloca i32, align 4
+// CHECK-NEXT:   %x7 = alloca i32, align 4
+// CHECK-NEXT:   %x8 = alloca i32, align 4
+// CHECK-NEXT:   %x10 = alloca i32, align 4
+// CHECK-NEXT:   %x12 = alloca i32, align 4
+// CHECK-NEXT:   %x14 = alloca i32, align 4
+// CHECK-NEXT:   %x16 = alloca i32, align 4
+// CHECK-NEXT:   %x18 = alloca i32, align 4
+// CHECK-NEXT:   %x20 = alloca i32, align 4
+// CHECK-NEXT:   %x22 = alloca i32, align 4
+// CHECK-NEXT:   %x24 = alloca i32, align 4
+// CHECK-NEXT:   %x26 = alloca i32, align 4
+// CHECK-NEXT:   %x28 = alloca i32, align 4
+// CHECK-NEXT:   %x30 = alloca i32, align 4
+// CHECK-NEXT:   %x32 = alloca i32, align 4
+// CHECK-NEXT:   %x34 = alloca i32, align 4
+// CHECK-NEXT:   %x36 = alloca i32, align 4
+// CHECK-NEXT:   %x38 = alloca i32, align 4
+// CHECK-NEXT:   %x40 = alloca i32, align 4
+// CHECK-NEXT:   %x42 = alloca %struct.X, align 4
+// CHECK-NEXT:   %x45 = alloca %struct.X, align 4
+// CHECK-NEXT:   %x51 = alloca %struct.X, align 4
+// CHECK-NEXT:   %x54 = alloca %struct.X, align 4
+// CHECK-NEXT:   store i32 %ts, ptr %ts.addr, align 4
+// CHECK-NEXT:   store i32 %ts1, ptr %ts.addr2, align 4
+// CHECK-NEXT:   store i32 %ts3, ptr %ts.addr4, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT:   store i32 %0, ptr %x, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   %2 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT:   store i32 %2, ptr %x5, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %x5, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %3)
+// CHECK-NEXT:   br label %expand.next6
+// CHECK: expand.next6:
+// CHECK-NEXT:   %4 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT:   store i32 %4, ptr %x7, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %x7, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %5)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store i32 1, ptr %x8, align 4
+// CHECK-NEXT:   %6 = load i32, ptr %x8, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %6)
+// CHECK-NEXT:   br label %expand.next9
+// CHECK: expand.next9:
+// CHECK-NEXT:   %7 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT:   store i32 %7, ptr %x10, align 4
+// CHECK-NEXT:   %8 = load i32, ptr %x10, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %8)
+// CHECK-NEXT:   br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT:   %9 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT:   store i32 %9, ptr %x12, align 4
+// CHECK-NEXT:   %10 = load i32, ptr %x12, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %10)
+// CHECK-NEXT:   br label %expand.next13
+// CHECK: expand.next13:
+// CHECK-NEXT:   %11 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT:   store i32 %11, ptr %x14, align 4
+// CHECK-NEXT:   %12 = load i32, ptr %x14, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %12)
+// CHECK-NEXT:   br label %expand.next15
+// CHECK: expand.next15:
+// CHECK-NEXT:   store i32 2, ptr %x16, align 4
+// CHECK-NEXT:   %13 = load i32, ptr %x16, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %13)
+// CHECK-NEXT:   br label %expand.next17
+// CHECK: expand.next17:
+// CHECK-NEXT:   %14 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT:   store i32 %14, ptr %x18, align 4
+// CHECK-NEXT:   %15 = load i32, ptr %x18, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %15)
+// CHECK-NEXT:   br label %expand.next19
+// CHECK: expand.next19:
+// CHECK-NEXT:   %16 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT:   store i32 %16, ptr %x20, align 4
+// CHECK-NEXT:   %17 = load i32, ptr %x20, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %17)
+// CHECK-NEXT:   br label %expand.next21
+// CHECK: expand.next21:
+// CHECK-NEXT:   %18 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT:   store i32 %18, ptr %x22, align 4
+// CHECK-NEXT:   %19 = load i32, ptr %x22, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %19)
+// CHECK-NEXT:   br label %expand.next23
+// CHECK: expand.next23:
+// CHECK-NEXT:   store i32 3, ptr %x24, align 4
+// CHECK-NEXT:   %20 = load i32, ptr %x24, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %20)
+// CHECK-NEXT:   br label %expand.end25
+// CHECK: expand.end25:
+// CHECK-NEXT:   store i32 4, ptr %x26, align 4
+// CHECK-NEXT:   %21 = load i32, ptr %x26, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %21)
+// CHECK-NEXT:   br label %expand.next27
+// CHECK: expand.next27:
+// CHECK-NEXT:   %22 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT:   store i32 %22, ptr %x28, align 4
+// CHECK-NEXT:   %23 = load i32, ptr %x28, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %23)
+// CHECK-NEXT:   br label %expand.next29
+// CHECK: expand.next29:
+// CHECK-NEXT:   %24 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT:   store i32 %24, ptr %x30, align 4
+// CHECK-NEXT:   %25 = load i32, ptr %x30, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %25)
+// CHECK-NEXT:   br label %expand.next31
+// CHECK: expand.next31:
+// CHECK-NEXT:   %26 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT:   store i32 %26, ptr %x32, align 4
+// CHECK-NEXT:   %27 = load i32, ptr %x32, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %27)
+// CHECK-NEXT:   br label %expand.next33
+// CHECK: expand.next33:
+// CHECK-NEXT:   %28 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT:   store i32 %28, ptr %x34, align 4
+// CHECK-NEXT:   %29 = load i32, ptr %x34, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %29)
+// CHECK-NEXT:   br label %expand.next35
+// CHECK: expand.next35:
+// CHECK-NEXT:   %30 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT:   store i32 %30, ptr %x36, align 4
+// CHECK-NEXT:   %31 = load i32, ptr %x36, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %31)
+// CHECK-NEXT:   br label %expand.next37
+// CHECK: expand.next37:
+// CHECK-NEXT:   %32 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT:   store i32 %32, ptr %x38, align 4
+// CHECK-NEXT:   %33 = load i32, ptr %x38, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %33)
+// CHECK-NEXT:   br label %expand.next39
+// CHECK: expand.next39:
+// CHECK-NEXT:   store i32 5, ptr %x40, align 4
+// CHECK-NEXT:   %34 = load i32, ptr %x40, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %34)
+// CHECK-NEXT:   br label %expand.end41
+// CHECK: expand.end41:
+// CHECK-NEXT:   %a = getelementptr inbounds nuw %struct.X, ptr %x42, i32 0, i32 0
+// CHECK-NEXT:   %35 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT:   store i32 %35, ptr %a, align 4
+// CHECK-NEXT:   %b = getelementptr inbounds nuw %struct.X, ptr %x42, i32 0, i32 1
+// CHECK-NEXT:   %36 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT:   store i32 %36, ptr %b, align 4
+// CHECK-NEXT:   %c = getelementptr inbounds nuw %struct.X, ptr %x42, i32 0, i32 2
+// CHECK-NEXT:   %37 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT:   store i32 %37, ptr %c, align 4
+// CHECK-NEXT:   %a43 = getelementptr inbounds nuw %struct.X, ptr %x42, i32 0, i32 0
+// CHECK-NEXT:   %38 = load i32, ptr %a43, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %38)
+// CHECK-NEXT:   br label %expand.next44
+// CHECK: expand.next44:
+// CHECK-NEXT:   %a46 = getelementptr inbounds nuw %struct.X, ptr %x45, i32 0, i32 0
+// CHECK-NEXT:   %39 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT:   store i32 %39, ptr %a46, align 4
+// CHECK-NEXT:   %b47 = getelementptr inbounds nuw %struct.X, ptr %x45, i32 0, i32 1
+// CHECK-NEXT:   %40 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT:   store i32 %40, ptr %b47, align 4
+// CHECK-NEXT:   %c48 = getelementptr inbounds nuw %struct.X, ptr %x45, i32 0, i32 2
+// CHECK-NEXT:   %41 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT:   store i32 %41, ptr %c48, align 4
+// CHECK-NEXT:   %a49 = getelementptr inbounds nuw %struct.X, ptr %x45, i32 0, i32 0
+// CHECK-NEXT:   %42 = load i32, ptr %a49, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %42)
+// CHECK-NEXT:   br label %expand.next50
+// CHECK: expand.next50:
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x51, ptr align 4 @__const._Z2t3IJiiiEEvDpT_.x, i64 12, i1 false)
+// CHECK-NEXT:   %a52 = getelementptr inbounds nuw %struct.X, ptr %x51, i32 0, i32 0
+// CHECK-NEXT:   %43 = load i32, ptr %a52, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %43)
+// CHECK-NEXT:   br label %expand.end53
+// CHECK: expand.end53:
+// CHECK-NEXT:   %a55 = getelementptr inbounds nuw %struct.X, ptr %x54, i32 0, i32 0
+// CHECK-NEXT:   %44 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT:   store i32 %44, ptr %a55, align 4
+// CHECK-NEXT:   %b56 = getelementptr inbounds nuw %struct.X, ptr %x54, i32 0, i32 1
+// CHECK-NEXT:   %45 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT:   store i32 %45, ptr %b56, align 4
+// CHECK-NEXT:   %c57 = getelementptr inbounds nuw %struct.X, ptr %x54, i32 0, i32 2
+// CHECK-NEXT:   %46 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT:   store i32 %46, ptr %c57, align 4
+// CHECK-NEXT:   %a58 = getelementptr inbounds nuw %struct.X, ptr %x54, i32 0, i32 0
+// CHECK-NEXT:   %47 = load i32, ptr %a58, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %47)
+// CHECK-NEXT:   br label %expand.end59
+// CHECK: expand.end59:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2t4IJLi42ELi43ELi44EEEvv()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x1 = alloca i32, align 4
+// CHECK-NEXT:   %x4 = alloca i32, align 4
+// CHECK-NEXT:   %x6 = alloca i32, align 4
+// CHECK-NEXT:   %x9 = alloca i32, align 4
+// CHECK-NEXT:   %x12 = alloca i32, align 4
+// CHECK-NEXT:   %x15 = alloca i32, align 4
+// CHECK-NEXT:   %x18 = alloca i32, align 4
+// CHECK-NEXT:   %x21 = alloca i32, align 4
+// CHECK-NEXT:   %x24 = alloca i32, align 4
+// CHECK-NEXT:   %x27 = alloca i32, align 4
+// CHECK-NEXT:   %x30 = alloca i32, align 4
+// CHECK-NEXT:   %x33 = alloca i32, align 4
+// CHECK-NEXT:   %x36 = alloca i32, align 4
+// CHECK-NEXT:   %x39 = alloca i32, align 4
+// CHECK-NEXT:   %x42 = alloca i32, align 4
+// CHECK-NEXT:   %x45 = alloca i32, align 4
+// CHECK-NEXT:   %x48 = alloca i32, align 4
+// CHECK-NEXT:   %x51 = alloca i32, align 4
+// CHECK-NEXT:   %x54 = alloca i32, align 4
+// CHECK-NEXT:   %x57 = alloca %struct.X, align 4
+// CHECK-NEXT:   %x60 = alloca %struct.X, align 4
+// CHECK-NEXT:   %x63 = alloca %struct.X, align 4
+// CHECK-NEXT:   %x66 = alloca %struct.X, align 4
+// CHECK-NEXT:   store i32 42, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT:   %call = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 43, ptr %x1, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 43)
+// CHECK-NEXT:   %call2 = call {{.*}} i32 @_Z2tgILi43EEiv()
+// CHECK-NEXT:   br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT:   store i32 44, ptr %x4, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 44)
+// CHECK-NEXT:   %call5 = call {{.*}} i32 @_Z2tgILi44EEiv()
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store i32 1, ptr %x6, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 1)
+// CHECK-NEXT:   %call7 = call {{.*}} i32 @_Z2tgILi1EEiv()
+// CHECK-NEXT:   br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT:   store i32 42, ptr %x9, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT:   %call10 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT:   br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT:   store i32 43, ptr %x12, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 43)
+// CHECK-NEXT:   %call13 = call {{.*}} i32 @_Z2tgILi43EEiv()
+// CHECK-NEXT:   br label %expand.next14
+// CHECK: expand.next14:
+// CHECK-NEXT:   store i32 44, ptr %x15, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 44)
+// CHECK-NEXT:   %call16 = call {{.*}} i32 @_Z2tgILi44EEiv()
+// CHECK-NEXT:   br label %expand.next17
+// CHECK: expand.next17:
+// CHECK-NEXT:   store i32 2, ptr %x18, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 2)
+// CHECK-NEXT:   %call19 = call {{.*}} i32 @_Z2tgILi2EEiv()
+// CHECK-NEXT:   br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT:   store i32 42, ptr %x21, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT:   %call22 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT:   br label %expand.next23
+// CHECK: expand.next23:
+// CHECK-NEXT:   store i32 43, ptr %x24, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 43)
+// CHECK-NEXT:   %call25 = call {{.*}} i32 @_Z2tgILi43EEiv()
+// CHECK-NEXT:   br label %expand.next26
+// CHECK: expand.next26:
+// CHECK-NEXT:   store i32 44, ptr %x27, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 44)
+// CHECK-NEXT:   %call28 = call {{.*}} i32 @_Z2tgILi44EEiv()
+// CHECK-NEXT:   br label %expand.next29
+// CHECK: expand.next29:
+// CHECK-NEXT:   store i32 3, ptr %x30, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 3)
+// CHECK-NEXT:   %call31 = call {{.*}} i32 @_Z2tgILi3EEiv()
+// CHECK-NEXT:   br label %expand.end32
+// CHECK: expand.end32:
+// CHECK-NEXT:   store i32 4, ptr %x33, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 4)
+// CHECK-NEXT:   %call34 = call {{.*}} i32 @_Z2tgILi4EEiv()
+// CHECK-NEXT:   br label %expand.next35
+// CHECK: expand.next35:
+// CHECK-NEXT:   store i32 42, ptr %x36, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT:   %call37 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT:   br label %expand.next38
+// CHECK: expand.next38:
+// CHECK-NEXT:   store i32 43, ptr %x39, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 43)
+// CHECK-NEXT:   %call40 = call {{.*}} i32 @_Z2tgILi43EEiv()
+// CHECK-NEXT:   br label %expand.next41
+// CHECK: expand.next41:
+// CHECK-NEXT:   store i32 44, ptr %x42, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 44)
+// CHECK-NEXT:   %call43 = call {{.*}} i32 @_Z2tgILi44EEiv()
+// CHECK-NEXT:   br label %expand.next44
+// CHECK: expand.next44:
+// CHECK-NEXT:   store i32 42, ptr %x45, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT:   %call46 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT:   br label %expand.next47
+// CHECK: expand.next47:
+// CHECK-NEXT:   store i32 43, ptr %x48, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 43)
+// CHECK-NEXT:   %call49 = call {{.*}} i32 @_Z2tgILi43EEiv()
+// CHECK-NEXT:   br label %expand.next50
+// CHECK: expand.next50:
+// CHECK-NEXT:   store i32 44, ptr %x51, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 44)
+// CHECK-NEXT:   %call52 = call {{.*}} i32 @_Z2tgILi44EEiv()
+// CHECK-NEXT:   br label %expand.next53
+// CHECK: expand.next53:
+// CHECK-NEXT:   store i32 5, ptr %x54, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 5)
+// CHECK-NEXT:   %call55 = call {{.*}} i32 @_Z2tgILi5EEiv()
+// CHECK-NEXT:   br label %expand.end56
+// CHECK: expand.end56:
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x57, ptr align 4 @__const._Z2t4IJLi42ELi43ELi44EEEvv.x, i64 12, i1 false)
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT:   %call58 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT:   br label %expand.next59
+// CHECK: expand.next59:
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x60, ptr align 4 @__const._Z2t4IJLi42ELi43ELi44EEEvv.x.3, i64 12, i1 false)
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT:   %call61 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT:   br label %expand.next62
+// CHECK: expand.next62:
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x63, ptr align 4 @__const._Z2t4IJLi42ELi43ELi44EEEvv.x.4, i64 12, i1 false)
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 6)
+// CHECK-NEXT:   %call64 = call {{.*}} i32 @_Z2tgILi6EEiv()
+// CHECK-NEXT:   br label %expand.end65
+// CHECK: expand.end65:
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x66, ptr align 4 @__const._Z2t4IJLi42ELi43ELi44EEEvv.x.5, i64 12, i1 false)
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT:   %call67 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT:   br label %expand.end68
+// CHECK: expand.end68:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZN2s2IJLi1ELi2ELi3EEE2tfIJLi4ELi5ELi6EEEEvv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT:   %this.addr = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x2 = alloca i32, align 4
+// CHECK-NEXT:   %x4 = alloca i32, align 4
+// CHECK-NEXT:   %x6 = alloca i32, align 4
+// CHECK-NEXT:   %x8 = alloca i32, align 4
+// CHECK-NEXT:   %x10 = alloca i32, align 4
+// CHECK-NEXT:   %x11 = alloca %struct.X, align 4
+// CHECK-NEXT:   %x13 = alloca %struct.X, align 4
+// CHECK-NEXT:   %x16 = alloca i32, align 4
+// CHECK-NEXT:   %x18 = alloca i32, align 4
+// CHECK-NEXT:   %x21 = alloca i32, align 4
+// CHECK-NEXT:   %x24 = alloca i32, align 4
+// CHECK-NEXT:   %x27 = alloca i32, align 4
+// CHECK-NEXT:   %x30 = alloca i32, align 4
+// CHECK-NEXT:   %x33 = alloca %struct.X, align 4
+// CHECK-NEXT:   %x36 = alloca %struct.X, align 4
+// CHECK-NEXT:   store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT:   %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 2, ptr %x2, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %x2, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT:   br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT:   store i32 3, ptr %x4, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x4, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %2)
+// CHECK-NEXT:   br label %expand.next5
+// CHECK: expand.next5:
+// CHECK-NEXT:   store i32 4, ptr %x6, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %x6, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %3)
+// CHECK-NEXT:   br label %expand.next7
+// CHECK: expand.next7:
+// CHECK-NEXT:   store i32 5, ptr %x8, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x8, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %4)
+// CHECK-NEXT:   br label %expand.next9
+// CHECK: expand.next9:
+// CHECK-NEXT:   store i32 6, ptr %x10, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %x10, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %5)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x11, ptr align 4 @__const._ZN2s2IJLi1ELi2ELi3EEE2tfIJLi4ELi5ELi6EEEEvv.x, i64 12, i1 false)
+// CHECK-NEXT:   %a = getelementptr inbounds nuw %struct.X, ptr %x11, i32 0, i32 0
+// CHECK-NEXT:   %6 = load i32, ptr %a, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %6)
+// CHECK-NEXT:   br label %expand.next12
+// CHECK: expand.next12:
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x13, ptr align 4 @__const._ZN2s2IJLi1ELi2ELi3EEE2tfIJLi4ELi5ELi6EEEEvv.x.6, i64 12, i1 false)
+// CHECK-NEXT:   %a14 = getelementptr inbounds nuw %struct.X, ptr %x13, i32 0, i32 0
+// CHECK-NEXT:   %7 = load i32, ptr %a14, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} %7)
+// CHECK-NEXT:   br label %expand.end15
+// CHECK: expand.end15:
+// CHECK-NEXT:   store i32 1, ptr %x16, align 4
+// CHECK-NEXT:   %call = call {{.*}} i32 @_Z2tgILi1EEiv()
+// CHECK-NEXT:   br label %expand.next17
+// CHECK: expand.next17:
+// CHECK-NEXT:   store i32 2, ptr %x18, align 4
+// CHECK-NEXT:   %call19 = call {{.*}} i32 @_Z2tgILi2EEiv()
+// CHECK-NEXT:   br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT:   store i32 3, ptr %x21, align 4
+// CHECK-NEXT:   %call22 = call {{.*}} i32 @_Z2tgILi3EEiv()
+// CHECK-NEXT:   br label %expand.next23
+// CHECK: expand.next23:
+// CHECK-NEXT:   store i32 4, ptr %x24, align 4
+// CHECK-NEXT:   %call25 = call {{.*}} i32 @_Z2tgILi4EEiv()
+// CHECK-NEXT:   br label %expand.next26
+// CHECK: expand.next26:
+// CHECK-NEXT:   store i32 5, ptr %x27, align 4
+// CHECK-NEXT:   %call28 = call {{.*}} i32 @_Z2tgILi5EEiv()
+// CHECK-NEXT:   br label %expand.next29
+// CHECK: expand.next29:
+// CHECK-NEXT:   store i32 6, ptr %x30, align 4
+// CHECK-NEXT:   %call31 = call {{.*}} i32 @_Z2tgILi6EEiv()
+// CHECK-NEXT:   br label %expand.end32
+// CHECK: expand.end32:
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x33, ptr align 4 @__const._ZN2s2IJLi1ELi2ELi3EEE2tfIJLi4ELi5ELi6EEEEvv.x.7, i64 12, i1 false)
+// CHECK-NEXT:   %call34 = call {{.*}} i32 @_Z2tgILi1EEiv()
+// CHECK-NEXT:   br label %expand.next35
+// CHECK: expand.next35:
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x36, ptr align 4 @__const._ZN2s2IJLi1ELi2ELi3EEE2tfIJLi4ELi5ELi6EEEEvv.x.8, i64 12, i1 false)
+// CHECK-NEXT:   %call37 = call {{.*}} i32 @_Z2tgILi4EEiv()
+// CHECK-NEXT:   br label %expand.end38
+// CHECK: expand.end38:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f8v()
+// CHECK: entry:
+// CHECK-NEXT:   call void @_Z2t5IJLi1ELi2ELi3EEEvv()
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2t5IJLi1ELi2ELi3EEEvv()
+// CHECK: entry:
+// CHECK-NEXT:   %ref.tmp = alloca %class.anon, align 1
+// CHECK-NEXT:   %ref.tmp1 = alloca %class.anon.1, align 1
+// CHECK-NEXT:   %ref.tmp2 = alloca %class.anon.3, align 1
+// CHECK-NEXT:   call void @_ZZ2t5IJLi1ELi2ELi3EEEvvENKUlvE1_clEv(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   call void @_ZZ2t5IJLi1ELi2ELi3EEEvvENKUlvE0_clEv(ptr {{.*}} %ref.tmp1)
+// CHECK-NEXT:   call void @_ZZ2t5IJLi1ELi2ELi3EEEvvENKUlvE_clEv(ptr {{.*}} %ref.tmp2)
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z22references_enumeratingv()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %y = alloca i32, align 4
+// CHECK-NEXT:   %z = alloca i32, align 4
+// CHECK-NEXT:   %v = alloca ptr, align 8
+// CHECK-NEXT:   %v1 = alloca ptr, align 8
+// CHECK-NEXT:   %v4 = alloca ptr, align 8
+// CHECK-NEXT:   %v6 = alloca ptr, align 8
+// CHECK-NEXT:   %v9 = alloca ptr, align 8
+// CHECK-NEXT:   %v12 = alloca ptr, align 8
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   store i32 2, ptr %y, align 4
+// CHECK-NEXT:   store i32 3, ptr %z, align 4
+// CHECK-NEXT:   store ptr %x, ptr %v, align 8
+// CHECK-NEXT:   %0 = load ptr, ptr %v, align 8
+// CHECK-NEXT:   %1 = load i32, ptr %0, align 4
+// CHECK-NEXT:   %inc = add nsw i32 %1, 1
+// CHECK-NEXT:   store i32 %inc, ptr %0, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store ptr %y, ptr %v1, align 8
+// CHECK-NEXT:   %2 = load ptr, ptr %v1, align 8
+// CHECK-NEXT:   %3 = load i32, ptr %2, align 4
+// CHECK-NEXT:   %inc2 = add nsw i32 %3, 1
+// CHECK-NEXT:   store i32 %inc2, ptr %2, align 4
+// CHECK-NEXT:   br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT:   store ptr %z, ptr %v4, align 8
+// CHECK-NEXT:   %4 = load ptr, ptr %v4, align 8
+// CHECK-NEXT:   %5 = load i32, ptr %4, align 4
+// CHECK-NEXT:   %inc5 = add nsw i32 %5, 1
+// CHECK-NEXT:   store i32 %inc5, ptr %4, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store ptr %x, ptr %v6, align 8
+// CHECK-NEXT:   %6 = load ptr, ptr %v6, align 8
+// CHECK-NEXT:   %7 = load i32, ptr %6, align 4
+// CHECK-NEXT:   %inc7 = add nsw i32 %7, 1
+// CHECK-NEXT:   store i32 %inc7, ptr %6, align 4
+// CHECK-NEXT:   br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT:   store ptr %y, ptr %v9, align 8
+// CHECK-NEXT:   %8 = load ptr, ptr %v9, align 8
+// CHECK-NEXT:   %9 = load i32, ptr %8, align 4
+// CHECK-NEXT:   %inc10 = add nsw i32 %9, 1
+// CHECK-NEXT:   store i32 %inc10, ptr %8, align 4
+// CHECK-NEXT:   br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT:   store ptr %z, ptr %v12, align 8
+// CHECK-NEXT:   %10 = load ptr, ptr %v12, align 8
+// CHECK-NEXT:   %11 = load i32, ptr %10, align 4
+// CHECK-NEXT:   %inc13 = add nsw i32 %11, 1
+// CHECK-NEXT:   store i32 %inc13, ptr %10, align 4
+// CHECK-NEXT:   br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT:   %12 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %13 = load i32, ptr %y, align 4
+// CHECK-NEXT:   %add = add nsw i32 %12, %13
+// CHECK-NEXT:   %14 = load i32, ptr %z, align 4
+// CHECK-NEXT:   %add15 = add nsw i32 %add, %14
+// CHECK-NEXT:   ret i32 %add15
+
+
+// CHECK-LABEL: define {{.*}} void @_ZZ2t5IJLi1ELi2ELi3EEEvvENKUlvE1_clEv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT:   %this.addr = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT:   %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 1)
+// CHECK-NEXT:   %call = call {{.*}} i32 @_Z2tgILi1EEiv()
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZZ2t5IJLi1ELi2ELi3EEEvvENKUlvE0_clEv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT:   %this.addr = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT:   %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT:   store i32 2, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 2)
+// CHECK-NEXT:   %call = call {{.*}} i32 @_Z2tgILi2EEiv()
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZZ2t5IJLi1ELi2ELi3EEEvvENKUlvE_clEv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT:   %this.addr = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT:   %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT:   store i32 3, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1gi(i32 {{.*}} 3)
+// CHECK-NEXT:   %call = call {{.*}} i32 @_Z2tgILi3EEiv()
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   ret void
diff --git a/clang/test/CodeGenCXX/cxx2c-expansion-stmts-control-flow.cpp b/clang/test/CodeGenCXX/cxx2c-expansion-stmts-control-flow.cpp
new file mode 100644
index 0000000000000..f94b580290500
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx2c-expansion-stmts-control-flow.cpp
@@ -0,0 +1,429 @@
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+void h(int, int);
+
+void break_continue() {
+  template for (auto x : {1, 2}) {
+    break;
+    h(1, x);
+  }
+
+  template for (auto x : {3, 4}) {
+    continue;
+    h(2, x);
+  }
+
+  template for (auto x : {5, 6}) {
+    if (x == 2) break;
+    h(3, x);
+  }
+
+  template for (auto x : {7, 8}) {
+    if (x == 2) continue;
+    h(4, x);
+  }
+}
+
+int break_continue_nested() {
+  int sum = 0;
+
+  template for (auto x : {1, 2}) {
+    template for (auto y : {3, 4}) {
+      if (x == 2) break;
+      sum += y;
+    }
+    sum += x;
+  }
+
+  template for (auto x : {5, 6}) {
+    template for (auto y : {7, 8}) {
+      if (x == 6) continue;
+      sum += y;
+    }
+    sum += x;
+  }
+
+  return sum;
+}
+
+void label() {
+  // Only local labels are allowed in expansion statements.
+  template for (auto x : {1, 2, 3}) {
+    __label__ a;
+    if (x == 1) goto a;
+    h(1, x);
+    a:;
+  }
+}
+
+void nested_label() {
+  template for (auto x : {1, 2}) {
+    __label__ a;
+    template for (auto y : {3, 4}) {
+      if (y == 3) goto a;
+      if (y == 4) goto end;
+      h(x, y);
+    }
+    a:;
+  }
+  end:
+}
+
+
+// CHECK-LABEL: define {{.*}} void @_Z14break_continuev()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x1 = alloca i32, align 4
+// CHECK-NEXT:   %x2 = alloca i32, align 4
+// CHECK-NEXT:   %x4 = alloca i32, align 4
+// CHECK-NEXT:   %x6 = alloca i32, align 4
+// CHECK-NEXT:   %x11 = alloca i32, align 4
+// CHECK-NEXT:   %x16 = alloca i32, align 4
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store i32 3, ptr %x1, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 4, ptr %x2, align 4
+// CHECK-NEXT:   br label %expand.end3
+// CHECK: expand.end3:
+// CHECK-NEXT:   store i32 5, ptr %x4, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %x4, align 4
+// CHECK-NEXT:   %cmp = icmp eq i32 %0, 2
+// CHECK-NEXT:   br i1 %cmp, label %if.then, label %if.end
+// CHECK: if.then:
+// CHECK-NEXT:   br label %expand.end10
+// CHECK: if.end:
+// CHECK-NEXT:   %1 = load i32, ptr %x4, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} 3, i32 {{.*}} %1)
+// CHECK-NEXT:   br label %expand.next5
+// CHECK: expand.next5:
+// CHECK-NEXT:   store i32 6, ptr %x6, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x6, align 4
+// CHECK-NEXT:   %cmp7 = icmp eq i32 %2, 2
+// CHECK-NEXT:   br i1 %cmp7, label %if.then8, label %if.end9
+// CHECK: if.then8:
+// CHECK-NEXT:   br label %expand.end10
+// CHECK: if.end9:
+// CHECK-NEXT:   %3 = load i32, ptr %x6, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} 3, i32 {{.*}} %3)
+// CHECK-NEXT:   br label %expand.end10
+// CHECK: expand.end10:
+// CHECK-NEXT:   store i32 7, ptr %x11, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x11, align 4
+// CHECK-NEXT:   %cmp12 = icmp eq i32 %4, 2
+// CHECK-NEXT:   br i1 %cmp12, label %if.then13, label %if.end14
+// CHECK: if.then13:
+// CHECK-NEXT:   br label %expand.next15
+// CHECK: if.end14:
+// CHECK-NEXT:   %5 = load i32, ptr %x11, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} 4, i32 {{.*}} %5)
+// CHECK-NEXT:   br label %expand.next15
+// CHECK: expand.next15:
+// CHECK-NEXT:   store i32 8, ptr %x16, align 4
+// CHECK-NEXT:   %6 = load i32, ptr %x16, align 4
+// CHECK-NEXT:   %cmp17 = icmp eq i32 %6, 2
+// CHECK-NEXT:   br i1 %cmp17, label %if.then18, label %if.end19
+// CHECK: if.then18:
+// CHECK-NEXT:   br label %expand.end20
+// CHECK: if.end19:
+// CHECK-NEXT:   %7 = load i32, ptr %x16, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} 4, i32 {{.*}} %7)
+// CHECK-NEXT:   br label %expand.end20
+// CHECK: expand.end20:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z21break_continue_nestedv()
+// CHECK: entry:
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %y = alloca i32, align 4
+// CHECK-NEXT:   %y1 = alloca i32, align 4
+// CHECK-NEXT:   %x8 = alloca i32, align 4
+// CHECK-NEXT:   %y9 = alloca i32, align 4
+// CHECK-NEXT:   %y15 = alloca i32, align 4
+// CHECK-NEXT:   %x23 = alloca i32, align 4
+// CHECK-NEXT:   %y24 = alloca i32, align 4
+// CHECK-NEXT:   %y30 = alloca i32, align 4
+// CHECK-NEXT:   %x38 = alloca i32, align 4
+// CHECK-NEXT:   %y39 = alloca i32, align 4
+// CHECK-NEXT:   %y45 = alloca i32, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   store i32 3, ptr %y, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %cmp = icmp eq i32 %0, 2
+// CHECK-NEXT:   br i1 %cmp, label %if.then, label %if.end
+// CHECK: if.then:
+// CHECK-NEXT:   br label %expand.end
+// CHECK: if.end:
+// CHECK-NEXT:   %1 = load i32, ptr %y, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add = add nsw i32 %2, %1
+// CHECK-NEXT:   store i32 %add, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 4, ptr %y1, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %cmp2 = icmp eq i32 %3, 2
+// CHECK-NEXT:   br i1 %cmp2, label %if.then3, label %if.end4
+// CHECK: if.then3:
+// CHECK-NEXT:   br label %expand.end
+// CHECK: if.end4:
+// CHECK-NEXT:   %4 = load i32, ptr %y1, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add5 = add nsw i32 %5, %4
+// CHECK-NEXT:   store i32 %add5, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   %6 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add6 = add nsw i32 %7, %6
+// CHECK-NEXT:   store i32 %add6, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next7
+// CHECK: expand.next7:
+// CHECK-NEXT:   store i32 2, ptr %x8, align 4
+// CHECK-NEXT:   store i32 3, ptr %y9, align 4
+// CHECK-NEXT:   %8 = load i32, ptr %x8, align 4
+// CHECK-NEXT:   %cmp10 = icmp eq i32 %8, 2
+// CHECK-NEXT:   br i1 %cmp10, label %if.then11, label %if.end12
+// CHECK: if.then11:
+// CHECK-NEXT:   br label %expand.end20
+// CHECK: if.end12:
+// CHECK-NEXT:   %9 = load i32, ptr %y9, align 4
+// CHECK-NEXT:   %10 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add13 = add nsw i32 %10, %9
+// CHECK-NEXT:   store i32 %add13, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next14
+// CHECK: expand.next14:
+// CHECK-NEXT:   store i32 4, ptr %y15, align 4
+// CHECK-NEXT:   %11 = load i32, ptr %x8, align 4
+// CHECK-NEXT:   %cmp16 = icmp eq i32 %11, 2
+// CHECK-NEXT:   br i1 %cmp16, label %if.then17, label %if.end18
+// CHECK: if.then17:
+// CHECK-NEXT:   br label %expand.end20
+// CHECK: if.end18:
+// CHECK-NEXT:   %12 = load i32, ptr %y15, align 4
+// CHECK-NEXT:   %13 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add19 = add nsw i32 %13, %12
+// CHECK-NEXT:   store i32 %add19, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end20
+// CHECK: expand.end20:
+// CHECK-NEXT:   %14 = load i32, ptr %x8, align 4
+// CHECK-NEXT:   %15 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add21 = add nsw i32 %15, %14
+// CHECK-NEXT:   store i32 %add21, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end22
+// CHECK: expand.end22:
+// CHECK-NEXT:   store i32 5, ptr %x23, align 4
+// CHECK-NEXT:   store i32 7, ptr %y24, align 4
+// CHECK-NEXT:   %16 = load i32, ptr %x23, align 4
+// CHECK-NEXT:   %cmp25 = icmp eq i32 %16, 6
+// CHECK-NEXT:   br i1 %cmp25, label %if.then26, label %if.end27
+// CHECK: if.then26:
+// CHECK-NEXT:   br label %expand.next29
+// CHECK: if.end27:
+// CHECK-NEXT:   %17 = load i32, ptr %y24, align 4
+// CHECK-NEXT:   %18 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add28 = add nsw i32 %18, %17
+// CHECK-NEXT:   store i32 %add28, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next29
+// CHECK: expand.next29:
+// CHECK-NEXT:   store i32 8, ptr %y30, align 4
+// CHECK-NEXT:   %19 = load i32, ptr %x23, align 4
+// CHECK-NEXT:   %cmp31 = icmp eq i32 %19, 6
+// CHECK-NEXT:   br i1 %cmp31, label %if.then32, label %if.end33
+// CHECK: if.then32:
+// CHECK-NEXT:   br label %expand.end35
+// CHECK: if.end33:
+// CHECK-NEXT:   %20 = load i32, ptr %y30, align 4
+// CHECK-NEXT:   %21 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add34 = add nsw i32 %21, %20
+// CHECK-NEXT:   store i32 %add34, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end35
+// CHECK: expand.end35:
+// CHECK-NEXT:   %22 = load i32, ptr %x23, align 4
+// CHECK-NEXT:   %23 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add36 = add nsw i32 %23, %22
+// CHECK-NEXT:   store i32 %add36, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next37
+// CHECK: expand.next37:
+// CHECK-NEXT:   store i32 6, ptr %x38, align 4
+// CHECK-NEXT:   store i32 7, ptr %y39, align 4
+// CHECK-NEXT:   %24 = load i32, ptr %x38, align 4
+// CHECK-NEXT:   %cmp40 = icmp eq i32 %24, 6
+// CHECK-NEXT:   br i1 %cmp40, label %if.then41, label %if.end42
+// CHECK: if.then41:
+// CHECK-NEXT:   br label %expand.next44
+// CHECK: if.end42:
+// CHECK-NEXT:   %25 = load i32, ptr %y39, align 4
+// CHECK-NEXT:   %26 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add43 = add nsw i32 %26, %25
+// CHECK-NEXT:   store i32 %add43, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next44
+// CHECK: expand.next44:
+// CHECK-NEXT:   store i32 8, ptr %y45, align 4
+// CHECK-NEXT:   %27 = load i32, ptr %x38, align 4
+// CHECK-NEXT:   %cmp46 = icmp eq i32 %27, 6
+// CHECK-NEXT:   br i1 %cmp46, label %if.then47, label %if.end48
+// CHECK: if.then47:
+// CHECK-NEXT:   br label %expand.end50
+// CHECK: if.end48:
+// CHECK-NEXT:   %28 = load i32, ptr %y45, align 4
+// CHECK-NEXT:   %29 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add49 = add nsw i32 %29, %28
+// CHECK-NEXT:   store i32 %add49, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end50
+// CHECK: expand.end50:
+// CHECK-NEXT:   %30 = load i32, ptr %x38, align 4
+// CHECK-NEXT:   %31 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add51 = add nsw i32 %31, %30
+// CHECK-NEXT:   store i32 %add51, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end52
+// CHECK: expand.end52:
+// CHECK-NEXT:   %32 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   ret i32 %32
+
+
+// CHECK-LABEL: define {{.*}} void @_Z5labelv()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x1 = alloca i32, align 4
+// CHECK-NEXT:   %x7 = alloca i32, align 4
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %cmp = icmp eq i32 %0, 1
+// CHECK-NEXT:   br i1 %cmp, label %if.then, label %if.end
+// CHECK: if.then:
+// CHECK-NEXT:   br label %a
+// CHECK: if.end:
+// CHECK-NEXT:   %1 = load i32, ptr %x, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} 1, i32 {{.*}} %1)
+// CHECK-NEXT:   br label %a
+// CHECK: a:
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 2, ptr %x1, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x1, align 4
+// CHECK-NEXT:   %cmp2 = icmp eq i32 %2, 1
+// CHECK-NEXT:   br i1 %cmp2, label %if.then3, label %if.end4
+// CHECK: if.then3:
+// CHECK-NEXT:   br label %a5
+// CHECK: if.end4:
+// CHECK-NEXT:   %3 = load i32, ptr %x1, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} 1, i32 {{.*}} %3)
+// CHECK-NEXT:   br label %a5
+// CHECK: a5:
+// CHECK-NEXT:   br label %expand.next6
+// CHECK: expand.next6:
+// CHECK-NEXT:   store i32 3, ptr %x7, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x7, align 4
+// CHECK-NEXT:   %cmp8 = icmp eq i32 %4, 1
+// CHECK-NEXT:   br i1 %cmp8, label %if.then9, label %if.end10
+// CHECK: if.then9:
+// CHECK-NEXT:   br label %a11
+// CHECK: if.end10:
+// CHECK-NEXT:   %5 = load i32, ptr %x7, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} 1, i32 {{.*}} %5)
+// CHECK-NEXT:   br label %a11
+// CHECK: a11:
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z12nested_labelv()
+// CHECK: entry:
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %y = alloca i32, align 4
+// CHECK-NEXT:   %y4 = alloca i32, align 4
+// CHECK-NEXT:   %x12 = alloca i32, align 4
+// CHECK-NEXT:   %y13 = alloca i32, align 4
+// CHECK-NEXT:   %y21 = alloca i32, align 4
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   store i32 3, ptr %y, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %y, align 4
+// CHECK-NEXT:   %cmp = icmp eq i32 %0, 3
+// CHECK-NEXT:   br i1 %cmp, label %if.then, label %if.end
+// CHECK: if.then:
+// CHECK-NEXT:   br label %a
+// CHECK: if.end:
+// CHECK-NEXT:   %1 = load i32, ptr %y, align 4
+// CHECK-NEXT:   %cmp1 = icmp eq i32 %1, 4
+// CHECK-NEXT:   br i1 %cmp1, label %if.then2, label %if.end3
+// CHECK: if.then2:
+// CHECK-NEXT:   br label %end
+// CHECK: if.end3:
+// CHECK-NEXT:   %2 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %y, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} %2, i32 {{.*}} %3)
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 4, ptr %y4, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %y4, align 4
+// CHECK-NEXT:   %cmp5 = icmp eq i32 %4, 3
+// CHECK-NEXT:   br i1 %cmp5, label %if.then6, label %if.end7
+// CHECK: if.then6:
+// CHECK-NEXT:   br label %a
+// CHECK: if.end7:
+// CHECK-NEXT:   %5 = load i32, ptr %y4, align 4
+// CHECK-NEXT:   %cmp8 = icmp eq i32 %5, 4
+// CHECK-NEXT:   br i1 %cmp8, label %if.then9, label %if.end10
+// CHECK: if.then9:
+// CHECK-NEXT:   br label %end
+// CHECK: if.end10:
+// CHECK-NEXT:   %6 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %y4, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} %6, i32 {{.*}} %7)
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   br label %a
+// CHECK: a:
+// CHECK-NEXT:   br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT:   store i32 2, ptr %x12, align 4
+// CHECK-NEXT:   store i32 3, ptr %y13, align 4
+// CHECK-NEXT:   %8 = load i32, ptr %y13, align 4
+// CHECK-NEXT:   %cmp14 = icmp eq i32 %8, 3
+// CHECK-NEXT:   br i1 %cmp14, label %if.then15, label %if.end16
+// CHECK: if.then15:
+// CHECK-NEXT:   br label %a29
+// CHECK: if.end16:
+// CHECK-NEXT:   %9 = load i32, ptr %y13, align 4
+// CHECK-NEXT:   %cmp17 = icmp eq i32 %9, 4
+// CHECK-NEXT:   br i1 %cmp17, label %if.then18, label %if.end19
+// CHECK: if.then18:
+// CHECK-NEXT:   br label %end
+// CHECK: if.end19:
+// CHECK-NEXT:   %10 = load i32, ptr %x12, align 4
+// CHECK-NEXT:   %11 = load i32, ptr %y13, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} %10, i32 {{.*}} %11)
+// CHECK-NEXT:   br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT:   store i32 4, ptr %y21, align 4
+// CHECK-NEXT:   %12 = load i32, ptr %y21, align 4
+// CHECK-NEXT:   %cmp22 = icmp eq i32 %12, 3
+// CHECK-NEXT:   br i1 %cmp22, label %if.then23, label %if.end24
+// CHECK: if.then23:
+// CHECK-NEXT:   br label %a29
+// CHECK: if.end24:
+// CHECK-NEXT:   %13 = load i32, ptr %y21, align 4
+// CHECK-NEXT:   %cmp25 = icmp eq i32 %13, 4
+// CHECK-NEXT:   br i1 %cmp25, label %if.then26, label %if.end27
+// CHECK: if.then26:
+// CHECK-NEXT:   br label %end
+// CHECK: if.end27:
+// CHECK-NEXT:   %14 = load i32, ptr %x12, align 4
+// CHECK-NEXT:   %15 = load i32, ptr %y21, align 4
+// CHECK-NEXT:   call void @_Z1hii(i32 {{.*}} %14, i32 {{.*}} %15)
+// CHECK-NEXT:   br label %expand.end28
+// CHECK: expand.end28:
+// CHECK-NEXT:   br label %a29
+// CHECK: a29:
+// CHECK-NEXT:   br label %expand.end30
+// CHECK: expand.end30:
+// CHECK-NEXT:   br label %end
+// CHECK: end:
+// CHECK-NEXT:   ret void
diff --git a/clang/test/CodeGenCXX/cxx2c-expansion-stmts-templates.cpp b/clang/test/CodeGenCXX/cxx2c-expansion-stmts-templates.cpp
new file mode 100644
index 0000000000000..e0de7ced5baee
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx2c-expansion-stmts-templates.cpp
@@ -0,0 +1,208 @@
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+struct E {
+  int x, y;
+  constexpr E(int x, int y) : x{x}, y{y} {}
+};
+
+template <typename ...Es>
+int unexpanded_pack_good(Es ...es) {
+  int sum = 0;
+  ([&] {
+    template for (auto x : es) sum += x;
+    template for (Es e : {{5, 6}, {7, 8}}) sum += e.x + e.y;
+  }(), ...);
+  return sum;
+}
+
+int unexpanded_pack() {
+  return unexpanded_pack_good(E{1, 2}, E{3, 4});
+}
+
+
+// CHECK: %struct.E = type { i32, i32 }
+// CHECK: %class.anon = type { ptr, ptr }
+// CHECK: %class.anon.0 = type { ptr, ptr }
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z15unexpanded_packv()
+// CHECK: entry:
+// CHECK-NEXT:   %agg.tmp = alloca %struct.E, align 4
+// CHECK-NEXT:   %agg.tmp1 = alloca %struct.E, align 4
+// CHECK-NEXT:   call void @_ZN1EC1Eii(ptr {{.*}} %agg.tmp, i32 {{.*}} 1, i32 {{.*}} 2)
+// CHECK-NEXT:   call void @_ZN1EC1Eii(ptr {{.*}} %agg.tmp1, i32 {{.*}} 3, i32 {{.*}} 4)
+// CHECK-NEXT:   %0 = load i64, ptr %agg.tmp, align 4
+// CHECK-NEXT:   %1 = load i64, ptr %agg.tmp1, align 4
+// CHECK-NEXT:   %call = call {{.*}} i32 @_Z20unexpanded_pack_goodIJ1ES0_EEiDpT_(i64 %0, i64 %1)
+// CHECK-NEXT:   ret i32 %call
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z20unexpanded_pack_goodIJ1ES0_EEiDpT_(i64 %es.coerce, i64 %es.coerce2)
+// CHECK: entry:
+// CHECK-NEXT:   %es = alloca %struct.E, align 4
+// CHECK-NEXT:   %es3 = alloca %struct.E, align 4
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %ref.tmp = alloca %class.anon, align 8
+// CHECK-NEXT:   %ref.tmp4 = alloca %class.anon.0, align 8
+// CHECK-NEXT:   store i64 %es.coerce, ptr %es, align 4
+// CHECK-NEXT:   store i64 %es.coerce2, ptr %es3, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK-NEXT:   %0 = getelementptr inbounds nuw %class.anon, ptr %ref.tmp, i32 0, i32 0
+// CHECK-NEXT:   store ptr %es, ptr %0, align 8
+// CHECK-NEXT:   %1 = getelementptr inbounds nuw %class.anon, ptr %ref.tmp, i32 0, i32 1
+// CHECK-NEXT:   store ptr %sum, ptr %1, align 8
+// CHECK-NEXT:   call void @_ZZ20unexpanded_pack_goodIJ1ES0_EEiDpT_ENKUlvE0_clEv(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   %2 = getelementptr inbounds nuw %class.anon.0, ptr %ref.tmp4, i32 0, i32 0
+// CHECK-NEXT:   store ptr %es3, ptr %2, align 8
+// CHECK-NEXT:   %3 = getelementptr inbounds nuw %class.anon.0, ptr %ref.tmp4, i32 0, i32 1
+// CHECK-NEXT:   store ptr %sum, ptr %3, align 8
+// CHECK-NEXT:   call void @_ZZ20unexpanded_pack_goodIJ1ES0_EEiDpT_ENKUlvE_clEv(ptr {{.*}} %ref.tmp4)
+// CHECK-NEXT:   %4 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   ret i32 %4
+
+
+// CHECK-LABEL: define {{.*}} void @_ZN1EC1Eii(ptr {{.*}} %this, i32 {{.*}} %x, i32 {{.*}} %y) {{.*}}
+// CHECK: entry:
+// CHECK-NEXT:   %this.addr = alloca ptr, align 8
+// CHECK-NEXT:   %x.addr = alloca i32, align 4
+// CHECK-NEXT:   %y.addr = alloca i32, align 4
+// CHECK-NEXT:   store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT:   store i32 %x, ptr %x.addr, align 4
+// CHECK-NEXT:   store i32 %y, ptr %y.addr, align 4
+// CHECK-NEXT:   %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT:   %0 = load i32, ptr %x.addr, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %y.addr, align 4
+// CHECK-NEXT:   call void @_ZN1EC2Eii(ptr {{.*}} %this1, i32 {{.*}} %0, i32 {{.*}} %1)
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZZ20unexpanded_pack_goodIJ1ES0_EEiDpT_ENKUlvE0_clEv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT:   %this.addr = alloca ptr, align 8
+// CHECK-NEXT:   %0 = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x3 = alloca i32, align 4
+// CHECK-NEXT:   %e = alloca %struct.E, align 4
+// CHECK-NEXT:   %e10 = alloca %struct.E, align 4
+// CHECK-NEXT:   store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT:   %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT:   %1 = getelementptr inbounds nuw %class.anon, ptr %this1, i32 0, i32 0
+// CHECK-NEXT:   %2 = load ptr, ptr %1, align 8
+// CHECK-NEXT:   store ptr %2, ptr %0, align 8
+// CHECK-NEXT:   %3 = load ptr, ptr %0, align 8
+// CHECK-NEXT:   %x2 = getelementptr inbounds nuw %struct.E, ptr %3, i32 0, i32 0
+// CHECK-NEXT:   %4 = load i32, ptr %x2, align 4
+// CHECK-NEXT:   store i32 %4, ptr %x, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %6 = getelementptr inbounds nuw %class.anon, ptr %this1, i32 0, i32 1
+// CHECK-NEXT:   %7 = load ptr, ptr %6, align 8
+// CHECK-NEXT:   %8 = load i32, ptr %7, align 4
+// CHECK-NEXT:   %add = add nsw i32 %8, %5
+// CHECK-NEXT:   store i32 %add, ptr %7, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   %9 = load ptr, ptr %0, align 8
+// CHECK-NEXT:   %y = getelementptr inbounds nuw %struct.E, ptr %9, i32 0, i32 1
+// CHECK-NEXT:   %10 = load i32, ptr %y, align 4
+// CHECK-NEXT:   store i32 %10, ptr %x3, align 4
+// CHECK-NEXT:   %11 = load i32, ptr %x3, align 4
+// CHECK-NEXT:   %12 = getelementptr inbounds nuw %class.anon, ptr %this1, i32 0, i32 1
+// CHECK-NEXT:   %13 = load ptr, ptr %12, align 8
+// CHECK-NEXT:   %14 = load i32, ptr %13, align 4
+// CHECK-NEXT:   %add4 = add nsw i32 %14, %11
+// CHECK-NEXT:   store i32 %add4, ptr %13, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   call void @_ZN1EC1Eii(ptr {{.*}} %e, i32 {{.*}} 5, i32 {{.*}} 6)
+// CHECK-NEXT:   %x5 = getelementptr inbounds nuw %struct.E, ptr %e, i32 0, i32 0
+// CHECK-NEXT:   %15 = load i32, ptr %x5, align 4
+// CHECK-NEXT:   %y6 = getelementptr inbounds nuw %struct.E, ptr %e, i32 0, i32 1
+// CHECK-NEXT:   %16 = load i32, ptr %y6, align 4
+// CHECK-NEXT:   %add7 = add nsw i32 %15, %16
+// CHECK-NEXT:   %17 = getelementptr inbounds nuw %class.anon, ptr %this1, i32 0, i32 1
+// CHECK-NEXT:   %18 = load ptr, ptr %17, align 8
+// CHECK-NEXT:   %19 = load i32, ptr %18, align 4
+// CHECK-NEXT:   %add8 = add nsw i32 %19, %add7
+// CHECK-NEXT:   store i32 %add8, ptr %18, align 4
+// CHECK-NEXT:   br label %expand.next9
+// CHECK: expand.next9:
+// CHECK-NEXT:   call void @_ZN1EC1Eii(ptr {{.*}} %e10, i32 {{.*}} 7, i32 {{.*}} 8)
+// CHECK-NEXT:   %x11 = getelementptr inbounds nuw %struct.E, ptr %e10, i32 0, i32 0
+// CHECK-NEXT:   %20 = load i32, ptr %x11, align 4
+// CHECK-NEXT:   %y12 = getelementptr inbounds nuw %struct.E, ptr %e10, i32 0, i32 1
+// CHECK-NEXT:   %21 = load i32, ptr %y12, align 4
+// CHECK-NEXT:   %add13 = add nsw i32 %20, %21
+// CHECK-NEXT:   %22 = getelementptr inbounds nuw %class.anon, ptr %this1, i32 0, i32 1
+// CHECK-NEXT:   %23 = load ptr, ptr %22, align 8
+// CHECK-NEXT:   %24 = load i32, ptr %23, align 4
+// CHECK-NEXT:   %add14 = add nsw i32 %24, %add13
+// CHECK-NEXT:   store i32 %add14, ptr %23, align 4
+// CHECK-NEXT:   br label %expand.end15
+// CHECK: expand.end15:
+// CHECK-NEXT:   ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZZ20unexpanded_pack_goodIJ1ES0_EEiDpT_ENKUlvE_clEv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT:   %this.addr = alloca ptr, align 8
+// CHECK-NEXT:   %0 = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x3 = alloca i32, align 4
+// CHECK-NEXT:   %e = alloca %struct.E, align 4
+// CHECK-NEXT:   %e10 = alloca %struct.E, align 4
+// CHECK-NEXT:   store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT:   %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT:   %1 = getelementptr inbounds nuw %class.anon.0, ptr %this1, i32 0, i32 0
+// CHECK-NEXT:   %2 = load ptr, ptr %1, align 8
+// CHECK-NEXT:   store ptr %2, ptr %0, align 8
+// CHECK-NEXT:   %3 = load ptr, ptr %0, align 8
+// CHECK-NEXT:   %x2 = getelementptr inbounds nuw %struct.E, ptr %3, i32 0, i32 0
+// CHECK-NEXT:   %4 = load i32, ptr %x2, align 4
+// CHECK-NEXT:   store i32 %4, ptr %x, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %6 = getelementptr inbounds nuw %class.anon.0, ptr %this1, i32 0, i32 1
+// CHECK-NEXT:   %7 = load ptr, ptr %6, align 8
+// CHECK-NEXT:   %8 = load i32, ptr %7, align 4
+// CHECK-NEXT:   %add = add nsw i32 %8, %5
+// CHECK-NEXT:   store i32 %add, ptr %7, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   %9 = load ptr, ptr %0, align 8
+// CHECK-NEXT:   %y = getelementptr inbounds nuw %struct.E, ptr %9, i32 0, i32 1
+// CHECK-NEXT:   %10 = load i32, ptr %y, align 4
+// CHECK-NEXT:   store i32 %10, ptr %x3, align 4
+// CHECK-NEXT:   %11 = load i32, ptr %x3, align 4
+// CHECK-NEXT:   %12 = getelementptr inbounds nuw %class.anon.0, ptr %this1, i32 0, i32 1
+// CHECK-NEXT:   %13 = load ptr, ptr %12, align 8
+// CHECK-NEXT:   %14 = load i32, ptr %13, align 4
+// CHECK-NEXT:   %add4 = add nsw i32 %14, %11
+// CHECK-NEXT:   store i32 %add4, ptr %13, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   call void @_ZN1EC1Eii(ptr {{.*}} %e, i32 {{.*}} 5, i32 {{.*}} 6)
+// CHECK-NEXT:   %x5 = getelementptr inbounds nuw %struct.E, ptr %e, i32 0, i32 0
+// CHECK-NEXT:   %15 = load i32, ptr %x5, align 4
+// CHECK-NEXT:   %y6 = getelementptr inbounds nuw %struct.E, ptr %e, i32 0, i32 1
+// CHECK-NEXT:   %16 = load i32, ptr %y6, align 4
+// CHECK-NEXT:   %add7 = add nsw i32 %15, %16
+// CHECK-NEXT:   %17 = getelementptr inbounds nuw %class.anon.0, ptr %this1, i32 0, i32 1
+// CHECK-NEXT:   %18 = load ptr, ptr %17, align 8
+// CHECK-NEXT:   %19 = load i32, ptr %18, align 4
+// CHECK-NEXT:   %add8 = add nsw i32 %19, %add7
+// CHECK-NEXT:   store i32 %add8, ptr %18, align 4
+// CHECK-NEXT:   br label %expand.next9
+// CHECK: expand.next9:
+// CHECK-NEXT:   call void @_ZN1EC1Eii(ptr {{.*}} %e10, i32 {{.*}} 7, i32 {{.*}} 8)
+// CHECK-NEXT:   %x11 = getelementptr inbounds nuw %struct.E, ptr %e10, i32 0, i32 0
+// CHECK-NEXT:   %20 = load i32, ptr %x11, align 4
+// CHECK-NEXT:   %y12 = getelementptr inbounds nuw %struct.E, ptr %e10, i32 0, i32 1
+// CHECK-NEXT:   %21 = load i32, ptr %y12, align 4
+// CHECK-NEXT:   %add13 = add nsw i32 %20, %21
+// CHECK-NEXT:   %22 = getelementptr inbounds nuw %class.anon.0, ptr %this1, i32 0, i32 1
+// CHECK-NEXT:   %23 = load ptr, ptr %22, align 8
+// CHECK-NEXT:   %24 = load i32, ptr %23, align 4
+// CHECK-NEXT:   %add14 = add nsw i32 %24, %add13
+// CHECK-NEXT:   store i32 %add14, ptr %23, align 4
+// CHECK-NEXT:   br label %expand.end15
+// CHECK: expand.end15:
+// CHECK-NEXT:   ret void
diff --git a/clang/test/CodeGenCXX/cxx2c-iterating-expansion-stmt.cpp b/clang/test/CodeGenCXX/cxx2c-iterating-expansion-stmt.cpp
new file mode 100644
index 0000000000000..ad73972740749
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx2c-iterating-expansion-stmt.cpp
@@ -0,0 +1,474 @@
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+template <typename T, __SIZE_TYPE__ size>
+struct Array {
+  T data[size]{};
+  constexpr const T* begin() const { return data; }
+  constexpr const T* end() const { return data + size; }
+};
+
+int f1() {
+  static constexpr Array<int, 3> integers{1, 2, 3};
+  int sum = 0;
+  template for (auto x : integers) sum += x;
+  return sum;
+}
+
+int f2() {
+  static constexpr Array<int, 3> integers{1, 2, 3};
+  int sum = 0;
+  template for (constexpr auto x : integers) sum += x;
+  return sum;
+}
+
+int f3() {
+  static constexpr Array<int, 0> integers{};
+  int sum = 0;
+  template for (constexpr auto x : integers) {
+    static_assert(false, "not expanded");
+    sum += x;
+  }
+  return sum;
+}
+
+int f4() {
+  static constexpr Array<int, 2> a{1, 2};
+  static constexpr Array<int, 2> b{3, 4};
+  int sum = 0;
+
+  template for (auto x : a)
+    template for (auto y : b)
+      sum += x + y;
+
+  template for (constexpr auto x : a)
+    template for (constexpr auto y : b)
+      sum += x + y;
+
+  return sum;
+}
+
+struct Private {
+  static constexpr Array<int, 3> integers{1, 2, 3};
+  friend constexpr int friend_func();
+
+private:
+  constexpr const int* begin() const { return integers.begin(); }
+  constexpr const int* end() const { return integers.end(); }
+
+public:
+  static int member_func();
+};
+
+int Private::member_func() {
+  int sum = 0;
+  static constexpr Private p1;
+  template for (auto x : p1) sum += x;
+  return sum;
+}
+
+struct CustomIterator {
+  struct iterator {
+    int n;
+
+    constexpr iterator operator+(int m) const {
+      return {n + m};
+    }
+
+    constexpr int operator*() const {
+      return n;
+    }
+
+    // FIXME: Should be '!=' once we support that properly.
+    friend constexpr __PTRDIFF_TYPE__ operator-(iterator a, iterator b) {
+      return a.n - b.n;
+    }
+  };
+
+   constexpr iterator begin() const { return iterator(1); }
+   constexpr iterator end() const { return iterator(5); }
+};
+
+int custom_iterator() {
+  static constexpr CustomIterator c;
+  int sum = 0;
+  template for (auto x : c) sum += x;
+  template for (constexpr auto x : c) sum += x;
+  return sum;
+}
+
+// CHECK: @_ZZ2f1vE8integers = internal constant %struct.Array { [3 x i32] [i32 1, i32 2, i32 3] }, align 4
+// CHECK: @_ZZ2f2vE8integers = internal constant %struct.Array { [3 x i32] [i32 1, i32 2, i32 3] }, align 4
+// CHECK: @_ZZ2f3vE8integers = internal constant %struct.Array.0 zeroinitializer, align 4
+// CHECK: @_ZZ2f4vE1a = internal constant %struct.Array.1 { [2 x i32] [i32 1, i32 2] }, align 4
+// CHECK: @_ZZ2f4vE1b = internal constant %struct.Array.1 { [2 x i32] [i32 3, i32 4] }, align 4
+// CHECK: @_ZZN7Private11member_funcEvE2p1 = internal constant %struct.Private zeroinitializer, align 1
+// CHECK: @_ZN7Private8integersE = {{.*}} constant %struct.Array { [3 x i32] [i32 1, i32 2, i32 3] }, comdat, align 4
+// CHECK: @_ZZ15custom_iteratorvE1c = internal constant %struct.CustomIterator zeroinitializer, align 1
+// CHECK: @__const._Z15custom_iteratorv.__begin1 = private {{.*}} constant %"struct.CustomIterator::iterator" { i32 1 }, align 4
+// CHECK: @__const._Z15custom_iteratorv.__end1 = private {{.*}} constant %"struct.CustomIterator::iterator" { i32 5 }, align 4
+// CHECK: @__const._Z15custom_iteratorv.__begin1.1 = private {{.*}} constant %"struct.CustomIterator::iterator" { i32 1 }, align 4
+// CHECK: @__const._Z15custom_iteratorv.__end1.2 = private {{.*}} constant %"struct.CustomIterator::iterator" { i32 5 }, align 4
+
+// CHECK-LABEL: define {{.*}} i32 @_Z2f1v()
+// CHECK: entry:
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %__range1 = alloca ptr, align 8
+// CHECK-NEXT:   %__begin1 = alloca ptr, align 8
+// CHECK-NEXT:   %__end1 = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x1 = alloca i32, align 4
+// CHECK-NEXT:   %x4 = alloca i32, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK-NEXT:   store ptr @_ZZ2f1vE8integers, ptr %__range1, align 8
+// CHECK-NEXT:   store ptr @_ZZ2f1vE8integers, ptr %__begin1, align 8
+// CHECK-NEXT:   store ptr getelementptr (i8, ptr @_ZZ2f1vE8integers, i64 12), ptr %__end1, align 8
+// CHECK-NEXT:   %0 = load i32, ptr @_ZZ2f1vE8integers, align 4
+// CHECK-NEXT:   store i32 %0, ptr %x, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add = add nsw i32 %2, %1
+// CHECK-NEXT:   store i32 %add, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   %3 = load i32, ptr getelementptr inbounds (i32, ptr @_ZZ2f1vE8integers, i64 1), align 4
+// CHECK-NEXT:   store i32 %3, ptr %x1, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x1, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add2 = add nsw i32 %5, %4
+// CHECK-NEXT:   store i32 %add2, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT:   %6 = load i32, ptr getelementptr inbounds (i32, ptr @_ZZ2f1vE8integers, i64 2), align 4
+// CHECK-NEXT:   store i32 %6, ptr %x4, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %x4, align 4
+// CHECK-NEXT:   %8 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add5 = add nsw i32 %8, %7
+// CHECK-NEXT:   store i32 %add5, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   %9 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   ret i32 %9
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z2f2v()
+// CHECK: entry:
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %__range1 = alloca ptr, align 8
+// CHECK-NEXT:   %__begin1 = alloca ptr, align 8
+// CHECK-NEXT:   %__end1 = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x1 = alloca i32, align 4
+// CHECK-NEXT:   %x4 = alloca i32, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK-NEXT:   store ptr @_ZZ2f2vE8integers, ptr %__range1, align 8
+// CHECK-NEXT:   store ptr @_ZZ2f2vE8integers, ptr %__begin1, align 8
+// CHECK-NEXT:   store ptr getelementptr (i8, ptr @_ZZ2f2vE8integers, i64 12), ptr %__end1, align 8
+// CHECK-NEXT:   store i32 1, ptr %x, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add = add nsw i32 %0, 1
+// CHECK-NEXT:   store i32 %add, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   store i32 2, ptr %x1, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add2 = add nsw i32 %1, 2
+// CHECK-NEXT:   store i32 %add2, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT:   store i32 3, ptr %x4, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add5 = add nsw i32 %2, 3
+// CHECK-NEXT:   store i32 %add5, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   %3 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   ret i32 %3
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z2f3v()
+// CHECK: entry:
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %__range1 = alloca ptr, align 8
+// CHECK-NEXT:   %__begin1 = alloca ptr, align 8
+// CHECK-NEXT:   %__end1 = alloca ptr, align 8
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK-NEXT:   store ptr @_ZZ2f3vE8integers, ptr %__range1, align 8
+// CHECK-NEXT:   store ptr @_ZZ2f3vE8integers, ptr %__begin1, align 8
+// CHECK-NEXT:   store ptr @_ZZ2f3vE8integers, ptr %__end1, align 8
+// CHECK-NEXT:   %0 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   ret i32 %0
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z2f4v()
+// CHECK: entry:
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %__range1 = alloca ptr, align 8
+// CHECK-NEXT:   %__begin1 = alloca ptr, align 8
+// CHECK-NEXT:   %__end1 = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %__range2 = alloca ptr, align 8
+// CHECK-NEXT:   %__begin2 = alloca ptr, align 8
+// CHECK-NEXT:   %__end2 = alloca ptr, align 8
+// CHECK-NEXT:   %y = alloca i32, align 4
+// CHECK-NEXT:   %y2 = alloca i32, align 4
+// CHECK-NEXT:   %x6 = alloca i32, align 4
+// CHECK-NEXT:   %__range27 = alloca ptr, align 8
+// CHECK-NEXT:   %__begin28 = alloca ptr, align 8
+// CHECK-NEXT:   %__end29 = alloca ptr, align 8
+// CHECK-NEXT:   %y10 = alloca i32, align 4
+// CHECK-NEXT:   %y14 = alloca i32, align 4
+// CHECK-NEXT:   %__range119 = alloca ptr, align 8
+// CHECK-NEXT:   %__begin120 = alloca ptr, align 8
+// CHECK-NEXT:   %__end121 = alloca ptr, align 8
+// CHECK-NEXT:   %x22 = alloca i32, align 4
+// CHECK-NEXT:   %__range223 = alloca ptr, align 8
+// CHECK-NEXT:   %__begin224 = alloca ptr, align 8
+// CHECK-NEXT:   %__end225 = alloca ptr, align 8
+// CHECK-NEXT:   %y26 = alloca i32, align 4
+// CHECK-NEXT:   %y29 = alloca i32, align 4
+// CHECK-NEXT:   %x33 = alloca i32, align 4
+// CHECK-NEXT:   %__range234 = alloca ptr, align 8
+// CHECK-NEXT:   %__begin235 = alloca ptr, align 8
+// CHECK-NEXT:   %__end236 = alloca ptr, align 8
+// CHECK-NEXT:   %y37 = alloca i32, align 4
+// CHECK-NEXT:   %y40 = alloca i32, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK-NEXT:   store ptr @_ZZ2f4vE1a, ptr %__range1, align 8
+// CHECK-NEXT:   store ptr @_ZZ2f4vE1a, ptr %__begin1, align 8
+// CHECK-NEXT:   store ptr getelementptr (i8, ptr @_ZZ2f4vE1a, i64 8), ptr %__end1, align 8
+// CHECK-NEXT:   %0 = load i32, ptr @_ZZ2f4vE1a, align 4
+// CHECK-NEXT:   store i32 %0, ptr %x, align 4
+// CHECK-NEXT:   store ptr @_ZZ2f4vE1b, ptr %__range2, align 8
+// CHECK-NEXT:   store ptr @_ZZ2f4vE1b, ptr %__begin2, align 8
+// CHECK-NEXT:   store ptr getelementptr (i8, ptr @_ZZ2f4vE1b, i64 8), ptr %__end2, align 8
+// CHECK-NEXT:   %1 = load i32, ptr @_ZZ2f4vE1b, align 4
+// CHECK-NEXT:   store i32 %1, ptr %y, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %y, align 4
+// CHECK-NEXT:   %add = add nsw i32 %2, %3
+// CHECK-NEXT:   %4 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add1 = add nsw i32 %4, %add
+// CHECK-NEXT:   store i32 %add1, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   %5 = load i32, ptr getelementptr inbounds (i32, ptr @_ZZ2f4vE1b, i64 1), align 4
+// CHECK-NEXT:   store i32 %5, ptr %y2, align 4
+// CHECK-NEXT:   %6 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %y2, align 4
+// CHECK-NEXT:   %add3 = add nsw i32 %6, %7
+// CHECK-NEXT:   %8 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add4 = add nsw i32 %8, %add3
+// CHECK-NEXT:   store i32 %add4, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   br label %expand.next5
+// CHECK: expand.next5:
+// CHECK-NEXT:   %9 = load i32, ptr getelementptr inbounds (i32, ptr @_ZZ2f4vE1a, i64 1), align 4
+// CHECK-NEXT:   store i32 %9, ptr %x6, align 4
+// CHECK-NEXT:   store ptr @_ZZ2f4vE1b, ptr %__range27, align 8
+// CHECK-NEXT:   store ptr @_ZZ2f4vE1b, ptr %__begin28, align 8
+// CHECK-NEXT:   store ptr getelementptr (i8, ptr @_ZZ2f4vE1b, i64 8), ptr %__end29, align 8
+// CHECK-NEXT:   %10 = load i32, ptr @_ZZ2f4vE1b, align 4
+// CHECK-NEXT:   store i32 %10, ptr %y10, align 4
+// CHECK-NEXT:   %11 = load i32, ptr %x6, align 4
+// CHECK-NEXT:   %12 = load i32, ptr %y10, align 4
+// CHECK-NEXT:   %add11 = add nsw i32 %11, %12
+// CHECK-NEXT:   %13 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add12 = add nsw i32 %13, %add11
+// CHECK-NEXT:   store i32 %add12, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next13
+// CHECK: expand.next13:
+// CHECK-NEXT:   %14 = load i32, ptr getelementptr inbounds (i32, ptr @_ZZ2f4vE1b, i64 1), align 4
+// CHECK-NEXT:   store i32 %14, ptr %y14, align 4
+// CHECK-NEXT:   %15 = load i32, ptr %x6, align 4
+// CHECK-NEXT:   %16 = load i32, ptr %y14, align 4
+// CHECK-NEXT:   %add15 = add nsw i32 %15, %16
+// CHECK-NEXT:   %17 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add16 = add nsw i32 %17, %add15
+// CHECK-NEXT:   store i32 %add16, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end17
+// CHECK: expand.end17:
+// CHECK-NEXT:   br label %expand.end18
+// CHECK: expand.end18:
+// CHECK-NEXT:   store ptr @_ZZ2f4vE1a, ptr %__range119, align 8
+// CHECK-NEXT:   store ptr @_ZZ2f4vE1a, ptr %__begin120, align 8
+// CHECK-NEXT:   store ptr getelementptr (i8, ptr @_ZZ2f4vE1a, i64 8), ptr %__end121, align 8
+// CHECK-NEXT:   store i32 1, ptr %x22, align 4
+// CHECK-NEXT:   store ptr @_ZZ2f4vE1b, ptr %__range223, align 8
+// CHECK-NEXT:   store ptr @_ZZ2f4vE1b, ptr %__begin224, align 8
+// CHECK-NEXT:   store ptr getelementptr (i8, ptr @_ZZ2f4vE1b, i64 8), ptr %__end225, align 8
+// CHECK-NEXT:   store i32 3, ptr %y26, align 4
+// CHECK-NEXT:   %18 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add27 = add nsw i32 %18, 4
+// CHECK-NEXT:   store i32 %add27, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next28
+// CHECK: expand.next28:
+// CHECK-NEXT:   store i32 4, ptr %y29, align 4
+// CHECK-NEXT:   %19 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add30 = add nsw i32 %19, 5
+// CHECK-NEXT:   store i32 %add30, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end31
+// CHECK: expand.end31:
+// CHECK-NEXT:   br label %expand.next32
+// CHECK: expand.next32:
+// CHECK-NEXT:   store i32 2, ptr %x33, align 4
+// CHECK-NEXT:   store ptr @_ZZ2f4vE1b, ptr %__range234, align 8
+// CHECK-NEXT:   store ptr @_ZZ2f4vE1b, ptr %__begin235, align 8
+// CHECK-NEXT:   store ptr getelementptr (i8, ptr @_ZZ2f4vE1b, i64 8), ptr %__end236, align 8
+// CHECK-NEXT:   store i32 3, ptr %y37, align 4
+// CHECK-NEXT:   %20 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add38 = add nsw i32 %20, 5
+// CHECK-NEXT:   store i32 %add38, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next39
+// CHECK: expand.next39:
+// CHECK-NEXT:   store i32 4, ptr %y40, align 4
+// CHECK-NEXT:   %21 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add41 = add nsw i32 %21, 6
+// CHECK-NEXT:   store i32 %add41, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end42
+// CHECK: expand.end42:
+// CHECK-NEXT:   br label %expand.end43
+// CHECK: expand.end43:
+// CHECK-NEXT:   %22 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   ret i32 %22
+
+
+// CHECK-LABEL: define {{.*}} i32 @_ZN7Private11member_funcEv()
+// CHECK: entry:
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %__range1 = alloca ptr, align 8
+// CHECK-NEXT:   %__begin1 = alloca ptr, align 8
+// CHECK-NEXT:   %__end1 = alloca ptr, align 8
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK-NEXT:   %x1 = alloca i32, align 4
+// CHECK-NEXT:   %x4 = alloca i32, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK-NEXT:   store ptr @_ZZN7Private11member_funcEvE2p1, ptr %__range1, align 8
+// CHECK-NEXT:   store ptr @_ZN7Private8integersE, ptr %__begin1, align 8
+// CHECK-NEXT:   store ptr getelementptr (i8, ptr @_ZN7Private8integersE, i64 12), ptr %__end1, align 8
+// CHECK-NEXT:   %0 = load i32, ptr @_ZN7Private8integersE, align 4
+// CHECK-NEXT:   store i32 %0, ptr %x, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add = add nsw i32 %2, %1
+// CHECK-NEXT:   store i32 %add, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   %3 = load i32, ptr getelementptr inbounds (i32, ptr @_ZN7Private8integersE, i64 1), align 4
+// CHECK-NEXT:   store i32 %3, ptr %x1, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x1, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add2 = add nsw i32 %5, %4
+// CHECK-NEXT:   store i32 %add2, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT:   %6 = load i32, ptr getelementptr inbounds (i32, ptr @_ZN7Private8integersE, i64 2), align 4
+// CHECK-NEXT:   store i32 %6, ptr %x4, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %x4, align 4
+// CHECK-NEXT:   %8 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add5 = add nsw i32 %8, %7
+// CHECK-NEXT:   store i32 %add5, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   %9 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   ret i32 %9
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z15custom_iteratorv()
+// CHECK: entry:
+// CHECK-NEXT:   %sum = alloca i32, align 4
+// CHECK-NEXT:   %__range1 = alloca ptr, align 8
+// CHECK: %__begin1 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK: %__end1 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK-NEXT:   %x = alloca i32, align 4
+// CHECK: %ref.tmp = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK-NEXT:   %x2 = alloca i32, align 4
+// CHECK: %ref.tmp3 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK-NEXT:   %x9 = alloca i32, align 4
+// CHECK: %ref.tmp10 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK-NEXT:   %x16 = alloca i32, align 4
+// CHECK: %ref.tmp17 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK-NEXT:   %__range122 = alloca ptr, align 8
+// CHECK: %__begin123 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK: %__end124 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK-NEXT:   %x25 = alloca i32, align 4
+// CHECK-NEXT:   %x28 = alloca i32, align 4
+// CHECK-NEXT:   %x31 = alloca i32, align 4
+// CHECK-NEXT:   %x34 = alloca i32, align 4
+// CHECK-NEXT:   store i32 0, ptr %sum, align 4
+// CHECK-NEXT:   store ptr @_ZZ15custom_iteratorvE1c, ptr %__range1, align 8
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %__begin1, ptr align 4 @__const._Z15custom_iteratorv.__begin1, i64 4, i1 false)
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %__end1, ptr align 4 @__const._Z15custom_iteratorv.__end1, i64 4, i1 false)
+// CHECK-NEXT:   %call = call i32 @_ZNK14CustomIterator8iteratorplEi(ptr {{.*}} %__begin1, i32 {{.*}} 0)
+// CHECK: %coerce.dive = getelementptr inbounds nuw %"struct.CustomIterator::iterator", ptr %ref.tmp, i32 0, i32 0
+// CHECK-NEXT:   store i32 %call, ptr %coerce.dive, align 4
+// CHECK-NEXT:   %call1 = call {{.*}} i32 @_ZNK14CustomIterator8iteratordeEv(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT:   store i32 %call1, ptr %x, align 4
+// CHECK-NEXT:   %0 = load i32, ptr %x, align 4
+// CHECK-NEXT:   %1 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add = add nsw i32 %1, %0
+// CHECK-NEXT:   store i32 %add, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT:   %call4 = call i32 @_ZNK14CustomIterator8iteratorplEi(ptr {{.*}} %__begin1, i32 {{.*}} 1)
+// CHECK: %coerce.dive5 = getelementptr inbounds nuw %"struct.CustomIterator::iterator", ptr %ref.tmp3, i32 0, i32 0
+// CHECK-NEXT:   store i32 %call4, ptr %coerce.dive5, align 4
+// CHECK-NEXT:   %call6 = call {{.*}} i32 @_ZNK14CustomIterator8iteratordeEv(ptr {{.*}} %ref.tmp3)
+// CHECK-NEXT:   store i32 %call6, ptr %x2, align 4
+// CHECK-NEXT:   %2 = load i32, ptr %x2, align 4
+// CHECK-NEXT:   %3 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add7 = add nsw i32 %3, %2
+// CHECK-NEXT:   store i32 %add7, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT:   %call11 = call i32 @_ZNK14CustomIterator8iteratorplEi(ptr {{.*}} %__begin1, i32 {{.*}} 2)
+// CHECK: %coerce.dive12 = getelementptr inbounds nuw %"struct.CustomIterator::iterator", ptr %ref.tmp10, i32 0, i32 0
+// CHECK-NEXT:   store i32 %call11, ptr %coerce.dive12, align 4
+// CHECK-NEXT:   %call13 = call {{.*}} i32 @_ZNK14CustomIterator8iteratordeEv(ptr {{.*}} %ref.tmp10)
+// CHECK-NEXT:   store i32 %call13, ptr %x9, align 4
+// CHECK-NEXT:   %4 = load i32, ptr %x9, align 4
+// CHECK-NEXT:   %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add14 = add nsw i32 %5, %4
+// CHECK-NEXT:   store i32 %add14, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next15
+// CHECK: expand.next15:
+// CHECK-NEXT:   %call18 = call i32 @_ZNK14CustomIterator8iteratorplEi(ptr {{.*}} %__begin1, i32 {{.*}} 3)
+// CHECK: %coerce.dive19 = getelementptr inbounds nuw %"struct.CustomIterator::iterator", ptr %ref.tmp17, i32 0, i32 0
+// CHECK-NEXT:   store i32 %call18, ptr %coerce.dive19, align 4
+// CHECK-NEXT:   %call20 = call {{.*}} i32 @_ZNK14CustomIterator8iteratordeEv(ptr {{.*}} %ref.tmp17)
+// CHECK-NEXT:   store i32 %call20, ptr %x16, align 4
+// CHECK-NEXT:   %6 = load i32, ptr %x16, align 4
+// CHECK-NEXT:   %7 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add21 = add nsw i32 %7, %6
+// CHECK-NEXT:   store i32 %add21, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT:   store ptr @_ZZ15custom_iteratorvE1c, ptr %__range122, align 8
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %__begin123, ptr align 4 @__const._Z15custom_iteratorv.__begin1.1, i64 4, i1 false)
+// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %__end124, ptr align 4 @__const._Z15custom_iteratorv.__end1.2, i64 4, i1 false)
+// CHECK-NEXT:   store i32 1, ptr %x25, align 4
+// CHECK-NEXT:   %8 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add26 = add nsw i32 %8, 1
+// CHECK-NEXT:   store i32 %add26, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next27
+// CHECK: expand.next27:
+// CHECK-NEXT:   store i32 2, ptr %x28, align 4
+// CHECK-NEXT:   %9 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add29 = add nsw i32 %9, 2
+// CHECK-NEXT:   store i32 %add29, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next30
+// CHECK: expand.next30:
+// CHECK-NEXT:   store i32 3, ptr %x31, align 4
+// CHECK-NEXT:   %10 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add32 = add nsw i32 %10, 3
+// CHECK-NEXT:   store i32 %add32, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.next33
+// CHECK: expand.next33:
+// CHECK-NEXT:   store i32 4, ptr %x34, align 4
+// CHECK-NEXT:   %11 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   %add35 = add nsw i32 %11, 4
+// CHECK-NEXT:   store i32 %add35, ptr %sum, align 4
+// CHECK-NEXT:   br label %expand.end36
+// CHECK: expand.end36:
+// CHECK-NEXT:   %12 = load i32, ptr %sum, align 4
+// CHECK-NEXT:   ret i32 %12

>From 89aec47918738f83b6c0a3f8b6e3ae6c4b5b97e6 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 26 Nov 2025 19:04:08 +0100
Subject: [PATCH 2/2] Move CGDecl implementation here

---
 clang/lib/CodeGen/CGDecl.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 7c96e38908267..678d2e9fa743a 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -143,8 +143,12 @@ void CodeGenFunction::EmitDecl(const Decl &D, bool EvaluateConditionDecl) {
     // None of these decls require codegen support.
     return;
 
-  case Decl::CXXExpansionStmt:
-    llvm_unreachable("TODO");
+  case Decl::CXXExpansionStmt: {
+    const auto *ESD = cast<CXXExpansionStmtDecl>(&D);
+    assert(ESD->getInstantiations() && "expansion statement not expanded?");
+    EmitStmt(ESD->getInstantiations());
+    return;
+  }
 
   case Decl::NamespaceAlias:
     if (CGDebugInfo *DI = getDebugInfo())



More information about the llvm-branch-commits mailing list