diff options
author | Noel Grandin <noel@peralex.com> | 2016-01-11 08:41:55 +0200 |
---|---|---|
committer | Noel Grandin <noel@peralex.com> | 2016-01-11 10:49:24 +0200 |
commit | 86bb6fdf9cf14342bcf8ee72aa3233dd9dee1b3a (patch) | |
tree | c1d70077b3c483835b1d271fba2cc88b1a112328 /compilerplugins | |
parent | f7c23897a354d9856ecaa5f7252520a350229bfa (diff) |
update unusedmethods loplugin to update unused return values
Change-Id: I825d022d09282bc9b6cffd9178e40e4090d335da
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/plugin.cxx | 6 | ||||
-rw-r--r-- | compilerplugins/clang/unusedmethods.cxx | 38 | ||||
-rwxr-xr-x | compilerplugins/clang/unusedmethods.py | 47 |
3 files changed, 79 insertions, 12 deletions
diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx index 2f45e4fbf7cc..9beca1146fd4 100644 --- a/compilerplugins/clang/plugin.cxx +++ b/compilerplugins/clang/plugin.cxx @@ -61,8 +61,8 @@ const Stmt* Plugin::parentStmt( const Stmt* stmt ) { if( parents.empty()) buildParents( compiler ); -if(parents.count(stmt)!=1)stmt->dump(); - assert( parents.count( stmt ) == 1 ); + //if(parents.count(stmt)!=1)stmt->dump(); + //assert( parents.count( stmt ) == 1 ); return parents[ stmt ]; } @@ -70,7 +70,7 @@ Stmt* Plugin::parentStmt( Stmt* stmt ) { if( parents.empty()) buildParents( compiler ); - assert( parents.count( stmt ) == 1 ); + //assert( parents.count( stmt ) == 1 ); return const_cast< Stmt* >( parents[ stmt ] ); } diff --git a/compilerplugins/clang/unusedmethods.cxx b/compilerplugins/clang/unusedmethods.cxx index 8df33265a2ab..c74bfed1f191 100644 --- a/compilerplugins/clang/unusedmethods.cxx +++ b/compilerplugins/clang/unusedmethods.cxx @@ -59,6 +59,7 @@ struct MyFuncInfo // try to limit the voluminous output a little static std::set<MyFuncInfo> callSet; +static std::set<MyFuncInfo> usedReturnSet; static std::set<MyFuncInfo> definitionSet; @@ -82,6 +83,8 @@ public: std::string output; for (const MyFuncInfo & s : callSet) output += "call:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; + for (const MyFuncInfo & s : usedReturnSet) + output += "usedReturn:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; for (const MyFuncInfo & s : definitionSet) { //treat all UNO interfaces as having been called, since they are part of our external ABI @@ -100,7 +103,7 @@ public: bool VisitFunctionDecl( const FunctionDecl* decl ); bool VisitDeclRefExpr( const DeclRefExpr* ); private: - void logCallToRootMethods(const FunctionDecl* functionDecl); + void logCallToRootMethods(const FunctionDecl* functionDecl, std::set<MyFuncInfo>& funcSet); MyFuncInfo niceName(const FunctionDecl* functionDecl); std::string fullyQualifiedName(const FunctionDecl* functionDecl); }; @@ -172,7 +175,7 @@ std::string UnusedMethods::fullyQualifiedName(const FunctionDecl* functionDecl) return ret; } -void UnusedMethods::logCallToRootMethods(const FunctionDecl* functionDecl) +void UnusedMethods::logCallToRootMethods(const FunctionDecl* functionDecl, std::set<MyFuncInfo>& funcSet) { functionDecl = functionDecl->getCanonicalDecl(); bool bCalledSuperMethod = false; @@ -183,7 +186,7 @@ void UnusedMethods::logCallToRootMethods(const FunctionDecl* functionDecl) for(CXXMethodDecl::method_iterator it = methodDecl->begin_overridden_methods(); it != methodDecl->end_overridden_methods(); ++it) { - logCallToRootMethods(*it); + logCallToRootMethods(*it, funcSet); bCalledSuperMethod = true; } } @@ -191,7 +194,7 @@ void UnusedMethods::logCallToRootMethods(const FunctionDecl* functionDecl) { while (functionDecl->getTemplateInstantiationPattern()) functionDecl = functionDecl->getTemplateInstantiationPattern(); - callSet.insert(niceName(functionDecl)); + funcSet.insert(niceName(functionDecl)); } } @@ -227,7 +230,29 @@ gotfunc: if (traversedFunctionSet.insert(fullyQualifiedName(calleeFunctionDecl)).second) TraverseFunctionDecl(calleeFunctionDecl); - logCallToRootMethods(calleeFunctionDecl); + logCallToRootMethods(calleeFunctionDecl, callSet); + + if (calleeFunctionDecl->getReturnType()->isVoidType()) { + return true; + } + const Stmt* parent = parentStmt(expr); + if (!parent) { + return true; + } + if (isa<Expr>(parent) || isa<ReturnStmt>(parent) || isa<DeclStmt>(parent) + || isa<IfStmt>(parent) || isa<SwitchStmt>(parent) || isa<ForStmt>(parent) + || isa<WhileStmt>(parent) || isa<DoStmt>(parent) + || isa<CXXForRangeStmt>(parent)) + { + logCallToRootMethods(calleeFunctionDecl, usedReturnSet); + return true; + } + if (isa<CompoundStmt>(parent) || isa<DefaultStmt>(parent) || isa<CaseStmt>(parent) + || isa<LabelStmt>(parent)) + { + return true; + } + parent->dump(); return true; } @@ -267,7 +292,8 @@ bool UnusedMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) if (!isa<FunctionDecl>(functionDecl)) { return true; } - logCallToRootMethods(dyn_cast<FunctionDecl>(functionDecl)->getCanonicalDecl()); + logCallToRootMethods(dyn_cast<FunctionDecl>(functionDecl)->getCanonicalDecl(), callSet); + logCallToRootMethods(dyn_cast<FunctionDecl>(functionDecl)->getCanonicalDecl(), usedReturnSet); return true; } diff --git a/compilerplugins/clang/unusedmethods.py b/compilerplugins/clang/unusedmethods.py index 0c2cdff7f640..aca8591fe0a8 100755 --- a/compilerplugins/clang/unusedmethods.py +++ b/compilerplugins/clang/unusedmethods.py @@ -7,6 +7,7 @@ import io definitionSet = set() definitionToSourceLocationMap = dict() callSet = set() +returnSet = set() sourceLocationSet = set() # things we need to exclude for reasons like : # - it's a weird template thingy that confuses the plugin @@ -125,6 +126,9 @@ with io.open(sys.argv[1], "rb", buffering=1024*1024) as txt: elif line.startswith("call:\t"): idx1 = line.find("\t",6) callSet.add((normalizeTypeParams(line[6:idx1]), normalizeTypeParams(line[idx1+1:].strip()))) + elif line.startswith("usedReturn:\t"): + idx1 = line.find("\t",12) + returnSet.add((normalizeTypeParams(line[12:idx1]), normalizeTypeParams(line[idx1+1:].strip()))) # Invert the definitionToSourceLocationMap # If we see more than one method at the same sourceLocation, it's being autogenerated as part of a template @@ -138,6 +142,10 @@ for k, definitions in sourceLocationToDefinitionMap.iteritems(): for d in definitions: definitionSet.remove(d) +# ------------------------------------------- +# Do the "unused methods" part +# ------------------------------------------- + tmp1set = set() for d in definitionSet: clazz = d[0] + " " + d[1] @@ -228,11 +236,44 @@ def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): tmp1list = sorted(tmp1set, key=lambda v: natural_sort_key(v[1])) # print out the results -for t in tmp1list: - print t[1] - print " ", t[0] +#for t in tmp1list: +# print t[1] +# print " ", t[0] + + +# ------------------------------------------- +# Do the "unused return types" part +# ------------------------------------------- + +tmp2set = set() +for d in definitionSet: + clazz = d[0] + " " + d[1] + if clazz in exclusionSet: + continue + if d in returnSet: + continue + if d[0] == "void": + continue + # ignore UNO constructor method entrypoints + if "_get_implementation" in d[1]: + continue + # the plugin can't see calls to these + if "operator new" in d[1]: + continue + # unused return type is not a problem here + if "operator=(" in d[1]: + continue + # ignore external code + if definitionToSourceLocationMap[d].startswith("external/"): + continue + tmp2set.add((clazz, definitionToSourceLocationMap[d])) +# sort results by name and line number +tmp2list = sorted(tmp2set, key=lambda v: natural_sort_key(v[1])) +for t in tmp2list: + print t[1] + print " ", t[0] # add an empty line at the end to make it easier for the unusedmethodsremove plugin to mmap() the output file print |