[Libreoffice-commits] core.git: compilerplugins/clang xmlhelp/source xmlsecurity/source

Noel Grandin noel at peralex.com
Tue Mar 8 07:05:20 UTC 2016


 compilerplugins/clang/constantparam.cxx             |  215 ++++++++++++++++++++
 compilerplugins/clang/constantparam.py              |   61 +++++
 xmlhelp/source/cxxhelp/provider/urlparameter.cxx    |    6 
 xmlhelp/source/cxxhelp/provider/urlparameter.hxx    |    2 
 xmlsecurity/source/framework/saxeventkeeperimpl.cxx |   15 -
 xmlsecurity/source/framework/saxeventkeeperimpl.hxx |    3 
 6 files changed, 284 insertions(+), 18 deletions(-)

New commits:
commit b4fda7b3f9cf928f45baf6846dd70e97cdb9904a
Author: Noel Grandin <noel at peralex.com>
Date:   Tue Mar 8 09:04:18 2016 +0200

    new loplugin:constantparam
    
    finds parameters that are only ever being called with a single value
    
    Change-Id: Ibd0c9b6e6dbc1d1b5d5a005eaa19959560a6e50f

diff --git a/compilerplugins/clang/constantparam.cxx b/compilerplugins/clang/constantparam.cxx
new file mode 100644
index 0000000..6726836
--- /dev/null
+++ b/compilerplugins/clang/constantparam.cxx
@@ -0,0 +1,215 @@
+/* -*- 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 <string>
+#include <set>
+#include <iostream>
+#include <fstream>
+
+#include "plugin.hxx"
+#include "compat.hxx"
+
+/*
+ Find methods with default params, where the callers never specify the default param i.e.
+ might as well remove it.
+
+ The process goes something like this:
+  $ make check
+  $ make FORCE_COMPILE_ALL=1 COMPILER_PLUGIN_TOOL='unuseddefaultparams' check
+  $ ./compilerplugins/clang/unuseddefaultparams.py unuseddefaultparams.log
+*/
+
+namespace {
+
+struct MyCallSiteInfo
+{
+    std::string returnType;
+    std::string nameAndParams;
+    std::string paramName;
+    std::string callValue;
+    std::string sourceLocation;
+};
+bool operator < (const MyCallSiteInfo &lhs, const MyCallSiteInfo &rhs)
+{
+    if (lhs.sourceLocation < rhs.sourceLocation)
+        return true;
+    else if (lhs.sourceLocation > rhs.sourceLocation)
+        return false;
+    else return lhs.callValue < rhs.callValue;
+}
+
+
+// try to limit the voluminous output a little
+static std::set<MyCallSiteInfo> callSet;
+
+class ConstantParam:
+    public RecursiveASTVisitor<ConstantParam>, public loplugin::Plugin
+{
+public:
+    explicit ConstantParam(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 MyCallSiteInfo & s : callSet)
+            output += s.returnType + "\t" + s.nameAndParams + "\t" + s.sourceLocation + "\t"
+                        + s.paramName + "\t" + s.callValue + "\n";
+        ofstream myfile;
+        myfile.open( SRCDIR "/constantparam.log", ios::app | ios::out);
+        myfile << output;
+        myfile.close();
+    }
+
+    bool shouldVisitTemplateInstantiations () const { return true; }
+
+    bool VisitCallExpr(CallExpr * callExpr);
+    bool VisitDeclRefExpr( const DeclRefExpr* declRefExpr );
+private:
+    MyCallSiteInfo niceName(const FunctionDecl* functionDecl, const ParmVarDecl* parmVarDecl, const std::string& callValue);
+};
+
+MyCallSiteInfo ConstantParam::niceName(const FunctionDecl* functionDecl, const ParmVarDecl* parmVarDecl, const std::string& callValue)
+{
+    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
+
+    MyCallSiteInfo aInfo;
+    aInfo.returnType = compat::getReturnType(*functionDecl).getCanonicalType().getAsString();
+
+    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 : functionDecl->params()) {
+        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.paramName = parmVarDecl->getName();
+    aInfo.callValue = callValue;
+
+    SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( functionDecl->getLocation() );
+    StringRef name = compiler.getSourceManager().getFilename(expansionLoc);
+    aInfo.sourceLocation = std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc));
+
+    return aInfo;
+}
+
+bool ConstantParam::VisitCallExpr(CallExpr * callExpr) {
+    if (ignoreLocation(callExpr)) {
+        return true;
+    }
+    const FunctionDecl* functionDecl;
+    if (isa<CXXMemberCallExpr>(callExpr)) {
+        functionDecl = dyn_cast<CXXMemberCallExpr>(callExpr)->getMethodDecl();
+    }
+    else {
+        functionDecl = callExpr->getDirectCallee();
+    }
+    if (functionDecl == nullptr) {
+        return true;
+    }
+    functionDecl = functionDecl->getCanonicalDecl();
+    // method overrides don't always specify the same default params (althogh they probably should)
+    // so we need to work our way up to the root method
+    while (isa<CXXMethodDecl>(functionDecl)) {
+        const CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(functionDecl);
+        if (methodDecl->size_overridden_methods()==0)
+            break;
+        functionDecl = *methodDecl->begin_overridden_methods();
+    }
+    // work our way back to the root definition for template methods
+    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
+
+    // ignore stuff that forms part of the stable URE interface
+    if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(
+                              functionDecl->getNameInfo().getLoc()))) {
+        return true;
+    }
+    if (functionDecl->getNameInfo().getLoc().isValid() && ignoreLocation(functionDecl)) {
+        return true;
+    }
+
+    for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) {
+        if (i >= functionDecl->getNumParams()) // can happen in template code
+            break;
+        Expr* arg = callExpr->getArg(i);
+        bool found = false;
+        std::string callValue;
+        // ignore this, it seems to trigger an infinite recursion
+        if (isa<UnaryExprOrTypeTraitExpr>(arg->IgnoreParenCasts())) {
+            found = true;
+            callValue = "unknown";
+        }
+        if (!found)
+        {
+            APSInt x1;
+            if (arg->EvaluateAsInt(x1, compiler.getASTContext()))
+            {
+                found = true;
+                callValue = x1.toString(10);
+            }
+        }
+        if (!found)
+            callValue = "unknown";
+        const ParmVarDecl* parmVarDecl = functionDecl->getParamDecl(i);
+        MyCallSiteInfo funcInfo = niceName(functionDecl, parmVarDecl, callValue);
+        callSet.insert(funcInfo);
+        break;
+    }
+    return true;
+}
+
+// this catches places that take the address of a method
+bool ConstantParam::VisitDeclRefExpr( const DeclRefExpr* declRefExpr )
+{
+    const Decl* functionDecl = declRefExpr->getDecl();
+    if (!isa<FunctionDecl>(functionDecl)) {
+        return true;
+    }
+// TODO
+//    MyCallSiteInfo funcInfo = niceName(dyn_cast<FunctionDecl>(functionDecl));
+//    callSet.insert(funcInfo);
+    return true;
+}
+
+loplugin::Plugin::Registration< ConstantParam > X("constantparam", false);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/compilerplugins/clang/constantparam.py b/compilerplugins/clang/constantparam.py
new file mode 100755
index 0000000..a23be74
--- /dev/null
+++ b/compilerplugins/clang/constantparam.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+
+import sys
+import re
+import io
+
+definitionSet = set()
+definitionToSourceLocationMap = dict()
+callParamSet = dict()
+
+# things we need to exclude for reasons like :
+# - it's a weird template thingy that confuses the plugin
+exclusionSet = set([
+])
+
+# 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.
+with io.open(sys.argv[1], "rb", buffering=1024*1024) as txt:
+    for line in txt:
+            idx1 = line.find("\t")
+            idx2 = line.find("\t",idx1+1)
+            idx3 = line.find("\t",idx2+1)
+            idx4 = line.find("\t",idx3+1)
+            returnType = line[:idx1]
+            nameAndParams = line[idx1+1:idx2]
+            sourceLocation = line[idx2+1:idx3]
+            paramName = line[idx3+1:idx4]
+            callValue = line[idx4+1:].strip()
+            callInfo = (normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams), paramName)
+            if callInfo in callParamSet:
+                callParamSet[callInfo].add(callValue)
+            else:
+                callParamSet[callInfo] = set([callValue])
+            definitionToSourceLocationMap[callInfo] = sourceLocation
+
+tmp1set = set()
+for callInfo, callValues in callParamSet.iteritems():
+    if len(callValues) == 1 and "unknown" not in callValues and ("0" in callValues or "1" in callValues or "nullptr" in callValues):
+        v1 = (" ".join(callInfo)) + " " + (",".join(callValues))
+        v2 = definitionToSourceLocationMap[callInfo]
+        tmp1set.add((v1,v2))
+
+# sort results by name and line number
+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)]
+tmp1list = sorted(tmp1set, key=lambda v: natural_sort_key(v[1]))
+
+# print out the results
+with open("unused.constantparams", "wt") as f:
+    for t in tmp1list:
+        f.write(t[1] + "\n")
+        f.write("    " + t[0] + "\n")
+
+
diff --git a/xmlhelp/source/cxxhelp/provider/urlparameter.cxx b/xmlhelp/source/cxxhelp/provider/urlparameter.cxx
index b2c3da0..cbb49ef 100644
--- a/xmlhelp/source/cxxhelp/provider/urlparameter.cxx
+++ b/xmlhelp/source/cxxhelp/provider/urlparameter.cxx
@@ -84,7 +84,7 @@ URLParameter::URLParameter( const OUString& aURL,
     : m_pDatabases( pDatabases ),
       m_aURL( aURL )
 {
-    init( false );
+    init();
     parse();
 }
 
@@ -196,10 +196,8 @@ OUString URLParameter::get_program()
 }
 
 
-void URLParameter::init( bool bDefaultLanguageIsInitialized )
+void URLParameter::init()
 {
-    (void)bDefaultLanguageIsInitialized;
-
     m_bHelpDataFileRead = false;
     m_bStart = false;
     m_bUseDB = true;
diff --git a/xmlhelp/source/cxxhelp/provider/urlparameter.hxx b/xmlhelp/source/cxxhelp/provider/urlparameter.hxx
index 13bdff6..044b922 100644
--- a/xmlhelp/source/cxxhelp/provider/urlparameter.hxx
+++ b/xmlhelp/source/cxxhelp/provider/urlparameter.hxx
@@ -212,7 +212,7 @@ namespace chelp {
 
         // private methods
 
-        void init( bool bDefaultLanguageIsInitialized );
+        void init();
 
         OUString get_the_tag();
 
diff --git a/xmlsecurity/source/framework/saxeventkeeperimpl.cxx b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx
index 036b541..492e23e 100644
--- a/xmlsecurity/source/framework/saxeventkeeperimpl.cxx
+++ b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx
@@ -855,7 +855,6 @@ void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId)
 }
 
 sal_Int32 SAXEventKeeperImpl::createElementCollector(
-    sal_Int32 nSecurityId,
     cssxc::sax::ElementMarkPriority nPriority,
     bool bModifyElement,
     const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
@@ -875,7 +874,6 @@ sal_Int32 SAXEventKeeperImpl::createElementCollector(
  *  Add the new created ElementCollector to the new ElementCollecotor list.
  *
  *   INPUTS
- *  nSecurityId -   the security Id of the new ElementCollector
  *  nPriority -     the priority of the new ElementCollector
  *  bModifyElement -whether this BufferNode will modify the content of
  *                  the corresponding element it works on
@@ -894,7 +892,7 @@ sal_Int32 SAXEventKeeperImpl::createElementCollector(
 
     ElementCollector* pElementCollector
         = new ElementCollector(
-            nSecurityId,
+            cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
             nId,
             nPriority,
             bModifyElement,
@@ -911,7 +909,7 @@ sal_Int32 SAXEventKeeperImpl::createElementCollector(
 }
 
 
-sal_Int32 SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId)
+sal_Int32 SAXEventKeeperImpl::createBlocker()
 /****** SAXEventKeeperImpl/createBlocker *************************************
  *
  *   NAME
@@ -923,9 +921,6 @@ sal_Int32 SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId)
  *   FUNCTION
  *  see NAME.
  *
- *   INPUTS
- *  nSecurityId -   the security Id of the new Blocker
- *
  *   RESULT
  *  nId - the Id of the new Blocker
  *
@@ -939,7 +934,7 @@ sal_Int32 SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId)
 
     OSL_ASSERT(m_pNewBlocker == nullptr);
 
-    m_pNewBlocker = new ElementMark(nSecurityId, nId);
+    m_pNewBlocker = new ElementMark(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, nId);
     m_vElementMarkBuffers.push_back( m_pNewBlocker );
 
     return nId;
@@ -950,7 +945,6 @@ sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector(  )
     throw (cssu::RuntimeException, std::exception)
 {
     return createElementCollector(
-        cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
         cssxc::sax::ElementMarkPriority_AFTERMODIFY,
         false,
         nullptr);
@@ -965,7 +959,7 @@ void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id )
 sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker(  )
     throw (cssu::RuntimeException, std::exception)
 {
-    return createBlocker(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID);
+    return createBlocker();
 }
 
 void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
@@ -1071,7 +1065,6 @@ sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
     throw (cssu::RuntimeException, std::exception)
 {
     return createElementCollector(
-        cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
         priority,
         modifyElement,
         nullptr);
diff --git a/xmlsecurity/source/framework/saxeventkeeperimpl.hxx b/xmlsecurity/source/framework/saxeventkeeperimpl.hxx
index 52fd955..f191583 100644
--- a/xmlsecurity/source/framework/saxeventkeeperimpl.hxx
+++ b/xmlsecurity/source/framework/saxeventkeeperimpl.hxx
@@ -213,14 +213,13 @@ private:
     void markElementMarkBuffer(sal_Int32 nId);
 
     sal_Int32 createElementCollector(
-        sal_Int32 nSecurityId,
         com::sun::star::xml::crypto::sax::ElementMarkPriority nPriority,
         bool bModifyElement,
         const com::sun::star::uno::Reference<
             com::sun::star::xml::crypto::sax::XReferenceResolvedListener>&
             xReferenceResolvedListener);
 
-    sal_Int32 createBlocker(sal_Int32 nSecurityId);
+    sal_Int32 createBlocker();
 
 public:
     SAXEventKeeperImpl();


More information about the Libreoffice-commits mailing list