146 lines · c
1//===------------- rtti.h - RTTI support 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-exception6//7//===----------------------------------------------------------------------===//8//9// \file10//11// Provides an extensible RTTI mechanism, that can be used regardless of whether12// the runtime is built with -frtti or not. This is predominantly used to13// support error handling.14//15// The RTTIRoot class defines methods for comparing type ids. Implementations16// of these methods can be injected into new classes using the RTTIExtends17// 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// @endcode52//53// Note:54// This header was adapted from llvm/Support/ExtensibleRTTI.h, however the55// data structures are not shared and the code need not be kept in sync.56//57//===----------------------------------------------------------------------===//58 59#ifndef ORC_RT_RTTI_H60#define ORC_RT_RTTI_H61 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 enable69/// 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 one99/// 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 the103/// 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 type138/// parameter.139template <typename To, typename From> bool isa(const From &Value) {140 return To::classof(&Value);141}142 143} // namespace orc_rt144 145#endif // ORC_RT_RTTI_H146