Author: Yuli Fiterman Date: 2026-06-29T10:41:25+02:00 New Revision: 4eb7340fcb8e644883826335955282dff42fa7ef
URL: https://github.com/llvm/llvm-project/commit/4eb7340fcb8e644883826335955282dff42fa7ef DIFF: https://github.com/llvm/llvm-project/commit/4eb7340fcb8e644883826335955282dff42fa7ef.diff LOG: [Clang][Sema] Fix crash on init-list of array with incomplete element type (#205973) ## Summary Fixes #140685. clangd (and clang itself, with assertions enabled) crashes on: ```cpp struct MoveOnly; void test() { MoveOnly (&&list)[1] = {}; } ``` with ``` Assertion failed: (CanDeclareSpecialMemberFunction(RD) && "doing special member lookup into record that isn't fully complete"), function LookupSpecialMember, file SemaLookup.cpp ``` The path is `InitListChecker::CheckArrayType` → `checkDestructorReference` → `LookupDestructor` → `LookupSpecialMember`. `LookupSpecialMember` asserts that the record is fully defined; `checkDestructorReference` was not guarding against incomplete records before calling. Error recovery for init-lists of incomplete element types reaches this point even after the parser has already diagnosed the incompleteness, so we hit the assert in any `+asserts` build. ## Fix One-line guard in `checkDestructorReference`: bail when the record has no definition. This matches the contract `LookupSpecialMember`'s assertion enforces (via the static `CanDeclareSpecialMemberFunction`) and is consistent with how other call sites guard their lookups. ```diff auto *CXXRD = ElementType->getAsCXXRecordDecl(); - if (!CXXRD) + if (!CXXRD || !CXXRD->hasDefinition()) return false; ``` ## Test `clang/test/SemaCXX/init-list-incomplete-dtor-crash.cpp` — minimal `-verify` test that crashed before, now compiles to the expected diagnostics. Confirmed it fails (assertion crash) without the fix and passes with it. No other regressions in `clang/test/SemaCXX`, `clang/test/CXX/dcl.decl/dcl.init`, `clang/test/CXX/special` (pre-existing platform-specific failures unchanged). ## Release note Added under "Bug Fixes to C++ Support" in `clang/docs/ReleaseNotes.rst`. --------- Co-authored-by: Corentin Jabot <[email protected]> Added: clang/test/SemaCXX/init-list-incomplete-dtor-crash.cpp Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaInit.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 05c28aa069d34..837e86d357129 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -820,6 +820,7 @@ Bug Fixes to C++ Support - Fixed an issue where Clang incorrectly accepted invalid unqualified uses of local nested class names outside their declaring scope. (#GH184622) - Fixed a crash when parsing invalid friend declaration with storage-class specifier. (#GH186569) - Fixed a missing vtable for ``dynamic_cast<FinalClass *>(this)`` in a function template. (#GH198511) +- Fixed an assertion failure during init-list checking of an array whose element type is an incomplete class. (#GH140685) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 8f685feac4beb..dad9c8c972dd9 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2094,7 +2094,12 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, static bool checkDestructorReference(QualType ElementType, SourceLocation Loc, Sema &SemaRef) { auto *CXXRD = ElementType->getAsCXXRecordDecl(); - if (!CXXRD) + // Bail out on incomplete record types: a forward-declared class has no + // destructor to look up, and `LookupDestructor` (via `LookupSpecialMember`) + // asserts that the record is fully defined. Error recovery for init lists + // of incomplete element types reaches this point even after the parser has + // already diagnosed the incompleteness. + if (!CXXRD || !CXXRD->hasDefinition()) return false; CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(CXXRD); diff --git a/clang/test/SemaCXX/init-list-incomplete-dtor-crash.cpp b/clang/test/SemaCXX/init-list-incomplete-dtor-crash.cpp new file mode 100644 index 0000000000000..f5ea89a3450a7 --- /dev/null +++ b/clang/test/SemaCXX/init-list-incomplete-dtor-crash.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s + +// Regression test for https://github.com/llvm/llvm-project/issues/140685 +// +// List-initialization of an array whose element type is an incomplete +// (forward-declared) class triggered destructor lookup on the incomplete +// type, hitting an assertion in Sema::LookupSpecialMember. + +namespace gh140685 { +struct MoveOnly; // expected-note {{forward declaration of 'gh140685::MoveOnly'}} + +void test() { + MoveOnly(&&list)[1] = {}; + // expected-error@-1 {{initialization of incomplete type 'MoveOnly'}} + // expected-note@-2 {{in implicit initialization of array element 0 with omitted initializer}} + // expected-note@-3 {{in initialization of temporary of type 'MoveOnly[1]' created to list-initialize this reference}} +} +} // namespace gh140685 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
