diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2019-11-29 17:42:03 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2019-11-29 22:02:52 +0100 |
commit | 4f8a744c4fcf2c69462af19bd807fee32413158d (patch) | |
tree | e8b39724c7b8f760a9c72e6a32db2f02346c64de /compilerplugins | |
parent | 40f67c9002d4cc245cd2c24981fd3af7910485a1 (diff) |
Make loplugin:unnecessaryparen treat member expressions consistently
Stumbled across a warning starting to get emitted for some
!(p->x)
when I temporarily changed x from boost::optional (which has a member operator!)
to std::optional (which instead implicitly uses a member conversion operator to
bool). (That is, for the new
static int foo3(Foo2 & foo) {
(void) !(foo.p);
(void) !(foo.b);
(void) !(foo.n);
return (foo.p) ? 1 : 0;
}
test, the first, third, and fourth body lines never warned, while the second one
erroneously warned without this fix.)
Change-Id: I60f6941aaa3a73db0f1373c954e47aa68d703170
Reviewed-on: https://gerrit.libreoffice.org/84079
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/test/unnecessaryparen.cxx | 13 | ||||
-rw-r--r-- | compilerplugins/clang/unnecessaryparen.cxx | 20 |
2 files changed, 33 insertions, 0 deletions
diff --git a/compilerplugins/clang/test/unnecessaryparen.cxx b/compilerplugins/clang/test/unnecessaryparen.cxx index fb36052778b5..88ed3650a09a 100644 --- a/compilerplugins/clang/test/unnecessaryparen.cxx +++ b/compilerplugins/clang/test/unnecessaryparen.cxx @@ -115,14 +115,27 @@ int main() (void)nBits; }; +struct B { operator bool(); }; + +struct N { bool operator !(); }; + class Foo2 { int* p; + B b; + N n; int foo2() { return (p) ? 1 : 0; // expected-error {{unnecessary parentheses around member expr [loplugin:unnecessaryparen]}} } + + static int foo3(Foo2 & foo) { + (void) !(foo.p); + (void) !(foo.b); + (void) !(foo.n); + return (foo.p) ? 1 : 0; + } }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/unnecessaryparen.cxx b/compilerplugins/clang/unnecessaryparen.cxx index f1c17c830207..79085d80027e 100644 --- a/compilerplugins/clang/unnecessaryparen.cxx +++ b/compilerplugins/clang/unnecessaryparen.cxx @@ -107,6 +107,26 @@ public: bool VisitBinaryConditionalOperator(BinaryConditionalOperator const * expr); bool VisitMemberExpr(const MemberExpr *f); bool VisitCXXDeleteExpr(const CXXDeleteExpr *); + + bool VisitImplicitCastExpr(ImplicitCastExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (expr->getCastKind() != CK_UserDefinedConversion) { + return true; + } + // Filter out a MemberExpr (resp. a ParenExpr sub-expr, if any, as would be found by + // VisitMemberExpr) that is part of a CXXMemberCallExpr which in turn is part of an + // ImplicitCastExpr, so that VisitMemberExpr doesn't erroneously pick it up (and note that + // CXXMemberCallExpr's getImplicitObjectArgument() skips past the underlying MemberExpr): + if (auto const e1 = dyn_cast<CXXMemberCallExpr>(expr->getSubExpr())) { + if (auto const e2 = dyn_cast<ParenExpr>(e1->getImplicitObjectArgument())) { + handled_.insert(e2); + } + } + return true; + } + private: void VisitSomeStmt(Stmt const * stmt, const Expr* cond, StringRef stmtName); |