summaryrefslogtreecommitdiff
path: root/compilerplugins/clang
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2019-11-04 15:58:29 +0100
committerStephan Bergmann <sbergman@redhat.com>2019-11-04 17:20:28 +0100
commit75bbbfc6bd94246c75c6d0f0e0da5d55b41009b7 (patch)
treee38aeebf098a4eee9334bec48160d664e7309fca /compilerplugins/clang
parent074cab391c20be872a4b5d14a342eda5c541b6fd (diff)
loplugin:redundantcast: Don't warn about cast from nullptr_t to function ptr
See comments at <https://gerrit.libreoffice.org/#/c/81958/> "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 <sbergman@redhat.com>
Diffstat (limited to 'compilerplugins/clang')
-rw-r--r--compilerplugins/clang/redundantcast.cxx17
-rw-r--r--compilerplugins/clang/test/redundantcast.cxx12
2 files changed, 26 insertions, 3 deletions
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<ImplicitCastExpr>(e1)) {
+ if (e2->getCastKind() != CK_FunctionToPointerDecay) {
+ return e2->getSubExpr();
+ }
+ }
+ return e1;
+}
+
class RedundantCast:
public loplugin::FilteringRewritePlugin<RedundantCast>
{
@@ -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<InitListExpr>(sub) || isa<CXXStdInitializerListExpr>(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<F>(nullptr);
+ case 1:
+ return F(nullptr);
+ default:
+ return p;
+ }
+}
+
int main() {
testConstCast();
testStaticCast();