summaryrefslogtreecommitdiff
path: root/docs/HowToSetUpLLVMStyleRTTI.rst
diff options
context:
space:
mode:
authorSean Silva <silvas@purdue.edu>2012-10-11 23:30:41 +0000
committerSean Silva <silvas@purdue.edu>2012-10-11 23:30:41 +0000
commit8a6538cd6117c5a7b1efb5c2e9cf172a5556c23e (patch)
tree552ea873d1ae8608d96e550c071e79042e8b1d66 /docs/HowToSetUpLLVMStyleRTTI.rst
parent8b8fa7b2f403ae2f342413239c4151e075022c97 (diff)
docs: Update HowToSetUpLLVMStyleRTTI.
Recent changes to isa<>/dyn_cast<> have made unnecessary those classof() of the form: static bool classof(const Foo *) { return true; } Accordingly, remove mention of such classof() from the documentation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165766 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'docs/HowToSetUpLLVMStyleRTTI.rst')
-rw-r--r--docs/HowToSetUpLLVMStyleRTTI.rst60
1 files changed, 39 insertions, 21 deletions
diff --git a/docs/HowToSetUpLLVMStyleRTTI.rst b/docs/HowToSetUpLLVMStyleRTTI.rst
index b5c1b78afeb..4c96c95a76f 100644
--- a/docs/HowToSetUpLLVMStyleRTTI.rst
+++ b/docs/HowToSetUpLLVMStyleRTTI.rst
@@ -174,8 +174,6 @@ steps:
Shape(ShapeKind K) : Kind(K) {}
virtual double computeArea() = 0;
- +
- + static bool classof(const Shape *) { return true; }
};
class Square : public Shape {
@@ -184,7 +182,6 @@ steps:
Square(double S) : Shape(SquareKind), SideLength(S) {}
double computeArea() /* override */;
+
- + static bool classof(const Square *) { return true; }
+ static bool classof(const Shape *S) {
+ return S->getKind() == SquareKind;
+ }
@@ -196,31 +193,43 @@ steps:
Circle(double R) : Shape(CircleKind), Radius(R) {}
double computeArea() /* override */;
+
- + static bool classof(const Circle *) { return true; }
+ static bool classof(const Shape *S) {
+ return S->getKind() == CircleKind;
+ }
};
- Basically, the job of ``classof`` is to return ``true`` if its argument
- is of the enclosing class's type. As you can see, there are two general
- overloads of ``classof`` in use here.
+ The job of ``classof`` is to dynamically determine whether an object of
+ a base class is in fact of a particular derived class. The argument to
+ ``classof`` should always be an *ancestor* class because the
+ implementation has logic to allow and optimize away
+ upcasts/up-``isa<>``'s automatically. It is as though every class
+ ``Foo`` automatically has a ``classof`` like:
+
+ .. code-block:: c++
+
+ class Foo {
+ [...]
+ static bool classof(const Foo *) { return true; }
+ [...]
+ };
+
+ In order to downcast a type ``Base`` to a type ``Derived``, there needs
+ to be a ``classof`` in ``Derived`` which will accept an object of type
+ ``Base``.
- #. The first, which just returns ``true``, means that if we know that the
- argument of the cast is of the enclosing type *at compile time*, then
- we don't need to bother to check anything since we already know that
- the type is convertible. This is an optimization for the case that we
- statically know the conversion is OK.
+ To be concrete, in the following code:
- #. The other overload takes a pointer to an object of the base of the
- class hierarchy: this is the "general case" of the cast. We need to
- check the ``Kind`` to dynamically decide if the argument is of (or
- derived from) the enclosing type.
+ .. code-block:: c++
+
+ Shape *S = ...;
+ if (isa<Circle>(S)) {
+ /* do something ... */
+ }
- To be more precise, let ``classof`` be inside a class ``C``. Then the
- contract for ``classof`` is "return ``true`` if the argument is-a
- ``C``". As long as your implementation fulfills this contract, you can
- tweak and optimize it as much as you want.
+ The code of ``isa<>`` will eventually boil down---after template
+ instantiation and some other machinery---to a check roughly like
+ ``Circle::classof(S)``. For more information, see
+ :ref:`classof-contract`.
Although for this small example setting up LLVM-style RTTI seems like a lot
of "boilerplate", if your classes are doing anything interesting then this
@@ -247,7 +256,6 @@ Then in ``Square``, we would need to modify the ``classof`` like so:
.. code-block:: c++
- static bool classof(const Square *) { return true; }
- static bool classof(const Shape *S) {
- return S->getKind() == SquareKind;
- }
@@ -273,6 +281,16 @@ ordering right::
| OtherSpecialSquare
| Circle
+.. _classof-contract:
+
+The Contract of ``classof``
+---------------------------
+
+To be more precise, let ``classof`` be inside a class ``C``. Then the
+contract for ``classof`` is "return ``true`` if the dynamic type of the
+argument is-a ``C``". As long as your implementation fulfills this
+contract, you can tweak and optimize it as much as you want.
+
.. TODO::
Touch on some of the more advanced features, like ``isa_impl`` and