diff --git a/compilerplugins/clang/staticmethods.cxx b/compilerplugins/clang/staticmethods.cxx index be014fd1630d..9108e0236d65 100644 --- a/compilerplugins/clang/staticmethods.cxx +++ b/compilerplugins/clang/staticmethods.cxx @@ -9,8 +9,9 @@ #include "clang/AST/Attr.h" -#include "plugin.hxx" #include "compat.hxx" +#include "plugin.hxx" +#include "typecheck.hxx" /* Look for member functions that can be static @@ -118,12 +119,14 @@ bool StaticMethods::TraverseCXXMethodDecl(const CXXMethodDecl * pCXXMethodDecl) } // can't change it because in debug mode it can't be static // sal/cpprt/operators_new_delete.cxx - if (aParentName == "(anonymous namespace)::AllocatorTraits") { + auto dc = loplugin::DeclCheck(pCXXMethodDecl->getParent()); + if (dc.Struct("AllocatorTraits").AnonymousNamespace().GlobalNamespace()) { return true; } // in this case, the code is taking the address of the member function // shell/source/unix/sysshell/recently_used_file_handler.cxx - if (aParentName == "(anonymous namespace)::recently_used_item") { + if (dc.Struct("recently_used_item").AnonymousNamespace().GlobalNamespace()) + { return true; } // the unotools and svl config code stuff is doing weird stuff with a reference-counted statically allocated pImpl class diff --git a/compilerplugins/clang/typecheck.cxx b/compilerplugins/clang/typecheck.cxx index d7bccfd814a8..c293b5750b87 100644 --- a/compilerplugins/clang/typecheck.cxx +++ b/compilerplugins/clang/typecheck.cxx @@ -85,6 +85,12 @@ TerminalCheck NamespaceCheck::StdNamespace() const { context_ != nullptr && compat::isStdNamespace(*context_)); } +NamespaceCheck NamespaceCheck::AnonymousNamespace() const { + auto n = llvm::dyn_cast_or_null(context_); + return NamespaceCheck( + n != nullptr && n->isAnonymousNamespace() ? n->getParent() : nullptr); +} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/typecheck.hxx b/compilerplugins/clang/typecheck.hxx index 9862890a2fc7..b3417bf823bf 100644 --- a/compilerplugins/clang/typecheck.hxx +++ b/compilerplugins/clang/typecheck.hxx @@ -21,6 +21,13 @@ namespace loplugin { class NamespaceCheck; class TerminalCheck; +namespace detail { + +template NamespaceCheck checkRecordDecl( + clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N]); + +} + class TypeCheck { public: explicit TypeCheck(clang::QualType type): type_(type) {} @@ -59,8 +66,12 @@ public: TerminalCheck StdNamespace() const; + NamespaceCheck AnonymousNamespace() const; + private: - friend class TypeCheck; + friend TypeCheck; + template friend NamespaceCheck detail::checkRecordDecl( + clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N]); explicit NamespaceCheck(clang::DeclContext const * context = nullptr): context_(context) {} @@ -68,6 +79,19 @@ private: clang::DeclContext const * const context_; }; +class DeclCheck { +public: + explicit DeclCheck(clang::Decl const * decl): decl_(decl) {} + + explicit operator bool() const { return decl_ != nullptr; } + + template inline NamespaceCheck Struct(char const (& id)[N]) + const; + +private: + clang::Decl const * const decl_; +}; + class TerminalCheck { public: explicit operator bool() const { return satisfied_; } @@ -81,19 +105,30 @@ private: bool const satisfied_; }; +namespace detail { + +template NamespaceCheck checkRecordDecl( + clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N]) +{ + auto r = llvm::dyn_cast_or_null(decl); + if (r != nullptr && r->getTagKind() == tag) { + auto const i = r->getIdentifier(); + if (i != nullptr && i->isStr(id)) { + return NamespaceCheck(r->getDeclContext()); + } + } + return NamespaceCheck(); +} + +} + template NamespaceCheck TypeCheck::Class(char const (& id)[N]) const { if (!type_.isNull()) { auto const t = type_->getAs(); 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 detail::checkRecordDecl(t->getDecl(), clang::TTK_Class, id); } } return NamespaceCheck(); @@ -114,6 +149,12 @@ template NamespaceCheck NamespaceCheck::Namespace( return NamespaceCheck(); } +template NamespaceCheck DeclCheck::Struct(char const (& id)[N]) + const +{ + return detail::checkRecordDecl(decl_, clang::TTK_Struct, id); +} + } #endif