diff options
author | Noel Grandin <noel@peralex.com> | 2015-10-27 01:59:25 +0100 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2015-10-27 02:33:18 +0000 |
commit | 3ce9af420afafa1a81de646220706fcdc8d84b55 (patch) | |
tree | fc73bb3f66a8bd7973cff8615de7feaa61c5a49d /compilerplugins/clang | |
parent | 64de38cf8eec4c0ff21fa886b616182acd8600a2 (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.cxx | 93 | ||||
-rwxr-xr-x | compilerplugins/clang/unusedmethods.py | 9 |
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: |