1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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 
10 #include <cassert>
11 #include <string>
12 #include <iostream>
13 #include <fstream>
14 #include <set>
15 
16 #include "check.hxx"
17 #include "plugin.hxx"
18 
19 /**
20 comparing floating point numbers using == or != is a bad idea.
21 */
22 
23 namespace {
24 
25 class FpComparison:
26     public loplugin::FilteringPlugin<FpComparison>
27 {
28 public:
FpComparison(loplugin::InstantiationData const & data)29     explicit FpComparison(loplugin::InstantiationData const & data):
30         FilteringPlugin(data) {}
31 
run()32     virtual void run() override
33     {
34         vclFloatDevicePixel = compiler.getPreprocessor()
35             .getIdentifierInfo("VCL_FLOAT_DEVICE_PIXEL")->hasMacroDefinition();
36         TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
37     }
38 
39     bool VisitBinaryOperator(const BinaryOperator* );
40     bool TraverseFunctionDecl(FunctionDecl* );
41     bool TraverseCXXMethodDecl(CXXMethodDecl* );
42 private:
43     bool ignore(FunctionDecl* );
44     enum class EState { None, TraverseProcess, TraverseIgnore };
45     EState meState = EState::None;
46     bool vclFloatDevicePixel;
47 };
48 
TraverseFunctionDecl(FunctionDecl * function)49 bool FpComparison::TraverseFunctionDecl(FunctionDecl* function)
50 {
51     bool bIgnore = ignore(function);
52     meState = bIgnore ? EState::TraverseIgnore : EState::TraverseProcess;
53     bool bRet = RecursiveASTVisitor::TraverseFunctionDecl(function);
54     meState = EState::None;
55     return bRet;
56 }
57 
TraverseCXXMethodDecl(CXXMethodDecl * function)58 bool FpComparison::TraverseCXXMethodDecl(CXXMethodDecl* function)
59 {
60     bool bIgnore = ignore(function);
61     meState = bIgnore ? EState::TraverseIgnore : EState::TraverseProcess;
62     bool bRet = RecursiveASTVisitor::TraverseCXXMethodDecl(function);
63     meState = EState::None;
64     return bRet;
65 }
66 
ignore(FunctionDecl * function)67 bool FpComparison::ignore(FunctionDecl* function)
68 {
69     if (ignoreLocation(function)) {
70         return true;
71     }
72     // we assume that these modules know what they are doing with FP stuff
73     StringRef aFileName = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(function->getLocStart()));
74     if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/sc/")) {
75         return true;
76     }
77     if (!function->doesThisDeclarationHaveABody()) {
78         return true;
79     }
80      // Ignore operator== and operator!=
81     if (function->getOverloadedOperator() == OO_EqualEqual
82         || function->getOverloadedOperator() == OO_ExclaimEqual) {
83         return true;
84     }
85     // ignore known good functions
86     loplugin::DeclCheck dc(function);
87     if ((dc.Function("approxEqual").Namespace("math").Namespace("rtl")
88          .GlobalNamespace())
89         || dc.Function("doubleToString").AnonymousNamespace().GlobalNamespace()
90         || dc.Function("stringToDouble").AnonymousNamespace().GlobalNamespace()
91         || dc.Function("rtl_math_round").GlobalNamespace()
92         || dc.Function("rtl_math_approxEqual").GlobalNamespace()
93         || dc.Function("rtl_math_approxValue").GlobalNamespace()
94         || dc.Function("rtl_math_asinh").GlobalNamespace()
95         || dc.Function("rtl_math_acosh").GlobalNamespace()
96         || dc.Function("_equalSequence").Namespace("cppu").GlobalNamespace()
97             // cppu/source/uno/eq.hxx
98         || dc.Function("_equalData").Namespace("cppu").GlobalNamespace()
99             // cppu/source/uno/eq.hxx
100         || dc.Function("equalFont").Namespace("xmlscript").GlobalNamespace()
101             // xmlscript/source/xmldlg_imexp/xmldlg_export.cxx
102         || (dc.Function("initialize").Class("Impl2").AnonymousNamespace()
103             .GlobalNamespace())
104             // testtools/source/bridgetest/constructors.cxx
105         || (dc.Function("initialize").Class("Impl").AnonymousNamespace()
106             .GlobalNamespace())
107             // testtools/source/bridgetest/constructors.cxx
108         || dc.Function("lok_approxEqual").AnonymousNamespace().GlobalNamespace()
109             // libreofficekit/source/gtk/lokdocview.cxx
110         // These might need fixing:
111         || (dc.Function("getSmallestDistancePointToPolygon").Namespace("utils")
112             .Namespace("basegfx").GlobalNamespace())
113             // basegfx/source/polygon/b2dpolygontools.cxx
114         || (dc.Function("getSmallestDistancePointToPolyPolygon")
115             .Namespace("utils").Namespace("basegfx").GlobalNamespace())
116             // basegfx/source/polygon/b2dpolypolygontools.cxx
117         || dc.Function("performTest").Namespace("bridge_test").GlobalNamespace()
118             // testtools/source/bridgetest/bridgetest.cxx
119         || dc.Function("equals").Namespace("bridge_test").GlobalNamespace()
120         || (dc.Function("lcl_getNANInsteadDBL_MIN").AnonymousNamespace()
121             .GlobalNamespace())
122             // chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx
123         || dc.Function("compareSubstring").Class("ChapterCollator").Namespace("i18npool").GlobalNamespace()
124         || dc.Function("setDateTime").Class("Calendar_gregorian").Namespace("i18npool").GlobalNamespace()
125         || dc.Function("setLocalDateTime").Class("Calendar_gregorian").Namespace("i18npool").GlobalNamespace()
126         //TODO:
127         || dc.Function("ImpCheckCondition").Class("SvNumberformat").GlobalNamespace()
128         || dc.Function("GetTimeFormat").Class("SvNumberFormatter").GlobalNamespace()
129         || dc.Function("GuessDateTimeFormat").Class("SvNumberFormatter").GlobalNamespace()
130         || dc.Function("GetEditFormat").Class("SvNumberFormatter").GlobalNamespace()
131         || dc.Function("getSmallestDistancePointToBezierSegment").Class("B2DCubicBezier").Namespace("basegfx").GlobalNamespace()
132         || dc.Function("getLength").Class("B3DVector").Namespace("basegfx").GlobalNamespace()
133         || dc.Function("getXZLength").Class("B3DVector").Namespace("basegfx").GlobalNamespace()
134         || dc.Function("getYZLength").Class("B3DVector").Namespace("basegfx").GlobalNamespace()
135         || dc.Function("impSolve").Class("solver").AnonymousNamespace().Namespace("basegfx").GlobalNamespace()
136         || dc.Function("getB2DPolyPolygon").Class("solver").AnonymousNamespace().Namespace("basegfx").GlobalNamespace()
137         || dc.Function("getNormal").Class("CoordinateDataArray3D").GlobalNamespace()
138         || dc.Function("append").Class("ImplPolygon").AnonymousNamespace().Namespace("basegfx").GlobalNamespace()
139         || dc.Function("finish").Class("ImplPolygon").AnonymousNamespace().Namespace("basegfx").GlobalNamespace()
140         || dc.Function("convertMeasure").Class("Converter").Namespace("sax").GlobalNamespace()
141         || dc.Function("convertDouble").Class("Converter").Namespace("sax").GlobalNamespace()
142         || dc.Function("convertDuration").Class("Converter").Namespace("sax").GlobalNamespace()
143         || dc.Function("Frustum").Class("B3dTransformationSet").GlobalNamespace()
144         || dc.Function("Ortho").Class("B3dTransformationSet").GlobalNamespace()
145         || dc.Function("SetRatio").Class("B3dTransformationSet").GlobalNamespace()
146         || dc.Function("SetDeviceRectangle").Class("B3dTransformationSet").GlobalNamespace()
147         || dc.Function("HSBtoRGB").Class("Color").GlobalNamespace()
148         || dc.Function("Normalize").Class("Vector2D").Namespace("tools").GlobalNamespace()
149         || dc.Function("setAcceleration").Class("AnimationNode").Namespace("animcore").GlobalNamespace()
150         || dc.Function("setDecelerate").Class("AnimationNode").Namespace("animcore").GlobalNamespace()
151         || dc.Function("setVolume").Class("AnimationNode").Namespace("animcore").GlobalNamespace()
152         || dc.Function("setIterateInterval").Class("AnimationNode").Namespace("animcore").GlobalNamespace()
153         || dc.Function("createElement").Struct("Style").Namespace("xmlscript").GlobalNamespace()
154         || dc.Function("set_property").Class("Window").Namespace("vcl").GlobalNamespace()
155         || dc.Function("Adjust").Class("Bitmap").GlobalNamespace()
156         || dc.Function("ImplWriteActions").Class("SVMConverter").GlobalNamespace()
157         || dc.Function("Mirror").Class("GDIMetaFile").GlobalNamespace()
158         || dc.Function("Adjust").Class("GDIMetaFile").GlobalNamespace()
159         || dc.Function("Scale").Class("MetaCommentAction").GlobalNamespace()
160         || dc.Function("ImplGetGamma").Class("PNGReaderImpl").Namespace("vcl").GlobalNamespace()
161         || dc.Function("playMetafile").Class("PDFWriterImpl").Namespace("vcl").GlobalNamespace()
162         || dc.Function("invert").Class("Matrix3").Namespace("vcl").GlobalNamespace()
163         || dc.Function("emitTilings").Class("PDFWriterImpl").Namespace("vcl").GlobalNamespace()
164         || dc.Function("drawHorizontalGlyphs").Class("PDFWriterImpl").Namespace("vcl").GlobalNamespace()
165         || dc.Function("ImplWrite").Class("EMFWriter").GlobalNamespace()
166         || dc.Function("WriteRecords").Class("WMFWriter").GlobalNamespace()
167         || dc.Function("convertOneTypeEsc").Class("CffSubsetterContext").GlobalNamespace()
168         || dc.Function("ApplyGlyphTransform").Class("FreetypeFont").GlobalNamespace()
169         || dc.Function("JoinVerticalClipRectangles").Class("PrinterGfx").Namespace("psp").GlobalNamespace()
170         || dc.Function("PSSetLineWidth").Class("PrinterGfx").Namespace("psp").GlobalNamespace()
171         || dc.Function("DrawEPS").Class("PrinterGfx").Namespace("psp").GlobalNamespace()
172         || dc.Function("addDrawRectangle").Class("RenderList").GlobalNamespace()
173         || dc.Function("addDrawPolyPolygon").Class("RenderList").GlobalNamespace()
174         || dc.Function("addDrawPolyLine").Class("RenderList").GlobalNamespace()
175         || dc.Function("ApplyMatrix").Class("OpenGLProgram").GlobalNamespace()
176         || dc.Function("GuessWidth").Class("BorderWidthImpl").GlobalNamespace()
177         || dc.Function("ImplSetValue").Class("FormattedField").GlobalNamespace()
178         || dc.Function("IsAdjusted").Class("GraphicAttr").GlobalNamespace()
179         || dc.Operator(OO_Call).Struct("SpriteWeakOrder").Namespace("canvas").GlobalNamespace()
180         || dc.Function("setAlpha").Class("CanvasCustomSpriteHelper").Namespace("canvas").GlobalNamespace()
181         || dc.Function("setPriority").Class("CanvasCustomSpriteHelper").Namespace("canvas").GlobalNamespace()
182         || dc.Function("createFillGraphicAttribute").Class("SdrFillGraphicAttribute").Namespace("attribute").Namespace("drawinglayer").GlobalNamespace()
183         || dc.Function("create2DDecomposition").Class("ScenePrimitive2D").Namespace("primitive2d").Namespace("drawinglayer").GlobalNamespace()
184         || dc.Function("createAtom").Class("SvgLinearGradientPrimitive2D").Namespace("primitive2d").Namespace("drawinglayer").GlobalNamespace()
185         || dc.Function("createAtom").Class("SvgRadialGradientPrimitive2D").Namespace("primitive2d").Namespace("drawinglayer").GlobalNamespace()
186         || dc.Function("FoldConstantsBinaryNode").Class("SbiExprNode").GlobalNamespace()
187         || dc.Function("Format").Class("SbxValue").GlobalNamespace()
188         || dc.Function("Compare").Class("SbxValue").GlobalNamespace()
189         || dc.Function("SelectPlayToolBoxItem").Class("MediaControlBase").Namespace("avmedia").GlobalNamespace()
190         || dc.Function("convertDateTime").Class("SvXMLUnitConverter").GlobalNamespace()
191         || dc.Function("exportAudio").Class("AnimationsExporterImpl").Namespace("xmloff").GlobalNamespace()
192         || dc.Function("StartElement").Class("XMLEnhancedCustomShapeContext").GlobalNamespace()
193         || dc.Function("SetString").Class("SdXMLImExTransform2D").GlobalNamespace()
194         || dc.Function("SetString").Class("SdXMLImExTransform3D").GlobalNamespace()
195         || dc.Function("ExportPart_Impl").Class("SvXMLNumFmtExport").GlobalNamespace()
196         || dc.Function("AddNumber").Class("SvXMLNumFormatContext").GlobalNamespace()
197         || dc.Function("GetColorData").Class("EnhancedCustomShape2d").GlobalNamespace()
198         || dc.Function("AdaptObjColor").Class("EnhancedCustomShape2d").GlobalNamespace()
199         || dc.Function("RotateScene").Class("E3dScene").GlobalNamespace()
200         || dc.Function("createViewIndependentPrimitive2DSequence").Class("ViewContactOfSdrCaptionObj").Namespace("contact").Namespace("sdr").GlobalNamespace()
201         || dc.Function("PostItemChange").Class("E3dSceneProperties").Namespace("properties").Namespace("sdr").GlobalNamespace()
202         || dc.Function("NbcRotate").Class("SdrObject").GlobalNamespace()
203         || dc.Function("TakeObjNameSingul").Class("SdrPathObj").GlobalNamespace()
204         || dc.Function("NbcInsPoint").Class("SdrPathObj").GlobalNamespace()
205         || dc.Function("setValue").Class("Cell").Namespace("table").Namespace("sdr").GlobalNamespace()
206         || dc.Function("implSetDepth").Class("ExtrusionDepthWindow").Namespace("svx").GlobalNamespace()
207         || dc.Function("PointsToBezier").Class("XPolygon").GlobalNamespace()
208         || dc.Function("SetPosition").Class("Svx3DLightControl").GlobalNamespace()
209         || dc.Function("SetRotation").Class("Svx3DLightControl").GlobalNamespace()
210         || dc.Function("PlayToolBoxSelectHdl").Class("MediaPlaybackPanel").Namespace("sidebar").Namespace("svx").GlobalNamespace()
211         || dc.Function("CreateGraphicProperties").Class("EscherPropertyContainer").GlobalNamespace()
212         || dc.Function("renderSprite").Class("CanvasCustomSprite").Namespace("oglcanvas").GlobalNamespace()
213         || dc.Operator(OO_Call).Struct("SpriteComparator").AnonymousNamespace().Namespace("oglcanvas").GlobalNamespace()
214         || dc.Function("isHorizontalAxis").Class("TickFactory2D").Namespace("chart").GlobalNamespace()
215         || dc.Function("isVerticalAxis").Class("TickFactory2D").Namespace("chart").GlobalNamespace()
216         || dc.Function("getDistanceAxisTickToText").Class("TickFactory2D").Namespace("chart").GlobalNamespace()
217         || dc.Function("calculateExplicitIncrementAndScaleForLogarithmic").Class("ScaleAutomatism").Namespace("chart").GlobalNamespace()
218         || dc.Function("calculateExplicitIncrementAndScaleForLinear").Class("ScaleAutomatism").Namespace("chart").GlobalNamespace()
219         || dc.Function("makeTickmarkPropertiesForComplexCategories").Struct("AxisProperties").Namespace("chart").GlobalNamespace()
220         || dc.Function("createShapes").Class("BarChart").Namespace("chart").GlobalNamespace()
221         || dc.Function("transform").Class("Linear3DTransformation").Namespace("chart").GlobalNamespace()
222         || dc.Function("CalculateCubicSplines").Class("SplineCalculater").Namespace("chart").GlobalNamespace()
223         || dc.Function("setDiagramPositioning").Class("DiagramHelper").Namespace("chart").GlobalNamespace()
224         || dc.Function("centerGrow").Class("RelativePositionHelper").Namespace("chart").GlobalNamespace()
225         || dc.Function("pushToPropMap").Struct("FillProperties").Namespace("drawingml").Namespace("oox").GlobalNamespace()
226         || dc.Function("convertFromProperties").Class("AxFontDataModel").Namespace("ole").Namespace("oox").GlobalNamespace()
227         || dc.Function("isNotANumber").Class("ChartDataWrapper").Namespace("wrapper").Namespace("chart").GlobalNamespace()
228         || dc.Function("Reset").Class("ErrorBarResources").Namespace("chart").GlobalNamespace()
229         || dc.Function("ApplySpecialItem").Class("AxisItemConverter").Namespace("wrapper").Namespace("chart").GlobalNamespace()
230         || dc.Function("ApplySpecialItem").Class("DataPointItemConverter").Namespace("wrapper").Namespace("chart").GlobalNamespace()
231         || dc.Function("ApplySpecialItem").Class("TitleItemConverter").Namespace("wrapper").Namespace("chart").GlobalNamespace()
232         || dc.Function("ApplySpecialItem").Class("TextLabelItemConverter").Namespace("wrapper").Namespace("chart").GlobalNamespace()
233         || dc.Function("operate").Class("OOp_COMPARE").Namespace("file").Namespace("connectivity").GlobalNamespace()
234         || dc.Function("Write").Class("ORTFImportExport").Namespace("dbaui").GlobalNamespace()
235         || dc.Function("appendRow").Class("ORTFImportExport").Namespace("dbaui").GlobalNamespace()
236         || dc.Function("WriteCell").Class("OHTMLImportExport").Namespace("dbaui").GlobalNamespace()
237         || dc.Function("getBold").Class("VbaFontBase").GlobalNamespace()
238         || dc.Function("ModifyHdl").Class("SaneDlg").GlobalNamespace()
239         || dc.Function("EstablishNumericOption").Class("SaneDlg").GlobalNamespace()
240         || dc.Function("translatePropertiesToItems").Class("ControlCharacterDialog").Namespace("pcr").GlobalNamespace()
241         || dc.Function("writeMatrix").Class("Tag").Namespace("swf").GlobalNamespace()
242         || dc.Function("Impl_writeActions").Class("Writer").Namespace("swf").GlobalNamespace()
243         || dc.Function("Impl_quadBezierApprox").Class("Writer").Namespace("swf").GlobalNamespace()
244         || dc.Function("hasGradientOpacity").Struct("AnnotatingVisitor").AnonymousNamespace().Namespace("svgi").GlobalNamespace()
245         || dc.Function("getOdfColor").Struct("AnnotatingVisitor").AnonymousNamespace().Namespace("svgi").GlobalNamespace()
246         || dc.Function("writeStyle").Struct("AnnotatingVisitor").AnonymousNamespace().Namespace("svgi").GlobalNamespace()
247         || dc.Operator(OO_Call).Struct("ShapeWritingVisitor").AnonymousNamespace().Namespace("svgi").GlobalNamespace()
248         || dc.Function("SvgDashArray2Odf").Struct("OfficeStylesWritingVisitor").Namespace("svgi").GlobalNamespace()
249         || dc.Function("ImplWriteMask").Class("SVGActionWriter").GlobalNamespace()
250         || dc.Function("Factor").Class("FormulaCompiler").Namespace("formula").GlobalNamespace()
251         || dc.Function("setDateTime").Class("Calendar_gregorian").Namespace("i18n").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()
252         || dc.Function("setLocalDateTime").Class("Calendar_gregorian").Namespace("i18n").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()
253         || dc.Function("compareSubstring").Class("ChapterCollator").Namespace("i18n").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()
254         || dc.Function("ToXml").Class("XFPadding").GlobalNamespace()
255         || dc.Function("Equal").Class("XFCellStyle").GlobalNamespace()
256         || dc.Function("Equal").Class("XFParaStyle").GlobalNamespace()
257         || dc.Function("GetAnimationEffect").Class("EffectMigration").Namespace("sd").GlobalNamespace()
258         || dc.Function("SetAnimationSpeed").Class("EffectMigration").Namespace("sd").GlobalNamespace()
259         || dc.Function("GetAnimationSpeed").Class("EffectMigration").Namespace("sd").GlobalNamespace()
260         || dc.Function("calculateIterateDuration").Class("CustomAnimationEffect").Namespace("sd").GlobalNamespace()
261         || dc.Function("setDuration").Class("CustomAnimationEffect").Namespace("sd").GlobalNamespace()
262         || dc.Function("replaceNode").Class("CustomAnimationEffect").Namespace("sd").GlobalNamespace()
263         || dc.Function("setIterateInterval").Class("CustomAnimationEffect").Namespace("sd").GlobalNamespace()
264         || dc.Function("append").Class("EffectSequenceHelper").Namespace("sd").GlobalNamespace()
265         || dc.Function("replace").Class("EffectSequenceHelper").Namespace("sd").GlobalNamespace()
266         || dc.Function("createTextGroupParagraphEffects").Class("EffectSequenceHelper").Namespace("sd").GlobalNamespace()
267         || dc.Function("setTextGrouping").Class("EffectSequenceHelper").Namespace("sd").GlobalNamespace()
268         || dc.Function("setTextGroupingAuto").Class("EffectSequenceHelper").Namespace("sd").GlobalNamespace()
269         || dc.Function("SetPresentationPenWidth").Class("SdOptionsMisc").GlobalNamespace()
270         || dc.Function("VarLook").Class("SwCalc").GlobalNamespace()
271         || dc.Function("Prim").Class("SwCalc").GlobalNamespace()
272         || dc.Function("keycompare").Struct("SwSortElement").GlobalNamespace()
273         || dc.Function("FormatValue").Class("SwDBField").GlobalNamespace()
274         || dc.Function("Evaluate").Class("SwDBField").GlobalNamespace()
275         || dc.Function("GetValue").Class("SwTableBox").GlobalNamespace()
276         || dc.Function("Modify").Class("SwTableBoxFormat").GlobalNamespace()
277         || dc.Function("isNotANumber").Class("SwXTextTable").GlobalNamespace()
278         || dc.Function("GetNextToken").Class("CSS1Parser").GlobalNamespace()
279         || dc.Function("update").Class("FontStylePropertyBox").Namespace("sd").GlobalNamespace()
280         || dc.Function("implMenuSelectHdl").Class("FontStylePropertyBox").Namespace("sd").GlobalNamespace()
281         || dc.Function("update").Class("CustomAnimationEffectTabPage").Namespace("sd").GlobalNamespace()
282         || dc.Function("update").Class("CustomAnimationDurationTabPage").Namespace("sd").GlobalNamespace()
283         || dc.Function("update").Class("CustomAnimationTextAnimTabPage").Namespace("sd").GlobalNamespace()
284         || dc.Function("FillCalcWithMergeData").Class("SwDBManager").GlobalNamespace()
285         || dc.Function("compareWith").Struct("TransitionEffect").Namespace("impl").Namespace("sd").GlobalNamespace()
286         || dc.Function("changeSelection").Class("CustomAnimationPane").Namespace("sd").GlobalNamespace()
287         || dc.Function("ContextMenuHdl").Class("SlideshowImpl").Namespace("sd").GlobalNamespace()
288         || dc.Function("FormatBox").Class("DocxAttributeOutput").GlobalNamespace()
289         || dc.Function("GetString").Class("Complex").Namespace("analysis").Namespace("sca").GlobalNamespace()
290         || dc.Function("getDelta").Class("AnalysisAddIn").GlobalNamespace()
291         || dc.Function("DataToDoc").Class("SwInsertDBColAutoPilot").GlobalNamespace()
292         || dc.Function("convertAnimateValue").Class("AnimationExporter").Namespace("ppt").GlobalNamespace()
293         || dc.Function("GetId").Class("PPTExBulletProvider").GlobalNamespace()
294         || dc.Function("SetThumbPosition").Class("PresenterScrollBar").Namespace("presenter").Namespace("sdext").GlobalNamespace()
295         || dc.Function("SetTotalSize").Class("PresenterScrollBar").Namespace("presenter").Namespace("sdext").GlobalNamespace()
296         || dc.Function("SetThumbSize").Class("PresenterScrollBar").Namespace("presenter").Namespace("sdext").GlobalNamespace()
297         || dc.Function("Layout").Class("PresenterNotesView").Namespace("presenter").Namespace("sdext").GlobalNamespace()
298         || dc.Function("compare").Struct("lessThanShape").Class("Shape").Namespace("internal").Namespace("slideshow").GlobalNamespace()
299         || dc.Operator(OO_Call).Struct("lessThanArea").Class("HyperlinkArea").Namespace("internal").Namespace("slideshow").GlobalNamespace()
300         || dc.Function("viewsChanged").Class("PointerSymbol").Namespace("internal").Namespace("slideshow").GlobalNamespace()
301         || dc.Function("RetrieveAttrs").Struct("SmXMLContext_Helper").GlobalNamespace()
302         || dc.Function("CompareImpl").Class("SortedResultSet").GlobalNamespace()
303         || dc.Function("emit").Struct("PDFNumber").Namespace("pdfparse").GlobalNamespace()
304         || dc.Function("visit").Class("DrawXmlOptimizer").Namespace("pdfi").GlobalNamespace()
305         || dc.Function("optimizeTextElements").Class("DrawXmlOptimizer").Namespace("pdfi").GlobalNamespace()
306         || dc.Function("init").Class("DrawXmlFinalizer").Namespace("pdfi").GlobalNamespace()
307         || dc.Function("visit").Class("DrawXmlFinalizer").Namespace("pdfi").GlobalNamespace()
308         || dc.Function("GetState").Class("OReportController").Namespace("rptui").GlobalNamespace()
309         || dc.Function("isFormatCommandEnabled").Class("OReportController").Namespace("rptui").GlobalNamespace()
310         || dc.Function("resolveUnderlines").Struct("PageElement").Namespace("pdfi").GlobalNamespace()
311         || dc.Function("visit").Class("WriterXmlOptimizer").Namespace("pdfi").GlobalNamespace()
312         || dc.Function("optimizeTextElements").Class("WriterXmlOptimizer").Namespace("pdfi").GlobalNamespace()
313         || dc.Function("drawGlyphs").Class("PDFIProcessor").Namespace("pdfi").GlobalNamespace()
314         || dc.Function("LTypeToDXFLineInfo").Class("DXF2GDIMetaFile").GlobalNamespace()
315         || dc.Function("DrawEntities").Class("DXF2GDIMetaFile").GlobalNamespace()
316         || dc.Function("ImplWriteActions").Class("PSWriter").GlobalNamespace()
317         || dc.Function("ImplWriteLineInfo").Class("PSWriter").GlobalNamespace()
318         || dc.Function("ImplInsert").Class("CGMBitmap").GlobalNamespace()
319         || dc.Function("GetNext").Class("CGMBitmap").GlobalNamespace()
320         || dc.Function("drawPolyLine").Class("X11SalGraphicsImpl").GlobalNamespace()
321         || dc.Function("testRefresh").Class("XDataPilotTable").Namespace("apitest").GlobalNamespace()
322         || dc.Function("testTitleManualLayoutXLSX").Class("Chart2ExportTest").GlobalNamespace()
323         || dc.Function("testPlotAreaManualLayoutXLSX").Class("Chart2ExportTest").GlobalNamespace()
324         || dc.Function("testLegendManualLayoutXLSX").Class("Chart2ExportTest").GlobalNamespace()
325         || dc.Function("SetScreenNumber").Class("AquaSalFrame").GlobalNamespace()
326         || (vclFloatDevicePixel
327             && (dc.Function("Justify").Class("GenericSalLayout").GlobalNamespace()
328                 || dc.Function("AdjustLayout").Class("MultiSalLayout").GlobalNamespace()))
329         // vcl/headless/svpgdi.cxx, ba4a124b0c0c66fd275f5147d55eeec27ce78da9:
330         || dc.Function("drawAlphaBitmap").Class("SvpSalGraphics").GlobalNamespace()
331         || dc.Function("drawMask").Class("SvpSalGraphics").GlobalNamespace()
332         || dc.Function("renderSource").GlobalNamespace())
333     {
334         return true;
335     }
336 //    cout << "xxx " + function->getQualifiedNameAsString() << endl;
337     return false;
338 }
339 
isZeroConstant(ASTContext & context,const Expr * expr)340 bool isZeroConstant(ASTContext& context, const Expr* expr)
341 {
342     if (!expr->getType()->isFloatingType()) {
343         return false;
344     }
345     // prevent clang crash
346     if (!context.getLangOpts().CPlusPlus) {
347         return false;
348     }
349     APValue result;
350     if (!expr->isCXX11ConstantExpr(context, &result)) {
351         return false;
352     }
353     assert(result.isFloat());
354     return result.getFloat().isZero();
355 }
VisitBinaryOperator(const BinaryOperator * binaryOp)356 bool FpComparison::VisitBinaryOperator(const BinaryOperator* binaryOp)
357 {
358     if (meState != EState::TraverseProcess || ignoreLocation(binaryOp)) {
359         return true;
360     }
361     if (binaryOp->getOpcode() != BO_EQ && binaryOp->getOpcode() != BO_NE) {
362         return true;
363     }
364     // comparison with zero is valid
365     if (isZeroConstant(compiler.getASTContext(), binaryOp->getLHS())
366         || isZeroConstant(compiler.getASTContext(), binaryOp->getRHS()))
367     {
368         return true;
369     }
370     QualType LHSStrippedType = binaryOp->getLHS()->IgnoreParenImpCasts()->getType();
371     QualType RHSStrippedType = binaryOp->getRHS()->IgnoreParenImpCasts()->getType();
372     if (LHSStrippedType->isFloatingType() && RHSStrippedType->isFloatingType()) {
373         report(
374             DiagnosticsEngine::Warning, "floating-point comparison",
375             binaryOp->getSourceRange().getBegin())
376           << binaryOp->getSourceRange();
377     }
378     return true;
379 }
380 
381 
382 loplugin::Plugin::Registration< FpComparison > X("fpcomparison", true);
383 
384 }
385 
386 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
387