diff options
author | Noel Grandin <noel@peralex.com> | 2015-05-07 10:00:46 +0200 |
---|---|---|
committer | Noel Grandin <noel@peralex.com> | 2015-05-07 10:33:51 +0200 |
commit | 0825b020caa0d802a0d76d9a7643daedbf9874e6 (patch) | |
tree | 97d94a7d133ae89f4d58542fa07eb26a65da35be /compilerplugins | |
parent | f72e77f4086e4c22072d5815c9a6cbebc323ba8e (diff) |
new clang plugin: rendercontext
to help with converting calls to OutputDevice to pass via
vcl::RenderContext.
Change-Id: I4b49d2f5e4afca46898d2a7c7ed33cbf5577e664
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/rendercontext.cxx | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/compilerplugins/clang/rendercontext.cxx b/compilerplugins/clang/rendercontext.cxx new file mode 100644 index 000000000000..a1e7018d5fd1 --- /dev/null +++ b/compilerplugins/clang/rendercontext.cxx @@ -0,0 +1,93 @@ +/* -*- 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/. + */ + +#include <string> +#include <iostream> + +#include "plugin.hxx" +#include "compat.hxx" +#include "clang/AST/CXXInheritance.h" + +// Check for calls to OutputDevice methods that are not passing through RenderContext + +namespace { + +class RenderContext: + public RecursiveASTVisitor<RenderContext>, public loplugin::Plugin +{ +public: + explicit RenderContext(InstantiationData const & data): Plugin(data) {} + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool TraverseFunctionDecl(const FunctionDecl * decl); + + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *); + +private: + bool mbChecking = false; +}; + +bool RenderContext::TraverseFunctionDecl(const FunctionDecl * pFunctionDecl) { + if (ignoreLocation(pFunctionDecl)) { + return true; + } + if (!pFunctionDecl->hasBody()) { + return true; + } + if ( pFunctionDecl != pFunctionDecl->getCanonicalDecl() ) { + return true; + } + const CXXMethodDecl *pCXXMethodDecl = dyn_cast<CXXMethodDecl>(pFunctionDecl); + if (pCXXMethodDecl) { + std::string aParentName = pCXXMethodDecl->getParent()->getQualifiedNameAsString(); + if (aParentName == "OutputDevice") + return true; + } + mbChecking = true; + TraverseStmt(pFunctionDecl->getBody()); + mbChecking = false; + return true; +} + +bool RenderContext::VisitCXXMemberCallExpr(const CXXMemberCallExpr* pCXXMemberCallExpr) +{ + if (!mbChecking) + return true; + if (ignoreLocation(pCXXMemberCallExpr)) { + return true; + } + const CXXRecordDecl *pCXXRecordDecl = pCXXMemberCallExpr->getRecordDecl(); + if (pCXXRecordDecl->getQualifiedNameAsString() != "OutputDevice") { + return true; + } + const ImplicitCastExpr *pImplicitCastExpr = dyn_cast<ImplicitCastExpr>(pCXXMemberCallExpr->getImplicitObjectArgument()); + std::string t2 = "0"; + if (pImplicitCastExpr) { + t2 = "2"; + QualType aType = pImplicitCastExpr->getSubExpr()->getType(); + if (aType->isPointerType()) + aType = aType->getPointeeType(); + t2 = aType.getAsString(); + if (t2 == "vcl::RenderContext") + return true; + } + report( + DiagnosticsEngine::Warning, + "Should be calling OutputDevice method through RenderContext.", + pCXXMemberCallExpr->getLocStart()) + << pCXXMemberCallExpr->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration< RenderContext > X("rendercontext", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |