From 9d9d024ffba8753db8a93e34d34e22818da002aa Mon Sep 17 00:00:00 2001 From: Noel Grandin Date: Mon, 19 Jun 2017 14:16:05 +0200 Subject: [PATCH] loplugin:unusedfields fix some more false positives in the write-only analysis Change-Id: Ic570416e855b8ec38d54f6f6f1adef4819ea53ee --- compilerplugins/clang/test/unusedfields.cxx | 17 ++++++++++++++++- 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(parent) || isa(parent) || isa(parent) || isa(parent) - || isa(parent) || isa(parent)) + || isa(parent)) { child = parent; auto parentsRange = compiler.getASTContext().getParents(*parent); parent = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get(); } + else if (auto unaryOperator = dyn_cast(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(); + } else if (isa(parent)) { bPotentiallyReadFrom = dyn_cast(parent)->getLHS() == child