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:
HeuristicResolverImpl(ASTContext & Ctx)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().
__anon96160a110202(const NamedDecl *D) 87 const auto NoFilter = [](const NamedDecl *D) { return true; };
__anon96160a110302(const NamedDecl *D) 88 const auto NonStaticFilter = [](const NamedDecl *D) {
89 return D->isCXXInstanceMember();
90 };
__anon96160a110402(const NamedDecl *D) 91 const auto StaticFilter = [](const NamedDecl *D) {
92 return !D->isCXXInstanceMember();
93 };
__anon96160a110502(const NamedDecl *D) 94 const auto ValueFilter = [](const NamedDecl *D) { return isa<ValueDecl>(D); };
__anon96160a110602(const NamedDecl *D) 95 const auto TypeFilter = [](const NamedDecl *D) { return isa<TypeDecl>(D); };
__anon96160a110702(const NamedDecl *D) 96 const auto TemplateFilter = [](const NamedDecl *D) {
97 return isa<TemplateDecl>(D);
98 };
99
resolveDeclsToType(const std::vector<const NamedDecl * > & Decls,ASTContext & Ctx)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
getReferencedTemplateName(const Type * T)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.
resolveTypeToTagDecl(QualType QT)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
getPointeeType(QualType T)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
simplifyType(QualType Type,const Expr * E,bool UnwrapPointer)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
resolveMemberExpr(const CXXDependentScopeMemberExpr * ME)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 *>
resolveDeclRefExpr(const DependentScopeDeclRefExpr * RE)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 *>
resolveTypeOfCallExpr(const CallExpr * CE)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 *>
resolveCalleeOfCallExpr(const CallExpr * CE)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
resolveUsingValueDecl(const UnresolvedUsingValueDecl * UUVD)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 *>
resolveDependentNameType(const DependentNameType * DNT)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 *>
resolveTemplateSpecializationType(const DependentTemplateSpecializationType * DTST)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 *>
resolveExprToDecls(const Expr * E)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
resolveExprToType(const Expr * E)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
resolveNestedNameSpecifierToType(const NestedNameSpecifier * NNS)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
isOrdinaryMember(const NamedDecl * ND)426 bool isOrdinaryMember(const NamedDecl *ND) {
427 return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag |
428 Decl::IDNS_Member);
429 }
430
findOrdinaryMember(const CXXRecordDecl * RD,CXXBasePath & Path,DeclarationName Name)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
findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier * Specifier,CXXBasePath & Path,DeclarationName Name)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
lookupDependentName(CXXRecordDecl * RD,DeclarationName Name,llvm::function_ref<bool (const NamedDecl * ND)> Filter)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
resolveDependentMember(QualType QT,DeclarationName Name,llvm::function_ref<bool (const NamedDecl * ND)> Filter)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
getFunctionProtoTypeLoc(const Expr * Fn)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
resolveMemberExpr(const CXXDependentScopeMemberExpr * ME) const563 std::vector<const NamedDecl *> HeuristicResolver::resolveMemberExpr(
564 const CXXDependentScopeMemberExpr *ME) const {
565 return HeuristicResolverImpl(Ctx).resolveMemberExpr(ME);
566 }
resolveDeclRefExpr(const DependentScopeDeclRefExpr * RE) const567 std::vector<const NamedDecl *> HeuristicResolver::resolveDeclRefExpr(
568 const DependentScopeDeclRefExpr *RE) const {
569 return HeuristicResolverImpl(Ctx).resolveDeclRefExpr(RE);
570 }
571 std::vector<const NamedDecl *>
resolveTypeOfCallExpr(const CallExpr * CE) const572 HeuristicResolver::resolveTypeOfCallExpr(const CallExpr *CE) const {
573 return HeuristicResolverImpl(Ctx).resolveTypeOfCallExpr(CE);
574 }
575 std::vector<const NamedDecl *>
resolveCalleeOfCallExpr(const CallExpr * CE) const576 HeuristicResolver::resolveCalleeOfCallExpr(const CallExpr *CE) const {
577 return HeuristicResolverImpl(Ctx).resolveCalleeOfCallExpr(CE);
578 }
resolveUsingValueDecl(const UnresolvedUsingValueDecl * UUVD) const579 std::vector<const NamedDecl *> HeuristicResolver::resolveUsingValueDecl(
580 const UnresolvedUsingValueDecl *UUVD) const {
581 return HeuristicResolverImpl(Ctx).resolveUsingValueDecl(UUVD);
582 }
resolveDependentNameType(const DependentNameType * DNT) const583 std::vector<const NamedDecl *> HeuristicResolver::resolveDependentNameType(
584 const DependentNameType *DNT) const {
585 return HeuristicResolverImpl(Ctx).resolveDependentNameType(DNT);
586 }
587 std::vector<const NamedDecl *>
resolveTemplateSpecializationType(const DependentTemplateSpecializationType * DTST) const588 HeuristicResolver::resolveTemplateSpecializationType(
589 const DependentTemplateSpecializationType *DTST) const {
590 return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST);
591 }
resolveNestedNameSpecifierToType(const NestedNameSpecifier * NNS) const592 QualType HeuristicResolver::resolveNestedNameSpecifierToType(
593 const NestedNameSpecifier *NNS) const {
594 return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS);
595 }
lookupDependentName(CXXRecordDecl * RD,DeclarationName Name,llvm::function_ref<bool (const NamedDecl * ND)> Filter)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 }
getPointeeType(QualType T) const601 const QualType HeuristicResolver::getPointeeType(QualType T) const {
602 return HeuristicResolverImpl(Ctx).getPointeeType(T);
603 }
resolveTypeToTagDecl(QualType T) const604 TagDecl *HeuristicResolver::resolveTypeToTagDecl(QualType T) const {
605 return HeuristicResolverImpl(Ctx).resolveTypeToTagDecl(T);
606 }
simplifyType(QualType Type,const Expr * E,bool UnwrapPointer)607 QualType HeuristicResolver::simplifyType(QualType Type, const Expr *E,
608 bool UnwrapPointer) {
609 return HeuristicResolverImpl(Ctx).simplifyType(Type, E, UnwrapPointer);
610 }
611
612 FunctionProtoTypeLoc
getFunctionProtoTypeLoc(const Expr * Fn) const613 HeuristicResolver::getFunctionProtoTypeLoc(const Expr *Fn) const {
614 return HeuristicResolverImpl(Ctx).getFunctionProtoTypeLoc(Fn);
615 }
616
617 } // namespace clang
618