================ @@ -181,42 +160,105 @@ void ConfusableIdentifierCheck::check( if (!ND) return; - IdentifierInfo *NDII = ND->getIdentifier(); + addDeclToCheck(ND, cast<Decl>(ND->getDeclContext() + ->getNonTransparentContext())); + + // Associate template parameters with this declaration of this template. + if (const auto *TD = dyn_cast<TemplateDecl>(ND)) { + for (const NamedDecl *Param : *TD->getTemplateParameters()) + addDeclToCheck(Param, TD->getTemplatedDecl()); + } + + // Associate function parameters with this declaration of this function. + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { + for (const NamedDecl *Param : FD->parameters()) + addDeclToCheck(Param, ND); + } +} + +void ConfusableIdentifierCheck::addDeclToCheck(const NamedDecl *ND, + const Decl *Parent) { + const IdentifierInfo *NDII = ND->getIdentifier(); if (!NDII) return; StringRef NDName = NDII->getName(); if (NDName.empty()) return; - const ContextInfo *Info = getContextInfo(ND->getDeclContext()); + NameToDecls[NDII].push_back({ND, Parent}); +} + +void ConfusableIdentifierCheck::onEndOfTranslationUnit() { + llvm::StringMap<llvm::SmallVector<const IdentifierInfo *, 1>> SkeletonToNames; + // Compute the skeleton for each identifier. + for (auto &[Ident, Decls] : NameToDecls) { + SkeletonToNames[skeleton(Ident->getName())].push_back(Ident); + } - llvm::SmallVector<Entry> &Mapped = Mapper[skeleton(NDName)]; - for (const Entry &E : Mapped) { - if (!mayShadow(ND, Info, E.Declaration, E.Info)) + // Visit each skeleton with more than one identifier. + for (auto &[Skel, Idents] : SkeletonToNames) { + if (Idents.size() < 2) { continue; + } - const IdentifierInfo *ONDII = E.Declaration->getIdentifier(); - StringRef ONDName = ONDII->getName(); - if (ONDName == NDName) - continue; + // Find the declaration contexts that transitively contain each identifier. + DeclsWithinContextMap DeclsWithinContext; ---------------- zygoloid wrote:
I ran this a couple of times both ways, and the difference seems to be in the noise (in fact, the clang-tidy profiler found that both runs without this change were faster than the ones with it, but they're close enough that I don't think it's a real difference). It might be that the extra allocations are actually faster than keeping the high-water-mark and performing extra work clearing out a larger bucket array each time? Or maybe we just don't reach this loop enough times for it to be interesting. I also tried using `SmallDenseMap` but that also seemed in the noise (slightly increased runtime). https://github.com/llvm/llvm-project/pull/130369 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits