[PATCH] D42796: [clangd] Skip inline namespace when collecting scopes for index symbols.
Eric Liu via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 2 02:19:52 PST 2018
ioeric added inline comments.
================
Comment at: clangd/index/SymbolCollector.cpp:69
+// qualifier. Inline namespaces and unscoped enums are skipped.
+llvm::Expected<std::string> getScope(const NamedDecl *ND) {
+ llvm::SmallVector<llvm::StringRef, 4> Contexts;
----------------
hokein wrote:
> There is a `SuppressUnwrittenScope` option in `PrintingPolicy`, I think we can probably use `printQualifiedName` with our customized policy (setting `SuppressUnwrittenScope` to true) here.
This is perfect! Thank you!
================
Comment at: clangd/index/SymbolCollector.cpp:73
+ Context = Context->getParent()) {
+ if (llvm::isa<TranslationUnitDecl>(Context) ||
+ llvm::isa<LinkageSpecDecl>(Context))
----------------
sammccall wrote:
> I'm not sure this is always correct: at least clang accepts this code:
>
> namespace X { extern "C++" { int y; }}
>
> and you'll emit "y" instead of "X::y".
>
> I think the check you want is
>
> if (Context->isTransparentContext() || Context->isInlineNamespace())
> continue;
>
> isTransparentContext will handle the Namespace and Enum cases as you do below, including the enum/enum class distinction.
>
> (The code you have below is otherwise correct, I think - but a reader needs to think about more separate cases in order to see that)
In `namespace X { extern "C++" { int y; }}`, we would still want `y` instead of `X::y` since C-style symbol doesn't have scope. `printQualifiedName` also does the same thing printing `y`; I've added a test case for `extern C`.
I also realized we've been dropping C symbols in `shouldFilterDecl` and fixed it in the same patch.
================
Comment at: clangd/index/SymbolCollector.cpp:74
+ if (llvm::isa<TranslationUnitDecl>(Context) ||
+ llvm::isa<LinkageSpecDecl>(Context))
+ break;
----------------
ilya-biryukov wrote:
> I may not know enough about the AST, sorry if the question is obvious.
> `TranslationUnitDecl` is the root of the tree, but why should we stop at `LinkageSpecDecl`?
>
> This code is probably going away per @hokein's comments.
Symbols in `LinkageSpecDecl` (i.e. `extern "C"`) are C style symbols and do not have scopes. Also see my reply to Sam's related comment.
================
Comment at: clangd/index/SymbolCollector.cpp:195
llvm::SmallString<128> USR;
+ if (ND->getIdentifier() == nullptr)
+ return true;
----------------
ilya-biryukov wrote:
> sammccall wrote:
> > hokein wrote:
> > > Consider moving to `shouldFilterDecl`? We also have a check `if (ND->getDeclName().isEmpty())` there, which I assume does similar thing.
> > hmm, what case is this handling? should `shouldFilterDecl` catch it?
> Why do we skip names without identifiers? AFAIK, they are perfectly reasonable C++ entities: overloaded operators, constructors, etc.
`getName` crashes for `NamedDecl` without identifier. I thought symbols without identifier are not interesting for global code completion, so I added this filter to avoid crash. But on a second thought, these symbols would still be useful for go-to-definition, for example.
This is no longer needed with `printQualifiedName` though.
Repository:
rCTE Clang Tools Extra
https://reviews.llvm.org/D42796
More information about the cfe-commits
mailing list