On Tue, Jul 27, 2010 at 10:29:14PM +0300, Argyrios Kyrtzidis wrote:
> On Jul 27, 2010, at 10:17 PM, Peter Collingbourne wrote:
> > On Tue, Jul 27, 2010 at 10:00:24PM +0300, Argyrios Kyrtzidis wrote:
> >> On Jul 27, 2010, at 9:55 PM, Peter Collingbourne wrote:
> >>> Another possibility would be to expose an iterator
> >>> specs_begin()..specs_end() over the set of specialisations.  This way
> >>> we don't need to copy the vector and the client still doesn't need
> >>> to care how the specialisation list is stored.
> >>
> >> Sounds good. I'd suggest that the iterator is a class wrapping the 
> >> FoldingSet's iterator and making sure to return the latest redeclaration, 
> >> what do you think ?
> > 
> > Agreed.  For consistency we can also have the FunctionTemplateDecl's
> > specialisation iterator produce FunctionDecls instead of
> > FunctionTemplateSpecializationInfos.
> 
> Yes, that'd be great.

Done, please see the attached patches.  I also decided to include
some refactoring for the find*Specialization member functions.
OK to commit?

Thanks,
-- 
Peter
>From 2101e942bff98f165255fa0c42b39293ec025a60 Mon Sep 17 00:00:00 2001
From: Peter Collingbourne <[email protected]>
Date: Fri, 30 Jul 2010 14:12:05 +0100
Subject: [PATCH 1/3] Introduce RedeclarableTemplateDecl::SpecEntryTraits

SpecEntryTraits describes how to obtain the most recent declaration
of a specialisation from an entry in a specialisation FoldingSet.
---
 include/clang/AST/DeclTemplate.h |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index b26c569..341c802 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -504,6 +504,14 @@ class RedeclarableTemplateDecl : public TemplateDecl {
   }
 
 protected:
+  template <typename EntryType> struct SpecEntryTraits {
+    typedef EntryType DeclType;
+
+    static DeclType *getMostRecentDeclaration(EntryType *D) {
+      return D->getMostRecentDeclaration();
+    }
+  };
+
   struct CommonBase {
     CommonBase() : InstantiatedFromMember(0, false) { }
 
@@ -677,6 +685,16 @@ public:
   }
 };
 
+template <> struct RedeclarableTemplateDecl::
+SpecEntryTraits<FunctionTemplateSpecializationInfo> {
+  typedef FunctionDecl DeclType;
+
+  static DeclType *
+  getMostRecentDeclaration(FunctionTemplateSpecializationInfo *I) {
+    return I->Function->getMostRecentDeclaration();
+  }
+};
+
 /// Declaration of a template function.
 class FunctionTemplateDecl : public RedeclarableTemplateDecl,
                              public RedeclarableTemplate<FunctionTemplateDecl> {
-- 
1.7.1

>From 14ba624982d4c7f5f662320b877c921262407a1f Mon Sep 17 00:00:00 2001
From: Peter Collingbourne <[email protected]>
Date: Fri, 30 Jul 2010 14:14:08 +0100
Subject: [PATCH 2/3] Refactor find*Specialization functions using SpecEntryTraits

This patch reimplements the find*Specialization family of member
functions of {Class,Function}TemplateDecl in terms of a common
implementation that uses SpecEntryTraits to obtain the most recent
declaration.
---
 include/clang/AST/DeclTemplate.h |    5 +++++
 lib/AST/DeclTemplate.cpp         |   33 +++++++++++++++++----------------
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 341c802..0f25547 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -512,6 +512,11 @@ protected:
     }
   };
 
+  template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType*
+  findSpecializationImpl(llvm::FoldingSet<EntryType> &Specs,
+                         const TemplateArgument *Args, unsigned NumArgs,
+                         void *&InsertPos);
+
   struct CommonBase {
     CommonBase() : InstantiatedFromMember(0, false) { }
 
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 25df086..e69338a 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -126,6 +126,19 @@ RedeclarableTemplateDecl *RedeclarableTemplateDecl::getNextRedeclaration() {
   return Common ? Common->Latest : this;
 }
 
+template <class EntryType>
+typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType*
+RedeclarableTemplateDecl::findSpecializationImpl(
+                                 llvm::FoldingSet<EntryType> &Specs,
+                                 const TemplateArgument *Args, unsigned NumArgs,
+                                 void *&InsertPos) {
+  typedef SpecEntryTraits<EntryType> SETraits;
+  llvm::FoldingSetNodeID ID;
+  EntryType::Profile(ID,Args,NumArgs, getASTContext());
+  EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
+  return Entry ? SETraits::getMostRecentDeclaration(Entry) : 0;
+}
+
 //===----------------------------------------------------------------------===//
 // FunctionTemplateDecl Implementation
 //===----------------------------------------------------------------------===//
@@ -152,11 +165,7 @@ RedeclarableTemplateDecl::CommonBase *FunctionTemplateDecl::newCommon() {
 FunctionDecl *
 FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
                                          unsigned NumArgs, void *&InsertPos) {
-  llvm::FoldingSetNodeID ID;
-  FunctionTemplateSpecializationInfo::Profile(ID,Args,NumArgs, getASTContext());
-  FunctionTemplateSpecializationInfo *Info
-      = getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
-  return Info ? Info->Function->getMostRecentDeclaration() : 0;
+  return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
 }
 
 //===----------------------------------------------------------------------===//
@@ -188,23 +197,15 @@ RedeclarableTemplateDecl::CommonBase *ClassTemplateDecl::newCommon() {
 ClassTemplateSpecializationDecl *
 ClassTemplateDecl::findSpecialization(const TemplateArgument *Args,
                                       unsigned NumArgs, void *&InsertPos) {
-  llvm::FoldingSetNodeID ID;
-  ClassTemplateSpecializationDecl::Profile(ID, Args, NumArgs, getASTContext());
-  ClassTemplateSpecializationDecl *D
-      = getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
-  return D ? D->getMostRecentDeclaration() : 0;
+  return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
 }
 
 ClassTemplatePartialSpecializationDecl *
 ClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args,
                                              unsigned NumArgs,
                                              void *&InsertPos) {
-  llvm::FoldingSetNodeID ID;
-  ClassTemplatePartialSpecializationDecl::Profile(ID, Args, NumArgs,
-                                                  getASTContext());
-  ClassTemplatePartialSpecializationDecl *D
-      = getPartialSpecializations().FindNodeOrInsertPos(ID, InsertPos);
-  return D ? D->getMostRecentDeclaration() : 0;
+  return findSpecializationImpl(getPartialSpecializations(), Args, NumArgs,
+                                InsertPos);
 }
 
 void ClassTemplateDecl::getPartialSpecializations(
-- 
1.7.1

>From d241ce39994419295bff8900bba242f5595c3066 Mon Sep 17 00:00:00 2001
From: Peter Collingbourne <[email protected]>
Date: Fri, 30 Jul 2010 14:15:28 +0100
Subject: [PATCH 3/3] Add specialisation iterators for {Class,Function}TemplateDecl

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.
---
 include/clang/AST/DeclTemplate.h |   74 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 74 insertions(+), 0 deletions(-)

diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 0f25547..246a06f 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -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; }
-- 
1.7.1

_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to