canvas/source/cairo/cairo_repainttarget.hxx                 |    2 
 canvas/source/cairo/cairo_surfaceprovider.hxx               |    2 
 canvas/source/vcl/repainttarget.hxx                         |    2 
 chart2/inc/ChartModel.hxx                                   |    3 
 chart2/source/controller/inc/TabPageNotifiable.hxx          |    2 
 compilerplugins/clang/crosscast.cxx                         |  166 ++++++++++++
 compilerplugins/clang/test/crosscast.cxx                    |   96 ++++++
 include/drawinglayer/primitive2d/svggradientprimitive2d.hxx |    2 
 include/editeng/unotext.hxx                                 |    3 
 include/embeddedobj/embeddedupdate.hxx                      |    2 
 include/oox/core/contexthandler2.hxx                        |    2 
 include/oox/mathml/export.hxx                               |    2 
 include/oox/mathml/import.hxx                               |    2 
 include/sal/types.h                                         |   12 
 include/sfx2/Metadatable.hxx                                |    2 
 include/sfx2/digitalsignatures.hxx                          |    2 
 include/sfx2/sidebar/IContextChangeReceiver.hxx             |    2 
 include/sfx2/sidebar/ILayoutableWindow.hxx                  |    2 
 include/sfx2/sidebar/SidebarModelUpdate.hxx                 |    2 
 include/sfx2/xmldump.hxx                                    |    2 
 include/svl/stylesheetuser.hxx                              |    2 
 include/svl/undo.hxx                                        |    2 
 include/svx/ipolypolygoneditorcontroller.hxx                |    2 
 include/vcl/IContext.hxx                                    |    2 
 include/vcl/ITiledRenderable.hxx                            |    2 
 include/vcl/NotebookbarContextControl.hxx                   |    2 
 include/vcl/gdimetafiletools.hxx                            |    2 
 include/vcl/syswin.hxx                                      |    2 
 include/vcl/toolkit/field.hxx                               |    2 
 include/vcl/transfer.hxx                                    |    4 
 include/vcl/wizardmachine.hxx                               |    2 
 include/xmloff/settingsstore.hxx                            |    2 
 include/xmloff/xmlimp.hxx                                   |    2 
 reportdesign/inc/RptObject.hxx                              |    2 
 sc/source/ui/inc/IAnyRefDialog.hxx                          |    3 
 sd/source/filter/eppt/epptbase.hxx                          |    2 
 sdext/source/presenter/PresenterViewFactory.hxx             |    2 
 slideshow/source/inc/cursormanager.hxx                      |    2 
 solenv/CompilerTest_compilerplugins_clang.mk                |    1 
 svx/source/inc/celltypes.hxx                                |    2 
 svx/source/inc/tablemodel.hxx                               |    2 
 sw/inc/IDocumentUndoRedo.hxx                                |    2 
 sw/inc/IMark.hxx                                            |    2 
 sw/inc/calbck.hxx                                           |    4 
 sw/inc/contentindex.hxx                                     |    2 
 sw/source/core/inc/flowfrm.hxx                              |    2 
 sw/source/core/unocore/unodraw.cxx                          |    3 
 sw/source/uibase/inc/FrameControl.hxx                       |    2 
 vcl/inc/IPrioritable.hxx                                    |    2 
 vcl/inc/jsdialog/jsdialogbuilder.hxx                        |    2 
 vcl/inc/unx/x11/x11gdiimpl.h                                |    2 
 xmlsecurity/inc/certificate.hxx                             |    2 
 52 files changed, 331 insertions(+), 48 deletions(-)

New commits:
commit 160689897cd5d46be0b4b1bdf67242d42bb72598
Author:     Stephan Bergmann <sberg...@redhat.com>
AuthorDate: Tue Nov 29 10:01:59 2022 +0100
Commit:     Stephan Bergmann <sberg...@redhat.com>
CommitDate: Tue Nov 29 18:07:23 2022 +0100

    New loplugin:crosscast
    
    ...inspired by 2fa426da15a12e2a63554247e3c1c3f8c0ec5c24 "Fix dynamic_cast 
after
    splitting OutputDevice and vcl::Window class hierarchies":
    
    "Find uses of dynamic_cast that cast between unrelated classes, which is
    suspicious and might indicate a bug.  The heuristic used to consider two 
classes
    unrelated is that neither derives from the other (directly or indirectly) 
and
    they do not both virtually derive (directly or indirectly) from a common 
third
    class.  Additionally, class definitions can be attributed with
    SAL_LOPLUGIN_ANNOTATE("crosscast") (from sal/types.h) to suppress false 
warnings
    about known-good cases casting from or to such a class."
    (quoting compilerplugins/clang/crosscast.cxx)
    
    This found two additional errors, 7a82ea5c79adee70eddf74ac53347544766a91b0 
"Fix
    presumed typo" and fc6aa9e49973c845915754caf765ff57e5b0cd59 "fix assert", 
and
    one still-open case that looks like an error, see the TODO comment in
    sw/source/core/unocore/unodraw.cxx.
    
    In addition to that it flagged another 102 uses of dynamic_cast as 
suspicious,
    which have all been addressed, at least for now, by marking certain classes 
as
    SAL_LOPLUGIN_ANNOTATE("crosscast"), see below.  (Where this commit also adds
    that generic SAL_LOPLUGIN_ANNOTATE mechanism to include/sal/types.h.)  
However,
    some of those annotations might benefit from further inspection and clean up
    similar to recent 8858962ec09478c203d43feb58f550bb36af37bb "Introduce
    ParagraphProeprtiesPropertyMap", 8467aa93e2038b3030e1add94e0ca6cc4ad44032
    "Replace a dynamic_cast with UNO_QUERY",
    a534361141d69096d896e6e0552d19f3138eeeb3 "Fold OldBasicPassword into
    basic::SfxScriptLibraryContainer", and 
589e03fb4c3b05bf3742c0cb8b366322ffdf1fa9
    "[PATCH] Replace some dynamic_cast with UNO_QUERY".
    
    * canvas/source/cairo/cairo_repainttarget.hxx RepaintTarget:
    > canvas/source/cairo/cairo_cachedbitmap.cxx:62:34: error: suspicious 
dynamic cross cast from 'com::sun::star::rendering::XCanvas *' to 
'RepaintTarget *' [loplugin:crosscast]
    >         RepaintTarget* pTarget = dynamic_cast< RepaintTarget* 
>(rTargetCanvas.get());
    * canvas/source/cairo/cairo_surfaceprovider.hxx SurfaceProvider:
    > canvas/source/cairo/cairo_canvashelper.cxx:301:45: error: suspicious 
dynamic cross cast from 'com::sun::star::rendering::XBitmap *' to 
'SurfaceProvider *' [loplugin:crosscast]
    >         SurfaceProvider* pSurfaceProvider = 
dynamic_cast<SurfaceProvider*>( xBitmap.get() );
    * canvas/source/vcl/repainttarget.hxx RepaintTarget:
    > canvas/source/vcl/cachedbitmap.cxx:73:34: error: suspicious dynamic cross 
cast from 'com::sun::star::rendering::XCanvas *' to 'RepaintTarget *' 
[loplugin:crosscast]
    >         RepaintTarget* pTarget = dynamic_cast< RepaintTarget* 
>(rTargetCanvas.get());
    * chart2/inc/ChartModel.hxx ChartModel:
    > chart2/source/controller/dialogs/dlg_ChartType_UNO.cxx:82:31: error: 
suspicious dynamic cross cast from 'com::sun::star::awt::XWindow *' to 
'ChartModel *' [loplugin:crosscast]
    >     ChartModel* pChartModel = dynamic_cast<ChartModel*>(rParent.get());
    * chart2/source/controller/inc/TabPageNotifiable.hxx TabPageNotifiable:
    > chart2/source/controller/dialogs/tp_RangeChooser.cxx:70:28: error: 
suspicious dynamic cross cast from 'weld::DialogController *' to 
'TabPageNotifiable *' [loplugin:crosscast]
    >     , m_pTabPageNotifiable(dynamic_cast<TabPageNotifiable*>(pController))
    > chart2/source/controller/dialogs/tp_DataSource.cxx:171:28: error: 
suspicious dynamic cross cast from 'weld::DialogController *' to 
'TabPageNotifiable *' [loplugin:crosscast]
    >     , m_pTabPageNotifiable(dynamic_cast<TabPageNotifiable*>(pController))
    * include/drawinglayer/primitive2d/svggradientprimitive2d.hxx 
SvgGradientHelper:
    > drawinglayer/source/primitive2d/svggradientprimitive2d.cxx:582:59: error: 
suspicious dynamic cross cast from 'const BasePrimitive2D *' to 'const 
SvgGradientHelper *' [loplugin:crosscast]
    >             const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< 
const SvgGradientHelper* >(&rPrimitive);
    > drawinglayer/source/primitive2d/svggradientprimitive2d.cxx:819:59: error: 
suspicious dynamic cross cast from 'const BasePrimitive2D *' to 'const 
SvgGradientHelper *' [loplugin:crosscast]
    >             const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< 
const SvgGradientHelper* >(&rPrimitive);
    * include/editeng/unotext.hxx SvxUnoTextRangeBase:
    > writerfilter/source/dmapper/DomainMapper_Impl.cxx:7645:62: error: 
suspicious dynamic cross cast from 'com::sun::star::text::XTextCursor *' to 
'SvxUnoTextRangeBase *' [loplugin:crosscast]
    >                             SvxUnoTextRangeBase* pDrawText = 
dynamic_cast<SvxUnoTextRangeBase*>(xCrsr.get());
    * include/embeddedobj/embeddedupdate.hxx EmbeddedUpdate:
    > svtools/source/misc/embedhlp.cxx:932:35: error: suspicious dynamic cross 
cast from 'com::sun::star::embed::XEmbeddedObject *' to 'embed::EmbeddedUpdate 
*' [loplugin:crosscast]
    >     embed::EmbeddedUpdate* pObj = dynamic_cast<embed::EmbeddedUpdate*> 
(GetObject().get());
    * include/oox/core/contexthandler2.hxx ContextHandler2Helper:
    > oox/source/core/contexthandler2.cxx:183:21: error: suspicious dynamic 
cross cast from 'const ContextHandler2Helper' to 'const ContextHandler &' 
[loplugin:crosscast]
    >     ContextHandler( dynamic_cast< ContextHandler const & >( rParent ) ),
    * include/oox/mathml/export.hxx FormulaExportBase:
    > oox/source/export/shapes.cxx:2475:42: error: suspicious dynamic cross 
cast from 'com::sun::star::frame::XModel *' to 'oox::FormulaExportBase *' 
[loplugin:crosscast]
    >     oox::FormulaExportBase *const 
pMagic(dynamic_cast<oox::FormulaExportBase*>(xMathModel.get()));
    * include/oox/mathml/import.hxx FormulaImportBase:
    > oox/source/drawingml/shape.cxx:1298:25: error: suspicious dynamic cross 
cast from 'com::sun::star::uno::XInterface *' to 'oox::FormulaImportBase *' 
[loplugin:crosscast]
    >                         
dynamic_cast<oox::FormulaImportBase*>(xMathModel.get()));
    > writerfilter/source/ooxml/OOXMLFastContextHandler.cxx:2287:38: error: 
suspicious dynamic cross cast from 'SfxBaseModel' to 'oox::FormulaImportBase &' 
[loplugin:crosscast]
    >     oox::FormulaImportBase& import = 
dynamic_cast<oox::FormulaImportBase&>(dynamic_cast<SfxBaseModel&>(*component));
    > writerfilter/source/rtftok/rtfdocumentimpl.cxx:2973:33: error: suspicious 
dynamic cross cast from 'SfxBaseModel' to 'oox::FormulaImportBase &' 
[loplugin:crosscast]
    >                 auto& rImport = dynamic_cast<oox::FormulaImportBase&>(
    > writerfilter/source/dmapper/DomainMapper_Impl.cxx:3000:53: error: 
suspicious dynamic cross cast from 'com::sun::star::uno::XInterface *' to 
'oox::FormulaImportBase *' [loplugin:crosscast]
    >         if( oox::FormulaImportBase* formulaimport = dynamic_cast< 
oox::FormulaImportBase* >( xInterface.get()))
    * include/sfx2/Metadatable.hxx Metadatable:
    > sw/source/core/doc/docbm.cxx:1837:17: error: suspicious dynamic cross 
cast from 'const IBookmark *const' to 'const ::sfx2::Metadatable *' 
[loplugin:crosscast]
    >                 dynamic_cast< ::sfx2::Metadatable const* >(pBookmark));
    > sw/source/core/doc/docbm.cxx:1924:13: error: suspicious dynamic cross 
cast from '::sw::mark::IBookmark *const' to '::sfx2::Metadatable *' 
[loplugin:crosscast]
    >             dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
    > sw/source/core/doc/DocumentContentOperationsManager.cxx:342:21: error: 
suspicious dynamic cross cast from 'const sw::mark::IMark *const' to 'const 
::sfx2::Metadatable *' [loplugin:crosscast]
    >                     dynamic_cast< ::sfx2::Metadatable const* >(pMark));
    > sw/source/core/doc/DocumentContentOperationsManager.cxx:344:21: error: 
suspicious dynamic cross cast from '::sw::mark::IMark *const' to 
'::sfx2::Metadatable *' [loplugin:crosscast]
    >                     dynamic_cast< ::sfx2::Metadatable      * >(pNewMark));
    > sw/source/core/unocore/unobkm.cxx:381:12: error: suspicious dynamic cross 
cast from '::sw::mark::IMark *' to '::sfx2::Metadatable *' [loplugin:crosscast]
    >     return dynamic_cast< ::sfx2::Metadatable* 
>(m_pImpl->m_pRegisteredBookmark);
    > sw/source/core/undo/rolbck.cxx:635:13: error: suspicious dynamic cross 
cast from 'const ::sw::mark::IBookmark *const' to 'const ::sfx2::Metadatable *' 
[loplugin:crosscast]
    >             dynamic_cast< ::sfx2::Metadatable const* >(pBookmark));
    > sw/source/core/undo/rolbck.cxx:713:13: error: suspicious dynamic cross 
cast from '::sw::mark::IBookmark *const' to '::sfx2::Metadatable *' 
[loplugin:crosscast]
    >             dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
    * include/sfx2/digitalsignatures.hxx DigitalSignatures:
    > sfx2/source/doc/docfile.cxx:3999:25: error: suspicious dynamic cross cast 
from 'com::sun::star::security::XDocumentDigitalSignatures *' to 
'sfx2::DigitalSignatures *' [loplugin:crosscast]
    >     auto xModelSigner = 
dynamic_cast<sfx2::DigitalSignatures*>(xSigner.get());
    * include/sfx2/sidebar/IContextChangeReceiver.hxx IContextChangeReceiver:
    > sfx2/source/sidebar/SidebarPanelBase.cxx:105:11: error: suspicious 
dynamic cross cast from 'pointer' (aka 'PanelLayout *') to 
'IContextChangeReceiver *' [loplugin:crosscast]
    >         = dynamic_cast<IContextChangeReceiver*>(mxControl.get());
    * include/sfx2/sidebar/ILayoutableWindow.hxx ILayoutableWindow:
    > sfx2/source/sidebar/SidebarPanelBase.cxx:164:44: error: suspicious 
dynamic cross cast from 'pointer' (aka 'PanelLayout *') to 'ILayoutableWindow 
*' [loplugin:crosscast]
    >     ILayoutableWindow* pLayoutableWindow = 
dynamic_cast<ILayoutableWindow*>(mxControl.get());
    * include/sfx2/sidebar/SidebarModelUpdate.hxx SidebarModelUpdate:
    > sfx2/source/sidebar/SidebarPanelBase.cxx:189:40: error: suspicious 
dynamic cross cast from 'pointer' (aka 'PanelLayout *') to 'SidebarModelUpdate 
*' [loplugin:crosscast]
    >     SidebarModelUpdate* pModelUpdate = 
dynamic_cast<SidebarModelUpdate*>(mxControl.get());
    * include/sfx2/xmldump.hxx XmlDump:
    > svtools/source/misc/embedhlp.cxx:290:27: error: suspicious dynamic cross 
cast from 'com::sun::star::util::XCloseable *' to 'sfx2::XmlDump *' 
[loplugin:crosscast]
    >         auto pComponent = 
dynamic_cast<sfx2::XmlDump*>(mxObj->getComponent().get());
    * include/svl/stylesheetuser.hxx StyleSheetUser:
    > sd/source/core/stlsheet.cxx:294:48: error: suspicious dynamic cross cast 
from 'SfxListener *' to 'svl::StyleSheetUser *' [loplugin:crosscast]
    >         const svl::StyleSheetUser* const 
pUser(dynamic_cast<svl::StyleSheetUser*>(pListener));
    * include/svl/undo.hxx SfxRepeatTarget:
    > starmath/source/action.cxx:45:5: error: suspicious dynamic cross cast 
from 'SfxRepeatTarget' to 'SmDocShell &' [loplugin:crosscast]
    >     dynamic_cast< SmDocShell & >(rDocSh).SetFormat(aNewFormat);
    * include/svx/ipolypolygoneditorcontroller.hxx IPolyPolygonEditorController:
    > sd/source/ui/view/drbezob.cxx:127:22: error: suspicious dynamic cross 
cast from 'sd::SmartTag *' to 'IPolyPolygonEditorController *' 
[loplugin:crosscast]
    >             pIPPEC = dynamic_cast< IPolyPolygonEditorController* >( 
mpView->getSmartTags().getSelected().get() );
    > sd/source/ui/view/drbezob.cxx:216:26: error: suspicious dynamic cross 
cast from 'sd::SmartTag *' to 'IPolyPolygonEditorController *' 
[loplugin:crosscast]
    >                 pIPPEC = dynamic_cast< IPolyPolygonEditorController* >( 
mpView->getSmartTags().getSelected().get() );
    * include/vcl/IContext.hxx IContext:
    > vcl/source/window/builder.cxx:3650:54: error: suspicious dynamic cross 
cast from 'vcl::Window *' to 'vcl::IContext *' [loplugin:crosscast]
    >                     vcl::IContext* pContextControl = 
dynamic_cast<vcl::IContext*>(pCurrentChild.get());
    * include/vcl/ITiledRenderable.hxx ITiledRenderable:
    > In file included from test/source/a11y/swaccessibletestbase.cxx:10:
    > In file included from include/test/a11y/swaccessibletestbase.hxx:22:
    > include/test/a11y/accessibletestbase.hxx:54:15: error: suspicious dynamic 
cross cast from 'com::sun::star::lang::XComponent *' to 'vcl::ITiledRenderable 
*' [loplugin:crosscast]
    >             = dynamic_cast<vcl::ITiledRenderable*>(mxDocument.get());
    * include/vcl/NotebookbarContextControl.hxx NotebookbarContextControl:
    > vcl/source/control/notebookbar.cxx:113:33: error: suspicious dynamic 
cross cast from 'vcl::Window *' to 'NotebookbarContextControl *' 
[loplugin:crosscast]
    >             pContextContainer = 
dynamic_cast<NotebookbarContextControl*>(m_pUIBuilder->get<Window>(OUStringToOString(aName,
 RTL_TEXTENCODING_UTF8)));
    * include/vcl/gdimetafiletools.hxx MetafileAccessor:
    > vcl/source/gdi/impgraph.cxx:716:61: error: suspicious dynamic cross cast 
from 'drawinglayer::primitive2d::BasePrimitive2D *' to 'const MetafileAccessor 
*' [loplugin:crosscast]
    >                 const MetafileAccessor* pMetafileAccessor = dynamic_cast< 
const MetafileAccessor* >(pUnoPrimitive->getBasePrimitive2D().get());
    * include/vcl/syswin.hxx VclBuilderContainer:
    > vcl/source/app/salvtables.cxx:7465:11: error: suspicious dynamic cross 
cast from 'vcl::Window *' to 'VclBuilderContainer *' [loplugin:crosscast]
    >         = dynamic_cast<VclBuilderContainer*>(m_aOwnedToplevel.get()))
    * include/vcl/toolkit/field.hxx NumericFormatter:
    > vcl/source/window/builder.cxx:583:37: error: suspicious dynamic cross 
cast from 'vcl::Window *' to 'NumericFormatter *' [loplugin:crosscast]
    >         NumericFormatter *pTarget = 
dynamic_cast<NumericFormatter*>(get(elem.m_sID));
    * include/vcl/transfer.hxx DragSourceHelper:
    > svx/source/sdr/contact/sdrmediawindow.cxx:163:47: error: suspicious 
dynamic cross cast from 'vcl::Window *' to 'DragSourceHelper *' 
[loplugin:crosscast]
    >         DragSourceHelper* pDragSourceHelper = dynamic_cast< 
DragSourceHelper* >( pWindow );
    * include/vcl/transfer.hxx DropTargetHelper:
    > svx/source/sdr/contact/sdrmediawindow.cxx:126:47: error: suspicious 
dynamic cross cast from 'vcl::Window *' to 'DropTargetHelper *' 
[loplugin:crosscast]
    >         DropTargetHelper* pDropTargetHelper = dynamic_cast< 
DropTargetHelper* >( pWindow );
    > svx/source/sdr/contact/sdrmediawindow.cxx:145:47: error: suspicious 
dynamic cross cast from 'vcl::Window *' to 'DropTargetHelper *' 
[loplugin:crosscast]
    >         DropTargetHelper* pDropTargetHelper = dynamic_cast< 
DropTargetHelper* >( pWindow );
    * include/vcl/wizardmachine.hxx IWizardPageController:
    > vcl/source/control/wizardmachine.cxx:1274:46: error: suspicious dynamic 
cross cast from 'BuilderPage *' to 'IWizardPageController *' 
[loplugin:crosscast]
    >         IWizardPageController* pController = 
dynamic_cast<IWizardPageController*>(pCurrentPage);
    * include/xmloff/settingsstore.hxx DocumentSettingsSerializer:
    > xmloff/source/draw/sdxmlimp.cxx:540:15: error: suspicious dynamic cross 
cast from 'com::sun::star::beans::XPropertySet *' to 
'DocumentSettingsSerializer *' [loplugin:crosscast]
    >     pFilter = dynamic_cast<DocumentSettingsSerializer *>(xProps.get());
    > xmloff/source/draw/sdxmlexp.cxx:2474:41: error: suspicious dynamic cross 
cast from 'com::sun::star::beans::XPropertySet *' to 
'DocumentSettingsSerializer *' [loplugin:crosscast]
    >     DocumentSettingsSerializer 
*pFilter(dynamic_cast<DocumentSettingsSerializer *>(xProps.get()));
    * include/xmloff/xmlimp.hxx SvXMLImport:
    > sdext/source/pdfimport/sax/emitcontext.cxx:45:37: error: suspicious 
dynamic cross cast from 'com::sun::star::xml::sax::XDocumentHandler *' to 
'SvXMLImport *' [loplugin:crosscast]
    >     if (SvXMLImport *pFastHandler = 
dynamic_cast<SvXMLImport*>(m_xDocHdl.get()))
    > writerperfect/source/common/DocumentHandler.cxx:118:37: error: suspicious 
dynamic cross cast from 'com::sun::star::xml::sax::XDocumentHandler *' to 
'SvXMLImport *' [loplugin:crosscast]
    >     if (SvXMLImport* pFastHandler = 
dynamic_cast<SvXMLImport*>(mxHandler.get()))
    * reportdesign/inc/RptObject.hxx OObjectBase:
    > reportdesign/source/ui/report/ViewsWindow.cxx:843:53: error: suspicious 
dynamic cross cast from 'SdrObject *' to 'OObjectBase *' [loplugin:crosscast]
    >                             OObjectBase* pObjBase = 
dynamic_cast<OObjectBase*>(pObj);
    > reportdesign/source/core/sdr/ReportUndoFactory.cxx:30:25: error: 
suspicious dynamic cross cast from 'SdrObject *' to 'OObjectBase *' 
[loplugin:crosscast]
    >     OObjectBase* pObj = dynamic_cast<OObjectBase*>(&rObject);
    > reportdesign/source/core/sdr/RptPage.cxx:62:29: error: suspicious dynamic 
cross cast from 'SdrObject *' to 'OObjectBase *' [loplugin:crosscast]
    >         OObjectBase* pObj = dynamic_cast<OObjectBase*>(GetObj(i));
    > reportdesign/source/core/sdr/RptPage.cxx:77:30: error: suspicious dynamic 
cross cast from 'SdrObject *' to 'OObjectBase *' [loplugin:crosscast]
    >         OObjectBase* pBase = dynamic_cast<OObjectBase*>(GetObj(nPos));
    > reportdesign/source/core/sdr/RptPage.cxx:116:28: error: suspicious 
dynamic cross cast from 'SdrObject *' to 'OObjectBase *' [loplugin:crosscast]
    >     OObjectBase* pObject = dynamic_cast< OObjectBase* 
>(SdrObject::getSdrObjectFromXShape( _xObject ));
    > reportdesign/source/core/sdr/RptPage.cxx:184:32: error: suspicious 
dynamic cross cast from 'SdrObject *' to 'OObjectBase *' [loplugin:crosscast]
    >     OObjectBase* pObjectBase = dynamic_cast< OObjectBase* >( pObj );
    > reportdesign/source/core/sdr/ReportDrawPage.cxx:60:29: error: suspicious 
dynamic cross cast from 'SdrObject *' to 'OObjectBase *' [loplugin:crosscast]
    >     OObjectBase* pBaseObj = dynamic_cast<OObjectBase*>(pObj);
    > reportdesign/source/ui/report/dlgedfunc.cxx:455:25: error: suspicious 
dynamic cross cast from 'SdrObject *' to 'OObjectBase *' [loplugin:crosscast]
    >     OObjectBase* pObj = dynamic_cast<OObjectBase*>(_pOverlappedObj);
    > reportdesign/source/ui/report/SectionView.cxx:177:37: error: suspicious 
dynamic cross cast from 'SdrObject' to 'OObjectBase &' [loplugin:crosscast]
    >             OObjectBase& rBaseObj = dynamic_cast<OObjectBase&>(*pObj);
    > reportdesign/source/ui/report/ReportSection.cxx:338:29: error: suspicious 
dynamic cross cast from 'SdrObject *' to 'OObjectBase *' [loplugin:crosscast]
    >         OObjectBase* pObj = dynamic_cast<OObjectBase*>(pSdrObject);
    > reportdesign/source/ui/report/ReportSection.cxx:513:38: error: suspicious 
dynamic cross cast from 'SdrObject' to 'OObjectBase &' [loplugin:crosscast]
    >                 OObjectBase& rBase = dynamic_cast<OObjectBase&>(*pObject);
    > reportdesign/source/ui/report/ReportSection.cxx:644:33: error: suspicious 
dynamic cross cast from 'SdrObject *' to 'OObjectBase *' [loplugin:crosscast]
    >             OObjectBase* pObj = dynamic_cast<OObjectBase*>(pDlgEdObj);
    > reportdesign/source/ui/report/ReportSection.cxx:663:35: error: suspicious 
dynamic cross cast from 'const SdrObject *' to 'const OObjectBase *' 
[loplugin:crosscast]
    >         const OObjectBase* pObj = dynamic_cast<const 
OObjectBase*>(pDlgEdObj);
    > reportdesign/source/ui/report/propbrw.cxx:286:33: error: suspicious 
dynamic cross cast from 'SdrObject *' to 'OObjectBase *' [loplugin:crosscast]
    >             OObjectBase* pObj = dynamic_cast<OObjectBase*>(pCurrent);
    > reportdesign/source/ui/report/ViewsWindow.cxx:843:53: error: suspicious 
dynamic cross cast from 'SdrObject *' to 'OObjectBase *' [loplugin:crosscast]
    >                             OObjectBase* pObjBase = 
dynamic_cast<OObjectBase*>(pObj);
    * sc/source/ui/inc/IAnyRefDialog.hxx IAnyRefDialog:
    > sc/source/ui/app/scmod.cxx:1607:42: error: suspicious dynamic cross cast 
from 'element_type *' (aka 'SfxDialogController *') to 'IAnyRefDialog *' 
[loplugin:crosscast]
    >                 IAnyRefDialog* pRefDlg = 
dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
    > sc/source/ui/app/scmod.cxx:1646:42: error: suspicious dynamic cross cast 
from 'element_type *' (aka 'SfxDialogController *') to 'IAnyRefDialog *' 
[loplugin:crosscast]
    >                 IAnyRefDialog* pRefDlg = 
dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
    > sc/source/ui/app/scmod.cxx:1697:42: error: suspicious dynamic cross cast 
from 'element_type *' (aka 'SfxDialogController *') to 'IAnyRefDialog *' 
[loplugin:crosscast]
    >                 IAnyRefDialog* pRefDlg = 
dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
    > sc/source/ui/app/scmod.cxx:1766:42: error: suspicious dynamic cross cast 
from 'element_type *' (aka 'SfxDialogController *') to 'IAnyRefDialog *' 
[loplugin:crosscast]
    >                 IAnyRefDialog* pRefDlg = 
dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
    > sc/source/ui/app/scmod.cxx:1813:42: error: suspicious dynamic cross cast 
from 'element_type *' (aka 'SfxDialogController *') to 'IAnyRefDialog *' 
[loplugin:crosscast]
    >                 IAnyRefDialog* pRefDlg = 
dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
    > sc/source/ui/app/scmod.cxx:1853:38: error: suspicious dynamic cross cast 
from 'element_type *' (aka 'SfxDialogController *') to 'IAnyRefDialog *' 
[loplugin:crosscast]
    >             IAnyRefDialog* pRefDlg = 
dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
    > sc/source/ui/view/tabview3.cxx:470:30: error: suspicious dynamic cross 
cast from 'element_type *' (aka 'SfxDialogController *') to 'IAnyRefDialog *' 
[loplugin:crosscast]
    >     IAnyRefDialog* pRefDlg = 
dynamic_cast<IAnyRefDialog*>(xDlgController.get());
    > sc/source/ui/view/tabview3.cxx:2053:42: error: suspicious dynamic cross 
cast from 'element_type *' (aka 'SfxDialogController *') to 'IAnyRefDialog *' 
[loplugin:crosscast]
    >                 IAnyRefDialog* pRefDlg = 
dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
    > sc/source/ui/view/tabvwsh4.cxx:210:46: error: suspicious dynamic cross 
cast from 'element_type *' (aka 'SfxDialogController *') to 'IAnyRefDialog *' 
[loplugin:crosscast]
    >                     IAnyRefDialog* pRefDlg = 
dynamic_cast<IAnyRefDialog*>(pController.get());
    * sd/source/filter/eppt/epptbase.hxx PPTExBulletProvider:
    > sd/source/filter/eppt/pptx-epptbase.cxx:497:74: error: suspicious dynamic 
cross cast from 'PPTWriterBase *' to 'PPTExBulletProvider *' 
[loplugin:crosscast]
    >         maStyleSheetList.emplace_back( new PPTExStyleSheet( nDefaultTab, 
dynamic_cast<PPTExBulletProvider*>(this) ) );
    * sdext/source/presenter/PresenterViewFactory.hxx CachablePresenterView:
    > sdext/source/presenter/PresenterViewFactory.cxx:218:36: error: suspicious 
dynamic cross cast from 'com::sun::star::drawing::framework::XResource *' to 
'CachablePresenterView *' [loplugin:crosscast]
    >     CachablePresenterView* pView = 
dynamic_cast<CachablePresenterView*>(rxView.get());
    > sdext/source/presenter/PresenterViewFactory.cxx:274:23: error: suspicious 
dynamic cross cast from 'com::sun::star::drawing::framework::XView *' to 
'CachablePresenterView *' [loplugin:crosscast]
    >                     = 
dynamic_cast<CachablePresenterView*>(iView->second.first.get());
    > sdext/source/presenter/PresenterViewFactory.cxx:325:40: error: suspicious 
dynamic cross cast from 'com::sun::star::drawing::framework::XView *' to 
'CachablePresenterView *' [loplugin:crosscast]
    >         CachablePresenterView* pView = 
dynamic_cast<CachablePresenterView*>(xView.get());
    * slideshow/source/inc/cursormanager.hxx CursorManager:
    > slideshow/source/engine/slide/userpaintoverlay.cxx:449:49: error: 
suspicious dynamic cross cast from 'CursorManager' to 'Slide &' 
[loplugin:crosscast]
    >                                                 
dynamic_cast<Slide&>(rContext.mrCursorManager),
    * svx/source/inc/celltypes.hxx TableDesignUser:
    > svx/source/table/tabledesign.cxx:267:38: error: suspicious dynamic cross 
cast from 'com::sun::star::util::XModifyListener *' to 'TableDesignUser *' 
[loplugin:crosscast]
    >             TableDesignUser* pUser = dynamic_cast< TableDesignUser* >( 
it.next().get() );
    * svx/source/inc/tablemodel.hxx ICellRange:
    > svx/source/table/tablemodel.cxx:285:26: error: suspicious dynamic cross 
cast from 'com::sun::star::table::XCellRange *' to 'ICellRange *' 
[loplugin:crosscast]
    >     ICellRange* pRange = dynamic_cast< ICellRange* >( rRange.get() );
    * sw/inc/IDocumentUndoRedo.hxx IDocumentUndoRedo:
    > sw/source/uibase/shells/drwtxtsh.cxx:585:38: error: suspicious dynamic 
cross cast from 'SfxUndoManager *' to 'IDocumentUndoRedo *' [loplugin:crosscast]
    >                 auto* pUndoManager = 
dynamic_cast<IDocumentUndoRedo*>(GetUndoManager());
    * sw/inc/IMark.hxx IFieldmark:
    > sw/source/core/doc/docbm.cxx:1415:15: error: suspicious dynamic cross 
cast from 'sw::mark::MarkBase *const' to 'IFieldmark *' [loplugin:crosscast]
    >             : dynamic_cast<IFieldmark*>(*pFieldmark);
    > sw/source/core/doc/docbm.cxx:1437:16: error: suspicious dynamic cross 
cast from 'sw::mark::MarkBase *' to 'IFieldmark *' [loplugin:crosscast]
    >         return dynamic_cast<IFieldmark*>(pFieldmark);
    > sw/source/core/doc/docbm.cxx:1570:37: error: suspicious dynamic cross 
cast from 'sw::mark::MarkBase *' to 'IFieldmark *' [loplugin:crosscast]
    >                 IFieldmark *pMark = dynamic_cast<IFieldmark*>(*aIter);
    * sw/inc/calbck.hxx BroadcastingModify:
    > sw/source/core/attr/swatrset.cxx:228:29: error: suspicious dynamic cross 
cast from 'const sw::BroadcastingModify *' to 'const sw::FormatDropDefiner *' 
[loplugin:crosscast]
    >         auto pDropDefiner = dynamic_cast<const 
sw::FormatDropDefiner*>(pModify);
    > sw/source/core/txtnode/OnlineAccessibilityCheck.cxx:38:28: error: 
suspicious dynamic cross cast from 'SwNode *' to 'sw::BroadcastingModify *' 
[loplugin:crosscast]
    >         auto* pBroadcast = dynamic_cast<sw::BroadcastingModify*>(m_pNode);
    * sw/inc/contentindex.hxx SwContentIndexReg:
    > sw/source/core/doc/DocumentRedlineManager.cxx:56:20: error: suspicious 
dynamic cross cast from 'SwNode *' to 'SwContentIndexReg *' [loplugin:crosscast]
    >             assert(dynamic_cast<SwContentIndexReg*>(&pPos->GetNode())
    * sw/source/core/inc/flowfrm.hxx SwFlowFrame:
    > sw/source/core/layout/frmtool.cxx:3044:35: error: suspicious dynamic 
cross cast from 'SwFrame *' to 'SwFlowFrame *' [loplugin:crosscast]
    >         SwFlowFrame *pFlowFrame = dynamic_cast<SwFlowFrame*>(pSibling);
    * sw/source/uibase/inc/FrameControl.hxx ISwFrameControl:
    > sw/source/uibase/docvw/FrameControlsManager.cxx:283:15: error: suspicious 
dynamic cross cast from 'vcl::Window *' to 'ISwFrameControl *' 
[loplugin:crosscast]
    >     mpIFace = dynamic_cast<ISwFrameControl *>( pWindow.get() );
    * vcl/inc/IPrioritable.hxx IPrioritable:
    > vcl/source/control/NotebookbarPopup.cxx:40:37: error: suspicious dynamic 
cross cast from 'vcl::Window *' to 'vcl::IPrioritable *' [loplugin:crosscast]
    >         vcl::IPrioritable* pChild = 
dynamic_cast<vcl::IPrioritable*>(GetChild(0));
    > vcl/source/control/PriorityHBox.cxx:89:43: error: suspicious dynamic 
cross cast from 'vcl::Window *' to 'vcl::IPrioritable *' [loplugin:crosscast]
    >         vcl::IPrioritable* pPrioritable = 
dynamic_cast<vcl::IPrioritable*>(pChild);
    > vcl/source/control/PriorityHBox.cxx:127:32: error: suspicious dynamic 
cross cast from 'vcl::IPrioritable *' to 'vcl::Window *' [loplugin:crosscast]
    >         vcl::Window* pWindow = dynamic_cast<vcl::Window*>(pPrioritable);
    > vcl/source/control/PriorityHBox.cxx:142:32: error: suspicious dynamic 
cross cast from 'vcl::IPrioritable *' to 'vcl::Window *' [loplugin:crosscast]
    >         vcl::Window* pWindow = dynamic_cast<vcl::Window*>(*pChildR);
    > vcl/source/control/PriorityHBox.cxx:186:43: error: suspicious dynamic 
cross cast from 'vcl::Window *' to 'vcl::IPrioritable *' [loplugin:crosscast]
    >         vcl::IPrioritable* pPrioritable = 
dynamic_cast<vcl::IPrioritable*>(pChild);
    > vcl/source/window/NotebookBarAddonsMerger.cxx:128:19: error: suspicious 
dynamic cross cast from 'vcl::Window *' to 'vcl::IPrioritable *' 
[loplugin:crosscast]
    >                 = dynamic_cast<vcl::IPrioritable*>(pOptionalParent.get());
    > ovcl/source/window/builder.cxx:3643:55: error: suspicious dynamic cross 
cast from 'vcl::Window *' to 'vcl::IPrioritable *' [loplugin:crosscast]
    >                     vcl::IPrioritable* pPrioritable = 
dynamic_cast<vcl::IPrioritable*>(pCurrentChild.get());
    * vcl/inc/jsdialog/jsdialogbuilder.hxx BaseJSWidget:
    > vcl/jsdialog/executor.cxx:41:26: error: suspicious dynamic cross cast 
from 'weld::Widget *' to 'BaseJSWidget *' [loplugin:crosscast]
    >     if (auto pJSWidget = dynamic_cast<BaseJSWidget*>(pWidget))
    > vcl/jsdialog/executor.cxx:49:26: error: suspicious dynamic cross cast 
from 'weld::Widget *' to 'BaseJSWidget *' [loplugin:crosscast]
    >     if (auto pJSWidget = dynamic_cast<BaseJSWidget*>(pWidget))
    > vcl/jsdialog/executor.cxx:155:49: error: suspicious dynamic cross cast 
from 'weld::MenuButton *' to 'BaseJSWidget *' [loplugin:crosscast]
    >                     BaseJSWidget* pMenuButton = 
dynamic_cast<BaseJSWidget*>(pButton);
    * vcl/inc/unx/x11/x11gdiimpl.h X11GraphicsImpl:
    > vcl/unx/generic/gdi/salgdi.cxx:387:36: error: suspicious dynamic cross 
cast from 'pointer' (aka 'SalGraphicsImpl *') to 'X11GraphicsImpl *' 
[loplugin:crosscast]
    >     if( X11GraphicsImpl* x11Impl = dynamic_cast< X11GraphicsImpl* >( 
mxImpl.get()))
    * xmlsecurity/inc/certificate.hxx Certificate:
    > xmlsecurity/source/helper/documentsignaturemanager.cxx:334:33: error: 
suspicious dynamic cross cast from 'com::sun::star::security::XCertificate *' 
to 'xmlsecurity::Certificate *' [loplugin:crosscast]
    >         if (auto pCertificate = 
dynamic_cast<xmlsecurity::Certificate*>(xCert.get()))
    > xmlsecurity/source/helper/documentsignaturemanager.cxx:381:33: error: 
suspicious dynamic cross cast from 'com::sun::star::security::XCertificate *' 
to 'xmlsecurity::Certificate *' [loplugin:crosscast]
    >         if (auto pCertificate = 
dynamic_cast<xmlsecurity::Certificate*>(xCert.get()))
    > xmlsecurity/source/component/documentdigitalsignatures.cxx:688:28: error: 
suspicious dynamic cross cast from 'com::sun::star::security::XCertificate *' 
to 'xmlsecurity::Certificate *' [loplugin:crosscast]
    >             auto pAuthor = 
dynamic_cast<xmlsecurity::Certificate*>(xAuthor.get());
    > xmlsecurity/source/component/documentdigitalsignatures.cxx:689:26: error: 
suspicious dynamic cross cast from 'com::sun::star::security::XCertificate *' 
to 'xmlsecurity::Certificate *' [loplugin:crosscast]
    >             auto pCert = 
dynamic_cast<xmlsecurity::Certificate*>(xCert.get());
    > xmlsecurity/qa/unit/signing/signing.cxx:130:29: error: suspicious dynamic 
cross cast from 'com::sun::star::security::XCertificate *' to 
'xmlsecurity::Certificate *' [loplugin:crosscast]
    >         auto pCertificate = 
dynamic_cast<xmlsecurity::Certificate*>(xCertificate.get());
    
    Change-Id: If4f9efd8c012d0f650fe670450cf7ac0c8978036
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143458
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>

diff --git a/canvas/source/cairo/cairo_repainttarget.hxx 
b/canvas/source/cairo/cairo_repainttarget.hxx
index 558ec7921ecb..94d3d3845b3e 100644
--- a/canvas/source/cairo/cairo_repainttarget.hxx
+++ b/canvas/source/cairo/cairo_repainttarget.hxx
@@ -33,7 +33,7 @@ namespace cairocanvas
         This interface must be implemented on all canvas
         implementations that hand out XCachedPrimitives
      */
-    class RepaintTarget
+    class SAL_LOPLUGIN_ANNOTATE("crosscast") RepaintTarget
     {
     public:
         virtual ~RepaintTarget() {}
diff --git a/canvas/source/cairo/cairo_surfaceprovider.hxx 
b/canvas/source/cairo/cairo_surfaceprovider.hxx
index a5115a507863..1ff6f2aa7d3f 100644
--- a/canvas/source/cairo/cairo_surfaceprovider.hxx
+++ b/canvas/source/cairo/cairo_surfaceprovider.hxx
@@ -37,7 +37,7 @@ namespace cairocanvas
         This interface must be implemented on all canvas
         implementations that hand out XCachedPrimitives
      */
-    class SurfaceProvider : public css::uno::XInterface
+    class SAL_LOPLUGIN_ANNOTATE("crosscast") SurfaceProvider : public 
css::uno::XInterface
     {
     public:
         virtual ~SurfaceProvider() {}
diff --git a/canvas/source/vcl/repainttarget.hxx 
b/canvas/source/vcl/repainttarget.hxx
index b7b4058e9e9d..b8bac4ab9210 100644
--- a/canvas/source/vcl/repainttarget.hxx
+++ b/canvas/source/vcl/repainttarget.hxx
@@ -34,7 +34,7 @@ namespace vclcanvas
         This interface must be implemented on all canvas
         implementations that hand out XCachedPrimitives
      */
-    class RepaintTarget
+    class SAL_LOPLUGIN_ANNOTATE("crosscast") RepaintTarget
     {
     public:
         virtual ~RepaintTarget() {}
diff --git a/chart2/inc/ChartModel.hxx b/chart2/inc/ChartModel.hxx
index c8dc4b55e969..b877e47db5e0 100644
--- a/chart2/inc/ChartModel.hxx
+++ b/chart2/inc/ChartModel.hxx
@@ -112,7 +112,8 @@ typedef cppu::WeakImplHelper<
 class UndoManager;
 class ChartView;
 
-class OOO_DLLPUBLIC_CHARTTOOLS ChartModel final : public 
impl::ChartModel_Base, public sfx2::XmlDump
+class OOO_DLLPUBLIC_CHARTTOOLS SAL_LOPLUGIN_ANNOTATE("crosscast") ChartModel 
final :
+    public impl::ChartModel_Base, public sfx2::XmlDump
 {
 
 private:
diff --git a/chart2/source/controller/inc/TabPageNotifiable.hxx 
b/chart2/source/controller/inc/TabPageNotifiable.hxx
index 440cda2de9aa..a5da029810b1 100644
--- a/chart2/source/controller/inc/TabPageNotifiable.hxx
+++ b/chart2/source/controller/inc/TabPageNotifiable.hxx
@@ -27,7 +27,7 @@ class BuilderPage;
 
 namespace chart
 {
-class TabPageNotifiable
+class SAL_LOPLUGIN_ANNOTATE("crosscast") TabPageNotifiable
 {
 public:
     virtual void setInvalidPage(BuilderPage* pTabPage) = 0;
diff --git a/compilerplugins/clang/crosscast.cxx 
b/compilerplugins/clang/crosscast.cxx
new file mode 100644
index 000000000000..293b8646d152
--- /dev/null
+++ b/compilerplugins/clang/crosscast.cxx
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+// Find uses of dynamic_cast that cast between unrelated classes, which is 
suspicious and might
+// indicate a bug.  The heuristic used to consider two classes unrelated is 
that neither derives
+// from the other (directly or indirectly) and they do not both virtually 
derive (directly or
+// indirectly) from a common third class.  Additionally, class definitions can 
be attributed with
+// SAL_LOPLUGIN_ANNOTATE("crosscast") (from sal/types.h) to suppress false 
warnings about known-good
+// cases casting from or to such a class.
+
+#ifndef LO_CLANG_SHARED_PLUGINS
+
+#include <cassert>
+#include <set>
+
+#include "compat.hxx"
+#include "plugin.hxx"
+
+namespace
+{
+void computeVirtualBases(CXXRecordDecl const* decl, std::set<CXXRecordDecl 
const*>* vbases)
+{
+    assert(vbases != nullptr);
+    for (auto const& i : decl->bases())
+    {
+        auto const d = i.getType()->getAsCXXRecordDecl();
+        if (d == nullptr)
+        {
+            continue;
+        }
+        if (i.isVirtual())
+        {
+            if (!vbases->insert(d->getCanonicalDecl()).second)
+            {
+                // As we track the already computed virtual bases in vbases 
anyway, we can cheaply
+                // optimize the case where we see a virtual base again, even 
though we don't bother
+                // to optimize the case where we see a non-virtual base 
multiple times:
+                continue;
+            }
+        }
+        computeVirtualBases(d, vbases);
+    }
+}
+
+bool compareVirtualBases(CXXRecordDecl const* decl, std::set<CXXRecordDecl 
const*>& vbases)
+{
+    for (auto const& i : decl->bases())
+    {
+        auto const d = i.getType()->getAsCXXRecordDecl();
+        if (d == nullptr)
+        {
+            continue;
+        }
+        if (i.isVirtual() && vbases.count(d->getCanonicalDecl()) == 1)
+        {
+            return true;
+        }
+        if (compareVirtualBases(d, vbases))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool haveCommonVirtualBase(CXXRecordDecl const* decl1, CXXRecordDecl const* 
decl2)
+{
+    std::set<CXXRecordDecl const*> vbases;
+    computeVirtualBases(decl1, &vbases);
+    return compareVirtualBases(decl2, vbases);
+}
+
+bool isAllowedInCrossCasts(CXXRecordDecl const* decl)
+{
+    auto const def = decl->getDefinition();
+    if (def == nullptr)
+    {
+        return false;
+    }
+    for (auto const attr : def->specific_attrs<AnnotateAttr>())
+    {
+        if (attr->getAnnotation() == "loplugin:crosscast")
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+class CrossCast final : public loplugin::FilteringPlugin<CrossCast>
+{
+public:
+    explicit CrossCast(loplugin::InstantiationData const& data)
+        : FilteringPlugin(data)
+    {
+    }
+
+    bool preRun() override { return compiler.getLangOpts().CPlusPlus; }
+
+    void run() override
+    {
+        if (preRun())
+        {
+            TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
+        }
+    }
+
+    bool VisitCXXDynamicCastExpr(CXXDynamicCastExpr const* expr)
+    {
+        if (ignoreLocation(expr))
+        {
+            return true;
+        }
+        auto const t2 = expr->getTypeAsWritten();
+        if (t2->isVoidPointerType())
+        {
+            return true;
+        }
+        auto const d2 = t2->getPointeeCXXRecordDecl();
+        if (d2 == nullptr)
+        {
+            return true;
+        }
+        auto const t1 = compat::getSubExprAsWritten(expr)->getType();
+        auto t1a = t1;
+        if (auto const t = t1a->getAs<clang::PointerType>())
+        {
+            t1a = t->getPointeeType();
+        }
+        auto const d1 = t1a->getAsCXXRecordDecl();
+        if (d1 == nullptr)
+        {
+            return true;
+        }
+        if (d1->getCanonicalDecl() == d2->getCanonicalDecl() || 
d1->isDerivedFrom(d2)
+            || d2->isDerivedFrom(d1) || haveCommonVirtualBase(d1, d2))
+        {
+            return true;
+        }
+        if (isAllowedInCrossCasts(d1) || isAllowedInCrossCasts(d2))
+        {
+            return true;
+        }
+        if (suppressWarningAt(expr->getBeginLoc()))
+        {
+            return true;
+        }
+        report(DiagnosticsEngine::Warning, "suspicious dynamic cross cast from 
%0 to %1",
+               expr->getExprLoc())
+            << t1 << t2 << expr->getSourceRange();
+        return true;
+    }
+};
+
+loplugin::Plugin::Registration<CrossCast> crosscast("crosscast");
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/compilerplugins/clang/test/crosscast.cxx 
b/compilerplugins/clang/test/crosscast.cxx
new file mode 100644
index 000000000000..113557337113
--- /dev/null
+++ b/compilerplugins/clang/test/crosscast.cxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+struct Base
+{
+    virtual ~Base();
+};
+
+struct Derived : Base
+{
+};
+
+struct Virtual1 : virtual Base
+{
+};
+
+struct Virtual2 : virtual Base
+{
+};
+
+struct Virtual2a : Virtual2
+{
+};
+
+struct Other
+{
+    virtual ~Other();
+};
+
+struct[[clang::annotate("loplugin:crosscast")]] Ok { virtual ~Ok(); };
+
+Base* up(Derived* p) { return dynamic_cast<Base*>(p); }
+
+Base& up(Derived& p) { return dynamic_cast<Base&>(p); }
+
+Derived* down(Base* p) { return dynamic_cast<Derived*>(p); }
+
+Derived& down(Base& p) { return dynamic_cast<Derived&>(p); }
+
+Base* self(Base* p) { return dynamic_cast<Base*>(p); }
+
+Base& self(Base& p) { return dynamic_cast<Base&>(p); }
+
+Virtual1* crossVirtual(Virtual2a* p) { return dynamic_cast<Virtual1*>(p); }
+
+Virtual1& crossVirtual(Virtual2a& p) { return dynamic_cast<Virtual1&>(p); }
+
+Base* crossFromOther(Other* p)
+{
+    // expected-error@+1 {{suspicious dynamic cross cast from 'Other *' to 
'Base *' [loplugin:crosscast]}}
+    return dynamic_cast<Base*>(p);
+}
+
+Base& crossFromOther(Other& p)
+{
+    // expected-error@+1 {{suspicious dynamic cross cast from 'Other' to 'Base 
&' [loplugin:crosscast]}}
+    return dynamic_cast<Base&>(p);
+}
+
+Other* crossToOther(Base* p)
+{
+    // expected-error@+1 {{suspicious dynamic cross cast from 'Base *' to 
'Other *' [loplugin:crosscast]}}
+    return dynamic_cast<Other*>(p);
+}
+
+Other& crossToOther(Base& p)
+{
+    // expected-error@+1 {{suspicious dynamic cross cast from 'Base' to 'Other 
&' [loplugin:crosscast]}}
+    return dynamic_cast<Other&>(p);
+}
+
+Base* crossFromOk(Ok* p) { return dynamic_cast<Base*>(p); }
+
+Base& crossFromOk(Ok& p) { return dynamic_cast<Base&>(p); }
+
+Ok* crossToOk(Base* p) { return dynamic_cast<Ok*>(p); }
+
+Ok& crossToOk(Base& p) { return dynamic_cast<Ok&>(p); }
+
+void* mostDerived(Base* p) { return dynamic_cast<void*>(p); }
+
+template <typename T> T generic1(Base* p) { return dynamic_cast<T>(p); }
+
+template <typename T> T* generic2(Base* p) { return dynamic_cast<T*>(p); }
+
+template <typename T> Derived* generic3(T p) { return 
dynamic_cast<Derived*>(p); }
+
+template <typename T> Derived* generic4(T* p) { return 
dynamic_cast<Derived*>(p); }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/include/drawinglayer/primitive2d/svggradientprimitive2d.hxx 
b/include/drawinglayer/primitive2d/svggradientprimitive2d.hxx
index a78f29fda86e..119ccb3b5f20 100644
--- a/include/drawinglayer/primitive2d/svggradientprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/svggradientprimitive2d.hxx
@@ -79,7 +79,7 @@ namespace drawinglayer::primitive2d
         /*  helper for linear and radial gradient, both get derived from this
             to share common definitions and functionality
          **/
-        class SvgGradientHelper
+        class SAL_LOPLUGIN_ANNOTATE("crosscast") SvgGradientHelper
         {
         private:
             /// the extra gradient transform
diff --git a/include/editeng/unotext.hxx b/include/editeng/unotext.hxx
index ece9b13de567..1d6743a0e410 100644
--- a/include/editeng/unotext.hxx
+++ b/include/editeng/unotext.hxx
@@ -235,7 +235,8 @@ namespace accessibility
 }
 
 
-class EDITENG_DLLPUBLIC SvxUnoTextRangeBase : public css::text::XTextRange,
+class EDITENG_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") SvxUnoTextRangeBase 
:
+                            public css::text::XTextRange,
                             public css::beans::XPropertySet,
                             public css::beans::XMultiPropertySet,
                             public css::beans::XMultiPropertyStates,
diff --git a/include/embeddedobj/embeddedupdate.hxx 
b/include/embeddedobj/embeddedupdate.hxx
index 1db3f36d61dc..63e7bf4464c8 100644
--- a/include/embeddedobj/embeddedupdate.hxx
+++ b/include/embeddedobj/embeddedupdate.hxx
@@ -24,7 +24,7 @@ namespace embed
 
     @since LibreOffice 7.4
  */
-class EMBOBJ_DLLPUBLIC EmbeddedUpdate
+class EMBOBJ_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") EmbeddedUpdate
 {
     /** By "Refresh all" is used to perform an OLE update and a link update.
         In the case of a link update, the class OCommonEmbeddedObject is
diff --git a/include/oox/core/contexthandler2.hxx 
b/include/oox/core/contexthandler2.hxx
index 9843a40e95d6..1414db7f242d 100644
--- a/include/oox/core/contexthandler2.hxx
+++ b/include/oox/core/contexthandler2.hxx
@@ -69,7 +69,7 @@ struct ElementInfo;
     and implEndRecord() functions of this helper. Again, this is implemented
     already in the classes ContextHandler2 and FragmentHandler2.
  */
-class OOX_DLLPUBLIC ContextHandler2Helper
+class OOX_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") ContextHandler2Helper
 {
 public:
     explicit            ContextHandler2Helper( bool bEnableTrimSpace, 
XmlFilterBase& rFilter );
diff --git a/include/oox/mathml/export.hxx b/include/oox/mathml/export.hxx
index e9589a0d1f46..a9f3862867ed 100644
--- a/include/oox/mathml/export.hxx
+++ b/include/oox/mathml/export.hxx
@@ -23,7 +23,7 @@ namespace oox
  Interface class, StarMath will implement writeFormula*() to write out markup
  representing the formula.
  */
-class OOX_DLLPUBLIC FormulaExportBase
+class OOX_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") FormulaExportBase
 {
 public:
     virtual void writeFormulaOoxml(::sax_fastparser::FSHelperPtr pSerializer,
diff --git a/include/oox/mathml/import.hxx b/include/oox/mathml/import.hxx
index 92db9a837a70..eefb609178e5 100644
--- a/include/oox/mathml/import.hxx
+++ b/include/oox/mathml/import.hxx
@@ -26,7 +26,7 @@ class XmlStream;
  representing the formula and getFormulaSize() to provide the size of the 
resulting
  formula.
  */
-class OOX_DLLPUBLIC FormulaImportBase
+class OOX_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") FormulaImportBase
 {
 public:
     virtual void readFormulaOoxml( oox::formulaimport::XmlStream& stream ) = 0;
diff --git a/include/sal/types.h b/include/sal/types.h
index 7bfb256e3208..df160d2eef50 100644
--- a/include/sal/types.h
+++ b/include/sal/types.h
@@ -682,6 +682,18 @@ template< typename T1, typename T2 > inline T1 
static_int_cast(T2 n) {
 #endif
 /// @endcond
 
+#if defined LIBO_INTERNAL_ONLY
+// An annotation mechanism used by some loplugins.  The id argument must be an 
ordinary string
+// literal.  For Clang, this expands to a clang::annotate attribute with an 
annotation consisting of
+// the concatenation of a "loplugin:" prefix and the given id suffix.  For 
non-Clang, this expands
+// to nothing to avoid e.g. -Wattributes from GCC's -Wall.
+#if defined __clang__
+#define SAL_LOPLUGIN_ANNOTATE(id) [[clang::annotate("loplugin:" id)]]
+#else
+#define SAL_LOPLUGIN_ANNOTATE(id)
+#endif
+#endif
+
 #endif // INCLUDED_SAL_TYPES_H
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/sfx2/Metadatable.hxx b/include/sfx2/Metadatable.hxx
index a84bddb899b1..ffd9b616e671 100644
--- a/include/sfx2/Metadatable.hxx
+++ b/include/sfx2/Metadatable.hxx
@@ -63,7 +63,7 @@ createXmlIdRegistry(const bool i_DocIsClipboard);
             previous hooks</li></ul>
     </p>
  */
-class SFX2_DLLPUBLIC Metadatable
+class SFX2_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") Metadatable
 {
 public:
     Metadatable() : m_pReg(nullptr) {}
diff --git a/include/sfx2/digitalsignatures.hxx 
b/include/sfx2/digitalsignatures.hxx
index 8f0e161b42a6..b46cdd52e9d9 100644
--- a/include/sfx2/digitalsignatures.hxx
+++ b/include/sfx2/digitalsignatures.hxx
@@ -19,7 +19,7 @@
 namespace sfx2
 {
 /// Extension of css::security::XDocumentDigitalSignatures for internal 
purposes.
-class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI DigitalSignatures
+class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI SAL_LOPLUGIN_ANNOTATE("crosscast") 
DigitalSignatures
 {
 public:
     /// Same as signDocumentWithCertificate(), but passes the xModel as well.
diff --git a/include/sfx2/sidebar/IContextChangeReceiver.hxx 
b/include/sfx2/sidebar/IContextChangeReceiver.hxx
index 784193c0496d..2667201444d5 100644
--- a/include/sfx2/sidebar/IContextChangeReceiver.hxx
+++ b/include/sfx2/sidebar/IContextChangeReceiver.hxx
@@ -27,7 +27,7 @@ class EnumContext;
 
 namespace sfx2::sidebar
 {
-class SFX2_DLLPUBLIC IContextChangeReceiver
+class SFX2_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") IContextChangeReceiver
 {
 public:
     virtual ~IContextChangeReceiver();
diff --git a/include/sfx2/sidebar/ILayoutableWindow.hxx 
b/include/sfx2/sidebar/ILayoutableWindow.hxx
index 344e7fd4fe55..d5124a898362 100644
--- a/include/sfx2/sidebar/ILayoutableWindow.hxx
+++ b/include/sfx2/sidebar/ILayoutableWindow.hxx
@@ -24,7 +24,7 @@
 
 namespace sfx2::sidebar
 {
-class SFX2_DLLPUBLIC ILayoutableWindow
+class SFX2_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") ILayoutableWindow
 {
 public:
     virtual ~ILayoutableWindow();
diff --git a/include/sfx2/sidebar/SidebarModelUpdate.hxx 
b/include/sfx2/sidebar/SidebarModelUpdate.hxx
index 988478bce7ab..33b273f14345 100644
--- a/include/sfx2/sidebar/SidebarModelUpdate.hxx
+++ b/include/sfx2/sidebar/SidebarModelUpdate.hxx
@@ -22,7 +22,7 @@ template <typename> class Reference;
 
 namespace sfx2::sidebar
 {
-class SFX2_DLLPUBLIC SidebarModelUpdate
+class SFX2_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") SidebarModelUpdate
 {
 public:
     virtual ~SidebarModelUpdate();
diff --git a/include/sfx2/xmldump.hxx b/include/sfx2/xmldump.hxx
index 245a07b2285f..cd32d73299e0 100644
--- a/include/sfx2/xmldump.hxx
+++ b/include/sfx2/xmldump.hxx
@@ -16,7 +16,7 @@ typedef struct _xmlTextWriter* xmlTextWriterPtr;
 namespace sfx2
 {
 /// Implemented by objects that can be dumped to xml for debugging purposes.
-class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI XmlDump
+class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI SAL_LOPLUGIN_ANNOTATE("crosscast") 
XmlDump
 {
 public:
     virtual void dumpAsXml(xmlTextWriterPtr pWriter) const = 0;
diff --git a/include/svl/stylesheetuser.hxx b/include/svl/stylesheetuser.hxx
index ba69268da809..24d23a94bde8 100644
--- a/include/svl/stylesheetuser.hxx
+++ b/include/svl/stylesheetuser.hxx
@@ -22,7 +22,7 @@ namespace svl
   a SfxStyleSheet (and listen on it). It can be queried by the stylesheet
   to determine if it is really used.
   */
-class SAL_DLLPUBLIC_RTTI StyleSheetUser
+class SAL_DLLPUBLIC_RTTI SAL_LOPLUGIN_ANNOTATE("crosscast") StyleSheetUser
 {
 public:
     /** Test whether this object is used.
diff --git a/include/svl/undo.hxx b/include/svl/undo.hxx
index eff352298a5c..a64a1f5151f3 100644
--- a/include/svl/undo.hxx
+++ b/include/svl/undo.hxx
@@ -32,7 +32,7 @@ typedef o3tl::strong_int<int, struct ViewShellDocIdTag> 
ViewShellDocId;
 
 typedef struct _xmlTextWriter* xmlTextWriterPtr;
 
-class SVL_DLLPUBLIC SfxRepeatTarget
+class SVL_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") SfxRepeatTarget
 {
 public:
     virtual             ~SfxRepeatTarget() = 0;
diff --git a/include/svx/ipolypolygoneditorcontroller.hxx 
b/include/svx/ipolypolygoneditorcontroller.hxx
index 22f7871216a6..401096b6e292 100644
--- a/include/svx/ipolypolygoneditorcontroller.hxx
+++ b/include/svx/ipolypolygoneditorcontroller.hxx
@@ -47,7 +47,7 @@ enum class SdrObjClosedKind
     Closed // closed object (polygon, ...)
 };
 
-class SAL_DLLPUBLIC_RTTI IPolyPolygonEditorController
+class SAL_DLLPUBLIC_RTTI SAL_LOPLUGIN_ANNOTATE("crosscast") 
IPolyPolygonEditorController
 {
 public:
     virtual void DeleteMarkedPoints() = 0;
diff --git a/include/vcl/IContext.hxx b/include/vcl/IContext.hxx
index d595d8771089..f4a913576e4f 100644
--- a/include/vcl/IContext.hxx
+++ b/include/vcl/IContext.hxx
@@ -16,7 +16,7 @@
 
 namespace vcl
 {
-class VCL_DLLPUBLIC IContext
+class VCL_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") IContext
 {
 protected:
     IContext() { maContext.push_back(vcl::EnumContext::Context::Any); }
diff --git a/include/vcl/ITiledRenderable.hxx b/include/vcl/ITiledRenderable.hxx
index 771ecf225c5a..10d0ea87752c 100644
--- a/include/vcl/ITiledRenderable.hxx
+++ b/include/vcl/ITiledRenderable.hxx
@@ -42,7 +42,7 @@ namespace vcl
     extern const std::map <PointerStyle, OString> gaLOKPointerMap;
 
 
-class VCL_DLLPUBLIC ITiledRenderable
+class VCL_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") ITiledRenderable
 {
 public:
 
diff --git a/include/vcl/NotebookbarContextControl.hxx 
b/include/vcl/NotebookbarContextControl.hxx
index adb6178e510d..6ded46658548 100644
--- a/include/vcl/NotebookbarContextControl.hxx
+++ b/include/vcl/NotebookbarContextControl.hxx
@@ -12,7 +12,7 @@
 
 #include <vcl/EnumContext.hxx>
 
-class NotebookbarContextControl
+class SAL_LOPLUGIN_ANNOTATE("crosscast") NotebookbarContextControl
 {
 public:
     virtual ~NotebookbarContextControl() {}
diff --git a/include/vcl/gdimetafiletools.hxx b/include/vcl/gdimetafiletools.hxx
index 665683dd279f..576ba41f372d 100644
--- a/include/vcl/gdimetafiletools.hxx
+++ b/include/vcl/gdimetafiletools.hxx
@@ -43,7 +43,7 @@ bool usesClipActions(const GDIMetaFile& rSource);
 // hook to access metafile members in classes of modules above vcl. Currently
 // used in MetafilePrimitive2D to be able to access the local Metafile member
 // e.g. from vcl module
-class UNLESS_MERGELIBS(VCL_DLLPUBLIC) MetafileAccessor
+class UNLESS_MERGELIBS(VCL_DLLPUBLIC) SAL_LOPLUGIN_ANNOTATE("crosscast") 
MetafileAccessor
 {
 public:
     virtual void accessMetafile(GDIMetaFile& rTargetMetafile) const = 0;
diff --git a/include/vcl/syswin.hxx b/include/vcl/syswin.hxx
index e2faf1337e62..d370c6399f0e 100644
--- a/include/vcl/syswin.hxx
+++ b/include/vcl/syswin.hxx
@@ -73,7 +73,7 @@ enum class TitleButton
 //dispose before the Window dispose; so a Dialog::dispose() method would
 //finish: disposeBuilder(); SystemWindow::dispose() to capture this ordering.
 
-class VCL_DLLPUBLIC VclBuilderContainer
+class VCL_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") VclBuilderContainer
 {
 public:
                     VclBuilderContainer();
diff --git a/include/vcl/toolkit/field.hxx b/include/vcl/toolkit/field.hxx
index 836e59591850..10f9cc3b571d 100644
--- a/include/vcl/toolkit/field.hxx
+++ b/include/vcl/toolkit/field.hxx
@@ -90,7 +90,7 @@ public:
     bool                    IsEmptyFieldValueEnabled() const        { return 
mbEmptyFieldValueEnabled; }
 };
 
-class VCL_DLLPUBLIC NumericFormatter : public FormatterBase
+class VCL_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") NumericFormatter : 
public FormatterBase
 {
 public:
     virtual                 ~NumericFormatter() override;
diff --git a/include/vcl/transfer.hxx b/include/vcl/transfer.hxx
index bdd8754a9e8a..bd5999a82234 100644
--- a/include/vcl/transfer.hxx
+++ b/include/vcl/transfer.hxx
@@ -373,7 +373,7 @@ public:
                                              const 
css::datatransfer::DataFlavor& rRequestFlavor );
 };
 
-class VCL_DLLPUBLIC DragSourceHelper
+class VCL_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") DragSourceHelper
 {
 private:
 
@@ -419,7 +419,7 @@ public:
     virtual             ~DragSourceHelper();
 };
 
-class VCL_DLLPUBLIC DropTargetHelper
+class VCL_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") DropTargetHelper
 {
 private:
 
diff --git a/include/vcl/wizardmachine.hxx b/include/vcl/wizardmachine.hxx
index a2ce936630c2..04698f387011 100644
--- a/include/vcl/wizardmachine.hxx
+++ b/include/vcl/wizardmachine.hxx
@@ -49,7 +49,7 @@ namespace vcl
         };
     };
 
-    class SAL_NO_VTABLE IWizardPageController
+    class SAL_NO_VTABLE SAL_LOPLUGIN_ANNOTATE("crosscast") 
IWizardPageController
     {
     public:
 
diff --git a/include/xmloff/settingsstore.hxx b/include/xmloff/settingsstore.hxx
index ba5526f72195..339e71bbd1a7 100644
--- a/include/xmloff/settingsstore.hxx
+++ b/include/xmloff/settingsstore.hxx
@@ -20,7 +20,7 @@ namespace com::sun::star::uno { template <typename > class 
Reference; }
 
 // Scans list of properties for certain URL properties that could refer
 // to internal objects, and initializes from these.
-class SAL_DLLPUBLIC_RTTI DocumentSettingsSerializer {
+class SAL_DLLPUBLIC_RTTI SAL_LOPLUGIN_ANNOTATE("crosscast") 
DocumentSettingsSerializer {
 public:
   // Import objects and update properties (eliding URLs)
   virtual css::uno::Sequence<css::beans::PropertyValue>
diff --git a/include/xmloff/xmlimp.hxx b/include/xmloff/xmlimp.hxx
index 14c7b92556b1..26873175268d 100644
--- a/include/xmloff/xmlimp.hxx
+++ b/include/xmloff/xmlimp.hxx
@@ -176,7 +176,7 @@ public:
     virtual void SAL_CALL setDocumentLocator(const css::uno::Reference< 
css::xml::sax::XLocator > & xLocator) override;
 };
 
-class XMLOFF_DLLPUBLIC SvXMLImport : public cppu::WeakImplHelper<
+class XMLOFF_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") SvXMLImport : public 
cppu::WeakImplHelper<
              css::xml::sax::XFastDocumentHandler,
              css::lang::XServiceInfo,
              css::lang::XInitialization,
diff --git a/reportdesign/inc/RptObject.hxx b/reportdesign/inc/RptObject.hxx
index c2ffe7176331..f0007d3eadca 100644
--- a/reportdesign/inc/RptObject.hxx
+++ b/reportdesign/inc/RptObject.hxx
@@ -60,7 +60,7 @@ typedef ::std::multimap< sal_Int16, OUString > IndexToNameMap;
 class OReportPage;
 class OPropertyMediator;
 
-class REPORTDESIGN_DLLPUBLIC OObjectBase
+class REPORTDESIGN_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") OObjectBase
 {
 protected:
     mutable rtl::Reference<OPropertyMediator>                         
m_xMediator;
diff --git a/sc/source/ui/inc/IAnyRefDialog.hxx 
b/sc/source/ui/inc/IAnyRefDialog.hxx
index acc8a5bfce8c..9db61ff04e32 100644
--- a/sc/source/ui/inc/IAnyRefDialog.hxx
+++ b/sc/source/ui/inc/IAnyRefDialog.hxx
@@ -28,7 +28,8 @@ namespace formula
 class RefEdit;
 class RefButton;
 }
-class SAL_NO_VTABLE IAnyRefDialog : public formula::IControlReferenceHandler
+class SAL_NO_VTABLE SAL_LOPLUGIN_ANNOTATE("crosscast") IAnyRefDialog
+    : public formula::IControlReferenceHandler
 {
 public:
     virtual ~IAnyRefDialog() COVERITY_NOEXCEPT_FALSE {}
diff --git a/sd/source/filter/eppt/epptbase.hxx 
b/sd/source/filter/eppt/epptbase.hxx
index e8ac992e3f1d..c56866b248fe 100644
--- a/sd/source/filter/eppt/epptbase.hxx
+++ b/sd/source/filter/eppt/epptbase.hxx
@@ -118,7 +118,7 @@ class PropValue
 };
 
 class EscherGraphicProvider;
-class PPTExBulletProvider
+class SAL_LOPLUGIN_ANNOTATE("crosscast") PPTExBulletProvider
 {
     friend struct PPTExParaSheet;
 
diff --git a/sdext/source/presenter/PresenterViewFactory.hxx 
b/sdext/source/presenter/PresenterViewFactory.hxx
index fa5e888ecad2..7f3468d4e57a 100644
--- a/sdext/source/presenter/PresenterViewFactory.hxx
+++ b/sdext/source/presenter/PresenterViewFactory.hxx
@@ -39,7 +39,7 @@ typedef ::cppu::WeakComponentImplHelper <
 /** Base class for presenter views that allows the view factory to store
     them in a cache and reuse deactivated views.
 */
-class CachablePresenterView
+class SAL_LOPLUGIN_ANNOTATE("crosscast") CachablePresenterView
 {
 public:
     virtual void ActivatePresenterView();
diff --git a/slideshow/source/inc/cursormanager.hxx 
b/slideshow/source/inc/cursormanager.hxx
index cfd5f0a74205..bb014696c028 100644
--- a/slideshow/source/inc/cursormanager.hxx
+++ b/slideshow/source/inc/cursormanager.hxx
@@ -33,7 +33,7 @@ namespace slideshow::internal
             Classes implementing this interface interact with the
             View, arbitrating access to the mouse cursor shape.
          */
-        class CursorManager
+        class SAL_LOPLUGIN_ANNOTATE("crosscast") CursorManager
         {
         public:
             virtual ~CursorManager() {}
diff --git a/solenv/CompilerTest_compilerplugins_clang.mk 
b/solenv/CompilerTest_compilerplugins_clang.mk
index 6e77d57cc2b3..6ea19156854f 100644
--- a/solenv/CompilerTest_compilerplugins_clang.mk
+++ b/solenv/CompilerTest_compilerplugins_clang.mk
@@ -24,6 +24,7 @@ $(eval $(call 
gb_CompilerTest_add_exception_objects,compilerplugins_clang, \
     compilerplugins/clang/test/consttobool \
     compilerplugins/clang/test/cow_wrapper \
     compilerplugins/clang/test/cppunitassertequals \
+    compilerplugins/clang/test/crosscast \
     compilerplugins/clang/test/cstylecast \
     compilerplugins/clang/test/datamembershadow \
     compilerplugins/clang/test/dbgunhandledexception \
diff --git a/svx/source/inc/celltypes.hxx b/svx/source/inc/celltypes.hxx
index 39edf2c5a81e..acc5bdec7caf 100644
--- a/svx/source/inc/celltypes.hxx
+++ b/svx/source/inc/celltypes.hxx
@@ -39,7 +39,7 @@ typedef std::vector<CellRef> CellVector;
 typedef std::vector<TableRowRef> RowVector;
 typedef std::vector<TableColumnRef> ColumnVector;
 
-class TableDesignUser
+class SAL_LOPLUGIN_ANNOTATE("crosscast") TableDesignUser
 {
 public:
     virtual bool isInUse() = 0;
diff --git a/svx/source/inc/tablemodel.hxx b/svx/source/inc/tablemodel.hxx
index 63c08a9b8891..7a2cf4851c7e 100644
--- a/svx/source/inc/tablemodel.hxx
+++ b/svx/source/inc/tablemodel.hxx
@@ -35,7 +35,7 @@ namespace sdr::table {
 class SdrTableObj;
 
 /** base class for each object implementing an XCellRange */
-class ICellRange
+class SAL_LOPLUGIN_ANNOTATE("crosscast") ICellRange
 {
 public:
     virtual sal_Int32 getLeft() = 0;
diff --git a/sw/inc/IDocumentUndoRedo.hxx b/sw/inc/IDocumentUndoRedo.hxx
index cea231a0c361..e946b5ec4efe 100644
--- a/sw/inc/IDocumentUndoRedo.hxx
+++ b/sw/inc/IDocumentUndoRedo.hxx
@@ -34,7 +34,7 @@ namespace sw {
     class RepeatContext;
 }
 
-class IDocumentUndoRedo
+class SAL_LOPLUGIN_ANNOTATE("crosscast") IDocumentUndoRedo
 {
 public:
 
diff --git a/sw/inc/IMark.hxx b/sw/inc/IMark.hxx
index c256c2ef997c..04b7efa22141 100644
--- a/sw/inc/IMark.hxx
+++ b/sw/inc/IMark.hxx
@@ -84,7 +84,7 @@ namespace sw::mark
             IBookmark &operator =(IBookmark const&) = delete;
     };
 
-    class SW_DLLPUBLIC IFieldmark
+    class SW_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") IFieldmark
         : virtual public IMark
     {
         protected:
diff --git a/sw/inc/calbck.hxx b/sw/inc/calbck.hxx
index 26dcd2566fc1..abe556ef6757 100644
--- a/sw/inc/calbck.hxx
+++ b/sw/inc/calbck.hxx
@@ -223,7 +223,9 @@ namespace sw
     // Still: in the long run the SwClient/SwModify interface should not be
     // used anymore, in which case a BroadcasterMixin should be enough instead
     // then.
-    class SW_DLLPUBLIC BroadcastingModify : public SwModify, public 
BroadcasterMixin {
+    class SW_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") BroadcastingModify :
+        public SwModify, public BroadcasterMixin
+    {
         public:
             virtual void CallSwClientNotify(const SfxHint& rHint) const 
override;
     };
diff --git a/sw/inc/contentindex.hxx b/sw/inc/contentindex.hxx
index 2be6bc650879..873e1512ca4f 100644
--- a/sw/inc/contentindex.hxx
+++ b/sw/inc/contentindex.hxx
@@ -113,7 +113,7 @@ public:
 SW_DLLPUBLIC std::ostream& operator <<(std::ostream& s, const SwContentIndex& 
index);
 
 /// Helper base class for SwContentNode to manage the list of attached 
SwContentIndex
-class SAL_WARN_UNUSED SwContentIndexReg
+class SAL_WARN_UNUSED SAL_LOPLUGIN_ANNOTATE("crosscast") SwContentIndexReg
 {
     friend class SwContentIndex;
 
diff --git a/sw/source/core/inc/flowfrm.hxx b/sw/source/core/inc/flowfrm.hxx
index a5766c793eb7..3eaf2adfb3ca 100644
--- a/sw/source/core/inc/flowfrm.hxx
+++ b/sw/source/core/inc/flowfrm.hxx
@@ -56,7 +56,7 @@ class SwNodeIndex;
     FlowFrame can work with the reference to the SwFrame instead of working 
with
     its own this-pointer.
  */
-class SwFlowFrame
+class SAL_LOPLUGIN_ANNOTATE("crosscast") SwFlowFrame
 {
     // PrepareMake is allowed to lock/unlock (robustness)
     friend inline void PrepareLock  ( SwFlowFrame * );
diff --git a/sw/source/core/unocore/unodraw.cxx 
b/sw/source/core/unocore/unodraw.cxx
index 9a2ff848de69..517dd5aaa8cd 100644
--- a/sw/source/core/unocore/unodraw.cxx
+++ b/sw/source/core/unocore/unodraw.cxx
@@ -295,6 +295,9 @@ uno::Reference<drawing::XShape> 
SwFmDrawPage::GetShape(SdrObject* pObj)
     if(!pObj)
         return nullptr;
     SwFrameFormat* pFormat = ::FindFrameFormat( pObj );
+    // TODO see comment at
+    // 
<https://gerrit.libreoffice.org/c/core/+/78734/4#message-5ee4e724a8073c5c475f07da0b5d79bc34e61de5>
+    // "make page bookkeep the SwXShapes" [-loplugin:crosscast]:
     SwFmDrawPage* pPage = dynamic_cast<SwFmDrawPage*>(pFormat);
     if(!pPage || pPage->m_vShapes.empty())
         return uno::Reference<drawing::XShape>(pObj->getUnoShape(), 
uno::UNO_QUERY);
diff --git a/sw/source/uibase/inc/FrameControl.hxx 
b/sw/source/uibase/inc/FrameControl.hxx
index 561dac78fcb7..4ab1d61b0303 100644
--- a/sw/source/uibase/inc/FrameControl.hxx
+++ b/sw/source/uibase/inc/FrameControl.hxx
@@ -20,7 +20,7 @@ class SwFrame;
 class Point;
 
 /// Abstract interface to be implemented by writer FrameControls
-class ISwFrameControl
+class SAL_LOPLUGIN_ANNOTATE("crosscast") ISwFrameControl
 {
 public:
     virtual ~ISwFrameControl();
diff --git a/vcl/inc/IPrioritable.hxx b/vcl/inc/IPrioritable.hxx
index 55faf6431243..559fbc982f74 100644
--- a/vcl/inc/IPrioritable.hxx
+++ b/vcl/inc/IPrioritable.hxx
@@ -17,7 +17,7 @@
 namespace vcl
 {
 
-class VCL_DLLPUBLIC IPrioritable
+class VCL_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") IPrioritable
 {
 protected:
     IPrioritable() : m_nPriority(VCL_PRIORITY_DEFAULT)
diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx 
b/vcl/inc/jsdialog/jsdialogbuilder.hxx
index a837df4998a1..291fd24babb7 100644
--- a/vcl/inc/jsdialog/jsdialogbuilder.hxx
+++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx
@@ -318,7 +318,7 @@ private:
     VclPtr<vcl::Window>& GetNotifierWindow();
 };
 
-class BaseJSWidget
+class SAL_LOPLUGIN_ANNOTATE("crosscast") BaseJSWidget
 {
 public:
     virtual ~BaseJSWidget() = default;
diff --git a/vcl/inc/unx/x11/x11gdiimpl.h b/vcl/inc/unx/x11/x11gdiimpl.h
index 43e4c6bda99e..51c1298089ad 100644
--- a/vcl/inc/unx/x11/x11gdiimpl.h
+++ b/vcl/inc/unx/x11/x11gdiimpl.h
@@ -14,7 +14,7 @@
 
 class ControlCacheKey;
 
-class X11GraphicsImpl
+class SAL_LOPLUGIN_ANNOTATE("crosscast") X11GraphicsImpl
 {
 public:
     virtual ~X11GraphicsImpl(){};
diff --git a/xmlsecurity/inc/certificate.hxx b/xmlsecurity/inc/certificate.hxx
index bd24bcd72c00..8357f50651a1 100644
--- a/xmlsecurity/inc/certificate.hxx
+++ b/xmlsecurity/inc/certificate.hxx
@@ -24,7 +24,7 @@ enum class SignatureMethodAlgorithm;
 namespace xmlsecurity
 {
 /// Extension of css::security::XCertificate for module-internal purposes.
-class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI Certificate
+class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI SAL_LOPLUGIN_ANNOTATE("crosscast") 
Certificate
 {
 public:
     /// Returns the SHA-256 thumbprint.

Reply via email to