1 //===--- Lookup.h - Classes for name lookup ---------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the LookupResult class, which is integral to 11 // Sema's name-lookup subsystem. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_SEMA_LOOKUP_H 16 #define LLVM_CLANG_SEMA_LOOKUP_H 17 18 #include "clang/AST/DeclCXX.h" 19 #include "clang/Sema/Sema.h" 20 21 namespace clang { 22 23 /// @brief Represents the results of name lookup. 24 /// 25 /// An instance of the LookupResult class captures the results of a 26 /// single name lookup, which can return no result (nothing found), 27 /// a single declaration, a set of overloaded functions, or an 28 /// ambiguity. Use the getKind() method to determine which of these 29 /// results occurred for a given lookup. 30 class LookupResult { 31 public: 32 enum LookupResultKind { 33 /// @brief No entity found met the criteria. 34 NotFound = 0, 35 36 /// @brief No entity found met the criteria within the current 37 /// instantiation,, but there were dependent base classes of the 38 /// current instantiation that could not be searched. 39 NotFoundInCurrentInstantiation, 40 41 /// @brief Name lookup found a single declaration that met the 42 /// criteria. getFoundDecl() will return this declaration. 43 Found, 44 45 /// @brief Name lookup found a set of overloaded functions that 46 /// met the criteria. 47 FoundOverloaded, 48 49 /// @brief Name lookup found an unresolvable value declaration 50 /// and cannot yet complete. This only happens in C++ dependent 51 /// contexts with dependent using declarations. 52 FoundUnresolvedValue, 53 54 /// @brief Name lookup results in an ambiguity; use 55 /// getAmbiguityKind to figure out what kind of ambiguity 56 /// we have. 57 Ambiguous 58 }; 59 60 enum AmbiguityKind { 61 /// Name lookup results in an ambiguity because multiple 62 /// entities that meet the lookup criteria were found in 63 /// subobjects of different types. For example: 64 /// @code 65 /// struct A { void f(int); } 66 /// struct B { void f(double); } 67 /// struct C : A, B { }; 68 /// void test(C c) { 69 /// c.f(0); // error: A::f and B::f come from subobjects of different 70 /// // types. overload resolution is not performed. 71 /// } 72 /// @endcode 73 AmbiguousBaseSubobjectTypes, 74 75 /// Name lookup results in an ambiguity because multiple 76 /// nonstatic entities that meet the lookup criteria were found 77 /// in different subobjects of the same type. For example: 78 /// @code 79 /// struct A { int x; }; 80 /// struct B : A { }; 81 /// struct C : A { }; 82 /// struct D : B, C { }; 83 /// int test(D d) { 84 /// return d.x; // error: 'x' is found in two A subobjects (of B and C) 85 /// } 86 /// @endcode 87 AmbiguousBaseSubobjects, 88 89 /// Name lookup results in an ambiguity because multiple definitions 90 /// of entity that meet the lookup criteria were found in different 91 /// declaration contexts. 92 /// @code 93 /// namespace A { 94 /// int i; 95 /// namespace B { int i; } 96 /// int test() { 97 /// using namespace B; 98 /// return i; // error 'i' is found in namespace A and A::B 99 /// } 100 /// } 101 /// @endcode 102 AmbiguousReference, 103 104 /// Name lookup results in an ambiguity because an entity with a 105 /// tag name was hidden by an entity with an ordinary name from 106 /// a different context. 107 /// @code 108 /// namespace A { struct Foo {}; } 109 /// namespace B { void Foo(); } 110 /// namespace C { 111 /// using namespace A; 112 /// using namespace B; 113 /// } 114 /// void test() { 115 /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a 116 /// // different namespace 117 /// } 118 /// @endcode 119 AmbiguousTagHiding 120 }; 121 122 /// A little identifier for flagging temporary lookup results. 123 enum TemporaryToken { 124 Temporary 125 }; 126 127 typedef UnresolvedSetImpl::iterator iterator; 128 129 LookupResult(Sema &SemaRef, const DeclarationNameInfo &NameInfo, 130 Sema::LookupNameKind LookupKind, 131 Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) ResultKind(NotFound)132 : ResultKind(NotFound), 133 Paths(nullptr), 134 NamingClass(nullptr), 135 SemaPtr(&SemaRef), 136 NameInfo(NameInfo), 137 LookupKind(LookupKind), 138 IDNS(0), 139 Redecl(Redecl != Sema::NotForRedeclaration), 140 HideTags(true), 141 Diagnose(Redecl == Sema::NotForRedeclaration), 142 AllowHidden(Redecl == Sema::ForRedeclaration), 143 Shadowed(false) 144 { 145 configure(); 146 } 147 148 // TODO: consider whether this constructor should be restricted to take 149 // as input a const IndentifierInfo* (instead of Name), 150 // forcing other cases towards the constructor taking a DNInfo. 151 LookupResult(Sema &SemaRef, DeclarationName Name, 152 SourceLocation NameLoc, Sema::LookupNameKind LookupKind, 153 Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) ResultKind(NotFound)154 : ResultKind(NotFound), 155 Paths(nullptr), 156 NamingClass(nullptr), 157 SemaPtr(&SemaRef), 158 NameInfo(Name, NameLoc), 159 LookupKind(LookupKind), 160 IDNS(0), 161 Redecl(Redecl != Sema::NotForRedeclaration), 162 HideTags(true), 163 Diagnose(Redecl == Sema::NotForRedeclaration), 164 AllowHidden(Redecl == Sema::ForRedeclaration), 165 Shadowed(false) 166 { 167 configure(); 168 } 169 170 /// Creates a temporary lookup result, initializing its core data 171 /// using the information from another result. Diagnostics are always 172 /// disabled. LookupResult(TemporaryToken _,const LookupResult & Other)173 LookupResult(TemporaryToken _, const LookupResult &Other) 174 : ResultKind(NotFound), 175 Paths(nullptr), 176 NamingClass(nullptr), 177 SemaPtr(Other.SemaPtr), 178 NameInfo(Other.NameInfo), 179 LookupKind(Other.LookupKind), 180 IDNS(Other.IDNS), 181 Redecl(Other.Redecl), 182 HideTags(Other.HideTags), 183 Diagnose(false), 184 AllowHidden(Other.AllowHidden), 185 Shadowed(false) 186 {} 187 ~LookupResult()188 ~LookupResult() { 189 if (Diagnose) diagnose(); 190 if (Paths) deletePaths(Paths); 191 } 192 193 /// Gets the name info to look up. getLookupNameInfo()194 const DeclarationNameInfo &getLookupNameInfo() const { 195 return NameInfo; 196 } 197 198 /// \brief Sets the name info to look up. setLookupNameInfo(const DeclarationNameInfo & NameInfo)199 void setLookupNameInfo(const DeclarationNameInfo &NameInfo) { 200 this->NameInfo = NameInfo; 201 } 202 203 /// Gets the name to look up. getLookupName()204 DeclarationName getLookupName() const { 205 return NameInfo.getName(); 206 } 207 208 /// \brief Sets the name to look up. setLookupName(DeclarationName Name)209 void setLookupName(DeclarationName Name) { 210 NameInfo.setName(Name); 211 } 212 213 /// Gets the kind of lookup to perform. getLookupKind()214 Sema::LookupNameKind getLookupKind() const { 215 return LookupKind; 216 } 217 218 /// True if this lookup is just looking for an existing declaration. isForRedeclaration()219 bool isForRedeclaration() const { 220 return Redecl; 221 } 222 223 /// \brief Specify whether hidden declarations are visible, e.g., 224 /// for recovery reasons. setAllowHidden(bool AH)225 void setAllowHidden(bool AH) { 226 AllowHidden = AH; 227 } 228 229 /// \brief Determine whether this lookup is permitted to see hidden 230 /// declarations, such as those in modules that have not yet been imported. isHiddenDeclarationVisible()231 bool isHiddenDeclarationVisible() const { 232 return AllowHidden || LookupKind == Sema::LookupTagName; 233 } 234 235 /// Sets whether tag declarations should be hidden by non-tag 236 /// declarations during resolution. The default is true. setHideTags(bool Hide)237 void setHideTags(bool Hide) { 238 HideTags = Hide; 239 } 240 isAmbiguous()241 bool isAmbiguous() const { 242 return getResultKind() == Ambiguous; 243 } 244 245 /// Determines if this names a single result which is not an 246 /// unresolved value using decl. If so, it is safe to call 247 /// getFoundDecl(). isSingleResult()248 bool isSingleResult() const { 249 return getResultKind() == Found; 250 } 251 252 /// Determines if the results are overloaded. isOverloadedResult()253 bool isOverloadedResult() const { 254 return getResultKind() == FoundOverloaded; 255 } 256 isUnresolvableResult()257 bool isUnresolvableResult() const { 258 return getResultKind() == FoundUnresolvedValue; 259 } 260 getResultKind()261 LookupResultKind getResultKind() const { 262 assert(sanity()); 263 return ResultKind; 264 } 265 getAmbiguityKind()266 AmbiguityKind getAmbiguityKind() const { 267 assert(isAmbiguous()); 268 return Ambiguity; 269 } 270 asUnresolvedSet()271 const UnresolvedSetImpl &asUnresolvedSet() const { 272 return Decls; 273 } 274 begin()275 iterator begin() const { return iterator(Decls.begin()); } end()276 iterator end() const { return iterator(Decls.end()); } 277 278 /// \brief Return true if no decls were found empty()279 bool empty() const { return Decls.empty(); } 280 281 /// \brief Return the base paths structure that's associated with 282 /// these results, or null if none is. getBasePaths()283 CXXBasePaths *getBasePaths() const { 284 return Paths; 285 } 286 287 /// \brief Determine whether the given declaration is visible to the 288 /// program. isVisible(Sema & SemaRef,NamedDecl * D)289 static bool isVisible(Sema &SemaRef, NamedDecl *D) { 290 // If this declaration is not hidden, it's visible. 291 if (!D->isHidden()) 292 return true; 293 294 if (SemaRef.ActiveTemplateInstantiations.empty()) 295 return false; 296 297 // During template instantiation, we can refer to hidden declarations, if 298 // they were visible in any module along the path of instantiation. 299 return isVisibleSlow(SemaRef, D); 300 } 301 302 /// \brief Retrieve the accepted (re)declaration of the given declaration, 303 /// if there is one. getAcceptableDecl(NamedDecl * D)304 NamedDecl *getAcceptableDecl(NamedDecl *D) const { 305 if (!D->isInIdentifierNamespace(IDNS)) 306 return nullptr; 307 308 if (isHiddenDeclarationVisible() || isVisible(getSema(), D)) 309 return D; 310 311 return getAcceptableDeclSlow(D); 312 } 313 314 private: 315 static bool isVisibleSlow(Sema &SemaRef, NamedDecl *D); 316 NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const; 317 318 public: 319 /// \brief Returns the identifier namespace mask for this lookup. getIdentifierNamespace()320 unsigned getIdentifierNamespace() const { 321 return IDNS; 322 } 323 324 /// \brief Returns whether these results arose from performing a 325 /// lookup into a class. isClassLookup()326 bool isClassLookup() const { 327 return NamingClass != nullptr; 328 } 329 330 /// \brief Returns the 'naming class' for this lookup, i.e. the 331 /// class which was looked into to find these results. 332 /// 333 /// C++0x [class.access.base]p5: 334 /// The access to a member is affected by the class in which the 335 /// member is named. This naming class is the class in which the 336 /// member name was looked up and found. [Note: this class can be 337 /// explicit, e.g., when a qualified-id is used, or implicit, 338 /// e.g., when a class member access operator (5.2.5) is used 339 /// (including cases where an implicit "this->" is added). If both 340 /// a class member access operator and a qualified-id are used to 341 /// name the member (as in p->T::m), the class naming the member 342 /// is the class named by the nested-name-specifier of the 343 /// qualified-id (that is, T). -- end note ] 344 /// 345 /// This is set by the lookup routines when they find results in a class. getNamingClass()346 CXXRecordDecl *getNamingClass() const { 347 return NamingClass; 348 } 349 350 /// \brief Sets the 'naming class' for this lookup. setNamingClass(CXXRecordDecl * Record)351 void setNamingClass(CXXRecordDecl *Record) { 352 NamingClass = Record; 353 } 354 355 /// \brief Returns the base object type associated with this lookup; 356 /// important for [class.protected]. Most lookups do not have an 357 /// associated base object. getBaseObjectType()358 QualType getBaseObjectType() const { 359 return BaseObjectType; 360 } 361 362 /// \brief Sets the base object type for this lookup. setBaseObjectType(QualType T)363 void setBaseObjectType(QualType T) { 364 BaseObjectType = T; 365 } 366 367 /// \brief Add a declaration to these results with its natural access. 368 /// Does not test the acceptance criteria. addDecl(NamedDecl * D)369 void addDecl(NamedDecl *D) { 370 addDecl(D, D->getAccess()); 371 } 372 373 /// \brief Add a declaration to these results with the given access. 374 /// Does not test the acceptance criteria. addDecl(NamedDecl * D,AccessSpecifier AS)375 void addDecl(NamedDecl *D, AccessSpecifier AS) { 376 Decls.addDecl(D, AS); 377 ResultKind = Found; 378 } 379 380 /// \brief Add all the declarations from another set of lookup 381 /// results. addAllDecls(const LookupResult & Other)382 void addAllDecls(const LookupResult &Other) { 383 Decls.append(Other.Decls.begin(), Other.Decls.end()); 384 ResultKind = Found; 385 } 386 387 /// \brief Determine whether no result was found because we could not 388 /// search into dependent base classes of the current instantiation. wasNotFoundInCurrentInstantiation()389 bool wasNotFoundInCurrentInstantiation() const { 390 return ResultKind == NotFoundInCurrentInstantiation; 391 } 392 393 /// \brief Note that while no result was found in the current instantiation, 394 /// there were dependent base classes that could not be searched. setNotFoundInCurrentInstantiation()395 void setNotFoundInCurrentInstantiation() { 396 assert(ResultKind == NotFound && Decls.empty()); 397 ResultKind = NotFoundInCurrentInstantiation; 398 } 399 400 /// \brief Determine whether the lookup result was shadowed by some other 401 /// declaration that lookup ignored. isShadowed()402 bool isShadowed() const { return Shadowed; } 403 404 /// \brief Note that we found and ignored a declaration while performing 405 /// lookup. setShadowed()406 void setShadowed() { Shadowed = true; } 407 408 /// \brief Resolves the result kind of the lookup, possibly hiding 409 /// decls. 410 /// 411 /// This should be called in any environment where lookup might 412 /// generate multiple lookup results. 413 void resolveKind(); 414 415 /// \brief Re-resolves the result kind of the lookup after a set of 416 /// removals has been performed. resolveKindAfterFilter()417 void resolveKindAfterFilter() { 418 if (Decls.empty()) { 419 if (ResultKind != NotFoundInCurrentInstantiation) 420 ResultKind = NotFound; 421 422 if (Paths) { 423 deletePaths(Paths); 424 Paths = nullptr; 425 } 426 } else { 427 AmbiguityKind SavedAK; 428 bool WasAmbiguous = false; 429 if (ResultKind == Ambiguous) { 430 SavedAK = Ambiguity; 431 WasAmbiguous = true; 432 } 433 ResultKind = Found; 434 resolveKind(); 435 436 // If we didn't make the lookup unambiguous, restore the old 437 // ambiguity kind. 438 if (ResultKind == Ambiguous) { 439 (void)WasAmbiguous; 440 assert(WasAmbiguous); 441 Ambiguity = SavedAK; 442 } else if (Paths) { 443 deletePaths(Paths); 444 Paths = nullptr; 445 } 446 } 447 } 448 449 template <class DeclClass> getAsSingle()450 DeclClass *getAsSingle() const { 451 if (getResultKind() != Found) return nullptr; 452 return dyn_cast<DeclClass>(getFoundDecl()); 453 } 454 455 /// \brief Fetch the unique decl found by this lookup. Asserts 456 /// that one was found. 457 /// 458 /// This is intended for users who have examined the result kind 459 /// and are certain that there is only one result. getFoundDecl()460 NamedDecl *getFoundDecl() const { 461 assert(getResultKind() == Found 462 && "getFoundDecl called on non-unique result"); 463 return (*begin())->getUnderlyingDecl(); 464 } 465 466 /// Fetches a representative decl. Useful for lazy diagnostics. getRepresentativeDecl()467 NamedDecl *getRepresentativeDecl() const { 468 assert(!Decls.empty() && "cannot get representative of empty set"); 469 return *begin(); 470 } 471 472 /// \brief Asks if the result is a single tag decl. isSingleTagDecl()473 bool isSingleTagDecl() const { 474 return getResultKind() == Found && isa<TagDecl>(getFoundDecl()); 475 } 476 477 /// \brief Make these results show that the name was found in 478 /// base classes of different types. 479 /// 480 /// The given paths object is copied and invalidated. 481 void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P); 482 483 /// \brief Make these results show that the name was found in 484 /// distinct base classes of the same type. 485 /// 486 /// The given paths object is copied and invalidated. 487 void setAmbiguousBaseSubobjects(CXXBasePaths &P); 488 489 /// \brief Make these results show that the name was found in 490 /// different contexts and a tag decl was hidden by an ordinary 491 /// decl in a different context. setAmbiguousQualifiedTagHiding()492 void setAmbiguousQualifiedTagHiding() { 493 setAmbiguous(AmbiguousTagHiding); 494 } 495 496 /// \brief Clears out any current state. clear()497 void clear() { 498 ResultKind = NotFound; 499 Decls.clear(); 500 if (Paths) deletePaths(Paths); 501 Paths = nullptr; 502 NamingClass = nullptr; 503 Shadowed = false; 504 } 505 506 /// \brief Clears out any current state and re-initializes for a 507 /// different kind of lookup. clear(Sema::LookupNameKind Kind)508 void clear(Sema::LookupNameKind Kind) { 509 clear(); 510 LookupKind = Kind; 511 configure(); 512 } 513 514 /// \brief Change this lookup's redeclaration kind. setRedeclarationKind(Sema::RedeclarationKind RK)515 void setRedeclarationKind(Sema::RedeclarationKind RK) { 516 Redecl = RK; 517 AllowHidden = (RK == Sema::ForRedeclaration); 518 configure(); 519 } 520 521 void print(raw_ostream &); 522 523 /// Suppress the diagnostics that would normally fire because of this 524 /// lookup. This happens during (e.g.) redeclaration lookups. suppressDiagnostics()525 void suppressDiagnostics() { 526 Diagnose = false; 527 } 528 529 /// Determines whether this lookup is suppressing diagnostics. isSuppressingDiagnostics()530 bool isSuppressingDiagnostics() const { 531 return !Diagnose; 532 } 533 534 /// Sets a 'context' source range. setContextRange(SourceRange SR)535 void setContextRange(SourceRange SR) { 536 NameContextRange = SR; 537 } 538 539 /// Gets the source range of the context of this name; for C++ 540 /// qualified lookups, this is the source range of the scope 541 /// specifier. getContextRange()542 SourceRange getContextRange() const { 543 return NameContextRange; 544 } 545 546 /// Gets the location of the identifier. This isn't always defined: 547 /// sometimes we're doing lookups on synthesized names. getNameLoc()548 SourceLocation getNameLoc() const { 549 return NameInfo.getLoc(); 550 } 551 552 /// \brief Get the Sema object that this lookup result is searching 553 /// with. getSema()554 Sema &getSema() const { return *SemaPtr; } 555 556 /// A class for iterating through a result set and possibly 557 /// filtering out results. The results returned are possibly 558 /// sugared. 559 class Filter { 560 LookupResult &Results; 561 LookupResult::iterator I; 562 bool Changed; 563 bool CalledDone; 564 565 friend class LookupResult; Filter(LookupResult & Results)566 Filter(LookupResult &Results) 567 : Results(Results), I(Results.begin()), Changed(false), CalledDone(false) 568 {} 569 570 public: ~Filter()571 ~Filter() { 572 assert(CalledDone && 573 "LookupResult::Filter destroyed without done() call"); 574 } 575 hasNext()576 bool hasNext() const { 577 return I != Results.end(); 578 } 579 next()580 NamedDecl *next() { 581 assert(I != Results.end() && "next() called on empty filter"); 582 return *I++; 583 } 584 585 /// Restart the iteration. restart()586 void restart() { 587 I = Results.begin(); 588 } 589 590 /// Erase the last element returned from this iterator. erase()591 void erase() { 592 Results.Decls.erase(--I); 593 Changed = true; 594 } 595 596 /// Replaces the current entry with the given one, preserving the 597 /// access bits. replace(NamedDecl * D)598 void replace(NamedDecl *D) { 599 Results.Decls.replace(I-1, D); 600 Changed = true; 601 } 602 603 /// Replaces the current entry with the given one. replace(NamedDecl * D,AccessSpecifier AS)604 void replace(NamedDecl *D, AccessSpecifier AS) { 605 Results.Decls.replace(I-1, D, AS); 606 Changed = true; 607 } 608 done()609 void done() { 610 assert(!CalledDone && "done() called twice"); 611 CalledDone = true; 612 613 if (Changed) 614 Results.resolveKindAfterFilter(); 615 } 616 }; 617 618 /// Create a filter for this result set. makeFilter()619 Filter makeFilter() { 620 return Filter(*this); 621 } 622 setFindLocalExtern(bool FindLocalExtern)623 void setFindLocalExtern(bool FindLocalExtern) { 624 if (FindLocalExtern) 625 IDNS |= Decl::IDNS_LocalExtern; 626 else 627 IDNS &= ~Decl::IDNS_LocalExtern; 628 } 629 630 private: diagnose()631 void diagnose() { 632 if (isAmbiguous()) 633 getSema().DiagnoseAmbiguousLookup(*this); 634 else if (isClassLookup() && getSema().getLangOpts().AccessControl) 635 getSema().CheckLookupAccess(*this); 636 } 637 setAmbiguous(AmbiguityKind AK)638 void setAmbiguous(AmbiguityKind AK) { 639 ResultKind = Ambiguous; 640 Ambiguity = AK; 641 } 642 643 void addDeclsFromBasePaths(const CXXBasePaths &P); 644 void configure(); 645 646 // Sanity checks. 647 bool sanity() const; 648 sanityCheckUnresolved()649 bool sanityCheckUnresolved() const { 650 for (iterator I = begin(), E = end(); I != E; ++I) 651 if (isa<UnresolvedUsingValueDecl>((*I)->getUnderlyingDecl())) 652 return true; 653 return false; 654 } 655 656 static void deletePaths(CXXBasePaths *); 657 658 // Results. 659 LookupResultKind ResultKind; 660 AmbiguityKind Ambiguity; // ill-defined unless ambiguous 661 UnresolvedSet<8> Decls; 662 CXXBasePaths *Paths; 663 CXXRecordDecl *NamingClass; 664 QualType BaseObjectType; 665 666 // Parameters. 667 Sema *SemaPtr; 668 DeclarationNameInfo NameInfo; 669 SourceRange NameContextRange; 670 Sema::LookupNameKind LookupKind; 671 unsigned IDNS; // set by configure() 672 673 bool Redecl; 674 675 /// \brief True if tag declarations should be hidden if non-tags 676 /// are present 677 bool HideTags; 678 679 bool Diagnose; 680 681 /// \brief True if we should allow hidden declarations to be 'visible'. 682 bool AllowHidden; 683 684 /// \brief True if the found declarations were shadowed by some other 685 /// declaration that we skipped. This only happens when \c LookupKind 686 /// is \c LookupRedeclarationWithLinkage. 687 bool Shadowed; 688 }; 689 690 /// \brief Consumes visible declarations found when searching for 691 /// all visible names within a given scope or context. 692 /// 693 /// This abstract class is meant to be subclassed by clients of \c 694 /// Sema::LookupVisibleDecls(), each of which should override the \c 695 /// FoundDecl() function to process declarations as they are found. 696 class VisibleDeclConsumer { 697 public: 698 /// \brief Destroys the visible declaration consumer. 699 virtual ~VisibleDeclConsumer(); 700 701 /// \brief Determine whether hidden declarations (from unimported 702 /// modules) should be given to this consumer. By default, they 703 /// are not included. 704 virtual bool includeHiddenDecls() const; 705 706 /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a 707 /// declaration visible from the current scope or context. 708 /// 709 /// \param ND the declaration found. 710 /// 711 /// \param Hiding a declaration that hides the declaration \p ND, 712 /// or NULL if no such declaration exists. 713 /// 714 /// \param Ctx the original context from which the lookup started. 715 /// 716 /// \param InBaseClass whether this declaration was found in base 717 /// class of the context we searched. 718 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, 719 bool InBaseClass) = 0; 720 }; 721 722 /// \brief A class for storing results from argument-dependent lookup. 723 class ADLResult { 724 private: 725 /// A map from canonical decls to the 'most recent' decl. 726 llvm::DenseMap<NamedDecl*, NamedDecl*> Decls; 727 728 public: 729 /// Adds a new ADL candidate to this map. 730 void insert(NamedDecl *D); 731 732 /// Removes any data associated with a given decl. erase(NamedDecl * D)733 void erase(NamedDecl *D) { 734 Decls.erase(cast<NamedDecl>(D->getCanonicalDecl())); 735 } 736 737 class iterator 738 : public std::iterator<std::forward_iterator_tag, NamedDecl *> { 739 typedef llvm::DenseMap<NamedDecl*,NamedDecl*>::iterator inner_iterator; 740 inner_iterator iter; 741 742 friend class ADLResult; iterator(const inner_iterator & iter)743 iterator(const inner_iterator &iter) : iter(iter) {} 744 public: iterator()745 iterator() {} 746 747 iterator &operator++() { ++iter; return *this; } 748 iterator operator++(int) { return iterator(iter++); } 749 750 value_type operator*() const { return iter->second; } 751 752 bool operator==(const iterator &other) const { return iter == other.iter; } 753 bool operator!=(const iterator &other) const { return iter != other.iter; } 754 }; 755 begin()756 iterator begin() { return iterator(Decls.begin()); } end()757 iterator end() { return iterator(Decls.end()); } 758 }; 759 760 } 761 762 #endif 763