1 | //===------ extensible_rtti.h - Extensible RTTI for ORC RT ------*- 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 | // Provides an extensible RTTI mechanism, that can be used regardless of whether |
12 | // the runtime is built with -frtti or not. This is predominantly used to |
13 | // support error handling. |
14 | // |
15 | // The RTTIRoot class defines methods for comparing type ids. Implementations |
16 | // of these methods can be injected into new classes using the RTTIExtends |
17 | // class template. |
18 | // |
19 | // E.g. |
20 | // |
21 | // @code{.cpp} |
22 | // class MyBaseClass : public RTTIExtends<MyBaseClass, RTTIRoot> { |
23 | // public: |
24 | // static char ID; |
25 | // virtual void foo() = 0; |
26 | // }; |
27 | // |
28 | // class MyDerivedClass1 : public RTTIExtends<MyDerivedClass1, MyBaseClass> { |
29 | // public: |
30 | // static char ID; |
31 | // void foo() override {} |
32 | // }; |
33 | // |
34 | // class MyDerivedClass2 : public RTTIExtends<MyDerivedClass2, MyBaseClass> { |
35 | // public: |
36 | // static char ID; |
37 | // void foo() override {} |
38 | // }; |
39 | // |
40 | // char MyBaseClass::ID = 0; |
41 | // char MyDerivedClass1::ID = 0; |
42 | // char MyDerivedClass2:: ID = 0; |
43 | // |
44 | // void fn() { |
45 | // std::unique_ptr<MyBaseClass> B = std::make_unique<MyDerivedClass1>(); |
46 | // outs() << isa<MyBaseClass>(B) << "\n"; // Outputs "1". |
47 | // outs() << isa<MyDerivedClass1>(B) << "\n"; // Outputs "1". |
48 | // outs() << isa<MyDerivedClass2>(B) << "\n"; // Outputs "0'. |
49 | // } |
50 | // |
51 | // @endcode |
52 | // |
53 | // Note: |
54 | // This header was adapted from llvm/Support/ExtensibleRTTI.h, however the |
55 | // data structures are not shared and the code need not be kept in sync. |
56 | // |
57 | //===----------------------------------------------------------------------===// |
58 | |
59 | #ifndef ORC_RT_EXTENSIBLE_RTTI_H |
60 | #define ORC_RT_EXTENSIBLE_RTTI_H |
61 | |
62 | namespace __orc_rt { |
63 | |
64 | template <typename ThisT, typename ParentT> class RTTIExtends; |
65 | |
66 | /// Base class for the extensible RTTI hierarchy. |
67 | /// |
68 | /// This class defines virtual methods, dynamicClassID and isA, that enable |
69 | /// type comparisons. |
70 | class RTTIRoot { |
71 | public: |
72 | virtual ~RTTIRoot() = default; |
73 | |
74 | /// Returns the class ID for this type. |
75 | static const void *classID() { return &ID; } |
76 | |
77 | /// Returns the class ID for the dynamic type of this RTTIRoot instance. |
78 | virtual const void *dynamicClassID() const = 0; |
79 | |
80 | /// Returns true if this class's ID matches the given class ID. |
81 | virtual bool isA(const void *const ClassID) const { |
82 | return ClassID == classID(); |
83 | } |
84 | |
85 | /// Check whether this instance is a subclass of QueryT. |
86 | template <typename QueryT> bool isA() const { return isA(QueryT::classID()); } |
87 | |
88 | static bool classof(const RTTIRoot *R) { return R->isA<RTTIRoot>(); } |
89 | |
90 | private: |
91 | virtual void anchor(); |
92 | |
93 | static char ID; |
94 | }; |
95 | |
96 | /// Inheritance utility for extensible RTTI. |
97 | /// |
98 | /// Supports single inheritance only: A class can only have one |
99 | /// ExtensibleRTTI-parent (i.e. a parent for which the isa<> test will work), |
100 | /// though it can have many non-ExtensibleRTTI parents. |
101 | /// |
102 | /// RTTIExtents uses CRTP so the first template argument to RTTIExtends is the |
103 | /// newly introduced type, and the *second* argument is the parent class. |
104 | /// |
105 | /// class MyType : public RTTIExtends<MyType, RTTIRoot> { |
106 | /// public: |
107 | /// static char ID; |
108 | /// }; |
109 | /// |
110 | /// class MyDerivedType : public RTTIExtends<MyDerivedType, MyType> { |
111 | /// public: |
112 | /// static char ID; |
113 | /// }; |
114 | /// |
115 | template <typename ThisT, typename ParentT> class RTTIExtends : public ParentT { |
116 | public: |
117 | // Inherit constructors and isA methods from ParentT. |
118 | using ParentT::isA; |
119 | using ParentT::ParentT; |
120 | |
121 | static char ID; |
122 | |
123 | static const void *classID() { return &ThisT::ID; } |
124 | |
125 | const void *dynamicClassID() const override { return &ThisT::ID; } |
126 | |
127 | bool isA(const void *const ClassID) const override { |
128 | return ClassID == classID() || ParentT::isA(ClassID); |
129 | } |
130 | |
131 | static bool classof(const RTTIRoot *R) { return R->isA<ThisT>(); } |
132 | }; |
133 | |
134 | template <typename ThisT, typename ParentT> |
135 | char RTTIExtends<ThisT, ParentT>::ID = 0; |
136 | |
137 | /// Returns true if the given value is an instance of the template type |
138 | /// parameter. |
139 | template <typename To, typename From> bool isa(const From &Value) { |
140 | return To::classof(&Value); |
141 | } |
142 | |
143 | } // end namespace __orc_rt |
144 | |
145 | #endif // ORC_RT_EXTENSIBLE_RTTI_H |
146 | |