summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorNoel Grandin <noel@peralex.com>2015-07-06 10:44:18 +0200
committerNoel Grandin <noelgrandin@gmail.com>2015-07-07 06:52:52 +0000
commit9d7727737b067c5228f129737046f718d5965659 (patch)
tree8a868ade788d8a01f676a09a6ea9815e79fa8904 /compilerplugins
parentfc0079ee90ab466ca5391292ed1be9e937ef6f2a (diff)
loplugin:unusedmethods ucb
Change-Id: Idc0ca78da8ebbdfe8489eee92a1167eb1bd9722f Reviewed-on: https://gerrit.libreoffice.org/16794 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Noel Grandin <noelgrandin@gmail.com>
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/unusedmethods.cxx39
-rwxr-xr-xcompilerplugins/clang/unusedmethods.py16
2 files changed, 38 insertions, 17 deletions
diff --git a/compilerplugins/clang/unusedmethods.cxx b/compilerplugins/clang/unusedmethods.cxx
index e45ee7fb7fd3..bdd606b91d50 100644
--- a/compilerplugins/clang/unusedmethods.cxx
+++ b/compilerplugins/clang/unusedmethods.cxx
@@ -10,6 +10,7 @@
#include <cassert>
#include <string>
#include <iostream>
+#include <fstream>
#include <set>
#include "plugin.hxx"
#include "compat.hxx"
@@ -18,13 +19,12 @@
Dump a list of calls to methods, and a list of method definitions.
Then we will post-process the 2 lists and find the set of unused methods.
-Be warned that it produces around 3G of log file.
+Be warned that it produces around 2.4G of log file.
The process goes something like this:
$ make check
- $ make FORCE_COMPILE_ALL=1 COMPILER_PLUGIN_TOOL='unusedmethods' check > log.txt
- $ grep -P '(call:)|(definition:)' log.txt | sort -u > log2.txt
- $ ./compilerplugins/clang/unusedmethods.py log2.txt > result.txt
+ $ make FORCE_COMPILE_ALL=1 COMPILER_PLUGIN_TOOL='unusedmethods' check
+ $ ./compilerplugins/clang/unusedmethods.py unusedmethods.log > result.txt
and then
$ for dir in *; do make FORCE_COMPILE_ALL=1 UPDATE_FILES=$dir COMPILER_PLUGIN_TOOL='unusedmethodsremove' $dir; done
@@ -44,13 +44,33 @@ TODO track instantiations of template class constructor methods
namespace {
+// try to limit the volumninous output a little
+static std::set<std::string> callSet;
+static std::set<std::string> definitionSet;
+
+
class UnusedMethods:
public RecursiveASTVisitor<UnusedMethods>, public loplugin::Plugin
{
public:
explicit UnusedMethods(InstantiationData const & data): Plugin(data) {}
- virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
+ virtual void run() override
+ {
+ TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
+
+ // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes
+ // writing to the same logfile
+ std::string output;
+ for (const std::string & s : callSet)
+ output += "call:\t" + s + "\t\n";
+ for (const std::string & s : definitionSet)
+ output += "definition:\t" + s + "\t\n";
+ ofstream myfile;
+ myfile.open("/home/noel/libo4/unusedmethods.log", ios::app | ios::out);
+ myfile << output;
+ myfile.close();
+ }
bool VisitCallExpr(CallExpr* );
bool VisitCXXMethodDecl( const CXXMethodDecl* decl );
@@ -80,13 +100,11 @@ static std::string niceName(const CXXMethodDecl* functionDecl)
return s;
}
-// try to limit the volumninous output a little
-static std::set<std::string> alreadySeenCallSet;
-
static void logCallToRootMethods(const CXXMethodDecl* decl)
{
// For virtual/overriding methods, we need to pretend we called the root method(s),
// so that they get marked as used.
+ decl = decl->getCanonicalDecl();
bool bPrinted = false;
for(CXXMethodDecl::method_iterator it = decl->begin_overridden_methods();
it != decl->end_overridden_methods(); ++it)
@@ -97,8 +115,7 @@ static void logCallToRootMethods(const CXXMethodDecl* decl)
if (!bPrinted)
{
std::string s = niceName(decl);
- if (alreadySeenCallSet.insert(s).second)
- cout << "call:\t" << niceName(decl) << endl;
+ callSet.insert(s);
}
}
@@ -173,7 +190,7 @@ bool UnusedMethods::VisitCXXMethodDecl( const CXXMethodDecl* functionDecl )
return true;
}
- cout << "definition:\t" << niceName(functionDecl) << endl;
+ definitionSet.insert(niceName(functionDecl));
return true;
}
diff --git a/compilerplugins/clang/unusedmethods.py b/compilerplugins/clang/unusedmethods.py
index 4b17f95a01d4..3ee4b386c95a 100755
--- a/compilerplugins/clang/unusedmethods.py
+++ b/compilerplugins/clang/unusedmethods.py
@@ -33,15 +33,19 @@ exclusionSet = set([
])
+# The parsing here is designed to also grab output which is mixed into the output from gbuild.
+# I have not yet found a way of suppressing the gbuild output.
with open(sys.argv[1]) as txt:
for line in txt:
- if line.startswith("definition:\t"):
- idx1 = line.find("\t")
- clazzName = line[idx1+1 : len(line)-1]
+ if line.find("definition:\t") != -1:
+ idx1 = line.find("definition:\t")
+ idx2 = line.find("\t", idx1+12)
+ clazzName = line[idx1+12 : idx2]
definitionSet.add(clazzName)
- elif line.startswith("call:\t"):
- idx1 = line.find("\t")
- clazzName = line[idx1+1 : len(line)-1]
+ elif line.find("call:\t") != -1:
+ idx1 = line.find("call:\t")
+ idx2 = line.find("\t", idx1+6)
+ clazzName = line[idx1+6 : idx2]
callSet.add(clazzName)
for clazz in sorted(definitionSet - callSet - exclusionSet):