[clang] [Clang] Implement P0963R3 "Structured binding declaration as a condition" (PR #130228)

Younan Zhang via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 10 09:06:35 PDT 2025


================
@@ -5218,16 +5218,28 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
   return true;
 }
 
+static bool EvaluateDecompositionDeclInit(EvalInfo &Info,
+                                          const DecompositionDecl *DD);
+
 static bool EvaluateDecl(EvalInfo &Info, const Decl *D) {
   bool OK = true;
 
   if (const VarDecl *VD = dyn_cast<VarDecl>(D))
     OK &= EvaluateVarDecl(Info, VD);
 
-  if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(D))
-    for (auto *BD : DD->flat_bindings())
-      if (auto *VD = BD->getHoldingVar())
-        OK &= EvaluateDecl(Info, VD);
+  if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(D);
+      DD && !DD->isDecisionVariable())
+    OK &= EvaluateDecompositionDeclInit(Info, DD);
+
+  return OK;
+}
+
+static bool EvaluateDecompositionDeclInit(EvalInfo &Info,
+                                          const DecompositionDecl *DD) {
+  bool OK = true;
+  for (auto *BD : DD->flat_bindings())
+    if (auto *VD = BD->getHoldingVar())
+      OK &= EvaluateDecl(Info, VD);
----------------
zyn0217 wrote:

We can't bail out early here: `EvaluateVarDecl()` might fail because `EvaluateInPlace()` might fail, and in that case, we still need to continue evaluating the initializers; otherwise, we'll crash. Here is an example

```cpp

namespace std {

template <typename T> struct tuple_size;

template <int, typename> struct tuple_element;

} // namespace std


namespace constant {
  struct Q {};
  template<int N> constexpr int get(Q &&) { return N * N; }
}
template<> struct std::tuple_size<constant::Q> { static const int value = 3; };
template<int N> struct std::tuple_element<N, constant::Q> { typedef int type; };

namespace constant {
Q q;

constexpr bool f() {
  auto [a, b, c] = q;
  return a == 0 && b == 1 && c == 4;
}
static_assert(f());
}
```



https://github.com/llvm/llvm-project/pull/130228


More information about the cfe-commits mailing list