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 62namespace __orc_rt { 63 64template <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. 70class RTTIRoot { 71public: 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 90private: 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/// 115template <typename ThisT, typename ParentT> class RTTIExtends : public ParentT { 116public: 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 134template <typename ThisT, typename ParentT> 135char RTTIExtends<ThisT, ParentT>::ID = 0; 136 137/// Returns true if the given value is an instance of the template type 138/// parameter. 139template <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