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