[docs] Improvements to CMake.rst
[oota-llvm.git] / docs / HowToSetUpLLVMStyleRTTI.rst
index 4c96c95a76f8123b2b314cbb9ea9a07820de57e8..38929948590916ecc1198980e012abe21631295e 100644 (file)
@@ -1,11 +1,7 @@
-.. _how-to-set-up-llvm-style-rtti:
-
 ======================================================
 How to set up LLVM-style RTTI for your class hierarchy
 ======================================================
 
-.. sectionauthor:: Sean Silva <silvas@purdue.edu>
-
 .. contents::
 
 Background
@@ -44,14 +40,14 @@ RTTI for this class hierarchy:
      double SideLength;
    public:
      Square(double S) : SideLength(S) {}
-     double computeArea() /* override */;
+     double computeArea() override;
    };
 
    class Circle : public Shape {
      double Radius;
    public:
      Circle(double R) : Radius(R) {}
-     double computeArea() /* override */;
+     double computeArea() override;
    };
 
 The most basic working setup for LLVM-style RTTI requires the following
@@ -65,10 +61,9 @@ steps:
 
       #include "llvm/Support/Casting.h"
 
-
 #. In the base class, introduce an enum which discriminates all of the
-   different classes in the hierarchy, and stash the enum value somewhere in
-   the base class.
+   different concrete classes in the hierarchy, and stash the enum value
+   somewhere in the base class.
 
    Here is the code after introducing this change:
 
@@ -78,8 +73,8 @@ steps:
        public:
       +  /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
       +  enum ShapeKind {
-      +    SquareKind,
-      +    CircleKind
+      +    SK_Square,
+      +    SK_Circle
       +  };
       +private:
       +  const ShapeKind Kind;
@@ -103,7 +98,7 @@ steps:
    You might wonder why the ``Kind`` enum doesn't have an entry for
    ``Shape``. The reason for this is that since ``Shape`` is abstract
    (``computeArea() = 0;``), you will never actually have non-derived
-   instances of exactly that class (only subclasses).  See `Concrete Bases
+   instances of exactly that class (only subclasses). See `Concrete Bases
    and Deeper Hierarchies`_ for information on how to deal with
    non-abstract bases. It's worth mentioning here that unlike
    ``dynamic_cast<>``, LLVM-style RTTI can be used (and is often used) for
@@ -122,8 +117,8 @@ steps:
        public:
          /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
          enum ShapeKind {
-           SquareKind,
-           CircleKind
+           SK_Square,
+           SK_Circle
          };
        private:
          const ShapeKind Kind;
@@ -139,16 +134,16 @@ steps:
          double SideLength;
        public:
       -  Square(double S) : SideLength(S) {}
-      +  Square(double S) : Shape(SquareKind), SideLength(S) {}
-         double computeArea() /* override */;
+      +  Square(double S) : Shape(SK_Square), SideLength(S) {}
+         double computeArea() override;
        };
 
        class Circle : public Shape {
          double Radius;
        public:
       -  Circle(double R) : Radius(R) {}
-      +  Circle(double R) : Shape(CircleKind), Radius(R) {}
-         double computeArea() /* override */;
+      +  Circle(double R) : Shape(SK_Circle), Radius(R) {}
+         double computeArea() override;
        };
 
 #. Finally, you need to inform LLVM's RTTI templates how to dynamically
@@ -164,8 +159,8 @@ steps:
        public:
          /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
          enum ShapeKind {
-           SquareKind,
-           CircleKind
+           SK_Square,
+           SK_Circle
          };
        private:
          const ShapeKind Kind;
@@ -179,45 +174,31 @@ steps:
        class Square : public Shape {
          double SideLength;
        public:
-         Square(double S) : Shape(SquareKind), SideLength(S) {}
-         double computeArea() /* override */;
+         Square(double S) : Shape(SK_Square), SideLength(S) {}
+         double computeArea() override;
       +
       +  static bool classof(const Shape *S) {
-      +    return S->getKind() == SquareKind;
+      +    return S->getKind() == SK_Square;
       +  }
        };
 
        class Circle : public Shape {
          double Radius;
        public:
-         Circle(double R) : Shape(CircleKind), Radius(R) {}
-         double computeArea() /* override */;
+         Circle(double R) : Shape(SK_Circle), Radius(R) {}
+         double computeArea() override;
       +
       +  static bool classof(const Shape *S) {
-      +    return S->getKind() == CircleKind;
+      +    return S->getKind() == SK_Circle;
       +  }
        };
 
    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:
+   a base class is in fact of a particular derived class.  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``.
 
-   .. 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``.
-
-   To be concrete, in the following code:
+   To be concrete, consider the following code:
 
    .. code-block:: c++
 
@@ -226,11 +207,35 @@ steps:
         /* do something ... */
       }
 
-   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
+   The code of the ``isa<>`` test in this code 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`.
 
+   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 {
+        [...]
+        template <class T>
+        static bool classof(const T *,
+                            ::std::enable_if<
+                              ::std::is_base_of<Foo, T>::value
+                            >::type* = 0) { return true; }
+        [...]
+      };
+
+   Note that this is the reason that we did not need to introduce a
+   ``classof`` into ``Shape``: all relevant classes derive from ``Shape``,
+   and ``Shape`` itself is abstract (has no entry in the ``Kind`` enum),
+   so this notional inferred ``classof`` is all we need. See `Concrete
+   Bases and Deeper Hierarchies`_ for more information about how to extend
+   this example to more general hierarchies.
+
 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
 will end up being a tiny fraction of the code.
@@ -240,16 +245,25 @@ Concrete Bases and Deeper Hierarchies
 
 For concrete bases (i.e. non-abstract interior nodes of the inheritance
 tree), the ``Kind`` check inside ``classof`` needs to be a bit more
-complicated. Say that ``SpecialSquare`` and ``OtherSpecialSquare`` derive
+complicated. The situation differs from the example above in that
+
+* Since the class is concrete, it must itself have an entry in the ``Kind``
+  enum because it is possible to have objects with this class as a dynamic
+  type.
+
+* Since the class has children, the check inside ``classof`` must take them
+  into account.
+
+Say that ``SpecialSquare`` and ``OtherSpecialSquare`` derive
 from ``Square``, and so ``ShapeKind`` becomes:
 
 .. code-block:: c++
 
     enum ShapeKind {
-      SquareKind,
-   +  SpecialSquareKind,
-   +  OtherSpecialSquareKind,
-      CircleKind
+      SK_Square,
+   +  SK_SpecialSquare,
+   +  SK_OtherSpecialSquare,
+      SK_Circle
     }
 
 Then in ``Square``, we would need to modify the ``classof`` like so:
@@ -257,11 +271,11 @@ Then in ``Square``, we would need to modify the ``classof`` like so:
 .. code-block:: c++
 
    -  static bool classof(const Shape *S) {
-   -    return S->getKind() == SquareKind;
+   -    return S->getKind() == SK_Square;
    -  }
    +  static bool classof(const Shape *S) {
-   +    return S->getKind() >= SquareKind &&
-   +           S->getKind() <= OtherSpecialSquareKind;
+   +    return S->getKind() >= SK_Square &&
+   +           S->getKind() <= SK_OtherSpecialSquare;
    +  }
 
 The reason that we need to test a range like this instead of just equality
@@ -281,6 +295,78 @@ ordering right::
        | OtherSpecialSquare
      | Circle
 
+A Bug to be Aware Of
+--------------------
+
+The example just given opens the door to bugs where the ``classof``\s are
+not updated to match the ``Kind`` enum when adding (or removing) classes to
+(from) the hierarchy.
+
+Continuing the example above, suppose we add a ``SomewhatSpecialSquare`` as
+a subclass of ``Square``, and update the ``ShapeKind`` enum like so:
+
+.. code-block:: c++
+
+    enum ShapeKind {
+      SK_Square,
+      SK_SpecialSquare,
+      SK_OtherSpecialSquare,
+   +  SK_SomewhatSpecialSquare,
+      SK_Circle
+    }
+
+Now, suppose that we forget to update ``Square::classof()``, so it still
+looks like:
+
+.. code-block:: c++
+
+   static bool classof(const Shape *S) {
+     // BUG: Returns false when S->getKind() == SK_SomewhatSpecialSquare,
+     // even though SomewhatSpecialSquare "is a" Square.
+     return S->getKind() >= SK_Square &&
+            S->getKind() <= SK_OtherSpecialSquare;
+   }
+
+As the comment indicates, this code contains a bug. A straightforward and
+non-clever way to avoid this is to introduce an explicit ``SK_LastSquare``
+entry in the enum when adding the first subclass(es). For example, we could
+rewrite the example at the beginning of `Concrete Bases and Deeper
+Hierarchies`_ as:
+
+.. code-block:: c++
+
+    enum ShapeKind {
+      SK_Square,
+   +  SK_SpecialSquare,
+   +  SK_OtherSpecialSquare,
+   +  SK_LastSquare,
+      SK_Circle
+    }
+   ...
+   // Square::classof()
+   -  static bool classof(const Shape *S) {
+   -    return S->getKind() == SK_Square;
+   -  }
+   +  static bool classof(const Shape *S) {
+   +    return S->getKind() >= SK_Square &&
+   +           S->getKind() <= SK_LastSquare;
+   +  }
+
+Then, adding new subclasses is easy:
+
+.. code-block:: c++
+
+    enum ShapeKind {
+      SK_Square,
+      SK_SpecialSquare,
+      SK_OtherSpecialSquare,
+   +  SK_SomewhatSpecialSquare,
+      SK_LastSquare,
+      SK_Circle
+    }
+
+Notice that ``Square::classof`` does not need to be changed.
+
 .. _classof-contract:
 
 The Contract of ``classof``
@@ -291,9 +377,38 @@ 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.
 
+For example, LLVM-style RTTI can work fine in the presence of
+multiple-inheritance by defining an appropriate ``classof``.
+An example of this in practice is
+`Decl <http://clang.llvm.org/doxygen/classclang_1_1Decl.html>`_ vs.
+`DeclContext <http://clang.llvm.org/doxygen/classclang_1_1DeclContext.html>`_
+inside Clang.
+The ``Decl`` hierarchy is done very similarly to the example setup
+demonstrated in this tutorial.
+The key part is how to then incorporate ``DeclContext``: all that is needed
+is in ``bool DeclContext::classof(const Decl *)``, which asks the question
+"Given a ``Decl``, how can I determine if it is-a ``DeclContext``?".
+It answers this with a simple switch over the set of ``Decl`` "kinds", and
+returning true for ones that are known to be ``DeclContext``'s.
+
 .. TODO::
 
    Touch on some of the more advanced features, like ``isa_impl`` and
    ``simplify_type``. However, those two need reference documentation in
    the form of doxygen comments as well. We need the doxygen so that we can
    say "for full details, see http://llvm.org/doxygen/..."
+
+Rules of Thumb
+==============
+
+#. The ``Kind`` enum should have one entry per concrete class, ordered
+   according to a preorder traversal of the inheritance tree.
+#. The argument to ``classof`` should be a ``const Base *``, where ``Base``
+   is some ancestor in the inheritance hierarchy. The argument should
+   *never* be a derived class or the class itself: the template machinery
+   for ``isa<>`` already handles this case and optimizes it.
+#. For each class in the hierarchy that has no children, implement a
+   ``classof`` that checks only against its ``Kind``.
+#. For each class in the hierarchy that has children, implement a
+   ``classof`` that checks a range of the first child's ``Kind`` and the
+   last child's ``Kind``.