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

Stephan Bergmann sbergman at redhat.com
Tue Jun 28 20:34:25 UTC 2016


 compilerplugins/clang/badstatics.cxx             |    2 
 compilerplugins/clang/check.cxx                  |  106 +++++++++++
 compilerplugins/clang/check.hxx                  |  211 +++++++++++++++++++++++
 compilerplugins/clang/fpcomparison.cxx           |   54 +++--
 compilerplugins/clang/getimplementationname.cxx  |    2 
 compilerplugins/clang/implicitboolconversion.cxx |    2 
 compilerplugins/clang/passstuffbyref.cxx         |   27 +-
 compilerplugins/clang/refcounting.cxx            |   10 -
 compilerplugins/clang/salbool.cxx                |    2 
 compilerplugins/clang/staticmethods.cxx          |    2 
 compilerplugins/clang/stringconstant.cxx         |    2 
 compilerplugins/clang/typecheck.cxx              |   96 ----------
 compilerplugins/clang/typecheck.hxx              |  162 -----------------
 compilerplugins/clang/weakobject.cxx             |    2 
 14 files changed, 381 insertions(+), 299 deletions(-)

New commits:
commit 0d3738a2580d72b778547bfcdf691fdeb0eccbdd
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Tue Jun 28 18:54:31 2016 +0200

    More Clang 3.4 "(anonymous namespace)" fixes
    
    Change-Id: I7cb43f915565dadd611b90ee30373e472f97efb5
    Reviewed-on: https://gerrit.libreoffice.org/26748
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>
    Tested-by: Stephan Bergmann <sbergman at redhat.com>

diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx
index aa50241..f316b4d 100644
--- a/compilerplugins/clang/badstatics.cxx
+++ b/compilerplugins/clang/badstatics.cxx
@@ -7,8 +7,8 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include "check.hxx"
 #include "plugin.hxx"
-#include "typecheck.hxx"
 
 namespace {
 
diff --git a/compilerplugins/clang/typecheck.cxx b/compilerplugins/clang/check.cxx
similarity index 83%
rename from compilerplugins/clang/typecheck.cxx
rename to compilerplugins/clang/check.cxx
index c293b57..c66a902 100644
--- a/compilerplugins/clang/typecheck.cxx
+++ b/compilerplugins/clang/check.cxx
@@ -7,8 +7,10 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include <cassert>
+
+#include "check.hxx"
 #include "compat.hxx"
-#include "typecheck.hxx"
 
 namespace loplugin {
 
@@ -72,7 +74,15 @@ TypeCheck TypeCheck::NotSubstTemplateTypeParmType() const {
         ? *this : TypeCheck();
 }
 
-TerminalCheck NamespaceCheck::GlobalNamespace() const {
+ContextCheck DeclCheck::Operator(clang::OverloadedOperatorKind op) const {
+    assert(op != clang::OO_None);
+    auto f = llvm::dyn_cast_or_null<clang::FunctionDecl>(decl_);
+    return ContextCheck(
+        f != nullptr && f->getOverloadedOperator() == op
+        ? f->getDeclContext() : nullptr);
+}
+
+TerminalCheck ContextCheck::GlobalNamespace() const {
     return TerminalCheck(
         context_ != nullptr
         && ((compat::isLookupContext(*context_)
@@ -80,14 +90,14 @@ TerminalCheck NamespaceCheck::GlobalNamespace() const {
             ->isTranslationUnit()));
 }
 
-TerminalCheck NamespaceCheck::StdNamespace() const {
+TerminalCheck ContextCheck::StdNamespace() const {
     return TerminalCheck(
         context_ != nullptr && compat::isStdNamespace(*context_));
 }
 
-NamespaceCheck NamespaceCheck::AnonymousNamespace() const {
+ContextCheck ContextCheck::AnonymousNamespace() const {
     auto n = llvm::dyn_cast_or_null<clang::NamespaceDecl>(context_);
-    return NamespaceCheck(
+    return ContextCheck(
         n != nullptr && n->isAnonymousNamespace() ? n->getParent() : nullptr);
 }
 
diff --git a/compilerplugins/clang/typecheck.hxx b/compilerplugins/clang/check.hxx
similarity index 53%
rename from compilerplugins/clang/typecheck.hxx
rename to compilerplugins/clang/check.hxx
index b3417bf..8381aec 100644
--- a/compilerplugins/clang/typecheck.hxx
+++ b/compilerplugins/clang/check.hxx
@@ -7,23 +7,24 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#ifndef INCLUDED_COMPILERPLUGINS_CLANG_TYPECHECK_HXX
-#define INCLUDED_COMPILERPLUGINS_CLANG_TYPECHECK_HXX
+#ifndef INCLUDED_COMPILERPLUGINS_CLANG_CHECK_HXX
+#define INCLUDED_COMPILERPLUGINS_CLANG_CHECK_HXX
 
 #include <cstddef>
 
 #include <clang/AST/DeclBase.h>
 #include <clang/AST/Decl.h>
 #include <clang/AST/Type.h>
+#include <clang/Basic/OperatorKinds.h>
 
 namespace loplugin {
 
-class NamespaceCheck;
+class ContextCheck;
 class TerminalCheck;
 
 namespace detail {
 
-template<std::size_t N> NamespaceCheck checkRecordDecl(
+template<std::size_t N> ContextCheck checkRecordDecl(
     clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N]);
 
 }
@@ -44,7 +45,7 @@ public:
 
     TypeCheck LvalueReference() const;
 
-    template<std::size_t N> inline NamespaceCheck Class(char const (& id)[N])
+    template<std::size_t N> inline ContextCheck Class(char const (& id)[N])
         const;
 
     TypeCheck NotSubstTemplateTypeParmType() const;
@@ -55,50 +56,65 @@ private:
     clang::QualType const type_;
 };
 
-class NamespaceCheck {
+class DeclCheck {
+public:
+    explicit DeclCheck(clang::Decl const * decl): decl_(decl) {}
+
+    explicit operator bool() const { return decl_ != nullptr; }
+
+    template<std::size_t N> inline ContextCheck Class(char const (& id)[N])
+        const;
+
+    template<std::size_t N> inline ContextCheck Struct(char const (& id)[N])
+        const;
+
+    template<std::size_t N> inline ContextCheck Function(char const (& id)[N])
+        const;
+
+    ContextCheck Operator(clang::OverloadedOperatorKind op) const;
+
+private:
+    clang::Decl const * const decl_;
+};
+
+class ContextCheck {
 public:
     explicit operator bool() const { return context_ != nullptr; }
 
     TerminalCheck GlobalNamespace() const;
 
-    template<std::size_t N> inline NamespaceCheck Namespace(
+    template<std::size_t N> inline ContextCheck Namespace(
         char const (& id)[N]) const;
 
     TerminalCheck StdNamespace() const;
 
-    NamespaceCheck AnonymousNamespace() const;
+    ContextCheck AnonymousNamespace() const;
+
+    template<std::size_t N> inline ContextCheck Class(char const (& id)[N])
+        const;
+
+    template<std::size_t N> inline ContextCheck Struct(char const (& id)[N])
+        const;
 
 private:
+    friend DeclCheck;
     friend TypeCheck;
-    template<std::size_t N> friend NamespaceCheck detail::checkRecordDecl(
+    template<std::size_t N> friend ContextCheck detail::checkRecordDecl(
         clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N]);
 
-    explicit NamespaceCheck(clang::DeclContext const * context = nullptr):
+    explicit ContextCheck(clang::DeclContext const * context = nullptr):
         context_(context) {}
 
     clang::DeclContext const * const context_;
 };
 
-class DeclCheck {
-public:
-    explicit DeclCheck(clang::Decl const * decl): decl_(decl) {}
-
-    explicit operator bool() const { return decl_ != nullptr; }
-
-    template<std::size_t N> inline NamespaceCheck Struct(char const (& id)[N])
-        const;
-
-private:
-    clang::Decl const * const decl_;
-};
-
 class TerminalCheck {
 public:
     explicit operator bool() const { return satisfied_; }
 
 private:
+    friend ContextCheck;
     friend TypeCheck;
-    friend NamespaceCheck;
 
     explicit TerminalCheck(bool satisfied): satisfied_(satisfied) {}
 
@@ -107,22 +123,22 @@ private:
 
 namespace detail {
 
-template<std::size_t N> NamespaceCheck checkRecordDecl(
+template<std::size_t N> ContextCheck checkRecordDecl(
     clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N])
 {
     auto r = llvm::dyn_cast_or_null<clang::RecordDecl>(decl);
     if (r != nullptr && r->getTagKind() == tag) {
         auto const i = r->getIdentifier();
         if (i != nullptr && i->isStr(id)) {
-            return NamespaceCheck(r->getDeclContext());
+            return ContextCheck(r->getDeclContext());
         }
     }
-    return NamespaceCheck();
+    return ContextCheck();
 }
 
 }
 
-template<std::size_t N> NamespaceCheck TypeCheck::Class(char const (& id)[N])
+template<std::size_t N> ContextCheck TypeCheck::Class(char const (& id)[N])
     const
 {
     if (!type_.isNull()) {
@@ -131,10 +147,35 @@ template<std::size_t N> NamespaceCheck TypeCheck::Class(char const (& id)[N])
             return detail::checkRecordDecl(t->getDecl(), clang::TTK_Class, id);
         }
     }
-    return NamespaceCheck();
+    return ContextCheck();
+}
+
+template<std::size_t N> ContextCheck DeclCheck::Class(char const (& id)[N])
+    const
+{
+    return detail::checkRecordDecl(decl_, clang::TTK_Class, id);
 }
 
-template<std::size_t N> NamespaceCheck NamespaceCheck::Namespace(
+template<std::size_t N> ContextCheck DeclCheck::Struct(char const (& id)[N])
+    const
+{
+    return detail::checkRecordDecl(decl_, clang::TTK_Struct, id);
+}
+
+template<std::size_t N> ContextCheck DeclCheck::Function(char const (& id)[N])
+    const
+{
+    auto f = llvm::dyn_cast_or_null<clang::FunctionDecl>(decl_);
+    if (f != nullptr) {
+        auto const i = f->getIdentifier();
+        if (i != nullptr && i->isStr(id)) {
+            return ContextCheck(f->getDeclContext());
+        }
+    }
+    return ContextCheck();
+}
+
+template<std::size_t N> ContextCheck ContextCheck::Namespace(
     char const (& id)[N]) const
 {
     if (context_) {
@@ -142,17 +183,25 @@ template<std::size_t N> NamespaceCheck NamespaceCheck::Namespace(
         if (n != nullptr) {
             auto const i = n->getIdentifier();
             if (i != nullptr && i->isStr(id)) {
-                return NamespaceCheck(n->getParent());
+                return ContextCheck(n->getParent());
             }
         }
     }
-    return NamespaceCheck();
+    return ContextCheck();
 }
 
-template<std::size_t N> NamespaceCheck DeclCheck::Struct(char const (& id)[N])
+template<std::size_t N> ContextCheck ContextCheck::Class(char const (& id)[N])
     const
 {
-    return detail::checkRecordDecl(decl_, clang::TTK_Struct, id);
+    return detail::checkRecordDecl(
+        llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Class, id);
+}
+
+template<std::size_t N> ContextCheck ContextCheck::Struct(char const (& id)[N])
+    const
+{
+    return detail::checkRecordDecl(
+        llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Struct, id);
 }
 
 }
diff --git a/compilerplugins/clang/fpcomparison.cxx b/compilerplugins/clang/fpcomparison.cxx
index 491eb80..63d69c1 100644
--- a/compilerplugins/clang/fpcomparison.cxx
+++ b/compilerplugins/clang/fpcomparison.cxx
@@ -12,8 +12,10 @@
 #include <iostream>
 #include <fstream>
 #include <set>
-#include "plugin.hxx"
+
+#include "check.hxx"
 #include "compat.hxx"
+#include "plugin.hxx"
 
 /**
 comparing floating point numbers using == or != is a bad idea.
@@ -40,25 +42,6 @@ private:
     EState meState = EState::None;
 };
 
-const std::set<std::string> whitelist {
-    "rtl::math::approxEqual",
-    "(anonymous namespace)::doubleToString",
-    "(anonymous namespace)::stringToDouble",
-    "rtl_math_round",
-    "rtl_math_approxValue",
-    "rtl_math_asinh",
-    "rtl_math_acosh",
-    "cppu::_equalSequence", // cppu/source/uno/eq.hxx
-    "cppu::_equalData", // cppu/source/uno/eq.hxx
-    "xmlscript::equalFont", // xmlscript/source/xmldlg_imexp/xmldlg_export.cxx
-
-    // these might need fixing
-    "basegfx::tools::getSmallestDistancePointToPolygon", // basegfx/source/polygon/b2dpolygontools.cxx
-    "basegfx::tools::getSmallestDistancePointToPolyPolygon", // basegfx/source/polygon/b2dpolypolygontools.cxx
-    "bridge_test::performTest", // testtools/source/bridgetest/bridgetest.cxx
-    "bridge_test::equals",
-    "(anonymous namespace)::lcl_getNANInsteadDBL_MIN", // chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx
-};
 bool FpComparison::TraverseFunctionDecl(FunctionDecl* function)
 {
     bool bIgnore = ignore(function);
@@ -87,8 +70,35 @@ bool FpComparison::ignore(FunctionDecl* function)
         return true;
     }
     // ignore known good functions
-    std::string s = function->getQualifiedNameAsString();
-    if (whitelist.find(s) != whitelist.end()) {
+    loplugin::DeclCheck dc(function);
+    if ((dc.Function("approxEqual").Namespace("math").Namespace("rtl")
+         .GlobalNamespace())
+        || dc.Function("doubleToString").AnonymousNamespace().GlobalNamespace()
+        || dc.Function("stringToDouble").AnonymousNamespace().GlobalNamespace()
+        || dc.Function("rtl_math_round").GlobalNamespace()
+        || dc.Function("rtl_math_approxValue").GlobalNamespace()
+        || dc.Function("rtl_math_asinh").GlobalNamespace()
+        || dc.Function("rtl_math_acosh").GlobalNamespace()
+        || dc.Function("_equalSequence").Namespace("cppu").GlobalNamespace()
+            // cppu/source/uno/eq.hxx
+        || dc.Function("_equalData").Namespace("cppu").GlobalNamespace()
+            // cppu/source/uno/eq.hxx
+        || dc.Function("equalFont").Namespace("xmlscript").GlobalNamespace()
+            // xmlscript/source/xmldlg_imexp/xmldlg_export.cxx
+        // These might need fixing:
+        || (dc.Function("getSmallestDistancePointToPolygon").Namespace("tools")
+            .Namespace("basegfx").GlobalNamespace())
+            // basegfx/source/polygon/b2dpolygontools.cxx
+        || (dc.Function("getSmallestDistancePointToPolyPolygon")
+            .Namespace("tools").Namespace("basegfx").GlobalNamespace())
+            // basegfx/source/polygon/b2dpolypolygontools.cxx
+        || dc.Function("performTest").Namespace("bridge_test").GlobalNamespace()
+            // testtools/source/bridgetest/bridgetest.cxx
+        || dc.Function("equals").Namespace("bridge_test").GlobalNamespace()
+        || (dc.Function("lcl_getNANInsteadDBL_MIN").AnonymousNamespace()
+            .GlobalNamespace()))
+            // chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx
+    {
         return true;
     }
 //    cout << "xxx " + function->getQualifiedNameAsString() << endl;
diff --git a/compilerplugins/clang/getimplementationname.cxx b/compilerplugins/clang/getimplementationname.cxx
index b887396..6b4c734 100644
--- a/compilerplugins/clang/getimplementationname.cxx
+++ b/compilerplugins/clang/getimplementationname.cxx
@@ -20,8 +20,8 @@
 #include <iostream>
 #include <fstream>
 #include <regex>
+#include "check.hxx"
 #include "plugin.hxx"
-#include "typecheck.hxx"
 #include "clang/Frontend/CompilerInstance.h"
 
 namespace {
diff --git a/compilerplugins/clang/implicitboolconversion.cxx b/compilerplugins/clang/implicitboolconversion.cxx
index 79dc8fb..552293f 100644
--- a/compilerplugins/clang/implicitboolconversion.cxx
+++ b/compilerplugins/clang/implicitboolconversion.cxx
@@ -15,9 +15,9 @@
 #include <string>
 #include <vector>
 
+#include "check.hxx"
 #include "compat.hxx"
 #include "plugin.hxx"
-#include "typecheck.hxx"
 
 #if CLANG_VERSION < 30700
 
diff --git a/compilerplugins/clang/passstuffbyref.cxx b/compilerplugins/clang/passstuffbyref.cxx
index b2f5ce6..f6200b0 100644
--- a/compilerplugins/clang/passstuffbyref.cxx
+++ b/compilerplugins/clang/passstuffbyref.cxx
@@ -10,9 +10,9 @@
 #include <string>
 #include <set>
 
-#include "plugin.hxx"
+#include "check.hxx"
 #include "compat.hxx"
-#include "typecheck.hxx"
+#include "plugin.hxx"
 
 // Find places where various things are passed by value.
 // It's not very efficient, because we generally end up copying it twice - once into the parameter and
@@ -244,22 +244,31 @@ void PassStuffByRef::checkReturnValue(const FunctionDecl * functionDecl, const C
                               functionDecl->getCanonicalDecl()->getNameInfo().getLoc()))) {
         return;
     }
+    loplugin::DeclCheck dc(functionDecl);
     std::string aFunctionName = functionDecl->getQualifiedNameAsString();
     // function is passed as parameter to another function
-    if (aFunctionName == "GDIMetaFile::ImplColMonoFnc"
-        || aFunctionName == "editeng::SvxBorderLine::darkColor"
+    if (dc.Function("ImplColMonoFnc").Class("GDIMetaFile").GlobalNamespace()
+        || (dc.Function("darkColor").Class("SvxBorderLine").Namespace("editeng")
+            .GlobalNamespace())
         || aFunctionName.compare(0, 8, "xforms::") == 0)
         return;
     // not sure how to exclude this yet, returns copy of one of it's params
-    if (aFunctionName == "sameDistColor" || aFunctionName == "sameColor"
-        || aFunctionName == "pcr::(anonymous namespace)::StringIdentity::operator()"
+    if (dc.Function("sameDistColor").GlobalNamespace()
+        || dc.Function("sameColor").GlobalNamespace()
+        || (dc.Operator(OO_Call).Struct("StringIdentity").AnonymousNamespace()
+            .Namespace("pcr").GlobalNamespace())
         || aFunctionName == "matop::COp<type-parameter-0-0, svl::SharedString>::operator()"
-        || aFunctionName == "slideshow::internal::accumulate"
-        || aFunctionName == "slideshow::internal::lerp")
+        || (dc.Function("accumulate").Namespace("internal")
+            .Namespace("slideshow").GlobalNamespace())
+        || (dc.Function("lerp").Namespace("internal").Namespace("slideshow")
+            .GlobalNamespace()))
         return;
     // depends on a define
-    if (aFunctionName == "SfxObjectShell::GetSharedFileURL")
+    if (dc.Function("GetSharedFileURL").Class("SfxObjectShell")
+        .GlobalNamespace())
+    {
         return;
+    }
     mbInsideFunctionDecl = true;
     mbFoundDisqualifier = false;
     TraverseStmt(functionDecl->getBody());
diff --git a/compilerplugins/clang/refcounting.cxx b/compilerplugins/clang/refcounting.cxx
index 9ce88a3..2049eab 100644
--- a/compilerplugins/clang/refcounting.cxx
+++ b/compilerplugins/clang/refcounting.cxx
@@ -10,9 +10,9 @@
 #include <string>
 #include <iostream>
 
-#include "plugin.hxx"
+#include "check.hxx"
 #include "compat.hxx"
-#include "typecheck.hxx"
+#include "plugin.hxx"
 #include "clang/AST/CXXInheritance.h"
 
 /**
@@ -110,7 +110,6 @@ bool containsXInterfaceSubclass(const QualType& qType) {
 }
 
 static std::vector<std::string> PROBABLY_GOOD_TEMPLATES = {
-    "(anonymous namespace)::FindUnoInstanceHint",
     "abp::OMultiInstanceAutoRegistration",
     "com::sun::star::uno::Reference",
     "com::sun::star::uno::WeakReference",
@@ -191,6 +190,11 @@ bool containsXInterfaceSubclass(const Type* pType0) {
     if (pRecordDecl) {
         const ClassTemplateSpecializationDecl* pTemplate = dyn_cast<ClassTemplateSpecializationDecl>(pRecordDecl);
         if (pTemplate) {
+            if (loplugin::DeclCheck(pTemplate).Struct("FindUnoInstanceHint")
+                .AnonymousNamespace().GlobalNamespace())
+            {
+                return false;
+            }
             std::string aName = pTemplate->getQualifiedNameAsString();
             if (std::find(PROBABLY_GOOD_TEMPLATES.begin(), PROBABLY_GOOD_TEMPLATES.end(), aName) != PROBABLY_GOOD_TEMPLATES.end())
                 return false;
diff --git a/compilerplugins/clang/salbool.cxx b/compilerplugins/clang/salbool.cxx
index f08b1c0..117ce61 100644
--- a/compilerplugins/clang/salbool.cxx
+++ b/compilerplugins/clang/salbool.cxx
@@ -14,9 +14,9 @@
 
 #include "clang/AST/Attr.h"
 
+#include "check.hxx"
 #include "compat.hxx"
 #include "plugin.hxx"
-#include "typecheck.hxx"
 
 namespace {
 
diff --git a/compilerplugins/clang/staticmethods.cxx b/compilerplugins/clang/staticmethods.cxx
index 9108e02..7eac313 100644
--- a/compilerplugins/clang/staticmethods.cxx
+++ b/compilerplugins/clang/staticmethods.cxx
@@ -9,9 +9,9 @@
 
 #include "clang/AST/Attr.h"
 
+#include "check.hxx"
 #include "compat.hxx"
 #include "plugin.hxx"
-#include "typecheck.hxx"
 
 /*
   Look for member functions that can be static
diff --git a/compilerplugins/clang/stringconstant.cxx b/compilerplugins/clang/stringconstant.cxx
index 3b16d82..157039b 100644
--- a/compilerplugins/clang/stringconstant.cxx
+++ b/compilerplugins/clang/stringconstant.cxx
@@ -15,9 +15,9 @@
 #include <string>
 #include <iostream>
 
+#include "check.hxx"
 #include "compat.hxx"
 #include "plugin.hxx"
-#include "typecheck.hxx"
 
 // Define a "string constant" to be a constant expression either of type "array
 // of N char" where each array element is a non-NUL ASCII character---except
diff --git a/compilerplugins/clang/weakobject.cxx b/compilerplugins/clang/weakobject.cxx
index c714274..a148da0 100644
--- a/compilerplugins/clang/weakobject.cxx
+++ b/compilerplugins/clang/weakobject.cxx
@@ -7,8 +7,8 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include "check.hxx"
 #include "plugin.hxx"
-#include "typecheck.hxx"
 
 /* OWeakObject::release() disposes weak references.  If that isn't done
  * because a sub-class improperly overrides release() then


More information about the Libreoffice-commits mailing list