diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2017-12-05 11:37:59 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2017-12-05 18:11:15 +0100 |
commit | 306ddfb1b87d94a343e8e2b6b9270ca682f92ac3 (patch) | |
tree | ef46ec8bc63d3db71ebe17a571ec8f9787d6c814 /compilerplugins | |
parent | 36c9eddf44b302bf1e9a9b88af8f89d3e2012df2 (diff) |
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')
-rw-r--r-- | compilerplugins/clang/redundantcast.cxx | 63 | ||||
-rw-r--r-- | compilerplugins/clang/test/redundantcast.cxx | 34 |
2 files changed, 93 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); } diff --git a/compilerplugins/clang/test/redundantcast.cxx b/compilerplugins/clang/test/redundantcast.cxx index 20578079c2cb..70fcdf3340cb 100644 --- a/compilerplugins/clang/test/redundantcast.cxx +++ b/compilerplugins/clang/test/redundantcast.cxx @@ -340,6 +340,40 @@ void testDynamicCast() { (void) dynamic_cast<S3 *>(s2); } +void overload(int); +void overload(long); +void nonOverload(); + +struct Overload { + int overload(); + long overload() const; + void nonOverload(); +}; + +void testOverloadResolution() { + (void) static_cast<void (*)(long)>(overload); + (void) static_cast<void (*)(long)>((overload)); + (void) static_cast<void (*)(long)>(&overload); + (void) static_cast<void (*)(long)>((&overload)); + (void) static_cast<void (*)(long)>(&((overload))); + (void) static_cast<void (*)()>(nonOverload); // expected-error {{static_cast from 'void (*)()' prvalue to 'void (*)()' prvalue is redundant [loplugin:redundantcast]}} + (void) static_cast<void (*)()>((nonOverload)); // expected-error {{static_cast from 'void (*)()' prvalue to 'void (*)()' prvalue is redundant [loplugin:redundantcast]}} + (void) static_cast<void (*)()>(&nonOverload); // expected-error {{static_cast from 'void (*)()' prvalue to 'void (*)()' prvalue is redundant [loplugin:redundantcast]}} + (void) static_cast<void (*)()>((&nonOverload)); // expected-error {{static_cast from 'void (*)()' prvalue to 'void (*)()' prvalue is redundant [loplugin:redundantcast]}} + (void) static_cast<void (*)()>(&((nonOverload))); // expected-error {{static_cast from 'void (*)()' prvalue to 'void (*)()' prvalue is redundant [loplugin:redundantcast]}} + (void) static_cast<long (Overload::*)() const>(&Overload::overload); + (void) static_cast<void (Overload::*)()>(&Overload::nonOverload); // expected-error {{static_cast from 'void (Overload::*)()' prvalue to 'void (Overload::*)()' prvalue is redundant [loplugin:redundantcast]}} + + using OverloadFn = void (*)(long); + (void) OverloadFn(overload); + using NonOverloadFn = void (*)(); + (void) NonOverloadFn(nonOverload); // expected-error {{redundant functional cast from 'void (*)()' to 'NonOverloadFn' (aka 'void (*)()') [loplugin:redundantcast]}} + using OverloadMemFn = long (Overload::*)() const; + (void) OverloadMemFn(&Overload::overload); + using NonOverloadMemFn = void (Overload::*)(); + (void) NonOverloadMemFn(&Overload::nonOverload); // expected-error {{redundant functional cast from 'void (Overload::*)()' to 'NonOverloadMemFn' (aka 'void (Overload::*)()') [loplugin:redundantcast]}} +}; + int main() { testConstCast(); testStaticCast(); |