summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/unusedmethods.cxx
diff options
context:
space:
mode:
authorNoel Grandin <noel@peralex.com>2015-09-30 10:29:19 +0200
committerNoel Grandin <noelgrandin@gmail.com>2015-10-01 10:43:24 +0000
commit58aea3f36c14414f95668e229a7350598f6c53a8 (patch)
tree70c115dffd44576313cefd49e4164d293895e4bd /compilerplugins/clang/unusedmethods.cxx
parent3fcbfe10857631212d8b8db9a079bb9692ed78bc (diff)
loplugin:unusedmethods
- improvements to the plugin to find more method calls - improvements to python script to remove more false+ - fix the FORCE_COMPILE_ALL build flag to include code in the $WORKDIR Change-Id: I4d6015dcb9b9d60c26f0bcee8abad807177a7836 Reviewed-on: https://gerrit.libreoffice.org/19064 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Noel Grandin <noelgrandin@gmail.com>
Diffstat (limited to 'compilerplugins/clang/unusedmethods.cxx')
-rw-r--r--compilerplugins/clang/unusedmethods.cxx95
1 files changed, 74 insertions, 21 deletions
diff --git a/compilerplugins/clang/unusedmethods.cxx b/compilerplugins/clang/unusedmethods.cxx
index fa62ce58e0d1..31ff68da6093 100644
--- a/compilerplugins/clang/unusedmethods.cxx
+++ b/compilerplugins/clang/unusedmethods.cxx
@@ -39,9 +39,27 @@ TODO deal with calls to superclass/member constructors from other constructors,
namespace {
+struct MyFuncInfo
+{
+ std::string returnType;
+ std::string nameAndParams;
+ std::string sourceLocation;
+
+ bool operator < (const MyFuncInfo &other) const
+ {
+ if (returnType < other.returnType)
+ return true;
+ else if (returnType == other.returnType)
+ return nameAndParams < other.nameAndParams;
+ else
+ return false;
+ }
+};
+
+
// try to limit the voluminous output a little
-static std::set<std::string> callSet;
-static std::set<std::string> definitionSet;
+static std::set<MyFuncInfo> callSet;
+static std::set<MyFuncInfo> definitionSet;
class UnusedMethods:
@@ -57,10 +75,10 @@ public:
// 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";
+ for (const MyFuncInfo & s : callSet)
+ output += "call:\t" + s.returnType + "\t" + s.nameAndParams + "\n";
+ for (const MyFuncInfo & s : definitionSet)
+ output += "definition:\t" + s.returnType + "\t" + s.nameAndParams + "\t" + s.sourceLocation + "\n";
ofstream myfile;
myfile.open( SRCDIR "/unusedmethods.log", ios::app | ios::out);
myfile << output;
@@ -72,9 +90,12 @@ public:
bool VisitDeclRefExpr( const DeclRefExpr* );
bool VisitCXXConstructExpr( const CXXConstructExpr* );
bool VisitVarDecl( const VarDecl* );
+private:
+ void logCallToRootMethods(const FunctionDecl* functionDecl);
+ MyFuncInfo niceName(const FunctionDecl* functionDecl);
};
-static std::string niceName(const FunctionDecl* functionDecl)
+MyFuncInfo UnusedMethods::niceName(const FunctionDecl* functionDecl)
{
if (functionDecl->getInstantiatedFromMemberFunction())
functionDecl = functionDecl->getInstantiatedFromMemberFunction();
@@ -86,31 +107,36 @@ static std::string niceName(const FunctionDecl* functionDecl)
functionDecl = functionDecl->getTemplateInstantiationPattern();
#endif
- std::string s =
- compat::getReturnType(*functionDecl).getCanonicalType().getAsString()
- + " ";
+ MyFuncInfo aInfo;
+ aInfo.returnType = compat::getReturnType(*functionDecl).getCanonicalType().getAsString();
+
if (isa<CXXMethodDecl>(functionDecl)) {
const CXXRecordDecl* recordDecl = dyn_cast<CXXMethodDecl>(functionDecl)->getParent();
- s += recordDecl->getQualifiedNameAsString();
- s += "::";
+ aInfo.nameAndParams += recordDecl->getQualifiedNameAsString();
+ aInfo.nameAndParams += "::";
}
- s += functionDecl->getNameAsString() + "(";
+ aInfo.nameAndParams += functionDecl->getNameAsString() + "(";
bool bFirst = true;
for (const ParmVarDecl *pParmVarDecl : functionDecl->params()) {
if (bFirst)
bFirst = false;
else
- s += ",";
- s += pParmVarDecl->getType().getCanonicalType().getAsString();
+ aInfo.nameAndParams += ",";
+ aInfo.nameAndParams += pParmVarDecl->getType().getCanonicalType().getAsString();
}
- s += ")";
+ aInfo.nameAndParams += ")";
if (isa<CXXMethodDecl>(functionDecl) && dyn_cast<CXXMethodDecl>(functionDecl)->isConst()) {
- s += " const";
+ aInfo.nameAndParams += " const";
}
- return s;
+
+ SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( functionDecl->getLocation() );
+ StringRef name = compiler.getSourceManager().getFilename(expansionLoc);
+ aInfo.sourceLocation = std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc));
+
+ return aInfo;
}
-static void logCallToRootMethods(const FunctionDecl* functionDecl)
+void UnusedMethods::logCallToRootMethods(const FunctionDecl* functionDecl)
{
functionDecl = functionDecl->getCanonicalDecl();
bool bPrinted = false;
@@ -127,8 +153,7 @@ static void logCallToRootMethods(const FunctionDecl* functionDecl)
}
if (!bPrinted)
{
- std::string s = niceName(functionDecl);
- callSet.insert(s);
+ callSet.insert(niceName(functionDecl));
}
}
@@ -170,8 +195,36 @@ bool UnusedMethods::VisitCallExpr(CallExpr* expr)
FunctionDecl* calleeFunctionDecl = expr->getDirectCallee();
if (calleeFunctionDecl == nullptr) {
+ Expr* callee = expr->getCallee()->IgnoreParenImpCasts();
+ DeclRefExpr* dr = dyn_cast<DeclRefExpr>(callee);
+ if (dr) {
+ calleeFunctionDecl = dyn_cast<FunctionDecl>(dr->getDecl());
+ if (calleeFunctionDecl)
+ goto gotfunc;
+ }
+ /*
+ // ignore case where we can't determine the target of the call because we're inside a template
+ if (isa<CXXDependentScopeMemberExpr>(callee))
+ return true;
+ if (isa<UnresolvedLookupExpr>(callee))
+ return true;
+ if (isa<UnresolvedMemberExpr>(callee))
+ return true;
+ if (isa<DependentScopeDeclRefExpr>(callee))
+ return true;
+ // ignore this, doesn't really exist (side-effect of template expansion on scalar types)
+ if (isa<CXXPseudoDestructorExpr>(callee))
+ return true;
+ expr->dump();
+ std::string name = compiler.getSourceManager().getFilename(expansionLoc);
+ std::string sourceLocation = name + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc));
+ cout << sourceLocation << endl;
+ throw "Cant touch this";
+ */
return true;
}
+
+gotfunc:
// if we see a call to a function, it may effectively create new code,
// if the function is templated. However, if we are inside a template function,
// calling another function on the same template, the same problem occurs.