1 //===-- llvm/Support/ExtensibleRTTI.h - ExtensibleRTTI support --*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // \file 11 // 12 // Defines an extensible RTTI mechanism designed to work with Casting.h. 13 // 14 // Extensible RTTI differs from LLVM's primary RTTI mechanism (see 15 // llvm.org/docs/HowToSetUpLLVMStyleRTTI.html) by supporting open type 16 // hierarchies, where new types can be added from outside libraries without 17 // needing to change existing code. LLVM's primary RTTI mechanism should be 18 // preferred where possible, but where open hierarchies are needed this system 19 // can be used. 20 // 21 // The RTTIRoot class defines methods for comparing type ids. Implementations 22 // of these methods can be injected into new classes using the RTTIExtends 23 // class template. 24 // 25 // E.g. 26 // 27 // @code{.cpp} 28 // class MyBaseClass : public RTTIExtends<MyBaseClass, RTTIRoot> { 29 // public: 30 // static char ID; 31 // virtual void foo() = 0; 32 // }; 33 // 34 // class MyDerivedClass1 : public RTTIExtends<MyDerivedClass1, MyBaseClass> { 35 // public: 36 // static char ID; 37 // void foo() override {} 38 // }; 39 // 40 // class MyDerivedClass2 : public RTTIExtends<MyDerivedClass2, MyBaseClass> { 41 // public: 42 // static char ID; 43 // void foo() override {} 44 // }; 45 // 46 // char MyBaseClass::ID = 0; 47 // char MyDerivedClass1::ID = 0; 48 // char MyDerivedClass2:: ID = 0; 49 // 50 // void fn() { 51 // std::unique_ptr<MyBaseClass> B = llvm::make_unique<MyDerivedClass1>(); 52 // llvm::outs() << isa<MyBaseClass>(B) << "\n"; // Outputs "1". 53 // llvm::outs() << isa<MyDerivedClass1>(B) << "\n"; // Outputs "1". 54 // llvm::outs() << isa<MyDerivedClass2>(B) << "\n"; // Outputs "0'. 55 // } 56 // 57 // @endcode 58 // 59 //===----------------------------------------------------------------------===// 60 61 #ifndef LLVM_SUPPORT_EXTENSIBLERTTI_H 62 #define LLVM_SUPPORT_EXTENSIBLERTTI_H 63 64 namespace llvm { 65 66 template <typename ThisT, typename ParentT> class RTTIExtends; 67 68 /// Base class for the extensible RTTI hierarchy. 69 /// 70 /// This class defines virtual methods, dynamicClassID and isA, that enable 71 /// type comparisons. 72 class RTTIRoot { 73 public: 74 virtual ~RTTIRoot() = default; 75 76 /// Returns the class ID for this type. classID()77 static const void *classID() { return &ID; } 78 79 /// Returns the class ID for the dynamic type of this RTTIRoot instance. 80 virtual const void *dynamicClassID() const = 0; 81 82 /// Returns true if this class's ID matches the given class ID. isA(const void * const ClassID)83 virtual bool isA(const void *const ClassID) const { 84 return ClassID == classID(); 85 } 86 87 /// Check whether this instance is a subclass of QueryT. 88 template <typename QueryT> isA()89 bool isA() const { return isA(QueryT::classID()); } 90 91 private: 92 virtual void anchor(); 93 94 static char ID; 95 }; 96 97 /// Inheritance utility for extensible RTTI. 98 /// 99 /// Supports single inheritance only: A class can only have one 100 /// ExtensibleRTTI-parent (i.e. a parent for which the isa<> test will work), 101 /// though it can have many non-ExtensibleRTTI parents. 102 /// 103 /// RTTIExtents uses CRTP so the first template argument to RTTIExtends is the 104 /// newly introduced type, and the *second* argument is the parent class. 105 /// 106 /// class MyType : public RTTIExtends<MyType, RTTIRoot> { 107 /// public: 108 /// static char ID; 109 /// }; 110 /// 111 /// class MyDerivedType : public RTTIExtends<MyDerivedType, MyType> { 112 /// public: 113 /// static char ID; 114 /// }; 115 /// 116 template <typename ThisT, typename ParentT> 117 class RTTIExtends : public ParentT { 118 public: 119 // Inherit constructors from ParentT. 120 using ParentT::ParentT; 121 classID()122 static const void *classID() { return &ThisT::ID; } 123 dynamicClassID()124 const void *dynamicClassID() const override { return &ThisT::ID; } 125 isA(const void * const ClassID)126 bool isA(const void *const ClassID) const override { 127 return ClassID == classID() || ParentT::isA(ClassID); 128 } 129 classof(const RTTIRoot * R)130 static bool classof(const RTTIRoot *R) { return R->isA<ThisT>(); } 131 }; 132 133 } // end namespace llvm 134 135 #endif // LLVM_SUPPORT_EXTENSIBLERTTI_H 136