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/.
9 #ifndef LO_CLANG_SHARED_PLUGINS
18 TODO multiplying/otherop on a combination of a float and int, and then truncating to int. like this:
19 float getRotation() {}
20 int moRotation = -F_PI180 * 90 * getRotation();
24 class IntVsFloat
: public loplugin::FilteringPlugin
<IntVsFloat
>
27 explicit IntVsFloat(loplugin::InstantiationData
const& data
)
28 : loplugin::FilteringPlugin
<IntVsFloat
>(data
)
32 void run() override
{ TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
34 bool VisitVarDecl(VarDecl
const*);
35 bool VisitBinaryOperator(BinaryOperator
const*);
38 compat::optional
<double> getExprValue(Expr
const* expr
);
41 bool IntVsFloat::VisitVarDecl(VarDecl
const* varDecl
)
43 if (ignoreLocation(varDecl
->getLocation()))
45 auto init
= varDecl
->getInit();
48 init
= init
->IgnoreImpCasts();
49 if (varDecl
->getType()->isFloatingType())
52 compat::optional
<double> d
= getExprValue(init
);
55 if (static_cast<long>(*d
) == *d
)
57 report(DiagnosticsEngine::Warning
, "assigning constant float value to int truncates data",
59 << init
->getSourceRange();
64 bool IntVsFloat::VisitBinaryOperator(BinaryOperator
const* op
)
66 if (op
->getOpcode() != BO_EQ
)
70 if (ignoreLocation(op
->getBeginLoc()))
72 auto lhs
= op
->getLHS()->IgnoreImpCasts();
73 auto rhs
= op
->getRHS()->IgnoreImpCasts();
74 if (!lhs
->getType()->isFloatingType())
76 if (!lhs
->getType()->isFloatingType())
78 if (rhs
->getType()->isFloatingType())
80 compat::optional
<double> d
= getExprValue(lhs
);
83 if (static_cast<long>(*d
) == *d
)
85 report(DiagnosticsEngine::Warning
, "comparing integer to float constant, can never be true",
87 << op
->getSourceRange();
91 compat::optional
<double> IntVsFloat::getExprValue(Expr
const* expr
)
93 // Of the available clang Evaluate* APIs, this is the __only__ one that produces useful output
94 // (as of 17 Aug 2018 checkout of clang, ie. towards clang 7)
96 if (expr
->isValueDependent())
97 return compat::optional
<double>();
98 Expr::EvalResult evalResult
;
99 if (!expr
->EvaluateAsRValue(evalResult
, compiler
.getASTContext()))
100 return compat::optional
<double>();
101 if (!evalResult
.Val
.isFloat())
102 return compat::optional
<double>();
103 llvm::APFloat floatResult
= evalResult
.Val
.getFloat();
105 floatResult
.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven
, &losesInfo
);
107 double d
= floatResult
.convertToDouble();
111 loplugin::Plugin::Registration
<IntVsFloat
> intvsfloat("intvsfloat");
115 #endif // LO_CLANG_SHARED_PLUGINS
117 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */