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