+
+ // Copy over the new array size
+ CurArraySize = that.CurArraySize;
+
+ // Copy over the contents from the other set
+ memcpy(CurArray, that.CurArray, sizeof(void*)*CurArraySize);
+
+ NumElements = that.NumElements;
+ NumTombstones = that.NumTombstones;
+}
+
+SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,
+ unsigned SmallSize,
+ SmallPtrSetImplBase &&that) {
+ SmallArray = SmallStorage;
+
+ // Copy over the basic members.
+ CurArraySize = that.CurArraySize;
+ NumElements = that.NumElements;
+ NumTombstones = that.NumTombstones;
+
+ // When small, just copy into our small buffer.
+ if (that.isSmall()) {
+ CurArray = SmallArray;
+ memcpy(CurArray, that.CurArray, sizeof(void *) * CurArraySize);
+ } else {
+ // Otherwise, we steal the large memory allocation and no copy is needed.
+ CurArray = that.CurArray;
+ that.CurArray = that.SmallArray;
+ }
+
+ // Make the "that" object small and empty.
+ that.CurArraySize = SmallSize;
+ assert(that.CurArray == that.SmallArray);
+ that.NumElements = 0;
+ that.NumTombstones = 0;
+}
+
+/// CopyFrom - implement operator= from a smallptrset that has the same pointer
+/// type, but may have a different small size.
+void SmallPtrSetImplBase::CopyFrom(const SmallPtrSetImplBase &RHS) {
+ assert(&RHS != this && "Self-copy should be handled by the caller.");
+
+ if (isSmall() && RHS.isSmall())
+ assert(CurArraySize == RHS.CurArraySize &&
+ "Cannot assign sets with different small sizes");
+
+ // If we're becoming small, prepare to insert into our stack space
+ if (RHS.isSmall()) {
+ if (!isSmall())
+ free(CurArray);
+ CurArray = SmallArray;
+ // Otherwise, allocate new heap space (unless we were the same size)
+ } else if (CurArraySize != RHS.CurArraySize) {
+ if (isSmall())
+ CurArray = (const void**)malloc(sizeof(void*) * RHS.CurArraySize);
+ else {
+ const void **T = (const void**)realloc(CurArray,
+ sizeof(void*) * RHS.CurArraySize);
+ if (!T)
+ free(CurArray);
+ CurArray = T;
+ }
+ assert(CurArray && "Failed to allocate memory?");
+ }
+
+ // Copy over the new array size
+ CurArraySize = RHS.CurArraySize;
+
+ // Copy over the contents from the other set
+ memcpy(CurArray, RHS.CurArray, sizeof(void*)*CurArraySize);
+
+ NumElements = RHS.NumElements;
+ NumTombstones = RHS.NumTombstones;
+}
+
+void SmallPtrSetImplBase::MoveFrom(unsigned SmallSize,
+ SmallPtrSetImplBase &&RHS) {
+ assert(&RHS != this && "Self-move should be handled by the caller.");
+
+ if (!isSmall())
+ free(CurArray);
+
+ if (RHS.isSmall()) {
+ // Copy a small RHS rather than moving.
+ CurArray = SmallArray;
+ memcpy(CurArray, RHS.CurArray, sizeof(void*)*RHS.CurArraySize);
+ } else {
+ CurArray = RHS.CurArray;
+ RHS.CurArray = RHS.SmallArray;
+ }
+
+ // Copy the rest of the trivial members.
+ CurArraySize = RHS.CurArraySize;
+ NumElements = RHS.NumElements;
+ NumTombstones = RHS.NumTombstones;
+
+ // Make the RHS small and empty.
+ RHS.CurArraySize = SmallSize;
+ assert(RHS.CurArray == RHS.SmallArray);
+ RHS.NumElements = 0;
+ RHS.NumTombstones = 0;
+}
+
+void SmallPtrSetImplBase::swap(SmallPtrSetImplBase &RHS) {
+ if (this == &RHS) return;
+
+ // We can only avoid copying elements if neither set is small.
+ if (!this->isSmall() && !RHS.isSmall()) {
+ std::swap(this->CurArray, RHS.CurArray);
+ std::swap(this->CurArraySize, RHS.CurArraySize);
+ std::swap(this->NumElements, RHS.NumElements);
+ std::swap(this->NumTombstones, RHS.NumTombstones);
+ return;
+ }
+
+ // FIXME: From here on we assume that both sets have the same small size.
+
+ // If only RHS is small, copy the small elements into LHS and move the pointer
+ // from LHS to RHS.
+ if (!this->isSmall() && RHS.isSmall()) {
+ std::copy(RHS.SmallArray, RHS.SmallArray+RHS.CurArraySize,
+ this->SmallArray);
+ std::swap(this->NumElements, RHS.NumElements);
+ std::swap(this->CurArraySize, RHS.CurArraySize);
+ RHS.CurArray = this->CurArray;
+ RHS.NumTombstones = this->NumTombstones;
+ this->CurArray = this->SmallArray;
+ this->NumTombstones = 0;
+ return;
+ }
+
+ // If only LHS is small, copy the small elements into RHS and move the pointer
+ // from RHS to LHS.
+ if (this->isSmall() && !RHS.isSmall()) {
+ std::copy(this->SmallArray, this->SmallArray+this->CurArraySize,
+ RHS.SmallArray);
+ std::swap(RHS.NumElements, this->NumElements);
+ std::swap(RHS.CurArraySize, this->CurArraySize);
+ this->CurArray = RHS.CurArray;
+ this->NumTombstones = RHS.NumTombstones;
+ RHS.CurArray = RHS.SmallArray;
+ RHS.NumTombstones = 0;
+ return;
+ }
+
+ // Both a small, just swap the small elements.
+ assert(this->isSmall() && RHS.isSmall());
+ assert(this->CurArraySize == RHS.CurArraySize);
+ std::swap_ranges(this->SmallArray, this->SmallArray+this->CurArraySize,
+ RHS.SmallArray);
+ std::swap(this->NumElements, RHS.NumElements);
+}
+
+SmallPtrSetImplBase::~SmallPtrSetImplBase() {
+ if (!isSmall())
+ free(CurArray);