diff options
-rw-r--r-- | include/llvm/ADT/TinyPtrVector.h | 65 | ||||
-rw-r--r-- | unittests/ADT/TinyPtrVectorTest.cpp | 166 |
2 files changed, 222 insertions, 9 deletions
diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h index a02c10edf7..1038c78448 100644 --- a/include/llvm/ADT/TinyPtrVector.h +++ b/include/llvm/ADT/TinyPtrVector.h @@ -32,19 +32,72 @@ public: llvm::PointerUnion<EltTy, VecTy*> Val; TinyPtrVector() {} + ~TinyPtrVector() { + if (VecTy *V = Val.template dyn_cast<VecTy*>()) + delete V; + } + TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) { if (VecTy *V = Val.template dyn_cast<VecTy*>()) Val = new VecTy(*V); } + TinyPtrVector &operator=(const TinyPtrVector &RHS) { + if (this == &RHS) + return *this; + if (RHS.empty()) { + this->clear(); + return *this; + } + + // Try to squeeze into the single slot. If it won't fit, allocate a copied + // vector. + if (Val.template is<EltTy>()) { + if (RHS.size() == 1) + Val = RHS.front(); + else + Val = new VecTy(*RHS.Val.template get<VecTy*>()); + return *this; + } + + // If we have a full vector allocated, try to re-use it. + if (RHS.Val.template is<EltTy>()) { + Val.template get<VecTy*>()->clear(); + Val.template get<VecTy*>()->push_back(RHS.front()); + } else { + *Val.template get<VecTy*>() = *RHS.Val.template get<VecTy*>(); + } + return *this; + } + #if LLVM_USE_RVALUE_REFERENCES TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) { RHS.Val = (EltTy)0; } -#endif - ~TinyPtrVector() { - if (VecTy *V = Val.template dyn_cast<VecTy*>()) + TinyPtrVector &operator=(TinyPtrVector &&RHS) { + if (this == &RHS) + return *this; + if (RHS.empty()) { + this->clear(); + return *this; + } + + // If this vector has been allocated on the heap, re-use it if cheap. If it + // would require more copying, just delete it and we'll steal the other + // side. + if (VecTy *V = Val.template dyn_cast<VecTy*>()) { + if (RHS.Val.template is<EltTy>()) { + V->clear(); + V->push_back(RHS.front()); + return *this; + } delete V; + } + + Val = RHS.Val; + RHS.Val = (EltTy)0; + return *this; } +#endif // implicit conversion operator to ArrayRef. operator ArrayRef<EltTy>() const { @@ -173,12 +226,6 @@ public: } return end(); } - -private: - void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET. -#if LLVM_USE_RVALUE_REFERENCES - void operator=(TinyPtrVector&&); // NOT IMPLEMENTED YET. -#endif }; } // end namespace llvm diff --git a/unittests/ADT/TinyPtrVectorTest.cpp b/unittests/ADT/TinyPtrVectorTest.cpp index 9f02b3ce0f..94939279c1 100644 --- a/unittests/ADT/TinyPtrVectorTest.cpp +++ b/unittests/ADT/TinyPtrVectorTest.cpp @@ -60,6 +60,13 @@ protected: V.push_back(Values[i]); } + void setVectors(ArrayRef<PtrT> Values1, ArrayRef<PtrT> Values2) { + V.clear(); + appendValues(V, Values1); + V2.clear(); + appendValues(V2, Values2); + } + void expectValues(const VectorT &V, ArrayRef<PtrT> Values) { EXPECT_EQ(Values.empty(), V.empty()); EXPECT_EQ(Values.size(), V.size()); @@ -157,6 +164,165 @@ TYPED_TEST(TinyPtrVectorTest, CopyAndMoveCtorTest) { #endif } +TYPED_TEST(TinyPtrVectorTest, CopyAndMoveTest) { + this->V = this->V2; + this->expectValues(this->V, this->testArray(0)); + this->expectValues(this->V2, this->testArray(0)); +#if LLVM_USE_RVALUE_REFERENCES + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(0)); +#endif + + this->setVectors(this->testArray(1), this->testArray(0)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(0)); + this->expectValues(this->V2, this->testArray(0)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(1), this->testArray(0)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(0)); +#endif + + this->setVectors(this->testArray(2), this->testArray(0)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(0)); + this->expectValues(this->V2, this->testArray(0)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(2), this->testArray(0)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(0)); +#endif + + this->setVectors(this->testArray(42), this->testArray(0)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(0)); + this->expectValues(this->V2, this->testArray(0)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(42), this->testArray(0)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(0)); +#endif + + this->setVectors(this->testArray(0), this->testArray(1)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(1)); + this->expectValues(this->V2, this->testArray(1)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(0), this->testArray(1)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(1)); +#endif + + this->setVectors(this->testArray(0), this->testArray(2)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(2)); + this->expectValues(this->V2, this->testArray(2)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(0), this->testArray(2)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(2)); +#endif + + this->setVectors(this->testArray(0), this->testArray(42)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(42)); + this->expectValues(this->V2, this->testArray(42)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(0), this->testArray(42)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(42)); +#endif + + this->setVectors(this->testArray(1), this->testArray(1)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(1)); + this->expectValues(this->V2, this->testArray(1)); +#if LLVM_USE_RVALUE_REFERENCES + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(1)); +#endif + + this->setVectors(this->testArray(1), this->testArray(2)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(2)); + this->expectValues(this->V2, this->testArray(2)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(1), this->testArray(2)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(2)); +#endif + + this->setVectors(this->testArray(1), this->testArray(42)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(42)); + this->expectValues(this->V2, this->testArray(42)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(1), this->testArray(42)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(42)); +#endif + + this->setVectors(this->testArray(2), this->testArray(1)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(1)); + this->expectValues(this->V2, this->testArray(1)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(2), this->testArray(1)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(1)); +#endif + + this->setVectors(this->testArray(2), this->testArray(2)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(2)); + this->expectValues(this->V2, this->testArray(2)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(2), this->testArray(2)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(2)); +#endif + + this->setVectors(this->testArray(2), this->testArray(42)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(42)); + this->expectValues(this->V2, this->testArray(42)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(2), this->testArray(42)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(42)); +#endif + + this->setVectors(this->testArray(42), this->testArray(1)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(1)); + this->expectValues(this->V2, this->testArray(1)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(42), this->testArray(1)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(1)); +#endif + + this->setVectors(this->testArray(42), this->testArray(2)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(2)); + this->expectValues(this->V2, this->testArray(2)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(42), this->testArray(2)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(2)); +#endif + + this->setVectors(this->testArray(42), this->testArray(42)); + this->V = this->V2; + this->expectValues(this->V, this->testArray(42)); + this->expectValues(this->V2, this->testArray(42)); +#if LLVM_USE_RVALUE_REFERENCES + this->setVectors(this->testArray(42), this->testArray(42)); + this->V = std::move(this->V2); + this->expectValues(this->V, this->testArray(42)); +#endif +} + TYPED_TEST(TinyPtrVectorTest, EraseTest) { this->appendValues(this->V, this->testArray(1)); this->expectValues(this->V, this->testArray(1)); |