Kaydet (Commit) 6f9cdf08 authored tarafından Noel Grandin's avatar Noel Grandin

can-be-private analysis needs to ignore virtual methods

Change-Id: I1e2f28ed550ff9751912f70e3eec511ddc5b75cf
üst bf8f90bf
...@@ -54,6 +54,7 @@ struct MyFuncInfo ...@@ -54,6 +54,7 @@ struct MyFuncInfo
std::string returnType; std::string returnType;
std::string nameAndParams; std::string nameAndParams;
std::string sourceLocation; std::string sourceLocation;
std::string virtualness;
}; };
bool operator < (const MyFuncInfo &lhs, const MyFuncInfo &rhs) bool operator < (const MyFuncInfo &lhs, const MyFuncInfo &rhs)
...@@ -88,7 +89,8 @@ public: ...@@ -88,7 +89,8 @@ public:
std::string output; std::string output;
for (const MyFuncInfo & s : definitionSet) 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 the "unused method" analysis
for (const MyFuncInfo & s : callSet) for (const MyFuncInfo & s : callSet)
output += "call:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; output += "call:\t" + s.returnType + "\t" + s.nameAndParams + "\n";
...@@ -144,10 +146,12 @@ MyFuncInfo UnusedMethods::niceName(const FunctionDecl* functionDecl) ...@@ -144,10 +146,12 @@ MyFuncInfo UnusedMethods::niceName(const FunctionDecl* functionDecl)
aInfo.returnType = ""; aInfo.returnType = "";
} }
if (isa<CXXMethodDecl>(functionDecl)) { if (const CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(functionDecl)) {
const CXXRecordDecl* recordDecl = dyn_cast<CXXMethodDecl>(functionDecl)->getParent(); const CXXRecordDecl* recordDecl = methodDecl->getParent();
aInfo.nameAndParams += recordDecl->getQualifiedNameAsString(); aInfo.nameAndParams += recordDecl->getQualifiedNameAsString();
aInfo.nameAndParams += "::"; aInfo.nameAndParams += "::";
if (methodDecl->isVirtual())
aInfo.virtualness = "virtual";
} }
aInfo.nameAndParams += functionDecl->getNameAsString() + "("; aInfo.nameAndParams += functionDecl->getNameAsString() + "(";
bool bFirst = true; bool bFirst = true;
...@@ -230,12 +234,12 @@ gotfunc: ...@@ -230,12 +234,12 @@ gotfunc:
// Now do the checks necessary for the "can be private" analysis // Now do the checks necessary for the "can be private" analysis
CXXMethodDecl* calleeMethodDecl = dyn_cast<CXXMethodDecl>(calleeFunctionDecl); CXXMethodDecl* calleeMethodDecl = dyn_cast<CXXMethodDecl>(calleeFunctionDecl);
if (calleeMethodDecl && calleeMethodDecl->getAccess() == AS_public) if (calleeMethodDecl && calleeMethodDecl->getAccess() != AS_private)
{ {
const FunctionDecl* parentFunction = parentFunctionDecl(expr); const FunctionDecl* parentFunctionOfCallSite = parentFunctionDecl(expr);
if (parentFunction && parentFunction != calleeFunctionDecl) { if (parentFunctionOfCallSite != calleeFunctionDecl) {
if (!ignoreLocation(parentFunction)) { if (!parentFunctionOfCallSite || !ignoreLocation(parentFunctionOfCallSite)) {
calledFromOutsideSet.insert(niceName(parentFunction)); calledFromOutsideSet.insert(niceName(calleeFunctionDecl));
} }
} }
} }
...@@ -316,7 +320,6 @@ bool UnusedMethods::VisitFunctionDecl( const FunctionDecl* functionDecl ) ...@@ -316,7 +320,6 @@ bool UnusedMethods::VisitFunctionDecl( const FunctionDecl* functionDecl )
return true; return true;
} }
// this catches places that take the address of a method
bool UnusedMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) bool UnusedMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr )
{ {
const FunctionDecl* functionDecl = dyn_cast<FunctionDecl>(declRefExpr->getDecl()); const FunctionDecl* functionDecl = dyn_cast<FunctionDecl>(declRefExpr->getDecl());
...@@ -325,6 +328,19 @@ bool UnusedMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) ...@@ -325,6 +328,19 @@ bool UnusedMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr )
} }
logCallToRootMethods(functionDecl->getCanonicalDecl(), callSet); logCallToRootMethods(functionDecl->getCanonicalDecl(), callSet);
logCallToRootMethods(functionDecl->getCanonicalDecl(), usedReturnSet); 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; return true;
} }
......
...@@ -17,6 +17,7 @@ callSet = set() # set of tuple(return_type, name_and_params) ...@@ -17,6 +17,7 @@ callSet = set() # set of tuple(return_type, name_and_params)
# for the "method can be private" analysis # for the "method can be private" analysis
publicDefinitionSet = set() # set of tuple(return_type, name_and_params) publicDefinitionSet = set() # set of tuple(return_type, name_and_params)
calledFromOutsideSet = 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 # for the "unused return types" analysis
usedReturnSet = set() # set of tuple(return_type, name_and_params) 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: ...@@ -114,11 +115,15 @@ with io.open("loplugin.unusedmethods.log", "rb", buffering=1024*1024) as txt:
returnType = tokens[2] returnType = tokens[2]
nameAndParams = tokens[3] nameAndParams = tokens[3]
sourceLocation = tokens[4] sourceLocation = tokens[4]
virtual = ""
if len(tokens)>=6: virtual = tokens[5]
funcInfo = (normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams)) funcInfo = (normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))
definitionSet.add(funcInfo) definitionSet.add(funcInfo)
if access == "public": if access == "public":
publicDefinitionSet.add(funcInfo) publicDefinitionSet.add(funcInfo)
definitionToSourceLocationMap[funcInfo] = sourceLocation definitionToSourceLocationMap[funcInfo] = sourceLocation
if virtual == "virtual":
virtualSet.add(funcInfo)
elif tokens[0] == "call:": elif tokens[0] == "call:":
returnType = tokens[1] returnType = tokens[1]
nameAndParams = tokens[2] nameAndParams = tokens[2]
...@@ -333,6 +338,8 @@ for d in publicDefinitionSet: ...@@ -333,6 +338,8 @@ for d in publicDefinitionSet:
method = d[0] + " " + d[1] method = d[0] + " " + d[1]
if d in calledFromOutsideSet: if d in calledFromOutsideSet:
continue continue
if d in virtualSet:
continue
# TODO ignore constructors for now, my called-from-outside analysis doesn't work here # TODO ignore constructors for now, my called-from-outside analysis doesn't work here
if d[0] == "": if d[0] == "":
continue continue
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment