[clang-tools-extra] [clang-tidy] Fix infinite loop in misc-multiple-inheritance (PR #220223)
Purna Chandra via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 22 00:15:41 PDT 2026
https://github.com/Purna-Chandra-4706 updated https://github.com/llvm/llvm-project/pull/220223
>From f4e08f4bbaee53ba1c6d7b34a40b1e6456c70538 Mon Sep 17 00:00:00 2001
From: Purna-Chandra-4706 <vennelapurnachandra2006 at gmail.com>
Date: Tue, 1 Sep 2026 16:15:44 +0530
Subject: [PATCH] [clang-tidy] Fix infinite loop in misc-multiple-inheritance
---
.../clang-tidy/misc/MultipleInheritanceCheck.cpp | 8 ++++----
clang-tools-extra/docs/ReleaseNotes.md | 4 ++++
.../clang-tidy/checkers/misc/multiple-inheritance.cpp | 6 ++++++
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/MultipleInheritanceCheck.cpp b/clang-tools-extra/clang-tidy/misc/MultipleInheritanceCheck.cpp
index 72e6aa6ac0b47..633842f3f6b22 100644
--- a/clang-tools-extra/clang-tidy/misc/MultipleInheritanceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/MultipleInheritanceCheck.cpp
@@ -23,16 +23,16 @@ AST_MATCHER(CXXRecordDecl, hasBases) {
bool MultipleInheritanceCheck::isInterface(const CXXBaseSpecifier &Base) {
const CXXRecordDecl *const Node = Base.getType()->getAsCXXRecordDecl();
- if (!Node)
+ if (!Node || !Node->hasDefinition())
return true;
- assert(Node->isCompleteDefinition());
-
// Short circuit the lookup if we have analyzed this record before.
if (const auto CachedValue = InterfaceMap.find(Node);
CachedValue != InterfaceMap.end())
return CachedValue->second;
+ InterfaceMap.try_emplace(Node, false);
+
// To be an interface, a class must have...
const bool CurrentClassIsInterface =
// ...no bases that aren't interfaces...
@@ -47,7 +47,7 @@ bool MultipleInheritanceCheck::isInterface(const CXXBaseSpecifier &Base) {
return M->isUserProvided() && !M->isPureVirtual() && !M->isStatic();
});
- InterfaceMap.try_emplace(Node, CurrentClassIsInterface);
+ InterfaceMap[Node] = CurrentClassIsInterface;
return CurrentClassIsInterface;
}
diff --git a/clang-tools-extra/docs/ReleaseNotes.md b/clang-tools-extra/docs/ReleaseNotes.md
index 420b7ddce20e6..6719b598c5de7 100644
--- a/clang-tools-extra/docs/ReleaseNotes.md
+++ b/clang-tools-extra/docs/ReleaseNotes.md
@@ -164,6 +164,10 @@ infrastructure are described first, followed by tool-specific sections.
- Fixed false positives when the pointee is written through a pointer
assignment, such as `*(p = q) = 0`.
+- Fixed an infinite loop in {doc}`misc-multiple-inheritance
+ <clang-tidy/checks/misc/multiple-inheritance>` when checking a class that
+ inherits from itself or has a circular inheritance graph.
+
- Improved {doc}`misc-redundant-expression
<clang-tidy/checks/misc/redundant-expression>` by fixing false positives in
nested expressions involving different macros or a mix of macro and
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/multiple-inheritance.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/multiple-inheritance.cpp
index 257e16ab18f2f..15aa5d4d11228 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/multiple-inheritance.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/multiple-inheritance.cpp
@@ -182,3 +182,9 @@ struct VI : virtual VA { virtual void h() = 0; };
struct VD : VI, VB {};
} // namespace M
+
+template<class T> struct X {
+ struct B;
+ struct A : public B { virtual void foo() {} };
+};
+template<class T> struct X<T>::B : public A { virtual void foo() {} };
More information about the cfe-commits
mailing list