The heuristic is to look in the definition of the primary template,
which is what you want in the vast majority of cases.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
- Build Status
Buildable 42176 Build 42586: arc lint + arc unit
Event Timeline
Awesome, thanks, I'd been hoping to get around to this! LG with some naming/structure nits.
This doesn't handle references into smart pointers (details below), but feel free to do that in this patch, separately, or not at all.
clang-tools-extra/clangd/FindTarget.cpp | ||
---|---|---|
81–82 | while here, I think UnresolvedUsingValueDecl and UnresolvedUsingTypenameDecl can be added here :-) | |
217 | If I'm understanding the AST correctly, this drops the operator-> case, where the base is a smart-pointer. e.g. void run(unique_ptr<Action<T>> X) { X->go(); } There are potentially two reasons then that x->go is a *dependent* memberexpr:
So it might be worth trying to get the pointee type (if the base type is a TemplateSpecializationType, look up operator-> in the primary template, and replace the base with its return type). | |
255 | In the long term, I'm not sure this comment will be as useful as one saying something like: | |
278 | can we make this function return the decls, and make the callers call add() in a loop? That way this function could be reused for the operator-> lookup, and could be a standalone helper function outside this class. (Maybe eventually exposed in AST.h, as I can imagine it being useful in other places, but static in this file seems fine) | |
278 | with multiple lookup results we could add all, discard all, or pick one arbitrarily. I'm not sure what the best policy is, but it's worth pointing out in a comment what the cases are and what the choice is. I think this should only affects overloads, where returning all seems reasonable (resolution would be way too much work). Can you add a test? | |
clang-tools-extra/clangd/unittests/XRefsTests.cpp | ||
470 | nit: dependent method (just so it's easier to search for) | |
501 | could you add a test for the operator-> case too, even if we don't handle it yet? (in which case with a FIXME) Something like: template <typename T> struct unique_ptr<T> { T* operator->(); }; template <typename T> struct S { void [[foo]](); } template <typename T> void test(unique_ptr<S<T>>& V) { V->f^oo(); } |
unique_ptr is harder to get to work than it might appear at first blush :)
Looking at the gcc 6 libstdc++ implementation as an example: the declared return type of operator-> is not T*, but unique_ptr<T>::pointer. The declaration of that is in turn:
typedef typename _Pointer::type pointer;
The definition of _Pointer is in turn:
// use SFINAE to determine whether _Del::pointer exists class _Pointer { template<typename _Up> static typename _Up::pointer __test(typename _Up::pointer*); template<typename _Up> static _Tp* __test(...); typedef typename remove_reference<_Dp>::type _Del; public: typedef decltype(__test<_Del>(0)) type; };
Writing heuristics that see through all that might be possible, and I'm happy to explore it, but definitely in a follow-up.
clang-tools-extra/clangd/FindTarget.cpp | ||
---|---|---|
278 | Note, the additions to LocateSymbol.Ambiguous provide test coverage for this. |
Tests fail on Windows: http://45.33.8.238/win/3976/step_9.txt
Probably needs the usual -fno-delayed-template-parsing workaround, see other clangd tests.
while here, I think UnresolvedUsingValueDecl and UnresolvedUsingTypenameDecl can be added here :-)