diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2017-06-19 14:16:05 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2017-06-20 10:01:48 +0200 |
commit | 9d9d024ffba8753db8a93e34d34e22818da002aa (patch) | |
tree | d463f8994286a98a238435270acbe50891194c0b | |
parent | 05f67637fc4f71750dda46fccf0bed5b3fd99233 (diff) |
loplugin:unusedfields fix some more false positives
in the write-only analysis
Change-Id: Ic570416e855b8ec38d54f6f6f1adef4819ea53ee
-rw-r--r-- | compilerplugins/clang/test/unusedfields.cxx | 17 | ||||
-rw-r--r-- | compilerplugins/clang/unusedfields.cxx | 18 |
2 files changed, 33 insertions, 2 deletions
diff --git a/compilerplugins/clang/test/unusedfields.cxx b/compilerplugins/clang/test/unusedfields.cxx index f549a9a37673..d24e6551c660 100644 --- a/compilerplugins/clang/test/unusedfields.cxx +++ b/compilerplugins/clang/test/unusedfields.cxx @@ -17,12 +17,27 @@ struct Foo struct Bar // expected-error@-1 {{read m_bar2 [loplugin:unusedfields]}} +// expected-error@-2 {{read m_bar3 [loplugin:unusedfields]}} +// expected-error@-3 {{read m_bar4 [loplugin:unusedfields]}} +// expected-error@-4 {{read m_functionpointer [loplugin:unusedfields]}} { int m_bar1; int m_bar2 = 1; + int* m_bar3; + int m_bar4; + void (*m_functionpointer)(int&); + //check that we see reads of fields when referred to via constructor initializer Bar(Foo const & foo) : m_bar1(foo.m_foo1) {} - int bar() { return m_bar2; } + int bar1() { return m_bar2; } + + // check that we see reads of fields when operated on via pointer de-ref + void bar2() { *m_bar3 = 2; } + + // check that we see reads of field when passed to a function pointer + // check that we see read of a field that is a function pointer + void bar3() { m_functionpointer(m_bar4); } + }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/unusedfields.cxx b/compilerplugins/clang/unusedfields.cxx index df64c987f347..824efa5c41f7 100644 --- a/compilerplugins/clang/unusedfields.cxx +++ b/compilerplugins/clang/unusedfields.cxx @@ -261,12 +261,28 @@ bool UnusedFields::VisitMemberExpr( const MemberExpr* memberExpr ) break; } if (isa<CastExpr>(parent) || isa<MemberExpr>(parent) || isa<ParenExpr>(parent) || isa<ParenListExpr>(parent) - || isa<ExprWithCleanups>(parent) || isa<UnaryOperator>(parent)) + || isa<ExprWithCleanups>(parent)) { child = parent; auto parentsRange = compiler.getASTContext().getParents(*parent); parent = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get<Stmt>(); } + else if (auto unaryOperator = dyn_cast<UnaryOperator>(parent)) + { + UnaryOperator::Opcode op = unaryOperator->getOpcode(); + if (op == UO_AddrOf || op == UO_Deref + || op == UO_Plus || op == UO_Minus + || op == UO_Not || op == UO_LNot + || op == UO_PreInc || op == UO_PostInc + || op == UO_PreDec || op == UO_PostDec) + { + bPotentiallyReadFrom = true; + break; + } + child = parent; + auto parentsRange = compiler.getASTContext().getParents(*parent); + parent = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get<Stmt>(); + } else if (isa<CaseStmt>(parent)) { bPotentiallyReadFrom = dyn_cast<CaseStmt>(parent)->getLHS() == child |