chart2/source/controller/dialogs/dlg_ObjectProperties.cxx |    5 
 compilerplugins/clang/sharedvisitor/dummyplugin.hxx       |    1 
 compilerplugins/clang/staticdynamic.cxx                   |  120 ++++++++++++++
 compilerplugins/clang/test/staticdynamic.cxx              |   28 +++
 sd/source/core/drawdoc2.cxx                               |    5 
 solenv/CompilerTest_compilerplugins_clang.mk              |    1 
 6 files changed, 156 insertions(+), 4 deletions(-)

New commits:
commit 11083d1fcfc2dde543c6daddea51b554d032392c
Author:     Noel <noel.gran...@collabora.co.uk>
AuthorDate: Fri Feb 26 15:20:17 2021 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Mon Mar 1 12:33:17 2021 +0100

    new loplugin:staticdynamic
    
    look for places we are dynamic_cast'ing after static_cast'ing,
    which means the dynamic_cast is a waste of time.
    
    Change-Id: Ife11bb675020738040646230bbd038278d84f7f2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111631
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx 
b/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx
index a356c1ac4185..b941deab6ab9 100644
--- a/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx
+++ b/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx
@@ -535,8 +535,9 @@ void SchAttribTabDlg::PageCreated(const OString& rId, 
SfxTabPage &rPage)
     else if (rId == "axislabel")
     {
         bool bShowStaggeringControls = 
m_pParameter->CanAxisLabelsBeStaggered();
-        static_cast<SchAxisLabelTabPage&>(rPage).ShowStaggeringControls( 
bShowStaggeringControls );
-        dynamic_cast< SchAxisLabelTabPage& >( rPage ).SetComplexCategories( 
m_pParameter->IsComplexCategoriesAxis() );
+        auto & rLabelPage = static_cast<SchAxisLabelTabPage&>(rPage);
+        rLabelPage.ShowStaggeringControls( bShowStaggeringControls );
+        rLabelPage.SetComplexCategories( 
m_pParameter->IsComplexCategoriesAxis() );
     }
     else if (rId == "axispos")
     {
diff --git a/compilerplugins/clang/sharedvisitor/dummyplugin.hxx 
b/compilerplugins/clang/sharedvisitor/dummyplugin.hxx
index d20f82f9278e..fea2786a796e 100644
--- a/compilerplugins/clang/sharedvisitor/dummyplugin.hxx
+++ b/compilerplugins/clang/sharedvisitor/dummyplugin.hxx
@@ -43,6 +43,7 @@ public:
     bool TraverseWhileStmt( WhileStmt* ) { return complain(); }
     bool TraverseDoStmt( DoStmt* ) { return complain(); }
     bool TraverseForStmt( ForStmt* ) { return complain(); }
+    bool TraverseCompoundStmt( CompoundStmt* ) { return complain(); }
     bool TraverseCXXForRangeStmt( CXXForRangeStmt* ) { return complain(); }
     bool TraverseConditionalOperator( ConditionalOperator* ) { return 
complain(); }
     bool TraverseCXXCatchStmt( CXXCatchStmt* ) { return complain(); }
diff --git a/compilerplugins/clang/staticdynamic.cxx 
b/compilerplugins/clang/staticdynamic.cxx
new file mode 100644
index 000000000000..b2383413b287
--- /dev/null
+++ b/compilerplugins/clang/staticdynamic.cxx
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+#ifndef LO_CLANG_SHARED_PLUGINS
+
+#include <cassert>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <map>
+#include <vector>
+
+#include "compat.hxx"
+#include "check.hxx"
+#include "plugin.hxx"
+
+namespace
+{
+class StaticDynamic : public loplugin::FilteringPlugin<StaticDynamic>
+{
+public:
+    explicit StaticDynamic(loplugin::InstantiationData const& data)
+        : FilteringPlugin(data)
+    {
+    }
+
+    bool preRun() override { return compiler.getLangOpts().CPlusPlus; }
+    void postRun() override {}
+    virtual void run() override
+    {
+        if (preRun())
+            TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
+    }
+
+    bool VisitCXXDynamicCastExpr(CXXDynamicCastExpr const*);
+    bool VisitCXXStaticCastExpr(CXXStaticCastExpr const*);
+    bool PreTraverseCompoundStmt(CompoundStmt*);
+    bool PostTraverseCompoundStmt(CompoundStmt*, bool);
+    bool TraverseCompoundStmt(CompoundStmt*);
+
+private:
+    // the key is the pair of VarDecl and the type being cast to.
+    typedef std::map<std::pair<VarDecl const*, clang::Type const*>, 
SourceLocation> MapType;
+    MapType staticCastVars;
+    // only maintain state inside a single basic block, we're not trying to 
analyse
+    // cross-block interactions.
+    std::vector<MapType> blockStack;
+};
+
+bool StaticDynamic::PreTraverseCompoundStmt(CompoundStmt*)
+{
+    blockStack.push_back(std::move(staticCastVars));
+    return true;
+}
+
+bool StaticDynamic::PostTraverseCompoundStmt(CompoundStmt*, bool)
+{
+    staticCastVars = std::move(blockStack.back());
+    blockStack.pop_back();
+    return true;
+}
+
+bool StaticDynamic::TraverseCompoundStmt(CompoundStmt* compoundStmt)
+{
+    bool ret = true;
+    if (PreTraverseCompoundStmt(compoundStmt))
+    {
+        ret = FilteringPlugin::TraverseCompoundStmt(compoundStmt);
+        PostTraverseCompoundStmt(compoundStmt, ret);
+    }
+    return ret;
+}
+
+bool StaticDynamic::VisitCXXStaticCastExpr(CXXStaticCastExpr const* 
staticCastExpr)
+{
+    if (ignoreLocation(staticCastExpr))
+        return true;
+    auto subExprDecl = 
dyn_cast<DeclRefExpr>(staticCastExpr->getSubExpr()->IgnoreParenImpCasts());
+    if (!subExprDecl)
+        return true;
+    auto varDecl = dyn_cast_or_null<VarDecl>(subExprDecl->getDecl());
+    if (!varDecl)
+        return true;
+    staticCastVars.insert({ { varDecl, 
staticCastExpr->getTypeAsWritten().getTypePtr() },
+                            compat::getBeginLoc(staticCastExpr) });
+    return true;
+}
+
+bool StaticDynamic::VisitCXXDynamicCastExpr(CXXDynamicCastExpr const* 
dynamicCastExpr)
+{
+    if (ignoreLocation(dynamicCastExpr))
+        return true;
+
+    auto subExprDecl = 
dyn_cast<DeclRefExpr>(dynamicCastExpr->getSubExpr()->IgnoreParenImpCasts());
+    if (!subExprDecl)
+        return true;
+    auto varDecl = dyn_cast_or_null<VarDecl>(subExprDecl->getDecl());
+    if (!varDecl)
+        return true;
+    auto it = staticCastVars.find({ varDecl, 
dynamicCastExpr->getTypeAsWritten().getTypePtr() });
+    if (it == staticCastVars.end())
+        return true;
+    report(DiagnosticsEngine::Warning, "dynamic_cast after static_cast",
+           compat::getBeginLoc(dynamicCastExpr))
+        << dynamicCastExpr->getSourceRange();
+    report(DiagnosticsEngine::Note, "static_cast here", it->second);
+    return true;
+}
+
+loplugin::Plugin::Registration<StaticDynamic> staticdynamic("staticdynamic");
+}
+
+#endif // LO_CLANG_SHARED_PLUGINS
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/compilerplugins/clang/test/staticdynamic.cxx 
b/compilerplugins/clang/test/staticdynamic.cxx
new file mode 100644
index 000000000000..af4ea94c754a
--- /dev/null
+++ b/compilerplugins/clang/test/staticdynamic.cxx
@@ -0,0 +1,28 @@
+/* -*- 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 ClassA
+{
+    virtual ~ClassA() {}
+};
+
+struct ClassB : public ClassA
+{
+    void foo() {}
+};
+
+void f1(ClassA* p1)
+{
+    // expected-note@+1 {{static_cast here [loplugin:staticdynamic]}}
+    static_cast<ClassB*>(p1)->foo();
+    // expected-error@+1 {{dynamic_cast after static_cast 
[loplugin:staticdynamic]}}
+    dynamic_cast<ClassB*>(p1)->foo();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sd/source/core/drawdoc2.cxx b/sd/source/core/drawdoc2.cxx
index 1603e9b8d9e8..f9af8c83b2ba 100644
--- a/sd/source/core/drawdoc2.cxx
+++ b/sd/source/core/drawdoc2.cxx
@@ -412,8 +412,9 @@ SdrPage* SdDrawDocument::RemovePage(sal_uInt16 nPgNum)
 
     bool bLast = ((nPgNum+1)/2 == (GetPageCount()+1)/2);
 
-    static_cast<SdPage*>(pPage)->DisconnectLink();
-    ReplacePageInCustomShows( dynamic_cast< SdPage* >( pPage ), nullptr );
+    auto pSdPage = static_cast<SdPage*>(pPage);
+    pSdPage->DisconnectLink();
+    ReplacePageInCustomShows( pSdPage, nullptr );
     UpdatePageObjectsInNotes(nPgNum);
 
     if (!bLast)
diff --git a/solenv/CompilerTest_compilerplugins_clang.mk 
b/solenv/CompilerTest_compilerplugins_clang.mk
index dc143526b9e4..6ac27d98d4cf 100644
--- a/solenv/CompilerTest_compilerplugins_clang.mk
+++ b/solenv/CompilerTest_compilerplugins_clang.mk
@@ -80,6 +80,7 @@ $(eval $(call 
gb_CompilerTest_add_exception_objects,compilerplugins_clang, \
     compilerplugins/clang/test/simplifypointertobool \
     compilerplugins/clang/test/singlevalfields \
     compilerplugins/clang/test/staticconstfield \
+    compilerplugins/clang/test/staticdynamic \
     compilerplugins/clang/test/staticvar \
     compilerplugins/clang/test/stdfunction \
     compilerplugins/clang/test/stringadd \
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to