// FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h.
// We can refactor this core logic into something common.
-#ifndef LLVM_CLANG_AST_VECTOR
-#define LLVM_CLANG_AST_VECTOR
+#ifndef LLVM_CLANG_AST_ASTVECTOR_H
+#define LLVM_CLANG_AST_ASTVECTOR_H
#include "clang/AST/AttrIterator.h"
#include "llvm/ADT/PointerIntPair.h"
#include <cstring>
#include <memory>
-#ifdef _MSC_VER
-namespace std {
-#if _MSC_VER <= 1310
- // Work around flawed VC++ implementation of std::uninitialized_copy. Define
- // additional overloads so that elements with pointer types are recognized as
- // scalars and not objects, causing bizarre type conversion errors.
- template<class T1, class T2>
- inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) {
- _Scalar_ptr_iterator_tag _Cat;
- return _Cat;
- }
-
- template<class T1, class T2>
- inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) {
- _Scalar_ptr_iterator_tag _Cat;
- return _Cat;
- }
-#else
- // FIXME: It is not clear if the problem is fixed in VS 2005. What is clear
- // is that the above hack won't work if it wasn't fixed.
-#endif
-}
-#endif
-
namespace clang {
class ASTContext;
template<typename T>
class ASTVector {
- T *Begin, *End, *Capacity;
+private:
+ T *Begin, *End;
+ llvm::PointerIntPair<T*, 1, bool> Capacity;
void setEnd(T *P) { this->End = P; }
+protected:
+ // Make a tag bit available to users of this class.
+ // FIXME: This is a horrible hack.
+ bool getTag() const { return Capacity.getInt(); }
+ void setTag(bool B) { Capacity.setInt(B); }
+
public:
// Default ctor - Initialize to empty.
- ASTVector() : Begin(NULL), End(NULL), Capacity(NULL) { }
+ ASTVector() : Begin(nullptr), End(nullptr), Capacity(nullptr, false) {}
+
+ ASTVector(ASTVector &&O) : Begin(O.Begin), End(O.End), Capacity(O.Capacity) {
+ O.Begin = O.End = nullptr;
+ O.Capacity.setPointer(nullptr);
+ O.Capacity.setInt(false);
+ }
ASTVector(const ASTContext &C, unsigned N)
- : Begin(NULL), End(NULL), Capacity(NULL) {
+ : Begin(nullptr), End(nullptr), Capacity(nullptr, false) {
reserve(C, N);
}
+ ASTVector &operator=(ASTVector &&RHS) {
+ ASTVector O(std::move(RHS));
+ using std::swap;
+ swap(Begin, O.Begin);
+ swap(End, O.End);
+ swap(Capacity, O.Capacity);
+ return *this;
+ }
+
~ASTVector() {
- if (llvm::is_class<T>::value) {
+ if (std::is_class<T>::value) {
// Destroy the constructed elements in the vector.
destroy_range(Begin, End);
}
}
void clear() {
- if (llvm::is_class<T>::value) {
+ if (std::is_class<T>::value) {
destroy_range(Begin, End);
}
End = Begin;
}
void push_back(const_reference Elt, const ASTContext &C) {
- if (End < Capacity) {
+ if (End < this->capacity_ptr()) {
Retry:
new (End) T(Elt);
++End;
}
void reserve(const ASTContext &C, unsigned N) {
- if (unsigned(Capacity-Begin) < N)
+ if (unsigned(this->capacity_ptr()-Begin) < N)
grow(C, N);
}
/// capacity - Return the total number of elements in the currently allocated
/// buffer.
- size_t capacity() const { return Capacity - Begin; }
+ size_t capacity() const { return this->capacity_ptr() - Begin; }
/// append - Add the specified range to the end of the SmallVector.
///
return this->end()-1;
}
- if (this->End < this->Capacity) {
+ if (this->End < this->capacity_ptr()) {
Retry:
new (this->end()) T(this->back());
this->setEnd(this->end()+1);
}
protected:
- iterator capacity_ptr() { return (iterator)this->Capacity; }
+ const_iterator capacity_ptr() const {
+ return (iterator) Capacity.getPointer();
+ }
+ iterator capacity_ptr() { return (iterator)Capacity.getPointer(); }
};
// Define this out-of-line to dissuade the C++ compiler from inlining it.
template <typename T>
void ASTVector<T>::grow(const ASTContext &C, size_t MinSize) {
- size_t CurCapacity = Capacity-Begin;
+ size_t CurCapacity = this->capacity();
size_t CurSize = size();
size_t NewCapacity = 2*CurCapacity;
if (NewCapacity < MinSize)
T *NewElts = new (C, llvm::alignOf<T>()) T[NewCapacity];
// Copy the elements over.
- if (llvm::is_class<T>::value) {
+ if (std::is_class<T>::value) {
std::uninitialized_copy(Begin, End, NewElts);
// Destroy the original elements.
destroy_range(Begin, End);
// ASTContext never frees any memory.
Begin = NewElts;
End = NewElts+CurSize;
- Capacity = Begin+NewCapacity;
+ Capacity.setPointer(Begin+NewCapacity);
}
} // end: clang namespace