//==- llvm/ADT/alist_node.h - Next/Prev helper class for alist ---*- C++ -*-==// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the alist_node class template, which is used by the alist // class template to provide next/prev pointers for arbitrary objects. // //===----------------------------------------------------------------------===// #ifndef LLVM_ADT_ALIST_NODE_H #define LLVM_ADT_ALIST_NODE_H #include #include "llvm/ADT/ilist.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/DataTypes.h" namespace llvm { /// alist_node - This is a utility class used by alist. It holds prev and next /// pointers for use with ilists, as well as storage for objects as large as /// LargestT, that are in T's inheritance tree. /// template class alist_node { alist_node *Prev, *Next; public: alist_node() : Prev(0), Next(0) {} alist_node *getPrev() const { return Prev; } alist_node *getNext() const { return Next; } void setPrev(alist_node *N) { Prev = N; } void setNext(alist_node *N) { Next = N; } union { char Bytes[sizeof(LargestT)]; long long L; void *P; } Storage; template SubClass *getElement(SubClass *) { assert(sizeof(SubClass) <= sizeof(LargestT)); assert(unsigned(AlignOf::Alignment) <= unsigned(AlignOf::Alignment)); return reinterpret_cast(&Storage.Bytes); } template const SubClass *getElement(SubClass *) const { assert(sizeof(SubClass) <= sizeof(LargestT)); assert(unsigned(AlignOf::Alignment) <= unsigned(AlignOf::Alignment)); return reinterpret_cast(&Storage.Bytes); } // This code essentially does offsetof, but actual offsetof hits an ICE in // GCC 4.0 relating to offsetof being used inside a template. static alist_node* getNode(T *D) { return reinterpret_cast(reinterpret_cast(D) - (uintptr_t)&getNull()->Storage); } static const alist_node* getNode(const T *D) { return reinterpret_cast(reinterpret_cast(D) - (uintptr_t)&getNull()->Storage); } private: static alist_node* getNull() { return 0; } }; // A specialization of ilist_traits for alist_nodes. template class ilist_traits > { typedef alist_node NodeTy; protected: // Allocate a sentinel inside the traits class. This works // because iplist carries an instance of the traits class. NodeTy Sentinel; public: static NodeTy *getPrev(NodeTy *N) { return N->getPrev(); } static NodeTy *getNext(NodeTy *N) { return N->getNext(); } static const NodeTy *getPrev(const NodeTy *N) { return N->getPrev(); } static const NodeTy *getNext(const NodeTy *N) { return N->getNext(); } static void setPrev(NodeTy *N, NodeTy *Prev) { N->setPrev(Prev); } static void setNext(NodeTy *N, NodeTy *Next) { N->setNext(Next); } NodeTy *createSentinel() const { assert(Sentinel.getPrev() == 0); assert(Sentinel.getNext() == 0); return const_cast(&Sentinel); } void destroySentinel(NodeTy *N) { assert(N == &Sentinel); Sentinel.setPrev(0); Sentinel.setNext(0); } void addNodeToList(NodeTy *N) {} void removeNodeFromList(NodeTy *N) {} void transferNodesFromList(iplist &L2, ilist_iterator first, ilist_iterator last) {} // Ideally we wouldn't implement this, but ilist's clear calls it, // which is called from ilist's destructor. We won't ever call // either of those with a non-empty list, but statically this // method needs to exist. void deleteNode(NodeTy *N) { assert(0); } private: static NodeTy *createNode(const NodeTy &V); // do not implement }; } #endif