================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits