summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/refcounting.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'compilerplugins/clang/refcounting.cxx')
-rw-r--r--compilerplugins/clang/refcounting.cxx109
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;
}