LLVM 20.0.0git
ExtensibleRTTI.h
Go to the documentation of this file.
1//===-- llvm/Support/ExtensibleRTTI.h - ExtensibleRTTI support --*- 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// Defines an extensible RTTI mechanism designed to work with Casting.h.
12//
13// Extensible RTTI differs from LLVM's primary RTTI mechanism (see
14// llvm.org/docs/HowToSetUpLLVMStyleRTTI.html) by supporting open type
15// hierarchies, where new types can be added from outside libraries without
16// needing to change existing code. LLVM's primary RTTI mechanism should be
17// preferred where possible, but where open hierarchies are needed this system
18// can be used.
19//
20// The RTTIRoot class defines methods for comparing type ids. Implementations
21// of these methods can be injected into new classes using the RTTIExtends
22// class template.
23//
24// E.g.
25//
26// @code{.cpp}
27// class MyBaseClass : public RTTIExtends<MyBaseClass, RTTIRoot> {
28// public:
29// static char ID;
30// virtual void foo() = 0;
31// };
32//
33// class MyDerivedClass1 : public RTTIExtends<MyDerivedClass1, MyBaseClass> {
34// public:
35// static char ID;
36// void foo() override {}
37// };
38//
39// class MyDerivedClass2 : public RTTIExtends<MyDerivedClass2, MyBaseClass> {
40// public:
41// static char ID;
42// void foo() override {}
43// };
44//
45// char MyBaseClass::ID = 0;
46// char MyDerivedClass1::ID = 0;
47// char MyDerivedClass2:: ID = 0;
48//
49// void fn() {
50// std::unique_ptr<MyBaseClass> B = llvm::make_unique<MyDerivedClass1>();
51// llvm::outs() << isa<MyBaseClass>(B) << "\n"; // Outputs "1".
52// llvm::outs() << isa<MyDerivedClass1>(B) << "\n"; // Outputs "1".
53// llvm::outs() << isa<MyDerivedClass2>(B) << "\n"; // Outputs "0'.
54// }
55//
56// @endcode
57//
58//===----------------------------------------------------------------------===//
59
60#ifndef LLVM_SUPPORT_EXTENSIBLERTTI_H
61#define LLVM_SUPPORT_EXTENSIBLERTTI_H
62
63namespace llvm {
64
65/// Base class for the extensible RTTI hierarchy.
66///
67/// This class defines virtual methods, dynamicClassID and isA, that enable
68/// type comparisons.
69class RTTIRoot {
70public:
71 virtual ~RTTIRoot() = default;
72
73 /// Returns the class ID for this type.
74 static const void *classID() { return &ID; }
75
76 /// Returns the class ID for the dynamic type of this RTTIRoot instance.
77 virtual const void *dynamicClassID() const = 0;
78
79 /// Returns true if this class's ID matches the given class ID.
80 virtual bool isA(const void *const ClassID) const {
81 return ClassID == classID();
82 }
83
84private:
85 virtual void anchor();
86
87 static char ID;
88};
89
90/// Inheritance utility for extensible RTTI.
91///
92/// Multiple inheritance is supported, but RTTIExtends only inherits
93/// constructors from the first base class. All subsequent bases will be
94/// default constructed. Virtual and non-public inheritance are not supported.
95///
96/// RTTIExtents uses CRTP so the first template argument to RTTIExtends is the
97/// newly introduced type, and the *second and later* arguments are the parent
98/// classes.
99///
100/// @code{.cpp}
101/// class MyType : public RTTIExtends<MyType, RTTIRoot> {
102/// public:
103/// static char ID;
104/// };
105///
106/// class MyDerivedType : public RTTIExtends<MyDerivedType, MyType> {
107/// public:
108/// static char ID;
109/// };
110///
111/// class MyOtherType : public RTTIExtends<MyOtherType, MyType> {
112/// public:
113/// static char ID;
114/// };
115///
116/// class MyMultipleInheritanceType
117/// : public RTTIExtends<MyMultipleInheritanceType,
118/// MyDerivedType, MyOtherType> {
119/// public:
120/// static char ID;
121/// };
122///
123/// @endcode
124///
125template <typename ThisT, typename ParentT, typename... ParentTs>
126class RTTIExtends : public ParentT, public ParentTs... {
127public:
128 // Inherit constructors from the first Parent.
129 using ParentT::ParentT;
130
131 static const void *classID() { return &ThisT::ID; }
132
133 const void *dynamicClassID() const override { return &ThisT::ID; }
134
135 /// Check whether this instance is a subclass of QueryT.
136 template <typename QueryT> bool isA() const { return isA(QueryT::classID()); }
137
138 bool isA(const void *const ClassID) const override {
139 return ClassID == classID() || ParentT::isA(ClassID) ||
140 (ParentTs::isA(ClassID) || ...);
141 }
142
143 template <typename T> static bool classof(const T *R) {
144 return R->template isA<ThisT>();
145 }
146};
147
148} // end namespace llvm
149
150#endif // LLVM_SUPPORT_EXTENSIBLERTTI_H
Inheritance utility for extensible RTTI.
bool isA(const void *const ClassID) const override
bool isA() const
Check whether this instance is a subclass of QueryT.
static const void * classID()
const void * dynamicClassID() const override
static bool classof(const T *R)
Base class for the extensible RTTI hierarchy.
static const void * classID()
Returns the class ID for this type.
virtual bool isA(const void *const ClassID) const
Returns true if this class's ID matches the given class ID.
virtual ~RTTIRoot()=default
virtual const void * dynamicClassID() const =0
Returns the class ID for the dynamic type of this RTTIRoot instance.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18