0028355: Stating wrong parent class in DEFINE_STANDARD_RTTIEXT is not recognized...
authorBenjamin Bihler <benjamin.bihler@compositence.de>
Thu, 19 Jan 2017 13:48:08 +0000 (16:48 +0300)
committerapn <apn@opencascade.com>
Thu, 19 Jan 2017 14:25:56 +0000 (17:25 +0300)
Added compile-time checks (static_assert) in DEFINE_STANDARD_RTTI*(A,B) macros to check that A is actually the class being defined, and B is its base class.
For GCC compiler version 4.7 and later on, check ensures that B is direct base class of A.

Fixed dubious RTTI definitions.

samples/qt/FuncDemo/src/CircleDriver.h
samples/qt/FuncDemo/src/ConeDriver.h
samples/qt/FuncDemo/src/CylinderDriver.h
samples/qt/FuncDemo/src/PointDriver.h
samples/qt/FuncDemo/src/PrismDriver.h
samples/qt/FuncDemo/src/ShapeSaverDriver.h
src/AIS/AIS_AnimationTimer.hxx
src/SelectMgr/SelectMgr_TriangularFrustum.hxx
src/Standard/Standard_Type.hxx
src/StepVisual/StepVisual_CharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation.hxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx

index 3e3be8b..11d55c2 100644 (file)
@@ -30,7 +30,7 @@ public:
        // Execution.
        virtual Standard_Integer Execute(Handle(TFunction_Logbook)& log) const;
 
-       DEFINE_STANDARD_RTTIEXT(CircleDriver, TFunction_Driver)
+       DEFINE_STANDARD_RTTIEXT(CircleDriver, BaseDriver)
 };
 
 #endif // !defined(_CIRCLEDRIVER_H_)
index c397b77..a7f9439 100644 (file)
@@ -30,7 +30,7 @@ public:
        // Execution.
        virtual Standard_Integer Execute(Handle(TFunction_Logbook)& log) const;
 
-       DEFINE_STANDARD_RTTIEXT(ConeDriver, TFunction_Driver)
+       DEFINE_STANDARD_RTTIEXT(ConeDriver, BaseDriver)
 };
 
 #endif // !defined(_CONEDRIVER_H_)
index 322d186..bfa8ee6 100644 (file)
@@ -30,7 +30,7 @@ public:
        // Execution.
        virtual Standard_Integer Execute(Handle(TFunction_Logbook)& log) const;
 
-       DEFINE_STANDARD_RTTIEXT(CylinderDriver, TFunction_Driver)
+       DEFINE_STANDARD_RTTIEXT(CylinderDriver, BaseDriver)
 };
 
 #endif // !defined(_CYLINDERDRIVER_H_)
index a71591b..0159237 100644 (file)
@@ -30,7 +30,7 @@ public:
        // Execution.
        virtual Standard_Integer Execute(Handle(TFunction_Logbook)& log) const;
 
-       DEFINE_STANDARD_RTTIEXT(PointDriver, TFunction_Driver)
+       DEFINE_STANDARD_RTTIEXT(PointDriver, BaseDriver)
 };
 
 #endif // !defined(_PointDRIVER_H_)
index 5f11dcb..778b1cd 100644 (file)
@@ -30,7 +30,7 @@ public:
        // Execution.
        virtual Standard_Integer Execute(Handle(TFunction_Logbook)& log) const;
 
-       DEFINE_STANDARD_RTTIEXT(PrismDriver, TFunction_Driver)
+       DEFINE_STANDARD_RTTIEXT(PrismDriver, BaseDriver)
 };
 
 #endif // !defined(_PRISMDRIVER_H_)
index cf3c399..5247949 100644 (file)
@@ -30,7 +30,7 @@ public:
        // Execution.
        virtual Standard_Integer Execute(Handle(TFunction_Logbook)& log) const;
 
-       DEFINE_STANDARD_RTTIEXT(ShapeSaverDriver, TFunction_Driver)
+       DEFINE_STANDARD_RTTIEXT(ShapeSaverDriver, BaseDriver)
 };
 
 #endif // !defined(_SHAPESAVERDRIVER_H_)
index 14add51..1970ead 100644 (file)
@@ -22,7 +22,7 @@
 //! Auxiliary class defining the animation timer.
 class AIS_AnimationTimer : public Standard_Transient
 {
-  DEFINE_STANDARD_RTTIEXT(AIS_Animation, Standard_Transient)
+  DEFINE_STANDARD_RTTIEXT(AIS_AnimationTimer, Standard_Transient)
 public:
 
   //! Empty constructor.
index 4e32813..c7851cc 100644 (file)
@@ -92,7 +92,7 @@ private:
 
   void cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum) const;
 
-  DEFINE_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum,Standard_Transient)
+  DEFINE_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum,SelectMgr_Frustum<3>)
 };
 
 #endif // _SelectMgr_TriangularFrustum_HeaderFile
index 76e9725..bbcf007 100644 (file)
 
 #include <typeinfo>
 
+// Auxiliary tools to check at compile time that class declared as base in 
+// DEFINE_STANDARD_RTTI* macro is actually a base class.
+// For GCC 4.7+, more strict check is possible -- ensuring that base class 
+// is direct base -- using non-standard C++ reflection functionality.
+#if ! defined(OCC_CHECK_BASE_CLASS)
+#if (defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ > 4)))
+
+#include <tr2/type_traits>
+#include <tuple>
+
+namespace opencascade 
+{
+  template<typename T>
+  struct direct_base_class_as_tuple {};
+
+  template<typename ... Ts>
+  struct direct_base_class_as_tuple<std::tr2::__reflection_typelist<Ts...> >
+  {
+    typedef std::tuple<Ts...> type;
+  };
+
+  template <typename T, typename Tuple>
+  struct has_type;
+
+  template <typename T>
+  struct has_type<T, std::tuple<> > : std::false_type {};
+
+  template <typename T, typename U, typename... Ts>
+  struct has_type<T, std::tuple<U, Ts...> > : has_type<T, std::tuple<Ts...> > {};
+
+  template <typename T, typename... Ts>
+  struct has_type<T, std::tuple<T, Ts...> > : std::true_type {};
+}
+
+#define OCC_CHECK_BASE_CLASS(Class,Base) \
+  using direct_base_classes = opencascade::direct_base_class_as_tuple<std::tr2::direct_bases<Class>::type>::type; \
+  static_assert(opencascade::has_type<Base, direct_base_classes>::type::value, "OCCT RTTI definition is incorrect: " #Base " is not direct base class of " #Class);
+
+#else /* ! GCC 4.7+ */
+
+#define OCC_CHECK_BASE_CLASS(Class,Base) \
+  static_assert(opencascade::is_base_but_not_same<Base, Class>::value, "OCCT RTTI definition is incorrect: " #Base " is not base class of " #Class);
+
+#endif /* GCC 4.7+ */
+#endif /* ! defined(OCC_CHECK_BASE_CLASS) */
+
 //! Helper macro to get instance of a type descriptor for a class in a legacy way.
 #define STANDARD_TYPE(theType) theType::get_type_descriptor()
 
 #define DEFINE_STANDARD_RTTI_INLINE(Class,Base) \
 public: \
   typedef Base base_type; \
-  static const char* get_type_name () { return #Class; } \
+  static const char* get_type_name () { return #Class; OCC_CHECK_BASE_CLASS(Class,Base) } \
   static const Handle(Standard_Type)& get_type_descriptor () { return Standard_Type::Instance<Class>(); } \
-  virtual const Handle(Standard_Type)& DynamicType() const Standard_OVERRIDE \
-  { return STANDARD_TYPE(Class); }
+  virtual const Handle(Standard_Type)& DynamicType() const Standard_OVERRIDE { \
+    static_assert(std::is_same<const Class*, decltype(this)>::value, "OCCT RTTI definition is misplaced: current class is not " #Class); \
+    return get_type_descriptor (); \
+  }
 
 //! Helper macro to be included in definition of the classes inheriting
 //! Standard_Transient to enable use of OCCT RTTI.
@@ -45,14 +93,17 @@ public: \
 #define DEFINE_STANDARD_RTTIEXT(Class,Base) \
 public: \
   typedef Base base_type; \
-  static const char* get_type_name () { return #Class; } \
+  static const char* get_type_name () { return #Class; OCC_CHECK_BASE_CLASS(Class,Base) } \
   Standard_EXPORT static const Handle(Standard_Type)& get_type_descriptor (); \
   Standard_EXPORT virtual const Handle(Standard_Type)& DynamicType() const Standard_OVERRIDE;
 
 //! Defines implementation of type descriptor and DynamicType() function
 #define IMPLEMENT_STANDARD_RTTIEXT(Class,Base) \
   const Handle(Standard_Type)& Class::get_type_descriptor () { return Standard_Type::Instance<Class>(); } \
-  const Handle(Standard_Type)& Class::DynamicType() const { return get_type_descriptor(); }
+  const Handle(Standard_Type)& Class::DynamicType() const { \
+    static_assert(std::is_same<const Class*, decltype(this)>::value, "OCCT RTTI definition is misplaced: current class is not " #Class); \
+    return STANDARD_TYPE(Class); \
+  }
 
 // forward declaration of type_instance class
 namespace opencascade {
index d8df7d2..4a49329 100644 (file)
@@ -32,7 +32,7 @@ public:
   
   Standard_EXPORT StepVisual_CharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation();
 
-  DEFINE_STANDARD_RTTIEXT(CharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation, StepVisual_DraughtingModel)
+  DEFINE_STANDARD_RTTIEXT(StepVisual_CharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation, StepVisual_DraughtingModel)
 
 };
 #endif // _StepVisual_CharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation_HeaderFile
index 914ebdc..358a35a 100644 (file)
@@ -4809,7 +4809,7 @@ public:
     myMarkerAspect = theMarkerAspect;
   }
 
-  DEFINE_STANDARD_RTTI_INLINE(MyPArrayObject,AIS_InteractiveObject);
+  DEFINE_STANDARD_RTTI_INLINE(ViewerTest_MarkersArrayObject,AIS_InteractiveObject);
 
 private: