summaryrefslogtreecommitdiffstats
path: root/compilerplugins/clang/redundantcast.cxx
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2017-12-05 11:37:59 +0100
committerStephan Bergmann <sbergman@redhat.com>2017-12-05 18:11:15 +0100
commit306ddfb1b87d94a343e8e2b6b9270ca682f92ac3 (patch)
treeef46ec8bc63d3db71ebe17a571ec8f9787d6c814 /compilerplugins/clang/redundantcast.cxx
parentFix typo (diff)
downloadcore-306ddfb1b87d94a343e8e2b6b9270ca682f92ac3.tar.gz
core-306ddfb1b87d94a343e8e2b6b9270ca682f92ac3.zip
Replace deprecated std::mem_fun et al in reportdesign
(as std::mem_fun is gone by default at least from recent libc++ in C++17 mode) Change-Id: Ib66134bd4072dfe0ce3bc36aa684cee710921235 Reviewed-on: https://gerrit.libreoffice.org/45868 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'compilerplugins/clang/redundantcast.cxx')
-rw-r--r--compilerplugins/clang/redundantcast.cxx63
1 files changed, 59 insertions, 4 deletions
diff --git a/compilerplugins/clang/redundantcast.cxx b/compilerplugins/clang/redundantcast.cxx
index bdf23d9094cf..2f905d355720 100644
--- a/compilerplugins/clang/redundantcast.cxx
+++ b/compilerplugins/clang/redundantcast.cxx
@@ -161,6 +161,7 @@ public:
private:
bool visitBinOp(BinaryOperator const * expr);
bool isOkToRemoveArithmeticCast(QualType t1, QualType t2, const Expr* subExpr);
+ bool isOverloadedFunction(FunctionDecl const * decl);
};
bool RedundantCast::VisitImplicitCastExpr(const ImplicitCastExpr * expr) {
@@ -362,9 +363,10 @@ bool RedundantCast::VisitCXXStaticCastExpr(CXXStaticCastExpr const * expr) {
if (ignoreLocation(expr)) {
return true;
}
- auto const sub = compat::getSubExprAsWritten(expr);
- auto const t1 = sub->getType();
auto const t2 = expr->getTypeAsWritten();
+ bool const fnptr = t2->isFunctionPointerType() || t2->isMemberFunctionPointerType();
+ auto const sub = fnptr ? expr->getSubExpr() : compat::getSubExprAsWritten(expr);
+ auto const t1 = sub->getType();
auto const nonClassObjectType = t2->isObjectType()
&& !(t2->isRecordType() || t2->isArrayType());
if (nonClassObjectType && t2.hasLocalQualifiers()) {
@@ -445,6 +447,23 @@ bool RedundantCast::VisitCXXStaticCastExpr(CXXStaticCastExpr const * expr) {
{
return true;
}
+ // Don't warn if a static_cast on a pointer to function or member function is used to
+ // disambiguate an overloaded function:
+ if (fnptr) {
+ auto e = sub->IgnoreParenImpCasts();
+ if (auto const e1 = dyn_cast<UnaryOperator>(e)) {
+ if (e1->getOpcode() == UO_AddrOf) {
+ e = e1->getSubExpr()->IgnoreParenImpCasts();
+ }
+ }
+ if (auto const e1 = dyn_cast<DeclRefExpr>(e)) {
+ if (auto const fdecl = dyn_cast<FunctionDecl>(e1->getDecl())) {
+ if (isOverloadedFunction(fdecl)) {
+ return true;
+ }
+ }
+ }
+ }
// Suppress warnings from static_cast<bool> in C++ definition of assert in
// <https://sourceware.org/git/?p=glibc.git;a=commit;
// h=b5889d25e9bf944a89fdd7bcabf3b6c6f6bb6f7c> "assert: Support types
@@ -625,7 +644,9 @@ bool RedundantCast::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const * exp
// ), and only to cases where the sub-expression already is a prvalue of
// non-class type (and thus the cast is unlikely to be meant to create a
// temporary):
- auto const sub = compat::getSubExprAsWritten(expr);
+ auto const t1 = expr->getTypeAsWritten();
+ bool const fnptr = t1->isFunctionPointerType() || t1->isMemberFunctionPointerType();
+ auto const sub = fnptr ? expr->getSubExpr() : compat::getSubExprAsWritten(expr);
if (sub->getValueKind() != VK_RValue || expr->getType()->isRecordType()
|| isa<InitListExpr>(sub) || isa<CXXStdInitializerListExpr>(sub))
{
@@ -643,6 +664,24 @@ bool RedundantCast::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const * exp
}
}
+ // Don't warn if a functional cast on a pointer to function or member function is used to
+ // disambiguate an overloaded function:
+ if (fnptr) {
+ auto e = sub->IgnoreParenImpCasts();
+ if (auto const e1 = dyn_cast<UnaryOperator>(e)) {
+ if (e1->getOpcode() == UO_AddrOf) {
+ e = e1->getSubExpr()->IgnoreParenImpCasts();
+ }
+ }
+ if (auto const e1 = dyn_cast<DeclRefExpr>(e)) {
+ if (auto const fdecl = dyn_cast<FunctionDecl>(e1->getDecl())) {
+ if (isOverloadedFunction(fdecl)) {
+ return true;
+ }
+ }
+ }
+ }
+
// See the commit message of d0e7d020fa405ab94f19916ec96fbd4611da0031
// "socket.c -> socket.cxx" for the reason to have
//
@@ -666,7 +705,6 @@ bool RedundantCast::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const * exp
}
}
- auto const t1 = expr->getTypeAsWritten();
auto const t2 = sub->getType();
if (t1.getCanonicalType() != t2.getCanonicalType())
return true;
@@ -766,6 +804,23 @@ bool RedundantCast::visitBinOp(BinaryOperator const * expr) {
return true;
}
+bool RedundantCast::isOverloadedFunction(FunctionDecl const * decl) {
+ auto const ctx = decl->getDeclContext();
+ if (!compat::isLookupContext(*ctx)) {
+ return false;
+ }
+ auto const canon = decl->getCanonicalDecl();
+ auto const res = ctx->lookup(decl->getDeclName());
+ for (auto d = res.begin(); d != res.end(); ++d) {
+ if (auto const f = dyn_cast<FunctionDecl>(*d)) {
+ if (f->getCanonicalDecl() != canon) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
loplugin::Plugin::Registration<RedundantCast> X("redundantcast", true);
}