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
84 /// Check whether this instance is a subclass of QueryT.
85 template <typename QueryT>
86 bool isA() const { return isA(QueryT::classID()); }
87
88private:
89 virtual void anchor();
90
91 static char ID;
92};
93
94/// Inheritance utility for extensible RTTI.
95///
96/// Supports single inheritance only: A class can only have one
97/// ExtensibleRTTI-parent (i.e. a parent for which the isa<> test will work),
98/// though it can have many non-ExtensibleRTTI parents.
99///
100/// RTTIExtents uses CRTP so the first template argument to RTTIExtends is the
101/// newly introduced type, and the *second* argument is the parent class.
102///
103/// class MyType : public RTTIExtends<MyType, RTTIRoot> {
104/// public:
105/// static char ID;
106/// };
107///
108/// class MyDerivedType : public RTTIExtends<MyDerivedType, MyType> {
109/// public:
110/// static char ID;
111/// };
112///
113template <typename ThisT, typename ParentT>
114class RTTIExtends : public ParentT {
115public:
116 // Inherit constructors from ParentT.
117 using ParentT::ParentT;
118
119 static const void *classID() { return &ThisT::ID; }
120
121 const void *dynamicClassID() const override { return &ThisT::ID; }
122
123 bool isA(const void *const ClassID) const override {
124 return ClassID == classID() || ParentT::isA(ClassID);
125 }
126
127 static bool classof(const RTTIRoot *R) { return R->isA<ThisT>(); }
128};
129
130} // end namespace llvm
131
132#endif // LLVM_SUPPORT_EXTENSIBLERTTI_H
133

source code of llvm/include/llvm/Support/ExtensibleRTTI.h