]> granicus.if.org Git - clang/commitdiff
Add specialisation iterators for {Class,Function}TemplateDecl
authorPeter Collingbourne <peter@pcc.me.uk>
Fri, 30 Jul 2010 17:09:11 +0000 (17:09 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Fri, 30 Jul 2010 17:09:11 +0000 (17:09 +0000)
This patch introduces the ClassTemplateDecl::spec_{begin,end}()
and FunctionTemplateDecl::{,partial_}spec_{begin,end}() member
functions as a public interface for iterating over the declarations'
specialisation sets.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109870 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclTemplate.h

index 0f255476759bf2983e15f163cfcd30f73118b896..246a06f9633c85630829cfa0a0a46332e5b28775 100644 (file)
@@ -512,6 +512,49 @@ protected:
     }
   };
 
+  template <typename EntryType,
+            typename _SETraits = SpecEntryTraits<EntryType>,
+            typename _DeclType = typename _SETraits::DeclType>
+  class SpecIterator : public std::iterator<std::forward_iterator_tag,
+                                            _DeclType*, ptrdiff_t,
+                                            _DeclType*, _DeclType*> {
+    typedef _SETraits SETraits;
+    typedef _DeclType DeclType;
+
+    typedef typename llvm::FoldingSet<EntryType>::iterator SetIteratorType;
+
+    SetIteratorType SetIter;
+
+  public:
+    SpecIterator() : SetIter() {}
+    SpecIterator(SetIteratorType SetIter) : SetIter(SetIter) {}
+
+    DeclType *operator*() const {
+      return SETraits::getMostRecentDeclaration(&*SetIter);
+    }
+    DeclType *operator->() const { return **this; }
+
+    SpecIterator &operator++() { ++SetIter; return *this; }
+    SpecIterator operator++(int) {
+      SpecIterator tmp(*this);
+      ++(*this);
+      return tmp;
+    }
+
+    bool operator==(SpecIterator Other) const {
+      return SetIter == Other.SetIter;
+    }
+    bool operator!=(SpecIterator Other) const {
+      return SetIter != Other.SetIter;
+    }
+  };
+
+  template <typename EntryType>
+  SpecIterator<EntryType> makeSpecIterator(llvm::FoldingSet<EntryType> &Specs,
+                                           bool isEnd) {
+    return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin());
+  }
+
   template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType*
   findSpecializationImpl(llvm::FoldingSet<EntryType> &Specs,
                          const TemplateArgument *Args, unsigned NumArgs,
@@ -774,6 +817,16 @@ public:
     return redeclarable_base::getInstantiatedFromMemberTemplate();
   }
 
+  typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator;
+
+  spec_iterator spec_begin() {
+    return makeSpecIterator(getSpecializations(), false);
+  }
+
+  spec_iterator spec_end() {
+    return makeSpecIterator(getSpecializations(), true);
+  }
+
   /// Create a template function node.
   static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
                                       SourceLocation L,
@@ -1679,6 +1732,27 @@ public:
   /// \endcode
   QualType getInjectedClassNameSpecialization();
 
+  typedef SpecIterator<ClassTemplateSpecializationDecl> spec_iterator;
+
+  spec_iterator spec_begin() {
+    return makeSpecIterator(getSpecializations(), false);
+  }
+
+  spec_iterator spec_end() {
+    return makeSpecIterator(getSpecializations(), true);
+  }
+
+  typedef SpecIterator<ClassTemplatePartialSpecializationDecl>
+          partial_spec_iterator;
+
+  partial_spec_iterator partial_spec_begin() {
+    return makeSpecIterator(getPartialSpecializations(), false);
+  }
+
+  partial_spec_iterator partial_spec_end() {
+    return makeSpecIterator(getPartialSpecializations(), true);
+  }
+
   // Implement isa/cast/dyncast support
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classof(const ClassTemplateDecl *D) { return true; }