-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[clang-tidy] Don't cache classes by name in fuchsia-multiple-inheritance
#171016
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@llvm/pr-subscribers-clang-tidy @llvm/pr-subscribers-clang-tools-extra Author: Victor Chernyakin (localspook) ChangesContext: for every class, this check needs to compute whether that class is an interface (i.e. only has pure virtual methods). This is expensive, so the check caches the computation. But it caches by class name, which is problematic, because the same name can refer to different classes at different scopes. Here's for example a false negative it causes: https://godbolt.org/z/bMGc5sYqh. This PR changes it to cache by Full diff: https://github.com/llvm/llvm-project/pull/171016.diff 3 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
index 652dec9bcc2a9..029c482691c00 100644
--- a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp
@@ -27,9 +27,7 @@ AST_MATCHER(CXXRecordDecl, hasBases) {
// previously.
void MultipleInheritanceCheck::addNodeToInterfaceMap(const CXXRecordDecl *Node,
bool IsInterface) {
- assert(Node->getIdentifier());
- const StringRef Name = Node->getIdentifier()->getName();
- InterfaceMap.insert(std::make_pair(Name, IsInterface));
+ InterfaceMap.try_emplace(Node, IsInterface);
}
// Returns "true" if the boolean "isInterface" has been set to the
@@ -37,9 +35,7 @@ void MultipleInheritanceCheck::addNodeToInterfaceMap(const CXXRecordDecl *Node,
// interface status for the current node is not yet known.
bool MultipleInheritanceCheck::getInterfaceStatus(const CXXRecordDecl *Node,
bool &IsInterface) const {
- assert(Node->getIdentifier());
- const StringRef Name = Node->getIdentifier()->getName();
- auto Pair = InterfaceMap.find(Name);
+ auto Pair = InterfaceMap.find(Node);
if (Pair == InterfaceMap.end())
return false;
IsInterface = Pair->second;
@@ -59,9 +55,6 @@ bool MultipleInheritanceCheck::isCurrentClassInterface(
}
bool MultipleInheritanceCheck::isInterface(const CXXRecordDecl *Node) {
- if (!Node->getIdentifier())
- return false;
-
// Short circuit the lookup if we have analyzed this record before.
bool PreviousIsInterfaceResult = false;
if (getInterfaceStatus(Node, PreviousIsInterfaceResult))
diff --git a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.h b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.h
index 2e268432c17cf..b9055eb58a300 100644
--- a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.h
+++ b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.h
@@ -38,7 +38,7 @@ class MultipleInheritanceCheck : public ClangTidyCheck {
// Contains the identity of each named CXXRecord as an interface. This is
// used to memoize lookup speeds and improve performance from O(N^2) to O(N),
// where N is the number of classes.
- llvm::StringMap<bool> InterfaceMap;
+ llvm::DenseMap<const CXXRecordDecl *, bool> InterfaceMap;
};
} // namespace clang::tidy::fuchsia
diff --git a/clang-tools-extra/test/clang-tidy/checkers/fuchsia/multiple-inheritance.cpp b/clang-tools-extra/test/clang-tidy/checkers/fuchsia/multiple-inheritance.cpp
index d53b3fde7736b..c60649f52cb94 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/fuchsia/multiple-inheritance.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/fuchsia/multiple-inheritance.cpp
@@ -148,3 +148,18 @@ void test_no_crash() {
auto foo = []() {};
WithTemplBase<decltype(foo)>();
}
+
+struct S1 {};
+struct S2 {};
+
+struct S3 : S1, S2 {};
+
+namespace N {
+
+struct S1 { int i; };
+struct S2 { int i; };
+
+// CHECK-MESSAGES: [[@LINE+1]]:1: warning: inheriting multiple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance]
+struct S3 : S1, S2 {};
+
+} // namespace N
|
vbvictor
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add release notes
Context: for every class, this check needs to compute whether that class is an interface (i.e. only has pure virtual methods). This is expensive, so the check caches the computation. But it caches by class name, which is problematic, because the same name can refer to different classes at different scopes. Here's for example a false negative it causes: https://godbolt.org/z/bMGc5sYqh. This PR changes it to cache by
CXXRecordDecl *instead.