LLVM API Documentation
00001 //==-- llvm/ADT/ilist.h - Intrusive Linked List Template ---------*- C++ -*-==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines classes to implement an intrusive doubly linked list class 00011 // (i.e. each node of the list must contain a next and previous field for the 00012 // list. 00013 // 00014 // The ilist_traits trait class is used to gain access to the next and previous 00015 // fields of the node type that the list is instantiated with. If it is not 00016 // specialized, the list defaults to using the getPrev(), getNext() method calls 00017 // to get the next and previous pointers. 00018 // 00019 // The ilist class itself, should be a plug in replacement for list, assuming 00020 // that the nodes contain next/prev pointers. This list replacement does not 00021 // provide a constant time size() method, so be careful to use empty() when you 00022 // really want to know if it's empty. 00023 // 00024 // The ilist class is implemented by allocating a 'tail' node when the list is 00025 // created (using ilist_traits<>::createSentinel()). This tail node is 00026 // absolutely required because the user must be able to compute end()-1. Because 00027 // of this, users of the direct next/prev links will see an extra link on the 00028 // end of the list, which should be ignored. 00029 // 00030 // Requirements for a user of this list: 00031 // 00032 // 1. The user must provide {g|s}et{Next|Prev} methods, or specialize 00033 // ilist_traits to provide an alternate way of getting and setting next and 00034 // prev links. 00035 // 00036 //===----------------------------------------------------------------------===// 00037 00038 #ifndef LLVM_ADT_ILIST_H 00039 #define LLVM_ADT_ILIST_H 00040 00041 #include "llvm/ADT/iterator.h" 00042 #include <cassert> 00043 #include <cstdlib> 00044 00045 namespace llvm { 00046 00047 template<typename NodeTy, typename Traits> class iplist; 00048 template<typename NodeTy> class ilist_iterator; 00049 00050 /// ilist_nextprev_traits - A fragment for template traits for intrusive list 00051 /// that provides default next/prev implementations for common operations. 00052 /// 00053 template<typename NodeTy> 00054 struct ilist_nextprev_traits { 00055 static NodeTy *getPrev(NodeTy *N) { return N->getPrev(); } 00056 static NodeTy *getNext(NodeTy *N) { return N->getNext(); } 00057 static const NodeTy *getPrev(const NodeTy *N) { return N->getPrev(); } 00058 static const NodeTy *getNext(const NodeTy *N) { return N->getNext(); } 00059 00060 static void setPrev(NodeTy *N, NodeTy *Prev) { N->setPrev(Prev); } 00061 static void setNext(NodeTy *N, NodeTy *Next) { N->setNext(Next); } 00062 }; 00063 00064 /// ilist_sentinel_traits - A fragment for template traits for intrusive list 00065 /// that provides default sentinel implementations for common operations. 00066 /// 00067 template<typename NodeTy> 00068 struct ilist_sentinel_traits { 00069 static NodeTy *createSentinel() { return new NodeTy(); } 00070 static void destroySentinel(NodeTy *N) { delete N; } 00071 }; 00072 00073 /// ilist_default_traits - Default template traits for intrusive list. 00074 /// By inheriting from this, you can easily use default implementations 00075 /// for all common operations. 00076 /// 00077 template<typename NodeTy> 00078 struct ilist_default_traits : ilist_nextprev_traits<NodeTy>, 00079 ilist_sentinel_traits<NodeTy> { 00080 static NodeTy *createNode(const NodeTy &V) { return new NodeTy(V); } 00081 static void deleteNode(NodeTy *V) { delete V; } 00082 00083 void addNodeToList(NodeTy *) {} 00084 void removeNodeFromList(NodeTy *) {} 00085 void transferNodesFromList(ilist_default_traits & /*SrcTraits*/, 00086 ilist_iterator<NodeTy> /*first*/, 00087 ilist_iterator<NodeTy> /*last*/) {} 00088 }; 00089 00090 // Template traits for intrusive list. By specializing this template class, you 00091 // can change what next/prev fields are used to store the links... 00092 template<typename NodeTy> 00093 struct ilist_traits : ilist_default_traits<NodeTy> {}; 00094 00095 // Const traits are the same as nonconst traits... 00096 template<typename Ty> 00097 struct ilist_traits<const Ty> : public ilist_traits<Ty> {}; 00098 00099 //===----------------------------------------------------------------------===// 00100 // ilist_iterator<Node> - Iterator for intrusive list. 00101 // 00102 template<typename NodeTy> 00103 class ilist_iterator 00104 : public bidirectional_iterator<NodeTy, ptrdiff_t> { 00105 00106 public: 00107 typedef ilist_traits<NodeTy> Traits; 00108 typedef bidirectional_iterator<NodeTy, ptrdiff_t> super; 00109 00110 typedef size_t size_type; 00111 typedef typename super::pointer pointer; 00112 typedef typename super::reference reference; 00113 private: 00114 pointer NodePtr; 00115 00116 // operator[] is not defined. Compile error instead of having a runtime bug. 00117 void operator[](unsigned) {} 00118 void operator[](unsigned) const {} 00119 public: 00120 00121 ilist_iterator(pointer NP) : NodePtr(NP) {} 00122 ilist_iterator(reference NR) : NodePtr(&NR) {} 00123 ilist_iterator() : NodePtr(0) {} 00124 00125 // This is templated so that we can allow constructing a const iterator from 00126 // a nonconst iterator... 00127 template<class node_ty> 00128 ilist_iterator(const ilist_iterator<node_ty> &RHS) 00129 : NodePtr(RHS.getNodePtrUnchecked()) {} 00130 00131 // This is templated so that we can allow assigning to a const iterator from 00132 // a nonconst iterator... 00133 template<class node_ty> 00134 const ilist_iterator &operator=(const ilist_iterator<node_ty> &RHS) { 00135 NodePtr = RHS.getNodePtrUnchecked(); 00136 return *this; 00137 } 00138 00139 // Accessors... 00140 operator pointer() const { 00141 assert(Traits::getNext(NodePtr) != 0 && "Dereferencing end()!"); 00142 return NodePtr; 00143 } 00144 00145 reference operator*() const { 00146 assert(Traits::getNext(NodePtr) != 0 && "Dereferencing end()!"); 00147 return *NodePtr; 00148 } 00149 pointer operator->() const { return &operator*(); } 00150 00151 // Comparison operators 00152 bool operator==(const ilist_iterator &RHS) const { 00153 return NodePtr == RHS.NodePtr; 00154 } 00155 bool operator!=(const ilist_iterator &RHS) const { 00156 return NodePtr != RHS.NodePtr; 00157 } 00158 00159 // Increment and decrement operators... 00160 ilist_iterator &operator--() { // predecrement - Back up 00161 NodePtr = Traits::getPrev(NodePtr); 00162 assert(Traits::getNext(NodePtr) && "--'d off the beginning of an ilist!"); 00163 return *this; 00164 } 00165 ilist_iterator &operator++() { // preincrement - Advance 00166 NodePtr = Traits::getNext(NodePtr); 00167 assert(NodePtr && "++'d off the end of an ilist!"); 00168 return *this; 00169 } 00170 ilist_iterator operator--(int) { // postdecrement operators... 00171 ilist_iterator tmp = *this; 00172 --*this; 00173 return tmp; 00174 } 00175 ilist_iterator operator++(int) { // postincrement operators... 00176 ilist_iterator tmp = *this; 00177 ++*this; 00178 return tmp; 00179 } 00180 00181 // Internal interface, do not use... 00182 pointer getNodePtrUnchecked() const { return NodePtr; } 00183 }; 00184 00185 // do not implement. this is to catch errors when people try to use 00186 // them as random access iterators 00187 template<typename T> 00188 void operator-(int, ilist_iterator<T>); 00189 template<typename T> 00190 void operator-(ilist_iterator<T>,int); 00191 00192 template<typename T> 00193 void operator+(int, ilist_iterator<T>); 00194 template<typename T> 00195 void operator+(ilist_iterator<T>,int); 00196 00197 // operator!=/operator== - Allow mixed comparisons without dereferencing 00198 // the iterator, which could very likely be pointing to end(). 00199 template<typename T> 00200 bool operator!=(const T* LHS, const ilist_iterator<const T> &RHS) { 00201 return LHS != RHS.getNodePtrUnchecked(); 00202 } 00203 template<typename T> 00204 bool operator==(const T* LHS, const ilist_iterator<const T> &RHS) { 00205 return LHS == RHS.getNodePtrUnchecked(); 00206 } 00207 template<typename T> 00208 bool operator!=(T* LHS, const ilist_iterator<T> &RHS) { 00209 return LHS != RHS.getNodePtrUnchecked(); 00210 } 00211 template<typename T> 00212 bool operator==(T* LHS, const ilist_iterator<T> &RHS) { 00213 return LHS == RHS.getNodePtrUnchecked(); 00214 } 00215 00216 00217 // Allow ilist_iterators to convert into pointers to a node automatically when 00218 // used by the dyn_cast, cast, isa mechanisms... 00219 00220 template<typename From> struct simplify_type; 00221 00222 template<typename NodeTy> struct simplify_type<ilist_iterator<NodeTy> > { 00223 typedef NodeTy* SimpleType; 00224 00225 static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) { 00226 return &*Node; 00227 } 00228 }; 00229 template<typename NodeTy> struct simplify_type<const ilist_iterator<NodeTy> > { 00230 typedef NodeTy* SimpleType; 00231 00232 static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) { 00233 return &*Node; 00234 } 00235 }; 00236 00237 00238 //===----------------------------------------------------------------------===// 00239 // 00240 /// iplist - The subset of list functionality that can safely be used on nodes 00241 /// of polymorphic types, i.e. a heterogenous list with a common base class that 00242 /// holds the next/prev pointers. The only state of the list itself is a single 00243 /// pointer to the head of the list. 00244 /// 00245 /// This list can be in one of three interesting states: 00246 /// 1. The list may be completely unconstructed. In this case, the head 00247 /// pointer is null. When in this form, any query for an iterator (e.g. 00248 /// begin() or end()) causes the list to transparently change to state #2. 00249 /// 2. The list may be empty, but contain a sentinal for the end iterator. This 00250 /// sentinal is created by the Traits::createSentinel method and is a link 00251 /// in the list. When the list is empty, the pointer in the iplist points 00252 /// to the sentinal. Once the sentinal is constructed, it 00253 /// is not destroyed until the list is. 00254 /// 3. The list may contain actual objects in it, which are stored as a doubly 00255 /// linked list of nodes. One invariant of the list is that the predecessor 00256 /// of the first node in the list always points to the last node in the list, 00257 /// and the successor pointer for the sentinal (which always stays at the 00258 /// end of the list) is always null. 00259 /// 00260 template<typename NodeTy, typename Traits=ilist_traits<NodeTy> > 00261 class iplist : public Traits { 00262 mutable NodeTy *Head; 00263 00264 // Use the prev node pointer of 'head' as the tail pointer. This is really a 00265 // circularly linked list where we snip the 'next' link from the sentinel node 00266 // back to the first node in the list (to preserve assertions about going off 00267 // the end of the list). 00268 NodeTy *getTail() { return getPrev(Head); } 00269 const NodeTy *getTail() const { return getPrev(Head); } 00270 void setTail(NodeTy *N) const { setPrev(Head, N); } 00271 00272 /// CreateLazySentinal - This method verifies whether the sentinal for the 00273 /// list has been created and lazily makes it if not. 00274 void CreateLazySentinal() const { 00275 if (Head != 0) return; 00276 Head = Traits::createSentinel(); 00277 setNext(Head, 0); 00278 setTail(Head); 00279 } 00280 00281 static bool op_less(NodeTy &L, NodeTy &R) { return L < R; } 00282 static bool op_equal(NodeTy &L, NodeTy &R) { return L == R; } 00283 00284 // No fundamental reason why iplist can't by copyable, but the default 00285 // copy/copy-assign won't do. 00286 iplist(const iplist &); // do not implement 00287 void operator=(const iplist &); // do not implement 00288 00289 public: 00290 typedef NodeTy *pointer; 00291 typedef const NodeTy *const_pointer; 00292 typedef NodeTy &reference; 00293 typedef const NodeTy &const_reference; 00294 typedef NodeTy value_type; 00295 typedef ilist_iterator<NodeTy> iterator; 00296 typedef ilist_iterator<const NodeTy> const_iterator; 00297 typedef size_t size_type; 00298 typedef ptrdiff_t difference_type; 00299 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00300 typedef std::reverse_iterator<iterator> reverse_iterator; 00301 00302 iplist() : Head(0) {} 00303 ~iplist() { 00304 if (!Head) return; 00305 clear(); 00306 Traits::destroySentinel(getTail()); 00307 } 00308 00309 // Iterator creation methods. 00310 iterator begin() { 00311 CreateLazySentinal(); 00312 return iterator(Head); 00313 } 00314 const_iterator begin() const { 00315 CreateLazySentinal(); 00316 return const_iterator(Head); 00317 } 00318 iterator end() { 00319 CreateLazySentinal(); 00320 return iterator(getTail()); 00321 } 00322 const_iterator end() const { 00323 CreateLazySentinal(); 00324 return const_iterator(getTail()); 00325 } 00326 00327 // reverse iterator creation methods. 00328 reverse_iterator rbegin() { return reverse_iterator(end()); } 00329 const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } 00330 reverse_iterator rend() { return reverse_iterator(begin()); } 00331 const_reverse_iterator rend() const { return const_reverse_iterator(begin());} 00332 00333 00334 // Miscellaneous inspection routines. 00335 size_type max_size() const { return size_type(-1); } 00336 bool empty() const { return Head == 0 || Head == getTail(); } 00337 00338 // Front and back accessor functions... 00339 reference front() { 00340 assert(!empty() && "Called front() on empty list!"); 00341 return *Head; 00342 } 00343 const_reference front() const { 00344 assert(!empty() && "Called front() on empty list!"); 00345 return *Head; 00346 } 00347 reference back() { 00348 assert(!empty() && "Called back() on empty list!"); 00349 return *getPrev(getTail()); 00350 } 00351 const_reference back() const { 00352 assert(!empty() && "Called back() on empty list!"); 00353 return *getPrev(getTail()); 00354 } 00355 00356 void swap(iplist &RHS) { 00357 abort(); // Swap does not use list traits callback correctly yet! 00358 std::swap(Head, RHS.Head); 00359 } 00360 00361 iterator insert(iterator where, NodeTy *New) { 00362 NodeTy *CurNode = where.getNodePtrUnchecked(), *PrevNode = getPrev(CurNode); 00363 setNext(New, CurNode); 00364 setPrev(New, PrevNode); 00365 00366 if (CurNode != Head) // Is PrevNode off the beginning of the list? 00367 setNext(PrevNode, New); 00368 else 00369 Head = New; 00370 setPrev(CurNode, New); 00371 00372 addNodeToList(New); // Notify traits that we added a node... 00373 return New; 00374 } 00375 00376 NodeTy *remove(iterator &IT) { 00377 assert(IT != end() && "Cannot remove end of list!"); 00378 NodeTy *Node = &*IT; 00379 NodeTy *NextNode = getNext(Node); 00380 NodeTy *PrevNode = getPrev(Node); 00381 00382 if (Node != Head) // Is PrevNode off the beginning of the list? 00383 setNext(PrevNode, NextNode); 00384 else 00385 Head = NextNode; 00386 setPrev(NextNode, PrevNode); 00387 IT = NextNode; 00388 removeNodeFromList(Node); // Notify traits that we removed a node... 00389 00390 // Set the next/prev pointers of the current node to null. This isn't 00391 // strictly required, but this catches errors where a node is removed from 00392 // an ilist (and potentially deleted) with iterators still pointing at it. 00393 // When those iterators are incremented or decremented, they will assert on 00394 // the null next/prev pointer instead of "usually working". 00395 setNext(Node, 0); 00396 setPrev(Node, 0); 00397 return Node; 00398 } 00399 00400 NodeTy *remove(const iterator &IT) { 00401 iterator MutIt = IT; 00402 return remove(MutIt); 00403 } 00404 00405 // erase - remove a node from the controlled sequence... and delete it. 00406 iterator erase(iterator where) { 00407 deleteNode(remove(where)); 00408 return where; 00409 } 00410 00411 00412 private: 00413 // transfer - The heart of the splice function. Move linked list nodes from 00414 // [first, last) into position. 00415 // 00416 void transfer(iterator position, iplist &L2, iterator first, iterator last) { 00417 assert(first != last && "Should be checked by callers"); 00418 00419 if (position != last) { 00420 // Note: we have to be careful about the case when we move the first node 00421 // in the list. This node is the list sentinel node and we can't move it. 00422 NodeTy *ThisSentinel = getTail(); 00423 setTail(0); 00424 NodeTy *L2Sentinel = L2.getTail(); 00425 L2.setTail(0); 00426 00427 // Remove [first, last) from its old position. 00428 NodeTy *First = &*first, *Prev = getPrev(First); 00429 NodeTy *Next = last.getNodePtrUnchecked(), *Last = getPrev(Next); 00430 if (Prev) 00431 setNext(Prev, Next); 00432 else 00433 L2.Head = Next; 00434 setPrev(Next, Prev); 00435 00436 // Splice [first, last) into its new position. 00437 NodeTy *PosNext = position.getNodePtrUnchecked(); 00438 NodeTy *PosPrev = getPrev(PosNext); 00439 00440 // Fix head of list... 00441 if (PosPrev) 00442 setNext(PosPrev, First); 00443 else 00444 Head = First; 00445 setPrev(First, PosPrev); 00446 00447 // Fix end of list... 00448 setNext(Last, PosNext); 00449 setPrev(PosNext, Last); 00450 00451 transferNodesFromList(L2, First, PosNext); 00452 00453 // Now that everything is set, restore the pointers to the list sentinals. 00454 L2.setTail(L2Sentinel); 00455 setTail(ThisSentinel); 00456 } 00457 } 00458 00459 public: 00460 00461 //===----------------------------------------------------------------------=== 00462 // Functionality derived from other functions defined above... 00463 // 00464 00465 size_type size() const { 00466 if (Head == 0) return 0; // Don't require construction of sentinal if empty. 00467 #if __GNUC__ == 2 00468 // GCC 2.95 has a broken std::distance 00469 size_type Result = 0; 00470 std::distance(begin(), end(), Result); 00471 return Result; 00472 #else 00473 return std::distance(begin(), end()); 00474 #endif 00475 } 00476 00477 iterator erase(iterator first, iterator last) { 00478 while (first != last) 00479 first = erase(first); 00480 return last; 00481 } 00482 00483 void clear() { if (Head) erase(begin(), end()); } 00484 00485 // Front and back inserters... 00486 void push_front(NodeTy *val) { insert(begin(), val); } 00487 void push_back(NodeTy *val) { insert(end(), val); } 00488 void pop_front() { 00489 assert(!empty() && "pop_front() on empty list!"); 00490 erase(begin()); 00491 } 00492 void pop_back() { 00493 assert(!empty() && "pop_back() on empty list!"); 00494 iterator t = end(); erase(--t); 00495 } 00496 00497 // Special forms of insert... 00498 template<class InIt> void insert(iterator where, InIt first, InIt last) { 00499 for (; first != last; ++first) insert(where, *first); 00500 } 00501 00502 // Splice members - defined in terms of transfer... 00503 void splice(iterator where, iplist &L2) { 00504 if (!L2.empty()) 00505 transfer(where, L2, L2.begin(), L2.end()); 00506 } 00507 void splice(iterator where, iplist &L2, iterator first) { 00508 iterator last = first; ++last; 00509 if (where == first || where == last) return; // No change 00510 transfer(where, L2, first, last); 00511 } 00512 void splice(iterator where, iplist &L2, iterator first, iterator last) { 00513 if (first != last) transfer(where, L2, first, last); 00514 } 00515 00516 00517 00518 //===----------------------------------------------------------------------=== 00519 // High-Level Functionality that shouldn't really be here, but is part of list 00520 // 00521 00522 // These two functions are actually called remove/remove_if in list<>, but 00523 // they actually do the job of erase, rename them accordingly. 00524 // 00525 void erase(const NodeTy &val) { 00526 for (iterator I = begin(), E = end(); I != E; ) { 00527 iterator next = I; ++next; 00528 if (*I == val) erase(I); 00529 I = next; 00530 } 00531 } 00532 template<class Pr1> void erase_if(Pr1 pred) { 00533 for (iterator I = begin(), E = end(); I != E; ) { 00534 iterator next = I; ++next; 00535 if (pred(*I)) erase(I); 00536 I = next; 00537 } 00538 } 00539 00540 template<class Pr2> void unique(Pr2 pred) { 00541 if (empty()) return; 00542 for (iterator I = begin(), E = end(), Next = begin(); ++Next != E;) { 00543 if (pred(*I)) 00544 erase(Next); 00545 else 00546 I = Next; 00547 Next = I; 00548 } 00549 } 00550 void unique() { unique(op_equal); } 00551 00552 template<class Pr3> void merge(iplist &right, Pr3 pred) { 00553 iterator first1 = begin(), last1 = end(); 00554 iterator first2 = right.begin(), last2 = right.end(); 00555 while (first1 != last1 && first2 != last2) 00556 if (pred(*first2, *first1)) { 00557 iterator next = first2; 00558 transfer(first1, right, first2, ++next); 00559 first2 = next; 00560 } else { 00561 ++first1; 00562 } 00563 if (first2 != last2) transfer(last1, right, first2, last2); 00564 } 00565 void merge(iplist &right) { return merge(right, op_less); } 00566 00567 template<class Pr3> void sort(Pr3 pred); 00568 void sort() { sort(op_less); } 00569 void reverse(); 00570 }; 00571 00572 00573 template<typename NodeTy> 00574 struct ilist : public iplist<NodeTy> { 00575 typedef typename iplist<NodeTy>::size_type size_type; 00576 typedef typename iplist<NodeTy>::iterator iterator; 00577 00578 ilist() {} 00579 ilist(const ilist &right) { 00580 insert(this->begin(), right.begin(), right.end()); 00581 } 00582 explicit ilist(size_type count) { 00583 insert(this->begin(), count, NodeTy()); 00584 } 00585 ilist(size_type count, const NodeTy &val) { 00586 insert(this->begin(), count, val); 00587 } 00588 template<class InIt> ilist(InIt first, InIt last) { 00589 insert(this->begin(), first, last); 00590 } 00591 00592 00593 // Forwarding functions: A workaround for GCC 2.95 which does not correctly 00594 // support 'using' declarations to bring a hidden member into scope. 00595 // 00596 iterator insert(iterator a, NodeTy *b){ return iplist<NodeTy>::insert(a, b); } 00597 void push_front(NodeTy *a) { iplist<NodeTy>::push_front(a); } 00598 void push_back(NodeTy *a) { iplist<NodeTy>::push_back(a); } 00599 00600 00601 // Main implementation here - Insert for a node passed by value... 00602 iterator insert(iterator where, const NodeTy &val) { 00603 return insert(where, createNode(val)); 00604 } 00605 00606 00607 // Front and back inserters... 00608 void push_front(const NodeTy &val) { insert(this->begin(), val); } 00609 void push_back(const NodeTy &val) { insert(this->end(), val); } 00610 00611 // Special forms of insert... 00612 template<class InIt> void insert(iterator where, InIt first, InIt last) { 00613 for (; first != last; ++first) insert(where, *first); 00614 } 00615 void insert(iterator where, size_type count, const NodeTy &val) { 00616 for (; count != 0; --count) insert(where, val); 00617 } 00618 00619 // Assign special forms... 00620 void assign(size_type count, const NodeTy &val) { 00621 iterator I = this->begin(); 00622 for (; I != this->end() && count != 0; ++I, --count) 00623 *I = val; 00624 if (count != 0) 00625 insert(this->end(), val, val); 00626 else 00627 erase(I, this->end()); 00628 } 00629 template<class InIt> void assign(InIt first1, InIt last1) { 00630 iterator first2 = this->begin(), last2 = this->end(); 00631 for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) 00632 *first1 = *first2; 00633 if (first2 == last2) 00634 erase(first1, last1); 00635 else 00636 insert(last1, first2, last2); 00637 } 00638 00639 00640 // Resize members... 00641 void resize(size_type newsize, NodeTy val) { 00642 iterator i = this->begin(); 00643 size_type len = 0; 00644 for ( ; i != this->end() && len < newsize; ++i, ++len) /* empty*/ ; 00645 00646 if (len == newsize) 00647 erase(i, this->end()); 00648 else // i == end() 00649 insert(this->end(), newsize - len, val); 00650 } 00651 void resize(size_type newsize) { resize(newsize, NodeTy()); } 00652 }; 00653 00654 } // End llvm namespace 00655 00656 namespace std { 00657 // Ensure that swap uses the fast list swap... 00658 template<class Ty> 00659 void swap(llvm::iplist<Ty> &Left, llvm::iplist<Ty> &Right) { 00660 Left.swap(Right); 00661 } 00662 } // End 'std' extensions... 00663 00664 #endif // LLVM_ADT_ILIST_H