This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Prefer the definition of a TagDecl (e.g. class) as CanonicalDeclaration.
ClosedPublic

Authored by ioeric on Feb 27 2018, 8:39 AM.

Details

Summary

Currently, we pick the first declaration of a symbol in a TU, which is considered
canonical in the clangIndex, as the canonical declaration in clangd. This causes
forward declarations that might appear in a random header to be used as a
canonical declaration, which is not desirable for features like go-to-declaration
or include insertion.

For example, for class X, we would consider the forward declaration in fwd.h to
be the canonical declaration, while the preferred canonical declaration should
be the actual definition in x.h.

// fwd.h
class X;  // forward decl

// x.h
class X {};

This patch fixes the issue by making symbol collector favor the actual definition of
a TagDecl (i.e. class/struct/enum/union) found in a header file over the first seen
declarations in a TU. Other symbol types like functions are not handled because
using the first seen declarations as canonical declarations is usually a good
heuristic for them.

The patch also removes the IncludeMainFile option from SymbolCollector because no user of SymbolCollector collects symbols in main files.

Diff Detail

Repository
rL LLVM

Event Timeline

ioeric created this revision.Feb 27 2018, 8:39 AM
ioeric edited the summary of this revision. (Show Details)Feb 27 2018, 8:41 AM
sammccall accepted this revision.Feb 27 2018, 9:59 AM
sammccall added inline comments.
clangd/index/FileIndex.cpp
23 ↗(On Diff #136085)

this comment doesn't make sense here anymore. I think it's ok just to remove, otherwise add to the documentation of symbolcollector I guess.

clangd/index/SymbolCollector.cpp
260 ↗(On Diff #136085)

This is a bit subtle and I think comment-worthy.
We're doing a bunch of duplicated work, but at most once because we expect to see only one preferred declaration per TU, because in practice they're definitions?

An alternative would be to have addDeclaration loop through the redecls to try to find a preferred one (and use the passed in one if none is found). This would avoid any duplicated work. Up to you.

289 ↗(On Diff #136085)

You're addressing this fixme. (I expected it to be done inside addDeclaration, which is why the fixme is here - may still be a good idea as noted above).

unittests/clangd/SymbolCollectorTests.cpp
218 ↗(On Diff #136085)

please keep this and verify it's not indexed.

222 ↗(On Diff #136085)

i'm not sure it's necessary to assert the file - it's inconsistent (i don't think there's anything special about this one?) and would add a lot of noise to do consistently.

There's not much risk of an actual collision, right? up to you though

This revision is now accepted and ready to land.Feb 27 2018, 9:59 AM
ioeric updated this revision to Diff 136247.Feb 28 2018, 1:34 AM
ioeric marked 5 inline comments as done.
  • Addressed review comments.
clangd/index/SymbolCollector.cpp
260 ↗(On Diff #136085)

The reason why I am a bit hesitant to use redecls is that we wouldn't know whether all re-declarations would have been indexed (e.g. there might be implicit decls that were dropped by the index library) and passed the filters we had (e.g. shouldFilterDecl). And you are right, the duplicated work should usually be little. I added a comment to clarify the duplicated work.

This revision was automatically updated to reflect the committed changes.
This revision was automatically updated to reflect the committed changes.