diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -34,6 +34,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/Type.h" +#include "clang/AST/TypeVisitor.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" @@ -463,6 +464,31 @@ return Result; } +// Unwrap a type for the purposes of go-to-definition on auto. +// e.g. pointer types - there's no definition for Foo*, so show class Foo. +// We could consider unwrapping unique_ptr too - confusing? slippery slope? +// We could also move this into targetDecl(), but it's semantically iffy. +QualType unwrapType(QualType T) { + struct OneStepUnwrap : TypeVisitor { + QualType VisitType(const Type *T) { return QualType(); } + QualType VisitArrayType(const ArrayType *T) { return T->getElementType(); } + QualType VisitPointerType(const PointerType *T) { + return T->getPointeeType(); + } + QualType VisitReferenceType(const ReferenceType *T) { + return T->getPointeeTypeAsWritten(); + } + } Unwrap; + if (T.isNull()) + return T; + while (true) { + QualType Next = Unwrap.Visit(T.getTypePtr()); + if (Next.isNull()) + return T; + T = Next; + } +} + std::vector locateSymbolForType(const ParsedAST &AST, const QualType &Type) { const auto &SM = AST.getSourceManager(); @@ -473,7 +499,7 @@ return {}; } - auto Decls = targetDecl(DynTypedNode::create(Type.getNonReferenceType()), + auto Decls = targetDecl(DynTypedNode::create(unwrapType(Type)), DeclRelation::TemplatePattern | DeclRelation::Alias); if (Decls.empty()) return {}; diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -657,6 +657,13 @@ ^auto x = ns1::S1{}; )cpp", + R"cpp(// auto unwraps pointers + struct [[S]] {}; + S **const*&y(); + + ^auto x = y(); + )cpp", + R"cpp(// decltype on struct namespace ns1 { struct [[S1]] {};