Skip to content

Commit

Permalink
[C++23] Fix infinite recursion (Clang 19.x regression) (#104829)
Browse files Browse the repository at this point in the history
d469794 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
  • Loading branch information
AaronBallman authored Aug 19, 2024
1 parent 7022498 commit 435cb0d
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
9 changes: 7 additions & 2 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
27 changes: 26 additions & 1 deletion clang/test/SemaCXX/gh102293.cpp
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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();
};
}

0 comments on commit 435cb0d

Please sign in to comment.