xref: /freebsd/contrib/llvm-project/clang/include/clang/Sema/HeuristicResolver.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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