summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2015-11-17 21:50:45 +0100
committerStephan Bergmann <sbergman@redhat.com>2015-11-17 21:50:45 +0100
commit6e6c0951870c9b1149755aa21be2ec5d7145f347 (patch)
tree7094ccd90a849ab5e1673ad4b0149aa2828023e6 /compilerplugins
parent27b45cc23c7b8ea8a62e1fc901279fb3f09ae274 (diff)
Fix check for std::weak_ptr (that may be in an inline namespace)
Change-Id: I048aef08df43d07544aafc69b711d258dc40bc21
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/badstatics.cxx4
-rw-r--r--compilerplugins/clang/typecheck.hxx129
2 files changed, 132 insertions, 1 deletions
diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx
index 942b331f1749..3b2881f388d5 100644
--- a/compilerplugins/clang/badstatics.cxx
+++ b/compilerplugins/clang/badstatics.cxx
@@ -8,6 +8,7 @@
*/
#include "plugin.hxx"
+#include "typecheck.hxx"
namespace {
@@ -64,7 +65,8 @@ public:
return std::make_pair(false, std::vector<FieldDecl const*>());
}
if ( startsWith(type, "class vcl::DeleteOnDeinit")
- || startsWith(type, "class std::weak_ptr") // not owning
+ || 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
diff --git a/compilerplugins/clang/typecheck.hxx b/compilerplugins/clang/typecheck.hxx
new file mode 100644
index 000000000000..6ab8f74e1aad
--- /dev/null
+++ b/compilerplugins/clang/typecheck.hxx
@@ -0,0 +1,129 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_COMPILERPLUGINS_CLANG_TYPECHECK_HXX
+#define INCLUDED_COMPILERPLUGINS_CLANG_TYPECHECK_HXX
+
+#include <cstddef>
+
+#include <iostream>
+
+#include <clang/AST/DeclBase.h>
+#include <clang/AST/Type.h>
+
+namespace loplugin {
+
+class NamespaceCheck;
+
+class TypeCheck {
+public:
+ explicit TypeCheck(clang::QualType type): type_(type) {}
+
+ explicit operator bool() const { return !type_.isNull(); }
+
+ TypeCheck Const() const {
+ return
+ (!type_.isNull() && type_.isConstQualified()
+ && !type_.isVolatileQualified())
+ ? *this : TypeCheck();
+ }
+
+ TypeCheck LvalueReference() const {
+ if (!type_.isNull()) {
+ auto const t = type_->getAs<LValueReferenceType>();
+ if (t != nullptr) {
+ return TypeCheck(t->getPointeeType());
+ }
+ }
+ return TypeCheck();
+ }
+
+ template<std::size_t N> inline NamespaceCheck Class(char const (& id)[N])
+ 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
+ && ((context_->isLookupContext()
+ ? context_ : context_->getLookupParent())
+ ->isTranslationUnit()));
+ }
+
+ 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();
+ }
+
+ TerminalCheck StdNamespace() const {
+ return TerminalCheck(context_ != nullptr && context_->isStdNamespace());
+ }
+
+private:
+ friend class TypeCheck;
+
+ explicit NamespaceCheck(clang::DeclContext const * context = nullptr):
+ context_(context) {}
+
+ clang::DeclContext const * const context_;
+};
+
+template<std::size_t N> NamespaceCheck TypeCheck::Class(char const (& id)[N])
+ const
+{
+ if (!type_.isNull()) {
+ auto const t = type_->getAs<RecordType>();
+ if (t != nullptr) {
+ auto const d = t->getDecl();
+ if (d->isClass()) {
+ auto const i = d->getIdentifier();
+ if (i != nullptr && i->isStr(id)) {
+ return NamespaceCheck(d->getDeclContext());
+ }
+ }
+ }
+ }
+ return NamespaceCheck();
+}
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */