summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2017-11-10 11:33:41 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2017-11-10 15:19:04 +0100
commit4cc7ebcca3d5fa33556fbc2666d8c63ae30a3424 (patch)
treed6a300ee99de1c01b3f4cf809de228ad1f0a73b2 /compilerplugins
parent42344398a839eddf1b498c266d8fe8ac0b3bb6b6 (diff)
loplugin:unusedmethods new analysis
look for classes containing protected methods where we can convert them all to private Change-Id: I4a448341943e0a613cde30501c4012da61dba713 Reviewed-on: https://gerrit.libreoffice.org/44588 Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk> Tested-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/unusedmethods.cxx15
-rwxr-xr-xcompilerplugins/clang/unusedmethods.py33
2 files changed, 48 insertions, 0 deletions
diff --git a/compilerplugins/clang/unusedmethods.cxx b/compilerplugins/clang/unusedmethods.cxx
index 3b7b4cb2a5fb..ef681f12c561 100644
--- a/compilerplugins/clang/unusedmethods.cxx
+++ b/compilerplugins/clang/unusedmethods.cxx
@@ -114,11 +114,13 @@ public:
bool VisitFunctionDecl( const FunctionDecl* decl );
bool VisitDeclRefExpr( const DeclRefExpr* );
bool VisitCXXConstructExpr( const CXXConstructExpr* );
+ bool TraverseCXXRecordDecl( CXXRecordDecl* );
private:
void logCallToRootMethods(const FunctionDecl* functionDecl, std::set<MyFuncInfo>& funcSet);
MyFuncInfo niceName(const FunctionDecl* functionDecl);
std::string toString(SourceLocation loc);
void functionTouchedFromExpr( const FunctionDecl* calleeFunctionDecl, const Expr* expr );
+ CXXRecordDecl const * currentCxxRecordDecl = nullptr;
};
MyFuncInfo UnusedMethods::niceName(const FunctionDecl* functionDecl)
@@ -281,6 +283,10 @@ bool UnusedMethods::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr
logCallToRootMethods(constructorDecl, callSet);
+ // Now do the checks necessary for the "can be private" analysis
+ if (constructorDecl->getParent() != currentCxxRecordDecl)
+ calledFromOutsideSet.insert(niceName(constructorDecl));
+
return true;
}
@@ -341,6 +347,15 @@ bool UnusedMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr )
return true;
}
+bool UnusedMethods::TraverseCXXRecordDecl(CXXRecordDecl* cxxRecordDecl)
+{
+ auto copy = currentCxxRecordDecl;
+ currentCxxRecordDecl = cxxRecordDecl;
+ bool ret = RecursiveASTVisitor::TraverseCXXRecordDecl(cxxRecordDecl);
+ currentCxxRecordDecl = copy;
+ return ret;
+}
+
loplugin::Plugin::Registration< UnusedMethods > X("unusedmethods", false);
}
diff --git a/compilerplugins/clang/unusedmethods.py b/compilerplugins/clang/unusedmethods.py
index aaa19abfc8e2..811eca65cae4 100755
--- a/compilerplugins/clang/unusedmethods.py
+++ b/compilerplugins/clang/unusedmethods.py
@@ -16,6 +16,7 @@ callSet = set() # set of tuple(return_type, name_and_params)
# for the "method can be private" analysis
publicDefinitionSet = set() # set of tuple(return_type, name_and_params)
+protectedDefinitionSet = set() # set of tuple(return_type, name_and_params)
calledFromOutsideSet = set() # set of tuple(return_type, name_and_params)
virtualSet = set() # set of tuple(return_type, name_and_params)
@@ -46,6 +47,8 @@ with io.open("loplugin.unusedmethods.log", "rb", buffering=1024*1024) as txt:
definitionSet.add(funcInfo)
if access == "public":
publicDefinitionSet.add(funcInfo)
+ elif access == "protected":
+ protectedDefinitionSet.add(funcInfo)
definitionToSourceLocationMap[funcInfo] = sourceLocation
if virtual == "virtual":
virtualSet.add(funcInfo)
@@ -275,3 +278,33 @@ with open("loplugin.unusedmethods.report-can-be-private", "wt") as f:
f.write(t[1] + "\n")
f.write(" " + t[0] + "\n")
+
+
+# --------------------------------------------------------------------------------------------
+# "all protected methods in class can be made private" analysis
+# --------------------------------------------------------------------------------------------
+
+potentialClasses = set()
+excludedClasses = set()
+potentialClassesSourceLocationMap = dict()
+matchClassName = re.compile(r"(\w+)::")
+for d in protectedDefinitionSet:
+ m = matchClassName.match(d[1])
+ if not m: continue
+ clazz = m.group(1)
+ if d in calledFromOutsideSet:
+ excludedClasses.add(clazz)
+ else:
+ potentialClasses.add(clazz)
+ potentialClassesSourceLocationMap[clazz] = definitionToSourceLocationMap[d]
+
+tmp4set = set()
+for d in (potentialClasses - excludedClasses):
+ tmp4set.add((d, potentialClassesSourceLocationMap[d]))
+
+# print output, sorted by name and line number
+with open("loplugin.unusedmethods.report-all-protected-can-be-private", "wt") as f:
+ for t in sort_set_by_natural_key(tmp4set):
+ f.write(t[1] + "\n")
+ f.write(" " + t[0] + "\n")
+