aboutsummaryrefslogtreecommitdiff
path: root/clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp
diff options
context:
space:
mode:
authorPiotr Zegar <me@piotrzegar.pl>2023-06-10 07:44:18 +0000
committerPiotr Zegar <me@piotrzegar.pl>2023-06-10 11:06:49 +0000
commit8fdedcd1a242f6b54eec969e72e35ac0a68b7ea1 (patch)
tree8be426793d7839f315c6ccfec74254f4706906a8 /clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp
parent7ffeb8efe8a08d74649c325a7eb70dc0b853326e (diff)
downloadllvm-8fdedcd1a242f6b54eec969e72e35ac0a68b7ea1.zip
llvm-8fdedcd1a242f6b54eec969e72e35ac0a68b7ea1.tar.gz
llvm-8fdedcd1a242f6b54eec969e72e35ac0a68b7ea1.tar.bz2
[clang-tidy] Optimize misc-confusable-identifiers
This is final optimization for this check. Main improvements comes from changing a logic order in mayShadow function, to first validate result of mayShadowImpl, then search primary context in a vectors. Secondary improvement comes from excluding all implicit code by using TK_IgnoreUnlessSpelledInSource. All other changes are just cosmetic improvements. Tested on Cataclysm-DDA open source project, result in check execution time reduction from 3682 seconds to 100 seconds (~0.25s per TU). That's 97.2% reduction for this change alone. Resulting in cumulative improvement for this check around -99.6%, finally bringing this check into a cheap category. Reviewed By: serge-sans-paille Differential Revision: https://reviews.llvm.org/D151594
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp92
1 files changed, 56 insertions, 36 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp b/clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp
index 63ba663..c2f72c8 100644
--- a/clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp
@@ -11,6 +11,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ConvertUTF.h"
namespace {
@@ -45,14 +46,13 @@ ConfusableIdentifierCheck::~ConfusableIdentifierCheck() = default;
// We're skipping 1. and 3. for the sake of simplicity, but this can lead to
// false positive.
-static std::string skeleton(StringRef Name) {
+static llvm::SmallString<64U> skeleton(StringRef Name) {
using namespace llvm;
- std::string SName = Name.str();
- std::string Skeleton;
- Skeleton.reserve(1 + Name.size());
+ SmallString<64U> Skeleton;
+ Skeleton.reserve(1U + Name.size());
- const char *Curr = SName.c_str();
- const char *End = Curr + SName.size();
+ const char *Curr = Name.data();
+ const char *End = Curr + Name.size();
while (Curr < End) {
const char *Prev = Curr;
@@ -99,8 +99,6 @@ static bool mayShadowImpl(const NamedDecl *ND0, const NamedDecl *ND1) {
static bool isMemberOf(const ConfusableIdentifierCheck::ContextInfo *DC0,
const ConfusableIdentifierCheck::ContextInfo *DC1) {
- if (DC0->Bases.empty())
- return false;
return llvm::is_contained(DC1->Bases, DC0->PrimaryContext);
}
@@ -117,16 +115,23 @@ static bool mayShadow(const NamedDecl *ND0,
const ConfusableIdentifierCheck::ContextInfo *DC0,
const NamedDecl *ND1,
const ConfusableIdentifierCheck::ContextInfo *DC1) {
- if (!DC0->Bases.empty() && ND1->getAccess() != AS_private &&
- isMemberOf(DC1, DC0))
- return true;
- if (!DC1->Bases.empty() && ND0->getAccess() != AS_private &&
- isMemberOf(DC0, DC1))
- return true;
- return enclosesContext(DC0, DC1) &&
- (mayShadowImpl(ND0, ND1) || mayShadowImpl(DC0->NonTransparentContext,
- DC1->NonTransparentContext));
+ if (!DC0->Bases.empty() && !DC1->Bases.empty()) {
+ // if any of the declaration is a non-private member of the other
+ // declaration, it's shadowed by the former
+
+ if (ND1->getAccess() != AS_private && isMemberOf(DC1, DC0))
+ return true;
+
+ if (ND0->getAccess() != AS_private && isMemberOf(DC0, DC1))
+ return true;
+ }
+
+ if (!mayShadowImpl(DC0->NonTransparentContext, DC1->NonTransparentContext) &&
+ !mayShadowImpl(ND0, ND1))
+ return false;
+
+ return enclosesContext(DC0, DC1);
}
const ConfusableIdentifierCheck::ContextInfo *
@@ -172,26 +177,41 @@ ConfusableIdentifierCheck::getContextInfo(const DeclContext *DC) {
void ConfusableIdentifierCheck::check(
const ast_matchers::MatchFinder::MatchResult &Result) {
- if (const auto *ND = Result.Nodes.getNodeAs<NamedDecl>("nameddecl")) {
- if (IdentifierInfo *NDII = ND->getIdentifier()) {
- const ContextInfo *Info = getContextInfo(ND->getDeclContext());
- StringRef NDName = NDII->getName();
- llvm::SmallVector<Entry> &Mapped = Mapper[skeleton(NDName)];
- for (const Entry &E : Mapped) {
- const IdentifierInfo *ONDII = E.Declaration->getIdentifier();
- if (mayShadow(ND, Info, E.Declaration, E.Info)) {
- StringRef ONDName = ONDII->getName();
- if (ONDName != NDName) {
- diag(ND->getLocation(), "%0 is confusable with %1")
- << ND << E.Declaration;
- diag(E.Declaration->getLocation(), "other declaration found here",
- DiagnosticIDs::Note);
- }
- }
- }
- Mapped.push_back({ND, Info});
- }
+ const auto *ND = Result.Nodes.getNodeAs<NamedDecl>("nameddecl");
+ if (!ND)
+ return;
+
+ IdentifierInfo *NDII = ND->getIdentifier();
+ if (!NDII)
+ return;
+
+ StringRef NDName = NDII->getName();
+ if (NDName.empty())
+ return;
+
+ const ContextInfo *Info = getContextInfo(ND->getDeclContext());
+
+ llvm::SmallVector<Entry> &Mapped = Mapper[skeleton(NDName)];
+ for (const Entry &E : Mapped) {
+ if (!mayShadow(ND, Info, E.Declaration, E.Info))
+ continue;
+
+ const IdentifierInfo *ONDII = E.Declaration->getIdentifier();
+ StringRef ONDName = ONDII->getName();
+ if (ONDName == NDName)
+ continue;
+
+ diag(ND->getLocation(), "%0 is confusable with %1") << ND << E.Declaration;
+ diag(E.Declaration->getLocation(), "other declaration found here",
+ DiagnosticIDs::Note);
}
+
+ Mapped.push_back({ND, Info});
+}
+
+void ConfusableIdentifierCheck::onEndOfTranslationUnit() {
+ Mapper.clear();
+ ContextInfos.clear();
}
void ConfusableIdentifierCheck::registerMatchers(