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/.
15 #include "clang/AST/CXXInheritance.h"
17 // Check for calls to OutputDevice methods that are not passing through RenderContext
23 public RecursiveASTVisitor
<RenderContext
>, public loplugin::Plugin
26 explicit RenderContext(InstantiationData
const & data
): Plugin(data
) {}
28 virtual void run() override
{
29 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
32 bool TraverseFunctionDecl(const FunctionDecl
* decl
);
34 bool VisitCXXMemberCallExpr(const CXXMemberCallExpr
*);
37 bool mbChecking
= false;
40 // We use Traverse to set a flag so we can easily ignore certain method calls
41 bool RenderContext::TraverseFunctionDecl(const FunctionDecl
* pFunctionDecl
)
43 if (ignoreLocation(pFunctionDecl
)) {
46 if (!pFunctionDecl
->hasBody()) {
49 if ( pFunctionDecl
!= pFunctionDecl
->getCanonicalDecl() ) {
52 // Ignore methods inside the OutputDevice class
53 const CXXMethodDecl
*pCXXMethodDecl
= dyn_cast
<CXXMethodDecl
>(pFunctionDecl
);
55 std::string aParentName
= pCXXMethodDecl
->getParent()->getQualifiedNameAsString();
56 if (aParentName
== "OutputDevice")
59 // we are only currently interested in methods where the first parameter is RenderContext
60 if (pFunctionDecl
->getNumParams() == 0)
62 string arg0
= pFunctionDecl
->getParamDecl( 0 )->getType().getAsString();
63 if ( arg0
.find("RenderContext") != std::string::npos
) {
67 TraverseStmt(pFunctionDecl
->getBody());
72 bool RenderContext::VisitCXXMemberCallExpr(const CXXMemberCallExpr
* pCXXMemberCallExpr
)
76 if (ignoreLocation(pCXXMemberCallExpr
)) {
79 const CXXRecordDecl
*pCXXRecordDecl
= pCXXMemberCallExpr
->getRecordDecl();
80 if (pCXXRecordDecl
->getQualifiedNameAsString() != "OutputDevice") {
83 // ignore a handful of methods. They will most probably still be present in Window for use during processing outside of the Paint()
85 const CXXMethodDecl
*pCXXMethodDecl
= pCXXMemberCallExpr
->getMethodDecl();
86 if (pCXXMethodDecl
->isInstance()) {
87 StringRef name
= pCXXMethodDecl
->getName();
88 if (name
== "LogicToPixel" || name
== "GetMapMode" || name
== "GetFontMetric" || name
== "LogicToLogic"
89 || name
== "PixelToLogic" || name
== "SetDigitLanguage")
94 // for calling through a pointer
95 const ImplicitCastExpr
*pImplicitCastExpr
= dyn_cast
<ImplicitCastExpr
>(pCXXMemberCallExpr
->getImplicitObjectArgument());
96 std::string x
= "0"; // for debugging
97 if (pImplicitCastExpr
) {
99 QualType aType
= pImplicitCastExpr
->getSubExpr()->getType();
100 if (aType
->isPointerType())
101 aType
= aType
->getPointeeType();
102 std::string t2
= aType
.getAsString();
103 if (t2
== "vcl::RenderContext" || t2
== "const vcl::RenderContext")
106 // for calling through a reference
107 const DeclRefExpr
*pDeclRefExpr
= dyn_cast
<DeclRefExpr
>(pCXXMemberCallExpr
->getImplicitObjectArgument());
110 QualType aType
= pDeclRefExpr
->getType();
111 std::string t2
= aType
.getAsString();
112 if (t2
== "vcl::RenderContext" || t2
== "const vcl::RenderContext")
115 // for calling through a chain of methods
116 const CXXMemberCallExpr
*pMemberExpr
= dyn_cast
<CXXMemberCallExpr
>(pCXXMemberCallExpr
->getImplicitObjectArgument());
119 QualType aType
= pMemberExpr
->getType();
120 if (aType
->isPointerType())
121 aType
= aType
->getPointeeType();
122 std::string t2
= aType
.getAsString();
124 if (t2
== "vcl::RenderContext" || t2
== "const vcl::RenderContext")
128 DiagnosticsEngine::Warning
,
129 // + x + pCXXMemberCallExpr->getImplicitObjectArgument()->getStmtClassName()
130 "Should be calling OutputDevice method through RenderContext.",
131 pCXXMemberCallExpr
->getLocStart())
132 << pCXXMemberCallExpr
->getSourceRange();
136 loplugin::Plugin::Registration
< RenderContext
> X("rendercontext", false);
140 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */