Provide a new kind of iterator, the specific_decl_iterator, that
filters the decls seen by decl_iterator with two criteria: the dynamic
type of the declaration and a run-time predicate described by a member
function. This simplifies EnumDecl, RecordDecl, and ObjCContainerDecl
considerably. It has no measurable performance impact.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61994 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index a6ab452..c6a18a2 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -490,6 +490,90 @@
   decl_iterator decls_begin() const { return Decls.begin(); }
   decl_iterator decls_end()   const { return Decls.end(); }
 
+  /// specific_decl_iterator - Iterates over a subrange of
+  /// declarations stored in a DeclContext, providing only those that
+  /// are of type SpecificDecl (or a class derived from it) and,
+  /// optionally, that meet some additional run-time criteria. This
+  /// iterator is used, for example, to provide iteration over just
+  /// the fields within a RecordDecl (with SpecificDecl = FieldDecl)
+  /// or the instance methods within an Objective-C interface (with
+  /// SpecificDecl = ObjCMethodDecl and using
+  /// ObjCMethodDecl::isInstanceMethod as the run-time criteria). 
+  template<typename SpecificDecl>
+  class specific_decl_iterator {
+    /// Current - The current, underlying declaration iterator, which
+    /// will either be the same as End or will point to a declaration of
+    /// type SpecificDecl.
+    DeclContext::decl_iterator Current;
+    
+    /// End - One past the last declaration within the DeclContext.
+    DeclContext::decl_iterator End;
+
+    /// Acceptable - If non-NULL, points to a member function that
+    /// will determine if a particular declaration of type
+    /// SpecificDecl should be visited by the iteration.
+    bool (SpecificDecl::*Acceptable)() const;
+
+    /// SkipToNextDecl - Advances the current position up to the next
+    /// declaration of type SpecificDecl that also meets the criteria
+    /// required by Acceptable.
+    void SkipToNextDecl() {
+      while (Current != End && 
+             (!isa<SpecificDecl>(*Current) ||
+              (Acceptable && !(cast<SpecificDecl>(*Current)->*Acceptable)())))
+        ++Current;
+    }
+
+  public:
+    typedef SpecificDecl* value_type;
+    typedef SpecificDecl* reference;
+    typedef SpecificDecl* pointer;
+    typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
+      difference_type;
+    typedef std::forward_iterator_tag iterator_category;
+
+    specific_decl_iterator() : Current(), End(), Acceptable(0) { }
+
+    /// specific_decl_iterator - Construct a new iterator over a
+    /// subset of the declarations in [C, E). If A is non-NULL, it is
+    /// a pointer to a member function of SpecificDecl that should
+    /// return true for all of the SpecificDecl instances that will be
+    /// in the subset of iterators. For example, if you want
+    /// Objective-C instance methods, SpecificDecl will be
+    /// ObjCMethodDecl and A will be &ObjCMethodDecl::isInstanceMethod.
+    specific_decl_iterator(DeclContext::decl_iterator C, 
+                           DeclContext::decl_iterator E,
+                           bool (SpecificDecl::*A)() const = 0)
+      : Current(C), End(E), Acceptable(A) {
+      SkipToNextDecl();
+    }
+
+    reference operator*() { return cast<SpecificDecl>(*Current); }
+    pointer operator->() { return cast<SpecificDecl>(*Current); }
+
+    specific_decl_iterator& operator++() {
+      ++Current;
+      SkipToNextDecl();
+      return *this;
+    }
+
+    specific_decl_iterator operator++(int) {
+      specific_decl_iterator tmp(*this);
+      ++(*this);
+      return tmp;
+    }
+  
+    friend bool
+    operator==(const specific_decl_iterator& x, const specific_decl_iterator& y) {
+      return x.Current == y.Current;
+    }
+  
+    friend bool 
+    operator!=(const specific_decl_iterator& x, const specific_decl_iterator& y) {
+      return x.Current != y.Current;
+    }
+  };
+
   /// addDecl - Add the declaration D to this scope. Note that
   /// declarations are added at the beginning of the declaration
   /// chain, so reverseDeclChain() should be called after all
@@ -590,7 +674,6 @@
   return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm;
 }
 
-
 } // end clang.
 
 namespace llvm {