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