<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><div style="direction: inherit;">Please attach the reproducer mentioned in the log message:</div><div style="direction: inherit;"><br></div><div style="direction: inherit;"><pre style="word-wrap: break-word;"><font face="UICTFontTextStyleBody"><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);">clang-4.0: note: diagnostic msg: PLEASE submit a bug report to <a href="http://llvm.org/bugs/">http://llvm.org/bugs/</a> and include the crash backtrace, preprocessed source, and associated run script.</span></font></pre><pre style="word-wrap: break-word;"><font face="UICTFontTextStyleBody"><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);">clang-4.0: note: diagnostic msg:</span></font></pre><pre style="word-wrap: break-word;"><font face="UICTFontTextStyleBody"><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);">********************</span></font></pre><pre style="word-wrap: break-word;"><font face="UICTFontTextStyleBody"><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);">PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:</span></font></pre><pre style="word-wrap: break-word;"><font face="UICTFontTextStyleBody"><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);">Preprocessed source(s) and associated run script(s) are located at:</span></font></pre><pre style="word-wrap: break-word;"><font face="UICTFontTextStyleBody"><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);">clang-4.0: note: diagnostic msg: /tmp/gtest-all-78e9e5.cpp</span></font></pre><pre style="word-wrap: break-word;"><span style="white-space: normal; background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleBody;">clang-4.0: note: diagnostic msg: /tmp/gtest-all-78e9e5.sh</span></pre><pre style="word-wrap: break-word;"><span style="white-space: normal; background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleBody;">clang-4.0: note: diagnostic msg:</span></pre><pre style="word-wrap: break-word;"><span style="white-space: normal; background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleBody;"> ********************</span></pre></div><div style="direction: inherit;"><br></div>-- dpnes</div><div><br>On Aug 18, 2016, at 04:32, Diana Picus <<a href="mailto:diana.picus@linaro.org">diana.picus@linaro.org</a>> wrote:<br><br></div><blockquote type="cite"><div><span>Hi,</span><br><span></span><br><span>I had to revert this because it was breaking some of the bots. I also</span><br><span>reverted r279012 because it was in the way (and it looked like a fixup</span><br><span>for this revision anyway).</span><br><span>I've attached a log of the failure to this bug:</span><br><span><a href="https://llvm.org/bugs/show_bug.cgi?id=29035">https://llvm.org/bugs/show_bug.cgi?id=29035</a></span><br><span>Please let me know if you need anything else to debug this.</span><br><span></span><br><span>Thanks,</span><br><span>Diana</span><br><span></span><br><span></span><br><span></span><br><span>On 17 August 2016 at 23:44, Duncan P. N. Exon Smith via llvm-commits</span><br><span><<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:</span><br><blockquote type="cite"><span>Author: dexonsmith</span><br></blockquote><blockquote type="cite"><span>Date: Wed Aug 17 15:44:33 2016</span><br></blockquote><blockquote type="cite"><span>New Revision: 278974</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=278974&view=rev">http://llvm.org/viewvc/llvm-project?rev=278974&view=rev</a></span><br></blockquote><blockquote type="cite"><span>Log:</span><br></blockquote><blockquote type="cite"><span>ADT: Remove UB in ilist (and use a circular linked list)</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>This removes the undefined behaviour (UB) in ilist/ilist_node/etc.,</span><br></blockquote><blockquote type="cite"><span>mainly by removing (gutting) the ilist_sentinel_traits customization</span><br></blockquote><blockquote type="cite"><span>point and canonicalizing on a single, efficient memory layout. This</span><br></blockquote><blockquote type="cite"><span>fixes PR26753.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>The new ilist is a doubly-linked circular list.</span><br></blockquote><blockquote type="cite"><span>- ilist_node_base has two ilist_node_base*: Next and Prev. Size-of: two</span><br></blockquote><blockquote type="cite"><span> pointers.</span><br></blockquote><blockquote type="cite"><span>- ilist_node<T> (size-of: two pointers) is a type-safe wrapper around</span><br></blockquote><blockquote type="cite"><span> ilist_node_base.</span><br></blockquote><blockquote type="cite"><span>- ilist_iterator<T> (size-of: two pointers) operates on an</span><br></blockquote><blockquote type="cite"><span> ilist_node<T>*, and downcasts to T* on dereference.</span><br></blockquote><blockquote type="cite"><span>- ilist_sentinel<T> (size-of: two pointers) is a wrapper around</span><br></blockquote><blockquote type="cite"><span> ilist_node<T> that has some extra API for list management.</span><br></blockquote><blockquote type="cite"><span>- ilist<T> (size-of: two pointers) has an ilist_sentinel<T>, whose</span><br></blockquote><blockquote type="cite"><span> address is returned for end().</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>The new memory layout matches ilist_half_embedded_sentinel_traits<T></span><br></blockquote><blockquote type="cite"><span>exactly. The Head pointer that previously lived in ilist<T> is</span><br></blockquote><blockquote type="cite"><span>effectively glued to the ilist_half_node<T> that lived in</span><br></blockquote><blockquote type="cite"><span>ilist_half_embedded_sentinel_traits<T>, becoming the Next and Prev in</span><br></blockquote><blockquote type="cite"><span>the ilist_sentinel_node<T>, respectively. sizeof(ilist<T>) is now the</span><br></blockquote><blockquote type="cite"><span>size of two pointers, and there is never any additional storage for a</span><br></blockquote><blockquote type="cite"><span>sentinel.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>This is a much simpler design for a doubly-linked list, removing most of</span><br></blockquote><blockquote type="cite"><span>the corner cases of list manipulation (add, remove, etc.). In follow-up</span><br></blockquote><blockquote type="cite"><span>commits, I intend to move as many algorithms as possible into a</span><br></blockquote><blockquote type="cite"><span>non-templated base class (ilist_base) to reduce code size.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Moreover, this fixes the UB in ilist_iterator/getNext/getPrev</span><br></blockquote><blockquote type="cite"><span>operations. Previously, ilist_iterator<T> operated on a T*, even when</span><br></blockquote><blockquote type="cite"><span>the sentinel was not of type T (i.e., ilist_embedded_sentinel_traits and</span><br></blockquote><blockquote type="cite"><span>ilist_half_embedded_sentinel_traits). This added UB to all operations</span><br></blockquote><blockquote type="cite"><span>involving end(). Now, ilist_iterator<T> operates on an ilist_node<T>*,</span><br></blockquote><blockquote type="cite"><span>and only downcasts when the full type is guaranteed to be T*.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>What did we lose? There used to be a crash (in some configurations) on</span><br></blockquote><blockquote type="cite"><span>++end(). Curiously (via UB), ++end() would return begin() for users of</span><br></blockquote><blockquote type="cite"><span>ilist_half_embedded_sentinel_traits<T>, but otherwise ++end() would</span><br></blockquote><blockquote type="cite"><span>cause a nice dependable nullptr dereference, crashing instead of a</span><br></blockquote><blockquote type="cite"><span>possible infinite loop. Options:</span><br></blockquote><blockquote type="cite"><span> 1. Lose that behaviour.</span><br></blockquote><blockquote type="cite"><span> 2. Keep it, by stealing a bit from Prev in asserts builds.</span><br></blockquote><blockquote type="cite"><span> 3. Crash on dereference instead, using the same technique.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Hans convinced me (because of the number of problems this and r278532</span><br></blockquote><blockquote type="cite"><span>exposed on Windows) that we really need some assertion here, at least in</span><br></blockquote><blockquote type="cite"><span>the short term. I've opted for #3 since I think it catches more bugs.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>I added only a couple of unit tests to root out specific bugs I hit</span><br></blockquote><blockquote type="cite"><span>during bring-up, but otherwise this is tested implicitly via the</span><br></blockquote><blockquote type="cite"><span>extensive usage throughout LLVM.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Planned follow-ups:</span><br></blockquote><blockquote type="cite"><span>- Remove ilist_*sentinel_traits<T>. Here I've just gutted them to</span><br></blockquote><blockquote type="cite"><span> prevent build failures in sub-projects. Once I stop referring to them</span><br></blockquote><blockquote type="cite"><span> in sub-projects, I'll come back and delete them.</span><br></blockquote><blockquote type="cite"><span>- Add ilist_base and move algorithms there.</span><br></blockquote><blockquote type="cite"><span>- Check and fix move construction and assignment.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Eventually, there are other interesting directions:</span><br></blockquote><blockquote type="cite"><span>- Rewrite reverse iterators, so that rbegin().getNodePtr()==&*rbegin().</span><br></blockquote><blockquote type="cite"><span> This allows much simpler logic when erasing elements during a reverse</span><br></blockquote><blockquote type="cite"><span> traversal.</span><br></blockquote><blockquote type="cite"><span>- Remove ilist_traits::createNode, by deleting the remaining API that</span><br></blockquote><blockquote type="cite"><span> creates nodes. Intrusive lists shouldn't be creating nodes</span><br></blockquote><blockquote type="cite"><span> themselves.</span><br></blockquote><blockquote type="cite"><span>- Remove ilist_traits::deleteNode, by (1) asserting that lists are empty</span><br></blockquote><blockquote type="cite"><span> on destruction and (2) changing API that calls it to take a Deleter</span><br></blockquote><blockquote type="cite"><span> functor (intrusive lists shouldn't be in the memory management</span><br></blockquote><blockquote type="cite"><span> business).</span><br></blockquote><blockquote type="cite"><span>- Reconfigure the remaining callback traits (addNodeToList, etc.) to be</span><br></blockquote><blockquote type="cite"><span> higher-level, pulling out a simple_ilist<T> that is much easier to</span><br></blockquote><blockquote type="cite"><span> read and understand.</span><br></blockquote><blockquote type="cite"><span>- Allow tags (e.g., ilist_node<T,tag1> and ilist_node<T,tag2>) so that T</span><br></blockquote><blockquote type="cite"><span> can be a member of multiple intrusive lists.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Modified:</span><br></blockquote><blockquote type="cite"><span> llvm/trunk/include/llvm/ADT/ilist.h</span><br></blockquote><blockquote type="cite"><span> llvm/trunk/include/llvm/ADT/ilist_node.h</span><br></blockquote><blockquote type="cite"><span> llvm/trunk/unittests/ADT/ilistTest.cpp</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Modified: llvm/trunk/include/llvm/ADT/ilist.h</span><br></blockquote><blockquote type="cite"><span>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ilist.h?rev=278974&r1=278973&r2=278974&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ilist.h?rev=278974&r1=278973&r2=278974&view=diff</a></span><br></blockquote><blockquote type="cite"><span>==============================================================================</span><br></blockquote><blockquote type="cite"><span>--- llvm/trunk/include/llvm/ADT/ilist.h (original)</span><br></blockquote><blockquote type="cite"><span>+++ llvm/trunk/include/llvm/ADT/ilist.h Wed Aug 17 15:44:33 2016</span><br></blockquote><blockquote type="cite"><span>@@ -15,17 +15,16 @@</span><br></blockquote><blockquote type="cite"><span> // replacement does not provide a constant time size() method, so be careful to</span><br></blockquote><blockquote type="cite"><span> // use empty() when you really want to know if it's empty.</span><br></blockquote><blockquote type="cite"><span> //</span><br></blockquote><blockquote type="cite"><span>-// The ilist class is implemented by allocating a 'tail' node when the list is</span><br></blockquote><blockquote type="cite"><span>-// created (using ilist_traits<>::createSentinel()). This tail node is</span><br></blockquote><blockquote type="cite"><span>-// absolutely required because the user must be able to compute end()-1. Because</span><br></blockquote><blockquote type="cite"><span>-// of this, users of the direct next/prev links will see an extra link on the</span><br></blockquote><blockquote type="cite"><span>-// end of the list, which should be ignored.</span><br></blockquote><blockquote type="cite"><span>+// The ilist class is implemented as a circular list. The list itself contains</span><br></blockquote><blockquote type="cite"><span>+// a sentinel node, whose Next points at begin() and whose Prev points at</span><br></blockquote><blockquote type="cite"><span>+// rbegin(). The sentinel node itself serves as end() and rend().</span><br></blockquote><blockquote type="cite"><span> //</span><br></blockquote><blockquote type="cite"><span> //===----------------------------------------------------------------------===//</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> #ifndef LLVM_ADT_ILIST_H</span><br></blockquote><blockquote type="cite"><span> #define LLVM_ADT_ILIST_H</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>+#include "llvm/ADT/ilist_node.h"</span><br></blockquote><blockquote type="cite"><span> #include "llvm/Support/Compiler.h"</span><br></blockquote><blockquote type="cite"><span> #include <algorithm></span><br></blockquote><blockquote type="cite"><span> #include <cassert></span><br></blockquote><blockquote type="cite"><span>@@ -38,37 +37,42 @@ namespace llvm {</span><br></blockquote><blockquote type="cite"><span> template<typename NodeTy, typename Traits> class iplist;</span><br></blockquote><blockquote type="cite"><span> template<typename NodeTy> class ilist_iterator;</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>-/// An access class for next/prev on ilist_nodes.</span><br></blockquote><blockquote type="cite"><span>+/// An access class for ilist_node private API.</span><br></blockquote><blockquote type="cite"><span> ///</span><br></blockquote><blockquote type="cite"><span> /// This gives access to the private parts of ilist nodes. Nodes for an ilist</span><br></blockquote><blockquote type="cite"><span> /// should friend this class if they inherit privately from ilist_node.</span><br></blockquote><blockquote type="cite"><span> ///</span><br></blockquote><blockquote type="cite"><span>-/// It's strongly discouraged to *use* this class outside of ilist</span><br></blockquote><blockquote type="cite"><span>+/// It's strongly discouraged to *use* this class outside of the ilist</span><br></blockquote><blockquote type="cite"><span> /// implementation.</span><br></blockquote><blockquote type="cite"><span> struct ilist_node_access {</span><br></blockquote><blockquote type="cite"><span>- template <typename NodeTy> static NodeTy *getPrev(NodeTy *N) {</span><br></blockquote><blockquote type="cite"><span>+ template <typename T> static ilist_node<T> *getNodePtr(T *N) { return N; }</span><br></blockquote><blockquote type="cite"><span>+ template <typename T> static const ilist_node<T> *getNodePtr(const T *N) {</span><br></blockquote><blockquote type="cite"><span>+ return N;</span><br></blockquote><blockquote type="cite"><span>+ }</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ template <typename T> static ilist_node<T> *getPrev(ilist_node<T> *N) {</span><br></blockquote><blockquote type="cite"><span> return N->getPrev();</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span>- template <typename NodeTy> static NodeTy *getNext(NodeTy *N) {</span><br></blockquote><blockquote type="cite"><span>+ template <typename T> static ilist_node<T> *getNext(ilist_node<T> *N) {</span><br></blockquote><blockquote type="cite"><span> return N->getNext();</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span>- template <typename NodeTy> static const NodeTy *getPrev(const NodeTy *N) {</span><br></blockquote><blockquote type="cite"><span>+ template <typename T> static const ilist_node<T> *getPrev(const ilist_node<T> *N) {</span><br></blockquote><blockquote type="cite"><span> return N->getPrev();</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span>- template <typename NodeTy> static const NodeTy *getNext(const NodeTy *N) {</span><br></blockquote><blockquote type="cite"><span>+ template <typename T> static const ilist_node<T> *getNext(const ilist_node<T> *N) {</span><br></blockquote><blockquote type="cite"><span> return N->getNext();</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>- template <typename NodeTy> static void setPrev(NodeTy *N, NodeTy *Prev) {</span><br></blockquote><blockquote type="cite"><span>+ template <typename T> static void setPrev(ilist_node<T> *N, ilist_node<T> *Prev) {</span><br></blockquote><blockquote type="cite"><span> N->setPrev(Prev);</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span>- template <typename NodeTy> static void setNext(NodeTy *N, NodeTy *Next) {</span><br></blockquote><blockquote type="cite"><span>+ template <typename T> static void setNext(ilist_node<T> *N, ilist_node<T> *Next) {</span><br></blockquote><blockquote type="cite"><span> N->setNext(Next);</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span>- template <typename NodeTy> static void setPrev(NodeTy *N, std::nullptr_t) {</span><br></blockquote><blockquote type="cite"><span>+ template <typename T> static void setPrev(ilist_node<T> *N, std::nullptr_t) {</span><br></blockquote><blockquote type="cite"><span> N->setPrev(nullptr);</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span>- template <typename NodeTy> static void setNext(NodeTy *N, std::nullptr_t) {</span><br></blockquote><blockquote type="cite"><span>+ template <typename T> static void setNext(ilist_node<T> *N, std::nullptr_t) {</span><br></blockquote><blockquote type="cite"><span> N->setNext(nullptr);</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span> };</span><br></blockquote><blockquote type="cite"><span>@@ -93,111 +97,31 @@ template <class TraitsT, class NodeT> st</span><br></blockquote><blockquote type="cite"><span> static const bool value = sizeof(hasGetNext<TraitsT>(nullptr)) == sizeof(Yes);</span><br></blockquote><blockquote type="cite"><span> };</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>-} // end namespace ilist_detail</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>-template<typename NodeTy></span><br></blockquote><blockquote type="cite"><span>-struct ilist_traits;</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>-/// ilist_sentinel_traits - A fragment for template traits for intrusive list</span><br></blockquote><blockquote type="cite"><span>-/// that provides default sentinel implementations for common operations.</span><br></blockquote><blockquote type="cite"><span>-///</span><br></blockquote><blockquote type="cite"><span>-/// ilist_sentinel_traits implements a lazy dynamic sentinel allocation</span><br></blockquote><blockquote type="cite"><span>-/// strategy. The sentinel is stored in the prev field of ilist's Head.</span><br></blockquote><blockquote type="cite"><span>-///</span><br></blockquote><blockquote type="cite"><span>-template<typename NodeTy></span><br></blockquote><blockquote type="cite"><span>-struct ilist_sentinel_traits {</span><br></blockquote><blockquote type="cite"><span>- /// createSentinel - create the dynamic sentinel</span><br></blockquote><blockquote type="cite"><span>- static NodeTy *createSentinel() { return new NodeTy(); }</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- /// destroySentinel - deallocate the dynamic sentinel</span><br></blockquote><blockquote type="cite"><span>- static void destroySentinel(NodeTy *N) { delete N; }</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- /// provideInitialHead - when constructing an ilist, provide a starting</span><br></blockquote><blockquote type="cite"><span>- /// value for its Head</span><br></blockquote><blockquote type="cite"><span>- /// @return null node to indicate that it needs to be allocated later</span><br></blockquote><blockquote type="cite"><span>- static NodeTy *provideInitialHead() { return nullptr; }</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- /// ensureHead - make sure that Head is either already</span><br></blockquote><blockquote type="cite"><span>- /// initialized or assigned a fresh sentinel</span><br></blockquote><blockquote type="cite"><span>- /// @return the sentinel</span><br></blockquote><blockquote type="cite"><span>- static NodeTy *ensureHead(NodeTy *&Head) {</span><br></blockquote><blockquote type="cite"><span>- if (!Head) {</span><br></blockquote><blockquote type="cite"><span>- Head = ilist_traits<NodeTy>::createSentinel();</span><br></blockquote><blockquote type="cite"><span>- ilist_traits<NodeTy>::noteHead(Head, Head);</span><br></blockquote><blockquote type="cite"><span>- ilist_node_access::setNext(Head, nullptr);</span><br></blockquote><blockquote type="cite"><span>- return Head;</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>- return ilist_node_access::getPrev(Head);</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- /// noteHead - stash the sentinel into its default location</span><br></blockquote><blockquote type="cite"><span>- static void noteHead(NodeTy *NewHead, NodeTy *Sentinel) {</span><br></blockquote><blockquote type="cite"><span>- ilist_node_access::setPrev(NewHead, Sentinel);</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>-};</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>-template <typename NodeTy> class ilist_half_node;</span><br></blockquote><blockquote type="cite"><span>-template <typename NodeTy> class ilist_node;</span><br></blockquote><blockquote type="cite"><span>+/// Type trait to check for a traits class that has a createSentinel member (as</span><br></blockquote><blockquote type="cite"><span>+/// a canary for any of the ilist_sentinel_traits API).</span><br></blockquote><blockquote type="cite"><span>+template <class TraitsT> struct HasCreateSentinel {</span><br></blockquote><blockquote type="cite"><span>+ typedef char Yes[1];</span><br></blockquote><blockquote type="cite"><span>+ typedef char No[2];</span><br></blockquote><blockquote type="cite"><span>+ template <size_t N> struct SFINAE {};</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>-/// Traits with an embedded ilist_node as a sentinel.</span><br></blockquote><blockquote type="cite"><span>-template <typename NodeTy> struct ilist_embedded_sentinel_traits {</span><br></blockquote><blockquote type="cite"><span>- /// Get hold of the node that marks the end of the list.</span><br></blockquote><blockquote type="cite"><span>- ///</span><br></blockquote><blockquote type="cite"><span>- /// FIXME: This downcast is UB. See <a href="http://llvm.org/PR26753">llvm.org/PR26753</a>.</span><br></blockquote><blockquote type="cite"><span>- LLVM_NO_SANITIZE("object-size")</span><br></blockquote><blockquote type="cite"><span>- NodeTy *createSentinel() const {</span><br></blockquote><blockquote type="cite"><span>- // Since i(p)lists always publicly derive from their corresponding traits,</span><br></blockquote><blockquote type="cite"><span>- // placing a data member in this class will augment the i(p)list. But since</span><br></blockquote><blockquote type="cite"><span>- // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>,</span><br></blockquote><blockquote type="cite"><span>- // there is a legal viable downcast from it to NodeTy. We use this trick to</span><br></blockquote><blockquote type="cite"><span>- // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the</span><br></blockquote><blockquote type="cite"><span>- // sentinel. Dereferencing the sentinel is forbidden (save the</span><br></blockquote><blockquote type="cite"><span>- // ilist_node<NodeTy>), so no one will ever notice the superposition.</span><br></blockquote><blockquote type="cite"><span>- return static_cast<NodeTy *>(&Sentinel);</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>- static void destroySentinel(NodeTy *) {}</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- NodeTy *provideInitialHead() const { return createSentinel(); }</span><br></blockquote><blockquote type="cite"><span>- NodeTy *ensureHead(NodeTy *) const { return createSentinel(); }</span><br></blockquote><blockquote type="cite"><span>- static void noteHead(NodeTy *, NodeTy *) {}</span><br></blockquote><blockquote type="cite"><span>+ template <class U></span><br></blockquote><blockquote type="cite"><span>+ static Yes &</span><br></blockquote><blockquote type="cite"><span>+ hasCreateSentinel(SFINAE<sizeof(make<U>().createSentinel())> * = 0);</span><br></blockquote><blockquote type="cite"><span>+ template <class U> static No &hasCreateSentinel(...);</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>-private:</span><br></blockquote><blockquote type="cite"><span>- mutable ilist_node<NodeTy> Sentinel;</span><br></blockquote><blockquote type="cite"><span>+ static const bool value =</span><br></blockquote><blockquote type="cite"><span>+ sizeof(hasCreateSentinel<TraitsT>(nullptr)) == sizeof(Yes);</span><br></blockquote><blockquote type="cite"><span> };</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>-/// Trait with an embedded ilist_half_node as a sentinel.</span><br></blockquote><blockquote type="cite"><span>-template <typename NodeTy> struct ilist_half_embedded_sentinel_traits {</span><br></blockquote><blockquote type="cite"><span>- /// Get hold of the node that marks the end of the list.</span><br></blockquote><blockquote type="cite"><span>- ///</span><br></blockquote><blockquote type="cite"><span>- /// FIXME: This downcast is UB. See <a href="http://llvm.org/PR26753">llvm.org/PR26753</a>.</span><br></blockquote><blockquote type="cite"><span>- LLVM_NO_SANITIZE("object-size")</span><br></blockquote><blockquote type="cite"><span>- NodeTy *createSentinel() const {</span><br></blockquote><blockquote type="cite"><span>- // See comment in ilist_embedded_sentinel_traits::createSentinel().</span><br></blockquote><blockquote type="cite"><span>- return static_cast<NodeTy *>(&Sentinel);</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>- static void destroySentinel(NodeTy *) {}</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- NodeTy *provideInitialHead() const { return createSentinel(); }</span><br></blockquote><blockquote type="cite"><span>- NodeTy *ensureHead(NodeTy *) const { return createSentinel(); }</span><br></blockquote><blockquote type="cite"><span>- static void noteHead(NodeTy *, NodeTy *) {}</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>-private:</span><br></blockquote><blockquote type="cite"><span>- mutable ilist_half_node<NodeTy> Sentinel;</span><br></blockquote><blockquote type="cite"><span>-};</span><br></blockquote><blockquote type="cite"><span>+} // end namespace ilist_detail</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>-/// Traits with an embedded full node as a sentinel.</span><br></blockquote><blockquote type="cite"><span>-template <typename NodeTy> struct ilist_full_embedded_sentinel_traits {</span><br></blockquote><blockquote type="cite"><span>- /// Get hold of the node that marks the end of the list.</span><br></blockquote><blockquote type="cite"><span>- NodeTy *createSentinel() const { return &Sentinel; }</span><br></blockquote><blockquote type="cite"><span>- static void destroySentinel(NodeTy *) {}</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- NodeTy *provideInitialHead() const { return createSentinel(); }</span><br></blockquote><blockquote type="cite"><span>- NodeTy *ensureHead(NodeTy *) const { return createSentinel(); }</span><br></blockquote><blockquote type="cite"><span>- static void noteHead(NodeTy *, NodeTy *) {}</span><br></blockquote><blockquote type="cite"><span>+template <typename NodeTy> struct ilist_traits;</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>-private:</span><br></blockquote><blockquote type="cite"><span>- mutable NodeTy Sentinel;</span><br></blockquote><blockquote type="cite"><span>-};</span><br></blockquote><blockquote type="cite"><span>+// TODO: Delete uses from subprojects, then delete these.</span><br></blockquote><blockquote type="cite"><span>+template <typename NodeTy> struct ilist_sentinel_traits {};</span><br></blockquote><blockquote type="cite"><span>+template <typename NodeTy> struct ilist_embedded_sentinel_traits {};</span><br></blockquote><blockquote type="cite"><span>+template <typename NodeTy> struct ilist_half_embedded_sentinel_traits {};</span><br></blockquote><blockquote type="cite"><span>+template <typename NodeTy> struct ilist_full_embedded_sentinel_traits {};</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> /// ilist_node_traits - A fragment for template traits for intrusive list</span><br></blockquote><blockquote type="cite"><span> /// that provides default node related operations.</span><br></blockquote><blockquote type="cite"><span>@@ -219,8 +143,7 @@ struct ilist_node_traits {</span><br></blockquote><blockquote type="cite"><span> /// for all common operations.</span><br></blockquote><blockquote type="cite"><span> ///</span><br></blockquote><blockquote type="cite"><span> template <typename NodeTy></span><br></blockquote><blockquote type="cite"><span>-struct ilist_default_traits : public ilist_sentinel_traits<NodeTy>,</span><br></blockquote><blockquote type="cite"><span>- public ilist_node_traits<NodeTy> {};</span><br></blockquote><blockquote type="cite"><span>+struct ilist_default_traits : public ilist_node_traits<NodeTy> {};</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> // Template traits for intrusive list. By specializing this template class, you</span><br></blockquote><blockquote type="cite"><span> // can change what next/prev fields are used to store the links...</span><br></blockquote><blockquote type="cite"><span>@@ -263,16 +186,15 @@ public:</span><br></blockquote><blockquote type="cite"><span> typedef node_type &node_reference;</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> private:</span><br></blockquote><blockquote type="cite"><span>- pointer NodePtr;</span><br></blockquote><blockquote type="cite"><span>+ node_pointer NodePtr = nullptr;</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> public:</span><br></blockquote><blockquote type="cite"><span> /// Create from an ilist_node.</span><br></blockquote><blockquote type="cite"><span>- explicit ilist_iterator(node_reference N)</span><br></blockquote><blockquote type="cite"><span>- : NodePtr(static_cast<NodeTy *>(&N)) {}</span><br></blockquote><blockquote type="cite"><span>+ explicit ilist_iterator(node_reference N) : NodePtr(&N) {}</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> explicit ilist_iterator(pointer NP) : NodePtr(NP) {}</span><br></blockquote><blockquote type="cite"><span> explicit ilist_iterator(reference NR) : NodePtr(&NR) {}</span><br></blockquote><blockquote type="cite"><span>- ilist_iterator() : NodePtr(nullptr) {}</span><br></blockquote><blockquote type="cite"><span>+ ilist_iterator() = default;</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> // This is templated so that we can allow constructing a const iterator from</span><br></blockquote><blockquote type="cite"><span> // a nonconst iterator...</span><br></blockquote><blockquote type="cite"><span>@@ -281,20 +203,23 @@ public:</span><br></blockquote><blockquote type="cite"><span> const ilist_iterator<node_ty> &RHS,</span><br></blockquote><blockquote type="cite"><span> typename std::enable_if<std::is_convertible<node_ty *, NodeTy *>::value,</span><br></blockquote><blockquote type="cite"><span> void *>::type = nullptr)</span><br></blockquote><blockquote type="cite"><span>- : NodePtr(RHS.getNodePtrUnchecked()) {}</span><br></blockquote><blockquote type="cite"><span>+ : NodePtr(RHS.getNodePtr()) {}</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> // This is templated so that we can allow assigning to a const iterator from</span><br></blockquote><blockquote type="cite"><span> // a nonconst iterator...</span><br></blockquote><blockquote type="cite"><span> template <class node_ty></span><br></blockquote><blockquote type="cite"><span> const ilist_iterator &operator=(const ilist_iterator<node_ty> &RHS) {</span><br></blockquote><blockquote type="cite"><span>- NodePtr = RHS.getNodePtrUnchecked();</span><br></blockquote><blockquote type="cite"><span>+ NodePtr = RHS.getNodePtr();</span><br></blockquote><blockquote type="cite"><span> return *this;</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> void reset(pointer NP) { NodePtr = NP; }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> // Accessors...</span><br></blockquote><blockquote type="cite"><span>- reference operator*() const { return *NodePtr; }</span><br></blockquote><blockquote type="cite"><span>+ reference operator*() const {</span><br></blockquote><blockquote type="cite"><span>+ assert(!NodePtr->isKnownSentinel());</span><br></blockquote><blockquote type="cite"><span>+ return static_cast<NodeTy &>(*getNodePtr());</span><br></blockquote><blockquote type="cite"><span>+ }</span><br></blockquote><blockquote type="cite"><span> pointer operator->() const { return &operator*(); }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> // Comparison operators</span><br></blockquote><blockquote type="cite"><span>@@ -328,9 +253,6 @@ public:</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> /// Get the underlying ilist_node.</span><br></blockquote><blockquote type="cite"><span> node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- // Internal interface, do not use...</span><br></blockquote><blockquote type="cite"><span>- pointer getNodePtrUnchecked() const { return NodePtr; }</span><br></blockquote><blockquote type="cite"><span> };</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> // Allow ilist_iterators to convert into pointers to a node automatically when</span><br></blockquote><blockquote type="cite"><span>@@ -356,56 +278,33 @@ template<typename NodeTy> struct simplif</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> //===----------------------------------------------------------------------===//</span><br></blockquote><blockquote type="cite"><span> //</span><br></blockquote><blockquote type="cite"><span>-/// iplist - The subset of list functionality that can safely be used on nodes</span><br></blockquote><blockquote type="cite"><span>-/// of polymorphic types, i.e. a heterogeneous list with a common base class that</span><br></blockquote><blockquote type="cite"><span>-/// holds the next/prev pointers. The only state of the list itself is a single</span><br></blockquote><blockquote type="cite"><span>-/// pointer to the head of the list.</span><br></blockquote><blockquote type="cite"><span>-///</span><br></blockquote><blockquote type="cite"><span>-/// This list can be in one of three interesting states:</span><br></blockquote><blockquote type="cite"><span>-/// 1. The list may be completely unconstructed. In this case, the head</span><br></blockquote><blockquote type="cite"><span>-/// pointer is null. When in this form, any query for an iterator (e.g.</span><br></blockquote><blockquote type="cite"><span>-/// begin() or end()) causes the list to transparently change to state #2.</span><br></blockquote><blockquote type="cite"><span>-/// 2. The list may be empty, but contain a sentinel for the end iterator. This</span><br></blockquote><blockquote type="cite"><span>-/// sentinel is created by the Traits::createSentinel method and is a link</span><br></blockquote><blockquote type="cite"><span>-/// in the list. When the list is empty, the pointer in the iplist points</span><br></blockquote><blockquote type="cite"><span>-/// to the sentinel. Once the sentinel is constructed, it</span><br></blockquote><blockquote type="cite"><span>-/// is not destroyed until the list is.</span><br></blockquote><blockquote type="cite"><span>-/// 3. The list may contain actual objects in it, which are stored as a doubly</span><br></blockquote><blockquote type="cite"><span>-/// linked list of nodes. One invariant of the list is that the predecessor</span><br></blockquote><blockquote type="cite"><span>-/// of the first node in the list always points to the last node in the list,</span><br></blockquote><blockquote type="cite"><span>-/// and the successor pointer for the sentinel (which always stays at the</span><br></blockquote><blockquote type="cite"><span>-/// end of the list) is always null.</span><br></blockquote><blockquote type="cite"><span>-///</span><br></blockquote><blockquote type="cite"><span>+/// The subset of list functionality that can safely be used on nodes of</span><br></blockquote><blockquote type="cite"><span>+/// polymorphic types, i.e. a heterogeneous list with a common base class that</span><br></blockquote><blockquote type="cite"><span>+/// holds the next/prev pointers. The only state of the list itself is an</span><br></blockquote><blockquote type="cite"><span>+/// ilist_sentinel, which holds pointers to the first and last nodes in the</span><br></blockquote><blockquote type="cite"><span>+/// list.</span><br></blockquote><blockquote type="cite"><span> template <typename NodeTy, typename Traits = ilist_traits<NodeTy>></span><br></blockquote><blockquote type="cite"><span> class iplist : public Traits, ilist_node_access {</span><br></blockquote><blockquote type="cite"><span>+ // TODO: Drop these assertions anytime after 4.0 is branched (keep them for</span><br></blockquote><blockquote type="cite"><span>+ // one release to help out-of-tree code update).</span><br></blockquote><blockquote type="cite"><span> #if !defined(_MSC_VER)</span><br></blockquote><blockquote type="cite"><span> // FIXME: This fails in MSVC, but it's worth keeping around to help</span><br></blockquote><blockquote type="cite"><span> // non-Windows users root out bugs in their ilist_traits.</span><br></blockquote><blockquote type="cite"><span> static_assert(!ilist_detail::HasGetNext<Traits, NodeTy>::value,</span><br></blockquote><blockquote type="cite"><span> "ilist next and prev links are not customizable!");</span><br></blockquote><blockquote type="cite"><span>+ static_assert(!ilist_detail::HasCreateSentinel<Traits>::value,</span><br></blockquote><blockquote type="cite"><span>+ "ilist sentinel is not customizable!");</span><br></blockquote><blockquote type="cite"><span> #endif</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>- mutable NodeTy *Head;</span><br></blockquote><blockquote type="cite"><span>+ ilist_sentinel<NodeTy> Sentinel;</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>- // Use the prev node pointer of 'head' as the tail pointer. This is really a</span><br></blockquote><blockquote type="cite"><span>- // circularly linked list where we snip the 'next' link from the sentinel node</span><br></blockquote><blockquote type="cite"><span>- // back to the first node in the list (to preserve assertions about going off</span><br></blockquote><blockquote type="cite"><span>- // the end of the list).</span><br></blockquote><blockquote type="cite"><span>- NodeTy *getTail() { return this->ensureHead(Head); }</span><br></blockquote><blockquote type="cite"><span>- const NodeTy *getTail() const { return this->ensureHead(Head); }</span><br></blockquote><blockquote type="cite"><span>- void setTail(NodeTy *N) const { this->noteHead(Head, N); }</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- /// CreateLazySentinel - This method verifies whether the sentinel for the</span><br></blockquote><blockquote type="cite"><span>- /// list has been created and lazily makes it if not.</span><br></blockquote><blockquote type="cite"><span>- void CreateLazySentinel() const {</span><br></blockquote><blockquote type="cite"><span>- this->ensureHead(Head);</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>+ typedef ilist_node<NodeTy> node_type;</span><br></blockquote><blockquote type="cite"><span>+ typedef const ilist_node<NodeTy> const_node_type;</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> static bool op_less(NodeTy &L, NodeTy &R) { return L < R; }</span><br></blockquote><blockquote type="cite"><span> static bool op_equal(NodeTy &L, NodeTy &R) { return L == R; }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>- // No fundamental reason why iplist can't be copyable, but the default</span><br></blockquote><blockquote type="cite"><span>- // copy/copy-assign won't do.</span><br></blockquote><blockquote type="cite"><span>+ // Copying intrusively linked nodes doesn't make sense.</span><br></blockquote><blockquote type="cite"><span> iplist(const iplist &) = delete;</span><br></blockquote><blockquote type="cite"><span> void operator=(const iplist &) = delete;</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>@@ -422,30 +321,14 @@ public:</span><br></blockquote><blockquote type="cite"><span> typedef std::reverse_iterator<const_iterator> const_reverse_iterator;</span><br></blockquote><blockquote type="cite"><span> typedef std::reverse_iterator<iterator> reverse_iterator;</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>- iplist() : Head(this->provideInitialHead()) {}</span><br></blockquote><blockquote type="cite"><span>- ~iplist() {</span><br></blockquote><blockquote type="cite"><span>- if (!Head) return;</span><br></blockquote><blockquote type="cite"><span>- clear();</span><br></blockquote><blockquote type="cite"><span>- Traits::destroySentinel(getTail());</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>+ iplist() = default;</span><br></blockquote><blockquote type="cite"><span>+ ~iplist() { clear(); }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> // Iterator creation methods.</span><br></blockquote><blockquote type="cite"><span>- iterator begin() {</span><br></blockquote><blockquote type="cite"><span>- CreateLazySentinel();</span><br></blockquote><blockquote type="cite"><span>- return iterator(Head);</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>- const_iterator begin() const {</span><br></blockquote><blockquote type="cite"><span>- CreateLazySentinel();</span><br></blockquote><blockquote type="cite"><span>- return const_iterator(Head);</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>- iterator end() {</span><br></blockquote><blockquote type="cite"><span>- CreateLazySentinel();</span><br></blockquote><blockquote type="cite"><span>- return iterator(getTail());</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>- const_iterator end() const {</span><br></blockquote><blockquote type="cite"><span>- CreateLazySentinel();</span><br></blockquote><blockquote type="cite"><span>- return const_iterator(getTail());</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>+ iterator begin() { return ++iterator(Sentinel); }</span><br></blockquote><blockquote type="cite"><span>+ const_iterator begin() const { return ++const_iterator(Sentinel); }</span><br></blockquote><blockquote type="cite"><span>+ iterator end() { return iterator(Sentinel); }</span><br></blockquote><blockquote type="cite"><span>+ const_iterator end() const { return const_iterator(Sentinel); }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> // reverse iterator creation methods.</span><br></blockquote><blockquote type="cite"><span> reverse_iterator rbegin() { return reverse_iterator(end()); }</span><br></blockquote><blockquote type="cite"><span>@@ -456,44 +339,39 @@ public:</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> // Miscellaneous inspection routines.</span><br></blockquote><blockquote type="cite"><span> size_type max_size() const { return size_type(-1); }</span><br></blockquote><blockquote type="cite"><span>- bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const {</span><br></blockquote><blockquote type="cite"><span>- return !Head || Head == getTail();</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>+ bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return Sentinel.empty(); }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> // Front and back accessor functions...</span><br></blockquote><blockquote type="cite"><span> reference front() {</span><br></blockquote><blockquote type="cite"><span> assert(!empty() && "Called front() on empty list!");</span><br></blockquote><blockquote type="cite"><span>- return *Head;</span><br></blockquote><blockquote type="cite"><span>+ return *begin();</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span> const_reference front() const {</span><br></blockquote><blockquote type="cite"><span> assert(!empty() && "Called front() on empty list!");</span><br></blockquote><blockquote type="cite"><span>- return *Head;</span><br></blockquote><blockquote type="cite"><span>+ return *begin();</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span> reference back() {</span><br></blockquote><blockquote type="cite"><span> assert(!empty() && "Called back() on empty list!");</span><br></blockquote><blockquote type="cite"><span>- return *this->getPrev(getTail());</span><br></blockquote><blockquote type="cite"><span>+ return *--end();</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span> const_reference back() const {</span><br></blockquote><blockquote type="cite"><span> assert(!empty() && "Called back() on empty list!");</span><br></blockquote><blockquote type="cite"><span>- return *this->getPrev(getTail());</span><br></blockquote><blockquote type="cite"><span>+ return *--end();</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> void swap(iplist &RHS) {</span><br></blockquote><blockquote type="cite"><span> assert(0 && "Swap does not use list traits callback correctly yet!");</span><br></blockquote><blockquote type="cite"><span>- std::swap(Head, RHS.Head);</span><br></blockquote><blockquote type="cite"><span>+ std::swap(Sentinel, RHS.Sentinel);</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> iterator insert(iterator where, NodeTy *New) {</span><br></blockquote><blockquote type="cite"><span>- NodeTy *CurNode = where.getNodePtrUnchecked();</span><br></blockquote><blockquote type="cite"><span>- NodeTy *PrevNode = this->getPrev(CurNode);</span><br></blockquote><blockquote type="cite"><span>- this->setNext(New, CurNode);</span><br></blockquote><blockquote type="cite"><span>- this->setPrev(New, PrevNode);</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- if (CurNode != Head) // Is PrevNode off the beginning of the list?</span><br></blockquote><blockquote type="cite"><span>- this->setNext(PrevNode, New);</span><br></blockquote><blockquote type="cite"><span>- else</span><br></blockquote><blockquote type="cite"><span>- Head = New;</span><br></blockquote><blockquote type="cite"><span>- this->setPrev(CurNode, New);</span><br></blockquote><blockquote type="cite"><span>+ node_type *NewN = this->getNodePtr(New);</span><br></blockquote><blockquote type="cite"><span>+ node_type *Next = where.getNodePtr();</span><br></blockquote><blockquote type="cite"><span>+ node_type *Prev = this->getPrev(Next);</span><br></blockquote><blockquote type="cite"><span>+ this->setNext(NewN, Next);</span><br></blockquote><blockquote type="cite"><span>+ this->setPrev(NewN, Prev);</span><br></blockquote><blockquote type="cite"><span>+ this->setNext(Prev, NewN);</span><br></blockquote><blockquote type="cite"><span>+ this->setPrev(Next, NewN);</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> this->addNodeToList(New); // Notify traits that we added a node...</span><br></blockquote><blockquote type="cite"><span> return iterator(New);</span><br></blockquote><blockquote type="cite"><span>@@ -513,24 +391,23 @@ public:</span><br></blockquote><blockquote type="cite"><span> NodeTy *remove(iterator &IT) {</span><br></blockquote><blockquote type="cite"><span> assert(IT != end() && "Cannot remove end of list!");</span><br></blockquote><blockquote type="cite"><span> NodeTy *Node = &*IT;</span><br></blockquote><blockquote type="cite"><span>- NodeTy *NextNode = this->getNext(Node);</span><br></blockquote><blockquote type="cite"><span>- NodeTy *PrevNode = this->getPrev(Node);</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- if (Node != Head) // Is PrevNode off the beginning of the list?</span><br></blockquote><blockquote type="cite"><span>- this->setNext(PrevNode, NextNode);</span><br></blockquote><blockquote type="cite"><span>- else</span><br></blockquote><blockquote type="cite"><span>- Head = NextNode;</span><br></blockquote><blockquote type="cite"><span>- this->setPrev(NextNode, PrevNode);</span><br></blockquote><blockquote type="cite"><span>- IT.reset(NextNode);</span><br></blockquote><blockquote type="cite"><span>+ node_type *Base = this->getNodePtr(Node);</span><br></blockquote><blockquote type="cite"><span>+ node_type *Next = this->getNext(Base);</span><br></blockquote><blockquote type="cite"><span>+ node_type *Prev = this->getPrev(Base);</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ this->setNext(Prev, Next);</span><br></blockquote><blockquote type="cite"><span>+ this->setPrev(Next, Prev);</span><br></blockquote><blockquote type="cite"><span>+ IT = iterator(*Next);</span><br></blockquote><blockquote type="cite"><span> this->removeNodeFromList(Node); // Notify traits that we removed a node...</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> // Set the next/prev pointers of the current node to null. This isn't</span><br></blockquote><blockquote type="cite"><span> // strictly required, but this catches errors where a node is removed from</span><br></blockquote><blockquote type="cite"><span> // an ilist (and potentially deleted) with iterators still pointing at it.</span><br></blockquote><blockquote type="cite"><span>- // When those iterators are incremented or decremented, they will assert on</span><br></blockquote><blockquote type="cite"><span>- // the null next/prev pointer instead of "usually working".</span><br></blockquote><blockquote type="cite"><span>- this->setNext(Node, nullptr);</span><br></blockquote><blockquote type="cite"><span>- this->setPrev(Node, nullptr);</span><br></blockquote><blockquote type="cite"><span>+ // After those iterators are incremented or decremented, they become</span><br></blockquote><blockquote type="cite"><span>+ // default-constructed iterators, and will assert on increment, decrement,</span><br></blockquote><blockquote type="cite"><span>+ // and dereference instead of "usually working".</span><br></blockquote><blockquote type="cite"><span>+ this->setNext(Base, nullptr);</span><br></blockquote><blockquote type="cite"><span>+ this->setPrev(Base, nullptr);</span><br></blockquote><blockquote type="cite"><span> return Node;</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>@@ -556,12 +433,7 @@ public:</span><br></blockquote><blockquote type="cite"><span> ///</span><br></blockquote><blockquote type="cite"><span> /// This should only be used immediately before freeing nodes in bulk to</span><br></blockquote><blockquote type="cite"><span> /// avoid traversing the list and bringing all the nodes into cache.</span><br></blockquote><blockquote type="cite"><span>- void clearAndLeakNodesUnsafely() {</span><br></blockquote><blockquote type="cite"><span>- if (Head) {</span><br></blockquote><blockquote type="cite"><span>- Head = getTail();</span><br></blockquote><blockquote type="cite"><span>- this->setPrev(Head, Head);</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>+ void clearAndLeakNodesUnsafely() { Sentinel.reset(); }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> private:</span><br></blockquote><blockquote type="cite"><span> // transfer - The heart of the splice function. Move linked list nodes from</span><br></blockquote><blockquote type="cite"><span>@@ -570,48 +442,34 @@ private:</span><br></blockquote><blockquote type="cite"><span> void transfer(iterator position, iplist &L2, iterator first, iterator last) {</span><br></blockquote><blockquote type="cite"><span> assert(first != last && "Should be checked by callers");</span><br></blockquote><blockquote type="cite"><span> // Position cannot be contained in the range to be transferred.</span><br></blockquote><blockquote type="cite"><span>- // Check for the most common mistake.</span><br></blockquote><blockquote type="cite"><span> assert(position != first &&</span><br></blockquote><blockquote type="cite"><span>+ // Check for the most common mistake.</span><br></blockquote><blockquote type="cite"><span> "Insertion point can't be one of the transferred nodes");</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>- if (position != last) {</span><br></blockquote><blockquote type="cite"><span>- // Note: we have to be careful about the case when we move the first node</span><br></blockquote><blockquote type="cite"><span>- // in the list. This node is the list sentinel node and we can't move it.</span><br></blockquote><blockquote type="cite"><span>- NodeTy *ThisSentinel = getTail();</span><br></blockquote><blockquote type="cite"><span>- setTail(nullptr);</span><br></blockquote><blockquote type="cite"><span>- NodeTy *L2Sentinel = L2.getTail();</span><br></blockquote><blockquote type="cite"><span>- L2.setTail(nullptr);</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- // Remove [first, last) from its old position.</span><br></blockquote><blockquote type="cite"><span>- NodeTy *First = &*first, *Prev = this->getPrev(First);</span><br></blockquote><blockquote type="cite"><span>- NodeTy *Next = last.getNodePtrUnchecked(), *Last = this->getPrev(Next);</span><br></blockquote><blockquote type="cite"><span>- if (Prev)</span><br></blockquote><blockquote type="cite"><span>- this->setNext(Prev, Next);</span><br></blockquote><blockquote type="cite"><span>- else</span><br></blockquote><blockquote type="cite"><span>- L2.Head = Next;</span><br></blockquote><blockquote type="cite"><span>- this->setPrev(Next, Prev);</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- // Splice [first, last) into its new position.</span><br></blockquote><blockquote type="cite"><span>- NodeTy *PosNext = position.getNodePtrUnchecked();</span><br></blockquote><blockquote type="cite"><span>- NodeTy *PosPrev = this->getPrev(PosNext);</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- // Fix head of list...</span><br></blockquote><blockquote type="cite"><span>- if (PosPrev)</span><br></blockquote><blockquote type="cite"><span>- this->setNext(PosPrev, First);</span><br></blockquote><blockquote type="cite"><span>- else</span><br></blockquote><blockquote type="cite"><span>- Head = First;</span><br></blockquote><blockquote type="cite"><span>- this->setPrev(First, PosPrev);</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- // Fix end of list...</span><br></blockquote><blockquote type="cite"><span>- this->setNext(Last, PosNext);</span><br></blockquote><blockquote type="cite"><span>- this->setPrev(PosNext, Last);</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- this->transferNodesFromList(L2, iterator(First), iterator(PosNext));</span><br></blockquote><blockquote type="cite"><span>-</span><br></blockquote><blockquote type="cite"><span>- // Now that everything is set, restore the pointers to the list sentinels.</span><br></blockquote><blockquote type="cite"><span>- L2.setTail(L2Sentinel);</span><br></blockquote><blockquote type="cite"><span>- setTail(ThisSentinel);</span><br></blockquote><blockquote type="cite"><span>- }</span><br></blockquote><blockquote type="cite"><span>+ if (position == last)</span><br></blockquote><blockquote type="cite"><span>+ return;</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ // Get raw hooks to the first and final nodes being transferred.</span><br></blockquote><blockquote type="cite"><span>+ node_type *First = first.getNodePtr();</span><br></blockquote><blockquote type="cite"><span>+ node_type *Final = (--last).getNodePtr();</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ // Detach from old list/position.</span><br></blockquote><blockquote type="cite"><span>+ node_type *Prev = this->getPrev(First);</span><br></blockquote><blockquote type="cite"><span>+ node_type *Next = this->getNext(Final);</span><br></blockquote><blockquote type="cite"><span>+ this->setNext(Prev, Next);</span><br></blockquote><blockquote type="cite"><span>+ this->setPrev(Next, Prev);</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ // Splice [First, Final] into its new list/position.</span><br></blockquote><blockquote type="cite"><span>+ Next = position.getNodePtr();</span><br></blockquote><blockquote type="cite"><span>+ Prev = this->getPrev(Next);</span><br></blockquote><blockquote type="cite"><span>+ this->setNext(Final, Next);</span><br></blockquote><blockquote type="cite"><span>+ this->setPrev(First, Prev);</span><br></blockquote><blockquote type="cite"><span>+ this->setNext(Prev, First);</span><br></blockquote><blockquote type="cite"><span>+ this->setPrev(Next, Final);</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ // Callback. Note that the nodes have moved from before-last to</span><br></blockquote><blockquote type="cite"><span>+ // before-position.</span><br></blockquote><blockquote type="cite"><span>+ this->transferNodesFromList(L2, first, position);</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> public:</span><br></blockquote><blockquote type="cite"><span>@@ -621,7 +479,6 @@ public:</span><br></blockquote><blockquote type="cite"><span> //</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> size_type LLVM_ATTRIBUTE_UNUSED_RESULT size() const {</span><br></blockquote><blockquote type="cite"><span>- if (!Head) return 0; // Don't require construction of sentinel if empty.</span><br></blockquote><blockquote type="cite"><span> return std::distance(begin(), end());</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>@@ -631,7 +488,7 @@ public:</span><br></blockquote><blockquote type="cite"><span> return last;</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>- void clear() { if (Head) erase(begin(), end()); }</span><br></blockquote><blockquote type="cite"><span>+ void clear() { erase(begin(), end()); }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> // Front and back inserters...</span><br></blockquote><blockquote type="cite"><span> void push_front(NodeTy *val) { insert(begin(), val); }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Modified: llvm/trunk/include/llvm/ADT/ilist_node.h</span><br></blockquote><blockquote type="cite"><span>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ilist_node.h?rev=278974&r1=278973&r2=278974&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ilist_node.h?rev=278974&r1=278973&r2=278974&view=diff</a></span><br></blockquote><blockquote type="cite"><span>==============================================================================</span><br></blockquote><blockquote type="cite"><span>--- llvm/trunk/include/llvm/ADT/ilist_node.h (original)</span><br></blockquote><blockquote type="cite"><span>+++ llvm/trunk/include/llvm/ADT/ilist_node.h Wed Aug 17 15:44:33 2016</span><br></blockquote><blockquote type="cite"><span>@@ -15,6 +15,8 @@</span><br></blockquote><blockquote type="cite"><span> #ifndef LLVM_ADT_ILIST_NODE_H</span><br></blockquote><blockquote type="cite"><span> #define LLVM_ADT_ILIST_NODE_H</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>+#include <llvm/ADT/PointerIntPair.h></span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span> namespace llvm {</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> template<typename NodeTy></span><br></blockquote><blockquote type="cite"><span>@@ -22,46 +24,81 @@ struct ilist_traits;</span><br></blockquote><blockquote type="cite"><span> template <typename NodeTy> struct ilist_embedded_sentinel_traits;</span><br></blockquote><blockquote type="cite"><span> template <typename NodeTy> struct ilist_half_embedded_sentinel_traits;</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>-/// ilist_half_node - Base class that provides prev services for sentinels.</span><br></blockquote><blockquote type="cite"><span>-///</span><br></blockquote><blockquote type="cite"><span>-template<typename NodeTy></span><br></blockquote><blockquote type="cite"><span>-class ilist_half_node {</span><br></blockquote><blockquote type="cite"><span>- friend struct ilist_traits<NodeTy>;</span><br></blockquote><blockquote type="cite"><span>- friend struct ilist_half_embedded_sentinel_traits<NodeTy>;</span><br></blockquote><blockquote type="cite"><span>- NodeTy *Prev;</span><br></blockquote><blockquote type="cite"><span>-protected:</span><br></blockquote><blockquote type="cite"><span>- NodeTy *getPrev() { return Prev; }</span><br></blockquote><blockquote type="cite"><span>- const NodeTy *getPrev() const { return Prev; }</span><br></blockquote><blockquote type="cite"><span>- void setPrev(NodeTy *P) { Prev = P; }</span><br></blockquote><blockquote type="cite"><span>- ilist_half_node() : Prev(nullptr) {}</span><br></blockquote><blockquote type="cite"><span>+/// Base class for ilist nodes.</span><br></blockquote><blockquote type="cite"><span>+struct ilist_node_base {</span><br></blockquote><blockquote type="cite"><span>+#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS</span><br></blockquote><blockquote type="cite"><span>+ PointerIntPair<ilist_node_base *, 1> PrevAndSentinel;</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ void setPrev(ilist_node_base *Prev) { PrevAndSentinel.setPointer(Prev); }</span><br></blockquote><blockquote type="cite"><span>+ ilist_node_base *getPrev() const { return PrevAndSentinel.getPointer(); }</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ bool isKnownSentinel() const { return PrevAndSentinel.getInt(); }</span><br></blockquote><blockquote type="cite"><span>+ void initializeSentinel() { PrevAndSentinel.setInt(true); }</span><br></blockquote><blockquote type="cite"><span>+#else</span><br></blockquote><blockquote type="cite"><span>+ ilist_node_base *Prev = nullptr;</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ void setPrev(ilist_node_base *Prev) { this->Prev = Prev; }</span><br></blockquote><blockquote type="cite"><span>+ ilist_node_base *getPrev() const { return Prev; }</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ bool isKnownSentinel() const { return false; }</span><br></blockquote><blockquote type="cite"><span>+ void initializeSentinel() {}</span><br></blockquote><blockquote type="cite"><span>+#endif</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ ilist_node_base *Next = nullptr;</span><br></blockquote><blockquote type="cite"><span> };</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> struct ilist_node_access;</span><br></blockquote><blockquote type="cite"><span> template <typename NodeTy> class ilist_iterator;</span><br></blockquote><blockquote type="cite"><span>+template <typename NodeTy> class ilist_sentinel;</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>-/// Base class that provides next/prev services for ilist nodes.</span><br></blockquote><blockquote type="cite"><span>-template<typename NodeTy></span><br></blockquote><blockquote type="cite"><span>-class ilist_node : private ilist_half_node<NodeTy> {</span><br></blockquote><blockquote type="cite"><span>+/// Templated wrapper class.</span><br></blockquote><blockquote type="cite"><span>+template <typename NodeTy> class ilist_node : ilist_node_base {</span><br></blockquote><blockquote type="cite"><span> friend struct ilist_node_access;</span><br></blockquote><blockquote type="cite"><span> friend struct ilist_traits<NodeTy>;</span><br></blockquote><blockquote type="cite"><span> friend struct ilist_half_embedded_sentinel_traits<NodeTy>;</span><br></blockquote><blockquote type="cite"><span> friend struct ilist_embedded_sentinel_traits<NodeTy>;</span><br></blockquote><blockquote type="cite"><span>- NodeTy *Next;</span><br></blockquote><blockquote type="cite"><span>- NodeTy *getNext() { return Next; }</span><br></blockquote><blockquote type="cite"><span>- const NodeTy *getNext() const { return Next; }</span><br></blockquote><blockquote type="cite"><span>- void setNext(NodeTy *N) { Next = N; }</span><br></blockquote><blockquote type="cite"><span>+ friend class ilist_iterator<NodeTy>;</span><br></blockquote><blockquote type="cite"><span>+ friend class ilist_sentinel<NodeTy>;</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span> protected:</span><br></blockquote><blockquote type="cite"><span>- ilist_node() : Next(nullptr) {}</span><br></blockquote><blockquote type="cite"><span>+ ilist_node() = default;</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>-public:</span><br></blockquote><blockquote type="cite"><span>- ilist_iterator<NodeTy> getIterator() {</span><br></blockquote><blockquote type="cite"><span>- // FIXME: Stop downcasting to create the iterator (potential UB).</span><br></blockquote><blockquote type="cite"><span>- return ilist_iterator<NodeTy>(static_cast<NodeTy *>(this));</span><br></blockquote><blockquote type="cite"><span>+private:</span><br></blockquote><blockquote type="cite"><span>+ ilist_node *getPrev() {</span><br></blockquote><blockquote type="cite"><span>+ return static_cast<ilist_node *>(ilist_node_base::getPrev());</span><br></blockquote><blockquote type="cite"><span>+ }</span><br></blockquote><blockquote type="cite"><span>+ ilist_node *getNext() { return static_cast<ilist_node *>(Next); }</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ const ilist_node *getPrev() const {</span><br></blockquote><blockquote type="cite"><span>+ return static_cast<ilist_node *>(ilist_node_base::getPrev());</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span>+ const ilist_node *getNext() const { return static_cast<ilist_node *>(Next); }</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ void setPrev(ilist_node *N) { ilist_node_base::setPrev(N); }</span><br></blockquote><blockquote type="cite"><span>+ void setNext(ilist_node *N) { Next = N; }</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+public:</span><br></blockquote><blockquote type="cite"><span>+ ilist_iterator<NodeTy> getIterator() { return ilist_iterator<NodeTy>(*this); }</span><br></blockquote><blockquote type="cite"><span> ilist_iterator<const NodeTy> getIterator() const {</span><br></blockquote><blockquote type="cite"><span>- // FIXME: Stop downcasting to create the iterator (potential UB).</span><br></blockquote><blockquote type="cite"><span>- return ilist_iterator<const NodeTy>(static_cast<const NodeTy *>(this));</span><br></blockquote><blockquote type="cite"><span>+ return ilist_iterator<const NodeTy>(*this);</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ using ilist_node_base::isKnownSentinel;</span><br></blockquote><blockquote type="cite"><span>+};</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+template <typename NodeTy> class ilist_sentinel : public ilist_node<NodeTy> {</span><br></blockquote><blockquote type="cite"><span>+public:</span><br></blockquote><blockquote type="cite"><span>+ ilist_sentinel() {</span><br></blockquote><blockquote type="cite"><span>+ ilist_node_base::initializeSentinel();</span><br></blockquote><blockquote type="cite"><span>+ reset();</span><br></blockquote><blockquote type="cite"><span>+ }</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ void reset() {</span><br></blockquote><blockquote type="cite"><span>+ this->setPrev(this);</span><br></blockquote><blockquote type="cite"><span>+ this->setNext(this);</span><br></blockquote><blockquote type="cite"><span>+ }</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ bool empty() const { return this == this->getPrev(); }</span><br></blockquote><blockquote type="cite"><span> };</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span> /// An ilist node that can access its parent list.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Modified: llvm/trunk/unittests/ADT/ilistTest.cpp</span><br></blockquote><blockquote type="cite"><span>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/ilistTest.cpp?rev=278974&r1=278973&r2=278974&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/ilistTest.cpp?rev=278974&r1=278973&r2=278974&view=diff</a></span><br></blockquote><blockquote type="cite"><span>==============================================================================</span><br></blockquote><blockquote type="cite"><span>--- llvm/trunk/unittests/ADT/ilistTest.cpp (original)</span><br></blockquote><blockquote type="cite"><span>+++ llvm/trunk/unittests/ADT/ilistTest.cpp Wed Aug 17 15:44:33 2016</span><br></blockquote><blockquote type="cite"><span>@@ -128,4 +128,66 @@ TEST(ilistTest, UnsafeClear) {</span><br></blockquote><blockquote type="cite"><span> EXPECT_EQ(6, List.back().Value);</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>+struct NodeWithCallback : ilist_node<NodeWithCallback> {</span><br></blockquote><blockquote type="cite"><span>+ int Value = 0;</span><br></blockquote><blockquote type="cite"><span>+ bool IsInList = false;</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ NodeWithCallback() = default;</span><br></blockquote><blockquote type="cite"><span>+ NodeWithCallback(int Value) : Value(Value) {}</span><br></blockquote><blockquote type="cite"><span>+ NodeWithCallback(const NodeWithCallback &) = delete;</span><br></blockquote><blockquote type="cite"><span>+};</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+} // end namespace</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+namespace llvm {</span><br></blockquote><blockquote type="cite"><span>+template <></span><br></blockquote><blockquote type="cite"><span>+struct ilist_traits<NodeWithCallback></span><br></blockquote><blockquote type="cite"><span>+ : public ilist_node_traits<NodeWithCallback> {</span><br></blockquote><blockquote type="cite"><span>+ void addNodeToList(NodeWithCallback *N) { N->IsInList = true; }</span><br></blockquote><blockquote type="cite"><span>+ void removeNodeFromList(NodeWithCallback *N) { N->IsInList = false; }</span><br></blockquote><blockquote type="cite"><span>+};</span><br></blockquote><blockquote type="cite"><span>+} // end namespace llvm</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+namespace {</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+TEST(ilistTest, addNodeToList) {</span><br></blockquote><blockquote type="cite"><span>+ ilist<NodeWithCallback> L;</span><br></blockquote><blockquote type="cite"><span>+ NodeWithCallback N(7);</span><br></blockquote><blockquote type="cite"><span>+ ASSERT_FALSE(N.IsInList);</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ L.insert(L.begin(), &N);</span><br></blockquote><blockquote type="cite"><span>+ ASSERT_EQ(1u, L.size());</span><br></blockquote><blockquote type="cite"><span>+ ASSERT_EQ(&N, &*L.begin());</span><br></blockquote><blockquote type="cite"><span>+ ASSERT_TRUE(N.IsInList);</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ L.remove(&N);</span><br></blockquote><blockquote type="cite"><span>+ ASSERT_EQ(0u, L.size());</span><br></blockquote><blockquote type="cite"><span>+ ASSERT_FALSE(N.IsInList);</span><br></blockquote><blockquote type="cite"><span> }</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+struct PrivateNode : private ilist_node<PrivateNode> {</span><br></blockquote><blockquote type="cite"><span>+ friend struct llvm::ilist_node_access;</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ int Value = 0;</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ PrivateNode() = default;</span><br></blockquote><blockquote type="cite"><span>+ PrivateNode(int Value) : Value(Value) {}</span><br></blockquote><blockquote type="cite"><span>+ PrivateNode(const PrivateNode &) = delete;</span><br></blockquote><blockquote type="cite"><span>+};</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+TEST(ilistTest, privateNode) {</span><br></blockquote><blockquote type="cite"><span>+ // Instantiate various APIs to be sure they're callable when ilist_node is</span><br></blockquote><blockquote type="cite"><span>+ // inherited privately.</span><br></blockquote><blockquote type="cite"><span>+ ilist<NodeWithCallback> L;</span><br></blockquote><blockquote type="cite"><span>+ NodeWithCallback N(7);</span><br></blockquote><blockquote type="cite"><span>+ L.insert(L.begin(), &N);</span><br></blockquote><blockquote type="cite"><span>+ ++L.begin();</span><br></blockquote><blockquote type="cite"><span>+ (void)*L.begin();</span><br></blockquote><blockquote type="cite"><span>+ (void)(L.begin() == L.end());</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+ ilist<NodeWithCallback> L2;</span><br></blockquote><blockquote type="cite"><span>+ L2.splice(L2.end(), L);</span><br></blockquote><blockquote type="cite"><span>+ L2.remove(&N);</span><br></blockquote><blockquote type="cite"><span>+}</span><br></blockquote><blockquote type="cite"><span>+</span><br></blockquote><blockquote type="cite"><span>+} // end namespace</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>_______________________________________________</span><br></blockquote><blockquote type="cite"><span>llvm-commits mailing list</span><br></blockquote><blockquote type="cite"><span><a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a></span><br></blockquote><blockquote type="cite"><span><a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a></span><br></blockquote></div></blockquote></body></html>