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