Author: Aaron Ballman Date: 2024-08-19T16:54:12-04:00 New Revision: 435cb0dc5eca08cdd8d9ed0d887fa1693cc2bf33
URL: https://github.com/llvm/llvm-project/commit/435cb0dc5eca08cdd8d9ed0d887fa1693cc2bf33 DIFF: https://github.com/llvm/llvm-project/commit/435cb0dc5eca08cdd8d9ed0d887fa1693cc2bf33.diff LOG: [C++23] Fix infinite recursion (Clang 19.x regression) (#104829) d469794d0cdfd2fea50a6ce0c0e33abb242d744c was fixing an issue with triggering vtable instantiations, but it accidentally introduced infinite recursion when the type to be checked is the same as the type used in a base specifier or field declaration. Fixes #104802 Added: Modified: clang/lib/Sema/SemaDeclCXX.cpp clang/test/SemaCXX/gh102293.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e05595e565d54a..d89a47f3e6226a 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7056,11 +7056,16 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { if (!RD->hasConstexprDestructor()) return false; + QualType CanUnqualT = T.getCanonicalType().getUnqualifiedType(); for (const CXXBaseSpecifier &B : RD->bases()) - if (!Check(B.getType(), Check)) + if (B.getType().getCanonicalType().getUnqualifiedType() != + CanUnqualT && + !Check(B.getType(), Check)) return false; for (const FieldDecl *FD : RD->fields()) - if (!Check(FD->getType(), Check)) + if (FD->getType().getCanonicalType().getUnqualifiedType() != + CanUnqualT && + !Check(FD->getType(), Check)) return false; return true; }; diff --git a/clang/test/SemaCXX/gh102293.cpp b/clang/test/SemaCXX/gh102293.cpp index 30629fc03bf6a9..d4218cc13dcecd 100644 --- a/clang/test/SemaCXX/gh102293.cpp +++ b/clang/test/SemaCXX/gh102293.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s -// expected-no-diagnostics template <typename T> static void destroy() { T t; @@ -20,3 +19,29 @@ struct S : HasVT { HasD<> v; }; +// Ensure we don't get infinite recursion from the check, however. See GH104802 +namespace GH104802 { +class foo { // expected-note {{definition of 'GH104802::foo' is not complete until the closing '}'}} + foo a; // expected-error {{field has incomplete type 'foo'}} + + virtual int c(); +}; + +class bar { // expected-note {{definition of 'GH104802::bar' is not complete until the closing '}'}} + const bar a; // expected-error {{field has incomplete type 'const bar'}} + + virtual int c(); +}; + +class baz { // expected-note {{definition of 'GH104802::baz' is not complete until the closing '}'}} + typedef class baz blech; + blech a; // expected-error {{field has incomplete type 'blech' (aka 'GH104802::baz')}} + + virtual int c(); +}; + +class quux : quux { // expected-error {{base class has incomplete type}} \ + expected-note {{definition of 'GH104802::quux' is not complete until the closing '}'}} + virtual int c(); +}; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits