summaryrefslogtreecommitdiff
path: root/compilerplugins/clang
diff options
context:
space:
mode:
authorNoel Grandin <noel@peralex.com>2015-10-27 01:59:25 +0100
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2015-10-27 02:33:18 +0000
commit3ce9af420afafa1a81de646220706fcdc8d84b55 (patch)
treefc73bb3f66a8bd7973cff8615de7feaa61c5a49d /compilerplugins/clang
parent64de38cf8eec4c0ff21fa886b616182acd8600a2 (diff)
loplugin:unusedmethods
Change-Id: I73180266c0af98dbd8d29bd3b11850996b94def9 Reviewed-on: https://gerrit.libreoffice.org/19195 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Diffstat (limited to 'compilerplugins/clang')
-rw-r--r--compilerplugins/clang/unusedmethods.cxx93
-rwxr-xr-xcompilerplugins/clang/unusedmethods.py9
2 files changed, 8 insertions, 94 deletions
diff --git a/compilerplugins/clang/unusedmethods.cxx b/compilerplugins/clang/unusedmethods.cxx
index e5fab5b9c023..a5550312e155 100644
--- a/compilerplugins/clang/unusedmethods.cxx
+++ b/compilerplugins/clang/unusedmethods.cxx
@@ -19,7 +19,7 @@
Dump a list of calls to methods, and a list of method definitions.
Then we will post-process the 2 lists and find the set of unused methods.
-Be warned that it produces around 4G of log file.
+Be warned that it produces around 5G of log file.
The process goes something like this:
$ make check
@@ -99,9 +99,6 @@ public:
bool VisitCallExpr(CallExpr* );
bool VisitFunctionDecl( const FunctionDecl* decl );
bool VisitDeclRefExpr( const DeclRefExpr* );
- bool VisitCXXConstructExpr( const CXXConstructExpr* );
- bool VisitVarDecl( const VarDecl* );
- bool VisitCXXRecordDecl( CXXRecordDecl* );
private:
void logCallToRootMethods(const FunctionDecl* functionDecl);
MyFuncInfo niceName(const FunctionDecl* functionDecl);
@@ -216,22 +213,7 @@ bool UnusedMethods::VisitCallExpr(CallExpr* expr)
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;
@@ -249,28 +231,6 @@ gotfunc:
return true;
}
-bool UnusedMethods::VisitCXXConstructExpr(const CXXConstructExpr* expr)
-{
- const CXXConstructorDecl *consDecl = expr->getConstructor();
- consDecl = consDecl->getCanonicalDecl();
- if (consDecl->getTemplatedKind() == FunctionDecl::TemplatedKind::TK_NonTemplate
- && !consDecl->isFunctionTemplateSpecialization()) {
- return true;
- }
- // if we see a call to a constructor, it may effectively create a whole new class,
- // if the constructor's class is templated.
- if (!traversedFunctionSet.insert(fullyQualifiedName(consDecl)).second)
- return true;
-
- const CXXRecordDecl* parent = consDecl->getParent();
- for( CXXRecordDecl::ctor_iterator it = parent->ctor_begin(); it != parent->ctor_end(); ++it)
- TraverseCXXConstructorDecl(*it);
- for( CXXRecordDecl::method_iterator it = parent->method_begin(); it != parent->method_end(); ++it)
- TraverseCXXMethodDecl(*it);
-
- return true;
-}
-
bool UnusedMethods::VisitFunctionDecl( const FunctionDecl* functionDecl )
{
functionDecl = functionDecl->getCanonicalDecl();
@@ -311,57 +271,6 @@ bool UnusedMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr )
return true;
}
-// this is for declarations of static variables that involve a template
-bool UnusedMethods::VisitVarDecl( const VarDecl* varDecl )
-{
- varDecl = varDecl->getCanonicalDecl();
-
- if (varDecl->getStorageClass() != SC_Static)
- return true;
- const CXXRecordDecl* recordDecl = varDecl->getType()->getAsCXXRecordDecl();
- if (!recordDecl)
- return true;
-// workaround clang-3.5 issue
-#if __clang_major__ > 3 || ( __clang_major__ == 3 && __clang_minor__ >= 6 )
- if (!recordDecl->getTemplateInstantiationPattern())
- return true;
-#endif
- for( CXXRecordDecl::ctor_iterator it = recordDecl->ctor_begin(); it != recordDecl->ctor_end(); ++it)
- TraverseCXXConstructorDecl(*it);
- for( CXXRecordDecl::method_iterator it = recordDecl->method_begin(); it != recordDecl->method_end(); ++it)
- TraverseCXXMethodDecl(*it);
- return true;
-}
-
-// Sometimes a class will inherit from something, and in the process invoke a template,
-// which can create new methods.
-//
-bool UnusedMethods::VisitCXXRecordDecl( CXXRecordDecl* recordDecl )
-{
- recordDecl = recordDecl->getCanonicalDecl();
- if (!recordDecl->hasDefinition())
- return true;
-// workaround clang-3.5 issue
-#if __clang_major__ > 3 || ( __clang_major__ == 3 && __clang_minor__ >= 6 )
- for(CXXBaseSpecifier* baseSpecifier = recordDecl->bases_begin();
- baseSpecifier != recordDecl->bases_end(); ++baseSpecifier)
- {
- const Type *baseType = baseSpecifier->getType().getTypePtr();
- if (isa<TypedefType>(baseSpecifier->getType())) {
- baseType = dyn_cast<TypedefType>(baseType)->desugar().getTypePtr();
- }
- if (isa<RecordType>(baseType)) {
- const RecordType *baseRecord = dyn_cast<RecordType>(baseType);
- CXXRecordDecl* baseRecordDecl = dyn_cast<CXXRecordDecl>(baseRecord->getDecl());
- if (baseRecordDecl && baseRecordDecl->getTemplateInstantiationPattern()) {
- TraverseCXXRecordDecl(baseRecordDecl);
- }
- }
- }
-#endif
- return true;
-}
-
loplugin::Plugin::Registration< UnusedMethods > X("unusedmethods", false);
}
diff --git a/compilerplugins/clang/unusedmethods.py b/compilerplugins/clang/unusedmethods.py
index 1ea23943a27d..fd17cb5c2f7d 100755
--- a/compilerplugins/clang/unusedmethods.py
+++ b/compilerplugins/clang/unusedmethods.py
@@ -103,6 +103,11 @@ exclusionSet = set([
"class vcl::Window * CreateWindow(class VCLXWindow **,const struct com::sun::star::awt::WindowDescriptor *,class vcl::Window *,long)",
])
+# clang does not always use exactly the same numbers in the type-parameter vars it generates
+# so I need to substitute them to ensure we can match correctly.
+normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+")
+def normalizeTypeParams( line ):
+ return normalizeTypeParamsRegex.sub("type-parameter-?-?", line)
# The parsing here is designed to avoid grabbing stuff which is mixed in from gbuild.
# I have not yet found a way of suppressing the gbuild output.
@@ -111,12 +116,12 @@ with io.open(sys.argv[1], "rb", buffering=1024*1024) as txt:
if line.startswith("definition:\t"):
idx1 = line.find("\t",12)
idx2 = line.find("\t",idx1+1)
- funcInfo = (line[12:idx1], line[idx1+1:idx2])
+ funcInfo = (normalizeTypeParams(line[12:idx1]), normalizeTypeParams(line[idx1+1:idx2]))
definitionSet.add(funcInfo)
definitionToSourceLocationMap[funcInfo] = line[idx2+1:].strip()
elif line.startswith("call:\t"):
idx1 = line.find("\t",6)
- callSet.add((line[6:idx1], line[idx1+1:].strip()))
+ callSet.add((normalizeTypeParams(line[6:idx1]), normalizeTypeParams(line[idx1+1:].strip())))
tmp1set = set()
for d in definitionSet: