summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2019-11-29 17:42:03 +0100
committerStephan Bergmann <sbergman@redhat.com>2019-11-29 22:02:52 +0100
commit4f8a744c4fcf2c69462af19bd807fee32413158d (patch)
treee8b39724c7b8f760a9c72e6a32db2f02346c64de /compilerplugins
parent40f67c9002d4cc245cd2c24981fd3af7910485a1 (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.cxx13
-rw-r--r--compilerplugins/clang/unnecessaryparen.cxx20
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);