Author: Purna Chandra Date: 2026-09-22T21:54:11+08:00 New Revision: db17738290efb586b9700bbecef3a82084a9c5f4
URL: https://github.com/llvm/llvm-project/commit/db17738290efb586b9700bbecef3a82084a9c5f4 DIFF: https://github.com/llvm/llvm-project/commit/db17738290efb586b9700bbecef3a82084a9c5f4.diff LOG: [clang-tidy] Fix infinite loop in misc-multiple-inheritance (#220223) This PR contains the fix for the infinite loop in `misc-multiple-inheritance`. The checker was getting stuck in an infinite cycle when it encountered circular inheritance. I fixed this by adding a visited map (`InterfaceMap.try_emplace(Node, false)`) to break the cycle during the DFS traversal. Part of #213948. Added: Modified: clang-tools-extra/clang-tidy/misc/MultipleInheritanceCheck.cpp clang-tools-extra/docs/ReleaseNotes.md clang-tools-extra/test/clang-tidy/checkers/misc/multiple-inheritance.cpp Removed: ################################################################################ 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 0441aef375c54..4973bef42e3bf 100644 --- a/clang-tools-extra/docs/ReleaseNotes.md +++ b/clang-tools-extra/docs/ReleaseNotes.md @@ -212,6 +212,10 @@ infrastructure are described first, followed by tool-specific sections. - No longer diagnoses variables declared with `decltype(auto)`, where the suggested `const` does not compile. + +- 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 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() {} }; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
