https://github.com/Takashiidobe updated 
https://github.com/llvm/llvm-project/pull/186594

>From 60e7856e41ec089ee744263575c64336f6b0c533 Mon Sep 17 00:00:00 2001
From: Takashiidobe <[email protected]>
Date: Sat, 14 Mar 2026 09:43:44 -0400
Subject: [PATCH 1/5] allow C++26 constexpr structured pack bindings to be
 emitted as constants

---
 clang/lib/CodeGen/CGExpr.cpp | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 23802cdeb4811..aa9411cff654e 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1942,6 +1942,17 @@ CodeGenFunction::tryEmitAsConstant(const DeclRefExpr 
*RefExpr) {
     CEK = checkVarTypeForConstantEmission(var->getType());
   } else if (isa<EnumConstantDecl>(Value)) {
     CEK = CEK_AsValueOnly;
+  } else if (const auto *BD = dyn_cast<BindingDecl>(Value)) {
+    // For structured binding elements from tuple-like decompositions, the
+    // binding is backed by a hidden holding variable (the "reference
+    // temporary"). Use the holding variable's type to decide whether we
+    // can constant-emit. Without this, static constexpr pack bindings used
+    // as array indices always materialise as loads from their reference-
+    // temporary globals, blocking constant folding and vectorisation.
+    if (VarDecl *HV = BD->getHoldingVar())
+      CEK = checkVarTypeForConstantEmission(HV->getType());
+    else
+      CEK = CEK_None;
   } else {
     CEK = CEK_None;
   }
@@ -2003,6 +2014,16 @@ CodeGenFunction::tryEmitAsConstant(const DeclRefExpr 
*RefExpr) {
   if (isa<VarDecl>(Value)) {
     if (!getContext().DeclMustBeEmitted(cast<VarDecl>(Value)))
       EmitDeclRefExprDbgValue(RefExpr, result.Val);
+  } else if (const auto *BD = dyn_cast<BindingDecl>(Value)) {
+    // For tuple-like structured binding elements, the holding variable is
+    // always emitted (static storage), so only emit a debug reference if
+    // it is not otherwise required to be emitted.
+    if (VarDecl *HV = BD->getHoldingVar()) {
+      if (!getContext().DeclMustBeEmitted(HV))
+        EmitDeclRefExprDbgValue(RefExpr, result.Val);
+    } else {
+      EmitDeclRefExprDbgValue(RefExpr, result.Val);
+    }
   } else {
     assert(isa<EnumConstantDecl>(Value));
     EmitDeclRefExprDbgValue(RefExpr, result.Val);

>From 34ef1db8f571117678b697355b4c48e128f3894a Mon Sep 17 00:00:00 2001
From: Takashiidobe <[email protected]>
Date: Sat, 14 Mar 2026 09:43:54 -0400
Subject: [PATCH 2/5] add test from issue

---
 ...cpp26-constexpr-binding-pack-subscript.cpp | 52 +++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 
clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp

diff --git a/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp 
b/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp
new file mode 100644
index 0000000000000..3f7a02a78717e
--- /dev/null
+++ b/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang -std=c++26 -O3 -emit-llvm -S -target x86_64-unknown-linux-gnu 
-o - %s | FileCheck %s
+// RUN: %clang -std=c++26 -emit-llvm -S -target x86_64-unknown-linux-gnu -o - 
%s | FileCheck %s --check-prefix=IR
+// UNSUPPORTED: system-windows
+
+// static constexpr structured binding pack elements used as array
+// subscript indices must be constant-folded at the Clang codegen level.
+// Without the fix, each element is emitted as a load from a "reference
+// temporary" static variable, preventing vectorisation at -O3.
+
+#include <array>
+#include <cstdint>
+
+using u8 = std::uint8_t;
+
+template <u8 N>
+struct Range {
+  template <std::size_t I>
+  consteval friend u8 get(Range) noexcept { return I; }
+};
+namespace std {
+       template <u8 N>
+       struct tuple_size<Range<N>> { static constexpr std::size_t value = N; };
+       template <std::size_t I, u8 N>
+       struct tuple_element<I, Range<N>> { using type = u8; };
+} // namespace std
+
+template <std::size_t L, std::size_t R>
+__attribute__((always_inline)) inline constexpr std::array<u8, L + R>
+concat(const std::array<u8, L> &l, const std::array<u8, R> &r) {
+  static constexpr auto [...I] = Range<L>{};
+  static constexpr auto [...J] = Range<R>{};
+  return {l[I]..., r[J]...};
+}
+
+auto test(const std::array<u8, 16> &l, const std::array<u8, 16> &r) {
+  return concat(l, r);
+}
+
+// At -O3 the two 16-byte arrays should be copied with a pair of vector
+// loads/stores; no scalar byte loop and no reference-temporary indirection.
+// CHECK-LABEL: define {{.*}} @{{.*test.*}}
+// CHECK-NOT:   reference temporary
+// CHECK:       load <16 x i8>
+// CHECK:       store <16 x i8>
+// CHECK:       load <16 x i8>
+// CHECK:       store <16 x i8>
+// CHECK:       ret void
+
+// At any optimisation level the binding-pack indices must not be materialised
+// as "reference temporary" static variables.
+// IR-LABEL: define {{.*}} @{{.*test.*}}
+// IR-NOT:   reference temporary

>From dc87ac57f932d6350c648d01f77cf76f6dd20437 Mon Sep 17 00:00:00 2001
From: Takashiidobe <[email protected]>
Date: Mon, 16 Mar 2026 21:45:52 -0400
Subject: [PATCH 3/5] code review feedback

---
 clang/lib/CodeGen/CGExpr.cpp                  | 24 ++++-----
 ...cpp26-constexpr-binding-pack-subscript.cpp | 52 +++++++++----------
 2 files changed, 35 insertions(+), 41 deletions(-)

diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index aa9411cff654e..a82b30f65cc32 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1935,11 +1935,15 @@ CodeGenFunction::tryEmitAsConstant(const DeclRefExpr 
*RefExpr) {
   const ValueDecl *Value = RefExpr->getDecl();
 
   // The value needs to be an enum constant or a constant variable.
+  // For BindingDecls backed by a holding variable, UnderlyingVar points to
+  // that holding variable and is used below for debug-value emission.
   ConstantEmissionKind CEK;
+  const VarDecl *UnderlyingVar = nullptr;
   if (isa<ParmVarDecl>(Value)) {
     CEK = CEK_None;
   } else if (const auto *var = dyn_cast<VarDecl>(Value)) {
     CEK = checkVarTypeForConstantEmission(var->getType());
+    UnderlyingVar = var;
   } else if (isa<EnumConstantDecl>(Value)) {
     CEK = CEK_AsValueOnly;
   } else if (const auto *BD = dyn_cast<BindingDecl>(Value)) {
@@ -1949,10 +1953,12 @@ CodeGenFunction::tryEmitAsConstant(const DeclRefExpr 
*RefExpr) {
     // can constant-emit. Without this, static constexpr pack bindings used
     // as array indices always materialise as loads from their reference-
     // temporary globals, blocking constant folding and vectorisation.
-    if (VarDecl *HV = BD->getHoldingVar())
+    if (VarDecl *HV = BD->getHoldingVar()) {
       CEK = checkVarTypeForConstantEmission(HV->getType());
-    else
+      UnderlyingVar = HV;
+    } else {
       CEK = CEK_None;
+    }
   } else {
     CEK = CEK_None;
   }
@@ -2011,19 +2017,9 @@ CodeGenFunction::tryEmitAsConstant(const DeclRefExpr 
*RefExpr) {
 
   // Make sure we emit a debug reference to the global variable.
   // This should probably fire even for
-  if (isa<VarDecl>(Value)) {
-    if (!getContext().DeclMustBeEmitted(cast<VarDecl>(Value)))
+  if (UnderlyingVar) {
+    if (!getContext().DeclMustBeEmitted(UnderlyingVar))
       EmitDeclRefExprDbgValue(RefExpr, result.Val);
-  } else if (const auto *BD = dyn_cast<BindingDecl>(Value)) {
-    // For tuple-like structured binding elements, the holding variable is
-    // always emitted (static storage), so only emit a debug reference if
-    // it is not otherwise required to be emitted.
-    if (VarDecl *HV = BD->getHoldingVar()) {
-      if (!getContext().DeclMustBeEmitted(HV))
-        EmitDeclRefExprDbgValue(RefExpr, result.Val);
-    } else {
-      EmitDeclRefExprDbgValue(RefExpr, result.Val);
-    }
   } else {
     assert(isa<EnumConstantDecl>(Value));
     EmitDeclRefExprDbgValue(RefExpr, result.Val);
diff --git a/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp 
b/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp
index 3f7a02a78717e..cd47a03dc3483 100644
--- a/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp
+++ b/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp
@@ -1,52 +1,50 @@
-// RUN: %clang -std=c++26 -O3 -emit-llvm -S -target x86_64-unknown-linux-gnu 
-o - %s | FileCheck %s
-// RUN: %clang -std=c++26 -emit-llvm -S -target x86_64-unknown-linux-gnu -o - 
%s | FileCheck %s --check-prefix=IR
-// UNSUPPORTED: system-windows
+// RUN: %clang_cc1 -std=c++26 -triple x86_64-linux-gnu -emit-llvm -o - %s | 
FileCheck %s
 
 // static constexpr structured binding pack elements used as array
 // subscript indices must be constant-folded at the Clang codegen level.
 // Without the fix, each element is emitted as a load from a "reference
-// temporary" static variable, preventing vectorisation at -O3.
+// temporary" static variable.
 
-#include <array>
-#include <cstdint>
+namespace std {
+  using size_t = decltype(sizeof(0));
+  template <typename T> struct tuple_size;
+  template <size_t I, typename T> struct tuple_element;
+} // namespace std
 
-using u8 = std::uint8_t;
+using u8 = unsigned char;
 
 template <u8 N>
 struct Range {
   template <std::size_t I>
   consteval friend u8 get(Range) noexcept { return I; }
 };
+
 namespace std {
-       template <u8 N>
-       struct tuple_size<Range<N>> { static constexpr std::size_t value = N; };
-       template <std::size_t I, u8 N>
-       struct tuple_element<I, Range<N>> { using type = u8; };
+  template <u8 N>
+  struct tuple_size<Range<N>> { static constexpr std::size_t value = N; };
+  template <std::size_t I, u8 N>
+  struct tuple_element<I, Range<N>> { using type = u8; };
 } // namespace std
 
+template <std::size_t N>
+struct Array {
+  u8 data[N];
+  constexpr const u8 &operator[](std::size_t i) const { return data[i]; }
+};
+
 template <std::size_t L, std::size_t R>
-__attribute__((always_inline)) inline constexpr std::array<u8, L + R>
-concat(const std::array<u8, L> &l, const std::array<u8, R> &r) {
+__attribute__((always_inline)) inline constexpr Array<L + R>
+concat(const Array<L> &l, const Array<R> &r) {
   static constexpr auto [...I] = Range<L>{};
   static constexpr auto [...J] = Range<R>{};
-  return {l[I]..., r[J]...};
+  return {{l[I]..., r[J]...}};
 }
 
-auto test(const std::array<u8, 16> &l, const std::array<u8, 16> &r) {
+Array<32> test(const Array<16> &l, const Array<16> &r) {
   return concat(l, r);
 }
 
-// At -O3 the two 16-byte arrays should be copied with a pair of vector
-// loads/stores; no scalar byte loop and no reference-temporary indirection.
+// The binding-pack indices must not be materialised as "reference temporary"
+// static variables at any optimisation level.
 // CHECK-LABEL: define {{.*}} @{{.*test.*}}
 // CHECK-NOT:   reference temporary
-// CHECK:       load <16 x i8>
-// CHECK:       store <16 x i8>
-// CHECK:       load <16 x i8>
-// CHECK:       store <16 x i8>
-// CHECK:       ret void
-
-// At any optimisation level the binding-pack indices must not be materialised
-// as "reference temporary" static variables.
-// IR-LABEL: define {{.*}} @{{.*test.*}}
-// IR-NOT:   reference temporary

>From 70997ba1cdefdc4cc415f04eaff9c9a549dc3574 Mon Sep 17 00:00:00 2001
From: Takashiidobe <[email protected]>
Date: Tue, 17 Mar 2026 22:04:09 -0400
Subject: [PATCH 4/5] fix test by adding cv-qualified tuple protocol forwarding
 to trigger constexpr pack decomposition

---
 ...cpp26-constexpr-binding-pack-subscript.cpp | 53 ++++++++++---------
 1 file changed, 29 insertions(+), 24 deletions(-)

diff --git a/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp 
b/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp
index cd47a03dc3483..fdc6e9fb36e93 100644
--- a/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp
+++ b/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp
@@ -1,50 +1,55 @@
-// RUN: %clang_cc1 -std=c++26 -triple x86_64-linux-gnu -emit-llvm -o - %s | 
FileCheck %s
+// RUN: %clang_cc1 -std=c++26 -O2 -triple x86_64-linux-gnu -emit-llvm -o - %s 
| FileCheck %s
 
-// static constexpr structured binding pack elements used as array
-// subscript indices must be constant-folded at the Clang codegen level.
-// Without the fix, each element is emitted as a load from a "reference
-// temporary" static variable.
+// static constexpr structured binding pack elements used as array subscript 
+// indices must be constant-folded at the Clang codegen level. Without the 
fix, 
+// each element is emitted as a load from a reference temporary static 
variable.
 
 namespace std {
-  using size_t = decltype(sizeof(0));
-  template <typename T> struct tuple_size;
-  template <size_t I, typename T> struct tuple_element;
+       using size_t = decltype(sizeof(0));
+       template <typename T> struct tuple_size;
+       template <size_t I, typename T> struct tuple_element;
+
+       template <typename T> struct tuple_size<const T> : tuple_size<T> {};
+
+       template <size_t I, typename T>
+               struct tuple_element<I, const T> {
+                       using type = const typename tuple_element<I, T>::type;
+               };
 } // namespace std
 
 using u8 = unsigned char;
 
 template <u8 N>
 struct Range {
-  template <std::size_t I>
-  consteval friend u8 get(Range) noexcept { return I; }
+       template <std::size_t I>
+               consteval friend u8 get(Range) noexcept { return I; }
 };
 
 namespace std {
-  template <u8 N>
-  struct tuple_size<Range<N>> { static constexpr std::size_t value = N; };
-  template <std::size_t I, u8 N>
-  struct tuple_element<I, Range<N>> { using type = u8; };
+       template <u8 N>
+               struct tuple_size<Range<N>> { static constexpr std::size_t 
value = N; };
+       template <std::size_t I, u8 N>
+               struct tuple_element<I, Range<N>> { using type = u8; };
 } // namespace std
 
 template <std::size_t N>
 struct Array {
-  u8 data[N];
-  constexpr const u8 &operator[](std::size_t i) const { return data[i]; }
+       u8 data[N];
+       const u8 &operator[](std::size_t i) const { return data[i]; }
 };
 
 template <std::size_t L, std::size_t R>
-__attribute__((always_inline)) inline constexpr Array<L + R>
-concat(const Array<L> &l, const Array<R> &r) {
-  static constexpr auto [...I] = Range<L>{};
-  static constexpr auto [...J] = Range<R>{};
-  return {{l[I]..., r[J]...}};
+Array<L + R> concat(const Array<L> &l, const Array<R> &r) {
+       static constexpr auto [...I] = Range<L>{};
+       static constexpr auto [...J] = Range<R>{};
+       return {{l[I]..., r[J]...}};
 }
 
 Array<32> test(const Array<16> &l, const Array<16> &r) {
-  return concat(l, r);
+       return concat(l, r);
 }
 
-// The binding-pack indices must not be materialised as "reference temporary"
+// The binding-pack indices must not be materialised as reference-temporary
 // static variables at any optimisation level.
 // CHECK-LABEL: define {{.*}} @{{.*test.*}}
-// CHECK-NOT:   reference temporary
+// CHECK-NOT:   @_ZGR

>From 2f4e79e7f8572a05dffea6a990aaff42706770f8 Mon Sep 17 00:00:00 2001
From: Takashiidobe <[email protected]>
Date: Wed, 18 Mar 2026 19:36:35 -0400
Subject: [PATCH 5/5] fix constexpr codegen problem in CodeGenModule instead.
 Keep the CV-qualifiers from the MaterializeTemporaryExpr which can be used to
 generate better code in a const context

---
 clang/lib/CodeGen/CGExpr.cpp                  | 21 +------
 clang/lib/CodeGen/CodeGenModule.cpp           | 11 ++--
 ...egen-for-constexpr-structured-bindings.cpp | 40 ++++++++++++++
 clang/test/CodeGenCXX/const-init-cxx11.cpp    |  3 +-
 ...cpp26-constexpr-binding-pack-subscript.cpp | 55 -------------------
 clang/test/CodeGenCXX/temporaries.cpp         |  5 +-
 6 files changed, 51 insertions(+), 84 deletions(-)
 create mode 100644 
clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp
 delete mode 100644 
clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp

diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index a82b30f65cc32..23802cdeb4811 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1935,30 +1935,13 @@ CodeGenFunction::tryEmitAsConstant(const DeclRefExpr 
*RefExpr) {
   const ValueDecl *Value = RefExpr->getDecl();
 
   // The value needs to be an enum constant or a constant variable.
-  // For BindingDecls backed by a holding variable, UnderlyingVar points to
-  // that holding variable and is used below for debug-value emission.
   ConstantEmissionKind CEK;
-  const VarDecl *UnderlyingVar = nullptr;
   if (isa<ParmVarDecl>(Value)) {
     CEK = CEK_None;
   } else if (const auto *var = dyn_cast<VarDecl>(Value)) {
     CEK = checkVarTypeForConstantEmission(var->getType());
-    UnderlyingVar = var;
   } else if (isa<EnumConstantDecl>(Value)) {
     CEK = CEK_AsValueOnly;
-  } else if (const auto *BD = dyn_cast<BindingDecl>(Value)) {
-    // For structured binding elements from tuple-like decompositions, the
-    // binding is backed by a hidden holding variable (the "reference
-    // temporary"). Use the holding variable's type to decide whether we
-    // can constant-emit. Without this, static constexpr pack bindings used
-    // as array indices always materialise as loads from their reference-
-    // temporary globals, blocking constant folding and vectorisation.
-    if (VarDecl *HV = BD->getHoldingVar()) {
-      CEK = checkVarTypeForConstantEmission(HV->getType());
-      UnderlyingVar = HV;
-    } else {
-      CEK = CEK_None;
-    }
   } else {
     CEK = CEK_None;
   }
@@ -2017,8 +2000,8 @@ CodeGenFunction::tryEmitAsConstant(const DeclRefExpr 
*RefExpr) {
 
   // Make sure we emit a debug reference to the global variable.
   // This should probably fire even for
-  if (UnderlyingVar) {
-    if (!getContext().DeclMustBeEmitted(UnderlyingVar))
+  if (isa<VarDecl>(Value)) {
+    if (!getContext().DeclMustBeEmitted(cast<VarDecl>(Value)))
       EmitDeclRefExprDbgValue(RefExpr, result.Val);
   } else {
     assert(isa<EnumConstantDecl>(Value));
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index daaa846bf42bc..256db38233c0e 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -7357,11 +7357,12 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
           E->getStorageDuration() == SD_Thread) && "not a global temporary");
   const auto *VD = cast<VarDecl>(E->getExtendingDecl());
 
-  // If we're not materializing a subobject of the temporary, keep the
-  // cv-qualifiers from the type of the MaterializeTemporaryExpr.
-  QualType MaterializedType = Init->getType();
-  if (Init == E->getSubExpr())
-    MaterializedType = E->getType();
+  // Keep cv-qualifiers from the MaterializeTemporaryExpr on the storage type.
+  // The initializer expression may have had rvalue subobject adjustments
+  // stripped, which can drop top-level qualifiers that are still part of the
+  // materialized temporary's type.
+  QualType MaterializedType = getContext().getQualifiedType(
+      Init->getType(), E->getType().getQualifiers());
 
   CharUnits Align = getContext().getTypeAlignInChars(MaterializedType);
 
diff --git 
a/clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp 
b/clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp
new file mode 100644
index 0000000000000..ec4e4a2acd644
--- /dev/null
+++ b/clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -emit-llvm -o - %s | 
FileCheck %s
+
+namespace std {
+using size_t = decltype(sizeof(0));
+template <typename T> struct tuple_size;
+template <size_t I, typename T> struct tuple_element;
+
+template <typename T> struct tuple_size<const T> : tuple_size<T> {};
+
+template <size_t I, typename T> struct tuple_element<I, const T> {
+  using type = const typename tuple_element<I, T>::type;
+};
+} // namespace std
+
+using u8 = unsigned char;
+
+template <u8 N> struct Range {
+  template <std::size_t I>
+  constexpr friend u8 get(Range) noexcept {
+    return I;
+  }
+};
+
+namespace std {
+template <u8 N> struct tuple_size<Range<N>> {
+  static constexpr std::size_t value = N;
+};
+template <std::size_t I, u8 N> struct tuple_element<I, Range<N>> {
+  using type = u8;
+};
+} // namespace std
+
+const u8 &f() {
+  static constexpr auto [I] = Range<1>();
+  return I;
+}
+
+// CHECK: @[[TMP:_ZGR.*]] = internal constant i8 0, align 1
+// CHECK-LABEL: define {{.*}} @_Z1fv(
+// CHECK: ret ptr @[[TMP]]
diff --git a/clang/test/CodeGenCXX/const-init-cxx11.cpp 
b/clang/test/CodeGenCXX/const-init-cxx11.cpp
index 0795fb534af4b..5dfe3488ca7bb 100644
--- a/clang/test/CodeGenCXX/const-init-cxx11.cpp
+++ b/clang/test/CodeGenCXX/const-init-cxx11.cpp
@@ -226,8 +226,7 @@ namespace LiteralReference {
     int n;
   };
 
-  // This creates a non-const temporary and binds a reference to it.
-  // CHECK: @[[TEMP:.*]] = internal global {{.*}} { i32 5 }, align 4
+  // CHECK: @[[TEMP:.*]] = internal constant {{.*}} { i32 5 }, align 4
   // CHECK: @_ZN16LiteralReference3litE ={{.*}} constant {{.*}} @[[TEMP]], 
align 8
   const Lit &lit = Lit();
 
diff --git a/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp 
b/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp
deleted file mode 100644
index fdc6e9fb36e93..0000000000000
--- a/clang/test/CodeGenCXX/cpp26-constexpr-binding-pack-subscript.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-// RUN: %clang_cc1 -std=c++26 -O2 -triple x86_64-linux-gnu -emit-llvm -o - %s 
| FileCheck %s
-
-// static constexpr structured binding pack elements used as array subscript 
-// indices must be constant-folded at the Clang codegen level. Without the 
fix, 
-// each element is emitted as a load from a reference temporary static 
variable.
-
-namespace std {
-       using size_t = decltype(sizeof(0));
-       template <typename T> struct tuple_size;
-       template <size_t I, typename T> struct tuple_element;
-
-       template <typename T> struct tuple_size<const T> : tuple_size<T> {};
-
-       template <size_t I, typename T>
-               struct tuple_element<I, const T> {
-                       using type = const typename tuple_element<I, T>::type;
-               };
-} // namespace std
-
-using u8 = unsigned char;
-
-template <u8 N>
-struct Range {
-       template <std::size_t I>
-               consteval friend u8 get(Range) noexcept { return I; }
-};
-
-namespace std {
-       template <u8 N>
-               struct tuple_size<Range<N>> { static constexpr std::size_t 
value = N; };
-       template <std::size_t I, u8 N>
-               struct tuple_element<I, Range<N>> { using type = u8; };
-} // namespace std
-
-template <std::size_t N>
-struct Array {
-       u8 data[N];
-       const u8 &operator[](std::size_t i) const { return data[i]; }
-};
-
-template <std::size_t L, std::size_t R>
-Array<L + R> concat(const Array<L> &l, const Array<R> &r) {
-       static constexpr auto [...I] = Range<L>{};
-       static constexpr auto [...J] = Range<R>{};
-       return {{l[I]..., r[J]...}};
-}
-
-Array<32> test(const Array<16> &l, const Array<16> &r) {
-       return concat(l, r);
-}
-
-// The binding-pack indices must not be materialised as reference-temporary
-// static variables at any optimisation level.
-// CHECK-LABEL: define {{.*}} @{{.*test.*}}
-// CHECK-NOT:   @_ZGR
diff --git a/clang/test/CodeGenCXX/temporaries.cpp 
b/clang/test/CodeGenCXX/temporaries.cpp
index 146ebc7dd090e..c3842776e0c5e 100644
--- a/clang/test/CodeGenCXX/temporaries.cpp
+++ b/clang/test/CodeGenCXX/temporaries.cpp
@@ -48,8 +48,7 @@ namespace BraceInit {
   typedef const int &CIR;
   CIR x = CIR{3};
   // CHECK-CXX11: @_ZGRN9BraceInit1xE_ = internal constant i32 3
-  // FIXME: This should still be emitted as 'constant' in C++17.
-  // CHECK-CXX17: @_ZGRN9BraceInit1xE_ = internal global i32 3
+  // CHECK-CXX17: @_ZGRN9BraceInit1xE_ = internal constant i32 3
   // CHECK: @_ZN9BraceInit1xE ={{.*}} constant ptr @_ZGRN9BraceInit1xE_
 }
 
@@ -59,7 +58,7 @@ namespace RefTempSubobject {
     int ints[3] = {1, 2, 3};
   };
 
-  // CHECK: @_ZGRN16RefTempSubobject2srE_ = internal global { ptr, [3 x i32] } 
{ {{.*}} getelementptr {{.*}} @_ZGRN16RefTempSubobject2srE_, {{.*}}, [3 x i32] 
[i32 1, i32 2, i32 3] }
+  // CHECK: @_ZGRN16RefTempSubobject2srE_ = internal constant { ptr, [3 x i32] 
} { {{.*}} getelementptr {{.*}} @_ZGRN16RefTempSubobject2srE_, {{.*}}, [3 x 
i32] [i32 1, i32 2, i32 3] }
   // CHECK: @_ZN16RefTempSubobject2srE = constant {{.*}} 
@_ZGRN16RefTempSubobject2srE_
   constexpr const SelfReferential &sr = SelfReferential();
 }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to