[PATCH] D47623: [clangd] Avoid indexing decls associated with friend decls.
Eric Liu via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 1 12:14:44 PDT 2018
ioeric updated this revision to Diff 149526.
ioeric added a comment.
- Make canonical decls determinstic.
Repository:
rCTE Clang Tools Extra
https://reviews.llvm.org/D47623
Files:
clangd/index/SymbolCollector.cpp
clangd/index/SymbolCollector.h
unittests/clangd/SymbolCollectorTests.cpp
Index: unittests/clangd/SymbolCollectorTests.cpp
===================================================================
--- unittests/clangd/SymbolCollectorTests.cpp
+++ unittests/clangd/SymbolCollectorTests.cpp
@@ -812,6 +812,50 @@
QName("nx::Kind"), QName("nx::Kind_Fine")));
}
+TEST_F(SymbolCollectorTest, DoNotIndexSymbolsInFriendDecl) {
+ Annotations Header(R"(
+ namespace nx {
+ class $z[[Z]] {};
+ class X {
+ friend class Y;
+ friend class Z;
+ friend void foo();
+ friend void $bar[[bar]]() {}
+ };
+ class $y[[Y]] {};
+ void $foo[[foo]]();
+ }
+ )");
+ runSymbolCollector(Header.code(), /*Main=*/"");
+
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(
+ QName("nx"), QName("nx::X"),
+ AllOf(QName("nx::Y"), DeclRange(Header.range("y"))),
+ AllOf(QName("nx::Z"), DeclRange(Header.range("z"))),
+ AllOf(QName("nx::foo"), DeclRange(Header.range("foo"))),
+ AllOf(QName("nx::bar"), DeclRange(Header.range("bar")))));
+}
+
+TEST_F(SymbolCollectorTest, ReferencesInFriendDecl) {
+ const std::string Header = R"(
+ class X;
+ class Y;
+ )";
+ const std::string Main = R"(
+ class C {
+ friend ::X;
+ friend class Y;
+ };
+ )";
+ CollectorOpts.CountReferences = true;
+ runSymbolCollector(Header, Main);
+ for (const auto &Sym : Symbols)
+ llvm::errs() << Sym.Name << ": " << Sym.References << "\n";
+ EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), Refs(1)),
+ AllOf(QName("Y"), Refs(1))));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
Index: clangd/index/SymbolCollector.h
===================================================================
--- clangd/index/SymbolCollector.h
+++ clangd/index/SymbolCollector.h
@@ -80,6 +80,12 @@
Options Opts;
// Decls referenced from the current TU, flushed on finish().
llvm::DenseSet<const NamedDecl *> ReferencedDecls;
+ // Maps canonical declaration provided by clang to canonical declaration for
+ // an index symbol, if clangd prefers a different declaration than that
+ // provided by clang. For example, friend declaration might be considered
+ // canonical by clang but should not be considered canonical in the index
+ // unless it's a definition.
+ llvm::DenseMap<const Decl *, const Decl *> CanonicalDecls;
};
} // namespace clangd
Index: clangd/index/SymbolCollector.cpp
===================================================================
--- clangd/index/SymbolCollector.cpp
+++ clangd/index/SymbolCollector.cpp
@@ -290,6 +290,23 @@
index::IndexDataConsumer::ASTNodeInfo ASTNode) {
assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
assert(CompletionAllocator && CompletionTUInfo);
+ assert(ASTNode.OrigD);
+ // If OrigD is an declaration associated with a friend declaration and it's
+ // not a definition, skip it. Note that OrigD is the occurrence that the
+ // collector is currently visiting.
+ if ((ASTNode.OrigD->getFriendObjectKind() !=
+ Decl::FriendObjectKind::FOK_None) &&
+ !(Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
+ return true;
+ // A declaration created for a friend declaration should not be used as the
+ // canonical declaration in the index. If D is a defintion and is not OrigD,
+ // D would have been picked as the canonical declaration, if it has been
+ // visited, or OrigD, which could only be a non-friend declaration as multiple
+ // definitons are not possible, will be preferred.
+ if (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None)
+ // Either use a OrigD or a previous recorded canonical declaration as the
+ // canonical declaration.
+ D = CanonicalDecls.try_emplace(D, ASTNode.OrigD).first->second;
const NamedDecl *ND = llvm::dyn_cast<NamedDecl>(D);
if (!ND)
return true;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D47623.149526.patch
Type: text/x-patch
Size: 4002 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180601/d5461545/attachment.bin>
More information about the cfe-commits
mailing list