diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2015-12-08 22:56:02 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2015-12-08 22:56:02 +0100 |
commit | bb24492c767eda30a14c83ac27b74b977b177dbb (patch) | |
tree | 0bd75004941a3b111e3c8c911bd2c22b6b259b0d /compilerplugins | |
parent | 8d2c9a60b2dca069dedb08cac38c26afea0a562d (diff) |
More loplugin::TypeCheck use
Change-Id: I2f4a26a918134568f541cd45bdcf5a12b1f1d2ee
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/badstatics.cxx | 24 | ||||
-rw-r--r-- | compilerplugins/clang/getimplementationname.cxx | 9 | ||||
-rw-r--r-- | compilerplugins/clang/passstuffbyref.cxx | 32 | ||||
-rw-r--r-- | compilerplugins/clang/stringconstant.cxx | 37 | ||||
-rw-r--r-- | compilerplugins/clang/typecheck.hxx | 94 |
5 files changed, 80 insertions, 116 deletions
diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx index 26773a8fca45..8b033cdd87fb 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 ac011eeeb73c..a73a7577bc4d 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 f2e66f710986..9da28b3c5938 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 56ae27c90bc5..0749abb3ddd0 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 35d4e5769b6e..70e3d8c9c265 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 |