loplugin:redundantfcast check for std::function cast

noticed by mike kaganski

Change-Id: I210f6d2655edde74d9256c6147b7d15a88180196
Reviewed-on: https://gerrit.libreoffice.org/78743
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
Noel Grandin
2019-09-07 14:28:59 +02:00
parent 06f99cd552
commit 81fd3bb4d7
4 changed files with 61 additions and 27 deletions

View File

@@ -13,6 +13,7 @@
#include "plugin.hxx" #include "plugin.hxx"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <unordered_set>
namespace namespace
{ {
@@ -53,6 +54,7 @@ public:
{ {
return true; return true;
} }
if (m_Seen.insert(cxxFunctionalCastExpr->getExprLoc()).second)
report(DiagnosticsEngine::Warning, "redundant functional cast from %0 to %1", report(DiagnosticsEngine::Warning, "redundant functional cast from %0 to %1",
cxxFunctionalCastExpr->getExprLoc()) cxxFunctionalCastExpr->getExprLoc())
<< t2 << t1 << cxxFunctionalCastExpr->getSourceRange(); << t2 << t1 << cxxFunctionalCastExpr->getSourceRange();
@@ -103,12 +105,15 @@ public:
if (t1.getCanonicalType().getTypePtr() != paramClassOrStructType) if (t1.getCanonicalType().getTypePtr() != paramClassOrStructType)
continue; continue;
if (m_Seen.insert(arg->getExprLoc()).second)
{
report(DiagnosticsEngine::Warning, "redundant functional cast from %0 to %1", report(DiagnosticsEngine::Warning, "redundant functional cast from %0 to %1",
arg->getExprLoc()) arg->getExprLoc())
<< t2 << t1 << arg->getSourceRange(); << t2 << t1 << arg->getSourceRange();
report(DiagnosticsEngine::Note, "in call to method here", param->getLocation()) report(DiagnosticsEngine::Note, "in call to method here", param->getLocation())
<< param->getSourceRange(); << param->getSourceRange();
} }
}
return true; return true;
} }
@@ -146,15 +151,28 @@ public:
if (t1.getCanonicalType().getTypePtr() != paramClassOrStructType) if (t1.getCanonicalType().getTypePtr() != paramClassOrStructType)
continue; continue;
if (m_Seen.insert(arg->getExprLoc()).second)
{
report(DiagnosticsEngine::Warning, "redundant functional cast from %0 to %1", report(DiagnosticsEngine::Warning, "redundant functional cast from %0 to %1",
arg->getExprLoc()) arg->getExprLoc())
<< t2 << t1 << arg->getSourceRange(); << t2 << t1 << arg->getSourceRange();
report(DiagnosticsEngine::Note, "in call to method here", param->getLocation()) report(DiagnosticsEngine::Note, "in call to method here", param->getLocation())
<< param->getSourceRange(); << param->getSourceRange();
} }
}
return true; return true;
} }
// Find redundant cast to std::function, where clang reports
// two different types for the inner and outer
static bool isRedundantStdFunctionCast(CXXFunctionalCastExpr const* expr)
{
auto cxxConstruct = dyn_cast<CXXConstructExpr>(compat::IgnoreImplicit(expr->getSubExpr()));
if (!cxxConstruct)
return false;
return isa<LambdaExpr>(cxxConstruct->getArg(0));
}
bool VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const* expr) bool VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const* expr)
{ {
if (ignoreLocation(expr)) if (ignoreLocation(expr))
@@ -166,7 +184,8 @@ public:
return true; return true;
auto const t1 = expr->getTypeAsWritten(); auto const t1 = expr->getTypeAsWritten();
auto const t2 = compat::getSubExprAsWritten(expr)->getType(); auto const t2 = compat::getSubExprAsWritten(expr)->getType();
if (t1.getCanonicalType().getTypePtr() != t2.getCanonicalType().getTypePtr()) if (!(t1.getCanonicalType().getTypePtr() == t2.getCanonicalType().getTypePtr()
|| isRedundantStdFunctionCast(expr)))
{ {
return true; return true;
} }
@@ -191,6 +210,7 @@ public:
if (tc.Typedef("sal_Int32").GlobalNamespace()) if (tc.Typedef("sal_Int32").GlobalNamespace())
return true; return true;
if (m_Seen.insert(expr->getExprLoc()).second)
report(DiagnosticsEngine::Warning, "redundant functional cast from %0 to %1", report(DiagnosticsEngine::Warning, "redundant functional cast from %0 to %1",
expr->getExprLoc()) expr->getExprLoc())
<< t2 << t1 << expr->getSourceRange(); << t2 << t1 << expr->getSourceRange();
@@ -218,6 +238,8 @@ public:
if (preRun()) if (preRun())
TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
} }
std::unordered_set<SourceLocation> m_Seen;
}; };
static loplugin::Plugin::Registration<RedundantFCast> redundantfcast("redundantfcast"); static loplugin::Plugin::Registration<RedundantFCast> redundantfcast("redundantfcast");

View File

@@ -9,11 +9,12 @@
#include "sal/config.h" #include "sal/config.h"
#include <memory>
#include "rtl/ustring.hxx" #include "rtl/ustring.hxx"
#include "tools/color.hxx" #include "tools/color.hxx"
#include <functional>
#include <memory>
void method1(OUString const&); // expected-note {{in call to method here [loplugin:redundantfcast]}} void method1(OUString const&); // expected-note {{in call to method here [loplugin:redundantfcast]}}
struct Foo struct Foo
@@ -56,7 +57,6 @@ int main()
OUString s1; OUString s1;
method1(OUString( method1(OUString(
s1)); // expected-error@-1 {{redundant functional cast from 'rtl::OUString' to 'rtl::OUString' [loplugin:redundantfcast]}} s1)); // expected-error@-1 {{redundant functional cast from 'rtl::OUString' to 'rtl::OUString' [loplugin:redundantfcast]}}
// expected-error@-2 {{redundant functional cast from 'rtl::OUString' to 'rtl::OUString' [loplugin:redundantfcast]}}
OUString s2; OUString s2;
s2 = OUString( s2 = OUString(
s1); // expected-error@-1 {{redundant functional cast from 'rtl::OUString' to 'rtl::OUString' [loplugin:redundantfcast]}} s1); // expected-error@-1 {{redundant functional cast from 'rtl::OUString' to 'rtl::OUString' [loplugin:redundantfcast]}}
@@ -68,11 +68,11 @@ int main()
Foo foo(1); Foo foo(1);
func1(Foo( func1(Foo(
foo)); // expected-error@-1 {{redundant functional cast from 'Foo' to 'Foo' [loplugin:redundantfcast]}} expected-error@-1 {{redundant functional cast from 'Foo' to 'Foo' [loplugin:redundantfcast]}} foo)); // expected-error@-1 {{redundant functional cast from 'Foo' to 'Foo' [loplugin:redundantfcast]}}
const tools::Polygon aPolygon; const tools::Polygon aPolygon;
ImplWritePolyPolygonRecord(tools::PolyPolygon(tools::Polygon( ImplWritePolyPolygonRecord(tools::PolyPolygon(tools::Polygon(
aPolygon))); // expected-error@-1 {{redundant functional cast from 'const tools::Polygon' to 'tools::Polygon' [loplugin:redundantfcast]}} expected-error@-1 {{redundant functional cast from 'const tools::Polygon' to 'tools::Polygon' [loplugin:redundantfcast]}} aPolygon))); // expected-error@-1 {{redundant functional cast from 'const tools::Polygon' to 'tools::Polygon' [loplugin:redundantfcast]}}
} }
class Class1 class Class1
@@ -81,7 +81,19 @@ class Class1
Foo func2() Foo func2()
{ {
return Foo( return Foo(
foo); // expected-error@-1 {{redundant functional cast from 'Foo' to 'Foo' [loplugin:redundantfcast]}} expected-error@-1 {{redundant functional cast from 'Foo' to 'Foo' [loplugin:redundantfcast]}} foo); // expected-error@-1 {{redundant functional cast from 'Foo' to 'Foo' [loplugin:redundantfcast]}}
} }
}; };
// casting of lambdas
namespace test5
{
void f1(std::function<void()> x);
void f2()
{
// expected-error-re@+1 {{redundant functional cast {{.+}} [loplugin:redundantfcast]}}
f1(std::function([&]() {}));
}
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View File

@@ -413,7 +413,7 @@ Qt5Instance::createPicker(css::uno::Reference<css::uno::XComponentContext> const
{ {
SolarMutexGuard g; SolarMutexGuard g;
Qt5FilePicker* pPicker; Qt5FilePicker* pPicker;
RunInMainThread(std::function([&, this]() { pPicker = createPicker(context, eMode); })); RunInMainThread([&, this]() { pPicker = createPicker(context, eMode); });
assert(pPicker); assert(pPicker);
return pPicker; return pPicker;
} }

View File

@@ -43,9 +43,9 @@ KF5SalInstance::KF5SalInstance(std::unique_ptr<QApplication>& pQApp)
SalFrame* KF5SalInstance::CreateFrame(SalFrame* pParent, SalFrameStyleFlags nState) SalFrame* KF5SalInstance::CreateFrame(SalFrame* pParent, SalFrameStyleFlags nState)
{ {
SalFrame* pRet(nullptr); SalFrame* pRet(nullptr);
RunInMainThread(std::function([&pRet, pParent, nState]() { RunInMainThread([&pRet, pParent, nState]() {
pRet = new KF5SalFrame(static_cast<KF5SalFrame*>(pParent), nState, true); pRet = new KF5SalFrame(static_cast<KF5SalFrame*>(pParent), nState, true);
})); });
assert(pRet); assert(pRet);
return pRet; return pRet;
} }
@@ -65,7 +65,7 @@ KF5SalInstance::createPicker(css::uno::Reference<css::uno::XComponentContext> co
{ {
SolarMutexGuard g; SolarMutexGuard g;
Qt5FilePicker* pPicker; Qt5FilePicker* pPicker;
RunInMainThread(std::function([&, this]() { pPicker = createPicker(context, eMode); })); RunInMainThread([&, this]() { pPicker = createPicker(context, eMode); });
assert(pPicker); assert(pPicker);
return pPicker; return pPicker;
} }