diff --git a/src/App/Document.cpp b/src/App/Document.cpp index fc80d7069..b042326cf 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -1894,14 +1894,15 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, string ObjectName; if (!base) return 0; - if (!base->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { + + App::DocumentObject* pcObject = dynamic_cast(base); + if (!pcObject) { delete base; std::stringstream str; str << "'" << sType << "' is not a document object type"; throw Base::TypeError(str.str()); } - App::DocumentObject* pcObject = dynamic_cast(base); pcObject->setDocument(this); // do no transactions if we do a rollback! diff --git a/src/App/DocumentObject.h b/src/App/DocumentObject.h index f6741985e..c1026b81a 100644 --- a/src/App/DocumentObject.h +++ b/src/App/DocumentObject.h @@ -259,5 +259,26 @@ protected: // attributes } //namespace App +/** + * Overload of freecads base class cast for all cases without any virtual inheritance + */ +template T * freecad_dynamic_cast(App::DocumentObject * t) +{ + if (t && t->isDerivedFrom(T::getClassTypeId())) + return static_cast(t); + else + return nullptr; +} + +/** + * See explaination above + */ +template const T * freecad_dynamic_cast(const App::DocumentObject * t) +{ + if (t && t->isDerivedFrom(T::getClassTypeId())) + return static_cast(t); + else + return nullptr; +} #endif // APP_DOCUMENTOBJECT_H diff --git a/src/App/ExtensionContainerPyImp.cpp b/src/App/ExtensionContainerPyImp.cpp index 1c47bd35a..284a8a736 100644 --- a/src/App/ExtensionContainerPyImp.cpp +++ b/src/App/ExtensionContainerPyImp.cpp @@ -149,7 +149,7 @@ PyObject* ExtensionContainerPy::addExtension(PyObject *args) { throw Py::Exception(Base::BaseExceptionFreeCADError,str.str()); } - ext->initExtension(dynamic_cast(getExtensionContainerPtr())); + ext->initExtension(getExtensionContainerPtr()); //set the proxy to allow python overrides App::Property* pp = ext->getPropertyByName("Proxy"); diff --git a/src/App/OriginGroupExtension.cpp b/src/App/OriginGroupExtension.cpp index d98efdf18..afe14a519 100644 --- a/src/App/OriginGroupExtension.cpp +++ b/src/App/OriginGroupExtension.cpp @@ -70,13 +70,15 @@ App::DocumentObject *OriginGroupExtension::getGroupOfObject (const DocumentObjec std::vector grps = doc->getObjectsWithExtension ( OriginGroupExtension::getClassTypeId() ); for (auto grpObj: grps) { OriginGroupExtension* grp = dynamic_cast (grpObj->getExtension(OriginGroupExtension::getClassTypeId())); + if(!grp) throw Base::TypeError("Wrong type in origin group extenion"); + if ( indirect ) { if ( grp->geoHasObject (obj) ) { - return dynamic_cast(grp); + return grp->getExtendedObject(); } } else { if ( grp->hasObject (obj) ) { - return dynamic_cast(grp); + return grp->getExtendedObject(); } } } diff --git a/src/App/PropertyLinks.cpp b/src/App/PropertyLinks.cpp index b44be4671..9e5466981 100644 --- a/src/App/PropertyLinks.cpp +++ b/src/App/PropertyLinks.cpp @@ -131,6 +131,7 @@ void PropertyLink::Restore(Base::XMLReader &reader) if (name != "") { DocumentObject* parent = dynamic_cast(getContainer()); + if(!parent) throw Base::TypeError("Property container is not document object"); App::Document* document = parent->getDocument(); DocumentObject* object = document ? document->getObject(name.c_str()) : 0; if (!object) { @@ -289,6 +290,7 @@ void PropertyLinkList::Restore(Base::XMLReader &reader) // document. Thus, we should silently ingore this. // Property not in an object! DocumentObject* father = dynamic_cast(getContainer()); + if(!father) throw Base::TypeError("Property container is not document object"); App::Document* document = father->getDocument(); DocumentObject* child = document ? document->getObject(name.c_str()) : 0; if (child) @@ -479,7 +481,10 @@ void PropertyLinkSub::Restore(Base::XMLReader &reader) DocumentObject *pcObject; if (!name.empty()) { - App::Document* document = dynamic_cast(getContainer())->getDocument(); + + auto* parent = dynamic_cast(getContainer()); + if(!parent) throw Base::TypeError("Property container is not document object"); + App::Document* document = parent->getDocument(); pcObject = document ? document->getObject(name.c_str()) : 0; if (!pcObject) { if (reader.isVerbose()) { @@ -807,7 +812,6 @@ void PropertyLinkSubList::Restore(Base::XMLReader &reader) reader.readElement("LinkSubList"); // get the value of my attribute int count = reader.getAttributeAsInteger("count"); - assert(getContainer()->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId()) ); std::vector values; values.reserve(count); @@ -821,6 +825,7 @@ void PropertyLinkSubList::Restore(Base::XMLReader &reader) // document. Thus, we should silently ignore this. // Property not in an object! DocumentObject* father = dynamic_cast(getContainer()); + if(!father) throw Base::TypeError("Property container is not document object"); App::Document* document = father->getDocument(); DocumentObject* child = document ? document->getObject(name.c_str()) : 0; if (child) diff --git a/src/Base/BaseClass.h b/src/Base/BaseClass.h index 2e7622910..bfe49baa6 100644 --- a/src/Base/BaseClass.h +++ b/src/Base/BaseClass.h @@ -105,30 +105,24 @@ public: /** * Template that works just like dynamic_cast, but expects the argument to - * inherit from Base::BaseClass. + * inherit from Base::BaseClass. Note thst for base class this is exactly the same as a dynamic_cast. + * The reason for that is that it is not possible to static_cast base to anything in the inheritance + * chain after PropertyContainer. The reason for this is the used virtual inheritance. + * However, the function can be overload for different cast between objects in the inheritnce + * chain after PropertyContainer, for example from DocumentObject to all its derived types- * */ - template T * freecad_dynamic_cast(Base::BaseClass * t) { - if (t && t->isDerivedFrom(T::getClassTypeId())) - return dynamic_cast(t); - else - return 0; + return dynamic_cast(t); } /** - * Template that works just like dynamic_cast, but expects the argument to - * inherit from a const Base::BaseClass. - * + * See explaination above */ - template const T * freecad_dynamic_cast(const Base::BaseClass * t) { - if (t && t->isDerivedFrom(T::getClassTypeId())) - return dynamic_cast(t); - else - return 0; + return dynamic_cast(t); } diff --git a/src/Gui/ViewProviderGeoFeatureGroupExtension.cpp b/src/Gui/ViewProviderGeoFeatureGroupExtension.cpp index ba532f0cb..867e2d87f 100644 --- a/src/Gui/ViewProviderGeoFeatureGroupExtension.cpp +++ b/src/Gui/ViewProviderGeoFeatureGroupExtension.cpp @@ -53,7 +53,7 @@ ViewProviderGeoFeatureGroupExtension::~ViewProviderGeoFeatureGroupExtension() std::vector ViewProviderGeoFeatureGroupExtension::extensionClaimChildren3D(void) const { auto* ext = getExtendedViewProvider()->getObject()->getExtensionByType(); - return ext->getGeoSubObjects(); + return ext ? ext->getGeoSubObjects() : std::vector(); } void ViewProviderGeoFeatureGroupExtension::extensionAttach(App::DocumentObject* pcObject) @@ -84,7 +84,7 @@ std::vector ViewProviderGeoFeatureGroupExtension::extensionGetDispl void ViewProviderGeoFeatureGroupExtension::extensionUpdateData(const App::Property* prop) { auto obj = getExtendedViewProvider()->getObject()->getExtensionByType(); - if (prop == &obj->Placement) { + if (obj && prop == &obj->Placement) { getExtendedViewProvider()->setTransformation ( obj->Placement.getValue().toMatrix() ); } else { ViewProviderGroupExtension::extensionUpdateData ( prop ); diff --git a/src/Gui/ViewProviderOriginGroupExtension.cpp b/src/Gui/ViewProviderOriginGroupExtension.cpp index e22121b23..45e8a7139 100644 --- a/src/Gui/ViewProviderOriginGroupExtension.cpp +++ b/src/Gui/ViewProviderOriginGroupExtension.cpp @@ -61,6 +61,9 @@ std::vector ViewProviderOriginGroupExtension::constructChi const std::vector &children ) const { auto* group = getExtendedViewProvider()->getObject()->getExtensionByType(); + if(!group) + return children; + App::DocumentObject *originObj = group->Origin.getValue(); // Origin must be first @@ -102,7 +105,7 @@ void ViewProviderOriginGroupExtension::extensionAttach(App::DocumentObject *pcOb void ViewProviderOriginGroupExtension::extensionUpdateData( const App::Property* prop ) { auto* group = getExtendedViewProvider()->getObject()->getExtensionByType(); - if ( prop == &group->Group ) { + if ( group && prop == &group->Group ) { updateOriginSize(); } @@ -111,7 +114,7 @@ void ViewProviderOriginGroupExtension::extensionUpdateData( const App::Property* void ViewProviderOriginGroupExtension::slotChangedObjectApp ( const App::DocumentObject& obj) { auto* group = getExtendedViewProvider()->getObject()->getExtensionByType(); - if ( group->hasObject (&obj, /*recusive=*/ true ) ) { + if ( group && group->hasObject (&obj, /*recusive=*/ true ) ) { updateOriginSize (); } } @@ -132,6 +135,8 @@ void ViewProviderOriginGroupExtension::slotChangedObjectGui ( const Gui::ViewPro void ViewProviderOriginGroupExtension::updateOriginSize () { auto* group = getExtendedViewProvider()->getObject()->getExtensionByType(); + if(!group) + return; // obtain an Origin and it's ViewProvider App::Origin* origin = 0; diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index 0180b61ec..23533541b 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -288,8 +288,8 @@ QString PropertyItem::pythonIdentifier(const App::Property* prop) const QString propName = QString::fromLatin1(parent->getPropertyName(prop)); return QString::fromLatin1("FreeCAD.getDocument(\"%1\").%2").arg(docName).arg(propName); } - if (parent->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { - App::DocumentObject* obj = dynamic_cast(parent); + App::DocumentObject* obj = dynamic_cast(parent); + if (obj) { App::Document* doc = obj->getDocument(); QString docName = QString::fromLatin1(App::GetApplication().getDocumentName(doc)); QString objName = QString::fromLatin1(obj->getNameInDocument()); @@ -3375,13 +3375,12 @@ QVariant PropertyLinkItem::value(const App::Property* prop) const else { // no object assigned // the document name - if (c->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { - App::DocumentObject* obj = dynamic_cast(c); + App::DocumentObject* obj = dynamic_cast(c); + if (obj) list << QString::fromLatin1(obj->getDocument()->getName()); - } - else { + else list << QString::fromLatin1(""); - } + // the internal object name list << QString::fromLatin1("Null"); // the object label @@ -3389,13 +3388,11 @@ QVariant PropertyLinkItem::value(const App::Property* prop) const } // the name of this object - if (c->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { - App::DocumentObject* obj = dynamic_cast(c); - list << QString::fromLatin1(obj->getNameInDocument()); - } - else { + App::DocumentObject* cobj = dynamic_cast(c); + if (cobj) + list << QString::fromLatin1(cobj->getNameInDocument()); + else list << QString::fromLatin1("Null"); - } return QVariant(list); } diff --git a/src/Mod/Fem/App/PropertyPostDataObject.cpp b/src/Mod/Fem/App/PropertyPostDataObject.cpp index 7e27d6aaf..3d8ce7cc5 100644 --- a/src/Mod/Fem/App/PropertyPostDataObject.cpp +++ b/src/Mod/Fem/App/PropertyPostDataObject.cpp @@ -263,10 +263,11 @@ void PropertyPostDataObject::SaveDocFile (Base::Writer &writer) const // We only print an error message but continue writing the next files to the // stream... App::PropertyContainer* father = this->getContainer(); - if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + if (father) { App::DocumentObject* obj = dynamic_cast(father); - Base::Console().Error("Dataset of '%s' cannot be written to vtk file '%s'\n", - obj->Label.getValue(),fi.filePath().c_str()); + if(obj) + Base::Console().Error("Dataset of '%s' cannot be written to vtk file '%s'\n", + obj->Label.getValue(),fi.filePath().c_str()); } else { Base::Console().Error("Cannot save vtk file '%s'\n", fi.filePath().c_str()); @@ -331,10 +332,11 @@ void PropertyPostDataObject::RestoreDocFile(Base::Reader &reader) // We only print an error message but continue reading the next files from the // stream... App::PropertyContainer* father = this->getContainer(); - if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + if (father) { App::DocumentObject* obj = dynamic_cast(father); - Base::Console().Error("Dataset file '%s' with data of '%s' seems to be empty\n", - fi.filePath().c_str(),obj->Label.getValue()); + if(obj) + Base::Console().Error("Dataset file '%s' with data of '%s' seems to be empty\n", + fi.filePath().c_str(),obj->Label.getValue()); } else { Base::Console().Warning("Loaded Dataset file '%s' seems to be empty\n", fi.filePath().c_str()); diff --git a/src/Mod/Part/App/PropertyTopoShape.cpp b/src/Mod/Part/App/PropertyTopoShape.cpp index 3b4b775b8..a24bbb23f 100644 --- a/src/Mod/Part/App/PropertyTopoShape.cpp +++ b/src/Mod/Part/App/PropertyTopoShape.cpp @@ -296,10 +296,11 @@ void PropertyPartShape::SaveDocFile (Base::Writer &writer) const // We only print an error message but continue writing the next files to the // stream... App::PropertyContainer* father = this->getContainer(); - if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + if (father) { App::DocumentObject* obj = dynamic_cast(father); - Base::Console().Error("Shape of '%s' cannot be written to BRep file '%s'\n", - obj->Label.getValue(),fi.filePath().c_str()); + if(obj) + Base::Console().Error("Shape of '%s' cannot be written to BRep file '%s'\n", + obj->Label.getValue(),fi.filePath().c_str()); } else { Base::Console().Error("Cannot save BRep file '%s'\n", fi.filePath().c_str()); @@ -375,10 +376,11 @@ void PropertyPartShape::RestoreDocFile(Base::Reader &reader) // We only print an error message but continue reading the next files from the // stream... App::PropertyContainer* father = this->getContainer(); - if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + if (father) { App::DocumentObject* obj = dynamic_cast(father); - Base::Console().Error("BRep file '%s' with shape of '%s' seems to be empty\n", - fi.filePath().c_str(),obj->Label.getValue()); + if(obj) + Base::Console().Error("BRep file '%s' with shape of '%s' seems to be empty\n", + fi.filePath().c_str(),obj->Label.getValue()); } else { Base::Console().Warning("Loaded BRep file '%s' seems to be empty\n", fi.filePath().c_str()); diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 5df71fc61..7c573e4f7 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -442,7 +442,7 @@ void CmdPartDesignNewSketch::activated(int iMsg) auto group = App::GeoFeatureGroupExtension::getGroupOfObject ( pcActiveBody ); App::GeoFeatureGroupExtension* geoGroup = nullptr; if(group) - geoGroup = dynamic_cast(group->getExtension(App::GeoFeatureGroupExtension::getClassTypeId())); + geoGroup = group->getExtensionByType(); std::vector planes; std::vector status; diff --git a/src/Mod/PartDesign/Gui/ViewProviderDatum.cpp b/src/Mod/PartDesign/Gui/ViewProviderDatum.cpp index b44758166..5e1a6c4cf 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderDatum.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderDatum.cpp @@ -330,7 +330,9 @@ SbBox3f ViewProviderDatum::getRelevantBoundBox () const { App::DocumentObject* group = App::DocumentObjectGroup::getGroupOfObject ( this->getObject () ); if(group) { - objs = dynamic_cast(group->getExtension(App::GroupExtension::getClassTypeId()))->getObjects (); + auto* ext = group->getExtensionByType(); + if(ext) + objs = ext->getObjects (); } else { // Fallback to whole document objs = this->getObject ()->getDocument ()->getObjects ();