[clang-tools-extra] 3887ae1 - [clang-tidy] Guard `readability-identifier-naming` recursion in dependent base lookup (#204913)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 25 00:31:42 PDT 2026
Author: Zihan Qin
Date: 2026-06-25T15:31:37+08:00
New Revision: 3887ae1aacf6799e83684ab2bd0d02fd6b169ccd
URL: https://github.com/llvm/llvm-project/commit/3887ae1aacf6799e83684ab2bd0d02fd6b169ccd
DIFF: https://github.com/llvm/llvm-project/commit/3887ae1aacf6799e83684ab2bd0d02fd6b169ccd.diff
LOG: [clang-tidy] Guard `readability-identifier-naming` recursion in dependent base lookup (#204913)
Prevent `readability-identifier-naming` from recursing indefinitely in
dependent base lookup when AggressiveDependentMemberLookup` is enabled.
In #204790, `findDeclInBases()` maps a dependent template base back to
the primary template, creating a recursive cycle that crashes
clang-tidy. Add a recursion guard to stop the crash. A more complete fix
could be explored separately.
Add a regression test covering the dependent base cycle reproducer.
Closes https://github.com/llvm/llvm-project/issues/204790.
---------
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
Added:
Modified:
clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-member-decl-usage.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp
index cb7ef19827675..bfdcd381b4122 100644
--- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp
+++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp
@@ -17,6 +17,7 @@
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/ScopeExit.h"
#include <optional>
#define DEBUG_TYPE "clang-tidy"
@@ -118,6 +119,8 @@ static const NamedDecl *getFailureForNamedDecl(const NamedDecl *ND) {
return ND;
}
+using RecursionProtectionSet = llvm::SmallPtrSet<const CXXRecordDecl *, 4>;
+
/// Returns a decl matching the \p DeclName in \p Parent or one of its base
/// classes. If \p AggressiveTemplateLookup is `true` then it will check
/// template dependent base classes as well.
@@ -125,9 +128,17 @@ static const NamedDecl *getFailureForNamedDecl(const NamedDecl *ND) {
/// flag indicating the multiple resolutions.
static NameLookup findDeclInBases(const CXXRecordDecl &Parent,
StringRef DeclName,
- bool AggressiveTemplateLookup) {
+ bool AggressiveTemplateLookup,
+ RecursionProtectionSet &Visited) {
if (!Parent.hasDefinition())
return NameLookup(nullptr);
+
+ const auto *Definition = Parent.getDefinition();
+ if (!Visited.insert(Definition).second)
+ return NameLookup(nullptr);
+ auto RemoveFromVisited =
+ llvm::scope_exit([&Visited, Definition] { Visited.erase(Definition); });
+
if (const NamedDecl *InClassRef = findDecl(Parent, DeclName))
return NameLookup(InClassRef);
const NamedDecl *Found = nullptr;
@@ -144,8 +155,8 @@ static NameLookup findDeclInBases(const CXXRecordDecl &Parent,
}
if (!Record)
continue;
- if (auto Search =
- findDeclInBases(*Record, DeclName, AggressiveTemplateLookup)) {
+ if (auto Search = findDeclInBases(*Record, DeclName,
+ AggressiveTemplateLookup, Visited)) {
if (*Search) {
if (Found)
return NameLookup(
@@ -301,8 +312,9 @@ class RenamerClangTidyVisitor
return true;
const StringRef DependentName = DeclName.getAsIdentifierInfo()->getName();
+ RecursionProtectionSet Visited;
if (const NameLookup Resolved = findDeclInBases(
- *Base, DependentName, AggressiveDependentMemberLookup)) {
+ *Base, DependentName, AggressiveDependentMemberLookup, Visited)) {
if (*Resolved)
Check->addUsage(*Resolved,
DepMemberRef->getMemberNameInfo().getSourceRange(), SM);
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 4a5863be59fe3..81e5de4e0a868 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -801,6 +801,9 @@ Changes in existing checks
- Fixed a false positive where function templates could be diagnosed as generic
identifiers when `DefaultCase` was enabled.
+ - Fixed a crash in dependent base lookup when
+ `AggressiveDependentMemberLookup` option is enabled.
+
- Improved :doc:`readability-implicit-bool-conversion
<clang-tidy/checks/readability/implicit-bool-conversion>` check:
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-member-decl-usage.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-member-decl-usage.cpp
index 61c3aeb043934..ce7065dc0643e 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-member-decl-usage.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-member-decl-usage.cpp
@@ -216,3 +216,18 @@ struct Derived : DependentBase<T> {
};
} // namespace unresolved_dependance
+
+namespace dependent_base_cycle {
+template <typename T>
+struct CycleBase;
+
+template <typename T>
+struct CycleBase<const T> {
+ int Value;
+};
+
+template <typename T>
+struct CycleBase : CycleBase<const T> {
+ CycleBase() { this->Value; }
+};
+} // namespace dependent_base_cycle
More information about the cfe-commits
mailing list