llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Yihan Wang (yronglin) <details> <summary>Changes</summary> The crash is from an internal inconsistency in Clang’s expression classification. Expr::ClassifyImpl computes a classification like CL_LValue or CL_PRValue, then asserts that this agrees with the AST node’s own value category: - clang/lib/AST/ExprClassification.cpp:37 - CL_LValue must satisfy E->isLValue() - CL_PRValue must satisfy E->isPRValue() Fixes https://github.com/llvm/llvm-project/issues/202693. --- Full diff: https://github.com/llvm/llvm-project/pull/202696.diff 3 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+2) - (modified) clang/lib/AST/ExprClassification.cpp (+5-4) - (added) clang/test/AST/dependent-assignment-classification.cpp (+39) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8a00b235860e4..340c0285072f9 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -744,6 +744,8 @@ Bug Fixes to C++ Support - We no longer consider conversion operators when copy-initializing from the same type. This was non conforming and could lead to recursive constraint satisfaction checking. (#GH149443) - Fixed a crash in Itanium C++ name mangling for a lambda in a local class field initializer inside a constructor/destructor. (#GH176395) +- Fixed a crash when Expr::ClassifyImpl computes a classification like CL_LValue or CL_PRValue, then asserts that this + agrees with the AST node's own value category. (#GH202693) - Fixed crashes in Itanium C++ name mangling for lambdas with trailing requires-clauses involving requires-expressions. (#GH100774) (#GH123854) - Fixed an invalid rejection and assertion failure while generating ``operator=`` for fields with the ``__restrict`` qualifier. (#GH37979) - Fixed a use-after-free bug when parsing default arguments containing lambdas in declarations with template-id declarators. (#GH196725) diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index a83c17074ea69..d153afda71c4b 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -617,11 +617,12 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { assert(Ctx.getLangOpts().CPlusPlus && "This is only relevant for C++."); - // For binary operators which are unknown due to type dependence, the - // convention is to classify them as a prvalue. This does not matter much, but - // it needs to agree with how they are created. + // For binary operators which are unknown due to type dependence, use the + // value kind assigned when the expression was created. Dependent assignment + // expressions can be either lvalues or prvalues depending on whether they + // might resolve to an overloaded operator. if (E->getType() == Ctx.DependentTy) - return Cl::CL_PRValue; + return ClassifyExprValueKind(Ctx.getLangOpts(), E, E->getValueKind()); // C++ [expr.ass]p1: All [...] return an lvalue referring to the left operand. // Except we override this for writes to ObjC properties. diff --git a/clang/test/AST/dependent-assignment-classification.cpp b/clang/test/AST/dependent-assignment-classification.cpp new file mode 100644 index 0000000000000..d31fa07fe0116 --- /dev/null +++ b/clang/test/AST/dependent-assignment-classification.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++26 %s + +// expected-no-diagnostics + +template <auto X, class = decltype(X)> +struct constant_wrapper; + +template <class T> +concept constexpr_param = requires { typename constant_wrapper<T::value>; }; + +struct ops { + template <constexpr_param T, constexpr_param R> + constexpr auto operator+=(this T, R) + -> constant_wrapper<(T::value += R::value)> { + return {}; + } +}; + +template <auto X, class> +struct constant_wrapper : ops { + static constexpr decltype(auto) value = (X); + + template <constexpr_param R> + constexpr auto operator=(R) const -> constant_wrapper<(value = R::value)> { + return {}; + } +}; + +struct A { + int n; + constexpr A(int n) : n(n) {} + constexpr A operator=(A rhs) const { return A{rhs.n}; } + constexpr A operator+=(A rhs) const { return A{n + rhs.n}; } +}; + +using X = constant_wrapper<A{1}>; +using Y = constant_wrapper<A{2}>; +using SimpleAssignment = decltype(X{} = Y{}); +using CompoundAssignment = decltype(X{} += Y{}); `````````` </details> https://github.com/llvm/llvm-project/pull/202696 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
