avoid windres preprocessor quoting-messups with current cygwin
[LibreOffice.git] / compilerplugins / clang / rendercontext.cxx
blobc0f3acf4f3cce130522fa960902283769bf5b4dc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <string>
11 #include <iostream>
13 #include "plugin.hxx"
14 #include "check.hxx"
15 #include "clang/AST/CXXInheritance.h"
17 // Check for calls to OutputDevice methods that are not passing through RenderContext
19 namespace
22 class RenderContext:
23 public RecursiveASTVisitor<RenderContext>, public loplugin::Plugin
25 public:
26 explicit RenderContext(loplugin::InstantiationData const & data):
27 Plugin(data) {}
29 virtual void run() override {
30 TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
33 bool TraverseFunctionDecl(const FunctionDecl * decl);
35 bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *);
37 private:
38 bool mbChecking = false;
41 // We use Traverse to set a flag so we can easily ignore certain method calls
42 bool RenderContext::TraverseFunctionDecl(const FunctionDecl * pFunctionDecl)
44 if (ignoreLocation(pFunctionDecl)) {
45 return true;
47 if (!pFunctionDecl->hasBody()) {
48 return true;
50 if ( pFunctionDecl != pFunctionDecl->getCanonicalDecl() ) {
51 return true;
53 // Ignore methods inside the OutputDevice class
54 const CXXMethodDecl *pCXXMethodDecl = dyn_cast<CXXMethodDecl>(pFunctionDecl);
55 if (pCXXMethodDecl) {
56 if (loplugin::TypeCheck(pCXXMethodDecl->getParent()).Class("OutputDevice").GlobalNamespace())
57 return true;
59 // we are only currently interested in methods where the first parameter is RenderContext
60 if (pFunctionDecl->getNumParams() == 0)
61 return true;
62 if ( loplugin::TypeCheck(pFunctionDecl->getParamDecl( 0 )->getType()).Class("RenderContext").GlobalNamespace() ) {
63 return true;
65 mbChecking = true;
66 TraverseStmt(pFunctionDecl->getBody());
67 mbChecking = false;
68 return true;
71 bool RenderContext::VisitCXXMemberCallExpr(const CXXMemberCallExpr* pCXXMemberCallExpr)
73 if (!mbChecking)
74 return true;
75 if (ignoreLocation(pCXXMemberCallExpr)) {
76 return true;
78 const CXXRecordDecl *pCXXRecordDecl = pCXXMemberCallExpr->getRecordDecl();
79 if (!loplugin::TypeCheck(pCXXRecordDecl).Class("OutputDevice").GlobalNamespace()) {
80 return true;
82 // ignore a handful of methods. They will most probably still be present in Window for use during processing outside of the Paint()
83 // method lifecycle
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")
90 return true;
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")
101 return true;
103 // for calling through a reference
104 const DeclRefExpr *pDeclRefExpr = dyn_cast<DeclRefExpr>(pCXXMemberCallExpr->getImplicitObjectArgument());
105 if (pDeclRefExpr) {
106 QualType aType = pDeclRefExpr->getType();
107 std::string t2 = aType.getAsString();
108 if (t2 == "vcl::RenderContext" || t2 == "const vcl::RenderContext")
109 return true;
111 // for calling through a chain of methods
112 const CXXMemberCallExpr *pMemberExpr = dyn_cast<CXXMemberCallExpr>(pCXXMemberCallExpr->getImplicitObjectArgument());
113 if (pMemberExpr) {
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")
119 return true;
121 report(
122 DiagnosticsEngine::Warning,
123 "Should be calling OutputDevice method through RenderContext.",
124 pCXXMemberCallExpr->getLocStart())
125 << pCXXMemberCallExpr->getSourceRange();
126 return true;
129 loplugin::Plugin::Registration< RenderContext > X("rendercontext", false);
133 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */