Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / compilerplugins / clang / simplifydynamiccast.cxx
blobf305f8cbeaefb14004d764a78e33a0176f9896b6
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 <cassert>
11 #include <string>
12 #include <iostream>
13 #include <fstream>
14 #include <set>
16 #include <clang/AST/CXXInheritance.h>
17 #include "compat.hxx"
18 #include "plugin.hxx"
20 namespace
22 class SimplifyDynamicCast : public RecursiveASTVisitor<SimplifyDynamicCast>, public loplugin::Plugin
24 public:
25 explicit SimplifyDynamicCast(loplugin::InstantiationData const& data)
26 : Plugin(data)
30 virtual void run() override
32 // StringRef fn( compiler.getSourceManager().getFileEntryForID(
33 // compiler.getSourceManager().getMainFileID())->getName() );
34 // if (loplugin::isSamePathname(fn, WORKDIR "/YaccTarget/unoidl/source/sourceprovider-parser.cxx"))
35 // return;
37 TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
40 bool TraverseIfStmt(IfStmt*);
41 bool VisitCXXStaticCastExpr(CXXStaticCastExpr const*);
43 private:
44 std::vector<QualType> dynamicCastVec;
45 std::vector<Decl const*> dynamicCastSubExprVec;
46 std::vector<IfStmt const*> ifVec;
49 bool SimplifyDynamicCast::TraverseIfStmt(IfStmt* ifStmt)
51 auto condExpr = ifStmt->getCond()->IgnoreParenImpCasts();
52 auto dynamicCastExpr = dyn_cast<CXXDynamicCastExpr>(condExpr);
53 if (!dynamicCastExpr)
55 if (auto binaryOp = dyn_cast<BinaryOperator>(condExpr))
57 if (binaryOp->getOpcode() == BO_NE)
58 dynamicCastExpr
59 = dyn_cast<CXXDynamicCastExpr>(binaryOp->getLHS()->IgnoreParenImpCasts());
62 Decl const* subExprDecl = nullptr;
63 if (dynamicCastExpr)
65 auto subExprDeclRefExpr
66 = dyn_cast<DeclRefExpr>(dynamicCastExpr->getSubExpr()->IgnoreParenImpCasts());
67 if (!subExprDeclRefExpr)
68 dynamicCastExpr = nullptr;
69 else
70 subExprDecl = subExprDeclRefExpr->getDecl();
72 if (dynamicCastExpr)
74 auto qt = dynamicCastExpr->getTypeAsWritten();
75 dynamicCastVec.push_back(qt);
76 dynamicCastSubExprVec.push_back(subExprDecl);
77 ifVec.push_back(ifStmt);
79 bool ret = RecursiveASTVisitor::TraverseIfStmt(ifStmt);
80 if (dynamicCastExpr)
82 dynamicCastVec.pop_back();
83 dynamicCastSubExprVec.pop_back();
84 ifVec.pop_back();
86 return ret;
89 bool SimplifyDynamicCast::VisitCXXStaticCastExpr(CXXStaticCastExpr const* staticCastExpr)
91 if (ignoreLocation(staticCastExpr))
92 return true;
93 if (dynamicCastVec.empty())
94 return true;
96 auto qt = staticCastExpr->getTypeAsWritten();
97 auto it = std::find(dynamicCastVec.begin(), dynamicCastVec.end(), qt);
98 if (it == dynamicCastVec.end())
99 return true;
100 int idx = it - dynamicCastVec.begin();
101 auto subExprDecl = dyn_cast<DeclRefExpr>(staticCastExpr->getSubExpr()->IgnoreParenImpCasts());
102 if (!subExprDecl)
103 return true;
104 if (dynamicCastSubExprVec[idx] != subExprDecl->getDecl())
105 return true;
106 report(DiagnosticsEngine::Warning, "simplify, use var in if", staticCastExpr->getLocStart())
107 << staticCastExpr->getSourceRange();
108 auto ifStmt = ifVec[idx];
109 report(DiagnosticsEngine::Note, "if here", ifStmt->getLocStart()) << ifStmt->getSourceRange();
110 return true;
113 loplugin::Plugin::Registration<SimplifyDynamicCast> X("simplifydynamiccast", true);
116 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */