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_SEMA_HEURISTICRESOLVER_H 10 #define LLVM_CLANG_SEMA_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 CXXBasePath; 20 class CXXDependentScopeMemberExpr; 21 class DeclarationName; 22 class DependentScopeDeclRefExpr; 23 class FunctionProtoTypeLoc; 24 class NamedDecl; 25 class Type; 26 class UnresolvedUsingValueDecl; 27 28 // This class handles heuristic resolution of declarations and types in template 29 // code. 30 // 31 // As a compiler, clang only needs to perform certain types of processing on 32 // template code (such as resolving dependent names to declarations, or 33 // resolving the type of a dependent expression) after instantiation. Indeed, 34 // C++ language features such as template specialization mean such resolution 35 // cannot be done accurately before instantiation. 36 // 37 // However, template code is written and read in uninstantiated form, and clangd 38 // would like to provide editor features like go-to-definition in template code 39 // where possible. To this end, clangd attempts to resolve declarations and 40 // types in uninstantiated code by using heuristics, understanding that the 41 // results may not be fully accurate but that this is better than nothing. 42 // 43 // At this time, the heuristic used is a simple but effective one: assume that 44 // template instantiations are based on the primary template definition and not 45 // not a specialization. More advanced heuristics may be added in the future. 46 class HeuristicResolver { 47 public: HeuristicResolver(ASTContext & Ctx)48 HeuristicResolver(ASTContext &Ctx) : Ctx(Ctx) {} 49 50 // Try to heuristically resolve certain types of expressions, declarations, or 51 // types to one or more likely-referenced declarations. 52 std::vector<const NamedDecl *> 53 resolveMemberExpr(const CXXDependentScopeMemberExpr *ME) const; 54 std::vector<const NamedDecl *> 55 resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) const; 56 std::vector<const NamedDecl *> 57 resolveTypeOfCallExpr(const CallExpr *CE) const; 58 std::vector<const NamedDecl *> 59 resolveCalleeOfCallExpr(const CallExpr *CE) const; 60 std::vector<const NamedDecl *> 61 resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD) const; 62 std::vector<const NamedDecl *> 63 resolveDependentNameType(const DependentNameType *DNT) const; 64 std::vector<const NamedDecl *> resolveTemplateSpecializationType( 65 const DependentTemplateSpecializationType *DTST) const; 66 67 // Try to heuristically resolve a dependent nested name specifier 68 // to the type it likely denotes. Note that *dependent* name specifiers always 69 // denote types, not namespaces. 70 QualType 71 resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS) const; 72 73 // Perform an imprecise lookup of a dependent name in `RD`. 74 // This function does not follow strict semantic rules and should be used 75 // only when lookup rules can be relaxed, e.g. indexing. 76 std::vector<const NamedDecl *> 77 lookupDependentName(CXXRecordDecl *RD, DeclarationName Name, 78 llvm::function_ref<bool(const NamedDecl *ND)> Filter); 79 80 // Given the type T of a dependent expression that appears of the LHS of a 81 // "->", heuristically find a corresponding pointee type in whose scope we 82 // could look up the name appearing on the RHS. 83 const QualType getPointeeType(QualType T) const; 84 85 // Heuristically resolve a possibly-dependent type `T` to a TagDecl 86 // in which a member's name can be looked up. 87 TagDecl *resolveTypeToTagDecl(QualType T) const; 88 89 // Simplify the type `Type`. 90 // `E` is the expression whose type `Type` is, if known. This sometimes 91 // contains information relevant to the type that's not stored in `Type` 92 // itself. 93 // If `UnwrapPointer` is true, exactly only pointer type will be unwrapped 94 // during simplification, and the operation fails if no pointer type is found. 95 QualType simplifyType(QualType Type, const Expr *E, bool UnwrapPointer); 96 97 // Given an expression `Fn` representing the callee in a function call, 98 // if the call is through a function pointer, try to find the declaration of 99 // the corresponding function pointer type, so that we can recover argument 100 // names from it. 101 FunctionProtoTypeLoc getFunctionProtoTypeLoc(const Expr *Fn) const; 102 103 private: 104 ASTContext &Ctx; 105 }; 106 107 } // namespace clang 108 109 #endif 110