summaryrefslogtreecommitdiffstats
path: root/compilerplugins
diff options
context:
space:
mode:
authorNoel <noel.grandin@collabora.co.uk>2021-03-05 08:37:41 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2021-03-06 13:08:26 +0100
commitbd37588605f7773d41b5388b18952e5c90f12214 (patch)
tree498116ae9376e7671bf0441e476dad16f2bd197e /compilerplugins
parentdrop StyleSettings::GetColorValueSetMaximumRowCount (diff)
downloadcore-bd37588605f7773d41b5388b18952e5c90f12214.tar.gz
core-bd37588605f7773d41b5388b18952e5c90f12214.zip
loplugin:staticdynamic look for static after dynamic
Change-Id: Ic3066d9a9441e369370cc6aa0fbffb9a321bc928 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111985 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/staticdynamic.cxx64
-rw-r--r--compilerplugins/clang/test/staticdynamic.cxx8
2 files changed, 59 insertions, 13 deletions
diff --git a/compilerplugins/clang/staticdynamic.cxx b/compilerplugins/clang/staticdynamic.cxx
index b2383413b287..b104b0333fcd 100644
--- a/compilerplugins/clang/staticdynamic.cxx
+++ b/compilerplugins/clang/staticdynamic.cxx
@@ -45,22 +45,26 @@ public:
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;
+ struct BlockState
+ {
+ std::map<std::pair<VarDecl const*, clang::Type const*>, SourceLocation> staticCastVars;
+ std::map<std::pair<VarDecl const*, clang::Type const*>, SourceLocation> dynamicCastVars;
+ };
// only maintain state inside a single basic block, we're not trying to analyse
// cross-block interactions.
- std::vector<MapType> blockStack;
+ std::vector<BlockState> blockStack;
+ BlockState blockState;
};
bool StaticDynamic::PreTraverseCompoundStmt(CompoundStmt*)
{
- blockStack.push_back(std::move(staticCastVars));
+ blockStack.push_back(std::move(blockState));
return true;
}
bool StaticDynamic::PostTraverseCompoundStmt(CompoundStmt*, bool)
{
- staticCastVars = std::move(blockStack.back());
+ blockState = std::move(blockStack.back());
blockStack.pop_back();
return true;
}
@@ -86,8 +90,28 @@ bool StaticDynamic::VisitCXXStaticCastExpr(CXXStaticCastExpr const* staticCastEx
auto varDecl = dyn_cast_or_null<VarDecl>(subExprDecl->getDecl());
if (!varDecl)
return true;
- staticCastVars.insert({ { varDecl, staticCastExpr->getTypeAsWritten().getTypePtr() },
- compat::getBeginLoc(staticCastExpr) });
+ auto it = blockState.dynamicCastVars.find(
+ { varDecl, staticCastExpr->getTypeAsWritten().getTypePtr() });
+ if (it != blockState.dynamicCastVars.end())
+ {
+ StringRef fn = getFilenameOfLocation(
+ compiler.getSourceManager().getSpellingLoc(compat::getBeginLoc(staticCastExpr)));
+ // loop
+ if (loplugin::isSamePathname(fn, SRCDIR "/basctl/source/basicide/basobj3.cxx"))
+ return true;
+ if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/doc/swserv.cxx"))
+ return true;
+ if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/text/txtfly.cxx"))
+ return true;
+
+ report(DiagnosticsEngine::Warning, "static_cast after dynamic_cast",
+ compat::getBeginLoc(staticCastExpr))
+ << staticCastExpr->getSourceRange();
+ report(DiagnosticsEngine::Note, "dynamic_cast here", it->second);
+ return true;
+ }
+ blockState.staticCastVars.insert({ { varDecl, staticCastExpr->getTypeAsWritten().getTypePtr() },
+ compat::getBeginLoc(staticCastExpr) });
return true;
}
@@ -102,13 +126,27 @@ bool StaticDynamic::VisitCXXDynamicCastExpr(CXXDynamicCastExpr const* dynamicCas
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())
+ auto it = blockState.staticCastVars.find(
+ { varDecl, dynamicCastExpr->getTypeAsWritten().getTypePtr() });
+ if (it != blockState.staticCastVars.end())
+ {
+ report(DiagnosticsEngine::Warning, "dynamic_cast after static_cast",
+ compat::getBeginLoc(dynamicCastExpr))
+ << dynamicCastExpr->getSourceRange();
+ report(DiagnosticsEngine::Note, "static_cast here", it->second);
return true;
- report(DiagnosticsEngine::Warning, "dynamic_cast after static_cast",
- compat::getBeginLoc(dynamicCastExpr))
- << dynamicCastExpr->getSourceRange();
- report(DiagnosticsEngine::Note, "static_cast here", it->second);
+ }
+ auto loc = compat::getBeginLoc(dynamicCastExpr);
+ if (compiler.getSourceManager().isMacroArgExpansion(loc)
+ && (Lexer::getImmediateMacroNameForDiagnostics(loc, compiler.getSourceManager(),
+ compiler.getLangOpts())
+ == "assert"))
+ {
+ return true;
+ }
+ blockState.dynamicCastVars.insert(
+ { { varDecl, dynamicCastExpr->getTypeAsWritten().getTypePtr() },
+ compat::getBeginLoc(dynamicCastExpr) });
return true;
}
diff --git a/compilerplugins/clang/test/staticdynamic.cxx b/compilerplugins/clang/test/staticdynamic.cxx
index af4ea94c754a..d700ea06c435 100644
--- a/compilerplugins/clang/test/staticdynamic.cxx
+++ b/compilerplugins/clang/test/staticdynamic.cxx
@@ -25,4 +25,12 @@ void f1(ClassA* p1)
dynamic_cast<ClassB*>(p1)->foo();
};
+void f2(ClassA* p1)
+{
+ // expected-note@+1 {{dynamic_cast here [loplugin:staticdynamic]}}
+ dynamic_cast<ClassB*>(p1)->foo();
+ // expected-error@+1 {{static_cast after dynamic_cast [loplugin:staticdynamic]}}
+ static_cast<ClassB*>(p1)->foo();
+};
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */