xref: /freebsd/contrib/llvm-project/clang/lib/Sema/HeuristicResolver.cpp (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
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 "clang/Sema/HeuristicResolver.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/CXXInheritance.h"
12 #include "clang/AST/DeclTemplate.h"
13 #include "clang/AST/ExprCXX.h"
14 #include "clang/AST/TemplateBase.h"
15 #include "clang/AST/Type.h"
16 #include "llvm/ADT/identity.h"
17 
18 namespace clang {
19 
20 namespace {
21 
22 // Helper class for implementing HeuristicResolver.
23 // Unlike HeuristicResolver which is a long-lived class,
24 // a new instance of this class is created for every external
25 // call into a HeuristicResolver operation. That allows this
26 // class to store state that's local to such a top-level call,
27 // particularly "recursion protection sets" that keep track of
28 // nodes that have already been seen to avoid infinite recursion.
29 class HeuristicResolverImpl {
30 public:
31   HeuristicResolverImpl(ASTContext &Ctx) : Ctx(Ctx) {}
32 
33   // These functions match the public interface of HeuristicResolver
34   // (but aren't const since they may modify the recursion protection sets).
35   std::vector<const NamedDecl *>
36   resolveMemberExpr(const CXXDependentScopeMemberExpr *ME);
37   std::vector<const NamedDecl *>
38   resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE);
39   std::vector<const NamedDecl *> resolveTypeOfCallExpr(const CallExpr *CE);
40   std::vector<const NamedDecl *> resolveCalleeOfCallExpr(const CallExpr *CE);
41   std::vector<const NamedDecl *>
42   resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD);
43   std::vector<const NamedDecl *>
44   resolveDependentNameType(const DependentNameType *DNT);
45   std::vector<const NamedDecl *> resolveTemplateSpecializationType(
46       const DependentTemplateSpecializationType *DTST);
47   QualType resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS);
48   QualType getPointeeType(QualType T);
49   std::vector<const NamedDecl *>
50   lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
51                       llvm::function_ref<bool(const NamedDecl *ND)> Filter);
52   TagDecl *resolveTypeToTagDecl(QualType T);
53   QualType simplifyType(QualType Type, const Expr *E, bool UnwrapPointer);
54   FunctionProtoTypeLoc getFunctionProtoTypeLoc(const Expr *Fn);
55 
56 private:
57   ASTContext &Ctx;
58 
59   // Recursion protection sets
60   llvm::SmallSet<const DependentNameType *, 4> SeenDependentNameTypes;
61 
62   // Given a tag-decl type and a member name, heuristically resolve the
63   // name to one or more declarations.
64   // The current heuristic is simply to look up the name in the primary
65   // template. This is a heuristic because the template could potentially
66   // have specializations that declare different members.
67   // Multiple declarations could be returned if the name is overloaded
68   // (e.g. an overloaded method in the primary template).
69   // This heuristic will give the desired answer in many cases, e.g.
70   // for a call to vector<T>::size().
71   std::vector<const NamedDecl *>
72   resolveDependentMember(QualType T, DeclarationName Name,
73                          llvm::function_ref<bool(const NamedDecl *ND)> Filter);
74 
75   // Try to heuristically resolve the type of a possibly-dependent expression
76   // `E`.
77   QualType resolveExprToType(const Expr *E);
78   std::vector<const NamedDecl *> resolveExprToDecls(const Expr *E);
79 
80   bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier,
81                                             CXXBasePath &Path,
82                                             DeclarationName Name);
83 };
84 
85 // Convenience lambdas for use as the 'Filter' parameter of
86 // HeuristicResolver::resolveDependentMember().
87 const auto NoFilter = [](const NamedDecl *D) { return true; };
88 const auto NonStaticFilter = [](const NamedDecl *D) {
89   return D->isCXXInstanceMember();
90 };
91 const auto StaticFilter = [](const NamedDecl *D) {
92   return !D->isCXXInstanceMember();
93 };
94 const auto ValueFilter = [](const NamedDecl *D) { return isa<ValueDecl>(D); };
95 const auto TypeFilter = [](const NamedDecl *D) { return isa<TypeDecl>(D); };
96 const auto TemplateFilter = [](const NamedDecl *D) {
97   return isa<TemplateDecl>(D);
98 };
99 
100 QualType resolveDeclsToType(const std::vector<const NamedDecl *> &Decls,
101                             ASTContext &Ctx) {
102   if (Decls.size() != 1) // Names an overload set -- just bail.
103     return QualType();
104   if (const auto *TD = dyn_cast<TypeDecl>(Decls[0])) {
105     return Ctx.getTypeDeclType(TD);
106   }
107   if (const auto *VD = dyn_cast<ValueDecl>(Decls[0])) {
108     return VD->getType();
109   }
110   return QualType();
111 }
112 
113 TemplateName getReferencedTemplateName(const Type *T) {
114   if (const auto *TST = T->getAs<TemplateSpecializationType>()) {
115     return TST->getTemplateName();
116   }
117   if (const auto *DTST = T->getAs<DeducedTemplateSpecializationType>()) {
118     return DTST->getTemplateName();
119   }
120   return TemplateName();
121 }
122 
123 // Helper function for HeuristicResolver::resolveDependentMember()
124 // which takes a possibly-dependent type `T` and heuristically
125 // resolves it to a CXXRecordDecl in which we can try name lookup.
126 TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) {
127   const Type *T = QT.getTypePtrOrNull();
128   if (!T)
129     return nullptr;
130 
131   // Unwrap type sugar such as type aliases.
132   T = T->getCanonicalTypeInternal().getTypePtr();
133 
134   if (const auto *DNT = T->getAs<DependentNameType>()) {
135     T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx)
136             .getTypePtrOrNull();
137     if (!T)
138       return nullptr;
139     T = T->getCanonicalTypeInternal().getTypePtr();
140   }
141 
142   if (auto *TT = T->getAs<TagType>()) {
143     TagDecl *TD = TT->getDecl();
144     // Template might not be instantiated yet, fall back to primary template
145     // in such cases.
146     if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) {
147       if (CTSD->getTemplateSpecializationKind() == TSK_Undeclared) {
148         return CTSD->getSpecializedTemplate()->getTemplatedDecl();
149       }
150     }
151     return TD;
152   }
153 
154   if (const auto *ICNT = T->getAs<InjectedClassNameType>())
155     T = ICNT->getInjectedSpecializationType().getTypePtrOrNull();
156   if (!T)
157     return nullptr;
158 
159   TemplateName TN = getReferencedTemplateName(T);
160   if (TN.isNull())
161     return nullptr;
162 
163   const ClassTemplateDecl *TD =
164       dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
165   if (!TD)
166     return nullptr;
167 
168   return TD->getTemplatedDecl();
169 }
170 
171 QualType HeuristicResolverImpl::getPointeeType(QualType T) {
172   if (T.isNull())
173     return QualType();
174 
175   if (T->isPointerType())
176     return T->castAs<PointerType>()->getPointeeType();
177 
178   // Try to handle smart pointer types.
179 
180   // Look up operator-> in the primary template. If we find one, it's probably a
181   // smart pointer type.
182   auto ArrowOps = resolveDependentMember(
183       T, Ctx.DeclarationNames.getCXXOperatorName(OO_Arrow), NonStaticFilter);
184   if (ArrowOps.empty())
185     return QualType();
186 
187   // Getting the return type of the found operator-> method decl isn't useful,
188   // because we discarded template arguments to perform lookup in the primary
189   // template scope, so the return type would just have the form U* where U is a
190   // template parameter type.
191   // Instead, just handle the common case where the smart pointer type has the
192   // form of SmartPtr<X, ...>, and assume X is the pointee type.
193   auto *TST = T->getAs<TemplateSpecializationType>();
194   if (!TST)
195     return QualType();
196   if (TST->template_arguments().size() == 0)
197     return QualType();
198   const TemplateArgument &FirstArg = TST->template_arguments()[0];
199   if (FirstArg.getKind() != TemplateArgument::Type)
200     return QualType();
201   return FirstArg.getAsType();
202 }
203 
204 QualType HeuristicResolverImpl::simplifyType(QualType Type, const Expr *E,
205                                              bool UnwrapPointer) {
206   bool DidUnwrapPointer = false;
207   // A type, together with an optional expression whose type it represents
208   // which may have additional information about the expression's type
209   // not stored in the QualType itself.
210   struct TypeExprPair {
211     QualType Type;
212     const Expr *E = nullptr;
213   };
214   TypeExprPair Current{Type, E};
215   auto SimplifyOneStep = [UnwrapPointer, &DidUnwrapPointer,
216                           this](TypeExprPair T) -> TypeExprPair {
217     if (UnwrapPointer) {
218       if (QualType Pointee = getPointeeType(T.Type); !Pointee.isNull()) {
219         DidUnwrapPointer = true;
220         return {Pointee};
221       }
222     }
223     if (const auto *RT = T.Type->getAs<ReferenceType>()) {
224       // Does not count as "unwrap pointer".
225       return {RT->getPointeeType()};
226     }
227     if (const auto *BT = T.Type->getAs<BuiltinType>()) {
228       // If BaseType is the type of a dependent expression, it's just
229       // represented as BuiltinType::Dependent which gives us no information. We
230       // can get further by analyzing the dependent expression.
231       if (T.E && BT->getKind() == BuiltinType::Dependent) {
232         return {resolveExprToType(T.E), T.E};
233       }
234     }
235     if (const auto *AT = T.Type->getContainedAutoType()) {
236       // If T contains a dependent `auto` type, deduction will not have
237       // been performed on it yet. In simple cases (e.g. `auto` variable with
238       // initializer), get the approximate type that would result from
239       // deduction.
240       // FIXME: A more accurate implementation would propagate things like the
241       // `const` in `const auto`.
242       if (T.E && AT->isUndeducedAutoType()) {
243         if (const auto *DRE = dyn_cast<DeclRefExpr>(T.E)) {
244           if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
245             if (auto *Init = VD->getInit())
246               return {resolveExprToType(Init), Init};
247           }
248         }
249       }
250     }
251     if (const auto *TTPT = dyn_cast_if_present<TemplateTypeParmType>(T.Type)) {
252       // We can't do much useful with a template parameter (e.g. we cannot look
253       // up member names inside it). However, if the template parameter has a
254       // default argument, as a heuristic we can replace T with the default
255       // argument type.
256       if (const auto *TTPD = TTPT->getDecl()) {
257         if (TTPD->hasDefaultArgument()) {
258           const auto &DefaultArg = TTPD->getDefaultArgument().getArgument();
259           if (DefaultArg.getKind() == TemplateArgument::Type) {
260             return {DefaultArg.getAsType()};
261           }
262         }
263       }
264     }
265     return T;
266   };
267   // As an additional protection against infinite loops, bound the number of
268   // simplification steps.
269   size_t StepCount = 0;
270   const size_t MaxSteps = 64;
271   while (!Current.Type.isNull() && StepCount++ < MaxSteps) {
272     TypeExprPair New = SimplifyOneStep(Current);
273     if (New.Type == Current.Type)
274       break;
275     Current = New;
276   }
277   if (UnwrapPointer && !DidUnwrapPointer)
278     return QualType();
279   return Current.Type;
280 }
281 
282 std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
283     const CXXDependentScopeMemberExpr *ME) {
284   // If the expression has a qualifier, try resolving the member inside the
285   // qualifier's type.
286   // Note that we cannot use a NonStaticFilter in either case, for a couple
287   // of reasons:
288   //   1. It's valid to access a static member using instance member syntax,
289   //      e.g. `instance.static_member`.
290   //   2. We can sometimes get a CXXDependentScopeMemberExpr for static
291   //      member syntax too, e.g. if `X::static_member` occurs inside
292   //      an instance method, it's represented as a CXXDependentScopeMemberExpr
293   //      with `this` as the base expression as `X` as the qualifier
294   //      (which could be valid if `X` names a base class after instantiation).
295   if (NestedNameSpecifier *NNS = ME->getQualifier()) {
296     if (QualType QualifierType = resolveNestedNameSpecifierToType(NNS);
297         !QualifierType.isNull()) {
298       auto Decls =
299           resolveDependentMember(QualifierType, ME->getMember(), NoFilter);
300       if (!Decls.empty())
301         return Decls;
302     }
303 
304     // Do not proceed to try resolving the member in the expression's base type
305     // without regard to the qualifier, as that could produce incorrect results.
306     // For example, `void foo() { this->Base::foo(); }` shouldn't resolve to
307     // foo() itself!
308     return {};
309   }
310 
311   // Try resolving the member inside the expression's base type.
312   Expr *Base = ME->isImplicitAccess() ? nullptr : ME->getBase();
313   QualType BaseType = ME->getBaseType();
314   BaseType = simplifyType(BaseType, Base, ME->isArrow());
315   return resolveDependentMember(BaseType, ME->getMember(), NoFilter);
316 }
317 
318 std::vector<const NamedDecl *>
319 HeuristicResolverImpl::resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) {
320   QualType Qualifier = resolveNestedNameSpecifierToType(RE->getQualifier());
321   Qualifier = simplifyType(Qualifier, nullptr, /*UnwrapPointer=*/false);
322   return resolveDependentMember(Qualifier, RE->getDeclName(), StaticFilter);
323 }
324 
325 std::vector<const NamedDecl *>
326 HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr *CE) {
327   QualType CalleeType = resolveExprToType(CE->getCallee());
328   if (CalleeType.isNull())
329     return {};
330   if (const auto *FnTypePtr = CalleeType->getAs<PointerType>())
331     CalleeType = FnTypePtr->getPointeeType();
332   if (const FunctionType *FnType = CalleeType->getAs<FunctionType>()) {
333     if (const auto *D = resolveTypeToTagDecl(FnType->getReturnType())) {
334       return {D};
335     }
336   }
337   return {};
338 }
339 
340 std::vector<const NamedDecl *>
341 HeuristicResolverImpl::resolveCalleeOfCallExpr(const CallExpr *CE) {
342   if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
343     return {ND};
344   }
345 
346   return resolveExprToDecls(CE->getCallee());
347 }
348 
349 std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl(
350     const UnresolvedUsingValueDecl *UUVD) {
351   return resolveDependentMember(QualType(UUVD->getQualifier()->getAsType(), 0),
352                                 UUVD->getNameInfo().getName(), ValueFilter);
353 }
354 
355 std::vector<const NamedDecl *>
356 HeuristicResolverImpl::resolveDependentNameType(const DependentNameType *DNT) {
357   if (auto [_, inserted] = SeenDependentNameTypes.insert(DNT); !inserted)
358     return {};
359   return resolveDependentMember(
360       resolveNestedNameSpecifierToType(DNT->getQualifier()),
361       DNT->getIdentifier(), TypeFilter);
362 }
363 
364 std::vector<const NamedDecl *>
365 HeuristicResolverImpl::resolveTemplateSpecializationType(
366     const DependentTemplateSpecializationType *DTST) {
367   const DependentTemplateStorage &DTN = DTST->getDependentTemplateName();
368   return resolveDependentMember(
369       resolveNestedNameSpecifierToType(DTN.getQualifier()),
370       DTN.getName().getIdentifier(), TemplateFilter);
371 }
372 
373 std::vector<const NamedDecl *>
374 HeuristicResolverImpl::resolveExprToDecls(const Expr *E) {
375   if (const auto *ME = dyn_cast<CXXDependentScopeMemberExpr>(E)) {
376     return resolveMemberExpr(ME);
377   }
378   if (const auto *RE = dyn_cast<DependentScopeDeclRefExpr>(E)) {
379     return resolveDeclRefExpr(RE);
380   }
381   if (const auto *OE = dyn_cast<OverloadExpr>(E)) {
382     return {OE->decls_begin(), OE->decls_end()};
383   }
384   if (const auto *CE = dyn_cast<CallExpr>(E)) {
385     return resolveTypeOfCallExpr(CE);
386   }
387   if (const auto *ME = dyn_cast<MemberExpr>(E))
388     return {ME->getMemberDecl()};
389 
390   return {};
391 }
392 
393 QualType HeuristicResolverImpl::resolveExprToType(const Expr *E) {
394   std::vector<const NamedDecl *> Decls = resolveExprToDecls(E);
395   if (!Decls.empty())
396     return resolveDeclsToType(Decls, Ctx);
397 
398   return E->getType();
399 }
400 
401 QualType HeuristicResolverImpl::resolveNestedNameSpecifierToType(
402     const NestedNameSpecifier *NNS) {
403   if (!NNS)
404     return QualType();
405 
406   // The purpose of this function is to handle the dependent (Kind ==
407   // Identifier) case, but we need to recurse on the prefix because
408   // that may be dependent as well, so for convenience handle
409   // the TypeSpec cases too.
410   switch (NNS->getKind()) {
411   case NestedNameSpecifier::TypeSpec:
412     return QualType(NNS->getAsType(), 0);
413   case NestedNameSpecifier::Identifier: {
414     return resolveDeclsToType(
415         resolveDependentMember(
416             resolveNestedNameSpecifierToType(NNS->getPrefix()),
417             NNS->getAsIdentifier(), TypeFilter),
418         Ctx);
419   }
420   default:
421     break;
422   }
423   return QualType();
424 }
425 
426 bool isOrdinaryMember(const NamedDecl *ND) {
427   return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag |
428                                      Decl::IDNS_Member);
429 }
430 
431 bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path,
432                         DeclarationName Name) {
433   Path.Decls = RD->lookup(Name).begin();
434   for (DeclContext::lookup_iterator I = Path.Decls, E = I.end(); I != E; ++I)
435     if (isOrdinaryMember(*I))
436       return true;
437 
438   return false;
439 }
440 
441 bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
442     const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
443     DeclarationName Name) {
444   TagDecl *TD = resolveTypeToTagDecl(Specifier->getType());
445   if (const auto *RD = dyn_cast_if_present<CXXRecordDecl>(TD)) {
446     return findOrdinaryMember(RD, Path, Name);
447   }
448   return false;
449 }
450 
451 std::vector<const NamedDecl *> HeuristicResolverImpl::lookupDependentName(
452     CXXRecordDecl *RD, DeclarationName Name,
453     llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
454   std::vector<const NamedDecl *> Results;
455 
456   // Lookup in the class.
457   bool AnyOrdinaryMembers = false;
458   for (const NamedDecl *ND : RD->lookup(Name)) {
459     if (isOrdinaryMember(ND))
460       AnyOrdinaryMembers = true;
461     if (Filter(ND))
462       Results.push_back(ND);
463   }
464   if (AnyOrdinaryMembers)
465     return Results;
466 
467   // Perform lookup into our base classes.
468   CXXBasePaths Paths;
469   Paths.setOrigin(RD);
470   if (!RD->lookupInBases(
471           [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
472             return findOrdinaryMemberInDependentClasses(Specifier, Path, Name);
473           },
474           Paths, /*LookupInDependent=*/true))
475     return Results;
476   for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end();
477        I != E; ++I) {
478     if (isOrdinaryMember(*I) && Filter(*I))
479       Results.push_back(*I);
480   }
481   return Results;
482 }
483 
484 std::vector<const NamedDecl *> HeuristicResolverImpl::resolveDependentMember(
485     QualType QT, DeclarationName Name,
486     llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
487   TagDecl *TD = resolveTypeToTagDecl(QT);
488   if (!TD)
489     return {};
490   if (auto *ED = dyn_cast<EnumDecl>(TD)) {
491     auto Result = ED->lookup(Name);
492     return {Result.begin(), Result.end()};
493   }
494   if (auto *RD = dyn_cast<CXXRecordDecl>(TD)) {
495     if (!RD->hasDefinition())
496       return {};
497     RD = RD->getDefinition();
498     return lookupDependentName(RD, Name, [&](const NamedDecl *ND) {
499       if (!Filter(ND))
500         return false;
501       if (const auto *MD = dyn_cast<CXXMethodDecl>(ND)) {
502         return !MD->isInstance() ||
503                MD->getMethodQualifiers().compatiblyIncludes(QT.getQualifiers(),
504                                                             Ctx);
505       }
506       return true;
507     });
508   }
509   return {};
510 }
511 
512 FunctionProtoTypeLoc
513 HeuristicResolverImpl::getFunctionProtoTypeLoc(const Expr *Fn) {
514   TypeLoc Target;
515   const Expr *NakedFn = Fn->IgnoreParenCasts();
516   if (const auto *T = NakedFn->getType().getTypePtr()->getAs<TypedefType>()) {
517     Target = T->getDecl()->getTypeSourceInfo()->getTypeLoc();
518   } else if (const auto *DR = dyn_cast<DeclRefExpr>(NakedFn)) {
519     const auto *D = DR->getDecl();
520     if (const auto *const VD = dyn_cast<VarDecl>(D)) {
521       Target = VD->getTypeSourceInfo()->getTypeLoc();
522     }
523   } else if (const auto *ME = dyn_cast<MemberExpr>(NakedFn)) {
524     const auto *MD = ME->getMemberDecl();
525     if (const auto *FD = dyn_cast<FieldDecl>(MD)) {
526       Target = FD->getTypeSourceInfo()->getTypeLoc();
527     }
528   }
529 
530   if (!Target)
531     return {};
532 
533   // Unwrap types that may be wrapping the function type
534   while (true) {
535     if (auto P = Target.getAs<PointerTypeLoc>()) {
536       Target = P.getPointeeLoc();
537       continue;
538     }
539     if (auto A = Target.getAs<AttributedTypeLoc>()) {
540       Target = A.getModifiedLoc();
541       continue;
542     }
543     if (auto P = Target.getAs<ParenTypeLoc>()) {
544       Target = P.getInnerLoc();
545       continue;
546     }
547     break;
548   }
549 
550   if (auto F = Target.getAs<FunctionProtoTypeLoc>()) {
551     // In some edge cases the AST can contain a "trivial" FunctionProtoTypeLoc
552     // which has null parameters. Avoid these as they don't contain useful
553     // information.
554     if (llvm::all_of(F.getParams(), llvm::identity<ParmVarDecl *>()))
555       return F;
556   }
557 
558   return {};
559 }
560 
561 } // namespace
562 
563 std::vector<const NamedDecl *> HeuristicResolver::resolveMemberExpr(
564     const CXXDependentScopeMemberExpr *ME) const {
565   return HeuristicResolverImpl(Ctx).resolveMemberExpr(ME);
566 }
567 std::vector<const NamedDecl *> HeuristicResolver::resolveDeclRefExpr(
568     const DependentScopeDeclRefExpr *RE) const {
569   return HeuristicResolverImpl(Ctx).resolveDeclRefExpr(RE);
570 }
571 std::vector<const NamedDecl *>
572 HeuristicResolver::resolveTypeOfCallExpr(const CallExpr *CE) const {
573   return HeuristicResolverImpl(Ctx).resolveTypeOfCallExpr(CE);
574 }
575 std::vector<const NamedDecl *>
576 HeuristicResolver::resolveCalleeOfCallExpr(const CallExpr *CE) const {
577   return HeuristicResolverImpl(Ctx).resolveCalleeOfCallExpr(CE);
578 }
579 std::vector<const NamedDecl *> HeuristicResolver::resolveUsingValueDecl(
580     const UnresolvedUsingValueDecl *UUVD) const {
581   return HeuristicResolverImpl(Ctx).resolveUsingValueDecl(UUVD);
582 }
583 std::vector<const NamedDecl *> HeuristicResolver::resolveDependentNameType(
584     const DependentNameType *DNT) const {
585   return HeuristicResolverImpl(Ctx).resolveDependentNameType(DNT);
586 }
587 std::vector<const NamedDecl *>
588 HeuristicResolver::resolveTemplateSpecializationType(
589     const DependentTemplateSpecializationType *DTST) const {
590   return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST);
591 }
592 QualType HeuristicResolver::resolveNestedNameSpecifierToType(
593     const NestedNameSpecifier *NNS) const {
594   return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS);
595 }
596 std::vector<const NamedDecl *> HeuristicResolver::lookupDependentName(
597     CXXRecordDecl *RD, DeclarationName Name,
598     llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
599   return HeuristicResolverImpl(Ctx).lookupDependentName(RD, Name, Filter);
600 }
601 const QualType HeuristicResolver::getPointeeType(QualType T) const {
602   return HeuristicResolverImpl(Ctx).getPointeeType(T);
603 }
604 TagDecl *HeuristicResolver::resolveTypeToTagDecl(QualType T) const {
605   return HeuristicResolverImpl(Ctx).resolveTypeToTagDecl(T);
606 }
607 QualType HeuristicResolver::simplifyType(QualType Type, const Expr *E,
608                                          bool UnwrapPointer) {
609   return HeuristicResolverImpl(Ctx).simplifyType(Type, E, UnwrapPointer);
610 }
611 
612 FunctionProtoTypeLoc
613 HeuristicResolver::getFunctionProtoTypeLoc(const Expr *Fn) const {
614   return HeuristicResolverImpl(Ctx).getFunctionProtoTypeLoc(Fn);
615 }
616 
617 } // namespace clang
618