summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2015-12-08 22:56:02 +0100
committerStephan Bergmann <sbergman@redhat.com>2015-12-08 22:56:02 +0100
commitbb24492c767eda30a14c83ac27b74b977b177dbb (patch)
tree0bd75004941a3b111e3c8c911bd2c22b6b259b0d /compilerplugins
parent8d2c9a60b2dca069dedb08cac38c26afea0a562d (diff)
More loplugin::TypeCheck use
Change-Id: I2f4a26a918134568f541cd45bdcf5a12b1f1d2ee
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/badstatics.cxx24
-rw-r--r--compilerplugins/clang/getimplementationname.cxx9
-rw-r--r--compilerplugins/clang/passstuffbyref.cxx32
-rw-r--r--compilerplugins/clang/stringconstant.cxx37
-rw-r--r--compilerplugins/clang/typecheck.hxx94
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