r232322 - Implement PreprocessingRecord's and LazyVector's iterators on top of iterator_adaptor_base

Benjamin Kramer benny.kra at googlemail.com
Sun Mar 15 08:27:19 PDT 2015


Author: d0k
Date: Sun Mar 15 10:27:19 2015
New Revision: 232322

URL: http://llvm.org/viewvc/llvm-project?rev=232322&view=rev
Log:
Implement PreprocessingRecord's and LazyVector's iterators on top of iterator_adaptor_base

This basically creates a wrapper around an 'int' that poses as an iterator.
While that looks a bit counter-intuitive it works just fine because iterator
operations and basic integer arithmetic works in exactly the same way.

Remove the manual integer wrapping code and reduce the reliance on iterator
internals in the implementation. No functionality change intended.

Modified:
    cfe/trunk/include/clang/AST/ExternalASTSource.h
    cfe/trunk/include/clang/Lex/PreprocessingRecord.h
    cfe/trunk/lib/Lex/PreprocessingRecord.cpp

Modified: cfe/trunk/include/clang/AST/ExternalASTSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExternalASTSource.h?rev=232322&r1=232321&r2=232322&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExternalASTSource.h (original)
+++ cfe/trunk/include/clang/AST/ExternalASTSource.h Sun Mar 15 10:27:19 2015
@@ -477,132 +477,42 @@ class LazyVector {
   SmallVector<T, LocalStorage> Local;
 
 public:
-  // Iteration over the elements in the vector.
-  class iterator {
+  /// Iteration over the elements in the vector.
+  ///
+  /// In a complete iteration, the iterator walks the range [-M, N),
+  /// where negative values are used to indicate elements
+  /// loaded from the external source while non-negative values are used to
+  /// indicate elements added via \c push_back().
+  /// However, to provide iteration in source order (for, e.g., chained
+  /// precompiled headers), dereferencing the iterator flips the negative
+  /// values (corresponding to loaded entities), so that position -M
+  /// corresponds to element 0 in the loaded entities vector, position -M+1
+  /// corresponds to element 1 in the loaded entities vector, etc. This
+  /// gives us a reasonably efficient, source-order walk.
+  ///
+  /// We define this as a wrapping iterator around an int. The
+  /// iterator_adaptor_base class forwards the iterator methods to basic integer
+  /// arithmetic.
+  class iterator : public llvm::iterator_adaptor_base<
+                       iterator, int, std::random_access_iterator_tag, T, int> {
     LazyVector *Self;
-    
-    /// \brief Position within the vector..
-    ///
-    /// In a complete iteration, the Position field walks the range [-M, N),
-    /// where negative values are used to indicate elements
-    /// loaded from the external source while non-negative values are used to
-    /// indicate elements added via \c push_back().
-    /// However, to provide iteration in source order (for, e.g., chained
-    /// precompiled headers), dereferencing the iterator flips the negative
-    /// values (corresponding to loaded entities), so that position -M 
-    /// corresponds to element 0 in the loaded entities vector, position -M+1
-    /// corresponds to element 1 in the loaded entities vector, etc. This
-    /// gives us a reasonably efficient, source-order walk.
-    int Position;
-    
+
+    iterator(LazyVector *Self, int Position)
+        : iterator::iterator_adaptor_base(Position), Self(Self) {}
+
+    bool isLoaded() const { return this->I < 0; }
     friend class LazyVector;
-    
+
   public:
-    typedef T                   value_type;
-    typedef value_type&         reference;
-    typedef value_type*         pointer;
-    typedef std::random_access_iterator_tag iterator_category;
-    typedef int                 difference_type;
-    
-    iterator() : Self(0), Position(0) { }
-    
-    iterator(LazyVector *Self, int Position) 
-      : Self(Self), Position(Position) { }
-    
-    reference operator*() const {
-      if (Position < 0)
-        return Self->Loaded.end()[Position];
-      return Self->Local[Position];
-    }
-    
-    pointer operator->() const {
-      if (Position < 0)
-        return &Self->Loaded.end()[Position];
-      
-      return &Self->Local[Position];        
-    }
-    
-    reference operator[](difference_type D) {
-      return *(*this + D);
-    }
-    
-    iterator &operator++() {
-      ++Position;
-      return *this;
-    }
-    
-    iterator operator++(int) {
-      iterator Prev(*this);
-      ++Position;
-      return Prev;
-    }
-    
-    iterator &operator--() {
-      --Position;
-      return *this;
-    }
-    
-    iterator operator--(int) {
-      iterator Prev(*this);
-      --Position;
-      return Prev;
-    }
-    
-    friend bool operator==(const iterator &X, const iterator &Y) {
-      return X.Position == Y.Position;
-    }
-    
-    friend bool operator!=(const iterator &X, const iterator &Y) {
-      return X.Position != Y.Position;
-    }
-    
-    friend bool operator<(const iterator &X, const iterator &Y) {
-      return X.Position < Y.Position;
-    }
-    
-    friend bool operator>(const iterator &X, const iterator &Y) {
-      return X.Position > Y.Position;
-    }
-    
-    friend bool operator<=(const iterator &X, const iterator &Y) {
-      return X.Position < Y.Position;
-    }
-    
-    friend bool operator>=(const iterator &X, const iterator &Y) {
-      return X.Position > Y.Position;
-    }
-    
-    friend iterator& operator+=(iterator &X, difference_type D) {
-      X.Position += D;
-      return X;
-    }
-    
-    friend iterator& operator-=(iterator &X, difference_type D) {
-      X.Position -= D;
-      return X;
-    }
-    
-    friend iterator operator+(iterator X, difference_type D) {
-      X.Position += D;
-      return X;
-    }
-    
-    friend iterator operator+(difference_type D, iterator X) {
-      X.Position += D;
-      return X;
-    }
-    
-    friend difference_type operator-(const iterator &X, const iterator &Y) {
-      return X.Position - Y.Position;
-    }
-    
-    friend iterator operator-(iterator X, difference_type D) {
-      X.Position -= D;
-      return X;
+    iterator() : iterator(nullptr, 0) {}
+
+    typename iterator::reference operator*() const {
+      if (isLoaded())
+        return Self->Loaded.end()[this->I];
+      return Self->Local.begin()[this->I];
     }
   };
-  friend class iterator;
-  
+
   iterator begin(Source *source, bool LocalOnly = false) {
     if (LocalOnly)
       return iterator(this, 0);
@@ -621,17 +531,17 @@ public:
   }
   
   void erase(iterator From, iterator To) {
-    if (From.Position < 0 && To.Position < 0) {
-      Loaded.erase(Loaded.end() + From.Position, Loaded.end() + To.Position);
+    if (From.isLoaded() && To.isLoaded()) {
+      Loaded.erase(&*From, &*To);
       return;
     }
-    
-    if (From.Position < 0) {
-      Loaded.erase(Loaded.end() + From.Position, Loaded.end());
+
+    if (From.isLoaded()) {
+      Loaded.erase(&*From, Loaded.end());
       From = begin(nullptr, true);
     }
-    
-    Local.erase(Local.begin() + From.Position, Local.begin() + To.Position);
+
+    Local.erase(&*From, &*To);
   }
 };
 

Modified: cfe/trunk/include/clang/Lex/PreprocessingRecord.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/PreprocessingRecord.h?rev=232322&r1=232321&r2=232322&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/PreprocessingRecord.h (original)
+++ cfe/trunk/include/clang/Lex/PreprocessingRecord.h Sun Mar 15 10:27:19 2015
@@ -20,6 +20,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Compiler.h"
 #include <vector>
@@ -378,125 +379,44 @@ namespace clang {
 
     SourceManager &getSourceManager() const { return SourceMgr; }
 
-    // Iteration over the preprocessed entities.
-    class iterator {
+    /// Iteration over the preprocessed entities.
+    ///
+    /// In a complete iteration, the iterator walks the range [-M, N),
+    /// where negative values are used to indicate preprocessed entities
+    /// loaded from the external source while non-negative values are used to
+    /// indicate preprocessed entities introduced by the current preprocessor.
+    /// However, to provide iteration in source order (for, e.g., chained
+    /// precompiled headers), dereferencing the iterator flips the negative
+    /// values (corresponding to loaded entities), so that position -M
+    /// corresponds to element 0 in the loaded entities vector, position -M+1
+    /// corresponds to element 1 in the loaded entities vector, etc. This
+    /// gives us a reasonably efficient, source-order walk.
+    ///
+    /// We define this as a wrapping iterator around an int. The
+    /// iterator_adaptor_base class forwards the iterator methods to basic
+    /// integer arithmetic.
+    class iterator : public llvm::iterator_adaptor_base<
+                         iterator, int, std::random_access_iterator_tag,
+                         PreprocessedEntity *, int, PreprocessedEntity *,
+                         PreprocessedEntity *> {
       PreprocessingRecord *Self;
-      
-      /// \brief Position within the preprocessed entity sequence.
-      ///
-      /// In a complete iteration, the Position field walks the range [-M, N),
-      /// where negative values are used to indicate preprocessed entities
-      /// loaded from the external source while non-negative values are used to
-      /// indicate preprocessed entities introduced by the current preprocessor.
-      /// However, to provide iteration in source order (for, e.g., chained
-      /// precompiled headers), dereferencing the iterator flips the negative
-      /// values (corresponding to loaded entities), so that position -M 
-      /// corresponds to element 0 in the loaded entities vector, position -M+1
-      /// corresponds to element 1 in the loaded entities vector, etc. This
-      /// gives us a reasonably efficient, source-order walk.
-      int Position;
-      
-    public:
-      typedef PreprocessedEntity *value_type;
-      typedef value_type&         reference;
-      typedef value_type*         pointer;
-      typedef std::random_access_iterator_tag iterator_category;
-      typedef int                 difference_type;
-      
-      iterator() : Self(nullptr), Position(0) { }
-      
+
       iterator(PreprocessingRecord *Self, int Position)
-        : Self(Self), Position(Position) { }
-      
-      value_type operator*() const {
-        bool isLoaded = Position < 0;
+          : iterator::iterator_adaptor_base(Position), Self(Self) {}
+      friend class PreprocessingRecord;
+
+    public:
+      iterator() : iterator(nullptr, 0) {}
+
+      PreprocessedEntity *operator*() const {
+        bool isLoaded = this->I < 0;
         unsigned Index = isLoaded ?
-            Self->LoadedPreprocessedEntities.size() + Position : Position;
+            Self->LoadedPreprocessedEntities.size() + this->I : this->I;
         PPEntityID ID = Self->getPPEntityID(Index, isLoaded);
         return Self->getPreprocessedEntity(ID);
       }
-      
-      value_type operator[](difference_type D) {
-        return *(*this + D);
-      }
-      
-      iterator &operator++() {
-        ++Position;
-        return *this;
-      }
-      
-      iterator operator++(int) {
-        iterator Prev(*this);
-        ++Position;
-        return Prev;
-      }
-
-      iterator &operator--() {
-        --Position;
-        return *this;
-      }
-      
-      iterator operator--(int) {
-        iterator Prev(*this);
-        --Position;
-        return Prev;
-      }
-
-      friend bool operator==(const iterator &X, const iterator &Y) {
-        return X.Position == Y.Position;
-      }
-
-      friend bool operator!=(const iterator &X, const iterator &Y) {
-        return X.Position != Y.Position;
-      }
-      
-      friend bool operator<(const iterator &X, const iterator &Y) {
-        return X.Position < Y.Position;
-      }
-
-      friend bool operator>(const iterator &X, const iterator &Y) {
-        return X.Position > Y.Position;
-      }
-
-      friend bool operator<=(const iterator &X, const iterator &Y) {
-        return X.Position < Y.Position;
-      }
-      
-      friend bool operator>=(const iterator &X, const iterator &Y) {
-        return X.Position > Y.Position;
-      }
-
-      friend iterator& operator+=(iterator &X, difference_type D) {
-        X.Position += D;
-        return X;
-      }
-
-      friend iterator& operator-=(iterator &X, difference_type D) {
-        X.Position -= D;
-        return X;
-      }
-
-      friend iterator operator+(iterator X, difference_type D) {
-        X.Position += D;
-        return X;
-      }
-
-      friend iterator operator+(difference_type D, iterator X) {
-        X.Position += D;
-        return X;
-      }
-
-      friend difference_type operator-(const iterator &X, const iterator &Y) {
-        return X.Position - Y.Position;
-      }
-
-      friend iterator operator-(iterator X, difference_type D) {
-        X.Position -= D;
-        return X;
-      }
-      friend class PreprocessingRecord;
+      PreprocessedEntity *operator->() const { return **this; }
     };
-    friend class iterator;
 
     /// \brief Begin iterator for all preprocessed entities.
     iterator begin() {

Modified: cfe/trunk/lib/Lex/PreprocessingRecord.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PreprocessingRecord.cpp?rev=232322&r1=232321&r2=232322&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PreprocessingRecord.cpp (original)
+++ cfe/trunk/lib/Lex/PreprocessingRecord.cpp Sun Mar 15 10:27:19 2015
@@ -88,7 +88,7 @@ bool PreprocessingRecord::isEntityInFile
   if (FID.isInvalid())
     return false;
 
-  int Pos = PPEI.Position;
+  int Pos = std::distance(iterator(this, 0), PPEI);
   if (Pos < 0) {
     if (unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) {
       assert(0 && "Out-of bounds loaded preprocessed entity");





More information about the cfe-commits mailing list