[clang] [Clang] Fixed a crash in constant evaluation when using a defaulted comparison operator in a union (PR #198830)
via cfe-commits
cfe-commits at lists.llvm.org
Thu May 21 00:42:02 PDT 2026
https://github.com/TPPPP72 updated https://github.com/llvm/llvm-project/pull/198830
>From fb18b67152e8561be3c993f31021381ebd86a31a Mon Sep 17 00:00:00 2001
From: TPPPP <TPPPP72 at outlook.com>
Date: Thu, 21 May 2026 15:41:36 +0800
Subject: [PATCH] [Clang] Fixed a crash in constant evaluation when using a
defaulted comparison operator in a union
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/AST/ExprConstant.cpp | 19 +++++++++++++------
clang/test/SemaCXX/gh147127.cpp | 12 ++++++++++++
3 files changed, 26 insertions(+), 6 deletions(-)
create mode 100644 clang/test/SemaCXX/gh147127.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 843a01f57c39f..7b8b4dba85d4c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -570,6 +570,7 @@ Bug Fixes in This Version
an array via an element-at-a-time copy loop (#GH192026)
- Fixed an issue where certain designated initializers would be rejected for constexpr variables. (#GH193373)
- Fixed a crash when ``#embed`` is used with C++ modules (#GH195350)
+- Fixed a assertion in constant evaluation when using a defaulted comparison operator in a ``union``. (#GH147127)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 38aa5798cfeb9..1374f837aa0a3 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -7020,13 +7020,20 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
// Skip this for non-union classes with no fields; in that case, the defaulted
// copy/move does not actually read the object.
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee);
- if (MD && MD->isDefaulted() &&
- (MD->getParent()->isUnion() ||
- (MD->isTrivial() &&
- isReadByLvalueToRvalueConversion(MD->getParent())))) {
+
+ auto IsTrivialMemoryOperation = [&](const CXXMethodDecl *MD) {
+ if (!MD || !MD->isDefaulted())
+ return false;
+ if (!MD->isCopyAssignmentOperator() && !MD->isMoveAssignmentOperator())
+ return false;
+ return MD->getParent()->isUnion() ||
+ (MD->isTrivial() &&
+ isReadByLvalueToRvalueConversion(MD->getParent()));
+ };
+
+ if (IsTrivialMemoryOperation(MD)) {
unsigned ExplicitOffset = MD->isExplicitObjectMemberFunction() ? 1 : 0;
- assert(ObjectArg &&
- (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()));
+ assert(ObjectArg);
APValue RHSValue;
if (!handleTrivialCopy(Info, MD->getParamDecl(0), Args[0], RHSValue,
MD->getParent()->isUnion()))
diff --git a/clang/test/SemaCXX/gh147127.cpp b/clang/test/SemaCXX/gh147127.cpp
new file mode 100644
index 0000000000000..35bdc663c798f
--- /dev/null
+++ b/clang/test/SemaCXX/gh147127.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++20-extensions -verify=cxx17 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=cxx20 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++20-extensions -fexperimental-new-constant-interpreter -verify=cxx17 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -fexperimental-new-constant-interpreter -verify=cxx20 %s
+
+union A {
+ // cxx20-no-diagnostics
+ bool operator==(const A&) const = default; // cxx17-warning {{defaulted comparison operators are a C++20 extension}}
+};
+
+A a;
+bool b = a == a;
More information about the cfe-commits
mailing list