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