diff options
author | Noel Grandin <noel@peralex.com> | 2016-05-26 16:02:39 +0200 |
---|---|---|
committer | Noel Grandin <noelgrandin@gmail.com> | 2016-05-31 06:25:45 +0000 |
commit | 0b23eec200c8c12db5778405df44f4bf8e38e4ad (patch) | |
tree | ee45856fe1781195c51f63835024865f283cdab8 /compilerplugins | |
parent | 88c03cd07a171e05c7fb4dcade8baa28e7c5a770 (diff) |
teach refcounting clang plugin about uno::Reference
uno::Reference is only allowed to used with classes that have a
::static_type member.
So convert all those places to rtl::Reference.
Maybe we need some LIBO_INTERNAL_ONLY constructors on rtl::Reference and
uno::Reference to make this a little smoother?
Change-Id: Icdcb35d71ca40a87b1dc474096776412adbfc7e3
Reviewed-on: https://gerrit.libreoffice.org/25516
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noelgrandin@gmail.com>
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/refcounting.cxx | 109 |
1 files changed, 82 insertions, 27 deletions
diff --git a/compilerplugins/clang/refcounting.cxx b/compilerplugins/clang/refcounting.cxx index 663fcb7a3958..9bb948517712 100644 --- a/compilerplugins/clang/refcounting.cxx +++ b/compilerplugins/clang/refcounting.cxx @@ -12,6 +12,7 @@ #include "plugin.hxx" #include "compat.hxx" +#include "typecheck.hxx" #include "clang/AST/CXXInheritance.h" /** @@ -50,6 +51,7 @@ public: bool VisitFieldDecl(const FieldDecl *); bool VisitVarDecl(const VarDecl *); + bool VisitFunctionDecl(const FunctionDecl *); bool WalkUpFromObjCIvarDecl(ObjCIvarDecl * decl) { // Don't recurse into WalkUpFromFieldDecl, as VisitFieldDecl calls @@ -58,6 +60,9 @@ public: // ObjCIvarDecl. return VisitObjCIvarDecl(decl); } +private: + void checkUnoReference(QualType qt, const Decl* decl, + const std::string& rParentName, const std::string& rDeclName); }; bool BaseCheckNotSubclass(const CXXRecordDecl *BaseDefinition, void *p) { @@ -287,6 +292,39 @@ bool containsSalhelperReferenceObjectSubclass(const Type* pType0) { } } +static bool containsStaticTypeMethod(const CXXRecordDecl* x) +{ + for (auto it = x->method_begin(); it != x->method_end(); ++it) { + auto i = *it; + if ( !i->isStatic() ) + continue; + auto ident = i->getIdentifier(); + if ( ident && ident->isStr("static_type") ) { + return true; + } + } + return false; +} + +void RefCounting::checkUnoReference(QualType qt, const Decl* decl, const std::string& rParentName, const std::string& rDeclName) +{ + if (loplugin::TypeCheck(qt).Class("Reference").Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()) { + const CXXRecordDecl* pRecordDecl = qt->getAsCXXRecordDecl(); + const ClassTemplateSpecializationDecl* pTemplate = dyn_cast<ClassTemplateSpecializationDecl>(pRecordDecl); + const TemplateArgument& rArg = pTemplate->getTemplateArgs()[0]; + const CXXRecordDecl* templateParam = rArg.getAsType()->getAsCXXRecordDecl()->getDefinition(); + if (templateParam && !containsStaticTypeMethod(templateParam)) { + report( + DiagnosticsEngine::Warning, + "uno::Reference " + rDeclName + " with template parameter that does not contain ::static_type() " + + qt.getAsString() + + ", parent is " + rParentName, + decl->getLocation()) + << decl->getSourceRange(); + } + } +} + bool RefCounting::VisitFieldDecl(const FieldDecl * fieldDecl) { if (ignoreLocation(fieldDecl)) { return true; @@ -334,6 +372,9 @@ bool RefCounting::VisitFieldDecl(const FieldDecl * fieldDecl) { fieldDecl->getLocation()) << fieldDecl->getSourceRange(); } + + checkUnoReference(fieldDecl->getType(), fieldDecl, aParentName, "field"); + return true; } @@ -342,37 +383,51 @@ bool RefCounting::VisitVarDecl(const VarDecl * varDecl) { if (ignoreLocation(varDecl)) { return true; } - if (isa<ParmVarDecl>(varDecl)) { - return true; + if (!isa<ParmVarDecl>(varDecl)) { + if (containsSvRefBaseSubclass(varDecl->getType().getTypePtr())) { + report( + DiagnosticsEngine::Warning, + "SvRefBase subclass being directly stack managed, should be managed via tools::SvRef, " + + varDecl->getType().getAsString(), + varDecl->getLocation()) + << varDecl->getSourceRange(); + } + if (containsSalhelperReferenceObjectSubclass(varDecl->getType().getTypePtr())) { + StringRef name { compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(varDecl->getLocation())) }; + // this is playing games that it believes is safe + if (name == SRCDIR "/stoc/source/security/permissions.cxx") + return true; + report( + DiagnosticsEngine::Warning, + "salhelper::SimpleReferenceObject subclass being directly stack managed, should be managed via rtl::Reference, " + + varDecl->getType().getAsString(), + varDecl->getLocation()) + << varDecl->getSourceRange(); + } + if (containsXInterfaceSubclass(varDecl->getType())) { + report( + DiagnosticsEngine::Warning, + "XInterface subclass being directly stack managed, should be managed via uno::Reference, " + + varDecl->getType().getAsString(), + varDecl->getLocation()) + << varDecl->getSourceRange(); + } } - if (containsSvRefBaseSubclass(varDecl->getType().getTypePtr())) { - report( - DiagnosticsEngine::Warning, - "SvRefBase subclass being directly stack managed, should be managed via tools::SvRef, " - + varDecl->getType().getAsString(), - varDecl->getLocation()) - << varDecl->getSourceRange(); + checkUnoReference(varDecl->getType(), varDecl, "", "var"); + return true; +} + +bool RefCounting::VisitFunctionDecl(const FunctionDecl * functionDecl) { + if (ignoreLocation(functionDecl)) { + return true; } - if (containsSalhelperReferenceObjectSubclass(varDecl->getType().getTypePtr())) { - StringRef name { compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(varDecl->getLocation())) }; - // this is playing games that it believes is safe - if (name == SRCDIR "/stoc/source/security/permissions.cxx") + // only consider base declarations, not overriden ones, or we warn on methods that + // are overriding stuff from external libraries + const CXXMethodDecl * methodDecl = dyn_cast<CXXMethodDecl>(functionDecl); + if (methodDecl && methodDecl->size_overridden_methods() > 0) { return true; - report( - DiagnosticsEngine::Warning, - "salhelper::SimpleReferenceObject subclass being directly stack managed, should be managed via rtl::Reference, " - + varDecl->getType().getAsString(), - varDecl->getLocation()) - << varDecl->getSourceRange(); - } - if (containsXInterfaceSubclass(varDecl->getType())) { - report( - DiagnosticsEngine::Warning, - "XInterface subclass being directly stack managed, should be managed via uno::Reference, " - + varDecl->getType().getAsString(), - varDecl->getLocation()) - << varDecl->getSourceRange(); } + checkUnoReference(functionDecl->getReturnType(), functionDecl, "", "return"); return true; } |