48static llvm::SmallString<64U>
skeleton(StringRef Name) {
50 SmallString<64U> Skeleton;
51 Skeleton.reserve(1U + Name.size());
53 const char *Curr = Name.data();
54 const char *End = Curr + Name.size();
57 const char *Prev = Curr;
59 ConversionResult Result = convertUTF8Sequence(
60 reinterpret_cast<const UTF8 **
>(&Curr),
61 reinterpret_cast<const UTF8 *
>(End), &CodePoint, strictConversion);
62 if (Result != conversionOK) {
63 errs() <<
"Unicode conversion issue\n";
67 StringRef Key(Prev, Curr - Prev);
68 auto *Where = llvm::lower_bound(ConfusableEntries, CodePoint,
69 [](
decltype(ConfusableEntries[0])
X,
70 UTF32 Y) {
return X.codepoint < Y; });
71 if (Where == std::end(ConfusableEntries) || CodePoint != Where->codepoint) {
72 Skeleton.append(Prev, Curr);
75 UTF8 *BufferStart = std::begin(Buffer);
76 UTF8 *IBuffer = BufferStart;
77 const UTF32 *ValuesStart = std::begin(Where->values);
78 const UTF32 *ValuesEnd = llvm::find(Where->values,
'\0');
79 if (ConvertUTF32toUTF8(&ValuesStart, ValuesEnd, &IBuffer,
81 strictConversion) != conversionOK) {
82 errs() <<
"Unicode conversion issue\n";
85 Skeleton.append((
char *)BufferStart, (
char *)IBuffer);
129 const Decl *Parent,
const NamedDecl *ND) {
130 const Decl *Outer = Parent;
132 if (
const auto *NS = dyn_cast<NamespaceDecl>(Outer))
133 Outer = NS->getCanonicalDecl();
135 if (!
addToContext(DeclsWithinContext, Outer, {ND, Parent,
false}))
138 if (
const auto *RD = dyn_cast<CXXRecordDecl>(Outer)) {
139 RD = RD->getDefinition();
141 RD->forallBases([&](
const CXXRecordDecl *Base) {
142 addToContext(DeclsWithinContext, Base, {ND, Parent,
true});
148 auto *OuterDC = Outer->getDeclContext();
151 Outer = cast_or_null<Decl>(OuterDC->getNonTransparentContext());
156 const ast_matchers::MatchFinder::MatchResult &Result) {
157 const auto *ND = Result.Nodes.getNodeAs<NamedDecl>(
"nameddecl");
162 cast<Decl>(ND->getDeclContext()->getNonTransparentContext()));
165 if (
const auto *TD = dyn_cast<TemplateDecl>(ND)) {
166 for (
const NamedDecl *Param : *TD->getTemplateParameters())
167 addDeclToCheck(Param, TD->getTemplatedDecl());
171 if (
const auto *FD = dyn_cast<FunctionDecl>(ND)) {
172 for (
const NamedDecl *Param : FD->parameters())
173 addDeclToCheck(Param, ND);
194 llvm::StringMap<llvm::SmallVector<const IdentifierInfo *, 1>> SkeletonToNames;
196 for (
auto &[Ident, Decls] : NameToDecls) {
197 SkeletonToNames[
skeleton(Ident->getName())].push_back(Ident);
201 for (
auto &[Skel, Idents] : SkeletonToNames) {
202 if (Idents.size() < 2) {
208 for (
const IdentifierInfo *II : Idents) {
209 for (
auto [ND, Parent] : NameToDecls[II]) {
217 for (
const IdentifierInfo *II : Idents) {
218 for (
auto [OuterND, OuterParent] : NameToDecls[II]) {
219 for (Entry Inner : DeclsWithinContext[OuterParent]) {
221 if (OuterND->getIdentifier() == Inner.ND->getIdentifier())
226 if (OuterND->getAccess() == AS_private && Inner.FromDerivedClass)
231 if (OuterParent == Inner.Parent &&
232 Inner.ND->getASTContext()
234 .isBeforeInTranslationUnit(Inner.ND->getLocation(),
235 OuterND->getLocation()))
238 diag(Inner.ND->getLocation(),
"%0 is confusable with %1")
239 << Inner.ND << OuterND;
240 diag(OuterND->getLocation(),
"other declaration found here",
241 DiagnosticIDs::Note);
251 ast_matchers::MatchFinder *Finder) {
255 auto AnyParamDecl = ast_matchers::anyOf(
256 ast_matchers::parmVarDecl(), ast_matchers::templateTypeParmDecl(),
257 ast_matchers::nonTypeTemplateParmDecl(),
258 ast_matchers::templateTemplateParmDecl());
259 Finder->addMatcher(ast_matchers::namedDecl(ast_matchers::unless(AnyParamDecl))