diff options
-rw-r--r-- | chart2/source/controller/dialogs/dlg_ObjectProperties.cxx | 5 | ||||
-rw-r--r-- | compilerplugins/clang/sharedvisitor/dummyplugin.hxx | 1 | ||||
-rw-r--r-- | compilerplugins/clang/staticdynamic.cxx | 120 | ||||
-rw-r--r-- | compilerplugins/clang/test/staticdynamic.cxx | 28 | ||||
-rw-r--r-- | sd/source/core/drawdoc2.cxx | 5 | ||||
-rw-r--r-- | solenv/CompilerTest_compilerplugins_clang.mk | 1 |
6 files changed, 156 insertions, 4 deletions
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 \ |