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