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>
22 class SimplifyDynamicCast
: public RecursiveASTVisitor
<SimplifyDynamicCast
>, public loplugin::Plugin
25 explicit SimplifyDynamicCast(loplugin::InstantiationData
const& 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"))
37 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
40 bool TraverseIfStmt(IfStmt
*);
41 bool VisitCXXStaticCastExpr(CXXStaticCastExpr
const*);
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
);
55 if (auto binaryOp
= dyn_cast
<BinaryOperator
>(condExpr
))
57 if (binaryOp
->getOpcode() == BO_NE
)
59 = dyn_cast
<CXXDynamicCastExpr
>(binaryOp
->getLHS()->IgnoreParenImpCasts());
62 Decl
const* subExprDecl
= nullptr;
65 auto subExprDeclRefExpr
66 = dyn_cast
<DeclRefExpr
>(dynamicCastExpr
->getSubExpr()->IgnoreParenImpCasts());
67 if (!subExprDeclRefExpr
)
68 dynamicCastExpr
= nullptr;
70 subExprDecl
= subExprDeclRefExpr
->getDecl();
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
);
82 dynamicCastVec
.pop_back();
83 dynamicCastSubExprVec
.pop_back();
89 bool SimplifyDynamicCast::VisitCXXStaticCastExpr(CXXStaticCastExpr
const* staticCastExpr
)
91 if (ignoreLocation(staticCastExpr
))
93 if (dynamicCastVec
.empty())
96 auto qt
= staticCastExpr
->getTypeAsWritten();
97 auto it
= std::find(dynamicCastVec
.begin(), dynamicCastVec
.end(), qt
);
98 if (it
== dynamicCastVec
.end())
100 int idx
= it
- dynamicCastVec
.begin();
101 auto subExprDecl
= dyn_cast
<DeclRefExpr
>(staticCastExpr
->getSubExpr()->IgnoreParenImpCasts());
104 if (dynamicCastSubExprVec
[idx
] != subExprDecl
->getDecl())
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();
113 loplugin::Plugin::Registration
<SimplifyDynamicCast
> X("simplifydynamiccast", true);
116 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */