1 //===--- HeuristicResolver.cpp ---------------------------*- 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 #include "HeuristicResolver.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/DeclTemplate.h"
12 #include "clang/AST/ExprCXX.h"
13 
14 namespace clang {
15 namespace clangd {
16 
17 // Convenience lambdas for use as the 'Filter' parameter of
18 // HeuristicResolver::resolveDependentMember().
__anon51be05cd0102(const NamedDecl *D) 19 const auto NoFilter = [](const NamedDecl *D) { return true; };
__anon51be05cd0202(const NamedDecl *D) 20 const auto NonStaticFilter = [](const NamedDecl *D) {
21   return D->isCXXInstanceMember();
22 };
__anon51be05cd0302(const NamedDecl *D) 23 const auto StaticFilter = [](const NamedDecl *D) {
24   return !D->isCXXInstanceMember();
25 };
__anon51be05cd0402(const NamedDecl *D) 26 const auto ValueFilter = [](const NamedDecl *D) { return isa<ValueDecl>(D); };
__anon51be05cd0502(const NamedDecl *D) 27 const auto TypeFilter = [](const NamedDecl *D) { return isa<TypeDecl>(D); };
__anon51be05cd0602(const NamedDecl *D) 28 const auto TemplateFilter = [](const NamedDecl *D) {
29   return isa<TemplateDecl>(D);
30 };
31 
32 // Helper function for HeuristicResolver::resolveDependentMember()
33 // which takes a possibly-dependent type `T` and heuristically
34 // resolves it to a CXXRecordDecl in which we can try name lookup.
resolveTypeToRecordDecl(const Type * T)35 CXXRecordDecl *resolveTypeToRecordDecl(const Type *T) {
36   assert(T);
37 
38   if (const auto *RT = T->getAs<RecordType>())
39     return dyn_cast<CXXRecordDecl>(RT->getDecl());
40 
41   if (const auto *ICNT = T->getAs<InjectedClassNameType>())
42     T = ICNT->getInjectedSpecializationType().getTypePtrOrNull();
43   if (!T)
44     return nullptr;
45 
46   const auto *TST = T->getAs<TemplateSpecializationType>();
47   if (!TST)
48     return nullptr;
49 
50   const ClassTemplateDecl *TD = dyn_cast_or_null<ClassTemplateDecl>(
51       TST->getTemplateName().getAsTemplateDecl());
52   if (!TD)
53     return nullptr;
54 
55   return TD->getTemplatedDecl();
56 }
57 
getPointeeType(const Type * T) const58 const Type *HeuristicResolver::getPointeeType(const Type *T) const {
59   if (!T)
60     return nullptr;
61 
62   if (T->isPointerType())
63     return T->castAs<PointerType>()->getPointeeType().getTypePtrOrNull();
64 
65   // Try to handle smart pointer types.
66 
67   // Look up operator-> in the primary template. If we find one, it's probably a
68   // smart pointer type.
69   auto ArrowOps = resolveDependentMember(
70       T, Ctx.DeclarationNames.getCXXOperatorName(OO_Arrow), NonStaticFilter);
71   if (ArrowOps.empty())
72     return nullptr;
73 
74   // Getting the return type of the found operator-> method decl isn't useful,
75   // because we discarded template arguments to perform lookup in the primary
76   // template scope, so the return type would just have the form U* where U is a
77   // template parameter type.
78   // Instead, just handle the common case where the smart pointer type has the
79   // form of SmartPtr<X, ...>, and assume X is the pointee type.
80   auto *TST = T->getAs<TemplateSpecializationType>();
81   if (!TST)
82     return nullptr;
83   if (TST->getNumArgs() == 0)
84     return nullptr;
85   const TemplateArgument &FirstArg = TST->getArg(0);
86   if (FirstArg.getKind() != TemplateArgument::Type)
87     return nullptr;
88   return FirstArg.getAsType().getTypePtrOrNull();
89 }
90 
resolveMemberExpr(const CXXDependentScopeMemberExpr * ME) const91 std::vector<const NamedDecl *> HeuristicResolver::resolveMemberExpr(
92     const CXXDependentScopeMemberExpr *ME) const {
93   // If the expression has a qualifier, first try resolving the member
94   // inside the qualifier's type.
95   // Note that we cannot use a NonStaticFilter in either case, for a couple
96   // of reasons:
97   //   1. It's valid to access a static member using instance member syntax,
98   //      e.g. `instance.static_member`.
99   //   2. We can sometimes get a CXXDependentScopeMemberExpr for static
100   //      member syntax too, e.g. if `X::static_member` occurs inside
101   //      an instance method, it's represented as a CXXDependentScopeMemberExpr
102   //      with `this` as the base expression as `X` as the qualifier
103   //      (which could be valid if `X` names a base class after instantiation).
104   if (NestedNameSpecifier *NNS = ME->getQualifier()) {
105     if (const Type *QualifierType = resolveNestedNameSpecifierToType(NNS)) {
106       auto Decls =
107           resolveDependentMember(QualifierType, ME->getMember(), NoFilter);
108       if (!Decls.empty())
109         return Decls;
110     }
111   }
112 
113   // If that didn't yield any results, try resolving the member inside
114   // the expression's base type.
115   const Type *BaseType = ME->getBaseType().getTypePtrOrNull();
116   if (ME->isArrow()) {
117     BaseType = getPointeeType(BaseType);
118   }
119   if (!BaseType)
120     return {};
121   if (const auto *BT = BaseType->getAs<BuiltinType>()) {
122     // If BaseType is the type of a dependent expression, it's just
123     // represented as BultinType::Dependent which gives us no information. We
124     // can get further by analyzing the depedent expression.
125     Expr *Base = ME->isImplicitAccess() ? nullptr : ME->getBase();
126     if (Base && BT->getKind() == BuiltinType::Dependent) {
127       BaseType = resolveExprToType(Base);
128     }
129   }
130   return resolveDependentMember(BaseType, ME->getMember(), NoFilter);
131 }
132 
resolveDeclRefExpr(const DependentScopeDeclRefExpr * RE) const133 std::vector<const NamedDecl *> HeuristicResolver::resolveDeclRefExpr(
134     const DependentScopeDeclRefExpr *RE) const {
135   return resolveDependentMember(RE->getQualifier()->getAsType(),
136                                 RE->getDeclName(), StaticFilter);
137 }
138 
139 std::vector<const NamedDecl *>
resolveTypeOfCallExpr(const CallExpr * CE) const140 HeuristicResolver::resolveTypeOfCallExpr(const CallExpr *CE) const {
141   const auto *CalleeType = resolveExprToType(CE->getCallee());
142   if (!CalleeType)
143     return {};
144   if (const auto *FnTypePtr = CalleeType->getAs<PointerType>())
145     CalleeType = FnTypePtr->getPointeeType().getTypePtr();
146   if (const FunctionType *FnType = CalleeType->getAs<FunctionType>()) {
147     if (const auto *D =
148             resolveTypeToRecordDecl(FnType->getReturnType().getTypePtr())) {
149       return {D};
150     }
151   }
152   return {};
153 }
154 
155 std::vector<const NamedDecl *>
resolveCalleeOfCallExpr(const CallExpr * CE) const156 HeuristicResolver::resolveCalleeOfCallExpr(const CallExpr *CE) const {
157   if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
158     return {ND};
159   }
160 
161   return resolveExprToDecls(CE->getCallee());
162 }
163 
resolveUsingValueDecl(const UnresolvedUsingValueDecl * UUVD) const164 std::vector<const NamedDecl *> HeuristicResolver::resolveUsingValueDecl(
165     const UnresolvedUsingValueDecl *UUVD) const {
166   return resolveDependentMember(UUVD->getQualifier()->getAsType(),
167                                 UUVD->getNameInfo().getName(), ValueFilter);
168 }
169 
resolveDependentNameType(const DependentNameType * DNT) const170 std::vector<const NamedDecl *> HeuristicResolver::resolveDependentNameType(
171     const DependentNameType *DNT) const {
172   return resolveDependentMember(
173       resolveNestedNameSpecifierToType(DNT->getQualifier()),
174       DNT->getIdentifier(), TypeFilter);
175 }
176 
177 std::vector<const NamedDecl *>
resolveTemplateSpecializationType(const DependentTemplateSpecializationType * DTST) const178 HeuristicResolver::resolveTemplateSpecializationType(
179     const DependentTemplateSpecializationType *DTST) const {
180   return resolveDependentMember(
181       resolveNestedNameSpecifierToType(DTST->getQualifier()),
182       DTST->getIdentifier(), TemplateFilter);
183 }
184 
resolveDeclsToType(const std::vector<const NamedDecl * > & Decls)185 const Type *resolveDeclsToType(const std::vector<const NamedDecl *> &Decls) {
186   if (Decls.size() != 1) // Names an overload set -- just bail.
187     return nullptr;
188   if (const auto *TD = dyn_cast<TypeDecl>(Decls[0])) {
189     return TD->getTypeForDecl();
190   }
191   if (const auto *VD = dyn_cast<ValueDecl>(Decls[0])) {
192     return VD->getType().getTypePtrOrNull();
193   }
194   return nullptr;
195 }
196 
197 std::vector<const NamedDecl *>
resolveExprToDecls(const Expr * E) const198 HeuristicResolver::resolveExprToDecls(const Expr *E) const {
199   if (const auto *ME = dyn_cast<CXXDependentScopeMemberExpr>(E)) {
200     return resolveMemberExpr(ME);
201   }
202   if (const auto *RE = dyn_cast<DependentScopeDeclRefExpr>(E)) {
203     return resolveDeclRefExpr(RE);
204   }
205   if (const auto *OE = dyn_cast<OverloadExpr>(E)) {
206     return {OE->decls_begin(), OE->decls_end()};
207   }
208   if (const auto *CE = dyn_cast<CallExpr>(E)) {
209     return resolveTypeOfCallExpr(CE);
210   }
211   if (const auto *ME = dyn_cast<MemberExpr>(E))
212     return {ME->getMemberDecl()};
213 
214   return {};
215 }
216 
resolveExprToType(const Expr * E) const217 const Type *HeuristicResolver::resolveExprToType(const Expr *E) const {
218   std::vector<const NamedDecl *> Decls = resolveExprToDecls(E);
219   if (!Decls.empty())
220     return resolveDeclsToType(Decls);
221 
222   return E->getType().getTypePtr();
223 }
224 
resolveNestedNameSpecifierToType(const NestedNameSpecifier * NNS) const225 const Type *HeuristicResolver::resolveNestedNameSpecifierToType(
226     const NestedNameSpecifier *NNS) const {
227   if (!NNS)
228     return nullptr;
229 
230   // The purpose of this function is to handle the dependent (Kind ==
231   // Identifier) case, but we need to recurse on the prefix because
232   // that may be dependent as well, so for convenience handle
233   // the TypeSpec cases too.
234   switch (NNS->getKind()) {
235   case NestedNameSpecifier::TypeSpec:
236   case NestedNameSpecifier::TypeSpecWithTemplate:
237     return NNS->getAsType();
238   case NestedNameSpecifier::Identifier: {
239     return resolveDeclsToType(resolveDependentMember(
240         resolveNestedNameSpecifierToType(NNS->getPrefix()),
241         NNS->getAsIdentifier(), TypeFilter));
242   }
243   default:
244     break;
245   }
246   return nullptr;
247 }
248 
resolveDependentMember(const Type * T,DeclarationName Name,llvm::function_ref<bool (const NamedDecl * ND)> Filter) const249 std::vector<const NamedDecl *> HeuristicResolver::resolveDependentMember(
250     const Type *T, DeclarationName Name,
251     llvm::function_ref<bool(const NamedDecl *ND)> Filter) const {
252   if (!T)
253     return {};
254   if (auto *ET = T->getAs<EnumType>()) {
255     auto Result = ET->getDecl()->lookup(Name);
256     return {Result.begin(), Result.end()};
257   }
258   if (auto *RD = resolveTypeToRecordDecl(T)) {
259     if (!RD->hasDefinition())
260       return {};
261     RD = RD->getDefinition();
262     return RD->lookupDependentName(Name, Filter);
263   }
264   return {};
265 }
266 
267 } // namespace clangd
268 } // namespace clang
269