[Libreoffice-commits] core.git: compilerplugins/clang
Noel Grandin
noel.grandin at collabora.co.uk
Tue Nov 22 06:36:46 UTC 2016
compilerplugins/clang/unusedmethods.cxx | 34 +++++++++++++++++++++++---------
compilerplugins/clang/unusedmethods.py | 7 ++++++
2 files changed, 32 insertions(+), 9 deletions(-)
New commits:
commit 6f9cdf0814c8364ee6000075f8c04bc7fa2e51f8
Author: Noel Grandin <noel.grandin at collabora.co.uk>
Date: Mon Nov 21 15:36:08 2016 +0200
can-be-private analysis needs to ignore virtual methods
Change-Id: I1e2f28ed550ff9751912f70e3eec511ddc5b75cf
diff --git a/compilerplugins/clang/unusedmethods.cxx b/compilerplugins/clang/unusedmethods.cxx
index 98f19ac..6a2d8d2 100644
--- a/compilerplugins/clang/unusedmethods.cxx
+++ b/compilerplugins/clang/unusedmethods.cxx
@@ -54,6 +54,7 @@ struct MyFuncInfo
std::string returnType;
std::string nameAndParams;
std::string sourceLocation;
+ std::string virtualness;
};
bool operator < (const MyFuncInfo &lhs, const MyFuncInfo &rhs)
@@ -88,7 +89,8 @@ public:
std::string output;
for (const MyFuncInfo & s : definitionSet)
- output += "definition:\t" + s.access + "\t" + s.returnType + "\t" + s.nameAndParams + "\t" + s.sourceLocation + "\n";
+ output += "definition:\t" + s.access + "\t" + s.returnType + "\t" + s.nameAndParams
+ + "\t" + s.sourceLocation + "\t" + s.virtualness + "\n";
// for the "unused method" analysis
for (const MyFuncInfo & s : callSet)
output += "call:\t" + s.returnType + "\t" + s.nameAndParams + "\n";
@@ -144,10 +146,12 @@ MyFuncInfo UnusedMethods::niceName(const FunctionDecl* functionDecl)
aInfo.returnType = "";
}
- if (isa<CXXMethodDecl>(functionDecl)) {
- const CXXRecordDecl* recordDecl = dyn_cast<CXXMethodDecl>(functionDecl)->getParent();
+ if (const CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(functionDecl)) {
+ const CXXRecordDecl* recordDecl = methodDecl->getParent();
aInfo.nameAndParams += recordDecl->getQualifiedNameAsString();
aInfo.nameAndParams += "::";
+ if (methodDecl->isVirtual())
+ aInfo.virtualness = "virtual";
}
aInfo.nameAndParams += functionDecl->getNameAsString() + "(";
bool bFirst = true;
@@ -230,12 +234,12 @@ gotfunc:
// Now do the checks necessary for the "can be private" analysis
CXXMethodDecl* calleeMethodDecl = dyn_cast<CXXMethodDecl>(calleeFunctionDecl);
- if (calleeMethodDecl && calleeMethodDecl->getAccess() == AS_public)
+ if (calleeMethodDecl && calleeMethodDecl->getAccess() != AS_private)
{
- const FunctionDecl* parentFunction = parentFunctionDecl(expr);
- if (parentFunction && parentFunction != calleeFunctionDecl) {
- if (!ignoreLocation(parentFunction)) {
- calledFromOutsideSet.insert(niceName(parentFunction));
+ const FunctionDecl* parentFunctionOfCallSite = parentFunctionDecl(expr);
+ if (parentFunctionOfCallSite != calleeFunctionDecl) {
+ if (!parentFunctionOfCallSite || !ignoreLocation(parentFunctionOfCallSite)) {
+ calledFromOutsideSet.insert(niceName(calleeFunctionDecl));
}
}
}
@@ -316,7 +320,6 @@ bool UnusedMethods::VisitFunctionDecl( const FunctionDecl* functionDecl )
return true;
}
-// this catches places that take the address of a method
bool UnusedMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr )
{
const FunctionDecl* functionDecl = dyn_cast<FunctionDecl>(declRefExpr->getDecl());
@@ -325,6 +328,19 @@ bool UnusedMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr )
}
logCallToRootMethods(functionDecl->getCanonicalDecl(), callSet);
logCallToRootMethods(functionDecl->getCanonicalDecl(), usedReturnSet);
+
+ // Now do the checks necessary for the "can be private" analysis
+ const CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(functionDecl);
+ if (methodDecl && methodDecl->getAccess() != AS_private)
+ {
+ const FunctionDecl* parentFunctionOfCallSite = parentFunctionDecl(declRefExpr);
+ if (parentFunctionOfCallSite != functionDecl) {
+ if (!parentFunctionOfCallSite || !ignoreLocation(parentFunctionOfCallSite)) {
+ calledFromOutsideSet.insert(niceName(functionDecl));
+ }
+ }
+ }
+
return true;
}
diff --git a/compilerplugins/clang/unusedmethods.py b/compilerplugins/clang/unusedmethods.py
index bf05c2f..53cc934 100755
--- a/compilerplugins/clang/unusedmethods.py
+++ b/compilerplugins/clang/unusedmethods.py
@@ -17,6 +17,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)
calledFromOutsideSet = set() # set of tuple(return_type, name_and_params)
+virtualSet = set() # set of tuple(return_type, name_and_params)
# for the "unused return types" analysis
usedReturnSet = set() # set of tuple(return_type, name_and_params)
@@ -114,11 +115,15 @@ with io.open("loplugin.unusedmethods.log", "rb", buffering=1024*1024) as txt:
returnType = tokens[2]
nameAndParams = tokens[3]
sourceLocation = tokens[4]
+ virtual = ""
+ if len(tokens)>=6: virtual = tokens[5]
funcInfo = (normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))
definitionSet.add(funcInfo)
if access == "public":
publicDefinitionSet.add(funcInfo)
definitionToSourceLocationMap[funcInfo] = sourceLocation
+ if virtual == "virtual":
+ virtualSet.add(funcInfo)
elif tokens[0] == "call:":
returnType = tokens[1]
nameAndParams = tokens[2]
@@ -333,6 +338,8 @@ for d in publicDefinitionSet:
method = d[0] + " " + d[1]
if d in calledFromOutsideSet:
continue
+ if d in virtualSet:
+ continue
# TODO ignore constructors for now, my called-from-outside analysis doesn't work here
if d[0] == "":
continue
More information about the Libreoffice-commits
mailing list