diff --git a/Control/AthenaKernel/AthenaKernel/AthenaKernelDict.h b/Control/AthenaKernel/AthenaKernel/AthenaKernelDict.h
index 931abac33f3704245ef7a2eb766ee2d2914a5c61..9755339bde2fe20471c535d495694146edea25a8 100644
--- a/Control/AthenaKernel/AthenaKernel/AthenaKernelDict.h
+++ b/Control/AthenaKernel/AthenaKernel/AthenaKernelDict.h
@@ -18,6 +18,7 @@
 #include "AthenaKernel/ILockable.h"
 #include "AthenaKernel/errorcheck.h"
 #include "AthenaKernel/ICutFlowSvc.h"
+#include "AthenaKernel/BaseInfo.h"
 
 #include "AthenaKernel/DsoDb.h"
 #include "AthenaKernel/AthDsoUtils.h"
diff --git a/Control/AthenaKernel/AthenaKernel/BaseInfo.h b/Control/AthenaKernel/AthenaKernel/BaseInfo.h
new file mode 100755
index 0000000000000000000000000000000000000000..f7bfbb93be524d5fe3eef7e086db7f1d2ac7829a
--- /dev/null
+++ b/Control/AthenaKernel/AthenaKernel/BaseInfo.h
@@ -0,0 +1,901 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: BaseInfo.h,v 1.11 2008-12-15 16:22:45 ssnyder Exp $
+
+/**
+ * @file  AthenaKernel/BaseInfo.h
+ * @author scott snyder
+ * @date Nov 2005
+ * @brief Provide an interface for finding inheritance information
+ *        at run time.
+ *
+ * The @a SG::BaseInfo<T> class provides an interface for finding
+ * inheritance information about class @a T.  In the absence of compiler
+ * support for reflection, the inheritance information must be
+ * explicitly declared.  This is done with the @a SG_BASE macro
+ * and friends.  To declare that class @a D derives from class @a B, use
+ *
+ *@code
+ *   struct B {};
+ *   struct D : public B {};
+ *   SG_BASE (D, B);
+ @endcode
+ *
+ * You can also use multiple inheritance with the @a SG_BASES2
+ * and @a SG_BASES3 macros:
+ *
+ *@code
+ *   struct B1 {};
+ *   struct B2 {};
+ *   struct B3 {};
+ *   struct D : public B1, public B2, public B3 {};
+ *   SG_BASES3 (D, B1, B2, B3);
+ @endcode
+ *
+ * Supporting more than three base classes requires (straightforward)
+ * changes to the code here.
+ *
+ * If any of the derivations are virtual, the corresponding
+ * base class should be within a @a SG_VIRTUAL macro:
+ *    
+ *@code
+ *   struct B1 {};
+ *   struct B2 {};
+ *   struct D : public B1, virtual public B2 {};
+ *   SG_BASES2 (D, B1, SG_VIRTUAL (B2));
+ @endcode
+ *
+ * Note that these macros will only work with non-templated types,
+ * or with specific instantiations of templated types.  If you want
+ * a templated @a SG_BASE, you'll need to declare the specialization
+ * yourself.  You should specialize @a SG::Bases<T>, defining types
+ * @a Base1, @a Base2, and @a Base3 (which should be @a SG::NoBase
+ * if not used).  Example:
+ *
+ *@code
+ *   template <class T> struct B {};
+ *   template <class T> struct D : public B<T> {};
+ *   namespace SG {
+ *     template <class T>
+ *     struct Bases<D<T> > {
+ *       typedef B<T> Base1;
+ *       typedef NoBase Base2;
+ *       typedef NoBase Base3;
+ *     };
+ *   }
+ @endcode
+ *
+ * Once these declarations are in place, what can you do with it?
+ * The interface is provided by the @a SG::BaseInfo<T> class.
+ * (This is a wrapper around a singleton, so it's not expensive
+ * to create instances of this class.)  You can specify the base
+ * classes either by the Gaudi class ID or by the C++ @c std::type_info.
+ * Of course, you'll only be able to get information by class ID
+ * if the classes actually have IDs defined.
+ *
+ * Here are the available methods of @a SG::BaseInfo<T>:
+ *
+ *@code
+ *   static bool is_base (CLID clid)
+ *   static bool is_base (const std::type_info& tinfo)
+ @endcode
+ *     Test to see if the type given by @a clid or @a tinfo
+ *     is a base of @a T.  Note that @a T counts as its own base.
+ *
+ *@code
+ *   static bool is_virtual (CLID clid)
+ *   static bool is_virtual (const std::type_info& tinfo)
+ @endcode
+ *     Test to see if the type given by @a clid or @a tinfo
+ *     is a virtual base of @a T.  This should always be @a false
+ *     for @a T itself.
+ *
+ *@code
+ *   static void* cast (T* p, CLID clid)
+ *   static void* cast (T* p, const std::type_info& tinfo)
+ @endcode
+ *     Cast a pointer from @a T* to a pointer to the type given
+ *     by @a clid or @a tinfo, which must be a base if @a T
+ *     known to @a BaseInfo.  The result is returned as a @a void*.
+ *     If the conversion cannot be done (because the target is not
+ *     known to be a base of @a T), then 0 is returned.
+ *
+ *@code
+ *   static T* castTo (void* p, CLID clid)
+ *   static T* castTo (void* p, const std::type_info& tinfo)
+ @endcode
+ *     Similar, except converts from a pointer to the type given by
+ *     @a clid or @a tinfo (which must be a base of @a T) to @a T*.
+ *     This involves a @a dynamic_cast.  Returns 0 if the cast fails.
+ *
+ *@code
+ *   static std::vector<CLID> get_bases ()
+ @endcode
+ *     Return all the known bases of @a T (that have class IDs).
+ *     @a T itself will be included in this list.
+ *
+ *@code
+ *   static std::vector<const std::type_info*> get_ti_bases ()
+ @endcode
+ *     Return all the known bases of @a T.
+ *     @a T itself will be included in this list.
+ *
+ * It is also possible to get a non-templated version of @c SG::BaseInfo<T>.
+ * This is called @c SG::BaseInfoBase.  These objects can be found using
+ * @c SG::BaseInfoBase::find, by either class ID or @c std::type_info
+ * (in order for this to work, the corresponding @c SG::BaseInfo<T> class
+ * must have been used somewhere in the program).  The interface
+ * of @c SG::BaseInfoBase is the same as @c SG::BaseInfo<T>, except
+ * that @c void* replaces @c T* in the @c cast methods.
+ *
+ * Initialization issues: We don't want to build the @c SG::BaseInfo<T>
+ * objects at static initialization time.  But we do need to remember
+ * which ones are available.  Thus, @c BaseInfoBase maintains a list
+ * of CLIDs and @c std::type_info's for which we may not have done
+ * initialization, along with a function to call to do the initialization.
+ * The initialization list is filled during static initialization.
+ * When we look for an instance, if we don't find one, we look in the
+ * initialization list; if there's a match there, we run the initialization
+ * and remove it from the list.
+ *
+ * Copy conversions: The conversion machinery above provides access to the
+ * standard C++ base<>derived conversions.  However, sometimes you'd like
+ * to allow additional conversions as well, for example between a
+ * vector<ElementLink<T> > and DataVector<T>.  For those cases,
+ * you can register a conversion function with the _source_ type
+ * that can initialize an instance of the _destination_ type
+ * from the _source_ type.  Then, when you try to retrieve the object
+ * from StoreGate with the _destination_ type, your conversion function
+ * will be called.
+ *
+ * Your conversion function should be the method @a convert of
+ * a class deriving from the @a SG::CopyConversion template;
+ * for example,
+ *
+ *@code
+ *   class MyCopyConversion
+ *     : public SG::CopyConversion<std::vector<ElementLink<MyType> >,
+ *                                 DataVector<MyType> >
+ *   {
+ *   public:
+ *     virtual void convert (const std::vector<ElementLink<MyType> >& src,
+ *                           DataVector<MyType>& dst) const
+ *     {
+ *       size_t sz = src.size();
+ *       if (dst.size() != sz) {
+ *         dst.clear (SG::VIEW_ELEMENTS);
+ *         dst.reserve (sz);
+ *         for (size_t i = 0; i < sz; i++) {
+ *           const MyType* p = *(src[i]).cptr(); 
+ *           dst.push_back (const_cast<MyType*> (p));
+ *         }
+ *       }
+ *     }
+ *   };
+ @endcode
+ *
+ * You then declare this using the macro
+ *
+ @code
+ *  SG_ADD_COPY_CONVERSION (std::vector<ElementLink<MyType> >,
+ *                          MyCopyConversion);
+ @endcode
+ *
+ * Copy conversions are enabled only for objects that have been marked as const.
+ */
+
+#ifndef ATHENAKERNEL_BASEINFO_H
+#define ATHENAKERNEL_BASEINFO_H
+
+#include "GaudiKernel/ClassID.h"
+#include <vector>
+#include <typeinfo>
+
+
+//===========================================================================
+// Macros used to declare base class information.
+//
+
+/**
+ * @brief Used to mark virtual derivation.
+ *        When using the @a SG_BASE macros below, use this in the case
+ *        of virtual derivation.  Example:
+ *
+ *@code
+ *   struct B1 {};
+ *   struct B2 {};
+ *   struct D : public B1, virtual public B2 {};
+ *   SG_BASES2 (D, B1, SG_VIRTUAL (B2));
+ @endcode
+ */
+#define SG_VIRTUAL(T) Virtual<T>
+
+
+/**
+ * @brief Declare that class @a D derives from class @a B.  Example:
+ *
+ *@code
+ *   struct B {};
+ *   struct D : public B {};
+ *   SG_BASE (D, B);
+ @endcode
+ */
+#define SG_BASE(D, B) SG_BASES1(D, B)
+
+
+/**
+ * @brief Declare that class @a D derives from class @a B.
+ *        This is the same as @a SG_BASE.  Example:
+ *
+ *@code
+ *   struct B {};
+ *   struct D : public B {};
+ *   SG_BASES1 (D, B);
+ @endcode
+ */
+#define SG_BASES1(D, B)          \
+  namespace SG        {          \
+    template<> struct Bases<D >{ \
+      typedef B Base1;           \
+      typedef NoBase Base2;      \
+      typedef NoBase Base3;      \
+    };                           \
+    template struct RegisterBaseInit<D >; \
+    template struct BaseInit<D >; \
+} struct sg_dummy // to swallow semicolon
+
+
+/**
+ * @brief Declare that class @a D derives from classes @a B1 and @a B2.
+ *        Example:
+ *
+ *@code
+ *   struct B1 {};
+ *   struct B2 {};
+ *   struct D : public B1, public B2 {};
+ *   SG_BASES2 (D, B1, B2);
+ @endcode
+ */
+#define SG_BASES2(D, B1, B2)     \
+  namespace SG        {          \
+    template<> struct Bases<D >{ \
+      typedef B1 Base1;          \
+      typedef B2 Base2;          \
+      typedef NoBase Base3;      \
+    };                           \
+    template struct RegisterBaseInit<D >; \
+    template struct BaseInit<D >; \
+} struct sg_dummy // to swallow semicolon
+
+
+/**
+ * @brief Declare that class @a D derives from classes @a B1, @a B2, and @a B3.
+ *        Example:
+ *
+ *@code
+ *   struct B1 {};
+ *   struct B2 {};
+ *   struct B3 {};
+ *   struct D : public B1, public B2, public B3 {};
+ *   SG_BASES3 (D, B1, B2, B3);
+ @endcode
+ */
+#define SG_BASES3(D, B1, B2, B3) \
+  namespace SG        {          \
+    template<> struct Bases<D >{ \
+      typedef B1 Base1;          \
+      typedef B2 Base2;          \
+      typedef B3 Base3;          \
+    };                           \
+    template struct RegisterBaseInit<D >; \
+    template struct BaseInit<D >; \
+} struct sg_dummy // to swallow semicolon
+
+
+
+/**
+ * @brief Add a new base class @c B to class @c D.
+ *
+ * Sometimes, the SG_BASE macro for a class isn't present in its header.
+ *
+ * One can try to put the appropriate SG_BASE macro somewhere else,
+ * but this doesn't always work: if the @c BaseInfoBase for @c D has
+ * already been created by the time the @c SG_BASE initialization
+ * runs, then that @c SG_BASE macro won't do anything.
+ *
+ * @c SG_ADD_BASE, however, will add a new base to an existing @c BaseInfoBase.
+ *
+ *@code
+ *   struct B {};
+ *   struct D : public B {};
+ *   SG_ADD_BASES (D, B);
+ @endcode
+ */
+#define SG_ADD_BASE(D, B) \
+  namespace SG        {          \
+    template struct AddBaseInit<D, B >;            \
+} struct sg_dummy // to swallow semicolon
+
+
+/**
+ * @brief Declare a copy conversion from class @c T using converter @c C.
+ *
+ * See the comments in the header for a detailed description.
+ */
+#define SG_ADD_COPY_CONVERSION(D, C) \
+  namespace SG        {          \
+    template struct AddCopyConversionInit<D, C >;            \
+} struct sg_dummy // to swallow semicolon
+
+
+
+namespace SG {
+
+
+/**
+ * @brief Helper metafunction to get base class types.
+ *
+ * For a class @c T,
+ *@code
+ *   SG::BaseType<SG::Bases<T>::Base1>::type
+ @endcode
+ * gives the type of @c T's first base.  Also,
+ *@code
+ *   SG::BaseType<SG::Bases<T>::Base1>::is_virtual
+ @endcode
+ * tells whether the derivation is virtual
+ * (either @c true_type or @c false_type).
+ *
+ * Note that @c SG::Bases\<T>::Base1 is not the actual type
+ * of @c T's first base if virtual derivation was used.
+ */
+template <class T>
+struct BaseType;
+
+
+// Forward declaration.
+template <class T>
+class BaseInfoImpl;
+
+
+struct BaseInfoBaseImpl;
+
+
+//===========================================================================
+// Copy conversion declarations.
+//
+
+
+/**
+ * @brief Base class for copy conversions.
+ */
+class CopyConversionBase
+{
+public:
+  /// Destructor.
+  virtual ~CopyConversionBase() {}
+
+  /// Create an instance of the destination class.
+  virtual void* create() const = 0;
+
+  /// Destroy an instance of the destination class.
+  virtual void destroy (void* p) const = 0;
+
+  /// Convert the contents of an instance of the source class SRC
+  /// to an instance of the destination class DST.
+  virtual void convertUntyped (const void* src, void* dst) const = 0;
+};
+
+
+/**
+ * @brief Base class for copy conversions, templated on source
+ *        and destination classes.
+ */
+template <class SRC, class DST>
+class CopyConversion
+  : public CopyConversionBase
+{
+public:
+  /// The destination class.
+  typedef DST target_type;
+
+  /// Create an instance of the destination class.
+  virtual void* create() const { return new DST; }
+
+  /// Destroy an instance of the destination class.
+  virtual void destroy (void* p) const { delete reinterpret_cast<DST*>(p); }
+
+  /// Convert the contents of an instance of the source class SRC
+  /// to an instance of the destination class DST.
+  virtual void convertUntyped (const void* src, void* dst) const
+  {
+    convert (*reinterpret_cast<const SRC*>(src),
+             *reinterpret_cast<DST*>(dst));
+  }
+
+  /// Convert the contents of an instance of the source class SRC
+  /// to an instance of the destination class DST.
+  /// (Type-safe version.)
+  virtual void convert (const SRC& src, DST& dst) const = 0;
+};
+
+
+//===========================================================================
+// Base class declaration.
+// This factors out the part of the implementation that doesn't
+// depend on the template parameter @a T.
+//
+
+
+/**
+ * @brief The non-template portion of the @a BaseInfo implementation.
+ */
+class BaseInfoBase
+{
+public:
+  /**
+   * @brief Return the CLID for this class.
+   */
+  CLID clid() const;
+
+
+  /**
+   * @brief Return the @c std::type_info for this class.
+   */
+  const std::type_info& typeinfo() const;
+  
+
+  /**
+   * @brief Cast to a base pointer.
+   * @param p The pointer to cast (a @a T* cast to a @a void*).
+   * @param clid ID of the class to which to cast.
+   * @return The pointer cast to the requested type, returned
+   *         as a @a void*.  @a clid must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  void* cast (void* p, CLID clid) const;
+
+  /**
+   * @brief Cast to a base pointer.
+   * @param p The pointer to cast (a @a T* cast to a @a void*).
+   * @param clid @a type_info of the class to which to cast.
+   * @return The pointer cast to the requested type, returned
+   *         as a @a void*.  @a tinfo must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  void* cast (void* p, const std::type_info& tinfo) const;
+
+
+  /**
+   * @brief Cast to a derived pointer.
+   * @param p The pointer to cast (a @a B* cast to a @a void*).
+   * @param clid ID of the class @a B from which to cast.
+   * @return The pointer cast to the requested type, returned
+   *         as a @a void*.  @a clid must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  void* castTo (void* p, CLID clid) const;
+
+  /**
+   * @brief Cast to a derived pointer.
+   * @param p The pointer to cast (a @a B* cast to a @a void*).
+   * @param clid @a type_info of the class @a B from which to cast.
+   * @return The pointer cast to the requested type, returned
+   *         as a @a void*.  @a tinfo must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  void* castTo (void* p, const std::type_info& tinfo) const;
+
+
+  /// Type of a pointer conversion function.
+  typedef void* castfn_t (void* p);
+
+
+  // gcc 4.3 complains about the code genreflex generates for these.
+  // They're not useful from python anyway, so just suppress them.
+#ifndef __REFLEX__
+  /**
+   * @brief Return a function for casting to a base pointer.
+   * @param clid ID of the class to which to cast.
+   * @return A function to convert a pointer to a @c T to a pointer
+   *         to the type identified by @a clid.
+   *         @a clid must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  castfn_t* castfn (CLID clid) const;
+
+
+  /**
+   * @brief Return a function for casting to a base pointer.
+   * @param clid @a type_info of the class to which to cast.
+   * @return A function to convert a pointer to a @c T to a pointer
+   *         to the type identified by @a tinfo.
+   *         @a tinfo must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  castfn_t* castfn (const std::type_info& tinfo) const;
+
+  /**
+   * @brief Return a function for casting to a derived pointer.
+   * @param clid ID of the class @a B from which to cast.
+   * @return A function to convert a pointer to a @a B to a pointer
+   *         to a @a T.  @a B must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  castfn_t* castfnTo (CLID clid) const;
+
+
+  /**
+   * @brief Return a function for casting to a derived pointer.
+   * @param clid @a type_info of the class @a B from which to cast.
+   * @return A function to convert a pointer to a @a B to a pointer
+   *         to a @a T.  @a B must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  castfn_t* castfnTo (const std::type_info& tinfo) const;
+#endif
+
+
+  /**
+   * @brief Return the class IDs of all known bases of @a T (that
+   *        have class IDs).  The list will include @a T itself.
+   */
+  std::vector<CLID> get_bases () const;
+
+  /**
+   * @brief Return the @c type_info's of all known bases of @a T.
+   *        The list will include @a T itself.
+   */
+  std::vector<const std::type_info*> get_ti_bases () const;
+
+  /**
+   * @brief Return true if @a clid is the ID of a class that
+   *        is known to be a base of @a T.  @a T is considered
+   *        to be its own base for this purpose.
+   * @param clid The ID of the class to test.
+   */
+  bool is_base (CLID clid) const;
+
+  /**
+   * @brief Return true if @a tinfo is the @a type_info of a class that
+   *        is known to be a base of @a T.  @a T is considered
+   *        to be its own base for this purpose.
+   * @param clid The ID of the class to test.
+   */
+  bool is_base (const std::type_info& tinfo) const;
+
+
+  /**
+   * @brief Return true if @a clid is the ID of a class that
+   *        is known to be a virtual base of @a T.  (This will always
+   *        be false for @a T itself.)
+   * @param clid The ID of the class to test.
+   */
+  bool is_virtual (CLID clid) const;
+
+  /**
+   * @brief Return true if @a tinfo is the @a std::type_info of a class that
+   *        is known to be a virtual base of @a T.  (This will always
+   *        be false for @a T itself.)
+   * @param tinfo The @a std::type_info of the class to test.
+   */
+  bool is_virtual (const std::type_info& tinfo) const;
+
+
+  /**
+   * @brief Search for a copy conversion to @c tinfo.
+   * @param tinfo The class to which we want to convert.
+   *
+   * Returns the conversion instance or 0.
+   */
+  const CopyConversionBase* copy_conversion (const std::type_info& tinfo) const;
+
+
+  /**
+   * @brief Search for a copy conversion to @c clid.
+   * @param clid The class to which we want to convert.
+   *
+   * Returns the conversion instance or 0.
+   */
+  const CopyConversionBase* copy_conversion (CLID clid) const;
+
+
+  /**
+   * @brief Add a new copy conversion.
+   * @param tinfo The @c std::type_info of the target class.
+   * @param cnv A @c CopyConversionBase instance describing the conversion.
+   *
+   * The @c BaseInfoBase takes ownership of the @c cnv object.
+   */
+  void add_copy_conversion (const std::type_info& tinfo,
+                            const CopyConversionBase* cnv);
+
+
+  /**
+   * @brief Return known copy conversions.
+   *
+   * Returns the CLIDs of all target classes that have been registered
+   * with this one for copy conversion.
+   */
+  std::vector<CLID> get_copy_conversions() const;
+
+
+#ifndef __REFLEX__
+  /**
+   * @brief Add information about one base class.
+   * @param tinfo The @a std::type_info of the base.
+   * @param converter Converter function.  This should be able to
+   *                  convert a @a T* to a pointer to this base.
+   * @param converterTo Converter function.  This should be able to
+   *                    convert a pointer to this base to a @a T*.
+   * @param is_virtual True if the derivation from this base to @a T
+   *                   is via virtual derivation.
+   */
+  void add_info (const std::type_info& tinfo,
+                 castfn_t* converter,
+                 castfn_t* converterTo,
+                 bool is_virtual);
+#endif
+
+
+  /**
+   * @brief Find the @c BaseInfoBase instance for @c clid.
+   * @param clid The class ID of the class for which we want information.
+   *
+   * Returns 0 if no @c BaseInfoBase instance is available.
+   */
+  static const BaseInfoBase* find (CLID clid);
+
+
+  /**
+   * @brief Find the @c BaseInfoBase instance for @c tinfo.
+   * @param tinfo The @c std::type_info of the class
+   *              for which we want information.
+   *
+   * Returns 0 if no @c BaseInfoBase instance is available.
+   */
+  static const BaseInfoBase* find (const std::type_info& tinfo);
+
+
+  /// Type for an initialization function.
+  typedef const BaseInfoBase& init_func_t();
+
+
+#ifndef __REFLEX__
+  /**
+   * @brief Register an initialization function.
+   * @param tinfo The @c std::type_info for the class being registered.
+   * @param init_func Function to initialize @c BaseInfo for the class.
+   */
+  static void addInit (const std::type_info* tinfo,
+                       init_func_t* init_func);
+#endif
+
+
+  /**
+   * @brief Run initializations for this class, if needed.
+   */
+  void maybeInit();
+
+
+protected:
+  /**
+   * @brief Constructor.
+   * @param tinfo The @c std::type_info for this class.
+   */
+  BaseInfoBase (const std::type_info& tinfo);
+
+
+  /**
+   * @brief Destructor.
+   */
+  ~BaseInfoBase();
+
+
+private:
+  /**
+   * @brief Helper for @c find.
+   * @param tinfo The @c std::type_info of the class
+   *              for which we want information.
+   *
+   * Returns 0 if no @c BaseInfoBase instance is available.
+   */
+  static const BaseInfoBase* find1 (const std::type_info& tinfo);
+
+
+  /// Pointer to internal state.
+  BaseInfoBaseImpl* m_impl;
+
+  BaseInfoBase (const BaseInfoBase&);
+  BaseInfoBase& operator= (const BaseInfoBase&);
+};
+
+
+//===========================================================================
+// The templated @c BaseInfo class.
+//
+
+/**
+ * @brief Provide an interface for finding inheritance information
+ *        at run time.  See the file comments for full details.
+ */
+template <class T>
+class BaseInfo
+{
+public:
+  /**
+   * @brief Cast to a base pointer.
+   * @param p The pointer to cast.
+   * @param clid ID of the class to which to cast.
+   * @return The pointer cast to the requested type, returned
+   *         as a @a void*.  @a clid must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  static void* cast (T* p, CLID clid);
+
+  /**
+   * @brief Cast to a base pointer.
+   * @param p The pointer to cast.
+   * @param clid @a type_info of the class to which to cast.
+   * @return The pointer cast to the requested type, returned
+   *         as a @a void*.  @a tinfo must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  static void* cast (T* p, const std::type_info& tinfo);
+
+
+  /**
+   * @brief Cast to a derived pointer.
+   * @param p The pointer to cast.
+   * @param clid ID of the class @a B from which to cast.
+   * @return The pointer cast to a @a T*.
+   *         @a B must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  static T* castTo (void* p, CLID clid);
+
+  /**
+   * @brief Cast to a derived pointer.
+   * @param p The pointer to cast.
+   * @param clid @a type_info of the class @a B from which to cast.
+   * @return The pointer cast to a @a T*.
+   *         @a B must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  static T* castTo (void* p, const std::type_info& tinfo);
+
+
+  /**
+   * @brief Return a function for casting to a base pointer.
+   * @param clid ID of the class to which to cast.
+   * @return A function to convert a pointer to a @c T to a pointer
+   *         to the type identified by @a clid.
+   *         @a clid must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  static BaseInfoBase::castfn_t* castfn (CLID clid);
+
+
+  /**
+   * @brief Return a function for casting to a base pointer.
+   * @param clid @a type_info of the class to which to cast.
+   * @return A function to convert a pointer to a @c T to a pointer
+   *         to the type identified by @a tinfo.
+   *         @a tinfo must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  static BaseInfoBase::castfn_t* castfn (const std::type_info& tinfo);
+
+
+  /**
+   * @brief Return a function for casting to a derived pointer.
+   * @param clid ID of the class @a B from which to cast.
+   * @return A function to convert a pointer to a @c T to a pointer
+   *         to a @a T.  @a clid must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  static BaseInfoBase::castfn_t* castfnTo (CLID clid);
+
+
+  /**
+   * @brief Return a function for casting to a derived pointer.
+   * @param clid @a type_info of the class @a B from which to cast.
+   * @return A function to convert a pointer to a @c B to a pointer
+   *         to a @a T.  @a tinfo must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  static BaseInfoBase::castfn_t* castfnTo (const std::type_info& tinfo);
+
+
+  /**
+   * @brief Return the class IDs of all known bases of @a T (that
+   *        have class IDs).  The list will include @a T itself.
+   */
+  static std::vector<CLID> get_bases ();
+
+
+  /**
+   * @brief Return the @c type_info's of all known bases of @a T.
+   *        The list will include @a T itself.
+   */
+  static std::vector<const std::type_info*> get_ti_bases ();
+
+
+  /**
+   * @brief Return true if @a clid is the ID of a class that
+   *        is known to be a base of @a T.  @a T is considered
+   *        to be its own base for this purpose.
+   * @param clid The ID of the class to test.
+   */
+  static bool is_base (CLID clid);
+
+  /**
+   * @brief Return true if @a tinfo is the @a std::type_info of a class that
+   *        is known to be a base of @a T.  @a T is considered
+   *        to be its own base for this purpose.
+   * @param tinfo The @a std::type_info of the class to test.
+   */
+  static bool is_base (const std::type_info& tinfo);
+
+
+  /**
+   * @brief Return true if @a clid is the ID of a class that
+   *        is known to be a virtual base of @a T.  (This will always
+   *        be false for @a T itself.)
+   * @param clid The ID of the class to test.
+   */
+  static bool is_virtual (CLID clid);
+
+  /**
+   * @brief Return true if @a tinfo is the @a std::type_info of a class that
+   *        is known to be a virtual base of @a T.  (This will always
+   *        be false for @a T itself.)
+   * @param tinfo The @a std::type_info of the class to test.
+   */
+  static bool is_virtual (const std::type_info& tinfo);
+
+
+  /**
+   * @brief Return the non-templated @c BaseInfoBase object for this type.
+   */
+  static const BaseInfoBase& baseinfo ();
+
+
+  static void maybeInit ();
+
+
+private:
+  /// Return a reference to the (singleton) implementation object
+  /// for this class.
+  static const BaseInfoImpl<T>& instance();
+
+  /// This holds the singleton implementation object instance.
+  struct instance_holder
+  {
+    instance_holder();
+    BaseInfoImpl<T>* instance;
+  };
+  static instance_holder s_instance;
+};
+
+
+} // namespace SG
+
+
+#include "AthenaKernel/BaseInfo.icc"
+
+
+#endif // not ATHENAKERNEL_BASEINFO_H
+
diff --git a/Control/AthenaKernel/AthenaKernel/BaseInfo.icc b/Control/AthenaKernel/AthenaKernel/BaseInfo.icc
new file mode 100755
index 0000000000000000000000000000000000000000..22f466458f10b7bfe8298eb8bd61c66142e80abd
--- /dev/null
+++ b/Control/AthenaKernel/AthenaKernel/BaseInfo.icc
@@ -0,0 +1,675 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: BaseInfo.icc,v 1.9 2008-12-15 15:12:39 ssnyder Exp $
+/**
+ * @file  AthenaKernel/BaseInfo.icc
+ * @author scott snyder
+ * @date Nov 2005
+ * @brief Provide an interface for finding inheritance information
+ *        at run time.
+ *        Implementation file.
+ */
+
+
+#include <type_traits>
+
+
+namespace SG {
+
+
+//===========================================================================
+// Inheritance data representation classes.
+//
+
+
+/**
+ * @brief Marker to indicate a nonexistent base class.
+ */
+struct NoBase {};
+
+
+/**
+ * @brief Wrapper to indicate virtual derivation.
+ *        @a Virtual<T> will mean that derivation from @a T is virtual.
+ */
+template <class T> struct Virtual {};
+
+
+/**
+ * @brief Traits class to hold derivation information for up to three
+ *        base classes.
+ *
+ * @a Base1, etc., get typedef'd to the appropriate
+ * base classes.  Use @a NoBase if there is no base class; use
+ * @a Virtual<T> to indicate virtual derivation.  This class should
+ * be specialized for every class @a T for which we want to know
+ * inheritance information.
+ */
+template <class T>
+struct Bases
+{
+  typedef NoBase Base1;
+  typedef NoBase Base2;
+  typedef NoBase Base3;
+};
+
+
+// Helper metafunction to get base class types.
+// Generic case.
+template <class T>
+struct BaseType
+{
+  typedef T type;
+  typedef std::false_type is_virtual;
+};
+
+
+// Helper metafunction to get base class types.
+// Virtual derivation case.
+template <class T>
+struct BaseType<Virtual<T> >
+{
+  typedef T type;
+  typedef std::true_type is_virtual;
+};
+
+
+//===========================================================================
+// Internal implementation class for @a BaseInfo.
+// This is used as a singleton, and should be accessed using the @a BaseInfo
+// wrapper class.
+//
+
+/**
+ * @brief Internal implementation class for @a BaseInfo.
+ */
+template <class T>
+class BaseInfoImpl
+  : public BaseInfoBase
+{
+public:
+  /**
+   * @brief Constructor.
+   */
+  BaseInfoImpl();
+
+
+  /**
+   * @brief Add information about base class @a B (for @a T).
+   * @param is_virtual True if the derivation from @a B to @a T
+   *                   is via virtual derivation.
+   */
+#if defined(__REFLEX__) || defined(__COVERITY__)
+  template <class B>
+  void add_base (bool is_virtual);
+#else
+  template <class B>
+  void add_base (bool is_virtual)
+  {
+    // Make sure the bib for the base class exists.
+    BaseInfo<B>::maybeInit();
+
+    // Add the information for this base.
+    this->add_info (typeid(B),
+                    converter<B>, converterTo<B>, is_virtual);
+  }
+#endif
+
+private:
+  /**
+   * @brief Converter function.
+   * @param p Pointer to convert.  A @a T* converted to a @a void*.
+   *
+   * Converts a @a T* to a @a B* (where @a T derives from @a B).
+   * The pointers are given and returned as @a void*.
+   */
+  template <class B>
+  static void* converter (void* p)
+  {
+    typedef typename std::remove_const<B>::type B_nc;
+    typedef typename std::remove_const<T>::type T_nc;
+    B_nc* b = reinterpret_cast<T_nc*> (p);
+    return b;
+  }
+
+
+  /**
+   * @brief Converter function.
+   * @param p Pointer to convert.  A @a B* converted to a @a void*.
+   *
+   * Converts a @a B* to a @a T* (where @a T derives from @a B).
+   * The pointers are given and returned as @a void*.
+   * Returns 0 if the conversion fails.
+   *
+   * Implementation note: to @c dynamic_cast @a B to @a T, @a B needs to have
+   * a vtable.  If B doesn't have a vtable, then we don't attempt the
+   * conversion.  (In principle, we could use is_virtual_base_of, and fall
+   * back to a static_cast if it's false.  However, using is_virtual_base_of
+   * generates some nasty compilation warnings, so i'll avoid it for now.)
+   */
+  template <class B>
+  static void* converterTo (void* p)
+  {
+    return converterToHelper<B> (p, std::is_polymorphic<B>());
+  }
+
+
+  // B has a vtable.  Use dynamic_cast.
+  template <class B>
+  static void* converterToHelper (void* p, std::true_type)
+  {
+    typedef typename std::remove_const<B>::type B_nc;
+    typedef typename std::remove_const<T>::type T_nc;
+    T_nc* b = dynamic_cast<T_nc*> (reinterpret_cast<B_nc*> (p));
+    return b;
+  }
+
+
+  // B doesn't have a vtable.  Don't try to convert.
+  template <class B>
+  static void* converterToHelper (void* /*p*/, std::false_type)
+  {
+    return 0;
+  }
+};
+
+
+//===========================================================================
+// Initialization.
+// Here we walk the class hierarchy, calling @a add_base for each base.
+
+
+/**
+ * @brief Generic initializer for base @a B.
+ */
+template <class B>
+struct BaseInfo_init
+{
+  template <class T>
+  static void init (BaseInfoImpl<T>& c, bool is_virtual)
+  {
+    // Here, we initialize the @a BaseInfo for @a T for base class @a B.
+    // First, we add the information for this base to the instance.
+    c.template add_base<B>(is_virtual);
+
+    // Then we recurse on each possible base.
+    BaseInfo_init<typename Bases<B>::Base1>::init (c, is_virtual);
+    BaseInfo_init<typename Bases<B>::Base2>::init (c, is_virtual);
+    BaseInfo_init<typename Bases<B>::Base3>::init (c, is_virtual);
+  }
+};
+
+
+/**
+ * @brief Dummy initializer.
+ */
+template <>
+struct BaseInfo_init<NoBase>
+{
+  template <class T>
+  static void init (BaseInfoImpl<T>& /*c*/, bool /*is_virtual*/)
+  {
+    // This gets called when there is no base in a slot
+    // (signaled by the use of @a NoBase).
+    // This ends the recursion.
+  }
+};
+
+
+/**
+ * @brief Initializer for virtual base @a B.
+ */
+template <class B>
+struct BaseInfo_init<Virtual<B> >
+{
+  template <class T>
+  static void init (BaseInfoImpl<T>& c, bool /*is_virtual*/)
+  {
+    // Here, we initialize the @a BaseInfo for @a T for a virtual
+    // base class @a B.  We recurse to the generic initializer
+    // for this base, with the @a is_virtual flag forced on.
+    BaseInfo_init<B>::init (c, true);
+  }
+};
+
+
+/**
+ * @brief Constructor.
+ */
+template <class T>
+BaseInfoImpl<T>::BaseInfoImpl ()
+  : BaseInfoBase (typeid(T))
+{
+  // This starts the walk over the bases.
+  // We start with @a T itself.
+  // The virtual flag is initially false.
+  BaseInfo_init<T>::init (*this, false);
+}
+
+
+//===========================================================================
+// The @a BaseInfo wrapper class.
+// This will statically hold a singleton instance of @a BaseInfoImpl
+// (in the instance function).
+
+
+/**
+ * @brief Cast to a base pointer.
+ * @param p The pointer to cast.
+ * @param clid ID of the class to which to cast.
+ * @return The pointer cast to the requested type, returned
+ *         as a @a void*.  @a clid must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+template <class T>
+void* BaseInfo<T>::cast (T* p, CLID clid)
+{
+  typedef typename std::remove_const<T>::type T_nc;
+  return instance().cast (const_cast<T_nc*>(p), clid);
+}
+
+
+/**
+ * @brief Cast to a base pointer.
+ * @param p The pointer to cast.
+ * @param clid @a type_info of the class to which to cast.
+ * @return The pointer cast to the requested type, returned
+ *         as a @a void*.  @a tinfo must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+template <class T>
+void* BaseInfo<T>::cast (T* p, const std::type_info& tinfo)
+{
+  typedef typename std::remove_const<T>::type T_nc;
+  return instance().cast (const_cast<T_nc*>(p), tinfo);
+}
+
+
+/**
+ * @brief Cast to a derived pointer.
+ * @param p The pointer to cast.
+ * @param clid ID of the class @a B from which to cast.
+ * @return The pointer cast to a @a T*.
+ *         @a B must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+template <class T>
+T* BaseInfo<T>::castTo (void* p, CLID clid)
+{
+  return reinterpret_cast<T*> (instance().castTo (p, clid));
+}
+
+
+/**
+ * @brief Cast to a derived pointer.
+ * @param p The pointer to cast.
+ * @param clid @a type_info of the class @a B from which to cast.
+ * @return The pointer cast to a @a T*.
+ *         @a B must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+template <class T>
+T* BaseInfo<T>::castTo (void* p, const std::type_info& tinfo)
+{
+  return reinterpret_cast<T*> (instance().castTo (p, tinfo));
+}
+
+
+#if !defined(__REFLEX__) && !defined(__COVERITY__)
+/**
+ * @brief Return a function for casting to a base pointer.
+ * @param clid ID of the class to which to cast.
+ * @return A function to convert a pointer to a @c T to a pointer
+ *         to the type identified by @a clid.
+ *         @a clid must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+template <class T>
+BaseInfoBase::castfn_t* BaseInfo<T>::castfn (CLID clid)
+{
+  return instance().castfn (clid);
+}
+
+
+/**
+ * @brief Return a function for casting to a base pointer.
+ * @param clid @a type_info of the class to which to cast.
+ * @return A function to convert a pointer to a @c T to a pointer
+ *         to the type identified by @a tinfo.
+ *         @a tinfo must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+template <class T>
+BaseInfoBase::castfn_t*
+BaseInfo<T>::castfn (const std::type_info& tinfo)
+{
+  return instance().castfn (tinfo);
+}
+
+
+/**
+ * @brief Return a function for casting to a derived pointer.
+ * @param clid ID of the class @a B from which to cast.
+ * @return A function to convert a pointer to a @c T to a pointer
+ *         to a @a T.  @a clid must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+template <class T>
+BaseInfoBase::castfn_t* BaseInfo<T>::castfnTo (CLID clid)
+{
+  return instance().castfnTo (clid);
+}
+
+
+/**
+ * @brief Return a function for casting to a derived pointer.
+ * @param clid @a type_info of the class @a B from which to cast.
+ * @return A function to convert a pointer to a @c B to a pointer
+ *         to a @T.  @a tinfo must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+template <class T>
+BaseInfoBase::castfn_t*
+BaseInfo<T>::castfnTo (const std::type_info& tinfo)
+{
+  return instance().castfnTo (tinfo);
+}
+#endif
+
+
+/**
+ * @brief Return the class IDs of all known bases of @a T (that
+ *        have class IDs).  The list will include @a T itself.
+ */
+template <class T>
+std::vector<CLID> BaseInfo<T>::get_bases ()
+{
+  return instance().get_bases();
+}
+
+
+/**
+ * @brief Return the @c type_info's of all known bases of @a T.
+ *        The list will include @a T itself.
+ */
+template <class T>
+std::vector<const std::type_info*>
+BaseInfo<T>::get_ti_bases ()
+{
+  return instance().get_ti_bases();
+}
+
+
+/**
+ * @brief Return true if @a clid is the ID of a class that
+ *        is known to be a base of @a T.  @a T is considered
+ *        to be its own base for this purpose.
+ * @param clid The ID of the class to test.
+ */
+template <class T>
+bool BaseInfo<T>::is_base (CLID clid)
+{
+  return instance().is_base (clid);
+}
+
+
+/**
+ * @brief Return true if @a tinfo is the @a std::type_info of a class that
+ *        is known to be a base of @a T.  @a T is considered
+ *        to be its own base for this purpose.
+ * @param tinfo The @a std::type_info of the class to test.
+ */
+template <class T>
+bool BaseInfo<T>::is_base (const std::type_info& tinfo)
+{
+  return instance().is_base (tinfo);
+}
+
+
+/**
+ * @brief Return true if @a clid is the ID of a class that
+ *        is known to be a virtual base of @a T.  (This will always
+ *        be false for @a T itself.)
+ * @param clid The ID of the class to test.
+ */
+template <class T>
+bool BaseInfo<T>::is_virtual (CLID clid)
+{
+  return instance().is_virtual (clid);
+}
+
+
+/**
+ * @brief Return true if @a tinfo is the @a std::type_info of a class that
+ *        is known to be a virtual base of @a T.  (This will always
+ *        be false for @a T itself.)
+ * @param tinfo The @a std::type_info of the class to test.
+ */
+template <class T>
+bool BaseInfo<T>::is_virtual (const std::type_info& tinfo)
+{
+  return instance().is_virtual (tinfo);
+}
+
+
+/**
+ * @brief Return the non-templated @c BaseInfoBase object for this type.
+ */
+template <class T>
+const BaseInfoBase& BaseInfo<T>::baseinfo()
+{
+  return instance();
+}
+
+
+template <class T>
+void BaseInfo<T>::maybeInit()
+{
+  BaseInfoImpl<T>* inst = s_instance.instance;
+  if (inst)
+    inst->maybeInit();
+}
+
+
+/**
+ * @brief Return a reference to the (singleton) implementation object
+ *        for this class.
+ */
+template <class T>
+const BaseInfoImpl<T>& BaseInfo<T>::instance()
+{
+  BaseInfoImpl<T>* inst = s_instance.instance;
+  if (inst)
+    inst->maybeInit();
+  return *inst;
+}
+
+
+/**
+ * @brief Constructor to get the singleton instance set up.
+ */
+template <class T>
+BaseInfo<T>::instance_holder::instance_holder()
+{
+  static BaseInfoImpl<T> inst;
+  instance = &inst;
+}
+
+
+/// Declare the static member of @c BaseInfo.
+template <class T>
+typename BaseInfo<T>::instance_holder BaseInfo<T>::s_instance;
+
+
+/**
+ * @brief Helper to get @c BaseInfo initialized.
+ */
+template <class T>
+struct RegisterBaseInit
+{
+  RegisterBaseInit()
+#ifdef __GNUC__
+    // Force this function to appear as a symbol in the output file,
+    // even in an optimized build where it's always inlined.
+    // Otherwise, we get complaints from cling that it can't find the symbol
+    // (as of root 6.04).
+    __attribute__ ((used))
+#endif
+  ;
+};
+
+
+#if !defined(__REFLEX__) && !defined(__COVERITY__)
+template <class T>
+RegisterBaseInit<T>::RegisterBaseInit()
+{
+  BaseInfoBase::addInit(&typeid(T), BaseInfo<T>::baseinfo);
+}
+#endif
+
+
+/**
+ * @brief Helper to get @c BaseInfo initialized.
+ */
+template <class T> struct BaseInit {
+  static RegisterBaseInit<T> s_regbase;
+};
+#ifndef __APPLE__
+template <class T> RegisterBaseInit<T> BaseInit<T>::s_regbase;
+#endif
+
+
+//**********************************************************
+// SG_ADD_BASE and SG_ADD_COPY_CONVERSION implementation.
+
+
+/**
+ * @brief Helper to get @c AddBaseInfo initialized.
+ */
+template <class D, class B>
+struct RegisterAddBaseInit
+{
+  /// Add ourself to the init list.
+  RegisterAddBaseInit();
+
+  /// Init callback: add the new base to the BIB.
+  static const BaseInfoBase& doinit();
+};
+
+
+#if !defined(__REFLEX__) && !defined(__COVERITY__)
+/**
+ * @brief Init callback: add the new base to the BIB.
+ */
+template <class D, class B>
+const BaseInfoBase& RegisterAddBaseInit<D, B>::doinit()
+{
+  // B may either be the actual base class we want,
+  // or Virtual<BB>. Unwrap a surrounding Virtual<> if needed.
+  typedef typename BaseType<B>::type base_type;
+  bool is_virtual = BaseType<B>::is_virtual::value;
+
+  // Look up the BIB.
+  SG::BaseInfoBase* bib =
+    const_cast<SG::BaseInfoBase*> (SG::BaseInfoBase::find (typeid(D)));
+  if (!bib)
+    bib = const_cast<SG::BaseInfoBase*> (&BaseInfo<D>::baseinfo());
+  if (bib) {
+    // Add the new base to it.
+    SG::BaseInfoImpl<D>& impl = *static_cast<SG::BaseInfoImpl<D>*> (bib);
+    impl.template add_base<base_type> (is_virtual);
+  }
+  return *bib;
+}
+
+
+/**
+ * @brief Add ourself to the init list.
+ */
+template <class D, class B>
+RegisterAddBaseInit<D, B>::RegisterAddBaseInit()
+{
+  BaseInfoBase::addInit(&typeid(D), doinit);
+}
+#endif
+
+
+/**
+ * @brief Helper to get @c AddBaseInfo initialized.
+ */
+template <class D, class B> struct AddBaseInit {
+  static RegisterAddBaseInit<D, B> s_regbase;
+};
+#ifndef __APPLE__
+template <class D, class B>
+RegisterAddBaseInit<D,B> AddBaseInit<D,B>::s_regbase;
+#endif
+
+
+
+/**
+ * @brief Helper to get the copy conversion initialized.
+ */
+template <class D, class B>
+struct RegisterAddCopyConversionInit
+{
+  /// Add ourself to the init list.
+  RegisterAddCopyConversionInit();
+
+  /// Init callback: xxx
+  static const BaseInfoBase& doinit();
+};
+
+
+#if !defined(__REFLEX__) && !defined(__COVERITY__)
+/**
+ * @brief Init callback: add the new conversion to the BIB.
+ */
+template <class T, class C>
+const BaseInfoBase& RegisterAddCopyConversionInit<T, C>::doinit()
+{
+  // Look up the BIB.
+  SG::BaseInfoBase* bib =
+    const_cast<SG::BaseInfoBase*> (SG::BaseInfoBase::find (typeid(T)));
+  if (!bib)
+    bib = const_cast<SG::BaseInfoBase*> (&BaseInfo<T>::baseinfo());
+  if (bib) {
+    typedef typename C::target_type target_type;
+    bib->add_copy_conversion (typeid(target_type),
+                              new C);
+  }
+  return *bib;
+}
+
+
+/**
+ * @brief Add ourself to the init list.
+ */
+template <class T, class C>
+RegisterAddCopyConversionInit<T, C>::RegisterAddCopyConversionInit()
+{
+  BaseInfoBase::addInit(&typeid(T), doinit);
+}
+#endif
+
+
+/**
+ * @brief Helper to get @c AddBaseInfo initialized.
+ */
+template <class T, class C> struct AddCopyConversionInit {
+  static RegisterAddCopyConversionInit<T, C> s_regbase;
+};
+#ifndef __APPLE__
+template <class T, class C>
+RegisterAddCopyConversionInit<T,C> AddCopyConversionInit<T,C>::s_regbase;
+#endif
+
+
+} // namespace SG
+
diff --git a/Control/AthenaKernel/AthenaKernel/selection.xml b/Control/AthenaKernel/AthenaKernel/selection.xml
index ba01f91974cf209144cdfd1246187130a03d1ecb..e42dbc4df73e664c38b965ecddcec9b3bd7671fd 100644
--- a/Control/AthenaKernel/AthenaKernel/selection.xml
+++ b/Control/AthenaKernel/AthenaKernel/selection.xml
@@ -20,4 +20,6 @@
    <function name="Athena::DsoUtils::inDso" />
    <function name="Athena::PackageInfo" />
 
+   <class name="SG::BaseInfoBase" />
+
 </lcgdict>
diff --git a/Control/AthenaKernel/CMakeLists.txt b/Control/AthenaKernel/CMakeLists.txt
index 20032938bf0d1928781de80065c9683a7c093368..b0e71e6787871cfa13e0398e12c0ef72633a2a70 100644
--- a/Control/AthenaKernel/CMakeLists.txt
+++ b/Control/AthenaKernel/CMakeLists.txt
@@ -98,3 +98,7 @@ atlas_add_test( CLIDRegistry_test
 atlas_add_test( ClassName_test
    SOURCES test/ClassName_test.cxx
    LINK_LIBRARIES AthenaKernel )
+
+atlas_add_test( BaseInfo_test
+   SOURCES test/BaseInfo_test.cxx
+   LINK_LIBRARIES AthenaKernel )
diff --git a/Control/AthenaKernel/share/BaseInfo_test.ref b/Control/AthenaKernel/share/BaseInfo_test.ref
new file mode 100755
index 0000000000000000000000000000000000000000..bae42c55f9e0a4e297a4d197d8aadfe147ef269b
--- /dev/null
+++ b/Control/AthenaKernel/share/BaseInfo_test.ref
@@ -0,0 +1,2 @@
+test1
+test2
diff --git a/Control/AthenaKernel/src/BaseInfo.cxx b/Control/AthenaKernel/src/BaseInfo.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..8f6f28735e0b3b0def4ff2f6ace22933a968c1f3
--- /dev/null
+++ b/Control/AthenaKernel/src/BaseInfo.cxx
@@ -0,0 +1,704 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: BaseInfo.cxx,v 1.9 2008-11-25 21:45:04 ssnyder Exp $
+/**
+ * @file  AthenaKernel/src/BaseInfo.cxx
+ * @author scott snyder
+ * @date Nov 2005
+ * @brief Provide an interface for finding inheritance information
+ *        at run time.
+ *        Out-of-line implementation.
+ */
+
+#include "AthenaKernel/BaseInfo.h"
+#include "AthenaKernel/CLIDRegistry.h"
+#include "GaudiKernel/System.h"
+#include <mutex>
+#include <map>
+#include <unordered_map>
+#include "string.h"
+
+
+namespace SG {
+
+
+struct BaseInfoBaseImpl {
+  /// Structure to hold information about one base.
+  struct info {
+    /// Constructor.  @a converter* and @a is_virtual are as for @a add_info.
+    info (BaseInfoBase::castfn_t* converter = 0,
+          BaseInfoBase::castfn_t* converterTo = 0,
+          bool is_virtual = false);
+
+    /// Converter function.  Takes a @a T* and converts to a pointer
+    /// to this base.
+    BaseInfoBase::castfn_t* m_converter;
+
+    /// Converter function.  Takes a pointer to this base and converts
+    /// to @a T*.
+    /// to this base.
+    BaseInfoBase::castfn_t* m_converterTo;
+
+    /// True if the derivation from this base to @a T is via
+    /// virtual derivation.
+    bool m_is_virtual;
+  };
+
+
+  /// CLID of this class.
+  CLID m_clid;
+
+  /// Set to true when first created.
+  /// Reset after we scan for init functions.
+  bool m_needs_init;
+
+  /// @c std::type_info of this class.
+  const std::type_info* m_typeinfo;
+
+
+  /// Hold base information indexed by @a type_info.
+  typedef std::pair<const std::type_info*, info> ti_map_pair_type;
+  typedef std::vector<ti_map_pair_type> ti_map_type;
+  ti_map_type m_timap;
+
+
+  /// Hold copy conversion information indexed by @ type_info.
+  typedef std::pair<const std::type_info*, const CopyConversionBase*>
+  ti_copyconversion_pair_type;
+  typedef std::vector<ti_copyconversion_pair_type> ti_copyconversion_type;
+  ti_copyconversion_type m_ti_copyconversion_map;
+
+
+  /// Map of all @c type_info pointers to @c BaseInfoBase instances.
+  typedef std::unordered_map<const std::type_info*, BaseInfoBase*> bi_by_ti_map_type;
+  static bi_by_ti_map_type* s_bi_by_ti;
+
+
+  /// Used to canonicalize @c type_info instances.
+  typedef std::unordered_map<std::string, const std::type_info*> ti_by_name_map_type;
+  static ti_by_name_map_type* s_ti_by_name;
+
+
+  /// Holds @c BaseInfo classes awaiting initialization.
+  /// This is used to defer initialization until everything's loaded.
+  typedef std::unordered_multimap<const std::type_info*,
+                                  BaseInfoBase::init_func_t*> init_list_t;
+  static init_list_t* s_init_list;
+
+
+  // To make sure that the maps get deleted at program termination.
+  struct Deleter {
+    ~Deleter();
+  };
+  static Deleter s_deleter;
+
+  /// For thread-safety.
+  typedef std::recursive_mutex mutex_t;
+  typedef std::lock_guard<mutex_t> lock_t;
+  static mutex_t s_mutex;
+
+
+  /**
+   * @brief Find a base by @c type_info.
+   * @param tinfo The @c type_info to find.
+   *
+   * Returns the @c info pointer for the base corresponding
+   * to @c info, or nullptr if there is no match.
+   */
+  const info* findInfo (const std::type_info& tinfo) const
+  {
+    // We don't expect there to be many entries, so just use a linear search.
+    for (const auto& i : m_timap) {
+      if (i.first == &tinfo)
+        return &i.second;
+    }
+
+    // Sometimes type_info's are not actually unique, depending on how libraries
+    // get loaded.  Try again, comparing names.
+    for (const auto& i : m_timap) {
+      if (strcmp (i.first->name(), tinfo.name()) == 0)
+        return &i.second;
+    }
+    return nullptr;
+  }
+};
+
+
+
+/**
+ * @brief Return the CLID for this class.
+ */
+CLID BaseInfoBase::clid() const
+{
+  return m_impl->m_clid;
+}
+
+
+/**
+ * @brief Return the @c std::type_info for this class.
+ */
+const std::type_info& BaseInfoBase::typeinfo() const
+{
+  return *m_impl->m_typeinfo;
+}
+
+
+/**
+ * @brief Cast to a base pointer.
+ * @param p The pointer to cast (a @a T* cast to a @a void*).
+ * @param clid ID of the class to which to cast.
+ * @return The pointer cast to the requested type, returned
+ *         as a @a void*.  @a clid must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+void* BaseInfoBase::cast (void* p, CLID clid) const
+{
+  const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
+  if (ti)
+    return this->cast (p, *ti);
+  return 0;
+}
+
+
+/**
+ * @brief Cast to a base pointer.
+ * @param p The pointer to cast (a @a T* cast to a @a void*).
+ * @param clid @a type_info of the class to which to cast.
+ * @return The pointer cast to the requested type, returned
+ *         as a @a void*.  @a tinfo must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+void* BaseInfoBase::cast (void* p, const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
+  if (i)
+    return i->m_converter (p);
+  return nullptr;
+}
+
+
+/**
+ * @brief Cast to a derived pointer.
+ * @param p The pointer to cast (a @a B* cast to a @a void*).
+ * @param clid ID of the class @a B from which to cast.
+ * @return The pointer cast to the requested type, returned
+ *         as a @a void*.  @a clid must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+void* BaseInfoBase::castTo (void* p, CLID clid) const
+{
+  const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
+  if (ti)
+    return this->castTo (p, *ti);
+  return 0;
+}
+
+
+/**
+ * @brief Cast to a derived pointer.
+ * @param p The pointer to cast (a @a B* cast to a @a void*).
+ * @param clid @a type_info of the class @a B from which to cast.
+ * @return The pointer cast to the requested type, returned
+ *         as a @a void*.  @a tinfo must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+void* BaseInfoBase::castTo (void* p, const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
+  if (i)
+    return i->m_converterTo (p);
+  return nullptr;
+}
+
+
+/**
+ * @brief Return a function for casting to a base pointer.
+ * @param clid ID of the class to which to cast.
+ * @return A function to convert a pointer to a @c T to a pointer
+ *         to the type identified by @a clid.
+ *         @a clid must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+BaseInfoBase::castfn_t* BaseInfoBase::castfn (CLID clid) const
+{
+  const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
+  if (ti)
+    return this->castfn (*ti);
+  return 0;
+}
+
+
+/**
+ * @brief Return a function for casting to a base pointer.
+ * @param clid @a type_info of the class to which to cast.
+ * @return A function to convert a pointer to a @c T to a pointer
+ *         to the type identified by @a tinfo.
+ *         @a tinfo must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+BaseInfoBase::castfn_t*
+BaseInfoBase::castfn (const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
+  if (i)
+    return i->m_converter;
+  return nullptr;
+}
+
+
+/**
+ * @brief Return a function for casting to a derived pointer.
+ * @param clid ID of the class @a B from which to cast.
+ * @return A function to convert a pointer to a @a B to a pointer
+ *         to a @a T.  @a B must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+BaseInfoBase::castfn_t* BaseInfoBase::castfnTo (CLID clid) const
+{
+  const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
+  if (ti)
+    return this->castfnTo (*ti);
+  return 0;
+}
+
+
+/**
+ * @brief Return a function for casting to a derived pointer.
+ * @param clid @a type_info of the class @a B from which to cast.
+ * @return A function to convert a pointer to a @a B to a pointer
+ *         to a @a T.  @a B must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+BaseInfoBase::castfn_t*
+BaseInfoBase::castfnTo (const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
+  if (i)
+    return i->m_converterTo;
+  return nullptr;
+}
+
+
+/**
+ * @brief Return the class IDs of all known bases of @a T (that
+ *        have class IDs).  The list will include @a T itself.
+ */
+std::vector<CLID> BaseInfoBase::get_bases() const
+{
+  const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
+  std::vector<CLID> v;
+  v.reserve (map.size());
+  for (const auto& p : map) {
+    CLID clid = CLIDRegistry::typeinfoToCLID (*p.first);
+    if (clid != CLID_NULL)
+      v.push_back (clid);
+  }
+  return v;
+}
+
+
+/**
+ * @brief Return the @c type_info's of all known bases of @a T.
+ *        The list will include @a T itself.
+ */
+std::vector<const std::type_info*> BaseInfoBase::get_ti_bases() const
+{
+  const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
+  std::vector<const std::type_info*> v;
+  v.reserve (map.size());
+  for (const auto& i : map)
+    v.push_back (i.first);
+  return v;
+}
+
+
+/**
+ * @brief Return true if @a clid is the ID of a class that
+ *        is known to be a base of @a T.  @a T is considered
+ *        to be its own base for this purpose.
+ * @param clid The ID of the class to test.
+ */
+bool BaseInfoBase::is_base (CLID clid) const
+{
+  const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
+  if (ti)
+    return this->is_base (*ti);
+  return 0;
+}
+
+
+/**
+ * @brief Return true if @a tinfo is the @a type_info of a class that
+ *        is known to be a base of @a T.  @a T is considered
+ *        to be its own base for this purpose.
+ * @param clid The ID of the class to test.
+ */
+bool BaseInfoBase::is_base (const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
+  return i != 0;
+}
+
+
+/**
+ * @brief Return true if @a clid is the ID of a class that
+ *        is known to be a virtual base of @a T.  (This will always
+ *        be false for @a T itself.)
+ * @param clid The ID of the class to test.
+ */
+bool BaseInfoBase::is_virtual (CLID clid) const
+{
+  const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
+  if (ti)
+    return this->is_virtual (*ti);
+  return false;
+}
+
+
+/**
+ * @brief Return true if @a tinfo is the @a std::type_info of a class that
+ *        is known to be a virtual base of @a T.  (This will always
+ *        be false for @a T itself.)
+ * @param tinfo The @a std::type_info of the class to test.
+ */
+bool BaseInfoBase::is_virtual (const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
+  if (i)
+    return i->m_is_virtual;
+  return false;
+}
+
+
+/**
+ * @brief Search for a copy conversion to @c tinfo.
+ * @param tinfo The class to which we want to convert.
+ *
+ * Returns the conversion instance or 0.
+ */
+const CopyConversionBase*
+BaseInfoBase::copy_conversion (const std::type_info& tinfo) const
+{
+  for (const auto& p : m_impl->m_ti_copyconversion_map) {
+    if (p.first == &tinfo)
+      return p.second;
+  }
+  return 0;
+}
+
+
+/**
+ * @brief Search for a copy conversion to @c clid.
+ * @param clid The class to which we want to convert.
+ *
+ * Returns the conversion instance or 0.
+ */
+const CopyConversionBase*
+BaseInfoBase::copy_conversion (CLID clid) const
+{
+  const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
+  if (ti)
+    return this->copy_conversion (*ti);
+  return 0;
+}
+
+
+/**
+ * @brief Add a new copy conversion.
+ * @param tinfo The @c std::type_info of the target class.
+ * @param cnv A @c CopyConversionBase instance describing the conversion.
+ *
+ * The @c BaseInfoBase takes ownership of the @c cnv object.
+ */
+void
+BaseInfoBase::add_copy_conversion (const std::type_info& tinfo,
+                                   const CopyConversionBase* cnv)
+{
+  m_impl->m_ti_copyconversion_map.emplace_back (&tinfo, cnv);
+}
+
+
+/**
+ * @brief Return known copy conversions.
+ *
+ * Returns the CLIDs of all target classes that have been registered
+ * with this one for copy conversion.
+ */
+std::vector<CLID>
+BaseInfoBase::get_copy_conversions() const
+{
+  std::vector<CLID> out;
+  out.reserve (m_impl->m_ti_copyconversion_map.size());
+  for (const auto& i : m_impl->m_ti_copyconversion_map) {
+    CLID clid = CLIDRegistry::typeinfoToCLID (*i.first);
+    if (clid != CLID_NULL)
+      out.push_back (clid);
+  }
+  return out;
+}
+
+
+/**
+ * @brief Add information about one base class.
+ * @param tinfo The @a std::type_info of the base.
+ * @param converter Converter function.  This should be able to
+ *                  convert a @a T* to a pointer to this base.
+ * @param converterTo Converter function.  This should be able to
+ *                    convert a pointer to this base to a @a T*.
+ * @param is_virtual True if the derivation from this base to @a T
+ *                   is via virtual derivation.
+ */
+void BaseInfoBase::add_info (const std::type_info& tinfo,
+                             castfn_t* converter,
+                             castfn_t* converterTo,
+                             bool is_virtual)
+{
+  {
+    const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
+    if (!i) {
+      m_impl->m_timap.emplace_back (&tinfo,
+                                    BaseInfoBaseImpl::info (converter, converterTo, is_virtual));
+    }
+  }
+
+  auto i = BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
+  if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
+    BaseInfoBaseImpl& impl = *i->second->m_impl;
+    if (impl.m_clid == CLID_NULL)
+      impl.m_clid = CLIDRegistry::typeinfoToCLID (tinfo);
+  }
+}
+
+
+/**
+ * @brief Convenience constructor.
+ * @param converter Converter function.  This should be able to
+ *                  convert a @a T* to a pointer to this base.
+ * @param converterTo Converter function.  This should be able to
+ *                    convert a pointer to this base to a @a T*.
+ * @param is_virtual True if the derivation from this base to @a T
+ *                   is via virtual derivation.
+ *
+ * The defaults are there just so this class can be used with STL
+ * containers that require a default ctor.
+ */
+BaseInfoBaseImpl::info::info (BaseInfoBase::castfn_t* converter /*= 0*/,
+                              BaseInfoBase::castfn_t* converterTo /*= 0*/,
+                              bool is_virtual /*= false*/)
+  : m_converter (converter),
+    m_converterTo (converterTo),
+    m_is_virtual (is_virtual)
+{
+}
+
+
+/**
+ * @brief Constructor.
+ * @param tinfo The @c std::type_info for this class.
+ */
+BaseInfoBase::BaseInfoBase (const std::type_info& tinfo)
+  : m_impl (new BaseInfoBaseImpl)
+{
+  m_impl->m_clid = CLIDRegistry::typeinfoToCLID (tinfo);
+  m_impl->m_typeinfo = &tinfo;
+  m_impl->m_needs_init = true;
+
+  BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
+  if (!BaseInfoBaseImpl::s_bi_by_ti)
+    BaseInfoBaseImpl::s_bi_by_ti   = new BaseInfoBaseImpl::bi_by_ti_map_type;
+  if (!BaseInfoBaseImpl::s_ti_by_name)
+    BaseInfoBaseImpl::s_ti_by_name   = new BaseInfoBaseImpl::ti_by_name_map_type;
+
+  // Register this instance in the static maps.
+  (*BaseInfoBaseImpl::s_bi_by_ti)[&tinfo] = this;
+  (*BaseInfoBaseImpl::s_ti_by_name)[tinfo.name()] = &tinfo;
+}
+
+
+/**
+ * @brief Destructor.
+ */
+BaseInfoBase::~BaseInfoBase()
+{
+  for (BaseInfoBaseImpl::ti_copyconversion_type::iterator it =
+         m_impl->m_ti_copyconversion_map.begin();
+       it != m_impl->m_ti_copyconversion_map.end();
+       ++it)
+  {
+    delete it->second;
+  }
+  delete m_impl;
+}
+
+
+/**
+ * @brief Find the @c BaseInfoBase instance for @c clid.
+ * @param clid The class ID of the class for which we want information.
+ *
+ * Returns 0 if no @c BaseInfoBase instance is available.
+ */
+const BaseInfoBase* BaseInfoBase::find (CLID clid)
+{
+  BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
+  const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
+  if (ti)
+    return BaseInfoBase::find (*ti);
+  return 0;
+}
+
+
+/**
+ * @brief Helper for @c find.
+ * @param tinfo The @c std::type_info of the class
+ *              for which we want information.
+ *
+ * Returns 0 if no @c BaseInfoBase instance is available.
+ */
+const BaseInfoBase* BaseInfoBase::find1 (const std::type_info& tinfo)
+{
+  BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
+  if (!BaseInfoBaseImpl::s_bi_by_ti) return 0;
+  BaseInfoBaseImpl::bi_by_ti_map_type::iterator i = 
+    BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
+  if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
+    if (!i->second->m_impl->m_needs_init)
+      return i->second;
+    i->second->m_impl->m_needs_init = false;
+  }
+
+  // Try the initlist.
+  if (BaseInfoBaseImpl::s_init_list) {
+    while (true) {
+      BaseInfoBaseImpl::init_list_t::iterator it = 
+        BaseInfoBaseImpl::s_init_list->find (&tinfo);
+      if (it == BaseInfoBaseImpl::s_init_list->end()) break;
+      BaseInfoBase::init_func_t* init = it->second;
+      BaseInfoBaseImpl::s_init_list->erase (it);
+      init();
+      i = BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
+    }
+  }
+  if (i != BaseInfoBaseImpl::s_bi_by_ti->end())
+    return i->second;
+
+  return 0;
+}
+
+
+/**
+ * @brief Find the @c BaseInfoBase instance for @c tinfo.
+ * @param tinfo The @c std::type_info of the class
+ *              for which we want information.
+ *
+ * Returns 0 if no @c BaseInfoBase instance is available.
+ */
+const BaseInfoBase* BaseInfoBase::find (const std::type_info& tinfo)
+{
+  const BaseInfoBase* bib = find1 (tinfo);
+
+  // If we didn't find it, try looking up by name.
+  // This to deal with the issue of sometimes getting duplicate
+  // @c std::type_info instances.
+  if (!bib && BaseInfoBaseImpl::s_ti_by_name) {
+    BaseInfoBaseImpl::ti_by_name_map_type::iterator i = 
+      BaseInfoBaseImpl::s_ti_by_name->find (tinfo.name());
+    if (i != BaseInfoBaseImpl::s_ti_by_name->end() && i->second != &tinfo)
+      bib = find1 (*i->second);
+  }
+
+  if (bib) {
+    BaseInfoBaseImpl& impl = *bib->m_impl;
+    if (impl.m_clid == CLID_NULL)
+      impl.m_clid = CLIDRegistry::typeinfoToCLID (*impl.m_typeinfo);
+  }
+
+  return bib;
+}
+
+
+/**
+ * @brief Register an initialization function.
+ * @param tinfo The @c std::type_info for the class being registered.
+ * @param init_func Function to initialize @c BaseInfo for the class.
+ */
+void BaseInfoBase::addInit (const std::type_info* tinfo,
+                            init_func_t* init_func)
+{
+  BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
+  if (!BaseInfoBaseImpl::s_init_list)
+    BaseInfoBaseImpl::s_init_list =
+      new BaseInfoBaseImpl::init_list_t;
+  BaseInfoBaseImpl::s_init_list->insert (std::make_pair (tinfo, init_func));
+
+  if (BaseInfoBaseImpl::s_bi_by_ti) {
+    auto i = BaseInfoBaseImpl::s_bi_by_ti->find (tinfo);
+    if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
+      BaseInfoBaseImpl& impl = *i->second->m_impl;
+      impl.m_needs_init = true;
+      if (impl.m_clid == CLID_NULL)
+        impl.m_clid = CLIDRegistry::typeinfoToCLID (*tinfo);
+    }
+  }
+}
+
+
+/**
+ * @brief Run initializations for this class, if needed.
+ */
+void BaseInfoBase::maybeInit()
+{
+  if (m_impl->m_needs_init)
+    find (*m_impl->m_typeinfo);
+}
+
+
+
+/// Declare the static members of @c BaseInfoBaseImpl.
+BaseInfoBaseImpl::bi_by_ti_map_type*        BaseInfoBaseImpl::s_bi_by_ti = 0;
+BaseInfoBaseImpl::ti_by_name_map_type*        BaseInfoBaseImpl::s_ti_by_name = 0;
+BaseInfoBaseImpl::init_list_t*               BaseInfoBaseImpl::s_init_list = 0;
+BaseInfoBaseImpl::mutex_t                    BaseInfoBaseImpl::s_mutex;
+
+// To get them deleted.
+BaseInfoBaseImpl::Deleter BaseInfoBaseImpl::s_deleter;
+BaseInfoBaseImpl::Deleter::~Deleter()
+{
+  delete s_bi_by_ti;
+  delete s_ti_by_name;
+  delete s_init_list;
+}
+
+
+// Helper for dumping within the debugger.
+void dumpBaseInfo()
+{
+  std::cout << "map:\n";
+  if (BaseInfoBaseImpl::s_bi_by_ti) {
+    std::vector<const std::type_info*> vv;
+    for (const auto& x : *BaseInfoBaseImpl::s_bi_by_ti)
+      vv.push_back (x.first);
+    std::sort (vv.begin(), vv.end());
+    for (const std::type_info* ti : vv)
+    {
+      const BaseInfoBase* bib = (*BaseInfoBaseImpl::s_bi_by_ti)[ti];
+      std::cout << ti << " " << bib->clid() << " [" << System::typeinfoName (*ti)
+                << "]\n";
+    }
+  }
+
+  std::cout << "\ninitlist:\n";
+  if (BaseInfoBaseImpl::s_init_list) {
+    for (const auto& x : *BaseInfoBaseImpl::s_init_list)
+      std::cout << x.first << " " << x.second << " ["
+                << System::typeinfoName (*x.first) << "]\n";
+  }
+}
+
+
+} // namespace SG
diff --git a/Control/AthenaKernel/test/BaseInfo_test.cxx b/Control/AthenaKernel/test/BaseInfo_test.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..981e046e1aa92932cb4ffc9bbd5e6fa06c627b2e
--- /dev/null
+++ b/Control/AthenaKernel/test/BaseInfo_test.cxx
@@ -0,0 +1,354 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file  AthenaKernel/test/BaseInfo_test.cxx
+ * @author scott snyder
+ * @date A while ago.
+ * @brief Regression test for BaseInfo.
+ */
+
+
+#undef NDEBUG
+
+#include "AthenaKernel/BaseInfo.h"
+#include "AthenaKernel/CLASS_DEF.h"
+#include "boost/assign/list_of.hpp"
+#include <iostream>
+#include <algorithm>
+#include <cassert>
+
+using std::cout;
+using boost::assign::list_of;
+
+struct AA
+{
+  AA (int the_x=0): x(the_x) {}
+  ~AA() { }
+  int x;
+};
+struct BB : public AA
+{
+  BB (int the_x=0) : AA(the_x) {}
+};
+struct CC : public BB
+{
+  CC (int the_x=0) : BB(the_x) {}
+};
+
+SG_BASE(BB, AA);
+SG_BASE(CC, BB);
+
+CLASS_DEF (AA, 1111, 2)
+CLASS_DEF (BB, 1112, 2)
+CLASS_DEF (CC, 1113, 2)
+
+struct M
+{
+  M (int the_x=0) : x(the_x) {}
+  virtual ~M() { }
+  int x;
+};
+struct N : virtual public M 
+{
+  N (int the_x=0) : M(the_x) {}
+};
+struct O : virtual public M
+{
+  O (int the_x=0) : M(the_x) {}
+};
+struct P : virtual public N, virtual public O
+{
+  P (int the_x=0) : M(the_x) {}
+};
+
+CLASS_DEF (M, 1114, 2)
+CLASS_DEF (N, 1115, 2)
+CLASS_DEF (O, 1116, 2)
+CLASS_DEF (P, 1117, 2)
+
+SG_BASE (N, SG_VIRTUAL (M));
+SG_BASE (O, SG_VIRTUAL (M));
+SG_BASES2 (P, SG_VIRTUAL (N), SG_VIRTUAL (O));
+
+struct X1 {};
+struct X2 : public X1 {};
+SG_BASE (X2, X1);
+
+struct Q : virtual public M
+{
+  Q (int the_x=0) : M(the_x) {}
+};
+struct R : virtual public N, virtual public O, virtual public Q
+{
+  R (int the_x=0) : M(the_x) {}
+};
+
+CLASS_DEF (Q, 1118, 2)
+CLASS_DEF (R, 1119, 2)
+
+SG_BASE (Q, SG_VIRTUAL (M));
+SG_BASES3 (R, SG_VIRTUAL (N),
+           SG_VIRTUAL (O),
+           SG_VIRTUAL (Q));
+
+
+struct I1 : public AA {};
+struct I2 : public AA {};
+SG_BASE (I1, AA);
+SG_BASE (I2, AA);
+CLASS_DEF (I2, 1120, 2)
+
+struct J : public AA, virtual public X1, public M {};
+SG_BASE(J, AA);
+SG_ADD_BASE(J, SG_VIRTUAL(X1));
+SG_ADD_BASE(J, M);
+
+struct K : public AA {};
+SG_ADD_BASE(K, AA);
+
+
+int test1()
+{
+  std::cout << "test1\n";
+
+  typedef SG::BaseInfo<CC> CC_C;
+  typedef SG::BaseInfo<R>  R_C;
+
+  std::vector<CLID> clids;
+  clids = CC_C::get_bases();
+  std::vector<CLID> exp1 = list_of
+    (ClassID_traits<CC>::ID())
+    (ClassID_traits<BB>::ID())
+    (ClassID_traits<AA>::ID());
+  std::sort (clids.begin(), clids.end());
+  std::sort (exp1.begin(), exp1.end());
+  assert (clids == exp1);
+
+  std::vector<const std::type_info*> tinfos;
+  tinfos = CC_C::get_ti_bases();
+  std::vector<const std::type_info*> exp1ti = list_of
+    (&typeid(CC))
+    (&typeid(BB))
+    (&typeid(AA));
+  std::sort (tinfos.begin(), tinfos.end());
+  std::sort (exp1ti.begin(), exp1ti.end());
+  assert (tinfos == exp1ti);
+
+  clids = R_C::get_bases();
+  std::vector<CLID> exp2 = list_of
+    (ClassID_traits<M>::ID())
+    (ClassID_traits<N>::ID())
+    (ClassID_traits<O>::ID())
+    (ClassID_traits<Q>::ID())
+    (ClassID_traits<R>::ID());
+  std::sort (clids.begin(), clids.end());
+  std::sort (exp2.begin(), exp2.end());
+  assert (clids == exp2);
+
+  tinfos = R_C::get_ti_bases();
+  std::vector<const std::type_info*> exp2ti = list_of
+    (&typeid(M))
+    (&typeid(N))
+    (&typeid(O))
+    (&typeid(Q))
+    (&typeid(R));
+  std::sort (tinfos.begin(), tinfos.end());
+  std::sort (exp2ti.begin(), exp2ti.end());
+  assert (tinfos == exp2ti);
+
+  SG::BaseInfoBase::castfn_t* castfn;
+
+  M* m0 = new M;
+  R* r1 = new R;
+  M* m1 = r1;
+  assert ((long)m1 != (long)r1);
+  M* m2 = (M*)R_C::cast (r1, ClassID_traits<M>::ID());
+  assert ((long)m1 == (long)m2);
+  m2 = (M*)R_C::cast (r1, typeid (M));
+  assert ((long)m1 == (long)m2);
+  R* r2 = (R*)R_C::castTo (m1, ClassID_traits<M>::ID());
+  assert ((long)r1 == (long)r2);
+  r2 = (R*)R_C::castTo (m1, typeid (M));
+  assert ((long)r1 == (long)r2);
+  r2 = (R*)R_C::castTo (m0, typeid (M));
+  assert (r2 == 0);
+
+  castfn = R_C::castfn (ClassID_traits<M>::ID());
+  assert ((long)m1 == (long)castfn(r1));
+  castfn = R_C::castfn (typeid (M));
+  assert ((long)m1 == (long)castfn(r1));
+  castfn = R_C::castfnTo (ClassID_traits<M>::ID());
+  assert ((long)r1 == (long)castfn(m1));
+  castfn = R_C::castfnTo (typeid (M));
+  assert ((long)r1 == (long)castfn(m1));
+  assert (0 == (long)castfn(m0));
+
+  assert (R_C::cast (r1, ClassID_traits<AA>::ID()) == 0);
+  assert (R_C::cast (r1, typeid (AA)) == 0);
+  assert (R_C::castTo (r1, ClassID_traits<AA>::ID()) == 0);
+  assert (R_C::castTo (r1, typeid (AA)) == 0);
+  assert (R_C::castfn (ClassID_traits<AA>::ID()) == 0);
+  assert (R_C::castfn (typeid (AA)) == 0);
+  assert (R_C::castfnTo (ClassID_traits<AA>::ID()) == 0);
+  assert (R_C::castfnTo (typeid (AA)) == 0);
+
+  assert (R_C::is_base (ClassID_traits<M>::ID()));
+  assert (R_C::is_base (typeid (M)));
+
+  assert (!R_C::is_base (ClassID_traits<AA>::ID()));
+  assert (!R_C::is_base (typeid (AA)));
+
+  assert (CC_C::is_base (ClassID_traits<AA>::ID()));
+  assert (CC_C::is_base (typeid (AA)));
+
+  assert (R_C::is_virtual (ClassID_traits<M>::ID()));
+  assert (R_C::is_virtual (typeid (M)));
+
+  assert (!CC_C::is_virtual (ClassID_traits<AA>::ID()));
+  assert (!CC_C::is_virtual (typeid (AA)));
+
+  typedef SG::BaseInfo<X2> X_C;
+  assert (X_C::is_base (typeid (X1)));
+  X2* x2 = new X2;
+  X1* x1 = (X1*)X_C::cast (x2, typeid (X1));
+  assert (x1 == x2);
+  X2* x2a = (X2*)X_C::castTo (x1, typeid (X1));
+  assert (x2a == 0); // castTo doesn't work now for non-polymorphic classes.
+
+  clids = SG::BaseInfoBase::find (ClassID_traits<CC>::ID())->get_bases();
+  std::sort (clids.begin(), clids.end());
+  assert (clids == exp1);
+  tinfos = SG::BaseInfoBase::find (ClassID_traits<CC>::ID())->get_ti_bases();
+  std::sort (tinfos.begin(), tinfos.end());
+  assert (tinfos == exp1ti);
+
+  clids = CC_C::baseinfo().get_bases();
+  std::sort (clids.begin(), clids.end());
+  assert (clids == exp1);
+  tinfos = CC_C::baseinfo().get_ti_bases();
+  std::sort (tinfos.begin(), tinfos.end());
+  assert (tinfos == exp1ti);
+
+  clids = SG::BaseInfoBase::find (typeid (CC))->get_bases();
+  std::sort (clids.begin(), clids.end());
+  assert (clids == exp1);
+  tinfos = SG::BaseInfoBase::find (typeid (CC))->get_ti_bases();
+  std::sort (tinfos.begin(), tinfos.end());
+  assert (tinfos == exp1ti);
+
+  assert (SG::BaseInfoBase::find (typeid(CC))->clid() ==
+          ClassID_traits<CC>::ID());
+  assert (SG::BaseInfoBase::find (typeid(CC))->typeinfo() == typeid(CC));
+
+  assert (SG::BaseInfoBase::find (99999) == 0);
+  assert (SG::BaseInfoBase::find (typeid(int)) == 0);
+
+  assert (typeid(SG::BaseType<SG::Bases<BB>::Base1>::type) == typeid(AA));
+  assert (typeid(SG::BaseType<SG::Bases<BB>::Base1>::is_virtual) ==
+          typeid(std::false_type));
+
+  assert (typeid(SG::BaseType<SG::Bases<N>::Base1>::type) == typeid(M));
+  assert (typeid(SG::BaseType<SG::Bases<N>::Base1>::is_virtual) ==
+          typeid(std::true_type));
+
+  std::vector<CLID> exp3 = list_of
+    (ClassID_traits<AA>::ID());
+  clids = SG::BaseInfoBase::find (typeid (I1))->get_bases();
+  assert (clids == exp3);
+
+  std::vector<const std::type_info*> exp3ti = list_of
+    (&typeid (AA))
+    (&typeid (I1));
+  std::sort (exp3ti.begin(), exp3ti.end());
+  tinfos = SG::BaseInfoBase::find (typeid (I1))->get_ti_bases();
+  std::sort (tinfos.begin(), tinfos.end());
+  assert (tinfos == exp3ti);
+
+  std::vector<CLID> exp4 = list_of
+    (ClassID_traits<AA>::ID())
+    (ClassID_traits<I2>::ID());
+  clids = SG::BaseInfoBase::find (ClassID_traits<I2>::ID())->get_bases();
+  std::sort (clids.begin(), clids.end());
+  assert (clids == exp4);
+
+  std::vector<const std::type_info*> exp4ti = list_of
+    (&typeid (AA))
+    (&typeid (I2));
+  std::sort (exp4ti.begin(), exp4ti.end());
+  tinfos = SG::BaseInfoBase::find (typeid (I2))->get_ti_bases();
+  std::sort (tinfos.begin(), tinfos.end());
+  assert (tinfos == exp4ti);
+
+  const SG::BaseInfoBase* jbib = SG::BaseInfoBase::find (typeid (J));
+  tinfos = jbib->get_ti_bases();
+  std::vector<const std::type_info*> exp5ti = list_of
+    (&typeid (AA))
+    (&typeid (X1))
+    (&typeid (M))
+    (&typeid (J));
+  std::sort (exp5ti.begin(), exp5ti.end());
+  std::sort (tinfos.begin(), tinfos.end());
+  assert (tinfos == exp5ti);
+  assert (!jbib->is_virtual (typeid (AA)));
+  assert ( jbib->is_virtual (typeid (X1)));
+  assert (!jbib->is_virtual (typeid (M)));
+
+  const SG::BaseInfoBase* kbib = SG::BaseInfoBase::find (typeid (K));
+  tinfos = kbib->get_ti_bases();
+  std::vector<const std::type_info*> exp6ti = list_of
+    (&typeid (AA))
+    (&typeid (K));
+  std::sort (exp6ti.begin(), exp6ti.end());
+  std::sort (tinfos.begin(), tinfos.end());
+  assert (tinfos == exp6ti);
+    
+  return 0;
+}
+
+
+class KCopyConversion
+  : public SG::CopyConversion<K, M>
+{
+public:
+  void convert (const K& src, M& dst) const
+  { dst.x = src.x; }
+};
+
+SG_ADD_COPY_CONVERSION(K, KCopyConversion);
+
+
+// Test copying conversions.
+void test2()
+{
+  std::cout << "test2\n";
+  const SG::BaseInfoBase& bib = SG::BaseInfo<K>::baseinfo();
+  std::vector<CLID> clids = bib.get_copy_conversions();
+  std::vector<CLID> exp1 = list_of
+    (ClassID_traits<M>::ID());
+  assert (clids == exp1);
+
+  const SG::CopyConversionBase* b = bib.copy_conversion (clids[0]);
+  assert (b == bib.copy_conversion (typeid (M)));
+  assert (0 == bib.copy_conversion (typeid (X1)));
+  assert (0 == bib.copy_conversion (typeid (Q)));
+  assert (0 == bib.copy_conversion (ClassID_traits<Q>::ID()));
+
+  K k;
+  k.x = 10;
+  M m;
+  m.x = 0;
+  b->convertUntyped (&k, &m);
+  assert (m.x == 10);
+}
+
+
+int main()
+{
+  test1();
+  test2();
+  return 0;
+}
+