From 75bbbfc6bd94246c75c6d0f0e0da5d55b41009b7 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Mon, 4 Nov 2019 15:58:29 +0100 Subject: loplugin:redundantcast: Don't warn about cast from nullptr_t to function ptr See comments at "Only initialize function pointer once" for a case where such a false warning caused trouble (in a lambda with deduced return type and multiple return statements). Change-Id: I64b0b8c45bd3d2a6075e336c361ec778fa0da481 Reviewed-on: https://gerrit.libreoffice.org/82034 Tested-by: Jenkins Reviewed-by: Stephan Bergmann --- compilerplugins/clang/redundantcast.cxx | 17 ++++++++++++++--- compilerplugins/clang/test/redundantcast.cxx | 12 ++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'compilerplugins') diff --git a/compilerplugins/clang/redundantcast.cxx b/compilerplugins/clang/redundantcast.cxx index d4e76846cbfa..1f7765b8978d 100644 --- a/compilerplugins/clang/redundantcast.cxx +++ b/compilerplugins/clang/redundantcast.cxx @@ -78,6 +78,17 @@ AlgebraicType algebraicType(clang::Type const & type) { } } +// Do not look through FunctionToPointerDecay, but through e.g. NullToPointer: +Expr const * stopAtFunctionPointerDecay(ExplicitCastExpr const * expr) { + auto const e1 = expr->getSubExpr(); + if (auto const e2 = dyn_cast(e1)) { + if (e2->getCastKind() != CK_FunctionToPointerDecay) { + return e2->getSubExpr(); + } + } + return e1; +} + class RedundantCast: public loplugin::FilteringRewritePlugin { @@ -394,7 +405,7 @@ bool RedundantCast::VisitCXXStaticCastExpr(CXXStaticCastExpr const * expr) { } auto const t2 = expr->getTypeAsWritten(); bool const fnptr = t2->isFunctionPointerType() || t2->isMemberFunctionPointerType(); - auto const sub = fnptr ? expr->getSubExpr() : compat::getSubExprAsWritten(expr); + auto const sub = fnptr ? stopAtFunctionPointerDecay(expr) : compat::getSubExprAsWritten(expr); auto const t1 = sub->getType(); auto const nonClassObjectType = t2->isObjectType() && !(t2->isRecordType() || t2->isArrayType()); @@ -722,8 +733,8 @@ bool RedundantCast::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const * exp // temporary): 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() + auto const sub = fnptr ? stopAtFunctionPointerDecay(expr) : compat::getSubExprAsWritten(expr); + if ((sub->getValueKind() != VK_RValue && !fnptr) || expr->getType()->isRecordType() || isa(sub) || isa(sub)) { return true; diff --git a/compilerplugins/clang/test/redundantcast.cxx b/compilerplugins/clang/test/redundantcast.cxx index a876fae6e4b3..2ffd8f93c96f 100644 --- a/compilerplugins/clang/test/redundantcast.cxx +++ b/compilerplugins/clang/test/redundantcast.cxx @@ -406,6 +406,18 @@ void testNew() { (void)p2; } +using F = void (*)(); +auto testNullFunctionPointer(int i, F p) { + switch (i) { + case 0: + return static_cast(nullptr); + case 1: + return F(nullptr); + default: + return p; + } +} + int main() { testConstCast(); testStaticCast(); -- cgit