tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

HeuristicResolver.h (5442B)


      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 CXXBasePath;
     20 class CXXDependentScopeMemberExpr;
     21 class DeclarationName;
     22 class DependentScopeDeclRefExpr;
     23 class NamedDecl;
     24 class Type;
     25 class UnresolvedUsingValueDecl;
     26 
     27 namespace clangd {
     28 
     29 // This class heuristic resolution of declarations and types in template 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:
     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  const Type *
     71  resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS) const;
     72 
     73  // Given the type T of a dependent expression that appears of the LHS of a
     74  // "->", heuristically find a corresponding pointee type in whose scope we
     75  // could look up the name appearing on the RHS.
     76  const Type *getPointeeType(const Type *T) const;
     77 
     78 private:
     79  ASTContext &Ctx;
     80 
     81  // Given a tag-decl type and a member name, heuristically resolve the
     82  // name to one or more declarations.
     83  // The current heuristic is simply to look up the name in the primary
     84  // template. This is a heuristic because the template could potentially
     85  // have specializations that declare different members.
     86  // Multiple declarations could be returned if the name is overloaded
     87  // (e.g. an overloaded method in the primary template).
     88  // This heuristic will give the desired answer in many cases, e.g.
     89  // for a call to vector<T>::size().
     90  std::vector<const NamedDecl *> resolveDependentMember(
     91      const Type *T, DeclarationName Name,
     92      llvm::function_ref<bool(const NamedDecl *ND)> Filter) const;
     93 
     94  // Try to heuristically resolve the type of a possibly-dependent expression
     95  // `E`.
     96  const Type *resolveExprToType(const Expr *E) const;
     97  std::vector<const NamedDecl *> resolveExprToDecls(const Expr *E) const;
     98 
     99  // Helper function for HeuristicResolver::resolveDependentMember()
    100  // which takes a possibly-dependent type `T` and heuristically
    101  // resolves it to a CXXRecordDecl in which we can try name lookup.
    102  CXXRecordDecl *resolveTypeToRecordDecl(const Type *T) const;
    103 
    104  // This is a reimplementation of CXXRecordDecl::lookupDependentName()
    105  // so that the implementation can call into other HeuristicResolver helpers.
    106  // FIXME: Once HeuristicResolver is upstreamed to the clang libraries
    107  // (https://github.com/clangd/clangd/discussions/1662),
    108  // CXXRecordDecl::lookupDepenedentName() can be removed, and its call sites
    109  // can be modified to benefit from the more comprehensive heuristics offered
    110  // by HeuristicResolver instead.
    111  std::vector<const NamedDecl *> lookupDependentName(
    112      CXXRecordDecl *RD, DeclarationName Name,
    113      llvm::function_ref<bool(const NamedDecl *ND)> Filter) const;
    114  bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier,
    115                                            CXXBasePath &Path,
    116                                            DeclarationName Name) const;
    117 };
    118 
    119 } // namespace clangd
    120 } // namespace clang
    121 
    122 #endif