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