1 //===-- llvm/Support/ExtensibleRTTI.h - ExtensibleRTTI support --*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 // Defines an extensible RTTI mechanism designed to work with Casting.h.
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
21 // The RTTIRoot class defines methods for comparing type ids. Implementations
22 // of these methods can be injected into new classes using the RTTIExtends
28 // class MyBaseClass : public RTTIExtends<MyBaseClass, RTTIRoot> {
31 // virtual void foo() = 0;
34 // class MyDerivedClass1 : public RTTIExtends<MyDerivedClass1, MyBaseClass> {
37 // void foo() override {}
40 // class MyDerivedClass2 : public RTTIExtends<MyDerivedClass2, MyBaseClass> {
43 // void foo() override {}
46 // char MyBaseClass::ID = 0;
47 // char MyDerivedClass1::ID = 0;
48 // char MyDerivedClass2:: ID = 0;
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'.
59 //===----------------------------------------------------------------------===//
61 #ifndef LLVM_SUPPORT_EXTENSIBLERTTI_H
62 #define LLVM_SUPPORT_EXTENSIBLERTTI_H
66 template <typename ThisT, typename ParentT> class RTTIExtends;
68 /// Base class for the extensible RTTI hierarchy.
70 /// This class defines virtual methods, dynamicClassID and isA, that enable
74 virtual ~RTTIRoot() = default;
76 /// Returns the class ID for this type.
77 static const void *classID() { return &ID; }
79 /// Returns the class ID for the dynamic type of this RTTIRoot instance.
80 virtual const void *dynamicClassID() const = 0;
82 /// Returns true if this class's ID matches the given class ID.
83 virtual bool isA(const void *const ClassID) const {
84 return ClassID == classID();
87 /// Check whether this instance is a subclass of QueryT.
88 template <typename QueryT>
89 bool isA() const { return isA(QueryT::classID()); }
92 virtual void anchor();
97 /// Inheritance utility for extensible RTTI.
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.
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.
106 /// class MyType : public RTTIExtends<MyType, RTTIRoot> {
111 /// class MyDerivedType : public RTTIExtends<MyDerivedType, MyType> {
116 template <typename ThisT, typename ParentT>
117 class RTTIExtends : public ParentT {
119 // Inherit constructors from ParentT.
120 using ParentT::ParentT;
122 static const void *classID() { return &ThisT::ID; }
124 const void *dynamicClassID() const override { return &ThisT::ID; }
126 bool isA(const void *const ClassID) const override {
127 return ClassID == classID() || ParentT::isA(ClassID);
130 static bool classof(const RTTIRoot *R) { return R->isA<ThisT>(); }
133 } // end namespace llvm
135 #endif // LLVM_SUPPORT_EXTENSIBLERTTI_H