1 .. _how-to-set-up-llvm-style-rtti:
3 ======================================================
4 How to set up LLVM-style RTTI for your class hierarchy
5 ======================================================
7 .. sectionauthor:: Sean Silva <silvas@purdue.edu>
14 LLVM avoids using C++'s built in RTTI. Instead, it pervasively uses its
15 own hand-rolled form of RTTI which is much more efficient and flexible,
16 although it requires a bit more work from you as a class author.
18 A description of how to use LLVM-style RTTI from a client's perspective is
19 given in the `Programmer's Manual <ProgrammersManual.html#isa>`_. This
20 document, in contrast, discusses the steps you need to take as a class
21 hierarchy author to make LLVM-style RTTI available to your clients.
23 Before diving in, make sure that you are familiar with the Object Oriented
24 Programming concept of "`is-a`_".
26 .. _is-a: http://en.wikipedia.org/wiki/Is-a
31 This section describes how to set up the most basic form of LLVM-style RTTI
32 (which is sufficient for 99.9% of the cases). We will set up LLVM-style
33 RTTI for this class hierarchy:
40 virtual double computeArea() = 0;
43 class Square : public Shape {
46 Square(double S) : SideLength(S) {}
47 double computeArea() /* override */;
50 class Circle : public Shape {
53 Circle(double R) : Radius(R) {}
54 double computeArea() /* override */;
57 The most basic working setup for LLVM-style RTTI requires the following
60 #. In the header where you declare ``Shape``, you will want to ``#include
61 "llvm/Support/Casting.h"``, which declares LLVM's RTTI templates. That
62 way your clients don't even have to think about it.
66 #include "llvm/Support/Casting.h"
68 #. In the base class, introduce an enum which discriminates all of the
69 different concrete classes in the hierarchy, and stash the enum value
70 somewhere in the base class.
72 Here is the code after introducing this change:
78 + /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
84 + const ShapeKind Kind;
86 + ShapeKind getKind() const { return Kind; }
89 virtual double computeArea() = 0;
92 You will usually want to keep the ``Kind`` member encapsulated and
93 private, but let the enum ``ShapeKind`` be public along with providing a
94 ``getKind()`` method. This is convenient for clients so that they can do
95 a ``switch`` over the enum.
97 A common naming convention is that these enums are "kind"s, to avoid
98 ambiguity with the words "type" or "class" which have overloaded meanings
99 in many contexts within LLVM. Sometimes there will be a natural name for
100 it, like "opcode". Don't bikeshed over this; when in doubt use ``Kind``.
102 You might wonder why the ``Kind`` enum doesn't have an entry for
103 ``Shape``. The reason for this is that since ``Shape`` is abstract
104 (``computeArea() = 0;``), you will never actually have non-derived
105 instances of exactly that class (only subclasses). See `Concrete Bases
106 and Deeper Hierarchies`_ for information on how to deal with
107 non-abstract bases. It's worth mentioning here that unlike
108 ``dynamic_cast<>``, LLVM-style RTTI can be used (and is often used) for
109 classes that don't have v-tables.
111 #. Next, you need to make sure that the ``Kind`` gets initialized to the
112 value corresponding to the dynamic type of the class. Typically, you will
113 want to have it be an argument to the constructor of the base class, and
114 then pass in the respective ``XXXKind`` from subclass constructors.
116 Here is the code after that change:
122 /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
128 const ShapeKind Kind;
130 ShapeKind getKind() const { return Kind; }
133 + Shape(ShapeKind K) : Kind(K) {}
134 virtual double computeArea() = 0;
137 class Square : public Shape {
140 - Square(double S) : SideLength(S) {}
141 + Square(double S) : Shape(SK_Square), SideLength(S) {}
142 double computeArea() /* override */;
145 class Circle : public Shape {
148 - Circle(double R) : Radius(R) {}
149 + Circle(double R) : Shape(SK_Circle), Radius(R) {}
150 double computeArea() /* override */;
153 #. Finally, you need to inform LLVM's RTTI templates how to dynamically
154 determine the type of a class (i.e. whether the ``isa<>``/``dyn_cast<>``
155 should succeed). The default "99.9% of use cases" way to accomplish this
156 is through a small static member function ``classof``. In order to have
157 proper context for an explanation, we will display this code first, and
158 then below describe each part:
164 /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
170 const ShapeKind Kind;
172 ShapeKind getKind() const { return Kind; }
174 Shape(ShapeKind K) : Kind(K) {}
175 virtual double computeArea() = 0;
178 class Square : public Shape {
181 Square(double S) : Shape(SK_Square), SideLength(S) {}
182 double computeArea() /* override */;
184 + static bool classof(const Shape *S) {
185 + return S->getKind() == SK_Square;
189 class Circle : public Shape {
192 Circle(double R) : Shape(SK_Circle), Radius(R) {}
193 double computeArea() /* override */;
195 + static bool classof(const Shape *S) {
196 + return S->getKind() == SK_Circle;
200 The job of ``classof`` is to dynamically determine whether an object of
201 a base class is in fact of a particular derived class. In order to
202 downcast a type ``Base`` to a type ``Derived``, there needs to be a
203 ``classof`` in ``Derived`` which will accept an object of type ``Base``.
205 To be concrete, consider the following code:
210 if (isa<Circle>(S)) {
211 /* do something ... */
214 The code of the ``isa<>`` test in this code will eventually boil
215 down---after template instantiation and some other machinery---to a
216 check roughly like ``Circle::classof(S)``. For more information, see
217 :ref:`classof-contract`.
219 The argument to ``classof`` should always be an *ancestor* class because
220 the implementation has logic to allow and optimize away
221 upcasts/up-``isa<>``'s automatically. It is as though every class
222 ``Foo`` automatically has a ``classof`` like:
229 static bool classof(const T *,
231 ::llvm::is_base_of<Foo, T>::value
232 >::type* = 0) { return true; }
236 Note that this is the reason that we did not need to introduce a
237 ``classof`` into ``Shape``: all relevant classes derive from ``Shape``,
238 and ``Shape`` itself is abstract (has no entry in the ``Kind`` enum),
239 so this notional inferred ``classof`` is all we need. See `Concrete
240 Bases and Deeper Hierarchies`_ for more information about how to extend
241 this example to more general hierarchies.
243 Although for this small example setting up LLVM-style RTTI seems like a lot
244 of "boilerplate", if your classes are doing anything interesting then this
245 will end up being a tiny fraction of the code.
247 Concrete Bases and Deeper Hierarchies
248 =====================================
250 For concrete bases (i.e. non-abstract interior nodes of the inheritance
251 tree), the ``Kind`` check inside ``classof`` needs to be a bit more
252 complicated. The situation differs from the example above in that
254 * Since the class is concrete, it must itself have an entry in the ``Kind``
255 enum because it is possible to have objects with this class as a dynamic
258 * Since the class has children, the check inside ``classof`` must take them
261 Say that ``SpecialSquare`` and ``OtherSpecialSquare`` derive
262 from ``Square``, and so ``ShapeKind`` becomes:
269 + SK_OtherSpecialSquare,
273 Then in ``Square``, we would need to modify the ``classof`` like so:
277 - static bool classof(const Shape *S) {
278 - return S->getKind() == SK_Square;
280 + static bool classof(const Shape *S) {
281 + return S->getKind() >= SK_Square &&
282 + S->getKind() <= SK_OtherSpecialSquare;
285 The reason that we need to test a range like this instead of just equality
286 is that both ``SpecialSquare`` and ``OtherSpecialSquare`` "is-a"
287 ``Square``, and so ``classof`` needs to return ``true`` for them.
289 This approach can be made to scale to arbitrarily deep hierarchies. The
290 trick is that you arrange the enum values so that they correspond to a
291 preorder traversal of the class hierarchy tree. With that arrangement, all
292 subclass tests can be done with two comparisons as shown above. If you just
293 list the class hierarchy like a list of bullet points, you'll get the
302 .. _classof-contract:
304 The Contract of ``classof``
305 ---------------------------
307 To be more precise, let ``classof`` be inside a class ``C``. Then the
308 contract for ``classof`` is "return ``true`` if the dynamic type of the
309 argument is-a ``C``". As long as your implementation fulfills this
310 contract, you can tweak and optimize it as much as you want.
314 Touch on some of the more advanced features, like ``isa_impl`` and
315 ``simplify_type``. However, those two need reference documentation in
316 the form of doxygen comments as well. We need the doxygen so that we can
317 say "for full details, see http://llvm.org/doxygen/..."
322 #. The ``Kind`` enum should have one entry per concrete class, ordered
323 according to a preorder traversal of the inheritance tree.
324 #. The argument to ``classof`` should be a ``const Base *``, where ``Base``
325 is some ancestor in the inheritance hierarchy. The argument should
326 *never* be a derived class or the class itself: the template machinery
327 for ``isa<>`` already handles this case and optimizes it.
328 #. For each class in the hierarchy that has no children, implement a
329 ``classof`` that checks only against its ``Kind``.
330 #. For each class in the hierarchy that has children, implement a
331 ``classof`` that checks a range of the first child's ``Kind`` and the
332 last child's ``Kind``.