Author: TPPPP Date: 2026-06-25T10:27:34+08:00 New Revision: 1f713c05e87e470cbdb5c5eee5bcbc0d46ba342b
URL: https://github.com/llvm/llvm-project/commit/1f713c05e87e470cbdb5c5eee5bcbc0d46ba342b DIFF: https://github.com/llvm/llvm-project/commit/1f713c05e87e470cbdb5c5eee5bcbc0d46ba342b.diff LOG: [Clang] Fixed an assertion in constant evaluation when using a defaulted comparison operator in a union (#198830) Fixes an assertion failure by decoupling `IsTrivialMemoryOperation` from assignment operators. fix #147127 Added: clang/test/SemaCXX/gh147127.cpp Modified: clang/docs/ReleaseNotes.rst clang/lib/AST/ExprConstant.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 4ca239ca5f2e4..5eea73ad9dc83 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -731,6 +731,7 @@ Bug Fixes in This Version EOF handling from accidentally restoring CLK_CachingLexer while a tentative parse is still active, which could trigger a caching lexer re-entry assertion in clangd signature help. (#GH200677) - Fixed a crash when ``#embed`` is used with C++ modules (#GH195350) +- Fixed an assertion in constant evaluation when using a defaulted comparison operator in a ``union``. (#GH147127) - Fixed a bug where ``-x cuda`` caused clang to immediately resolve templates that should not be. (#GH200545) - Fixed an issue where ``__typeof_unqual`` and ``__typeof_unqual__`` were rejected as a declaration specifier in block scope in C++. - Fixed crash when checking for overflow for unary operator that can't overflow (#GH170072) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index b628669880f2b..5ee27dd4e2ba2 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -7016,13 +7016,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; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
