clang 22.0.0git
HeuristicResolver.cpp
Go to the documentation of this file.
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
13#include "clang/AST/ExprCXX.h"
15#include "clang/AST/Type.h"
16#include "llvm/ADT/identity.h"
17
18namespace clang {
19
20namespace {
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.
29class HeuristicResolverImpl {
30public:
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(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
56private:
57 ASTContext &Ctx;
58
59 // Recursion protection sets
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().
87const auto NoFilter = [](const NamedDecl *D) { return true; };
88const auto NonStaticFilter = [](const NamedDecl *D) {
89 return D->isCXXInstanceMember();
90};
91const auto StaticFilter = [](const NamedDecl *D) {
92 return !D->isCXXInstanceMember();
93};
94const auto ValueFilter = [](const NamedDecl *D) { return isa<ValueDecl>(D); };
95const auto TypeFilter = [](const NamedDecl *D) { return isa<TypeDecl>(D); };
96const auto TemplateFilter = [](const NamedDecl *D) {
97 return isa<TemplateDecl>(D);
98};
99
100QualType 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.getCanonicalTypeDeclType(TD);
106 if (const auto *VD = dyn_cast<ValueDecl>(Decls[0])) {
107 return VD->getType();
108 }
109 return QualType();
110}
111
112TemplateName getReferencedTemplateName(const Type *T) {
113 if (const auto *TST = T->getAs<TemplateSpecializationType>()) {
114 return TST->getTemplateName();
115 }
116 if (const auto *DTST = T->getAs<DeducedTemplateSpecializationType>()) {
117 return DTST->getTemplateName();
118 }
119 return TemplateName();
120}
121
122// Helper function for HeuristicResolver::resolveDependentMember()
123// which takes a possibly-dependent type `T` and heuristically
124// resolves it to a CXXRecordDecl in which we can try name lookup.
125TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) {
126 const Type *T = QT.getTypePtrOrNull();
127 if (!T)
128 return nullptr;
129
130 // Unwrap type sugar such as type aliases.
132
133 if (const auto *DNT = T->getAs<DependentNameType>()) {
134 T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx)
135 .getTypePtrOrNull();
136 if (!T)
137 return nullptr;
139 }
140
141 if (auto *TD = T->getAsTagDecl()) {
142 // Template might not be instantiated yet, fall back to primary template
143 // in such cases.
144 if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) {
145 if (CTSD->getTemplateSpecializationKind() == TSK_Undeclared) {
146 return CTSD->getSpecializedTemplate()->getTemplatedDecl();
147 }
148 }
149 return TD;
150 }
151
152 TemplateName TN = getReferencedTemplateName(T);
153 if (TN.isNull())
154 return nullptr;
155
156 const ClassTemplateDecl *TD =
157 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
158 if (!TD)
159 return nullptr;
160
161 return TD->getTemplatedDecl();
162}
163
164QualType HeuristicResolverImpl::getPointeeType(QualType T) {
165 if (T.isNull())
166 return QualType();
167
168 if (T->isPointerType())
169 return T->castAs<PointerType>()->getPointeeType();
170
171 // Try to handle smart pointer types.
172
173 // Look up operator-> in the primary template. If we find one, it's probably a
174 // smart pointer type.
175 auto ArrowOps = resolveDependentMember(
176 T, Ctx.DeclarationNames.getCXXOperatorName(OO_Arrow), NonStaticFilter);
177 if (ArrowOps.empty())
178 return QualType();
179
180 // Getting the return type of the found operator-> method decl isn't useful,
181 // because we discarded template arguments to perform lookup in the primary
182 // template scope, so the return type would just have the form U* where U is a
183 // template parameter type.
184 // Instead, just handle the common case where the smart pointer type has the
185 // form of SmartPtr<X, ...>, and assume X is the pointee type.
186 auto *TST = T->getAs<TemplateSpecializationType>();
187 if (!TST)
188 return QualType();
189 if (TST->template_arguments().size() == 0)
190 return QualType();
191 const TemplateArgument &FirstArg = TST->template_arguments()[0];
192 if (FirstArg.getKind() != TemplateArgument::Type)
193 return QualType();
194 return FirstArg.getAsType();
195}
196
197QualType HeuristicResolverImpl::simplifyType(QualType Type, const Expr *E,
198 bool UnwrapPointer) {
199 bool DidUnwrapPointer = false;
200 // A type, together with an optional expression whose type it represents
201 // which may have additional information about the expression's type
202 // not stored in the QualType itself.
203 struct TypeExprPair {
204 QualType Type;
205 const Expr *E = nullptr;
206 };
207 TypeExprPair Current{Type, E};
208 auto SimplifyOneStep = [UnwrapPointer, &DidUnwrapPointer,
209 this](TypeExprPair T) -> TypeExprPair {
210 if (UnwrapPointer) {
211 if (QualType Pointee = getPointeeType(T.Type); !Pointee.isNull()) {
212 DidUnwrapPointer = true;
213 return {Pointee};
214 }
215 }
216 if (const auto *RT = T.Type->getAs<ReferenceType>()) {
217 // Does not count as "unwrap pointer".
218 return {RT->getPointeeType()};
219 }
220 if (const auto *BT = T.Type->getAs<BuiltinType>()) {
221 // If BaseType is the type of a dependent expression, it's just
222 // represented as BuiltinType::Dependent which gives us no information. We
223 // can get further by analyzing the dependent expression.
224 if (T.E && BT->getKind() == BuiltinType::Dependent) {
225 return {resolveExprToType(T.E), T.E};
226 }
227 }
228 if (const auto *AT = T.Type->getContainedAutoType()) {
229 // If T contains a dependent `auto` type, deduction will not have
230 // been performed on it yet. In simple cases (e.g. `auto` variable with
231 // initializer), get the approximate type that would result from
232 // deduction.
233 // FIXME: A more accurate implementation would propagate things like the
234 // `const` in `const auto`.
235 if (T.E && AT->isUndeducedAutoType()) {
236 if (const auto *DRE = dyn_cast<DeclRefExpr>(T.E)) {
237 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
238 if (auto *Init = VD->getInit())
239 return {resolveExprToType(Init), Init};
240 }
241 }
242 }
243 }
244 if (const auto *TTPT = dyn_cast_if_present<TemplateTypeParmType>(T.Type)) {
245 // We can't do much useful with a template parameter (e.g. we cannot look
246 // up member names inside it). However, if the template parameter has a
247 // default argument, as a heuristic we can replace T with the default
248 // argument type.
249 if (const auto *TTPD = TTPT->getDecl()) {
250 if (TTPD->hasDefaultArgument()) {
251 const auto &DefaultArg = TTPD->getDefaultArgument().getArgument();
252 if (DefaultArg.getKind() == TemplateArgument::Type) {
253 return {DefaultArg.getAsType()};
254 }
255 }
256 }
257 }
258 // Check if the expression refers to an explicit object parameter of
259 // templated type. If so, heuristically treat it as having the type of the
260 // enclosing class.
261 if (!T.Type.isNull() &&
262 (T.Type->isUndeducedAutoType() || T.Type->isTemplateTypeParmType())) {
263 if (auto *DRE = dyn_cast_if_present<DeclRefExpr>(T.E)) {
264 auto *PrDecl = dyn_cast<ParmVarDecl>(DRE->getDecl());
265 if (PrDecl && PrDecl->isExplicitObjectParameter()) {
266 const auto *Parent =
267 dyn_cast<TagDecl>(PrDecl->getDeclContext()->getParent());
268 return {Ctx.getCanonicalTagType(Parent)};
269 }
270 }
271 }
272
273 return T;
274 };
275 // As an additional protection against infinite loops, bound the number of
276 // simplification steps.
277 size_t StepCount = 0;
278 const size_t MaxSteps = 64;
279 while (!Current.Type.isNull() && StepCount++ < MaxSteps) {
280 TypeExprPair New = SimplifyOneStep(Current);
281 if (New.Type == Current.Type)
282 break;
283 Current = New;
284 }
285 if (UnwrapPointer && !DidUnwrapPointer)
286 return QualType();
287 return Current.Type;
288}
289
290std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
291 const CXXDependentScopeMemberExpr *ME) {
292 // If the expression has a qualifier, try resolving the member inside the
293 // qualifier's type.
294 // Note that we cannot use a NonStaticFilter in either case, for a couple
295 // of reasons:
296 // 1. It's valid to access a static member using instance member syntax,
297 // e.g. `instance.static_member`.
298 // 2. We can sometimes get a CXXDependentScopeMemberExpr for static
299 // member syntax too, e.g. if `X::static_member` occurs inside
300 // an instance method, it's represented as a CXXDependentScopeMemberExpr
301 // with `this` as the base expression as `X` as the qualifier
302 // (which could be valid if `X` names a base class after instantiation).
303 if (NestedNameSpecifier NNS = ME->getQualifier()) {
304 if (QualType QualifierType = resolveNestedNameSpecifierToType(NNS);
305 !QualifierType.isNull()) {
306 auto Decls =
307 resolveDependentMember(QualifierType, ME->getMember(), NoFilter);
308 if (!Decls.empty())
309 return Decls;
310 }
311
312 // Do not proceed to try resolving the member in the expression's base type
313 // without regard to the qualifier, as that could produce incorrect results.
314 // For example, `void foo() { this->Base::foo(); }` shouldn't resolve to
315 // foo() itself!
316 return {};
317 }
318
319 // Try resolving the member inside the expression's base type.
320 Expr *Base = ME->isImplicitAccess() ? nullptr : ME->getBase();
321 QualType BaseType = ME->getBaseType();
322 BaseType = simplifyType(BaseType, Base, ME->isArrow());
323 return resolveDependentMember(BaseType, ME->getMember(), NoFilter);
324}
325
326std::vector<const NamedDecl *>
327HeuristicResolverImpl::resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) {
328 QualType Qualifier = resolveNestedNameSpecifierToType(RE->getQualifier());
329 Qualifier = simplifyType(Qualifier, nullptr, /*UnwrapPointer=*/false);
330 return resolveDependentMember(Qualifier, RE->getDeclName(), StaticFilter);
331}
332
333std::vector<const NamedDecl *>
334HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr *CE) {
335 QualType CalleeType = resolveExprToType(CE->getCallee());
336 if (CalleeType.isNull())
337 return {};
338 if (const auto *FnTypePtr = CalleeType->getAs<PointerType>())
339 CalleeType = FnTypePtr->getPointeeType();
340 if (const FunctionType *FnType = CalleeType->getAs<FunctionType>()) {
341 if (const auto *D = resolveTypeToTagDecl(FnType->getReturnType())) {
342 return {D};
343 }
344 }
345 return {};
346}
347
348std::vector<const NamedDecl *>
349HeuristicResolverImpl::resolveCalleeOfCallExpr(const CallExpr *CE) {
350 if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
351 return {ND};
352 }
353
354 return resolveExprToDecls(CE->getCallee());
355}
356
357std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl(
358 const UnresolvedUsingValueDecl *UUVD) {
359 NestedNameSpecifier Qualifier = UUVD->getQualifier();
361 return {};
362 return resolveDependentMember(QualType(Qualifier.getAsType(), 0),
363 UUVD->getNameInfo().getName(), ValueFilter);
364}
365
366std::vector<const NamedDecl *>
367HeuristicResolverImpl::resolveDependentNameType(const DependentNameType *DNT) {
368 if (auto [_, inserted] = SeenDependentNameTypes.insert(DNT); !inserted)
369 return {};
370 return resolveDependentMember(
371 resolveNestedNameSpecifierToType(DNT->getQualifier()),
372 DNT->getIdentifier(), TypeFilter);
373}
374
375std::vector<const NamedDecl *>
376HeuristicResolverImpl::resolveTemplateSpecializationType(
377 const DependentTemplateSpecializationType *DTST) {
378 const DependentTemplateStorage &DTN = DTST->getDependentTemplateName();
379 return resolveDependentMember(
380 resolveNestedNameSpecifierToType(DTN.getQualifier()),
381 DTN.getName().getIdentifier(), TemplateFilter);
382}
383
384std::vector<const NamedDecl *>
385HeuristicResolverImpl::resolveExprToDecls(const Expr *E) {
386 if (const auto *ME = dyn_cast<CXXDependentScopeMemberExpr>(E)) {
387 return resolveMemberExpr(ME);
388 }
389 if (const auto *RE = dyn_cast<DependentScopeDeclRefExpr>(E)) {
390 return resolveDeclRefExpr(RE);
391 }
392 if (const auto *OE = dyn_cast<OverloadExpr>(E)) {
393 return {OE->decls_begin(), OE->decls_end()};
394 }
395 if (const auto *CE = dyn_cast<CallExpr>(E)) {
396 return resolveTypeOfCallExpr(CE);
397 }
398 if (const auto *ME = dyn_cast<MemberExpr>(E))
399 return {ME->getMemberDecl()};
400
401 return {};
402}
403
404QualType HeuristicResolverImpl::resolveExprToType(const Expr *E) {
405 std::vector<const NamedDecl *> Decls = resolveExprToDecls(E);
406 if (!Decls.empty())
407 return resolveDeclsToType(Decls, Ctx);
408
409 return E->getType();
410}
411
412QualType HeuristicResolverImpl::resolveNestedNameSpecifierToType(
413 NestedNameSpecifier NNS) {
414 // The purpose of this function is to handle the dependent (Kind ==
415 // Identifier) case, but we need to recurse on the prefix because
416 // that may be dependent as well, so for convenience handle
417 // the TypeSpec cases too.
418 switch (NNS.getKind()) {
420 const auto *T = NNS.getAsType();
421 // FIXME: Should this handle the DependentTemplateSpecializationType as
422 // well?
423 if (const auto *DTN = dyn_cast<DependentNameType>(T))
424 return resolveDeclsToType(
425 resolveDependentMember(
426 resolveNestedNameSpecifierToType(DTN->getQualifier()),
427 DTN->getIdentifier(), TypeFilter),
428 Ctx);
429 return QualType(T, 0);
430 }
431 default:
432 break;
433 }
434 return QualType();
435}
436
437bool isOrdinaryMember(const NamedDecl *ND) {
438 return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag |
440}
441
442bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path,
443 DeclarationName Name) {
444 Path.Decls = RD->lookup(Name).begin();
445 for (DeclContext::lookup_iterator I = Path.Decls, E = I.end(); I != E; ++I)
446 if (isOrdinaryMember(*I))
447 return true;
448
449 return false;
450}
451
452bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
453 const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
454 DeclarationName Name) {
455 TagDecl *TD = resolveTypeToTagDecl(Specifier->getType());
456 if (const auto *RD = dyn_cast_if_present<CXXRecordDecl>(TD)) {
457 return findOrdinaryMember(RD, Path, Name);
458 }
459 return false;
460}
461
462std::vector<const NamedDecl *> HeuristicResolverImpl::lookupDependentName(
463 CXXRecordDecl *RD, DeclarationName Name,
464 llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
465 std::vector<const NamedDecl *> Results;
466
467 // Lookup in the class.
468 bool AnyOrdinaryMembers = false;
469 for (const NamedDecl *ND : RD->lookup(Name)) {
470 if (isOrdinaryMember(ND))
471 AnyOrdinaryMembers = true;
472 if (Filter(ND))
473 Results.push_back(ND);
474 }
475 if (AnyOrdinaryMembers)
476 return Results;
477
478 // Perform lookup into our base classes.
479 CXXBasePaths Paths;
480 Paths.setOrigin(RD);
481 if (!RD->lookupInBases(
482 [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
483 return findOrdinaryMemberInDependentClasses(Specifier, Path, Name);
484 },
485 Paths, /*LookupInDependent=*/true))
486 return Results;
487 for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end();
488 I != E; ++I) {
489 if (isOrdinaryMember(*I) && Filter(*I))
490 Results.push_back(*I);
491 }
492 return Results;
493}
494
495std::vector<const NamedDecl *> HeuristicResolverImpl::resolveDependentMember(
496 QualType QT, DeclarationName Name,
497 llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
498 TagDecl *TD = resolveTypeToTagDecl(QT);
499 if (!TD)
500 return {};
501 if (auto *ED = dyn_cast<EnumDecl>(TD)) {
502 auto Result = ED->lookup(Name);
503 return {Result.begin(), Result.end()};
504 }
505 if (auto *RD = dyn_cast<CXXRecordDecl>(TD)) {
506 if (!RD->hasDefinition())
507 return {};
508 RD = RD->getDefinition();
509 return lookupDependentName(RD, Name, [&](const NamedDecl *ND) {
510 if (!Filter(ND))
511 return false;
512 if (const auto *MD = dyn_cast<CXXMethodDecl>(ND)) {
513 return !MD->isInstance() ||
514 MD->getMethodQualifiers().compatiblyIncludes(QT.getQualifiers(),
515 Ctx);
516 }
517 return true;
518 });
519 }
520 return {};
521}
522
523FunctionProtoTypeLoc
524HeuristicResolverImpl::getFunctionProtoTypeLoc(const Expr *Fn) {
525 TypeLoc Target;
526 const Expr *NakedFn = Fn->IgnoreParenCasts();
527 if (const auto *T = NakedFn->getType().getTypePtr()->getAs<TypedefType>()) {
528 Target = T->getDecl()->getTypeSourceInfo()->getTypeLoc();
529 } else if (const auto *DR = dyn_cast<DeclRefExpr>(NakedFn)) {
530 const auto *D = DR->getDecl();
531 if (const auto *const VD = dyn_cast<VarDecl>(D)) {
532 Target = VD->getTypeSourceInfo()->getTypeLoc();
533 }
534 } else if (const auto *ME = dyn_cast<MemberExpr>(NakedFn)) {
535 const auto *MD = ME->getMemberDecl();
536 if (const auto *FD = dyn_cast<FieldDecl>(MD)) {
537 Target = FD->getTypeSourceInfo()->getTypeLoc();
538 }
539 }
540
541 if (!Target)
542 return {};
543
544 // Unwrap types that may be wrapping the function type
545 while (true) {
546 if (auto P = Target.getAs<PointerTypeLoc>()) {
547 Target = P.getPointeeLoc();
548 continue;
549 }
550 if (auto A = Target.getAs<AttributedTypeLoc>()) {
551 Target = A.getModifiedLoc();
552 continue;
553 }
554 if (auto P = Target.getAs<ParenTypeLoc>()) {
555 Target = P.getInnerLoc();
556 continue;
557 }
558 break;
559 }
560
561 if (auto F = Target.getAs<FunctionProtoTypeLoc>()) {
562 // In some edge cases the AST can contain a "trivial" FunctionProtoTypeLoc
563 // which has null parameters. Avoid these as they don't contain useful
564 // information.
565 if (llvm::all_of(F.getParams(), llvm::identity<ParmVarDecl *>()))
566 return F;
567 }
568
569 return {};
570}
571
572} // namespace
573
574std::vector<const NamedDecl *> HeuristicResolver::resolveMemberExpr(
575 const CXXDependentScopeMemberExpr *ME) const {
576 return HeuristicResolverImpl(Ctx).resolveMemberExpr(ME);
577}
578std::vector<const NamedDecl *> HeuristicResolver::resolveDeclRefExpr(
579 const DependentScopeDeclRefExpr *RE) const {
580 return HeuristicResolverImpl(Ctx).resolveDeclRefExpr(RE);
581}
582std::vector<const NamedDecl *>
584 return HeuristicResolverImpl(Ctx).resolveTypeOfCallExpr(CE);
585}
586std::vector<const NamedDecl *>
588 return HeuristicResolverImpl(Ctx).resolveCalleeOfCallExpr(CE);
589}
590std::vector<const NamedDecl *> HeuristicResolver::resolveUsingValueDecl(
591 const UnresolvedUsingValueDecl *UUVD) const {
592 return HeuristicResolverImpl(Ctx).resolveUsingValueDecl(UUVD);
593}
594std::vector<const NamedDecl *> HeuristicResolver::resolveDependentNameType(
595 const DependentNameType *DNT) const {
596 return HeuristicResolverImpl(Ctx).resolveDependentNameType(DNT);
597}
598std::vector<const NamedDecl *>
600 const DependentTemplateSpecializationType *DTST) const {
601 return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST);
602}
604 NestedNameSpecifier NNS) const {
605 return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS);
606}
607std::vector<const NamedDecl *> HeuristicResolver::lookupDependentName(
609 llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
610 return HeuristicResolverImpl(Ctx).lookupDependentName(RD, Name, Filter);
611}
613 return HeuristicResolverImpl(Ctx).getPointeeType(T);
614}
616 return HeuristicResolverImpl(Ctx).resolveTypeToTagDecl(T);
617}
619 bool UnwrapPointer) {
620 return HeuristicResolverImpl(Ctx).simplifyType(Type, E, UnwrapPointer);
621}
622
625 return HeuristicResolverImpl(Ctx).getFunctionProtoTypeLoc(Fn);
626}
627
628} // namespace clang
Defines the clang::ASTContext interface.
NodeId Parent
Definition: ASTDiff.cpp:191
MatchType Type
StringRef P
static bool isOrdinaryMember(const NamedDecl *ND)
static bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path, DeclarationName Name)
const Decl * D
IndirectLocalPath & Path
Expr * E
Defines the C++ template declaration subclasses.
Defines the clang::Expr interface and subclasses for C++ expressions.
llvm::MachO::Target Target
Definition: MachO.h:51
static QualType getPointeeType(const MemRegion *R)
C Language Family Type Representation.
NestedNameSpecifier Specifier
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:744
CanQualType getCanonicalTypeDeclType(const TypeDecl *TD) const
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents a C++ member access expression where the actual member referenced could not be resolved be...
Definition: ExprCXX.h:3864
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2879
lookup_result::iterator lookup_iterator
Definition: DeclBase.h:2578
@ IDNS_Ordinary
Ordinary names.
Definition: DeclBase.h:144
@ IDNS_Member
Members, declared with object declarations within tag definitions.
Definition: DeclBase.h:136
@ IDNS_Tag
Tags, declared with 'struct foo;' and referenced with 'struct foo'.
Definition: DeclBase.h:125
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op)
Get the name of the overloadable C++ operator corresponding to Op.
The name of a declaration.
Represents a qualified type name for which the type name is dependent.
Definition: TypeBase.h:7414
A qualified reference to a name whose declaration cannot yet be resolved.
Definition: ExprCXX.h:3504
Represents a template specialization type whose template cannot be resolved, e.g.
Definition: TypeBase.h:7465
This represents one expression.
Definition: Expr.h:112
QualType getType() const
Definition: Expr.h:144
std::vector< const NamedDecl * > resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) const
const QualType getPointeeType(QualType T) const
QualType simplifyType(QualType Type, const Expr *E, bool UnwrapPointer)
std::vector< const NamedDecl * > resolveMemberExpr(const CXXDependentScopeMemberExpr *ME) const
FunctionProtoTypeLoc getFunctionProtoTypeLoc(const Expr *Fn) const
QualType resolveNestedNameSpecifierToType(NestedNameSpecifier NNS) const
std::vector< const NamedDecl * > resolveCalleeOfCallExpr(const CallExpr *CE) const
TagDecl * resolveTypeToTagDecl(QualType T) const
std::vector< const NamedDecl * > resolveTypeOfCallExpr(const CallExpr *CE) const
std::vector< const NamedDecl * > resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD) const
std::vector< const NamedDecl * > resolveTemplateSpecializationType(const DependentTemplateSpecializationType *DTST) const
std::vector< const NamedDecl * > resolveDependentNameType(const DependentNameType *DNT) const
std::vector< const NamedDecl * > lookupDependentName(CXXRecordDecl *RD, DeclarationName Name, llvm::function_ref< bool(const NamedDecl *ND)> Filter)
This represents a decl that may have a name.
Definition: Decl.h:273
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
@ Type
A type, stored as a Type*.
A (possibly-)qualified type.
Definition: TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: TypeBase.h:8343
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3714
@ Type
The template argument is a type.
Definition: TemplateBase.h:70
The base class of the type hierarchy.
Definition: TypeBase.h:1833
bool isUndeducedAutoType() const
Definition: TypeBase.h:8766
bool isPointerType() const
Definition: TypeBase.h:8580
const T * castAs() const
Member-template castAs<specific type>.
Definition: TypeBase.h:9226
Type(TypeClass tc, QualType canon, TypeDependence Dependence)
Definition: TypeBase.h:2367
TagDecl * getAsTagDecl() const
Retrieves the TagDecl that this type refers to, either because the type is a TagType or because it is...
Definition: Type.h:65
QualType getCanonicalTypeInternal() const
Definition: TypeBase.h:3137
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
Represents a dependent using declaration which was not marked with typename.
Definition: DeclCXX.h:3934
llvm::cl::opt< std::string > Filter
The JSON file list parser is used to communicate input to InstallAPI.
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
@ Result
The result type of a method or function.
const FunctionProtoType * T
@ TSK_Undeclared
This template specialization was formed from a template-id but has not yet been declared,...
Definition: Specifiers.h:191