Skip to content

Commit 3856058

Browse files
committed
add visit check
1 parent c3057de commit 3856058

File tree

2 files changed

+23
-8
lines changed

2 files changed

+23
-8
lines changed

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7172,7 +7172,10 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
71727172
// "effectively constexpr" for better compatibility.
71737173
// See https://github.com/llvm/llvm-project/issues/102293 for more info.
71747174
if (isa<CXXDestructorDecl>(M)) {
7175-
auto Check = [](QualType T, auto &&Check) -> bool {
7175+
llvm::DenseSet<QualType> Visited;
7176+
auto Check = [&Visited](QualType T, auto &&Check) -> bool {
7177+
if (!Visited.insert(T).second)
7178+
return false;
71767179
const CXXRecordDecl *RD =
71777180
T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
71787181
if (!RD || !RD->isCompleteDefinition())
@@ -7181,16 +7184,11 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
71817184
if (!RD->hasConstexprDestructor())
71827185
return false;
71837186

7184-
QualType CanUnqualT = T.getCanonicalType().getUnqualifiedType();
71857187
for (const CXXBaseSpecifier &B : RD->bases())
7186-
if (B.getType().getCanonicalType().getUnqualifiedType() !=
7187-
CanUnqualT &&
7188-
!Check(B.getType(), Check))
7188+
if (!Check(B.getType(), Check))
71897189
return false;
71907190
for (const FieldDecl *FD : RD->fields())
7191-
if (FD->getType().getCanonicalType().getUnqualifiedType() !=
7192-
CanUnqualT &&
7193-
!Check(FD->getType(), Check))
7191+
if (!Check(FD->getType(), Check))
71947192
return false;
71957193
return true;
71967194
};

clang/test/SemaCXX/gh102293.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,20 @@ class quux : quux { // expected-error {{base class has incomplete type}} \
4545
virtual int c();
4646
};
4747
}
48+
49+
// Ensure we don't get infinite recursion from the check, however. See GH141789
50+
namespace GH141789 {
51+
template <typename Ty>
52+
struct S {
53+
Ty t; // expected-error {{field has incomplete type 'GH141789::X'}}
54+
};
55+
56+
struct T {
57+
~T();
58+
};
59+
60+
struct X { // expected-note {{definition of 'GH141789::X' is not complete until the closing '}'}}
61+
S<X> next; // expected-note {{in instantiation of template class 'GH141789::S<GH141789::X>' requested here}}
62+
T m;
63+
};
64+
}

0 commit comments

Comments
 (0)