1 //===--- HeuristicResolver.h - Resolution of dependent names -----*- C++-*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEURISTICRESOLVER_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEURISTICRESOLVER_H 11 12 #include "clang/AST/Decl.h" 13 #include <vector> 14 15 namespace clang { 16 17 class ASTContext; 18 class CallExpr; 19 class CXXDependentScopeMemberExpr; 20 class DeclarationName; 21 class DependentScopeDeclRefExpr; 22 class NamedDecl; 23 class Type; 24 class UnresolvedUsingValueDecl; 25 26 namespace clangd { 27 28 // This class heuristic resolution of declarations and types in template code. 29 // 30 // As a compiler, clang only needs to perform certain types of processing on 31 // template code (such as resolving dependent names to declarations, or 32 // resolving the type of a dependent expression) after instantiation. Indeed, 33 // C++ language features such as template specialization mean such resolution 34 // cannot be done accurately before instantiation 35 // 36 // However, template code is written and read in uninstantiated form, and clangd 37 // would like to provide editor features like go-to-definition in template code 38 // where possible. To this end, clangd attempts to resolve declarations and 39 // types in uninstantiated code by using heuristics, understanding that the 40 // results may not be fully accurate but that this is better than nothing. 41 // 42 // At this time, the heuristic used is a simple but effective one: assume that 43 // template instantiations are based on the primary template definition and not 44 // not a specialization. More advanced heuristics may be added in the future. 45 class HeuristicResolver { 46 public: HeuristicResolver(ASTContext & Ctx)47 HeuristicResolver(ASTContext &Ctx) : Ctx(Ctx) {} 48 49 // Try to heuristically resolve certain types of expressions, declarations, or 50 // types to one or more likely-referenced declarations. 51 std::vector<const NamedDecl *> 52 resolveMemberExpr(const CXXDependentScopeMemberExpr *ME) const; 53 std::vector<const NamedDecl *> 54 resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) const; 55 std::vector<const NamedDecl *> 56 resolveTypeOfCallExpr(const CallExpr *CE) const; 57 std::vector<const NamedDecl *> 58 resolveCalleeOfCallExpr(const CallExpr *CE) const; 59 std::vector<const NamedDecl *> 60 resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD) const; 61 std::vector<const NamedDecl *> 62 resolveDependentNameType(const DependentNameType *DNT) const; 63 std::vector<const NamedDecl *> resolveTemplateSpecializationType( 64 const DependentTemplateSpecializationType *DTST) const; 65 66 // Try to heuristically resolve a dependent nested name specifier 67 // to the type it likely denotes. Note that *dependent* name specifiers always 68 // denote types, not namespaces. 69 const Type * 70 resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS) const; 71 72 // Given the type T of a dependent expression that appears of the LHS of a 73 // "->", heuristically find a corresponding pointee type in whose scope we 74 // could look up the name appearing on the RHS. 75 const Type *getPointeeType(const Type *T) const; 76 77 private: 78 ASTContext &Ctx; 79 80 // Given a tag-decl type and a member name, heuristically resolve the 81 // name to one or more declarations. 82 // The current heuristic is simply to look up the name in the primary 83 // template. This is a heuristic because the template could potentially 84 // have specializations that declare different members. 85 // Multiple declarations could be returned if the name is overloaded 86 // (e.g. an overloaded method in the primary template). 87 // This heuristic will give the desired answer in many cases, e.g. 88 // for a call to vector<T>::size(). 89 std::vector<const NamedDecl *> resolveDependentMember( 90 const Type *T, DeclarationName Name, 91 llvm::function_ref<bool(const NamedDecl *ND)> Filter) const; 92 93 // Try to heuristically resolve the type of a possibly-dependent expression 94 // `E`. 95 const Type *resolveExprToType(const Expr *E) const; 96 std::vector<const NamedDecl *> resolveExprToDecls(const Expr *E) const; 97 }; 98 99 } // namespace clangd 100 } // namespace clang 101 102 #endif 103