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

Stephan Bergmann sbergman at redhat.com
Tue Dec 8 13:56:39 PST 2015


 compilerplugins/clang/badstatics.cxx            |   24 ++----
 compilerplugins/clang/getimplementationname.cxx |    9 --
 compilerplugins/clang/passstuffbyref.cxx        |   32 ++++----
 compilerplugins/clang/stringconstant.cxx        |   37 ++-------
 compilerplugins/clang/typecheck.hxx             |   94 ++++++++++--------------
 5 files changed, 80 insertions(+), 116 deletions(-)

New commits:
commit bb24492c767eda30a14c83ac27b74b977b177dbb
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Tue Dec 8 22:56:02 2015 +0100

    More loplugin::TypeCheck use
    
    Change-Id: I2f4a26a918134568f541cd45bdcf5a12b1f1d2ee

diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx
index 26773a8..8b033cd 100644
--- a/compilerplugins/clang/badstatics.cxx
+++ b/compilerplugins/clang/badstatics.cxx
@@ -12,11 +12,6 @@
 
 namespace {
 
-static bool startsWith(const std::string& s, const char* other)
-{
-    return s.compare(0, strlen(other), other) == 0;
-}
-
 class BadStatics
     : public clang::RecursiveASTVisitor<BadStatics>
     , public loplugin::Plugin
@@ -52,10 +47,10 @@ public:
         if (!pRecordType) {
             return std::make_pair(false, std::vector<FieldDecl const*>());
         }
-        auto const type(pCanonical.getAsString());
-        if (   type == "class Image"
-            || type == "class Bitmap"
-            || type == "class BitmapEx"
+        auto const type = loplugin::TypeCheck(rpType);
+        if (   type.Class("Image").GlobalNamespace()
+            || type.Class("Bitmap").GlobalNamespace()
+            || type.Class("BitmapEx").GlobalNamespace()
            )
         {
             return std::make_pair(true, chain);
@@ -64,12 +59,11 @@ public:
         if (!pDefinition) { // maybe no definition if it's a pointer/reference
             return std::make_pair(false, std::vector<FieldDecl const*>());
         }
-        if (   startsWith(type, "class vcl::DeleteOnDeinit")
-            || loplugin::TypeCheck(rpType).Class("weak_ptr").StdNamespace()
-                // not owning
-            || type == "class ImplWallpaper" // very odd static instance here
-            || type == "class Application" // numerous odd subclasses in vclmain::createApplication()
-            || type == "class DemoMtfApp" // one of these Application with own VclPtr
+        if (   type.Class("DeleteOnDeinit").Namespace("vcl").GlobalNamespace()
+            || type.Class("weak_ptr").StdNamespace() // not owning
+            || type.Class("ImplWallpaper").GlobalNamespace() // very odd static instance here
+            || type.Class("Application").GlobalNamespace() // numerous odd subclasses in vclmain::createApplication()
+            || type.Class("DemoMtfApp").GlobalNamespace() // one of these Application with own VclPtr
            )
         {
             return std::make_pair(false, std::vector<FieldDecl const*>());
diff --git a/compilerplugins/clang/getimplementationname.cxx b/compilerplugins/clang/getimplementationname.cxx
index ac011ee..a73a757 100644
--- a/compilerplugins/clang/getimplementationname.cxx
+++ b/compilerplugins/clang/getimplementationname.cxx
@@ -20,6 +20,7 @@
 #include <fstream>
 #include <regex>
 #include "plugin.hxx"
+#include "typecheck.hxx"
 #include "clang/Frontend/CompilerInstance.h"
 
 namespace {
@@ -45,11 +46,6 @@ clang::Expr const * ignoreParenImplicitComma(clang::Expr const * expr) {
     }
 }
 
-bool isPlainChar(clang::QualType type) {
-    return type->isSpecificBuiltinType(clang::BuiltinType::Char_S)
-        || type->isSpecificBuiltinType(clang::BuiltinType::Char_U);
-}
-
 bool overridesXServiceInfo(clang::CXXMethodDecl const * decl) {
     for (auto i = decl->begin_overridden_methods();
          i != decl->end_overridden_methods(); ++i)
@@ -145,7 +141,8 @@ bool GetImplementationName::isStringConstant(
 {
     QualType t = expr->getType();
     if (!(t->isConstantArrayType() && t.isConstQualified()
-          && isPlainChar(t->getAsArrayTypeUnsafe()->getElementType())))
+          && (loplugin::TypeCheck(t->getAsArrayTypeUnsafe()->getElementType())
+              .Char())))
     {
         return false;
     }
diff --git a/compilerplugins/clang/passstuffbyref.cxx b/compilerplugins/clang/passstuffbyref.cxx
index f2e66f7..9da28b3 100644
--- a/compilerplugins/clang/passstuffbyref.cxx
+++ b/compilerplugins/clang/passstuffbyref.cxx
@@ -11,6 +11,7 @@
 #include <set>
 
 #include "plugin.hxx"
+#include "typecheck.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
@@ -38,7 +39,7 @@ public:
     bool VisitLambdaExpr(const LambdaExpr * expr);
 
 private:
-    bool isFat(QualType type, std::string * name);
+    bool isFat(QualType type);
 };
 
 bool PassStuffByRef::VisitFunctionDecl(const FunctionDecl * functionDecl) {
@@ -63,14 +64,13 @@ bool PassStuffByRef::VisitFunctionDecl(const FunctionDecl * functionDecl) {
     unsigned n = functionDecl->getNumParams();
     for (unsigned i = 0; i != n; ++i) {
         const ParmVarDecl * pvDecl = functionDecl->getParamDecl(i);
-        std::string name;
-        if (isFat(pvDecl->getType(), &name)) {
+        auto const t = pvDecl->getType();
+        if (isFat(t)) {
             report(
                 DiagnosticsEngine::Warning,
-                ("passing '%0' by value, rather pass by reference, e.g., '%0"
-                 " const &'"),
+                ("passing %0 by value, rather pass by const lvalue reference"),
                 pvDecl->getLocation())
-                << name << pvDecl->getSourceRange();
+                << t << pvDecl->getSourceRange();
         }
     }
     return true;
@@ -82,14 +82,14 @@ bool PassStuffByRef::VisitLambdaExpr(const LambdaExpr * expr) {
     }
     for (auto i(expr->capture_begin()); i != expr->capture_end(); ++i) {
         if (i->getCaptureKind() == LambdaCaptureKind::LCK_ByCopy) {
-            std::string name;
-            if (isFat(i->getCapturedVar()->getType(), &name)) {
+            auto const t = i->getCapturedVar()->getType();
+            if (isFat(t)) {
                 report(
                     DiagnosticsEngine::Warning,
-                    ("%0 capture of '%1' variable by copy, rather use capture"
+                    ("%0 capture of %1 variable by copy, rather use capture"
                      " by reference---UNLESS THE LAMBDA OUTLIVES THE VARIABLE"),
                     i->getLocation())
-                    << (i->isImplicit() ? "implicit" : "explicit") << name
+                    << (i->isImplicit() ? "implicit" : "explicit") << t
                     << expr->getSourceRange();
             }
         }
@@ -97,13 +97,17 @@ bool PassStuffByRef::VisitLambdaExpr(const LambdaExpr * expr) {
     return true;
 }
 
-bool PassStuffByRef::isFat(QualType type, std::string * name) {
+bool PassStuffByRef::isFat(QualType type) {
     if (!type->isRecordType()) {
         return false;
     }
-    *name = type.getUnqualifiedType().getCanonicalType().getAsString();
-    if (*name == "class rtl::OUString" || *name == "class rtl::OString"
-        || name->compare(0, 35, "class com::sun::star::uno::Sequence") == 0)
+    if ((loplugin::TypeCheck(type).Class("OUString").Namespace("rtl")
+         .GlobalNamespace())
+        || (loplugin::TypeCheck(type).Class("OString").Namespace("rtl")
+            .GlobalNamespace())
+        || (loplugin::TypeCheck(type).Class("Sequence").Namespace("uno")
+            .Namespace("star").Namespace("sun").Namespace("com")
+            .GlobalNamespace()))
     {
         return true;
     }
diff --git a/compilerplugins/clang/stringconstant.cxx b/compilerplugins/clang/stringconstant.cxx
index 56ae27c..0749abb 100644
--- a/compilerplugins/clang/stringconstant.cxx
+++ b/compilerplugins/clang/stringconstant.cxx
@@ -16,6 +16,7 @@
 
 #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
@@ -37,11 +38,6 @@
 
 namespace {
 
-bool isPlainChar(QualType type) {
-    return type->isSpecificBuiltinType(BuiltinType::Char_S)
-        || type->isSpecificBuiltinType(BuiltinType::Char_U);
-}
-
 SourceLocation getMemberLocation(Expr const * expr) {
     CallExpr const * e1 = dyn_cast<CallExpr>(expr);
     MemberExpr const * e2 = e1 == nullptr
@@ -227,30 +223,14 @@ bool StringConstant::VisitCallExpr(CallExpr const * expr) {
     std::string qname(fdecl->getQualifiedNameAsString());
     for (unsigned i = 0; i != fdecl->getNumParams(); ++i) {
         auto t = fdecl->getParamDecl(i)->getType();
-        if (t->isLValueReferenceType()
-            && t->getAs<SubstTemplateTypeParmType>() == nullptr)
+        if (loplugin::TypeCheck(t).NotSubstTemplateTypeParmType()
+            .LvalueReference().Const().NotSubstTemplateTypeParmType()
+            .Class("OUString").Namespace("rtl").GlobalNamespace())
         {
-            t = t->getAs<LValueReferenceType>()->getPointeeType();
-            if (t.isConstQualified() && !t.isVolatileQualified()
-                && t->isClassType()
-                && t->getAs<SubstTemplateTypeParmType>() == nullptr)
+            if (!(isLhsOfAssignment(fdecl, i)
+                  || hasOverloads(fdecl, expr->getNumArgs())))
             {
-                auto td = compat::getAsTagDecl(*t);
-                auto id = td->getIdentifier();
-                if (id != nullptr && id->isStr("OUString")) {
-                    auto nd = dyn_cast<NamespaceDecl>(td->getParent());
-                    if (nd != nullptr) {
-                        id = nd->getIdentifier();
-                        if (id != nullptr && id->isStr("rtl")) {
-                            //TODO: check rtl is outermost namespace
-                            if (!(isLhsOfAssignment(fdecl, i)
-                                  || hasOverloads(fdecl, expr->getNumArgs())))
-                            {
-                                handleOUStringCtor(expr, i, qname, true);
-                            }
-                        }
-                    }
-                }
+                handleOUStringCtor(expr, i, qname, true);
             }
         }
     }
@@ -839,7 +819,8 @@ bool StringConstant::isStringConstant(
     assert(terminatingNul != nullptr);
     QualType t = expr->getType();
     if (!(t->isConstantArrayType() && t.isConstQualified()
-          && isPlainChar(t->getAsArrayTypeUnsafe()->getElementType())))
+          && (loplugin::TypeCheck(t->getAsArrayTypeUnsafe()->getElementType())
+              .Char())))
     {
         return false;
     }
diff --git a/compilerplugins/clang/typecheck.hxx b/compilerplugins/clang/typecheck.hxx
index 35d4e57..70e3d8c 100644
--- a/compilerplugins/clang/typecheck.hxx
+++ b/compilerplugins/clang/typecheck.hxx
@@ -13,13 +13,13 @@
 #include <cstddef>
 
 #include <clang/AST/DeclBase.h>
+#include <clang/AST/Decl.h>
 #include <clang/AST/Type.h>
 
-#include "compat.hxx"
-
 namespace loplugin {
 
 class NamespaceCheck;
+class TerminalCheck;
 
 class TypeCheck {
 public:
@@ -27,73 +27,33 @@ public:
 
     explicit operator bool() const { return !type_.isNull(); }
 
-    TypeCheck Const() const {
-        return
-            (!type_.isNull() && type_.isConstQualified()
-             && !type_.isVolatileQualified())
-            ? *this : TypeCheck();
-    }
+    TypeCheck Const() const;
 
-    TypeCheck LvalueReference() const {
-        if (!type_.isNull()) {
-            auto const t = type_->getAs<LValueReferenceType>();
-            if (t != nullptr) {
-                return TypeCheck(t->getPointeeType());
-            }
-        }
-        return TypeCheck();
-    }
+    TerminalCheck Char() const;
+
+    TypeCheck LvalueReference() const;
 
     template<std::size_t N> inline NamespaceCheck Class(char const (& id)[N])
         const;
 
+    TypeCheck NotSubstTemplateTypeParmType() const;
+
 private:
     TypeCheck() = default;
 
     clang::QualType const type_;
 };
 
-class TerminalCheck {
-public:
-    explicit operator bool() const { return satisfied_; }
-
-private:
-    friend NamespaceCheck;
-
-    explicit TerminalCheck(bool satisfied): satisfied_(satisfied) {}
-
-    bool const satisfied_;
-};
-
 class NamespaceCheck {
 public:
     explicit operator bool() const { return context_ != nullptr; }
 
-    TerminalCheck GlobalNamespace() const {
-        return TerminalCheck(
-            context_ != nullptr
-            && ((compat::isLookupContext(*context_)
-                 ? context_ : context_->getLookupParent())
-                ->isTranslationUnit()));
-    }
+    TerminalCheck GlobalNamespace() const;
 
-    template<std::size_t N> NamespaceCheck Namespace(char const (& id)[N]) const
-    {
-        if (context_) {
-            auto n = llvm::dyn_cast<clang::NamespaceDecl>(context_);
-            if (n != nullptr) {
-                auto const i = n->getIdentifier();
-                if (i != nullptr && i->isStr(id)) {
-                    return NamespaceCheck(n->getParent());
-                }
-            }
-        }
-        return NamespaceCheck();
-    }
+    template<std::size_t N> inline NamespaceCheck Namespace(
+        char const (& id)[N]) const;
 
-    TerminalCheck StdNamespace() const {
-        return TerminalCheck(context_ != nullptr && context_->isStdNamespace());
-    }
+    TerminalCheck StdNamespace() const;
 
 private:
     friend class TypeCheck;
@@ -104,11 +64,24 @@ private:
     clang::DeclContext const * const context_;
 };
 
+class TerminalCheck {
+public:
+    explicit operator bool() const { return satisfied_; }
+
+private:
+    friend TypeCheck;
+    friend NamespaceCheck;
+
+    explicit TerminalCheck(bool satisfied): satisfied_(satisfied) {}
+
+    bool const satisfied_;
+};
+
 template<std::size_t N> NamespaceCheck TypeCheck::Class(char const (& id)[N])
     const
 {
     if (!type_.isNull()) {
-        auto const t = type_->getAs<RecordType>();
+        auto const t = type_->getAs<clang::RecordType>();
         if (t != nullptr) {
             auto const d = t->getDecl();
             if (d->isClass()) {
@@ -122,6 +95,21 @@ template<std::size_t N> NamespaceCheck TypeCheck::Class(char const (& id)[N])
     return NamespaceCheck();
 }
 
+template<std::size_t N> NamespaceCheck NamespaceCheck::Namespace(
+    char const (& id)[N]) const
+{
+    if (context_) {
+        auto n = llvm::dyn_cast<clang::NamespaceDecl>(context_);
+        if (n != nullptr) {
+            auto const i = n->getIdentifier();
+            if (i != nullptr && i->isStr(id)) {
+                return NamespaceCheck(n->getParent());
+            }
+        }
+    }
+    return NamespaceCheck();
+}
+
 }
 
 #endif


More information about the Libreoffice-commits mailing list