xref: /aosp_15_r20/external/llvm/docs/HowToSetUpLLVMStyleRTTI.rst (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker======================================================
2*9880d681SAndroid Build Coastguard WorkerHow to set up LLVM-style RTTI for your class hierarchy
3*9880d681SAndroid Build Coastguard Worker======================================================
4*9880d681SAndroid Build Coastguard Worker
5*9880d681SAndroid Build Coastguard Worker.. contents::
6*9880d681SAndroid Build Coastguard Worker
7*9880d681SAndroid Build Coastguard WorkerBackground
8*9880d681SAndroid Build Coastguard Worker==========
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard WorkerLLVM avoids using C++'s built in RTTI. Instead, it  pervasively uses its
11*9880d681SAndroid Build Coastguard Workerown hand-rolled form of RTTI which is much more efficient and flexible,
12*9880d681SAndroid Build Coastguard Workeralthough it requires a bit more work from you as a class author.
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard WorkerA description of how to use LLVM-style RTTI from a client's perspective is
15*9880d681SAndroid Build Coastguard Workergiven in the `Programmer's Manual <ProgrammersManual.html#isa>`_. This
16*9880d681SAndroid Build Coastguard Workerdocument, in contrast, discusses the steps you need to take as a class
17*9880d681SAndroid Build Coastguard Workerhierarchy author to make LLVM-style RTTI available to your clients.
18*9880d681SAndroid Build Coastguard Worker
19*9880d681SAndroid Build Coastguard WorkerBefore diving in, make sure that you are familiar with the Object Oriented
20*9880d681SAndroid Build Coastguard WorkerProgramming concept of "`is-a`_".
21*9880d681SAndroid Build Coastguard Worker
22*9880d681SAndroid Build Coastguard Worker.. _is-a: http://en.wikipedia.org/wiki/Is-a
23*9880d681SAndroid Build Coastguard Worker
24*9880d681SAndroid Build Coastguard WorkerBasic Setup
25*9880d681SAndroid Build Coastguard Worker===========
26*9880d681SAndroid Build Coastguard Worker
27*9880d681SAndroid Build Coastguard WorkerThis section describes how to set up the most basic form of LLVM-style RTTI
28*9880d681SAndroid Build Coastguard Worker(which is sufficient for 99.9% of the cases). We will set up LLVM-style
29*9880d681SAndroid Build Coastguard WorkerRTTI for this class hierarchy:
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker.. code-block:: c++
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Worker   class Shape {
34*9880d681SAndroid Build Coastguard Worker   public:
35*9880d681SAndroid Build Coastguard Worker     Shape() {}
36*9880d681SAndroid Build Coastguard Worker     virtual double computeArea() = 0;
37*9880d681SAndroid Build Coastguard Worker   };
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker   class Square : public Shape {
40*9880d681SAndroid Build Coastguard Worker     double SideLength;
41*9880d681SAndroid Build Coastguard Worker   public:
42*9880d681SAndroid Build Coastguard Worker     Square(double S) : SideLength(S) {}
43*9880d681SAndroid Build Coastguard Worker     double computeArea() override;
44*9880d681SAndroid Build Coastguard Worker   };
45*9880d681SAndroid Build Coastguard Worker
46*9880d681SAndroid Build Coastguard Worker   class Circle : public Shape {
47*9880d681SAndroid Build Coastguard Worker     double Radius;
48*9880d681SAndroid Build Coastguard Worker   public:
49*9880d681SAndroid Build Coastguard Worker     Circle(double R) : Radius(R) {}
50*9880d681SAndroid Build Coastguard Worker     double computeArea() override;
51*9880d681SAndroid Build Coastguard Worker   };
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard WorkerThe most basic working setup for LLVM-style RTTI requires the following
54*9880d681SAndroid Build Coastguard Workersteps:
55*9880d681SAndroid Build Coastguard Worker
56*9880d681SAndroid Build Coastguard Worker#. In the header where you declare ``Shape``, you will want to ``#include
57*9880d681SAndroid Build Coastguard Worker   "llvm/Support/Casting.h"``, which declares LLVM's RTTI templates. That
58*9880d681SAndroid Build Coastguard Worker   way your clients don't even have to think about it.
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker   .. code-block:: c++
61*9880d681SAndroid Build Coastguard Worker
62*9880d681SAndroid Build Coastguard Worker      #include "llvm/Support/Casting.h"
63*9880d681SAndroid Build Coastguard Worker
64*9880d681SAndroid Build Coastguard Worker#. In the base class, introduce an enum which discriminates all of the
65*9880d681SAndroid Build Coastguard Worker   different concrete classes in the hierarchy, and stash the enum value
66*9880d681SAndroid Build Coastguard Worker   somewhere in the base class.
67*9880d681SAndroid Build Coastguard Worker
68*9880d681SAndroid Build Coastguard Worker   Here is the code after introducing this change:
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker   .. code-block:: c++
71*9880d681SAndroid Build Coastguard Worker
72*9880d681SAndroid Build Coastguard Worker       class Shape {
73*9880d681SAndroid Build Coastguard Worker       public:
74*9880d681SAndroid Build Coastguard Worker      +  /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
75*9880d681SAndroid Build Coastguard Worker      +  enum ShapeKind {
76*9880d681SAndroid Build Coastguard Worker      +    SK_Square,
77*9880d681SAndroid Build Coastguard Worker      +    SK_Circle
78*9880d681SAndroid Build Coastguard Worker      +  };
79*9880d681SAndroid Build Coastguard Worker      +private:
80*9880d681SAndroid Build Coastguard Worker      +  const ShapeKind Kind;
81*9880d681SAndroid Build Coastguard Worker      +public:
82*9880d681SAndroid Build Coastguard Worker      +  ShapeKind getKind() const { return Kind; }
83*9880d681SAndroid Build Coastguard Worker      +
84*9880d681SAndroid Build Coastguard Worker         Shape() {}
85*9880d681SAndroid Build Coastguard Worker         virtual double computeArea() = 0;
86*9880d681SAndroid Build Coastguard Worker       };
87*9880d681SAndroid Build Coastguard Worker
88*9880d681SAndroid Build Coastguard Worker   You will usually want to keep the ``Kind`` member encapsulated and
89*9880d681SAndroid Build Coastguard Worker   private, but let the enum ``ShapeKind`` be public along with providing a
90*9880d681SAndroid Build Coastguard Worker   ``getKind()`` method. This is convenient for clients so that they can do
91*9880d681SAndroid Build Coastguard Worker   a ``switch`` over the enum.
92*9880d681SAndroid Build Coastguard Worker
93*9880d681SAndroid Build Coastguard Worker   A common naming convention is that these enums are "kind"s, to avoid
94*9880d681SAndroid Build Coastguard Worker   ambiguity with the words "type" or "class" which have overloaded meanings
95*9880d681SAndroid Build Coastguard Worker   in many contexts within LLVM. Sometimes there will be a natural name for
96*9880d681SAndroid Build Coastguard Worker   it, like "opcode". Don't bikeshed over this; when in doubt use ``Kind``.
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker   You might wonder why the ``Kind`` enum doesn't have an entry for
99*9880d681SAndroid Build Coastguard Worker   ``Shape``. The reason for this is that since ``Shape`` is abstract
100*9880d681SAndroid Build Coastguard Worker   (``computeArea() = 0;``), you will never actually have non-derived
101*9880d681SAndroid Build Coastguard Worker   instances of exactly that class (only subclasses). See `Concrete Bases
102*9880d681SAndroid Build Coastguard Worker   and Deeper Hierarchies`_ for information on how to deal with
103*9880d681SAndroid Build Coastguard Worker   non-abstract bases. It's worth mentioning here that unlike
104*9880d681SAndroid Build Coastguard Worker   ``dynamic_cast<>``, LLVM-style RTTI can be used (and is often used) for
105*9880d681SAndroid Build Coastguard Worker   classes that don't have v-tables.
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker#. Next, you need to make sure that the ``Kind`` gets initialized to the
108*9880d681SAndroid Build Coastguard Worker   value corresponding to the dynamic type of the class. Typically, you will
109*9880d681SAndroid Build Coastguard Worker   want to have it be an argument to the constructor of the base class, and
110*9880d681SAndroid Build Coastguard Worker   then pass in the respective ``XXXKind`` from subclass constructors.
111*9880d681SAndroid Build Coastguard Worker
112*9880d681SAndroid Build Coastguard Worker   Here is the code after that change:
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker   .. code-block:: c++
115*9880d681SAndroid Build Coastguard Worker
116*9880d681SAndroid Build Coastguard Worker       class Shape {
117*9880d681SAndroid Build Coastguard Worker       public:
118*9880d681SAndroid Build Coastguard Worker         /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
119*9880d681SAndroid Build Coastguard Worker         enum ShapeKind {
120*9880d681SAndroid Build Coastguard Worker           SK_Square,
121*9880d681SAndroid Build Coastguard Worker           SK_Circle
122*9880d681SAndroid Build Coastguard Worker         };
123*9880d681SAndroid Build Coastguard Worker       private:
124*9880d681SAndroid Build Coastguard Worker         const ShapeKind Kind;
125*9880d681SAndroid Build Coastguard Worker       public:
126*9880d681SAndroid Build Coastguard Worker         ShapeKind getKind() const { return Kind; }
127*9880d681SAndroid Build Coastguard Worker
128*9880d681SAndroid Build Coastguard Worker      -  Shape() {}
129*9880d681SAndroid Build Coastguard Worker      +  Shape(ShapeKind K) : Kind(K) {}
130*9880d681SAndroid Build Coastguard Worker         virtual double computeArea() = 0;
131*9880d681SAndroid Build Coastguard Worker       };
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker       class Square : public Shape {
134*9880d681SAndroid Build Coastguard Worker         double SideLength;
135*9880d681SAndroid Build Coastguard Worker       public:
136*9880d681SAndroid Build Coastguard Worker      -  Square(double S) : SideLength(S) {}
137*9880d681SAndroid Build Coastguard Worker      +  Square(double S) : Shape(SK_Square), SideLength(S) {}
138*9880d681SAndroid Build Coastguard Worker         double computeArea() override;
139*9880d681SAndroid Build Coastguard Worker       };
140*9880d681SAndroid Build Coastguard Worker
141*9880d681SAndroid Build Coastguard Worker       class Circle : public Shape {
142*9880d681SAndroid Build Coastguard Worker         double Radius;
143*9880d681SAndroid Build Coastguard Worker       public:
144*9880d681SAndroid Build Coastguard Worker      -  Circle(double R) : Radius(R) {}
145*9880d681SAndroid Build Coastguard Worker      +  Circle(double R) : Shape(SK_Circle), Radius(R) {}
146*9880d681SAndroid Build Coastguard Worker         double computeArea() override;
147*9880d681SAndroid Build Coastguard Worker       };
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker#. Finally, you need to inform LLVM's RTTI templates how to dynamically
150*9880d681SAndroid Build Coastguard Worker   determine the type of a class (i.e. whether the ``isa<>``/``dyn_cast<>``
151*9880d681SAndroid Build Coastguard Worker   should succeed). The default "99.9% of use cases" way to accomplish this
152*9880d681SAndroid Build Coastguard Worker   is through a small static member function ``classof``. In order to have
153*9880d681SAndroid Build Coastguard Worker   proper context for an explanation, we will display this code first, and
154*9880d681SAndroid Build Coastguard Worker   then below describe each part:
155*9880d681SAndroid Build Coastguard Worker
156*9880d681SAndroid Build Coastguard Worker   .. code-block:: c++
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Worker       class Shape {
159*9880d681SAndroid Build Coastguard Worker       public:
160*9880d681SAndroid Build Coastguard Worker         /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
161*9880d681SAndroid Build Coastguard Worker         enum ShapeKind {
162*9880d681SAndroid Build Coastguard Worker           SK_Square,
163*9880d681SAndroid Build Coastguard Worker           SK_Circle
164*9880d681SAndroid Build Coastguard Worker         };
165*9880d681SAndroid Build Coastguard Worker       private:
166*9880d681SAndroid Build Coastguard Worker         const ShapeKind Kind;
167*9880d681SAndroid Build Coastguard Worker       public:
168*9880d681SAndroid Build Coastguard Worker         ShapeKind getKind() const { return Kind; }
169*9880d681SAndroid Build Coastguard Worker
170*9880d681SAndroid Build Coastguard Worker         Shape(ShapeKind K) : Kind(K) {}
171*9880d681SAndroid Build Coastguard Worker         virtual double computeArea() = 0;
172*9880d681SAndroid Build Coastguard Worker       };
173*9880d681SAndroid Build Coastguard Worker
174*9880d681SAndroid Build Coastguard Worker       class Square : public Shape {
175*9880d681SAndroid Build Coastguard Worker         double SideLength;
176*9880d681SAndroid Build Coastguard Worker       public:
177*9880d681SAndroid Build Coastguard Worker         Square(double S) : Shape(SK_Square), SideLength(S) {}
178*9880d681SAndroid Build Coastguard Worker         double computeArea() override;
179*9880d681SAndroid Build Coastguard Worker      +
180*9880d681SAndroid Build Coastguard Worker      +  static bool classof(const Shape *S) {
181*9880d681SAndroid Build Coastguard Worker      +    return S->getKind() == SK_Square;
182*9880d681SAndroid Build Coastguard Worker      +  }
183*9880d681SAndroid Build Coastguard Worker       };
184*9880d681SAndroid Build Coastguard Worker
185*9880d681SAndroid Build Coastguard Worker       class Circle : public Shape {
186*9880d681SAndroid Build Coastguard Worker         double Radius;
187*9880d681SAndroid Build Coastguard Worker       public:
188*9880d681SAndroid Build Coastguard Worker         Circle(double R) : Shape(SK_Circle), Radius(R) {}
189*9880d681SAndroid Build Coastguard Worker         double computeArea() override;
190*9880d681SAndroid Build Coastguard Worker      +
191*9880d681SAndroid Build Coastguard Worker      +  static bool classof(const Shape *S) {
192*9880d681SAndroid Build Coastguard Worker      +    return S->getKind() == SK_Circle;
193*9880d681SAndroid Build Coastguard Worker      +  }
194*9880d681SAndroid Build Coastguard Worker       };
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker   The job of ``classof`` is to dynamically determine whether an object of
197*9880d681SAndroid Build Coastguard Worker   a base class is in fact of a particular derived class.  In order to
198*9880d681SAndroid Build Coastguard Worker   downcast a type ``Base`` to a type ``Derived``, there needs to be a
199*9880d681SAndroid Build Coastguard Worker   ``classof`` in ``Derived`` which will accept an object of type ``Base``.
200*9880d681SAndroid Build Coastguard Worker
201*9880d681SAndroid Build Coastguard Worker   To be concrete, consider the following code:
202*9880d681SAndroid Build Coastguard Worker
203*9880d681SAndroid Build Coastguard Worker   .. code-block:: c++
204*9880d681SAndroid Build Coastguard Worker
205*9880d681SAndroid Build Coastguard Worker      Shape *S = ...;
206*9880d681SAndroid Build Coastguard Worker      if (isa<Circle>(S)) {
207*9880d681SAndroid Build Coastguard Worker        /* do something ... */
208*9880d681SAndroid Build Coastguard Worker      }
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Worker   The code of the ``isa<>`` test in this code will eventually boil
211*9880d681SAndroid Build Coastguard Worker   down---after template instantiation and some other machinery---to a
212*9880d681SAndroid Build Coastguard Worker   check roughly like ``Circle::classof(S)``. For more information, see
213*9880d681SAndroid Build Coastguard Worker   :ref:`classof-contract`.
214*9880d681SAndroid Build Coastguard Worker
215*9880d681SAndroid Build Coastguard Worker   The argument to ``classof`` should always be an *ancestor* class because
216*9880d681SAndroid Build Coastguard Worker   the implementation has logic to allow and optimize away
217*9880d681SAndroid Build Coastguard Worker   upcasts/up-``isa<>``'s automatically. It is as though every class
218*9880d681SAndroid Build Coastguard Worker   ``Foo`` automatically has a ``classof`` like:
219*9880d681SAndroid Build Coastguard Worker
220*9880d681SAndroid Build Coastguard Worker   .. code-block:: c++
221*9880d681SAndroid Build Coastguard Worker
222*9880d681SAndroid Build Coastguard Worker      class Foo {
223*9880d681SAndroid Build Coastguard Worker        [...]
224*9880d681SAndroid Build Coastguard Worker        template <class T>
225*9880d681SAndroid Build Coastguard Worker        static bool classof(const T *,
226*9880d681SAndroid Build Coastguard Worker                            ::std::enable_if<
227*9880d681SAndroid Build Coastguard Worker                              ::std::is_base_of<Foo, T>::value
228*9880d681SAndroid Build Coastguard Worker                            >::type* = 0) { return true; }
229*9880d681SAndroid Build Coastguard Worker        [...]
230*9880d681SAndroid Build Coastguard Worker      };
231*9880d681SAndroid Build Coastguard Worker
232*9880d681SAndroid Build Coastguard Worker   Note that this is the reason that we did not need to introduce a
233*9880d681SAndroid Build Coastguard Worker   ``classof`` into ``Shape``: all relevant classes derive from ``Shape``,
234*9880d681SAndroid Build Coastguard Worker   and ``Shape`` itself is abstract (has no entry in the ``Kind`` enum),
235*9880d681SAndroid Build Coastguard Worker   so this notional inferred ``classof`` is all we need. See `Concrete
236*9880d681SAndroid Build Coastguard Worker   Bases and Deeper Hierarchies`_ for more information about how to extend
237*9880d681SAndroid Build Coastguard Worker   this example to more general hierarchies.
238*9880d681SAndroid Build Coastguard Worker
239*9880d681SAndroid Build Coastguard WorkerAlthough for this small example setting up LLVM-style RTTI seems like a lot
240*9880d681SAndroid Build Coastguard Workerof "boilerplate", if your classes are doing anything interesting then this
241*9880d681SAndroid Build Coastguard Workerwill end up being a tiny fraction of the code.
242*9880d681SAndroid Build Coastguard Worker
243*9880d681SAndroid Build Coastguard WorkerConcrete Bases and Deeper Hierarchies
244*9880d681SAndroid Build Coastguard Worker=====================================
245*9880d681SAndroid Build Coastguard Worker
246*9880d681SAndroid Build Coastguard WorkerFor concrete bases (i.e. non-abstract interior nodes of the inheritance
247*9880d681SAndroid Build Coastguard Workertree), the ``Kind`` check inside ``classof`` needs to be a bit more
248*9880d681SAndroid Build Coastguard Workercomplicated. The situation differs from the example above in that
249*9880d681SAndroid Build Coastguard Worker
250*9880d681SAndroid Build Coastguard Worker* Since the class is concrete, it must itself have an entry in the ``Kind``
251*9880d681SAndroid Build Coastguard Worker  enum because it is possible to have objects with this class as a dynamic
252*9880d681SAndroid Build Coastguard Worker  type.
253*9880d681SAndroid Build Coastguard Worker
254*9880d681SAndroid Build Coastguard Worker* Since the class has children, the check inside ``classof`` must take them
255*9880d681SAndroid Build Coastguard Worker  into account.
256*9880d681SAndroid Build Coastguard Worker
257*9880d681SAndroid Build Coastguard WorkerSay that ``SpecialSquare`` and ``OtherSpecialSquare`` derive
258*9880d681SAndroid Build Coastguard Workerfrom ``Square``, and so ``ShapeKind`` becomes:
259*9880d681SAndroid Build Coastguard Worker
260*9880d681SAndroid Build Coastguard Worker.. code-block:: c++
261*9880d681SAndroid Build Coastguard Worker
262*9880d681SAndroid Build Coastguard Worker    enum ShapeKind {
263*9880d681SAndroid Build Coastguard Worker      SK_Square,
264*9880d681SAndroid Build Coastguard Worker   +  SK_SpecialSquare,
265*9880d681SAndroid Build Coastguard Worker   +  SK_OtherSpecialSquare,
266*9880d681SAndroid Build Coastguard Worker      SK_Circle
267*9880d681SAndroid Build Coastguard Worker    }
268*9880d681SAndroid Build Coastguard Worker
269*9880d681SAndroid Build Coastguard WorkerThen in ``Square``, we would need to modify the ``classof`` like so:
270*9880d681SAndroid Build Coastguard Worker
271*9880d681SAndroid Build Coastguard Worker.. code-block:: c++
272*9880d681SAndroid Build Coastguard Worker
273*9880d681SAndroid Build Coastguard Worker   -  static bool classof(const Shape *S) {
274*9880d681SAndroid Build Coastguard Worker   -    return S->getKind() == SK_Square;
275*9880d681SAndroid Build Coastguard Worker   -  }
276*9880d681SAndroid Build Coastguard Worker   +  static bool classof(const Shape *S) {
277*9880d681SAndroid Build Coastguard Worker   +    return S->getKind() >= SK_Square &&
278*9880d681SAndroid Build Coastguard Worker   +           S->getKind() <= SK_OtherSpecialSquare;
279*9880d681SAndroid Build Coastguard Worker   +  }
280*9880d681SAndroid Build Coastguard Worker
281*9880d681SAndroid Build Coastguard WorkerThe reason that we need to test a range like this instead of just equality
282*9880d681SAndroid Build Coastguard Workeris that both ``SpecialSquare`` and ``OtherSpecialSquare`` "is-a"
283*9880d681SAndroid Build Coastguard Worker``Square``, and so ``classof`` needs to return ``true`` for them.
284*9880d681SAndroid Build Coastguard Worker
285*9880d681SAndroid Build Coastguard WorkerThis approach can be made to scale to arbitrarily deep hierarchies. The
286*9880d681SAndroid Build Coastguard Workertrick is that you arrange the enum values so that they correspond to a
287*9880d681SAndroid Build Coastguard Workerpreorder traversal of the class hierarchy tree. With that arrangement, all
288*9880d681SAndroid Build Coastguard Workersubclass tests can be done with two comparisons as shown above. If you just
289*9880d681SAndroid Build Coastguard Workerlist the class hierarchy like a list of bullet points, you'll get the
290*9880d681SAndroid Build Coastguard Workerordering right::
291*9880d681SAndroid Build Coastguard Worker
292*9880d681SAndroid Build Coastguard Worker   | Shape
293*9880d681SAndroid Build Coastguard Worker     | Square
294*9880d681SAndroid Build Coastguard Worker       | SpecialSquare
295*9880d681SAndroid Build Coastguard Worker       | OtherSpecialSquare
296*9880d681SAndroid Build Coastguard Worker     | Circle
297*9880d681SAndroid Build Coastguard Worker
298*9880d681SAndroid Build Coastguard WorkerA Bug to be Aware Of
299*9880d681SAndroid Build Coastguard Worker--------------------
300*9880d681SAndroid Build Coastguard Worker
301*9880d681SAndroid Build Coastguard WorkerThe example just given opens the door to bugs where the ``classof``\s are
302*9880d681SAndroid Build Coastguard Workernot updated to match the ``Kind`` enum when adding (or removing) classes to
303*9880d681SAndroid Build Coastguard Worker(from) the hierarchy.
304*9880d681SAndroid Build Coastguard Worker
305*9880d681SAndroid Build Coastguard WorkerContinuing the example above, suppose we add a ``SomewhatSpecialSquare`` as
306*9880d681SAndroid Build Coastguard Workera subclass of ``Square``, and update the ``ShapeKind`` enum like so:
307*9880d681SAndroid Build Coastguard Worker
308*9880d681SAndroid Build Coastguard Worker.. code-block:: c++
309*9880d681SAndroid Build Coastguard Worker
310*9880d681SAndroid Build Coastguard Worker    enum ShapeKind {
311*9880d681SAndroid Build Coastguard Worker      SK_Square,
312*9880d681SAndroid Build Coastguard Worker      SK_SpecialSquare,
313*9880d681SAndroid Build Coastguard Worker      SK_OtherSpecialSquare,
314*9880d681SAndroid Build Coastguard Worker   +  SK_SomewhatSpecialSquare,
315*9880d681SAndroid Build Coastguard Worker      SK_Circle
316*9880d681SAndroid Build Coastguard Worker    }
317*9880d681SAndroid Build Coastguard Worker
318*9880d681SAndroid Build Coastguard WorkerNow, suppose that we forget to update ``Square::classof()``, so it still
319*9880d681SAndroid Build Coastguard Workerlooks like:
320*9880d681SAndroid Build Coastguard Worker
321*9880d681SAndroid Build Coastguard Worker.. code-block:: c++
322*9880d681SAndroid Build Coastguard Worker
323*9880d681SAndroid Build Coastguard Worker   static bool classof(const Shape *S) {
324*9880d681SAndroid Build Coastguard Worker     // BUG: Returns false when S->getKind() == SK_SomewhatSpecialSquare,
325*9880d681SAndroid Build Coastguard Worker     // even though SomewhatSpecialSquare "is a" Square.
326*9880d681SAndroid Build Coastguard Worker     return S->getKind() >= SK_Square &&
327*9880d681SAndroid Build Coastguard Worker            S->getKind() <= SK_OtherSpecialSquare;
328*9880d681SAndroid Build Coastguard Worker   }
329*9880d681SAndroid Build Coastguard Worker
330*9880d681SAndroid Build Coastguard WorkerAs the comment indicates, this code contains a bug. A straightforward and
331*9880d681SAndroid Build Coastguard Workernon-clever way to avoid this is to introduce an explicit ``SK_LastSquare``
332*9880d681SAndroid Build Coastguard Workerentry in the enum when adding the first subclass(es). For example, we could
333*9880d681SAndroid Build Coastguard Workerrewrite the example at the beginning of `Concrete Bases and Deeper
334*9880d681SAndroid Build Coastguard WorkerHierarchies`_ as:
335*9880d681SAndroid Build Coastguard Worker
336*9880d681SAndroid Build Coastguard Worker.. code-block:: c++
337*9880d681SAndroid Build Coastguard Worker
338*9880d681SAndroid Build Coastguard Worker    enum ShapeKind {
339*9880d681SAndroid Build Coastguard Worker      SK_Square,
340*9880d681SAndroid Build Coastguard Worker   +  SK_SpecialSquare,
341*9880d681SAndroid Build Coastguard Worker   +  SK_OtherSpecialSquare,
342*9880d681SAndroid Build Coastguard Worker   +  SK_LastSquare,
343*9880d681SAndroid Build Coastguard Worker      SK_Circle
344*9880d681SAndroid Build Coastguard Worker    }
345*9880d681SAndroid Build Coastguard Worker   ...
346*9880d681SAndroid Build Coastguard Worker   // Square::classof()
347*9880d681SAndroid Build Coastguard Worker   -  static bool classof(const Shape *S) {
348*9880d681SAndroid Build Coastguard Worker   -    return S->getKind() == SK_Square;
349*9880d681SAndroid Build Coastguard Worker   -  }
350*9880d681SAndroid Build Coastguard Worker   +  static bool classof(const Shape *S) {
351*9880d681SAndroid Build Coastguard Worker   +    return S->getKind() >= SK_Square &&
352*9880d681SAndroid Build Coastguard Worker   +           S->getKind() <= SK_LastSquare;
353*9880d681SAndroid Build Coastguard Worker   +  }
354*9880d681SAndroid Build Coastguard Worker
355*9880d681SAndroid Build Coastguard WorkerThen, adding new subclasses is easy:
356*9880d681SAndroid Build Coastguard Worker
357*9880d681SAndroid Build Coastguard Worker.. code-block:: c++
358*9880d681SAndroid Build Coastguard Worker
359*9880d681SAndroid Build Coastguard Worker    enum ShapeKind {
360*9880d681SAndroid Build Coastguard Worker      SK_Square,
361*9880d681SAndroid Build Coastguard Worker      SK_SpecialSquare,
362*9880d681SAndroid Build Coastguard Worker      SK_OtherSpecialSquare,
363*9880d681SAndroid Build Coastguard Worker   +  SK_SomewhatSpecialSquare,
364*9880d681SAndroid Build Coastguard Worker      SK_LastSquare,
365*9880d681SAndroid Build Coastguard Worker      SK_Circle
366*9880d681SAndroid Build Coastguard Worker    }
367*9880d681SAndroid Build Coastguard Worker
368*9880d681SAndroid Build Coastguard WorkerNotice that ``Square::classof`` does not need to be changed.
369*9880d681SAndroid Build Coastguard Worker
370*9880d681SAndroid Build Coastguard Worker.. _classof-contract:
371*9880d681SAndroid Build Coastguard Worker
372*9880d681SAndroid Build Coastguard WorkerThe Contract of ``classof``
373*9880d681SAndroid Build Coastguard Worker---------------------------
374*9880d681SAndroid Build Coastguard Worker
375*9880d681SAndroid Build Coastguard WorkerTo be more precise, let ``classof`` be inside a class ``C``.  Then the
376*9880d681SAndroid Build Coastguard Workercontract for ``classof`` is "return ``true`` if the dynamic type of the
377*9880d681SAndroid Build Coastguard Workerargument is-a ``C``".  As long as your implementation fulfills this
378*9880d681SAndroid Build Coastguard Workercontract, you can tweak and optimize it as much as you want.
379*9880d681SAndroid Build Coastguard Worker
380*9880d681SAndroid Build Coastguard WorkerFor example, LLVM-style RTTI can work fine in the presence of
381*9880d681SAndroid Build Coastguard Workermultiple-inheritance by defining an appropriate ``classof``.
382*9880d681SAndroid Build Coastguard WorkerAn example of this in practice is
383*9880d681SAndroid Build Coastguard Worker`Decl <http://clang.llvm.org/doxygen/classclang_1_1Decl.html>`_ vs.
384*9880d681SAndroid Build Coastguard Worker`DeclContext <http://clang.llvm.org/doxygen/classclang_1_1DeclContext.html>`_
385*9880d681SAndroid Build Coastguard Workerinside Clang.
386*9880d681SAndroid Build Coastguard WorkerThe ``Decl`` hierarchy is done very similarly to the example setup
387*9880d681SAndroid Build Coastguard Workerdemonstrated in this tutorial.
388*9880d681SAndroid Build Coastguard WorkerThe key part is how to then incorporate ``DeclContext``: all that is needed
389*9880d681SAndroid Build Coastguard Workeris in ``bool DeclContext::classof(const Decl *)``, which asks the question
390*9880d681SAndroid Build Coastguard Worker"Given a ``Decl``, how can I determine if it is-a ``DeclContext``?".
391*9880d681SAndroid Build Coastguard WorkerIt answers this with a simple switch over the set of ``Decl`` "kinds", and
392*9880d681SAndroid Build Coastguard Workerreturning true for ones that are known to be ``DeclContext``'s.
393*9880d681SAndroid Build Coastguard Worker
394*9880d681SAndroid Build Coastguard Worker.. TODO::
395*9880d681SAndroid Build Coastguard Worker
396*9880d681SAndroid Build Coastguard Worker   Touch on some of the more advanced features, like ``isa_impl`` and
397*9880d681SAndroid Build Coastguard Worker   ``simplify_type``. However, those two need reference documentation in
398*9880d681SAndroid Build Coastguard Worker   the form of doxygen comments as well. We need the doxygen so that we can
399*9880d681SAndroid Build Coastguard Worker   say "for full details, see http://llvm.org/doxygen/..."
400*9880d681SAndroid Build Coastguard Worker
401*9880d681SAndroid Build Coastguard WorkerRules of Thumb
402*9880d681SAndroid Build Coastguard Worker==============
403*9880d681SAndroid Build Coastguard Worker
404*9880d681SAndroid Build Coastguard Worker#. The ``Kind`` enum should have one entry per concrete class, ordered
405*9880d681SAndroid Build Coastguard Worker   according to a preorder traversal of the inheritance tree.
406*9880d681SAndroid Build Coastguard Worker#. The argument to ``classof`` should be a ``const Base *``, where ``Base``
407*9880d681SAndroid Build Coastguard Worker   is some ancestor in the inheritance hierarchy. The argument should
408*9880d681SAndroid Build Coastguard Worker   *never* be a derived class or the class itself: the template machinery
409*9880d681SAndroid Build Coastguard Worker   for ``isa<>`` already handles this case and optimizes it.
410*9880d681SAndroid Build Coastguard Worker#. For each class in the hierarchy that has no children, implement a
411*9880d681SAndroid Build Coastguard Worker   ``classof`` that checks only against its ``Kind``.
412*9880d681SAndroid Build Coastguard Worker#. For each class in the hierarchy that has children, implement a
413*9880d681SAndroid Build Coastguard Worker   ``classof`` that checks a range of the first child's ``Kind`` and the
414*9880d681SAndroid Build Coastguard Worker   last child's ``Kind``.
415