tdf#130857 qt weld: Support "Insert Breaks" dialog
[LibreOffice.git] / compilerplugins / clang / intvsfloat.cxx
blobf6bd996a1e6dfb50b926ce14bed7273ea3e8f87e
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 */
9 #ifndef LO_CLANG_SHARED_PLUGINS
11 #include "plugin.hxx"
12 #include "check.hxx"
13 #include "compat.hxx"
14 #include <iostream>
16 /**
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();
22 namespace
24 class IntVsFloat : public loplugin::FilteringPlugin<IntVsFloat>
26 public:
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*);
37 private:
38 compat::optional<double> getExprValue(Expr const* expr);
41 bool IntVsFloat::VisitVarDecl(VarDecl const* varDecl)
43 if (ignoreLocation(varDecl->getLocation()))
44 return true;
45 auto init = varDecl->getInit();
46 if (!init)
47 return true;
48 init = init->IgnoreImpCasts();
49 if (varDecl->getType()->isFloatingType())
50 return true;
51 // init->dump();
52 compat::optional<double> d = getExprValue(init);
53 if (!d)
54 return true;
55 if (static_cast<long>(*d) == *d)
56 return true;
57 report(DiagnosticsEngine::Warning, "assigning constant float value to int truncates data",
58 init->getBeginLoc())
59 << init->getSourceRange();
61 return true;
64 bool IntVsFloat::VisitBinaryOperator(BinaryOperator const* op)
66 if (op->getOpcode() != BO_EQ)
68 return true;
70 if (ignoreLocation(op->getBeginLoc()))
71 return true;
72 auto lhs = op->getLHS()->IgnoreImpCasts();
73 auto rhs = op->getRHS()->IgnoreImpCasts();
74 if (!lhs->getType()->isFloatingType())
75 std::swap(lhs, rhs);
76 if (!lhs->getType()->isFloatingType())
77 return true;
78 if (rhs->getType()->isFloatingType())
79 return true;
80 compat::optional<double> d = getExprValue(lhs);
81 if (!d)
82 return true;
83 if (static_cast<long>(*d) == *d)
84 return true;
85 report(DiagnosticsEngine::Warning, "comparing integer to float constant, can never be true",
86 op->getBeginLoc())
87 << op->getSourceRange();
88 return true;
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();
104 bool losesInfo;
105 floatResult.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &losesInfo);
107 double d = floatResult.convertToDouble();
108 return d;
111 loplugin::Plugin::Registration<IntVsFloat> intvsfloat("intvsfloat");
113 } // namespace
115 #endif // LO_CLANG_SHARED_PLUGINS
117 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */