compilerplugins/clang/constantparam.cxx | 2 compilerplugins/clang/constparams.cxx | 3 compilerplugins/clang/countusersofdefaultparams.cxx | 3 compilerplugins/clang/expandablemethods.cxx | 322 ++++++++++ compilerplugins/clang/expandablemethods.py | 148 ++++ compilerplugins/clang/inlinesimplememberfunctions.cxx | 3 compilerplugins/clang/passstuffbyref.cxx | 6 compilerplugins/clang/plugin.cxx | 5 compilerplugins/clang/plugin.hxx | 1 compilerplugins/clang/salbool.cxx | 8 compilerplugins/clang/staticmethods.cxx | 2 compilerplugins/clang/store/constantfunction.cxx | 2 compilerplugins/clang/store/removevirtuals.cxx | 3 compilerplugins/clang/store/returnbyref.cxx | 3 compilerplugins/clang/unnecessaryvirtual.cxx | 3 compilerplugins/clang/unreffun.cxx | 4 compilerplugins/clang/unusedmethods.cxx | 82 +- compilerplugins/clang/unusedmethods.py | 41 - compilerplugins/clang/unusedmethodsremove.cxx | 3 include/xmloff/shapeexport.hxx | 1 include/xmloff/xmlexp.hxx | 3 include/xmloff/xmlimp.hxx | 3 writerfilter/source/dmapper/TableManager.cxx | 6 writerfilter/source/dmapper/TableManager.hxx | 14 writerfilter/source/ooxml/OOXMLDocumentImpl.cxx | 2 writerfilter/source/ooxml/OOXMLDocumentImpl.hxx | 1 writerfilter/source/rtftok/rtfdocumentimpl.cxx | 28 writerfilter/source/rtftok/rtfdocumentimpl.hxx | 4 xmlhelp/source/cxxhelp/provider/urlparameter.cxx | 2 xmlhelp/source/cxxhelp/provider/urlparameter.hxx | 2 xmloff/inc/xexptran.hxx | 4 xmloff/source/core/DomExport.cxx | 8 xmloff/source/core/xmlexp.cxx | 7 xmloff/source/core/xmlimp.cxx | 7 xmloff/source/draw/animationexport.cxx | 8 xmloff/source/draw/sdxmlimp.cxx | 2 xmloff/source/draw/sdxmlimp_impl.hxx | 2 xmloff/source/draw/shapeexport.cxx | 2 xmloff/source/draw/xexptran.cxx | 18 xmloff/source/text/XMLTextListBlockContext.cxx | 2 xmloff/source/text/XMLTextListBlockContext.hxx | 1 xmloff/source/transform/ChartPlotAreaOASISTContext.cxx | 4 xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx | 6 xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx | 3 44 files changed, 557 insertions(+), 227 deletions(-)
New commits: commit 5af68a26f13f6abc44c276ee47b85e3a8fa20e65 Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Tue Oct 18 08:50:15 2016 +0200 rename inlineablemethods plugin to expandablemethods and add support for nested functions Change-Id: I63daee5b3047fa1ed5de0e5ddaf998f8b17bc780 diff --git a/compilerplugins/clang/inlineablemethods.cxx b/compilerplugins/clang/expandablemethods.cxx similarity index 85% rename from compilerplugins/clang/inlineablemethods.cxx rename to compilerplugins/clang/expandablemethods.cxx index c9feb75..73946f5 100644 --- a/compilerplugins/clang/inlineablemethods.cxx +++ b/compilerplugins/clang/expandablemethods.cxx @@ -21,7 +21,8 @@ #include "compat.hxx" /** - Methods that are only called from inside their own class, and are only called from one spot + Find methods that are only called from inside their own class, and are only called from one spot. + They are candidates to be removed and have their code inlined into the call site. TODO if a method has only one call-site, and that call site is inside a constructor @@ -54,11 +55,11 @@ static std::set<MyFuncInfo> largeFunctionSet; static std::set<MyFuncInfo> addressOfSet; -class InlineableMethods: - public RecursiveASTVisitor<InlineableMethods>, public loplugin::Plugin +class ExpandableMethods: + public RecursiveASTVisitor<ExpandableMethods>, public loplugin::Plugin { public: - explicit InlineableMethods(InstantiationData const & data): Plugin(data) {} + explicit ExpandableMethods(InstantiationData const & data): Plugin(data) {} virtual void run() override { @@ -80,7 +81,7 @@ public: for (const MyFuncInfo & s : addressOfSet) output += "addrof:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; ofstream myfile; - myfile.open( SRCDIR "/loplugin.inlineablemethods.log", ios::app | ios::out); + myfile.open( SRCDIR "/loplugin.expandablemethods.log", ios::app | ios::out); myfile << output; myfile.close(); } @@ -105,11 +106,10 @@ private: bool isCalleeFunctionInteresting( const FunctionDecl* ); // I use traverse and a member variable because I cannot find a reliable way of walking back up the AST tree using the parentStmt() stuff - // TODO doesn't cope with nested functions - const FunctionDecl* mpTraversingFunction = nullptr; + std::vector<const FunctionDecl*> maTraversingFunctions; }; -MyFuncInfo InlineableMethods::niceName(const FunctionDecl* functionDecl) +MyFuncInfo ExpandableMethods::niceName(const FunctionDecl* functionDecl) { if (functionDecl->getInstantiatedFromMemberFunction()) functionDecl = functionDecl->getInstantiatedFromMemberFunction(); @@ -159,7 +159,7 @@ MyFuncInfo InlineableMethods::niceName(const FunctionDecl* functionDecl) return aInfo; } -std::string InlineableMethods::toString(SourceLocation loc) +std::string ExpandableMethods::toString(SourceLocation loc) { SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( loc ); StringRef name = compiler.getSourceManager().getFilename(expansionLoc); @@ -168,7 +168,7 @@ std::string InlineableMethods::toString(SourceLocation loc) return sourceLocation; } -bool InlineableMethods::VisitFunctionDecl( const FunctionDecl* functionDecl ) +bool ExpandableMethods::VisitFunctionDecl( const FunctionDecl* functionDecl ) { const FunctionDecl* canonicalFunctionDecl = functionDecl->getCanonicalDecl(); if (!isCalleeFunctionInteresting(canonicalFunctionDecl)) { @@ -209,43 +209,43 @@ bool InlineableMethods::VisitFunctionDecl( const FunctionDecl* functionDecl ) return true; } -bool InlineableMethods::TraverseFunctionDecl( FunctionDecl* p ) +bool ExpandableMethods::TraverseFunctionDecl( FunctionDecl* p ) { - mpTraversingFunction = p; + maTraversingFunctions.push_back(p); bool ret = RecursiveASTVisitor::TraverseFunctionDecl(p); - mpTraversingFunction = nullptr; + maTraversingFunctions.pop_back(); return ret; } -bool InlineableMethods::TraverseCXXMethodDecl( CXXMethodDecl* p ) +bool ExpandableMethods::TraverseCXXMethodDecl( CXXMethodDecl* p ) { - mpTraversingFunction = p; + maTraversingFunctions.push_back(p); bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(p); - mpTraversingFunction = nullptr; + maTraversingFunctions.pop_back(); return ret; } -bool InlineableMethods::TraverseCXXConstructorDecl( CXXConstructorDecl* p ) +bool ExpandableMethods::TraverseCXXConstructorDecl( CXXConstructorDecl* p ) { - mpTraversingFunction = p; + maTraversingFunctions.push_back(p); bool ret = RecursiveASTVisitor::TraverseCXXConstructorDecl(p); - mpTraversingFunction = nullptr; + maTraversingFunctions.pop_back(); return ret; } -bool InlineableMethods::TraverseCXXConversionDecl( CXXConversionDecl* p ) +bool ExpandableMethods::TraverseCXXConversionDecl( CXXConversionDecl* p ) { - mpTraversingFunction = p; + maTraversingFunctions.push_back(p); bool ret = RecursiveASTVisitor::TraverseCXXConversionDecl(p); - mpTraversingFunction = nullptr; + maTraversingFunctions.pop_back(); return ret; } -bool InlineableMethods::TraverseCXXDestructorDecl( CXXDestructorDecl* p ) +bool ExpandableMethods::TraverseCXXDestructorDecl( CXXDestructorDecl* p ) { - mpTraversingFunction = p; + maTraversingFunctions.push_back(p); bool ret = RecursiveASTVisitor::TraverseCXXDestructorDecl(p); - mpTraversingFunction = nullptr; + maTraversingFunctions.pop_back(); return ret; } -bool InlineableMethods::VisitMemberExpr( const MemberExpr* memberExpr ) +bool ExpandableMethods::VisitMemberExpr( const MemberExpr* memberExpr ) { const FunctionDecl* functionDecl = dyn_cast<FunctionDecl>(memberExpr->getMemberDecl()); if (functionDecl) { @@ -254,7 +254,7 @@ bool InlineableMethods::VisitMemberExpr( const MemberExpr* memberExpr ) return true; } -bool InlineableMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) +bool ExpandableMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) { const FunctionDecl* functionDecl = dyn_cast<FunctionDecl>(declRefExpr->getDecl()); if (functionDecl) { @@ -263,9 +263,9 @@ bool InlineableMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) return true; } -void InlineableMethods::functionTouchedFromExpr( const FunctionDecl* calleeFunctionDecl, const Expr* expr ) +void ExpandableMethods::functionTouchedFromExpr( const FunctionDecl* calleeFunctionDecl, const Expr* expr ) { - if (!mpTraversingFunction) { + if (maTraversingFunctions.empty()) { return; } const FunctionDecl* canonicalFunctionDecl = calleeFunctionDecl->getCanonicalDecl(); @@ -282,7 +282,7 @@ void InlineableMethods::functionTouchedFromExpr( const FunctionDecl* calleeFunct } const CXXMethodDecl* calleeMethodDecl = dyn_cast<CXXMethodDecl>(calleeFunctionDecl); - const CXXMethodDecl* callsiteParentMethodDecl = dyn_cast<CXXMethodDecl>(mpTraversingFunction); + const CXXMethodDecl* callsiteParentMethodDecl = dyn_cast<CXXMethodDecl>(maTraversingFunctions.back()); if (!callsiteParentMethodDecl || calleeMethodDecl->getParent() != callsiteParentMethodDecl->getParent()) { @@ -290,7 +290,7 @@ void InlineableMethods::functionTouchedFromExpr( const FunctionDecl* calleeFunct } } -bool InlineableMethods::isCalleeFunctionInteresting(const FunctionDecl* functionDecl) +bool ExpandableMethods::isCalleeFunctionInteresting(const FunctionDecl* functionDecl) { // ignore stuff that forms part of the stable URE interface if (isInUnoIncludeFile(functionDecl)) { @@ -315,7 +315,7 @@ bool InlineableMethods::isCalleeFunctionInteresting(const FunctionDecl* function return true; } -loplugin::Plugin::Registration< InlineableMethods > X("inlineablemethods", false); +loplugin::Plugin::Registration< ExpandableMethods > X("expandablemethods", false); } diff --git a/compilerplugins/clang/inlineablemethods.py b/compilerplugins/clang/expandablemethods.py similarity index 98% rename from compilerplugins/clang/inlineablemethods.py rename to compilerplugins/clang/expandablemethods.py index a9b75472..ac97c2b 100755 --- a/compilerplugins/clang/inlineablemethods.py +++ b/compilerplugins/clang/expandablemethods.py @@ -27,7 +27,7 @@ def normalizeTypeParams( 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. -with io.open("loplugin.inlineablemethods.log", "rb", buffering=1024*1024) as txt: +with io.open("loplugin.expandablemethods.log", "rb", buffering=1024*1024) as txt: for line in txt: tokens = line.strip().split("\t") if tokens[0] == "definition:": @@ -142,7 +142,7 @@ for d in definitionSet: tmp4set.add((method, definitionToSourceLocationMap[d])) # print output, sorted by name and line number -with open("loplugin.inlineablemethods.report", "wt") as f: +with open("loplugin.expandablemethods.report", "wt") as f: for t in sort_set_by_natural_key(tmp4set): f.write(t[1] + "\n") f.write(" " + t[0] + "\n") commit 40fd53a2383ba353054ed440c45f2319a9b8efef Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Tue Oct 18 08:15:21 2016 +0200 loplugins: extract some common functionality Change-Id: If470e1d9b481c9eda0829aa985152baf8fb46d7a diff --git a/compilerplugins/clang/constantparam.cxx b/compilerplugins/clang/constantparam.cxx index 550cdd1..f5a3d53 100644 --- a/compilerplugins/clang/constantparam.cxx +++ b/compilerplugins/clang/constantparam.cxx @@ -100,7 +100,7 @@ void ConstantParam::addToCallSet(const FunctionDecl* functionDecl, int paramInde if (ignoreLocation(functionDecl)) return; // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(functionDecl->getLocation()))) + if (isInUnoIncludeFile(functionDecl)) return; SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( functionDecl->getLocation() ); StringRef filename = compiler.getSourceManager().getFilename(expansionLoc); diff --git a/compilerplugins/clang/constparams.cxx b/compilerplugins/clang/constparams.cxx index 291a4e7..52f1ffe 100644 --- a/compilerplugins/clang/constparams.cxx +++ b/compilerplugins/clang/constparams.cxx @@ -52,8 +52,7 @@ bool ConstParams::VisitFunctionDecl(FunctionDecl * functionDecl) return true; } // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( - functionDecl->getCanonicalDecl()->getNameInfo().getLoc()))) { + if (isInUnoIncludeFile(functionDecl)) { return true; } // TODO ignore these for now, requires some extra work diff --git a/compilerplugins/clang/countusersofdefaultparams.cxx b/compilerplugins/clang/countusersofdefaultparams.cxx index b6323d0..d17377b 100644 --- a/compilerplugins/clang/countusersofdefaultparams.cxx +++ b/compilerplugins/clang/countusersofdefaultparams.cxx @@ -234,8 +234,7 @@ bool CountUsersOfDefaultParams::VisitFunctionDecl( const FunctionDecl* functionD return true; } // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( - functionDecl->getNameInfo().getLoc()))) { + if (isInUnoIncludeFile(functionDecl)) { return true; } if (isa<CXXDestructorDecl>(functionDecl)) { diff --git a/compilerplugins/clang/inlineablemethods.cxx b/compilerplugins/clang/inlineablemethods.cxx index 032853b..c9feb75 100644 --- a/compilerplugins/clang/inlineablemethods.cxx +++ b/compilerplugins/clang/inlineablemethods.cxx @@ -293,8 +293,7 @@ void InlineableMethods::functionTouchedFromExpr( const FunctionDecl* calleeFunct bool InlineableMethods::isCalleeFunctionInteresting(const FunctionDecl* functionDecl) { // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( - functionDecl->getNameInfo().getLoc()))) { + if (isInUnoIncludeFile(functionDecl)) { return false; } if (isa<CXXDestructorDecl>(functionDecl)) { diff --git a/compilerplugins/clang/inlinesimplememberfunctions.cxx b/compilerplugins/clang/inlinesimplememberfunctions.cxx index b151538..9048bb4 100644 --- a/compilerplugins/clang/inlinesimplememberfunctions.cxx +++ b/compilerplugins/clang/inlinesimplememberfunctions.cxx @@ -71,8 +71,7 @@ bool InlineSimpleMemberFunctions::VisitCXXMethodDecl(const CXXMethodDecl * funct return true; } // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( - functionDecl->getCanonicalDecl()->getNameInfo().getLoc()))) { + if (isInUnoIncludeFile(functionDecl)) { return true; } // ignore stuff like: diff --git a/compilerplugins/clang/passstuffbyref.cxx b/compilerplugins/clang/passstuffbyref.cxx index b1b3169..ad6c100 100644 --- a/compilerplugins/clang/passstuffbyref.cxx +++ b/compilerplugins/clang/passstuffbyref.cxx @@ -205,8 +205,7 @@ void PassStuffByRef::checkParams(const FunctionDecl * functionDecl) { } } // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( - functionDecl->getCanonicalDecl()->getNameInfo().getLoc()))) { + if (isInUnoIncludeFile(functionDecl)) { return; } // these functions are passed as parameters to another function @@ -245,8 +244,7 @@ void PassStuffByRef::checkReturnValue(const FunctionDecl * functionDecl, const C } // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( - functionDecl->getCanonicalDecl()->getNameInfo().getLoc()))) { + if (isInUnoIncludeFile(functionDecl)) { return; } loplugin::DeclCheck dc(functionDecl); diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx index 3507371..dc48101 100644 --- a/compilerplugins/clang/plugin.cxx +++ b/compilerplugins/clang/plugin.cxx @@ -170,6 +170,11 @@ bool Plugin::isInUnoIncludeFile(SourceLocation spellingLocation) const { || name.startswith(WORKDIR "/")); } +bool Plugin::isInUnoIncludeFile(const FunctionDecl* functionDecl) const { + return isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( + functionDecl->getCanonicalDecl()->getNameInfo().getLoc())); +} + namespace { class ParentBuilder diff --git a/compilerplugins/clang/plugin.hxx b/compilerplugins/clang/plugin.hxx index 635dcfe..6248ef7 100644 --- a/compilerplugins/clang/plugin.hxx +++ b/compilerplugins/clang/plugin.hxx @@ -75,6 +75,7 @@ class Plugin which is not allowed to be changed. */ bool isInUnoIncludeFile(SourceLocation spellingLocation) const; + bool isInUnoIncludeFile(const FunctionDecl*) const; static void normalizeDotDotInFilePath(std::string&); private: diff --git a/compilerplugins/clang/salbool.cxx b/compilerplugins/clang/salbool.cxx index 040512c..a443234 100644 --- a/compilerplugins/clang/salbool.cxx +++ b/compilerplugins/clang/salbool.cxx @@ -479,9 +479,7 @@ bool SalBool::VisitParmVarDecl(ParmVarDecl const * decl) { if (f != nullptr) { // e.g.: typedef sal_Bool (* FuncPtr )( sal_Bool ); f = f->getCanonicalDecl(); if (!(hasCLanguageLinkageType(f) - || (isInUnoIncludeFile( - compiler.getSourceManager().getSpellingLoc( - f->getNameInfo().getLoc())) + || (isInUnoIncludeFile(f) && (!f->isInlined() || f->hasAttr<DeprecatedAttr>() || decl->getType()->isReferenceType() || hasBoolOverload(f, false))) @@ -654,9 +652,7 @@ bool SalBool::VisitFunctionDecl(FunctionDecl const * decl) { OverrideKind k = getOverrideKind(f); if (k != OverrideKind::YES && !(hasCLanguageLinkageType(f) - || (isInUnoIncludeFile( - compiler.getSourceManager().getSpellingLoc( - f->getNameInfo().getLoc())) + || (isInUnoIncludeFile(f) && (!f->isInlined() || f->hasAttr<DeprecatedAttr>())))) { SourceLocation loc { decl->getLocStart() }; diff --git a/compilerplugins/clang/staticmethods.cxx b/compilerplugins/clang/staticmethods.cxx index 5b88d0c..588e534 100644 --- a/compilerplugins/clang/staticmethods.cxx +++ b/compilerplugins/clang/staticmethods.cxx @@ -87,7 +87,7 @@ bool StaticMethods::TraverseCXXMethodDecl(const CXXMethodDecl * pCXXMethodDecl) if (isa<CXXConstructorDecl>(pCXXMethodDecl) || isa<CXXDestructorDecl>(pCXXMethodDecl) || isa<CXXConversionDecl>(pCXXMethodDecl)) { return true; } - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(pCXXMethodDecl->getCanonicalDecl()->getNameInfo().getLoc()))) { + if (isInUnoIncludeFile(pCXXMethodDecl)) { return true; } if ( pCXXMethodDecl != pCXXMethodDecl->getCanonicalDecl() ) { diff --git a/compilerplugins/clang/store/constantfunction.cxx b/compilerplugins/clang/store/constantfunction.cxx index 943cc7d..cd14c48 100644 --- a/compilerplugins/clang/store/constantfunction.cxx +++ b/compilerplugins/clang/store/constantfunction.cxx @@ -152,7 +152,7 @@ bool ConstantFunction::VisitFunctionDecl(const FunctionDecl * pFunctionDecl) { return true; } SourceLocation canonicalLoc = pFunctionDecl->getCanonicalDecl()->getNameInfo().getLoc(); - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(canonicalLoc))) { + if (isInUnoIncludeFile(pFunctionDecl)) { return true; } diff --git a/compilerplugins/clang/store/removevirtuals.cxx b/compilerplugins/clang/store/removevirtuals.cxx index da204d3..6ed3dd6 100644 --- a/compilerplugins/clang/store/removevirtuals.cxx +++ b/compilerplugins/clang/store/removevirtuals.cxx @@ -97,8 +97,7 @@ bool RemoveVirtuals::VisitCXXMethodDecl( const CXXMethodDecl* functionDecl ) return true; } // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( - functionDecl->getCanonicalDecl()->getNameInfo().getLoc()))) { + if (isInUnoIncludeFile(functionDecl)) { return true; } diff --git a/compilerplugins/clang/store/returnbyref.cxx b/compilerplugins/clang/store/returnbyref.cxx index d5052d6..aacfd7d 100644 --- a/compilerplugins/clang/store/returnbyref.cxx +++ b/compilerplugins/clang/store/returnbyref.cxx @@ -52,8 +52,7 @@ bool ReturnByRef::VisitCXXMethodDecl(const CXXMethodDecl * functionDecl) { return true; } // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( - functionDecl->getCanonicalDecl()->getNameInfo().getLoc()))) { + if (isInUnoIncludeFile(functionDecl)) { return true; } QualType t1 { compat::getReturnType(*functionDecl) }; diff --git a/compilerplugins/clang/unnecessaryvirtual.cxx b/compilerplugins/clang/unnecessaryvirtual.cxx index 9403213..1ecc471 100644 --- a/compilerplugins/clang/unnecessaryvirtual.cxx +++ b/compilerplugins/clang/unnecessaryvirtual.cxx @@ -154,8 +154,7 @@ bool UnnecessaryVirtual::VisitCXXMethodDecl( const CXXMethodDecl* methodDecl ) } if (methodDecl->size_overridden_methods() == 0) { // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( - methodDecl->getNameInfo().getLoc()))) { + if (isInUnoIncludeFile(methodDecl)) { return true; } // ignore templates and template instantiations, diff --git a/compilerplugins/clang/unreffun.cxx b/compilerplugins/clang/unreffun.cxx index bf381f9..0284d36 100644 --- a/compilerplugins/clang/unreffun.cxx +++ b/compilerplugins/clang/unreffun.cxx @@ -112,9 +112,7 @@ bool UnrefFun::VisitFunctionDecl(FunctionDecl const * decl) { || !(canon->isDefined() ? decl->isThisDeclarationADefinition() : decl->isFirstDecl()) || !compiler.getSourceManager().isInMainFile(canon->getLocation()) - || isInUnoIncludeFile( - compiler.getSourceManager().getSpellingLoc( - canon->getNameInfo().getLoc())) + || isInUnoIncludeFile(canon) || canon->isMain() || (decl->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate && (decl->getDescribedFunctionTemplate()->spec_begin() diff --git a/compilerplugins/clang/unusedmethods.cxx b/compilerplugins/clang/unusedmethods.cxx index 80af024..c265381 100644 --- a/compilerplugins/clang/unusedmethods.cxx +++ b/compilerplugins/clang/unusedmethods.cxx @@ -312,12 +312,11 @@ bool UnusedMethods::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr bool UnusedMethods::VisitFunctionDecl( const FunctionDecl* functionDecl ) { - const FunctionDecl* canonicalFunctionDecl = functionDecl->getCanonicalDecl(); // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( - canonicalFunctionDecl->getNameInfo().getLoc()))) { + if (isInUnoIncludeFile(functionDecl)) { return true; } + const FunctionDecl* canonicalFunctionDecl = functionDecl->getCanonicalDecl(); if (isa<CXXDestructorDecl>(functionDecl)) { return true; } diff --git a/compilerplugins/clang/unusedmethodsremove.cxx b/compilerplugins/clang/unusedmethodsremove.cxx index 273b415..09187ed 100644 --- a/compilerplugins/clang/unusedmethodsremove.cxx +++ b/compilerplugins/clang/unusedmethodsremove.cxx @@ -102,8 +102,7 @@ bool UnusedMethodsRemove::VisitCXXMethodDecl( const CXXMethodDecl* functionDecl return true; } // ignore stuff that forms part of the stable URE interface - if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( - functionDecl->getCanonicalDecl()->getNameInfo().getLoc()))) { + if (isInUnoIncludeFile(functionDecl)) { return true; } commit 9d8d2e0787b8d866a651bcb9778393fb080ab6e8 Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Mon Oct 17 16:20:50 2016 +0200 simplify inlineablemethods loplugin Change-Id: I72750a14664aa042da232c35cca3373ce367cfb0 diff --git a/compilerplugins/clang/inlineablemethods.cxx b/compilerplugins/clang/inlineablemethods.cxx index df98463..032853b 100644 --- a/compilerplugins/clang/inlineablemethods.cxx +++ b/compilerplugins/clang/inlineablemethods.cxx @@ -103,7 +103,6 @@ private: std::string toString(SourceLocation loc); void functionTouchedFromExpr( const FunctionDecl* calleeFunctionDecl, const Expr* expr ); bool isCalleeFunctionInteresting( const FunctionDecl* ); - void logCalledFrom(SourceLocation calleeSite, const FunctionDecl* functionDecl); // I use traverse and a member variable because I cannot find a reliable way of walking back up the AST tree using the parentStmt() stuff // TODO doesn't cope with nested functions @@ -274,7 +273,7 @@ void InlineableMethods::functionTouchedFromExpr( const FunctionDecl* calleeFunct return; } - logCalledFrom(expr->getLocStart(), canonicalFunctionDecl); + calledFromMap.emplace(toString(expr->getLocStart()), niceName(canonicalFunctionDecl)); if (const UnaryOperator* unaryOp = dyn_cast_or_null<UnaryOperator>(parentStmt(expr))) { if (unaryOp->getOpcode() == UO_AddrOf) { @@ -291,14 +290,6 @@ void InlineableMethods::functionTouchedFromExpr( const FunctionDecl* calleeFunct } } -void InlineableMethods::logCalledFrom(SourceLocation calleeLoc, const FunctionDecl* functionDecl) -{ - functionDecl = functionDecl->getCanonicalDecl(); - while (functionDecl->getTemplateInstantiationPattern()) - functionDecl = functionDecl->getTemplateInstantiationPattern(); - calledFromMap.emplace(toString(calleeLoc), niceName(functionDecl)); -} - bool InlineableMethods::isCalleeFunctionInteresting(const FunctionDecl* functionDecl) { // ignore stuff that forms part of the stable URE interface commit a8b2bfdcb0d62afdc6c363cb3c456b2379090ce2 Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Mon Oct 17 16:15:04 2016 +0200 loplugin:inlineablemethods in writerfilter Change-Id: Iada0f4d631703b3067c90923632ce9a1012bad62 diff --git a/writerfilter/source/dmapper/TableManager.cxx b/writerfilter/source/dmapper/TableManager.cxx index d9f5079..e69d322 100644 --- a/writerfilter/source/dmapper/TableManager.cxx +++ b/writerfilter/source/dmapper/TableManager.cxx @@ -257,7 +257,7 @@ void TableManager::endParagraphGroup() { endOfRowAction(); mTableDataStack.top()->endRow(getRowProps()); - resetRowProps(); + mState.resetRowProps(); } else if (isInCell()) @@ -270,7 +270,7 @@ void TableManager::endParagraphGroup() closeCell(getHandle()); } } - resetCellProps(); + mState.resetCellProps(); } } @@ -321,7 +321,7 @@ void TableManager::resolveCurrentTable() SAL_WARN("writerfilter", "resolving of current table failed with: " << e.Message); } } - resetTableProps(); + mState.resetTableProps(); clearData(); #ifdef DEBUG_WRITERFILTER diff --git a/writerfilter/source/dmapper/TableManager.hxx b/writerfilter/source/dmapper/TableManager.hxx index 334634d..d94a805 100644 --- a/writerfilter/source/dmapper/TableManager.hxx +++ b/writerfilter/source/dmapper/TableManager.hxx @@ -216,11 +216,6 @@ protected: mState.setCellProps(pProps); } - void resetCellProps() - { - mState.resetCellProps(); - } - public: TablePropertyMapPtr getRowProps() { @@ -232,10 +227,6 @@ public: mState.setRowProps(pProps); } - void resetRowProps() - { - mState.resetRowProps(); - } protected: void setInCell(bool bInCell) @@ -278,11 +269,6 @@ protected: mState.setTableProps(pProps); } - void resetTableProps() - { - mState.resetTableProps(); - } - const css::uno::Reference<css::text::XTextRange>& getHandle() { return mCurHandle; diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx index ae8d8fe..f8d5bdc 100644 --- a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx +++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx @@ -271,7 +271,7 @@ OOXMLDocumentImpl::getSubStream(const OUString & rId) writerfilter::Reference<Stream>::Pointer_t pRet( pTemp = new OOXMLDocumentImpl(pStream, uno::Reference<task::XStatusIndicator>(), mbSkipImages, maMediaDescriptor)); pTemp->setModel(mxModel); pTemp->setDrawPage(mxDrawPage); - pTemp->setIsSubstream( true ); + pTemp->mbIsSubstream = true; return pRet; } diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx index 12a49ab..43bdeb6 100644 --- a/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx +++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx @@ -87,7 +87,6 @@ protected: Id aType, const sal_Int32 nNoteId); - void setIsSubstream( bool bSubstream ) { mbIsSubstream = bSubstream; }; void resolveCustomXmlStream(Stream & rStream); void resolveActiveXStream(Stream & rStream); void resolveGlossaryStream(Stream & rStream); diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index 01c0c0c..577cddc 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -308,16 +308,6 @@ void RTFDocumentImpl::setSuperstream(RTFDocumentImpl* pSuperstream) m_pSuperstream = pSuperstream; } -void RTFDocumentImpl::setStreamType(Id nId) -{ - m_nStreamType = nId; -} - -void RTFDocumentImpl::setAuthor(OUString& rAuthor) -{ - m_aAuthor = rAuthor; -} - void RTFDocumentImpl::setAuthorInitials(OUString& rAuthorInitials) { m_aAuthorInitials = rAuthorInitials; @@ -333,11 +323,6 @@ void RTFDocumentImpl::finishSubstream() checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true); } -void RTFDocumentImpl::setIgnoreFirst(OUString& rIgnoreFirst) -{ - m_aIgnoreFirst = rIgnoreFirst; -} - void RTFDocumentImpl::resolveSubstream(std::size_t nPos, Id nId) { OUString aStr; @@ -349,11 +334,11 @@ void RTFDocumentImpl::resolveSubstream(std::size_t nPos, Id nId, OUString& rIgno // Seek to header position, parse, then seek back. auto pImpl = std::make_shared<RTFDocumentImpl>(m_xContext, m_xInputStream, m_xDstDoc, m_xFrame, m_xStatusIndicator, m_rMediaDescriptor); pImpl->setSuperstream(this); - pImpl->setStreamType(nId); - pImpl->setIgnoreFirst(rIgnoreFirst); + pImpl->m_nStreamType = nId; + pImpl->m_aIgnoreFirst = rIgnoreFirst; if (!m_aAuthor.isEmpty()) { - pImpl->setAuthor(m_aAuthor); + pImpl->m_aAuthor = m_aAuthor; m_aAuthor.clear(); } if (!m_aAuthorInitials.isEmpty()) @@ -362,7 +347,7 @@ void RTFDocumentImpl::resolveSubstream(std::size_t nPos, Id nId, OUString& rIgno m_aAuthorInitials.clear(); } pImpl->m_nDefaultFontIndex = m_nDefaultFontIndex; - pImpl->seek(nPos); + pImpl->Strm().Seek(nPos); SAL_INFO("writerfilter", "substream start"); Mapper().substream(nId, pImpl); SAL_INFO("writerfilter", "substream end"); @@ -635,11 +620,6 @@ void RTFDocumentImpl::sectBreak(bool bFinal) m_bNeedSect = false; } -void RTFDocumentImpl::seek(sal_uInt64 const nPos) -{ - Strm().Seek(nPos); -} - sal_uInt32 RTFDocumentImpl::getColorTable(sal_uInt32 nIndex) { if (!m_pSuperstream) diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx index d1b5ca1..3fec689 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx @@ -413,11 +413,7 @@ public: return *m_pMapperStream; } void setSuperstream(RTFDocumentImpl* pSuperstream); - void setStreamType(Id nId); - void setAuthor(OUString& rAuthor); void setAuthorInitials(OUString& rAuthorInitials); - void setIgnoreFirst(OUString& rIgnoreFirst); - void seek(sal_uInt64 nPos); const css::uno::Reference<css::lang::XMultiServiceFactory>& getModelFactory() { return m_xModelFactory; commit 7477ab139142c55da6a7d4fb10903dcb464ee97b Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Mon Oct 17 16:02:40 2016 +0200 loplugin:inlineablemethods in xmloff Change-Id: I22202f85c65a862ccdafe1d521e2945e3d99252a diff --git a/include/xmloff/shapeexport.hxx b/include/xmloff/shapeexport.hxx index 2d741ca..ce74b19 100644 --- a/include/xmloff/shapeexport.hxx +++ b/include/xmloff/shapeexport.hxx @@ -297,7 +297,6 @@ public: static SvXMLExportPropertyMapper* CreateShapePropMapper( SvXMLExport& rExport ); void enableLayerExport() { mbExportLayer = true; } - bool IsLayerExportEnabled() const { return mbExportLayer; } /** defines if the export should increment the progress bar or not */ void enableHandleProgressBar() { mbHandleProgressBar = true; } diff --git a/include/xmloff/xmlexp.hxx b/include/xmloff/xmlexp.hxx index a59ddd3..a8d85af 100644 --- a/include/xmloff/xmlexp.hxx +++ b/include/xmloff/xmlexp.hxx @@ -543,9 +543,6 @@ public: /// returns the deterministic version for odf export SvtSaveOptions::ODFSaneDefaultVersion getSaneDefaultVersion() const; - /// name of stream in package, e.g., "content.xml" - OUString GetStreamName() const; - // FIXME: this is only for legacy stuff that has not yet been adapted // to implement XMetadatable; this can write duplicate IDs! /// add xml:id and legacy namespace id diff --git a/include/xmloff/xmlimp.hxx b/include/xmloff/xmlimp.hxx index 07168bc..8ba9695 100644 --- a/include/xmloff/xmlimp.hxx +++ b/include/xmloff/xmlimp.hxx @@ -484,9 +484,6 @@ public: OUString GetBaseURL() const; OUString GetDocumentBase() const; - /// name of stream in package, e.g., "content.xml" - OUString GetStreamName() const; - /// set the XmlId attribute of given UNO object (for RDF metadata) void SetXmlId(css::uno::Reference< css::uno::XInterface> const & i_xIfc, diff --git a/xmlhelp/source/cxxhelp/provider/urlparameter.cxx b/xmlhelp/source/cxxhelp/provider/urlparameter.cxx index 0099970..f0e3b76 100644 --- a/xmlhelp/source/cxxhelp/provider/urlparameter.cxx +++ b/xmlhelp/source/cxxhelp/provider/urlparameter.cxx @@ -102,7 +102,7 @@ OString URLParameter::getByName( const char* par ) else if( strcmp( par,"System" ) == 0 ) val = get_system(); else if( strcmp( par,"HelpPrefix" ) == 0 ) - val = get_prefix(); + val = m_aPrefix; return OString( val.getStr(),val.getLength(),RTL_TEXTENCODING_UTF8 ); } diff --git a/xmlhelp/source/cxxhelp/provider/urlparameter.hxx b/xmlhelp/source/cxxhelp/provider/urlparameter.hxx index 294a473..21dd802 100644 --- a/xmlhelp/source/cxxhelp/provider/urlparameter.hxx +++ b/xmlhelp/source/cxxhelp/provider/urlparameter.hxx @@ -147,8 +147,6 @@ namespace chelp { return m_aModule; } - const OUString& get_prefix() const { return m_aPrefix; } - OUString const & get_language(); OUString const & get_program(); diff --git a/xmloff/inc/xexptran.hxx b/xmloff/inc/xexptran.hxx index 129317e..3242d52 100644 --- a/xmloff/inc/xexptran.hxx +++ b/xmloff/inc/xexptran.hxx @@ -51,8 +51,6 @@ class SdXMLImExTransform2D std::vector< std::shared_ptr< ImpSdXMLExpTransObj2DBase > > maList; OUString msString; - void EmptyList(); - public: SdXMLImExTransform2D() {} @@ -73,8 +71,6 @@ class SdXMLImExTransform3D std::vector< std::shared_ptr< ImpSdXMLExpTransObj3DBase > > maList; OUString msString; - void EmptyList(); - public: SdXMLImExTransform3D() {} SdXMLImExTransform3D(const OUString& rNew, const SvXMLUnitConverter& rConv); diff --git a/xmloff/source/core/DomExport.cxx b/xmloff/source/core/DomExport.cxx index f271e3c..21dc039 100644 --- a/xmloff/source/core/DomExport.cxx +++ b/xmloff/source/core/DomExport.cxx @@ -125,7 +125,6 @@ class DomExport: public DomVisitor vector<SvXMLNamespaceMap> maNamespaces; void pushNamespace(); - void popNamespace(); void addNamespace( const OUString& sPrefix, const OUString& sURI ); OUString qualifiedName( const OUString& sPrefix, const OUString& sURI, const OUString& sLocalName ); @@ -161,11 +160,6 @@ void DomExport::pushNamespace() maNamespaces.push_back(aMap); } -void DomExport::popNamespace() -{ - maNamespaces.pop_back(); -} - void DomExport::addNamespace( const OUString& sPrefix, const OUString& sURI ) { SvXMLNamespaceMap& rMap = maNamespaces.back(); @@ -234,7 +228,7 @@ void DomExport::element( const Reference<XElement>& xElement ) void DomExport::endElement( const Reference<XElement>& xElement ) { mrExport.EndElement( qualifiedName( xElement ), false ); - popNamespace(); + maNamespaces.pop_back(); } void DomExport::character( const Reference<XCharacterData>& xChars ) diff --git a/xmloff/source/core/xmlexp.cxx b/xmloff/source/core/xmlexp.cxx index 42be779..3bcbd91 100644 --- a/xmloff/source/core/xmlexp.cxx +++ b/xmloff/source/core/xmlexp.cxx @@ -2365,11 +2365,6 @@ SvtSaveOptions::ODFSaneDefaultVersion SvXMLExport::getSaneDefaultVersion() const return SvtSaveOptions::ODFSVER_LATEST; } -OUString SvXMLExport::GetStreamName() const -{ - return mpImpl->mStreamName; -} - void SvXMLExport::AddAttributeIdLegacy( sal_uInt16 const nLegacyPrefix, OUString const& rValue) @@ -2403,7 +2398,7 @@ SvXMLExport::AddAttributeXmlId(uno::Reference<uno::XInterface> const & i_xIfc) const beans::StringPair mdref( xMeta->getMetadataReference() ); if ( !mdref.Second.isEmpty() ) { - const OUString streamName( GetStreamName() ); + const OUString streamName = mpImpl->mStreamName; if ( !streamName.isEmpty() ) { if ( streamName.equals(mdref.First) ) diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx index a8ebb95..638b519 100644 --- a/xmloff/source/core/xmlimp.cxx +++ b/xmloff/source/core/xmlimp.cxx @@ -1929,11 +1929,6 @@ OUString SvXMLImport::GetDocumentBase() const return mpImpl->aDocBase.GetMainURL( INetURLObject::NO_DECODE ); } -OUString SvXMLImport::GetStreamName() const -{ - return mpImpl->mStreamName; -} - // Convert drawing object positions from OOo file format to OASIS (#i28749#) bool SvXMLImport::IsShapePositionInHoriL2R() const { @@ -2009,7 +2004,7 @@ void SvXMLImport::SetXmlId(uno::Reference<uno::XInterface> const & i_xIfc, uno::UNO_QUERY); //FIXME: not yet if (xMeta.is()) { - const beans::StringPair mdref( GetStreamName(), i_rXmlId ); + const beans::StringPair mdref( mpImpl->mStreamName, i_rXmlId ); try { xMeta->setMetadataReference(mdref); } catch (lang::IllegalArgumentException &) { diff --git a/xmloff/source/draw/animationexport.cxx b/xmloff/source/draw/animationexport.cxx index 9dcfa58..88ba4da 100644 --- a/xmloff/source/draw/animationexport.cxx +++ b/xmloff/source/draw/animationexport.cxx @@ -518,7 +518,6 @@ public: static void convertPath( OUStringBuffer& sTmp, const Any& rPath ); void convertValue( XMLTokenEnum eAttributeName, OUStringBuffer& sTmp, const Any& rValue ) const; void convertTiming( OUStringBuffer& sTmp, const Any& rTiming ) const; - void convertSource( OUStringBuffer& sTmp, const Any& rSource ) const; void convertTarget( OUStringBuffer& sTmp, const Any& rTarget ) const; void prepareValue( const Any& rValue ); @@ -1564,7 +1563,7 @@ void AnimationsExporterImpl::convertTiming( OUStringBuffer& sTmp, const Any& rVa { if( pEvent->Source.hasValue() ) { - convertSource( sTmp, pEvent->Source ); + convertTarget( sTmp, pEvent->Source ); sTmp.append( '.' ); } @@ -1589,11 +1588,6 @@ void AnimationsExporterImpl::convertTiming( OUStringBuffer& sTmp, const Any& rVa } } -void AnimationsExporterImpl::convertSource( OUStringBuffer& sTmp, const Any& rSource ) const -{ - convertTarget( sTmp, rSource ); -} - void AnimationsExporterImpl::convertTarget( OUStringBuffer& sTmp, const Any& rTarget ) const { if( !rTarget.hasValue() ) diff --git a/xmloff/source/draw/sdxmlimp.cxx b/xmloff/source/draw/sdxmlimp.cxx index fa523c2..92d40d4 100644 --- a/xmloff/source/draw/sdxmlimp.cxx +++ b/xmloff/source/draw/sdxmlimp.cxx @@ -641,7 +641,7 @@ SvXMLImportContext *SdXMLImport::CreateMetaContext(const OUString& rLocalName, uno::Reference<document::XDocumentPropertiesSupplier> xDPS( GetModel(), uno::UNO_QUERY_THROW); uno::Reference<document::XDocumentProperties> const xDocProps( - (IsStylesOnlyMode()) ? nullptr : xDPS->getDocumentProperties()); + !mbLoadDoc ? nullptr : xDPS->getDocumentProperties()); pContext = new SvXMLMetaDocumentContext(*this, XML_NAMESPACE_OFFICE, rLocalName, xDocProps); diff --git a/xmloff/source/draw/sdxmlimp_impl.hxx b/xmloff/source/draw/sdxmlimp_impl.hxx index 1fc6e3e..06fe670 100644 --- a/xmloff/source/draw/sdxmlimp_impl.hxx +++ b/xmloff/source/draw/sdxmlimp_impl.hxx @@ -218,8 +218,6 @@ public: // Styles and AutoStyles contexts - bool IsStylesOnlyMode() const { return !mbLoadDoc; } - const SvXMLTokenMap& GetDocElemTokenMap(); const SvXMLTokenMap& GetBodyElemTokenMap(); const SvXMLTokenMap& GetStylesElemTokenMap(); diff --git a/xmloff/source/draw/shapeexport.cxx b/xmloff/source/draw/shapeexport.cxx index 504c4b9..0fd26d7 100644 --- a/xmloff/source/draw/shapeexport.cxx +++ b/xmloff/source/draw/shapeexport.cxx @@ -704,7 +704,7 @@ void XMLShapeExport::exportShape(const uno::Reference< drawing::XShape >& xShape } // export layer information - if( IsLayerExportEnabled() ) + if( mbExportLayer ) { // check for group or scene shape and not export layer if this is one uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY ); diff --git a/xmloff/source/draw/xexptran.cxx b/xmloff/source/draw/xexptran.cxx index f87f33d..925d796 100644 --- a/xmloff/source/draw/xexptran.cxx +++ b/xmloff/source/draw/xexptran.cxx @@ -224,13 +224,6 @@ struct ImpSdXMLExpTransObj2DMatrix : public ImpSdXMLExpTransObj2DBase : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_MATRIX), maMatrix(rNew) {} }; -// delete all entries in list - -void SdXMLImExTransform2D::EmptyList() -{ - maList.clear(); -} - // add members void SdXMLImExTransform2D::AddRotate(double fNew) @@ -357,7 +350,7 @@ const OUString& SdXMLImExTransform2D::GetExportString(const SvXMLUnitConverter& void SdXMLImExTransform2D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv) { msString = rNew; - EmptyList(); + maList.clear(); if(!msString.isEmpty()) { @@ -602,13 +595,6 @@ struct ImpSdXMLExpTransObj3DMatrix : public ImpSdXMLExpTransObj3DBase : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_MATRIX), maMatrix(rNew) {} }; -// delete all entries in list - -void SdXMLImExTransform3D::EmptyList() -{ - maList.clear(); -} - // add members void SdXMLImExTransform3D::AddMatrix(const ::basegfx::B3DHomMatrix& rNew) @@ -777,7 +763,7 @@ SdXMLImExTransform3D::SdXMLImExTransform3D(const OUString& rNew, const SvXMLUnit void SdXMLImExTransform3D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv) { msString = rNew; - EmptyList(); + maList.clear(); if(!msString.isEmpty()) { diff --git a/xmloff/source/text/XMLTextListBlockContext.cxx b/xmloff/source/text/XMLTextListBlockContext.cxx index 1637cf3..968b1f5 100644 --- a/xmloff/source/text/XMLTextListBlockContext.cxx +++ b/xmloff/source/text/XMLTextListBlockContext.cxx @@ -75,7 +75,7 @@ XMLTextListBlockContext::XMLTextListBlockContext( { XMLTextListBlockContext *pParent = static_cast<XMLTextListBlockContext *>(mxParentListBlock.get()); - msListStyleName = pParent->GetListStyleName(); + msListStyleName = pParent->msListStyleName; sParentListStyleName = msListStyleName; mxNumRules = pParent->GetNumRules(); mnLevel = pParent->GetLevel() + 1; diff --git a/xmloff/source/text/XMLTextListBlockContext.hxx b/xmloff/source/text/XMLTextListBlockContext.hxx index cd2fc69..eb46554 100644 --- a/xmloff/source/text/XMLTextListBlockContext.hxx +++ b/xmloff/source/text/XMLTextListBlockContext.hxx @@ -65,7 +65,6 @@ public: const OUString& rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > & xAttrList ) override; - const OUString& GetListStyleName() const { return msListStyleName; } sal_Int16 GetLevel() const { return mnLevel; } bool IsRestartNumbering() const { return mbRestartNumbering; } void ResetRestartNumbering() { mbRestartNumbering = false; } diff --git a/xmloff/source/transform/ChartPlotAreaOASISTContext.cxx b/xmloff/source/transform/ChartPlotAreaOASISTContext.cxx index e1eeb3b..8440b20 100644 --- a/xmloff/source/transform/ChartPlotAreaOASISTContext.cxx +++ b/xmloff/source/transform/ChartPlotAreaOASISTContext.cxx @@ -49,8 +49,6 @@ public: virtual void StartElement( const Reference< xml::sax::XAttributeList >& rAttrList ) override; virtual void EndElement() override; - bool IsCategoryAxis() const { return m_bHasCategories;} - private: ::rtl::Reference< XMLPersAttrListTContext > & m_rCategoriesContext; bool m_bHasCategories; @@ -155,7 +153,7 @@ void XMLAxisOASISContext::StartElement( void XMLAxisOASISContext::EndElement() { // if we have categories, change the "class" attribute - if( IsCategoryAxis() && + if( m_bHasCategories && m_rCategoriesContext.is() ) { OSL_ENSURE( GetAttrList().is(), "Invalid attribute list" ); diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx index a0db876..f5eb1d2 100644 --- a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx +++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx @@ -220,10 +220,6 @@ void SecurityEnvironment_NssImpl::addCryptoSlot( PK11SlotInfo* aSlot) throw( Exc m_Slots.push_back(aSlot); } -CERTCertDBHandle* SecurityEnvironment_NssImpl::getCertDb() throw( Exception , RuntimeException ) { - return m_pHandler ; -} - //Could we have multiple cert dbs? void SecurityEnvironment_NssImpl::setCertDb( CERTCertDBHandle* aCertDb ) throw( Exception , RuntimeException ) { m_pHandler = aCertDb ; @@ -909,7 +905,7 @@ xmlSecKeysMngrPtr SecurityEnvironment_NssImpl::createKeysManager() throw( Except SECKEYPrivateKey* priKey = nullptr ; xmlSecKeysMngrPtr pKeysMngr = nullptr ; - handler = this->getCertDb() ; + handler = m_pHandler; /*- * The following lines is based on the private version of xmlSec-NSS diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx index a6fa7a7..30394bb 100644 --- a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx +++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx @@ -105,9 +105,6 @@ private: static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId() ; - //Native methods - CERTCertDBHandle* getCertDb() throw( css::uno::Exception , css::uno::RuntimeException ) ; - void setCertDb( CERTCertDBHandle* aCertDb ) throw( css::uno::Exception , css::uno::RuntimeException ) ; void adoptSymKey( PK11SymKey* aSymKey ) throw( css::uno::Exception , css::uno::RuntimeException ) ; commit 281fa6ac6a7df48dd65f5019d5a74148a096e253 Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Mon Oct 17 15:34:04 2016 +0200 some cleanups to the unusedmethods loplugin - publicDefinitionSet is unnecessary, the python post-processor does not need it - remove the traversing of templates, clang will do that for us since we have set the shouldVisitTemplateInstantiations() method Change-Id: I0e96dad0b1cc941fe6c4a2e9227e86d8c3f1d85a diff --git a/compilerplugins/clang/inlineablemethods.cxx b/compilerplugins/clang/inlineablemethods.cxx index 3dd58d3..df98463 100644 --- a/compilerplugins/clang/inlineablemethods.cxx +++ b/compilerplugins/clang/inlineablemethods.cxx @@ -325,7 +325,7 @@ bool InlineableMethods::isCalleeFunctionInteresting(const FunctionDecl* function return true; } -loplugin::Plugin::Registration< InlineableMethods > X("inlineablemethods", true); +loplugin::Plugin::Registration< InlineableMethods > X("inlineablemethods", false); } diff --git a/compilerplugins/clang/unusedmethods.cxx b/compilerplugins/clang/unusedmethods.cxx index 3c5498d..80af024 100644 --- a/compilerplugins/clang/unusedmethods.cxx +++ b/compilerplugins/clang/unusedmethods.cxx @@ -12,6 +12,8 @@ #include <iostream> #include <fstream> #include <set> +#include <unordered_map> + #include "clang/AST/Attr.h" @@ -42,8 +44,6 @@ to auto-remove the method declarations Note that the actual process may involve a fair amount of undoing, hand editing, and general messing around to get it to work :-) -TODO deal with calls to superclass/member constructors from other constructors, so - we can find unused constructors */ namespace { @@ -69,8 +69,7 @@ static std::set<MyFuncInfo> callSet; static std::set<MyFuncInfo> definitionSet; // for the "unused return type" analysis static std::set<MyFuncInfo> usedReturnSet; -// for the "unnecessary public" analysis -static std::set<MyFuncInfo> publicDefinitionSet; +// for the "can be private" analysis static std::set<MyFuncInfo> calledFromOutsideSet; @@ -96,7 +95,7 @@ public: // for the "unused return type" analysis for (const MyFuncInfo & s : usedReturnSet) output += "usedReturn:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; - // for the "unnecessary public" analysis + // for the "method can be private" analysis for (const MyFuncInfo & s : calledFromOutsideSet) output += "outside:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; ofstream myfile; @@ -116,6 +115,8 @@ private: void logCallToRootMethods(const FunctionDecl* functionDecl, std::set<MyFuncInfo>& funcSet); MyFuncInfo niceName(const FunctionDecl* functionDecl); std::string fullyQualifiedName(const FunctionDecl* functionDecl); + std::string toString(SourceLocation loc); + void functionTouchedFromExpr( const FunctionDecl* calleeFunctionDecl, const Expr* expr ); }; MyFuncInfo UnusedMethods::niceName(const FunctionDecl* functionDecl) @@ -163,14 +164,20 @@ MyFuncInfo UnusedMethods::niceName(const FunctionDecl* functionDecl) aInfo.nameAndParams += " const"; } - 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)); - normalizeDotDotInFilePath(aInfo.sourceLocation); + aInfo.sourceLocation = toString( functionDecl->getLocation() ); return aInfo; } +std::string UnusedMethods::toString(SourceLocation loc) +{ + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( loc ); + StringRef name = compiler.getSourceManager().getFilename(expansionLoc); + std::string sourceLocation = std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + normalizeDotDotInFilePath(sourceLocation); + return sourceLocation; +} + std::string UnusedMethods::fullyQualifiedName(const FunctionDecl* functionDecl) { std::string ret = compat::getReturnType(*functionDecl).getCanonicalType().getAsString(); @@ -197,13 +204,13 @@ std::string UnusedMethods::fullyQualifiedName(const FunctionDecl* functionDecl) return ret; } +// For virtual/overriding methods, we need to pretend we called the root method(s), +// so that they get marked as used. void UnusedMethods::logCallToRootMethods(const FunctionDecl* functionDecl, std::set<MyFuncInfo>& funcSet) { functionDecl = functionDecl->getCanonicalDecl(); bool bCalledSuperMethod = false; if (isa<CXXMethodDecl>(functionDecl)) { - // For virtual/overriding methods, we need to pretend we called the root method(s), - // so that they get marked as used. const CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(functionDecl); for(CXXMethodDecl::method_iterator it = methodDecl->begin_overridden_methods(); it != methodDecl->end_overridden_methods(); ++it) @@ -222,9 +229,6 @@ void UnusedMethods::logCallToRootMethods(const FunctionDecl* functionDecl, std:: } } -// prevent recursive templates from blowing up the stack -static std::set<std::string> traversedFunctionSet; - bool UnusedMethods::VisitCallExpr(CallExpr* expr) { // Note that I don't ignore ANYTHING here, because I want to get calls to my code that result @@ -247,18 +251,11 @@ bool UnusedMethods::VisitCallExpr(CallExpr* expr) } 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. - // Rather than tracking all of that, just traverse anything we have not already traversed. - if (traversedFunctionSet.insert(fullyQualifiedName(calleeFunctionDecl)).second) - TraverseFunctionDecl(calleeFunctionDecl); - logCallToRootMethods(calleeFunctionDecl, callSet); const Stmt* parent = parentStmt(expr); - // Now do the checks necessary for the "unnecessary public" analysis + // Now do the checks necessary for the "can be private" analysis CXXMethodDecl* calleeMethodDecl = dyn_cast<CXXMethodDecl>(calleeFunctionDecl); if (calleeMethodDecl && calleeMethodDecl->getAccess() == AS_public) { @@ -304,6 +301,10 @@ bool UnusedMethods::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr const CXXConstructorDecl* constructorDecl = constructExpr->getConstructor(); constructorDecl = constructorDecl->getCanonicalDecl(); + if (!constructorDecl->getLocation().isValid() || ignoreLocation(constructorDecl)) { + return true; + } + logCallToRootMethods(constructorDecl, callSet); return true; @@ -311,16 +312,10 @@ bool UnusedMethods::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr bool UnusedMethods::VisitFunctionDecl( const FunctionDecl* functionDecl ) { - functionDecl = functionDecl->getCanonicalDecl(); - const CXXMethodDecl* methodDecl = dyn_cast_or_null<CXXMethodDecl>(functionDecl); - - // ignore method overrides, since the call will show up as being directed to the root method - if (methodDecl && (methodDecl->size_overridden_methods() != 0 || methodDecl->hasAttr<OverrideAttr>())) { - return true; - } + const FunctionDecl* canonicalFunctionDecl = functionDecl->getCanonicalDecl(); // ignore stuff that forms part of the stable URE interface if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( - functionDecl->getCanonicalDecl()->getNameInfo().getLoc()))) { + canonicalFunctionDecl->getNameInfo().getLoc()))) { return true; } if (isa<CXXDestructorDecl>(functionDecl)) { @@ -332,15 +327,17 @@ bool UnusedMethods::VisitFunctionDecl( const FunctionDecl* functionDecl ) if (isa<CXXConstructorDecl>(functionDecl) && dyn_cast<CXXConstructorDecl>(functionDecl)->isCopyConstructor()) { return true; } - - if( functionDecl->getLocation().isValid() && !ignoreLocation( functionDecl ) - && !functionDecl->isExternC()) - { - MyFuncInfo funcInfo = niceName(functionDecl); + if (!canonicalFunctionDecl->getLocation().isValid() || ignoreLocation(canonicalFunctionDecl)) { + return true; + } + // ignore method overrides, since the call will show up as being directed to the root method + const CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(functionDecl); + if (methodDecl && (methodDecl->size_overridden_methods() != 0 || methodDecl->hasAttr<OverrideAttr>())) { + return true; + } + if (!functionDecl->isExternC()) { + MyFuncInfo funcInfo = niceName(canonicalFunctionDecl); definitionSet.insert(funcInfo); - if (functionDecl->getAccess() == AS_public) { - publicDefinitionSet.insert(funcInfo); - } } return true; } @@ -348,12 +345,12 @@ bool UnusedMethods::VisitFunctionDecl( const FunctionDecl* functionDecl ) // this catches places that take the address of a method bool UnusedMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) { - const Decl* functionDecl = declRefExpr->getDecl(); - if (!isa<FunctionDecl>(functionDecl)) { + const FunctionDecl* functionDecl = dyn_cast<FunctionDecl>(declRefExpr->getDecl()); + if (!functionDecl) { return true; } - logCallToRootMethods(dyn_cast<FunctionDecl>(functionDecl)->getCanonicalDecl(), callSet); - logCallToRootMethods(dyn_cast<FunctionDecl>(functionDecl)->getCanonicalDecl(), usedReturnSet); + logCallToRootMethods(functionDecl->getCanonicalDecl(), callSet); + logCallToRootMethods(functionDecl->getCanonicalDecl(), usedReturnSet); return true; } diff --git a/compilerplugins/clang/unusedmethods.py b/compilerplugins/clang/unusedmethods.py index 41044d3..1e2a674 100755 --- a/compilerplugins/clang/unusedmethods.py +++ b/compilerplugins/clang/unusedmethods.py @@ -14,7 +14,7 @@ definitionToSourceLocationMap = dict() # for the "unused methods" analysis callSet = set() # set of tuple(return_type, name_and_params) -# for the "unnecessary public" analysis +# for the "method can be private" analysis publicDefinitionSet = set() # set of tuple(return_type, name_and_params) calledFromOutsideSet = set() # set of tuple(return_type, name_and_params) @@ -25,23 +25,6 @@ usedReturnSet = set() # set of tuple(return_type, name_and_params) # things we need to exclude for reasons like : # - it's a weird template thingy that confuses the plugin unusedMethodsExclusionSet = set([ - "double basegfx::DoubleTraits::maxVal()", - "double basegfx::DoubleTraits::minVal()", - "double basegfx::DoubleTraits::neutral()", - "int basegfx::Int32Traits::maxVal()", - "int basegfx::Int32Traits::minVal()", - "int basegfx::Int32Traits::neutral()", - "unsigned long UniqueIndexImpl::Insert(void *)", - "class XMLPropertyBackpatcher<short> & XMLTextImportHelper::GetFootnoteBP()", - "class XMLPropertyBackpatcher<short> & XMLTextImportHelper::GetSequenceIdBP()", - "void XclExpPivotCache::SaveXml(class XclExpXmlStream &)", - - - # TODO track instantiations of template class constructors - "void comphelper::IEventProcessor::release()", - "void SotMutexHolder::acquire()", - "void SotMutexHolder::release()", - # only used by Windows build "_Bool basegfx::B2ITuple::equalZero() const", "class basegfx::B2DPolyPolygon basegfx::unotools::UnoPolyPolygon::getPolyPolygonUnsafe() const", @@ -72,10 +55,6 @@ unusedMethodsExclusionSet = set([ "_Bool ScImportExport::ImportData(const class rtl::OUString &,const class com::sun::star::uno::Any &)", "void* ScannerManager::GetData()", "void ScannerManager::SetData(void *)", - # instantiated from templates, not sure why it is not being picked up - "class basegfx::B2DPolygon OutputDevice::PixelToLogic(const class basegfx::B2DPolygon &,const class MapMode &) const", - "type-parameter-0-0 * detail::cloner::clone(type-parameter-0-0 *const)", - "const class rtl::OUString writerperfect::DocumentHandlerFor::name()", # only used by OSX build "void StyleSettings::SetHideDisabledMenuItems(_Bool)", # debugging methods @@ -83,12 +62,6 @@ unusedMethodsExclusionSet = set([ "void oox::PropertyMap::dumpCode(class com::sun::star::uno::Reference<class com::sun::star::beans::XPropertySet>)", "void oox::PropertyMap::dumpData(class com::sun::star::uno::Reference<class com::sun::star::beans::XPropertySet>)", "class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char> > writerfilter::ooxml::OOXMLPropertySet::toString()", - # deep template magic in SW - "Ring<value_type> * sw::Ring::Ring_node_traits::get_next(const Ring<value_type> *)", - "Ring<value_type> * sw::Ring::Ring_node_traits::get_previous(const Ring<value_type> *)", - "void sw::Ring::Ring_node_traits::set_next(Ring<value_type> *,Ring<value_type> *)", - "void sw::Ring::Ring_node_traits::set_previous(Ring<value_type> *,Ring<value_type> *)", - "type-parameter-0-0 checking_cast(type-parameter-0-0,type-parameter-0-0)", # I need to teach the plugin that for loops with range expressions call begin() and end() "class __gnu_debug::_Safe_iterator<class __gnu_cxx::__normal_iterator<class SwAnchoredObject *const *, class std::__cxx1998::vector<class SwAnchoredObject *, class std::allocator<class SwAnchoredObject *> > >, class std::__debug::vector<class SwAnchoredObject *, class std::allocator<class SwAnchoredObject *> > > SwSortedObjs::begin() const", "class __gnu_debug::_Safe_iterator<class __gnu_cxx::__normal_iterator<class SwAnchoredObject *const *, class std::__cxx1998::vector<class SwAnchoredObject *, class std::allocator<class SwAnchoredObject *> > >, class std::__debug::vector<class SwAnchoredObject *, class std::allocator<class SwAnchoredObject *> > > SwSortedObjs::end() const", @@ -158,6 +131,8 @@ with io.open("loplugin.unusedmethods.log", "rb", buffering=1024*1024) as txt: returnType = tokens[1] nameAndParams = tokens[2] calledFromOutsideSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))) + else: + print( "unknown line: " + line) # Invert the definitionToSourceLocationMap. # If we see more than one method at the same sourceLocation, it's being autogenerated as part of a template @@ -283,7 +258,7 @@ for d in definitionSet: tmp1set.add((method, location)) # print out the results, sorted by name and line number -with open("loplugin.unusedmethods.report-methods", "wt") as f: +with open("loplugin.unusedmethods.report-unused-methods", "wt") as f: for t in sort_set_by_natural_key(tmp1set): f.write(t[1] + "\n") f.write(" " + t[0] + "\n") @@ -343,14 +318,14 @@ for d in definitionSet: tmp2set.add((method, location)) # print output, sorted by name and line number -with open("loplugin.unusedmethods.report-returns", "wt") as f: +with open("loplugin.unusedmethods.report-unused-returns", "wt") as f: for t in sort_set_by_natural_key(tmp2set): f.write(t[1] + "\n") f.write(" " + t[0] + "\n") # -------------------------------------------------------------------------------------------- -# "unnecessary public" analysis +# "method can be private" analysis # -------------------------------------------------------------------------------------------- tmp3set = set() @@ -366,10 +341,8 @@ for d in publicDefinitionSet: tmp3set.add((method, definitionToSourceLocationMap[d])) # print output, sorted by name and line number -with open("loplugin.unusedmethods.report-public", "wt") as f: +with open("loplugin.unusedmethods.report-can-be-private", "wt") as f: for t in sort_set_by_natural_key(tmp3set): f.write(t[1] + "\n") f.write(" " + t[0] + "\n") - - commit a18d92bca8ff50a34cacdd978467dc2c61f16f31 Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Mon Oct 17 15:21:00 2016 +0200 new loplugin inlineablemethods look for methods that are: (*) non-virtual (*) only called once (*) only called from inside their own class (*) small i.e. < 40 characters which are candidates for just having their code inlined Change-Id: I0e9e8125d140282cdcdd2a77374059b17b2fcd7d diff --git a/compilerplugins/clang/inlineablemethods.cxx b/compilerplugins/clang/inlineablemethods.cxx new file mode 100644 index 0000000..3dd58d3 --- /dev/null +++ b/compilerplugins/clang/inlineablemethods.cxx @@ -0,0 +1,332 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <cassert> +#include <string> +#include <iostream> +#include <fstream> +#include <set> +#include <unordered_map> + + +#include "clang/AST/Attr.h" + +#include "plugin.hxx" +#include "compat.hxx" + +/** + Methods that are only called from inside their own class, and are only called from one spot + + + TODO if a method has only one call-site, and that call site is inside a constructor + then it's probably worth inlining, since it's probably an old method that was intended to be shared amongst + multiple constructors +*/ + +namespace { + +struct MyFuncInfo +{ + std::string access; + std::string returnType; + std::string nameAndParams; + std::string sourceLocation; + +}; +bool operator < (const MyFuncInfo &lhs, const MyFuncInfo &rhs) +{ + return std::tie(lhs.returnType, lhs.nameAndParams) + < std::tie(rhs.returnType, rhs.nameAndParams); +} + +// try to limit the voluminous output a little + +static std::unordered_map<std::string, MyFuncInfo> calledFromMap; +static std::set<MyFuncInfo> definitionSet; +static std::set<MyFuncInfo> calledFromOutsideSet; +static std::set<MyFuncInfo> largeFunctionSet; +static std::set<MyFuncInfo> addressOfSet; + + +class InlineableMethods: + public RecursiveASTVisitor<InlineableMethods>, public loplugin::Plugin +{ +public: + explicit InlineableMethods(InstantiationData const & data): Plugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + // 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 MyFuncInfo & s : definitionSet) + output += "definition:\t" + s.access + "\t" + s.returnType + "\t" + s.nameAndParams + "\t" + s.sourceLocation + "\n"; + for (const MyFuncInfo & s : calledFromOutsideSet) + output += "outside:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; + for (const std::pair<std::string,MyFuncInfo> & s : calledFromMap) + output += "calledFrom:\t" + s.first + + "\t" + s.second.returnType + "\t" + s.second.nameAndParams + "\n"; + for (const MyFuncInfo & s : largeFunctionSet) + output += "large:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; + for (const MyFuncInfo & s : addressOfSet) + output += "addrof:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; + ofstream myfile; + myfile.open( SRCDIR "/loplugin.inlineablemethods.log", ios::app | ios::out); + myfile << output; + myfile.close(); + } + + bool shouldVisitTemplateInstantiations () const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitFunctionDecl( const FunctionDecl* ); + bool VisitDeclRefExpr( const DeclRefExpr* ); + bool VisitMemberExpr( const MemberExpr* ); + // interception methods for FunctionDecl and all its subclasses + bool TraverseFunctionDecl( FunctionDecl* ); + bool TraverseCXXMethodDecl( CXXMethodDecl* ); + bool TraverseCXXConstructorDecl( CXXConstructorDecl* ); + bool TraverseCXXConversionDecl( CXXConversionDecl* ); + bool TraverseCXXDestructorDecl( CXXDestructorDecl* ); + +private: + MyFuncInfo niceName(const FunctionDecl* functionDecl); + std::string toString(SourceLocation loc); + void functionTouchedFromExpr( const FunctionDecl* calleeFunctionDecl, const Expr* expr ); + bool isCalleeFunctionInteresting( const FunctionDecl* ); + void logCalledFrom(SourceLocation calleeSite, const FunctionDecl* functionDecl); + + // I use traverse and a member variable because I cannot find a reliable way of walking back up the AST tree using the parentStmt() stuff + // TODO doesn't cope with nested functions + const FunctionDecl* mpTraversingFunction = nullptr; +}; + +MyFuncInfo InlineableMethods::niceName(const FunctionDecl* functionDecl) +{ + if (functionDecl->getInstantiatedFromMemberFunction()) + functionDecl = functionDecl->getInstantiatedFromMemberFunction(); + else if (functionDecl->getClassScopeSpecializationPattern()) + functionDecl = functionDecl->getClassScopeSpecializationPattern(); +// workaround clang-3.5 issue +#if CLANG_VERSION >= 30600 + else if (functionDecl->getTemplateInstantiationPattern()) + functionDecl = functionDecl->getTemplateInstantiationPattern(); +#endif + + MyFuncInfo aInfo; + switch (functionDecl->getAccess()) + { + case AS_public: aInfo.access = "public"; break; + case AS_private: aInfo.access = "private"; break; + case AS_protected: aInfo.access = "protected"; break; + default: aInfo.access = "unknown"; break; + } + if (!isa<CXXConstructorDecl>(functionDecl)) { + aInfo.returnType = compat::getReturnType(*functionDecl).getCanonicalType().getAsString(); + } else { + aInfo.returnType = ""; + } + + if (isa<CXXMethodDecl>(functionDecl)) { + const CXXRecordDecl* recordDecl = dyn_cast<CXXMethodDecl>(functionDecl)->getParent(); + aInfo.nameAndParams += recordDecl->getQualifiedNameAsString(); + aInfo.nameAndParams += "::"; + } + aInfo.nameAndParams += functionDecl->getNameAsString() + "("; + bool bFirst = true; + for (const ParmVarDecl *pParmVarDecl : compat::parameters(*functionDecl)) { + if (bFirst) + bFirst = false; + else + aInfo.nameAndParams += ","; + aInfo.nameAndParams += pParmVarDecl->getType().getCanonicalType().getAsString(); + } + aInfo.nameAndParams += ")"; + if (isa<CXXMethodDecl>(functionDecl) && dyn_cast<CXXMethodDecl>(functionDecl)->isConst()) { + aInfo.nameAndParams += " const"; + } + + aInfo.sourceLocation = toString( functionDecl->getLocation() ); + + return aInfo; +} + +std::string InlineableMethods::toString(SourceLocation loc) +{ + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( loc ); + StringRef name = compiler.getSourceManager().getFilename(expansionLoc); + std::string sourceLocation = std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + normalizeDotDotInFilePath(sourceLocation); + return sourceLocation; +} + +bool InlineableMethods::VisitFunctionDecl( const FunctionDecl* functionDecl ) +{ + const FunctionDecl* canonicalFunctionDecl = functionDecl->getCanonicalDecl(); + if (!isCalleeFunctionInteresting(canonicalFunctionDecl)) { + return true; + } + definitionSet.insert(niceName(canonicalFunctionDecl)); + + if (functionDecl->doesThisDeclarationHaveABody()) { + bool bLargeFunction = false; + if (const CompoundStmt* compoundStmt = dyn_cast<CompoundStmt>(functionDecl->getBody())) { + if (compoundStmt->size() > 1) { + bLargeFunction = true; + } + if (!bLargeFunction) { + auto s1 = compiler.getSourceManager().getCharacterData(compoundStmt->getLBracLoc()); + auto s2 = compiler.getSourceManager().getCharacterData(compoundStmt->getRBracLoc()); + bLargeFunction = (s2 - s1) > 40; + // any function that uses a parameter more than once + if (!bLargeFunction) { + StringRef bodyText(s1, s2-s1); + for (const ParmVarDecl* param : compat::parameters(*functionDecl)) { + StringRef name = param->getName(); + if (name.empty()) + continue; + size_t idx = bodyText.find(name); + if (idx != StringRef::npos && bodyText.find(name, idx+1) != StringRef::npos) { + bLargeFunction = true; + break; + } + } + } + } + } + if (bLargeFunction) { + largeFunctionSet.insert(niceName(canonicalFunctionDecl)); + } + } + return true; +} + +bool InlineableMethods::TraverseFunctionDecl( FunctionDecl* p ) +{ + mpTraversingFunction = p; + bool ret = RecursiveASTVisitor::TraverseFunctionDecl(p); + mpTraversingFunction = nullptr; + return ret; +} +bool InlineableMethods::TraverseCXXMethodDecl( CXXMethodDecl* p ) +{ + mpTraversingFunction = p; + bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(p); + mpTraversingFunction = nullptr; + return ret; +} +bool InlineableMethods::TraverseCXXConstructorDecl( CXXConstructorDecl* p ) +{ + mpTraversingFunction = p; + bool ret = RecursiveASTVisitor::TraverseCXXConstructorDecl(p); + mpTraversingFunction = nullptr; + return ret; +} +bool InlineableMethods::TraverseCXXConversionDecl( CXXConversionDecl* p ) +{ + mpTraversingFunction = p; + bool ret = RecursiveASTVisitor::TraverseCXXConversionDecl(p); + mpTraversingFunction = nullptr; + return ret; +} +bool InlineableMethods::TraverseCXXDestructorDecl( CXXDestructorDecl* p ) +{ + mpTraversingFunction = p; + bool ret = RecursiveASTVisitor::TraverseCXXDestructorDecl(p); + mpTraversingFunction = nullptr; + return ret; +} + +bool InlineableMethods::VisitMemberExpr( const MemberExpr* memberExpr ) +{ + const FunctionDecl* functionDecl = dyn_cast<FunctionDecl>(memberExpr->getMemberDecl()); + if (functionDecl) { + functionTouchedFromExpr(functionDecl, memberExpr); + } + return true; +} + +bool InlineableMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) +{ + const FunctionDecl* functionDecl = dyn_cast<FunctionDecl>(declRefExpr->getDecl()); + if (functionDecl) { + functionTouchedFromExpr(functionDecl, declRefExpr); + } + return true; +} + +void InlineableMethods::functionTouchedFromExpr( const FunctionDecl* calleeFunctionDecl, const Expr* expr ) +{ + if (!mpTraversingFunction) { + return; + } + const FunctionDecl* canonicalFunctionDecl = calleeFunctionDecl->getCanonicalDecl(); + if (!isCalleeFunctionInteresting(canonicalFunctionDecl)) { + return; + } + + logCalledFrom(expr->getLocStart(), canonicalFunctionDecl); + + if (const UnaryOperator* unaryOp = dyn_cast_or_null<UnaryOperator>(parentStmt(expr))) { + if (unaryOp->getOpcode() == UO_AddrOf) { + addressOfSet.insert(niceName(canonicalFunctionDecl)); + } + } + + const CXXMethodDecl* calleeMethodDecl = dyn_cast<CXXMethodDecl>(calleeFunctionDecl); + const CXXMethodDecl* callsiteParentMethodDecl = dyn_cast<CXXMethodDecl>(mpTraversingFunction); + if (!callsiteParentMethodDecl + || calleeMethodDecl->getParent() != callsiteParentMethodDecl->getParent()) + { + calledFromOutsideSet.insert(niceName(canonicalFunctionDecl)); + } +} + +void InlineableMethods::logCalledFrom(SourceLocation calleeLoc, const FunctionDecl* functionDecl) +{ + functionDecl = functionDecl->getCanonicalDecl(); + while (functionDecl->getTemplateInstantiationPattern()) + functionDecl = functionDecl->getTemplateInstantiationPattern(); + calledFromMap.emplace(toString(calleeLoc), niceName(functionDecl)); +} + +bool InlineableMethods::isCalleeFunctionInteresting(const FunctionDecl* functionDecl) +{ + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( + functionDecl->getNameInfo().getLoc()))) { + return false; + } + if (isa<CXXDestructorDecl>(functionDecl)) { + return false; + } + if (functionDecl->isDeleted() || functionDecl->isDefaulted()) { + return false; + } + if (isa<CXXConstructorDecl>(functionDecl) && dyn_cast<CXXConstructorDecl>(functionDecl)->isCopyConstructor()) { + return false; + } + if (!functionDecl->getLocation().isValid() || ignoreLocation(functionDecl)) { + return false; + } + const CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(functionDecl); + if (!methodDecl || methodDecl->isVirtual()) { + return false; + } + return true; +} + +loplugin::Plugin::Registration< InlineableMethods > X("inlineablemethods", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/inlineablemethods.py b/compilerplugins/clang/inlineablemethods.py new file mode 100755 index 0000000..a9b75472 --- /dev/null +++ b/compilerplugins/clang/inlineablemethods.py @@ -0,0 +1,148 @@ +#!/usr/bin/python + +import sys +import re +import io + +# -------------------------------------------------------------------------------------------- +# globals +# -------------------------------------------------------------------------------------------- + +definitionSet = set() # set of tuple(return_type, name_and_params) +definitionToSourceLocationMap = dict() +calledFromDict = dict() +calledFromOutsideSet = set() +largeFunctionSet = set() # set of tuple(return_type, name_and_params) +addressOfSet = set() # set of tuple(return_type, name_and_params) + +# 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) + +# -------------------------------------------------------------------------------------------- +# primary input loop +# -------------------------------------------------------------------------------------------- + +# 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. +with io.open("loplugin.inlineablemethods.log", "rb", buffering=1024*1024) as txt: + for line in txt: + tokens = line.strip().split("\t") + if tokens[0] == "definition:": + access = tokens[1] + returnType = tokens[2] + nameAndParams = tokens[3] + sourceLocation = tokens[4] + funcInfo = (normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams)) + definitionSet.add(funcInfo) + definitionToSourceLocationMap[funcInfo] = sourceLocation + elif tokens[0] == "calledFrom:": + calleeLocation = tokens[1] + returnType = tokens[2] + nameAndParams = tokens[3] + funcInfo = (normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams)) + if not funcInfo in calledFromDict: + calledFromDict[funcInfo] = set() + calledFromDict[funcInfo].add(calleeLocation) + elif tokens[0] == "outside:": + returnType = tokens[1] + nameAndParams = tokens[2] + calledFromOutsideSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))) + elif tokens[0] == "large:": + returnType = tokens[1] + nameAndParams = tokens[2] + largeFunctionSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))) + elif tokens[0] == "addrof:": + returnType = tokens[1] + nameAndParams = tokens[2] + addressOfSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))) + else: + print( "unknown line: " + line) + +# Invert the definitionToSourceLocationMap. +# If we see more than one method at the same sourceLocation, it's being autogenerated as part of a template +# and we should just ignore it. +sourceLocationToDefinitionMap = {} +for k, v in definitionToSourceLocationMap.iteritems(): + sourceLocationToDefinitionMap[v] = sourceLocationToDefinitionMap.get(v, []) + sourceLocationToDefinitionMap[v].append(k) +for k, definitions in sourceLocationToDefinitionMap.iteritems(): + if len(definitions) > 1: + for d in definitions: + definitionSet.remove(d) + +def isOtherConstness( d, callSet ): + method = d[0] + " " + d[1] + # if this method is const, and there is a non-const variant of it, and the non-const variant is in use, then leave it alone + if d[0].startswith("const ") and d[1].endswith(" const"): + if ((d[0][6:],d[1][:-6]) in callSet): + return True + elif method.endswith(" const"): + method2 = method[:len(method)-6] # strip off " const" + if ((d[0],method2) in callSet): + return True + if method.endswith(" const") and ("::iterator" in method): + method2 = method[:len(method)-6] # strip off " const" + method2 = method2.replace("::const_iterator", "::iterator") + if ((d[0],method2) in callSet): + return True + # if this method is non-const, and there is a const variant of it, and the const variant is in use, then leave it alone + if (not method.endswith(" const")) and ((d[0],"const " + method + " const") in callSet): + return True + if (not method.endswith(" const")) and ("::iterator" in method): + method2 = method.replace("::iterator", "::const_iterator") + " const" + if ((d[0],method2) in callSet): + return True + return False + +# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +def sort_set_by_natural_key(s): + return sorted(s, key=lambda v: natural_sort_key(v[1])) + + +# -------------------------------------------------------------------------------------------- +# Methods that are only called from inside their own class, and are only called from one spot +# -------------------------------------------------------------------------------------------- + +tmp4set = set() +for d in definitionSet: + if d in calledFromOutsideSet: + continue + if isOtherConstness(d, calledFromOutsideSet): + continue + if d not in definitionToSourceLocationMap: + print("warning, method has no location: " + d[0] + " " + d[1]) + continue + # ignore external code + if definitionToSourceLocationMap[d].startswith("external/"): + continue + # ignore constructors, calledFromOutsideSet does not provide accurate info for them + tokens = d[1].split("(")[0].split("::") + if len(tokens)>1 and tokens[-2] == tokens[-1]: + continue + # ignore large methods, which make the code clearer by being out of line + if d in largeFunctionSet: + continue + # ignore methods whose address we take + if d in addressOfSet: + continue + # ignore unused methods, leave them to the dedicated analysis + if d not in calledFromDict: + continue + # ignore methods called from more than one site + if len(calledFromDict[d]) > 1: + continue + + method = d[0] + " " + d[1] + tmp4set.add((method, definitionToSourceLocationMap[d])) + +# print output, sorted by name and line number +with open("loplugin.inlineablemethods.report", "wt") as f: + for t in sort_set_by_natural_key(tmp4set): + f.write(t[1] + "\n") + f.write(" " + t[0] + "\n") _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits