1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
14 #include "clang/AST/CXXInheritance.h"
16 // Check for calls to OutputDevice methods that are not passing through RenderContext
22 public RecursiveASTVisitor
<RenderContext
>, public loplugin::Plugin
25 explicit RenderContext(InstantiationData
const & data
): Plugin(data
) {}
27 virtual void run() override
{
28 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
31 bool TraverseFunctionDecl(const FunctionDecl
* decl
);
33 bool VisitCXXMemberCallExpr(const CXXMemberCallExpr
*);
36 bool mbChecking
= false;
39 // We use Traverse to set a flag so we can easily ignore certain method calls
40 bool RenderContext::TraverseFunctionDecl(const FunctionDecl
* pFunctionDecl
)
42 if (ignoreLocation(pFunctionDecl
)) {
45 if (!pFunctionDecl
->hasBody()) {
48 if ( pFunctionDecl
!= pFunctionDecl
->getCanonicalDecl() ) {
51 // Ignore methods inside the OutputDevice class
52 const CXXMethodDecl
*pCXXMethodDecl
= dyn_cast
<CXXMethodDecl
>(pFunctionDecl
);
54 std::string aParentName
= pCXXMethodDecl
->getParent()->getQualifiedNameAsString();
55 if (aParentName
== "OutputDevice")
58 // we are only currently interested in methods where the first parameter is RenderContext
59 if (pFunctionDecl
->getNumParams() == 0)
61 string arg0
= pFunctionDecl
->getParamDecl( 0 )->getType().getAsString();
62 if ( arg0
.find("RenderContext") != std::string::npos
) {
66 TraverseStmt(pFunctionDecl
->getBody());
71 bool RenderContext::VisitCXXMemberCallExpr(const CXXMemberCallExpr
* pCXXMemberCallExpr
)
75 if (ignoreLocation(pCXXMemberCallExpr
)) {
78 const CXXRecordDecl
*pCXXRecordDecl
= pCXXMemberCallExpr
->getRecordDecl();
79 if (pCXXRecordDecl
->getQualifiedNameAsString() != "OutputDevice") {
82 // ignore a handful of methods. They will most probably still be present in Window for use during processing outside of the Paint()
84 const CXXMethodDecl
*pCXXMethodDecl
= pCXXMemberCallExpr
->getMethodDecl();
85 if (pCXXMethodDecl
->isInstance()) {
86 StringRef name
= pCXXMethodDecl
->getName();
87 if (name
== "LogicToPixel" || name
== "GetMapMode" || name
== "GetFontMetric" || name
== "LogicToLogic"
88 || name
== "PixelToLogic" || name
== "SetDigitLanguage")
93 // for calling through a pointer
94 const ImplicitCastExpr
*pImplicitCastExpr
= dyn_cast
<ImplicitCastExpr
>(pCXXMemberCallExpr
->getImplicitObjectArgument());
95 if (pImplicitCastExpr
) {
96 QualType aType
= pImplicitCastExpr
->getSubExpr()->getType();
97 if (aType
->isPointerType())
98 aType
= aType
->getPointeeType();
99 std::string t2
= aType
.getAsString();
100 if (t2
== "vcl::RenderContext" || t2
== "const vcl::RenderContext")
103 // for calling through a reference
104 const DeclRefExpr
*pDeclRefExpr
= dyn_cast
<DeclRefExpr
>(pCXXMemberCallExpr
->getImplicitObjectArgument());
106 QualType aType
= pDeclRefExpr
->getType();
107 std::string t2
= aType
.getAsString();
108 if (t2
== "vcl::RenderContext" || t2
== "const vcl::RenderContext")
111 // for calling through a chain of methods
112 const CXXMemberCallExpr
*pMemberExpr
= dyn_cast
<CXXMemberCallExpr
>(pCXXMemberCallExpr
->getImplicitObjectArgument());
114 QualType aType
= pMemberExpr
->getType();
115 if (aType
->isPointerType())
116 aType
= aType
->getPointeeType();
117 std::string t2
= aType
.getAsString();
118 if (t2
== "vcl::RenderContext" || t2
== "const vcl::RenderContext")
122 DiagnosticsEngine::Warning
,
123 "Should be calling OutputDevice method through RenderContext.",
124 pCXXMemberCallExpr
->getLocStart())
125 << pCXXMemberCallExpr
->getSourceRange();
129 loplugin::Plugin::Registration
< RenderContext
> X("rendercontext", false);
133 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */