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/.
16 #include <clang/AST/CXXInheritance.h>
21 class SimplifyDynamicCast
: public loplugin::FilteringPlugin
<SimplifyDynamicCast
>
24 explicit SimplifyDynamicCast(loplugin::InstantiationData
const& data
)
25 : FilteringPlugin(data
)
29 virtual void run() override
31 // StringRef fn(handler.getMainFileName());
32 // if (loplugin::isSamePathname(fn, WORKDIR "/YaccTarget/unoidl/source/sourceprovider-parser.cxx"))
35 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
38 bool TraverseIfStmt(IfStmt
*);
39 bool VisitCXXStaticCastExpr(CXXStaticCastExpr
const*);
42 std::vector
<QualType
> dynamicCastVec
;
43 std::vector
<Decl
const*> dynamicCastSubExprVec
;
44 std::vector
<IfStmt
const*> ifVec
;
47 bool SimplifyDynamicCast::TraverseIfStmt(IfStmt
* ifStmt
)
49 CXXDynamicCastExpr
const* dynamicCastExpr
= nullptr;
50 if (Expr
const* condExpr
= ifStmt
->getCond())
52 condExpr
= condExpr
->IgnoreParenImpCasts();
53 dynamicCastExpr
= dyn_cast
<CXXDynamicCastExpr
>(condExpr
);
56 if (auto binaryOp
= dyn_cast
<BinaryOperator
>(condExpr
))
58 if (binaryOp
->getOpcode() == BO_NE
)
60 = dyn_cast
<CXXDynamicCastExpr
>(binaryOp
->getLHS()->IgnoreParenImpCasts());
64 Decl
const* subExprDecl
= nullptr;
67 auto subExprDeclRefExpr
68 = dyn_cast
<DeclRefExpr
>(dynamicCastExpr
->getSubExpr()->IgnoreParenImpCasts());
69 if (!subExprDeclRefExpr
)
70 dynamicCastExpr
= nullptr;
72 subExprDecl
= subExprDeclRefExpr
->getDecl();
76 auto qt
= dynamicCastExpr
->getTypeAsWritten();
77 dynamicCastVec
.push_back(qt
);
78 dynamicCastSubExprVec
.push_back(subExprDecl
);
79 ifVec
.push_back(ifStmt
);
81 bool ret
= RecursiveASTVisitor::TraverseIfStmt(ifStmt
);
84 dynamicCastVec
.pop_back();
85 dynamicCastSubExprVec
.pop_back();
91 bool SimplifyDynamicCast::VisitCXXStaticCastExpr(CXXStaticCastExpr
const* staticCastExpr
)
93 if (ignoreLocation(staticCastExpr
))
95 if (dynamicCastVec
.empty())
98 auto qt
= staticCastExpr
->getTypeAsWritten();
99 auto it
= std::find(dynamicCastVec
.begin(), dynamicCastVec
.end(), qt
);
100 if (it
== dynamicCastVec
.end())
102 int idx
= it
- dynamicCastVec
.begin();
103 auto subExprDecl
= dyn_cast
<DeclRefExpr
>(staticCastExpr
->getSubExpr()->IgnoreParenImpCasts());
106 if (dynamicCastSubExprVec
[idx
] != subExprDecl
->getDecl())
108 report(DiagnosticsEngine::Warning
, "simplify, use var in if", staticCastExpr
->getBeginLoc())
109 << staticCastExpr
->getSourceRange();
110 auto ifStmt
= ifVec
[idx
];
111 report(DiagnosticsEngine::Note
, "if here", ifStmt
->getBeginLoc()) << ifStmt
->getSourceRange();
115 loplugin::Plugin::Registration
<SimplifyDynamicCast
> X("simplifydynamiccast", true);
118 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */