llvm.org GIT mirror llvm / 4057399
docs: Improve HowToSetUpLLVMStyleRTTI. * Fix confusing explanation regarding abstract classes. * Clarify auto-upcasting and why `Shape` doesn't need a `classof()`. * Add section `Rules of Thumb` with some quick summary tips. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165768 91177308-0d34-0410-b5e6-96231b3b80d8 Sean Silva 6 years ago
1 changed file(s) with 60 addition(s) and 27 deletion(s). Raw diff Collapse all Expand all
6464
6565 #include "llvm/Support/Casting.h"
6666
67
6867 #. In the base class, introduce an enum which discriminates all of the
69 different classes in the hierarchy, and stash the enum value somewhere in
70 the base class.
68 different concrete classes in the hierarchy, and stash the enum value
69 somewhere in the base class.
7170
7271 Here is the code after introducing this change:
7372
102101 You might wonder why the ``Kind`` enum doesn't have an entry for
103102 ``Shape``. The reason for this is that since ``Shape`` is abstract
104103 (``computeArea() = 0;``), you will never actually have non-derived
105 instances of exactly that class (only subclasses). See `Concrete Bases
104 instances of exactly that class (only subclasses). See `Concrete Bases
106105 and Deeper Hierarchies`_ for information on how to deal with
107106 non-abstract bases. It's worth mentioning here that unlike
108107 ``dynamic_cast<>``, LLVM-style RTTI can be used (and is often used) for
198197 };
199198
200199 The job of ``classof`` is to dynamically determine whether an object of
201 a base class is in fact of a particular derived class. The argument to
202 ``classof`` should always be an *ancestor* class because the
203 implementation has logic to allow and optimize away
204 upcasts/up-``isa<>``'s automatically. It is as though every class
205 ``Foo`` automatically has a ``classof`` like:
206
207 .. code-block:: c++
208
209 class Foo {
210 [...]
211 static bool classof(const Foo *) { return true; }
212 [...]
213 };
214
215 In order to downcast a type ``Base`` to a type ``Derived``, there needs
216 to be a ``classof`` in ``Derived`` which will accept an object of type
217 ``Base``.
218
219 To be concrete, in the following code:
200 a base class is in fact of a particular derived class. In order to
201 downcast a type ``Base`` to a type ``Derived``, there needs to be a
202 ``classof`` in ``Derived`` which will accept an object of type ``Base``.
203
204 To be concrete, consider the following code:
220205
221206 .. code-block:: c++
222207
225210 /* do something ... */
226211 }
227212
228 The code of ``isa<>`` will eventually boil down---after template
229 instantiation and some other machinery---to a check roughly like
230 ``Circle::classof(S)``. For more information, see
213 The code of the ``isa<>`` test in this code will eventually boil
214 down---after template instantiation and some other machinery---to a
215 check roughly like ``Circle::classof(S)``. For more information, see
231216 :ref:`classof-contract`.
217
218 The argument to ``classof`` should always be an *ancestor* class because
219 the implementation has logic to allow and optimize away
220 upcasts/up-``isa<>``'s automatically. It is as though every class
221 ``Foo`` automatically has a ``classof`` like:
222
223 .. code-block:: c++
224
225 class Foo {
226 [...]
227 template
228 static bool classof(const T *,
229 ::llvm::enable_if_c<
230 ::llvm::is_base_of::value
231 >::type* = 0) { return true; }
232 [...]
233 };
234
235 Note that this is the reason that we did not need to introduce a
236 ``classof`` into ``Shape``: all relevant classes derive from ``Shape``,
237 and ``Shape`` itself is abstract (has no entry in the ``Kind`` enum),
238 so this notional inferred ``classof`` is all we need. See `Concrete
239 Bases and Deeper Hierarchies`_ for more information about how to extend
240 this example to more general hierarchies.
232241
233242 Although for this small example setting up LLVM-style RTTI seems like a lot
234243 of "boilerplate", if your classes are doing anything interesting then this
239248
240249 For concrete bases (i.e. non-abstract interior nodes of the inheritance
241250 tree), the ``Kind`` check inside ``classof`` needs to be a bit more
242 complicated. Say that ``SpecialSquare`` and ``OtherSpecialSquare`` derive
251 complicated. The situation differs from the example above in that
252
253 * Since the class is concrete, it must itself have an entry in the ``Kind``
254 enum because it is possible to have objects with this class as a dynamic
255 type.
256
257 * Since the class has children, the check inside ``classof`` must take them
258 into account.
259
260 Say that ``SpecialSquare`` and ``OtherSpecialSquare`` derive
243261 from ``Square``, and so ``ShapeKind`` becomes:
244262
245263 .. code-block:: c++
296314 ``simplify_type``. However, those two need reference documentation in
297315 the form of doxygen comments as well. We need the doxygen so that we can
298316 say "for full details, see http://llvm.org/doxygen/..."
317
318 Rules of Thumb
319 ==============
320
321 #. The ``Kind`` enum should have one entry per concrete class, ordered
322 according to a preorder traversal of the inheritance tree.
323 #. The argument to ``classof`` should be a ``const Base *``, where ``Base``
324 is some ancestor in the inheritance hierarchy. The argument should
325 *never* be a derived class or the class itself: the template machinery
326 for ``isa<>`` already handles this case and optimizes it.
327 #. For each class in the hierarchy that has no children, implement a
328 ``classof`` that checks only against its ``Kind``.
329 #. For each class in the hierarchy that has children, implement a
330 ``classof`` that checks a range of the first child's ``Kind`` and the
331 last child's ``Kind``.