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