[Libreoffice-commits] core.git: compilerplugins/clang
Stephan Bergmann (via logerrit)
logerrit at kemper.freedesktop.org
Fri Sep 13 07:27:57 UTC 2019
compilerplugins/clang/check.hxx | 11 +++
compilerplugins/clang/redundantfcast.cxx | 80 +++++++++++++++++++++++++-
compilerplugins/clang/test/redundantfcast.cxx | 9 ++
3 files changed, 98 insertions(+), 2 deletions(-)
New commits:
commit d27e70fce2acfc9b14f2f07c9096daa50dc2acd8
Author: Stephan Bergmann <sbergman at redhat.com>
AuthorDate: Fri Sep 13 08:31:20 2019 +0200
Commit: Stephan Bergmann <sbergman at redhat.com>
CommitDate: Fri Sep 13 09:27:20 2019 +0200
Avoid some false loplugin:redundantfcast involving std::function and lambdas
Change-Id: Id9a93fb60f957d75450deb93f1461b1d9dacf8ca
Reviewed-on: https://gerrit.libreoffice.org/78860
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman at redhat.com>
diff --git a/compilerplugins/clang/check.hxx b/compilerplugins/clang/check.hxx
index 4ac4f8e99cb6..e027a5ca709f 100644
--- a/compilerplugins/clang/check.hxx
+++ b/compilerplugins/clang/check.hxx
@@ -87,6 +87,8 @@ public:
inline ContextCheck Struct(llvm::StringRef id) const;
+ inline ContextCheck ClassOrStruct(llvm::StringRef id) const;
+
inline ContextCheck Union(llvm::StringRef id) const;
inline ContextCheck Function(llvm::StringRef id) const;
@@ -212,6 +214,15 @@ ContextCheck DeclCheck::Struct(llvm::StringRef id) const
return detail::checkRecordDecl(decl_, clang::TTK_Struct, id);
}
+ContextCheck DeclCheck::ClassOrStruct(llvm::StringRef id) const
+{
+ auto const c1 = Class(id);
+ if (c1) {
+ return c1;
+ }
+ return Struct(id);
+}
+
ContextCheck DeclCheck::Union(llvm::StringRef id) const
{
return detail::checkRecordDecl(decl_, clang::TTK_Union, id);
diff --git a/compilerplugins/clang/redundantfcast.cxx b/compilerplugins/clang/redundantfcast.cxx
index 8879a386d621..260fe1852417 100644
--- a/compilerplugins/clang/redundantfcast.cxx
+++ b/compilerplugins/clang/redundantfcast.cxx
@@ -14,6 +14,7 @@
#include <iostream>
#include <fstream>
#include <unordered_set>
+#include <vector>
namespace
{
@@ -165,12 +166,87 @@ public:
// Find redundant cast to std::function, where clang reports
// two different types for the inner and outer
- static bool isRedundantStdFunctionCast(CXXFunctionalCastExpr const* expr)
+ bool isRedundantStdFunctionCast(CXXFunctionalCastExpr const* expr)
{
+ bool deduced = false;
+ QualType target;
+ auto const written = expr->getTypeAsWritten();
+ if (auto const t1 = written->getAs<DeducedTemplateSpecializationType>())
+ {
+ auto const decl = t1->getTemplateName().getAsTemplateDecl();
+ if (!decl)
+ {
+ return false;
+ }
+ if (!loplugin::DeclCheck(decl->getTemplatedDecl())
+ .ClassOrStruct("function")
+ .StdNamespace())
+ {
+ return false;
+ }
+ deduced = true;
+ }
+ else if (auto const t2 = written->getAs<TemplateSpecializationType>())
+ {
+ auto const decl = t2->getTemplateName().getAsTemplateDecl();
+ if (!decl)
+ {
+ return false;
+ }
+ if (!loplugin::DeclCheck(decl->getTemplatedDecl())
+ .ClassOrStruct("function")
+ .StdNamespace())
+ {
+ return false;
+ }
+ if (t2->getNumArgs() != 1)
+ {
+ if (isDebugMode())
+ {
+ report(DiagnosticsEngine::Fatal,
+ "TODO: unexpected std::function with %0 template arguments",
+ expr->getExprLoc())
+ << t2->getNumArgs() << expr->getSourceRange();
+ }
+ return false;
+ }
+ if (t2->getArg(0).getKind() != TemplateArgument::Type)
+ {
+ if (isDebugMode())
+ {
+ report(DiagnosticsEngine::Fatal,
+ "TODO: unexpected std::function with non-type template argument",
+ expr->getExprLoc())
+ << expr->getSourceRange();
+ }
+ return false;
+ }
+ target = t2->getArg(0).getAsType();
+ }
+ else
+ {
+ return false;
+ }
auto cxxConstruct = dyn_cast<CXXConstructExpr>(compat::IgnoreImplicit(expr->getSubExpr()));
if (!cxxConstruct)
return false;
- return isa<LambdaExpr>(cxxConstruct->getArg(0));
+ auto const lambda = dyn_cast<LambdaExpr>(cxxConstruct->getArg(0));
+ if (!lambda)
+ return false;
+ if (deduced)
+ // std::function([...](Args)->Ret{...}) should always be redundant:
+ return true;
+ auto const decl = lambda->getCallOperator();
+ std::vector<QualType> args;
+ for (unsigned i = 0; i != decl->getNumParams(); ++i)
+ {
+ args.push_back(decl->getParamDecl(i)->getType());
+ }
+ auto const source
+ = compiler.getASTContext().getFunctionType(decl->getReturnType(), args, {});
+ // std::function<Ret1(Args1)>([...](Args2)->Ret2{...}) is redundant if target Ret1(Args1)
+ // matches source Ret2(Args2):
+ return target.getCanonicalType() == source.getCanonicalType();
}
bool VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const* expr)
diff --git a/compilerplugins/clang/test/redundantfcast.cxx b/compilerplugins/clang/test/redundantfcast.cxx
index 9b377c97d395..985aa8c02994 100644
--- a/compilerplugins/clang/test/redundantfcast.cxx
+++ b/compilerplugins/clang/test/redundantfcast.cxx
@@ -95,5 +95,14 @@ void f2()
f1(std::function([&]() {}));
}
};
+namespace test6
+{
+void f1(std::function<void(int)>);
+void f1(std::function<void(long)>);
+void f2()
+{
+ f1(std::function<void(long)>([&](int) {})); // should not warn here
+}
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
More information about the Libreoffice-commits
mailing list