From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- compilerplugins/clang/automem.cxx | 92 + compilerplugins/clang/badstatics.cxx | 282 + compilerplugins/clang/blockblock.cxx | 109 + compilerplugins/clang/bufferadd.cxx | 393 ++ compilerplugins/clang/buriedassign.cxx | 650 ++ compilerplugins/clang/casttovoid.cxx | 535 ++ compilerplugins/clang/changetoolsgen.cxx | 376 ++ compilerplugins/clang/charrightshift.cxx | 65 + compilerplugins/clang/check.cxx | 389 ++ compilerplugins/clang/check.hxx | 311 + compilerplugins/clang/checkconfigmacros.cxx | 120 + compilerplugins/clang/checkunusedparams.cxx | 502 ++ compilerplugins/clang/classmemaccess.cxx | 133 + compilerplugins/clang/collapseif.cxx | 129 + compilerplugins/clang/colorcheck.cxx | 97 + compilerplugins/clang/commaoperator.cxx | 130 + compilerplugins/clang/comparisonwithconstant.cxx | 168 + compilerplugins/clang/compat.hxx | 130 + compilerplugins/clang/conditionalstring.cxx | 459 ++ .../clang/constantparam.bitmask.results | 54 + .../clang/constantparam.booleans.results | 4308 ++++++++++++++ .../clang/constantparam.constructors.results | 1120 ++++ compilerplugins/clang/constantparam.cxx | 296 + .../clang/constantparam.numbers.results | 3424 +++++++++++ compilerplugins/clang/constantparam.py | 198 + compilerplugins/clang/constfields.cxx | 596 ++ compilerplugins/clang/constfields.py | 87 + compilerplugins/clang/constfieldsrewrite.cxx | 169 + compilerplugins/clang/constmethod.cxx | 563 ++ compilerplugins/clang/constparams.cxx | 618 ++ compilerplugins/clang/conststringvar.cxx | 156 + compilerplugins/clang/consttobool.cxx | 291 + compilerplugins/clang/constvars.cxx | 558 ++ compilerplugins/clang/convertlong.cxx | 139 + .../clang/countusersofdefaultparams.cxx | 250 + compilerplugins/clang/countusersofdefaultparams.py | 81 + compilerplugins/clang/cow_wrapper.cxx | 121 + compilerplugins/clang/cppunitassertequals.cxx | 240 + compilerplugins/clang/cstylecast.cxx | 707 +++ compilerplugins/clang/data.cxx | 89 + compilerplugins/clang/datamembershadow.cxx | 126 + compilerplugins/clang/dbgunhandledexception.cxx | 128 + compilerplugins/clang/derefnullptr.cxx | 52 + compilerplugins/clang/dllprivate.cxx | 86 + compilerplugins/clang/dodgyswitch.cxx | 78 + compilerplugins/clang/doubleconvert.cxx | 83 + compilerplugins/clang/duplicate-defines.cxx | 136 + compilerplugins/clang/dyncastvisibility.cxx | 209 + compilerplugins/clang/dynexcspec.cxx | 186 + compilerplugins/clang/elidestringvar.cxx | 460 ++ compilerplugins/clang/empty.cxx | 167 + compilerplugins/clang/emptyif.cxx | 93 + compilerplugins/clang/expandablemethods.cxx | 325 + compilerplugins/clang/expandablemethods.py | 150 + compilerplugins/clang/expressionalwayszero.cxx | 151 + compilerplugins/clang/external.cxx | 608 ++ compilerplugins/clang/externandnotdefined.cxx | 77 + compilerplugins/clang/faileddyncast.cxx | 138 + compilerplugins/clang/fakebool.cxx | 910 +++ compilerplugins/clang/finalclasses.cxx | 162 + compilerplugins/clang/finalclasses.py | 81 + compilerplugins/clang/flatten.cxx | 687 +++ compilerplugins/clang/fragiledestructor.cxx | 147 + compilerplugins/clang/functionaddress.hxx | 120 + compilerplugins/clang/getimplementationname.cxx | 313 + compilerplugins/clang/getstr.cxx | 170 + compilerplugins/clang/implicitboolconversion.cxx | 896 +++ compilerplugins/clang/includeform.cxx | 117 + compilerplugins/clang/indentation.cxx | 460 ++ compilerplugins/clang/inlinefields.cxx | 251 + compilerplugins/clang/inlinefields.py | 73 + .../clang/inlinesimplememberfunctions.cxx | 294 + compilerplugins/clang/inlinevisible.cxx | 56 + compilerplugins/clang/intvsfloat.cxx | 116 + compilerplugins/clang/literaltoboolconversion.cxx | 232 + compilerplugins/clang/logexceptionnicely.cxx | 150 + compilerplugins/clang/loopvartoosmall.cxx | 246 + compilerplugins/clang/makeshared.cxx | 252 + compilerplugins/clang/mapindex.cxx | 108 + compilerplugins/clang/memoryvar.cxx | 238 + compilerplugins/clang/mergeclasses.cxx | 170 + compilerplugins/clang/mergeclasses.py | 78 + compilerplugins/clang/mergeclasses.results | 506 ++ compilerplugins/clang/methodcycles.cxx | 378 ++ .../clang/methodcycles.partition.results | 8 + compilerplugins/clang/methodcycles.py | 266 + compilerplugins/clang/methodcycles.results | 157 + compilerplugins/clang/moveit.cxx | 250 + compilerplugins/clang/moveparam.cxx | 191 + compilerplugins/clang/namespaceindentation.cxx | 220 + compilerplugins/clang/nestedunnamed.cxx | 81 + compilerplugins/clang/noexcept.cxx | 83 + compilerplugins/clang/noexceptmove.cxx | 331 ++ compilerplugins/clang/nullptr.cxx | 431 ++ compilerplugins/clang/oncevar.cxx | 414 ++ compilerplugins/clang/oslendian.cxx | 133 + compilerplugins/clang/overrideparam.cxx | 166 + compilerplugins/clang/overridevirtual.cxx | 174 + compilerplugins/clang/pahole-all-classes.py | 156 + compilerplugins/clang/passparamsbyref.cxx | 234 + compilerplugins/clang/passstuffbyref.cxx | 502 ++ compilerplugins/clang/plugin.cxx | 1081 ++++ compilerplugins/clang/plugin.hxx | 319 + compilerplugins/clang/pluginhandler.cxx | 532 ++ compilerplugins/clang/pluginhandler.hxx | 107 + compilerplugins/clang/pointerbool.cxx | 169 + compilerplugins/clang/precompiled_clang.hxx | 54 + compilerplugins/clang/privatebase.cxx | 59 + compilerplugins/clang/ptrvector.cxx | 91 + compilerplugins/clang/rangedforcopy.cxx | 70 + compilerplugins/clang/readability-redundant-pp.cxx | 133 + compilerplugins/clang/reducevarscope.cxx | 551 ++ compilerplugins/clang/redundantcast.cxx | 969 +++ compilerplugins/clang/redundantfcast.cxx | 357 ++ compilerplugins/clang/redundantinline.cxx | 177 + compilerplugins/clang/redundantpointerops.cxx | 168 + compilerplugins/clang/redundantstatic.cxx | 122 + compilerplugins/clang/refcounting.cxx | 812 +++ compilerplugins/clang/referencecasting.cxx | 538 ++ compilerplugins/clang/rendercontext.cxx | 133 + compilerplugins/clang/reservedid.cxx | 328 ++ compilerplugins/clang/returnconstant.cxx | 226 + compilerplugins/clang/returnconstval.cxx | 79 + compilerplugins/clang/salcall.cxx | 615 ++ compilerplugins/clang/sallogareas.cxx | 284 + compilerplugins/clang/salunicodeliteral.cxx | 102 + compilerplugins/clang/selfinit.cxx | 109 + compilerplugins/clang/sequentialassign.cxx | 327 + compilerplugins/clang/sfxpoolitem.cxx | 134 + compilerplugins/clang/sharedvisitor/README | 45 + compilerplugins/clang/sharedvisitor/analyzer.cxx | 299 + .../clang/sharedvisitor/dummyplugin.hxx | 81 + compilerplugins/clang/sharedvisitor/generator.cxx | 480 ++ .../clang/sharedvisitor/precompiled_clang.hxx | 12 + compilerplugins/clang/shouldreturnbool.cxx | 251 + compilerplugins/clang/simplifyconstruct.cxx | 110 + compilerplugins/clang/simplifydynamiccast.cxx | 114 + compilerplugins/clang/simplifypointertobool.cxx | 444 ++ .../clang/singlevalfields.could-be-bool.results | 117 + compilerplugins/clang/singlevalfields.cxx | 577 ++ compilerplugins/clang/singlevalfields.py | 111 + compilerplugins/clang/singlevalfields.results | 1134 ++++ compilerplugins/clang/staticaccess.cxx | 100 + compilerplugins/clang/staticconstfield.cxx | 174 + compilerplugins/clang/staticdynamic.cxx | 168 + compilerplugins/clang/staticmethods.cxx | 244 + compilerplugins/clang/staticvar.cxx | 213 + compilerplugins/clang/stdfunction.cxx | 52 + compilerplugins/clang/store/README | 3 + compilerplugins/clang/store/badvectorinit.cxx | 214 + compilerplugins/clang/store/bodynotinblock.cxx | 147 + compilerplugins/clang/store/bodynotinblock.hxx | 35 + compilerplugins/clang/store/cascadingassignop.cxx | 94 + compilerplugins/clang/store/cascadingassignop.hxx | 35 + compilerplugins/clang/store/cascadingcondop.cxx | 85 + compilerplugins/clang/store/cascadingcondop.hxx | 35 + .../clang/store/changefunctioncalls.cxx | 91 + compilerplugins/clang/store/constantfunction.cxx | 506 ++ compilerplugins/clang/store/deadclass.cxx | 69 + compilerplugins/clang/store/defaultparams.cxx | 128 + compilerplugins/clang/store/deletedspecial.cxx | 153 + compilerplugins/clang/store/derivedclass.cxx | 70 + compilerplugins/clang/store/finalprotected.cxx | 84 + compilerplugins/clang/store/findoncontainer.cxx | 77 + compilerplugins/clang/store/fpcomparison.cxx | 386 ++ compilerplugins/clang/store/lclstaticfix.cxx | 54 + compilerplugins/clang/store/lclstaticfix.hxx | 30 + compilerplugins/clang/store/manualrefcount.cxx | 323 + compilerplugins/clang/store/optmove.cxx | 161 + .../clang/store/paintmethodconversion.cxx | 94 + .../clang/store/postfixincrementfix.cxx | 132 + .../clang/store/postfixincrementfix.hxx | 35 + compilerplugins/clang/store/putpoolitem.cxx | 103 + compilerplugins/clang/store/refassign.cxx | 151 + .../clang/store/removeforwardstringdecl.cxx | 78 + .../clang/store/removeforwardstringdecl.hxx | 32 + compilerplugins/clang/store/removevirtuals.cxx | 150 + compilerplugins/clang/store/returnbyref.cxx | 138 + compilerplugins/clang/store/returnunique.cxx | 83 + compilerplugins/clang/store/revisibility.cxx | 89 + compilerplugins/clang/store/rtlconstasciimacro.cxx | 144 + compilerplugins/clang/store/sfxitemsetrewrite.cxx | 419 ++ compilerplugins/clang/store/simplifybool.cxx | 1333 +++++ compilerplugins/clang/store/stdexception.cxx | 188 + compilerplugins/clang/store/stringbuffer.cxx | 75 + compilerplugins/clang/store/stylepolice.cxx | 196 + .../clang/store/svstreamoutputoperators.cxx | 223 + compilerplugins/clang/store/test/deadclass.cxx | 15 + compilerplugins/clang/store/tutorial/tutorial1.cxx | 68 + compilerplugins/clang/store/tutorial/tutorial1.hxx | 35 + .../clang/store/tutorial/tutorial1_example.cxx | 21 + compilerplugins/clang/store/tutorial/tutorial2.cxx | 95 + compilerplugins/clang/store/tutorial/tutorial2.hxx | 35 + .../clang/store/tutorial/tutorial2_example.cxx | 18 + compilerplugins/clang/store/tutorial/tutorial3.cxx | 77 + compilerplugins/clang/store/tutorial/tutorial3.hxx | 37 + compilerplugins/clang/store/unusedcode.cxx | 77 + compilerplugins/clang/store/valueof.cxx | 148 + compilerplugins/clang/stringadd.cxx | 467 ++ compilerplugins/clang/stringconcatauto.cxx | 112 + compilerplugins/clang/stringconcatliterals.cxx | 156 + compilerplugins/clang/stringconstant.cxx | 2216 +++++++ compilerplugins/clang/stringliteraldefine.cxx | 171 + compilerplugins/clang/stringliteralvar.cxx | 320 + compilerplugins/clang/stringloop.cxx | 292 + compilerplugins/clang/stringstatic.cxx | 202 + compilerplugins/clang/stringview.cxx | 424 ++ compilerplugins/clang/stringviewdangle.cxx | 117 + compilerplugins/clang/stringviewparam.cxx | 575 ++ compilerplugins/clang/stringviewvar.cxx | 407 ++ compilerplugins/clang/subtlezeroinit.cxx | 67 + compilerplugins/clang/test/badstatics.cxx | 58 + compilerplugins/clang/test/blockblock.cxx | 47 + compilerplugins/clang/test/bufferadd.cxx | 116 + compilerplugins/clang/test/buriedassign.cxx | 133 + compilerplugins/clang/test/casttovoid.cxx | 125 + compilerplugins/clang/test/classmemaccess.cxx | 36 + compilerplugins/clang/test/collapseif.cxx | 55 + compilerplugins/clang/test/commaoperator.cxx | 28 + compilerplugins/clang/test/conditionalstring.cxx | 27 + compilerplugins/clang/test/constfields.cxx | 45 + compilerplugins/clang/test/constmethod.cxx | 59 + compilerplugins/clang/test/constparams.cxx | 73 + compilerplugins/clang/test/consttobool.cxx | 70 + compilerplugins/clang/test/constvars.cxx | 94 + compilerplugins/clang/test/convertlong.cxx | 42 + compilerplugins/clang/test/cow_wrapper.cxx | 44 + compilerplugins/clang/test/cppunitassertequals.cxx | 75 + compilerplugins/clang/test/cppunitassertequals.hxx | 23 + compilerplugins/clang/test/cstylecast.cxx | 74 + compilerplugins/clang/test/datamembershadow.cxx | 24 + .../clang/test/dbgunhandledexception.cxx | 38 + compilerplugins/clang/test/dodgyswitch.cxx | 30 + compilerplugins/clang/test/doubleconvert.cxx | 25 + compilerplugins/clang/test/elidestringvar.cxx | 46 + compilerplugins/clang/test/emptyif.cxx | 61 + .../clang/test/expressionalwayszero.cxx | 47 + compilerplugins/clang/test/external.cxx | 195 + compilerplugins/clang/test/external.hxx | 23 + compilerplugins/clang/test/faileddyncast.cxx | 21 + compilerplugins/clang/test/fakebool.cxx | 50 + compilerplugins/clang/test/flatten.cxx | 191 + compilerplugins/clang/test/fragiledestructor.cxx | 88 + compilerplugins/clang/test/getstr.cxx | 59 + .../clang/test/implicitboolconversion.cxx | 83 + compilerplugins/clang/test/indentation.cxx | 110 + compilerplugins/clang/test/intvsfloat.cxx | 62 + compilerplugins/clang/test/logexceptionnicely.cxx | 52 + compilerplugins/clang/test/loopvartoosmall.cxx | 26 + compilerplugins/clang/test/makeshared.cxx | 63 + compilerplugins/clang/test/mapindex.cxx | 43 + compilerplugins/clang/test/moveit.cxx | 60 + compilerplugins/clang/test/moveparam.cxx | 60 + .../clang/test/namespaceindentation.cxx | 50 + compilerplugins/clang/test/noexcept.cxx | 16 + compilerplugins/clang/test/noexceptmove.cxx | 95 + compilerplugins/clang/test/nullptr.cxx | 23 + compilerplugins/clang/test/oncevar.cxx | 66 + compilerplugins/clang/test/optmove.cxx | 53 + compilerplugins/clang/test/oslendian-1.cxx | 47 + compilerplugins/clang/test/oslendian-2.cxx | 23 + compilerplugins/clang/test/oslendian-3.cxx | 25 + compilerplugins/clang/test/overridevirtual.cxx | 44 + compilerplugins/clang/test/passparamsbyref.cxx | 42 + compilerplugins/clang/test/passstuffbyref.cxx | 84 + compilerplugins/clang/test/pointerbool.cxx | 46 + compilerplugins/clang/test/putpoolitem.cxx | 48 + compilerplugins/clang/test/reducevarscope.cxx | 99 + compilerplugins/clang/test/redundantcast.cxx | 458 ++ compilerplugins/clang/test/redundantcast.hxx | 35 + compilerplugins/clang/test/redundantfcast.cxx | 224 + compilerplugins/clang/test/redundantinline.cxx | 24 + compilerplugins/clang/test/redundantinline.hxx | 78 + compilerplugins/clang/test/redundantpointerops.cxx | 95 + .../clang/test/redundantpreprocessor.cxx | 15 + compilerplugins/clang/test/refassign.cxx | 31 + compilerplugins/clang/test/refcounting.cxx | 120 + compilerplugins/clang/test/referencecasting.cxx | 212 + compilerplugins/clang/test/returnconstval.cxx | 21 + compilerplugins/clang/test/salcall.cxx | 188 + compilerplugins/clang/test/sallogareas.cxx | 51 + compilerplugins/clang/test/salunicodeliteral.cxx | 40 + compilerplugins/clang/test/salunicodeliteral.hxx | 14 + compilerplugins/clang/test/selfinit.cxx | 33 + compilerplugins/clang/test/sequentialassign.cxx | 98 + compilerplugins/clang/test/shouldreturnbool.cxx | 31 + compilerplugins/clang/test/simplifyconstruct.cxx | 88 + compilerplugins/clang/test/simplifydynamiccast.cxx | 34 + .../clang/test/simplifypointertobool.cxx | 74 + compilerplugins/clang/test/singlevalfields.cxx | 26 + compilerplugins/clang/test/staticconstfield.cxx | 120 + compilerplugins/clang/test/staticdynamic.cxx | 44 + compilerplugins/clang/test/staticvar.cxx | 80 + compilerplugins/clang/test/stdfunction.cxx | 56 + compilerplugins/clang/test/stringadd.cxx | 262 + compilerplugins/clang/test/stringbuffer.cxx | 22 + compilerplugins/clang/test/stringconcatauto.cxx | 56 + .../clang/test/stringconcatliterals.cxx | 67 + compilerplugins/clang/test/stringconstant.cxx | 134 + compilerplugins/clang/test/stringliteraldefine.cxx | 56 + compilerplugins/clang/test/stringliteralvar.cxx | 134 + compilerplugins/clang/test/stringloop.cxx | 41 + compilerplugins/clang/test/stringstatic.cxx | 29 + compilerplugins/clang/test/stringstatic.hxx | 23 + compilerplugins/clang/test/stringview-c++03.cxx | 21 + compilerplugins/clang/test/stringview.cxx | 221 + compilerplugins/clang/test/stringviewdangle.cxx | 37 + compilerplugins/clang/test/stringviewparam.cxx | 98 + compilerplugins/clang/test/stringviewvar.cxx | 65 + compilerplugins/clang/test/trivialconstructor.cxx | 58 + compilerplugins/clang/test/trivialdestructor.cxx | 57 + compilerplugins/clang/test/typedefparam.cxx | 80 + compilerplugins/clang/test/typeidcomparison.cxx | 41 + .../clang/test/unnecessarycatchthrow.cxx | 58 + compilerplugins/clang/test/unnecessarylocking.cxx | 71 + .../clang/test/unnecessaryoverride-dtor.cxx | 137 + .../clang/test/unnecessaryoverride-dtor.hxx | 52 + compilerplugins/clang/test/unnecessaryoverride.cxx | 196 + compilerplugins/clang/test/unnecessaryparen.cxx | 143 + compilerplugins/clang/test/unoany.cxx | 29 + compilerplugins/clang/test/unoquery.cxx | 19 + compilerplugins/clang/test/unreffun.cxx | 39 + compilerplugins/clang/test/unreffun.hxx | 16 + compilerplugins/clang/test/unsignedcompare.cxx | 16 + .../clang/test/unusedcapturedefault.cxx | 16 + compilerplugins/clang/test/unusedenumconstants.cxx | 120 + compilerplugins/clang/test/unusedfields.cxx | 382 ++ compilerplugins/clang/test/unusedindex.cxx | 42 + compilerplugins/clang/test/unusedmember.cxx | 238 + compilerplugins/clang/test/unusedvariablecheck.cxx | 38 + compilerplugins/clang/test/unusedvariablemore.cxx | 58 + compilerplugins/clang/test/unusedvarsglobal.cxx | 24 + compilerplugins/clang/test/useuniqueptr.cxx | 311 + compilerplugins/clang/test/vclwidgets.cxx | 99 + compilerplugins/clang/test/weakbase.cxx | 34 + compilerplugins/clang/test/weakobject.cxx | 31 + compilerplugins/clang/test/writeonlyvars.cxx | 168 + compilerplugins/clang/test/xmlimport.cxx | 233 + compilerplugins/clang/toolslong.cxx | 653 ++ compilerplugins/clang/trivialconstructor.cxx | 156 + compilerplugins/clang/trivialdestructor.cxx | 113 + compilerplugins/clang/typedefparam.cxx | 334 ++ compilerplugins/clang/typeidcomparison.cxx | 90 + compilerplugins/clang/unicodetochar.cxx | 122 + compilerplugins/clang/unnecessarycatchthrow.cxx | 91 + compilerplugins/clang/unnecessarylocking.cxx | 215 + compilerplugins/clang/unnecessaryoverride.cxx | 539 ++ compilerplugins/clang/unnecessaryparen.cxx | 680 +++ .../clang/unnecessaryvirtual-dead.results | 30 + compilerplugins/clang/unnecessaryvirtual.cxx | 206 + compilerplugins/clang/unnecessaryvirtual.py | 104 + compilerplugins/clang/unnecessaryvirtual.results | 475 ++ compilerplugins/clang/unoany.cxx | 92 + compilerplugins/clang/unoquery.cxx | 99 + compilerplugins/clang/unreffun.cxx | 198 + compilerplugins/clang/unsignedcompare.cxx | 232 + compilerplugins/clang/unusedcapturedefault.cxx | 60 + compilerplugins/clang/unusedenumconstants.cxx | 301 + compilerplugins/clang/unusedenumconstants.py | 262 + .../clang/unusedenumconstants.readonly.results | 1030 ++++ .../clang/unusedenumconstants.untouched.results | 388 ++ .../clang/unusedenumconstants.writeonly.results | 6230 ++++++++++++++++++++ compilerplugins/clang/unusedfields.cxx | 1235 ++++ .../unusedfields.only-used-in-constructor.results | 980 +++ compilerplugins/clang/unusedfields.py | 290 + .../clang/unusedfields.readonly.results | 824 +++ .../clang/unusedfields.untouched.results | 626 ++ .../clang/unusedfields.writeonly.results | 1108 ++++ compilerplugins/clang/unusedfieldsremove.cxx | 137 + compilerplugins/clang/unusedindex.cxx | 87 + compilerplugins/clang/unusedmember.cxx | 441 ++ compilerplugins/clang/unusedmethods.cxx | 464 ++ compilerplugins/clang/unusedmethods.py | 309 + compilerplugins/clang/unusedmethods.results | 2344 ++++++++ .../clang/unusedmethods.unused-returns.results | 388 ++ compilerplugins/clang/unusedmethodsremove.cxx | 153 + compilerplugins/clang/unusedvariablecheck.cxx | 125 + compilerplugins/clang/unusedvariablecheck.hxx | 32 + compilerplugins/clang/unusedvariablemore.cxx | 337 ++ compilerplugins/clang/unusedvariableplus.cxx | 519 ++ compilerplugins/clang/unusedvarsglobal.cxx | 959 +++ compilerplugins/clang/unusedvarsglobal.py | 151 + .../clang/unusedvarsglobal.untouched.results | 44 + .../clang/unusedvarsglobal.writeonly.results | 180 + compilerplugins/clang/useuniqueptr.cxx | 1307 ++++ compilerplugins/clang/vclwidgets.cxx | 876 +++ compilerplugins/clang/virtualdead.cxx | 283 + compilerplugins/clang/virtualdead.py | 129 + compilerplugins/clang/virtualdead.results | 126 + .../clang/virtualdead.unusedparams.results | 264 + compilerplugins/clang/virtualdown.cxx | 219 + compilerplugins/clang/virtualdown.py | 55 + compilerplugins/clang/virtualdown.results | 675 +++ compilerplugins/clang/weakbase.cxx | 123 + compilerplugins/clang/weakobject.cxx | 84 + compilerplugins/clang/writeonlyvars.cxx | 1142 ++++ compilerplugins/clang/xmlimport.cxx | 394 ++ 397 files changed, 99277 insertions(+) create mode 100644 compilerplugins/clang/automem.cxx create mode 100644 compilerplugins/clang/badstatics.cxx create mode 100644 compilerplugins/clang/blockblock.cxx create mode 100644 compilerplugins/clang/bufferadd.cxx create mode 100644 compilerplugins/clang/buriedassign.cxx create mode 100644 compilerplugins/clang/casttovoid.cxx create mode 100644 compilerplugins/clang/changetoolsgen.cxx create mode 100644 compilerplugins/clang/charrightshift.cxx create mode 100644 compilerplugins/clang/check.cxx create mode 100644 compilerplugins/clang/check.hxx create mode 100644 compilerplugins/clang/checkconfigmacros.cxx create mode 100644 compilerplugins/clang/checkunusedparams.cxx create mode 100644 compilerplugins/clang/classmemaccess.cxx create mode 100644 compilerplugins/clang/collapseif.cxx create mode 100644 compilerplugins/clang/colorcheck.cxx create mode 100644 compilerplugins/clang/commaoperator.cxx create mode 100644 compilerplugins/clang/comparisonwithconstant.cxx create mode 100644 compilerplugins/clang/compat.hxx create mode 100644 compilerplugins/clang/conditionalstring.cxx create mode 100644 compilerplugins/clang/constantparam.bitmask.results create mode 100644 compilerplugins/clang/constantparam.booleans.results create mode 100644 compilerplugins/clang/constantparam.constructors.results create mode 100644 compilerplugins/clang/constantparam.cxx create mode 100644 compilerplugins/clang/constantparam.numbers.results create mode 100755 compilerplugins/clang/constantparam.py create mode 100644 compilerplugins/clang/constfields.cxx create mode 100755 compilerplugins/clang/constfields.py create mode 100644 compilerplugins/clang/constfieldsrewrite.cxx create mode 100644 compilerplugins/clang/constmethod.cxx create mode 100644 compilerplugins/clang/constparams.cxx create mode 100644 compilerplugins/clang/conststringvar.cxx create mode 100644 compilerplugins/clang/consttobool.cxx create mode 100644 compilerplugins/clang/constvars.cxx create mode 100644 compilerplugins/clang/convertlong.cxx create mode 100644 compilerplugins/clang/countusersofdefaultparams.cxx create mode 100755 compilerplugins/clang/countusersofdefaultparams.py create mode 100644 compilerplugins/clang/cow_wrapper.cxx create mode 100644 compilerplugins/clang/cppunitassertequals.cxx create mode 100644 compilerplugins/clang/cstylecast.cxx create mode 100644 compilerplugins/clang/data.cxx create mode 100644 compilerplugins/clang/datamembershadow.cxx create mode 100644 compilerplugins/clang/dbgunhandledexception.cxx create mode 100644 compilerplugins/clang/derefnullptr.cxx create mode 100644 compilerplugins/clang/dllprivate.cxx create mode 100644 compilerplugins/clang/dodgyswitch.cxx create mode 100644 compilerplugins/clang/doubleconvert.cxx create mode 100644 compilerplugins/clang/duplicate-defines.cxx create mode 100644 compilerplugins/clang/dyncastvisibility.cxx create mode 100644 compilerplugins/clang/dynexcspec.cxx create mode 100644 compilerplugins/clang/elidestringvar.cxx create mode 100644 compilerplugins/clang/empty.cxx create mode 100644 compilerplugins/clang/emptyif.cxx create mode 100644 compilerplugins/clang/expandablemethods.cxx create mode 100755 compilerplugins/clang/expandablemethods.py create mode 100644 compilerplugins/clang/expressionalwayszero.cxx create mode 100644 compilerplugins/clang/external.cxx create mode 100644 compilerplugins/clang/externandnotdefined.cxx create mode 100644 compilerplugins/clang/faileddyncast.cxx create mode 100644 compilerplugins/clang/fakebool.cxx create mode 100644 compilerplugins/clang/finalclasses.cxx create mode 100755 compilerplugins/clang/finalclasses.py create mode 100644 compilerplugins/clang/flatten.cxx create mode 100644 compilerplugins/clang/fragiledestructor.cxx create mode 100644 compilerplugins/clang/functionaddress.hxx create mode 100644 compilerplugins/clang/getimplementationname.cxx create mode 100644 compilerplugins/clang/getstr.cxx create mode 100644 compilerplugins/clang/implicitboolconversion.cxx create mode 100644 compilerplugins/clang/includeform.cxx create mode 100644 compilerplugins/clang/indentation.cxx create mode 100644 compilerplugins/clang/inlinefields.cxx create mode 100755 compilerplugins/clang/inlinefields.py create mode 100644 compilerplugins/clang/inlinesimplememberfunctions.cxx create mode 100644 compilerplugins/clang/inlinevisible.cxx create mode 100644 compilerplugins/clang/intvsfloat.cxx create mode 100644 compilerplugins/clang/literaltoboolconversion.cxx create mode 100644 compilerplugins/clang/logexceptionnicely.cxx create mode 100644 compilerplugins/clang/loopvartoosmall.cxx create mode 100644 compilerplugins/clang/makeshared.cxx create mode 100644 compilerplugins/clang/mapindex.cxx create mode 100644 compilerplugins/clang/memoryvar.cxx create mode 100644 compilerplugins/clang/mergeclasses.cxx create mode 100755 compilerplugins/clang/mergeclasses.py create mode 100644 compilerplugins/clang/mergeclasses.results create mode 100644 compilerplugins/clang/methodcycles.cxx create mode 100644 compilerplugins/clang/methodcycles.partition.results create mode 100755 compilerplugins/clang/methodcycles.py create mode 100644 compilerplugins/clang/methodcycles.results create mode 100644 compilerplugins/clang/moveit.cxx create mode 100644 compilerplugins/clang/moveparam.cxx create mode 100644 compilerplugins/clang/namespaceindentation.cxx create mode 100644 compilerplugins/clang/nestedunnamed.cxx create mode 100644 compilerplugins/clang/noexcept.cxx create mode 100644 compilerplugins/clang/noexceptmove.cxx create mode 100644 compilerplugins/clang/nullptr.cxx create mode 100644 compilerplugins/clang/oncevar.cxx create mode 100644 compilerplugins/clang/oslendian.cxx create mode 100644 compilerplugins/clang/overrideparam.cxx create mode 100644 compilerplugins/clang/overridevirtual.cxx create mode 100755 compilerplugins/clang/pahole-all-classes.py create mode 100644 compilerplugins/clang/passparamsbyref.cxx create mode 100644 compilerplugins/clang/passstuffbyref.cxx create mode 100644 compilerplugins/clang/plugin.cxx create mode 100644 compilerplugins/clang/plugin.hxx create mode 100644 compilerplugins/clang/pluginhandler.cxx create mode 100644 compilerplugins/clang/pluginhandler.hxx create mode 100644 compilerplugins/clang/pointerbool.cxx create mode 100644 compilerplugins/clang/precompiled_clang.hxx create mode 100644 compilerplugins/clang/privatebase.cxx create mode 100644 compilerplugins/clang/ptrvector.cxx create mode 100644 compilerplugins/clang/rangedforcopy.cxx create mode 100644 compilerplugins/clang/readability-redundant-pp.cxx create mode 100644 compilerplugins/clang/reducevarscope.cxx create mode 100644 compilerplugins/clang/redundantcast.cxx create mode 100644 compilerplugins/clang/redundantfcast.cxx create mode 100644 compilerplugins/clang/redundantinline.cxx create mode 100644 compilerplugins/clang/redundantpointerops.cxx create mode 100644 compilerplugins/clang/redundantstatic.cxx create mode 100644 compilerplugins/clang/refcounting.cxx create mode 100644 compilerplugins/clang/referencecasting.cxx create mode 100644 compilerplugins/clang/rendercontext.cxx create mode 100644 compilerplugins/clang/reservedid.cxx create mode 100644 compilerplugins/clang/returnconstant.cxx create mode 100644 compilerplugins/clang/returnconstval.cxx create mode 100644 compilerplugins/clang/salcall.cxx create mode 100644 compilerplugins/clang/sallogareas.cxx create mode 100644 compilerplugins/clang/salunicodeliteral.cxx create mode 100644 compilerplugins/clang/selfinit.cxx create mode 100644 compilerplugins/clang/sequentialassign.cxx create mode 100644 compilerplugins/clang/sfxpoolitem.cxx create mode 100644 compilerplugins/clang/sharedvisitor/README create mode 100644 compilerplugins/clang/sharedvisitor/analyzer.cxx create mode 100644 compilerplugins/clang/sharedvisitor/dummyplugin.hxx create mode 100644 compilerplugins/clang/sharedvisitor/generator.cxx create mode 100644 compilerplugins/clang/sharedvisitor/precompiled_clang.hxx create mode 100644 compilerplugins/clang/shouldreturnbool.cxx create mode 100644 compilerplugins/clang/simplifyconstruct.cxx create mode 100644 compilerplugins/clang/simplifydynamiccast.cxx create mode 100644 compilerplugins/clang/simplifypointertobool.cxx create mode 100644 compilerplugins/clang/singlevalfields.could-be-bool.results create mode 100644 compilerplugins/clang/singlevalfields.cxx create mode 100755 compilerplugins/clang/singlevalfields.py create mode 100644 compilerplugins/clang/singlevalfields.results create mode 100644 compilerplugins/clang/staticaccess.cxx create mode 100644 compilerplugins/clang/staticconstfield.cxx create mode 100644 compilerplugins/clang/staticdynamic.cxx create mode 100644 compilerplugins/clang/staticmethods.cxx create mode 100644 compilerplugins/clang/staticvar.cxx create mode 100644 compilerplugins/clang/stdfunction.cxx create mode 100644 compilerplugins/clang/store/README create mode 100644 compilerplugins/clang/store/badvectorinit.cxx create mode 100644 compilerplugins/clang/store/bodynotinblock.cxx create mode 100644 compilerplugins/clang/store/bodynotinblock.hxx create mode 100644 compilerplugins/clang/store/cascadingassignop.cxx create mode 100644 compilerplugins/clang/store/cascadingassignop.hxx create mode 100644 compilerplugins/clang/store/cascadingcondop.cxx create mode 100644 compilerplugins/clang/store/cascadingcondop.hxx create mode 100644 compilerplugins/clang/store/changefunctioncalls.cxx create mode 100644 compilerplugins/clang/store/constantfunction.cxx create mode 100644 compilerplugins/clang/store/deadclass.cxx create mode 100644 compilerplugins/clang/store/defaultparams.cxx create mode 100644 compilerplugins/clang/store/deletedspecial.cxx create mode 100644 compilerplugins/clang/store/derivedclass.cxx create mode 100644 compilerplugins/clang/store/finalprotected.cxx create mode 100644 compilerplugins/clang/store/findoncontainer.cxx create mode 100644 compilerplugins/clang/store/fpcomparison.cxx create mode 100644 compilerplugins/clang/store/lclstaticfix.cxx create mode 100644 compilerplugins/clang/store/lclstaticfix.hxx create mode 100644 compilerplugins/clang/store/manualrefcount.cxx create mode 100644 compilerplugins/clang/store/optmove.cxx create mode 100644 compilerplugins/clang/store/paintmethodconversion.cxx create mode 100644 compilerplugins/clang/store/postfixincrementfix.cxx create mode 100644 compilerplugins/clang/store/postfixincrementfix.hxx create mode 100644 compilerplugins/clang/store/putpoolitem.cxx create mode 100644 compilerplugins/clang/store/refassign.cxx create mode 100644 compilerplugins/clang/store/removeforwardstringdecl.cxx create mode 100644 compilerplugins/clang/store/removeforwardstringdecl.hxx create mode 100644 compilerplugins/clang/store/removevirtuals.cxx create mode 100644 compilerplugins/clang/store/returnbyref.cxx create mode 100644 compilerplugins/clang/store/returnunique.cxx create mode 100644 compilerplugins/clang/store/revisibility.cxx create mode 100644 compilerplugins/clang/store/rtlconstasciimacro.cxx create mode 100644 compilerplugins/clang/store/sfxitemsetrewrite.cxx create mode 100644 compilerplugins/clang/store/simplifybool.cxx create mode 100644 compilerplugins/clang/store/stdexception.cxx create mode 100644 compilerplugins/clang/store/stringbuffer.cxx create mode 100644 compilerplugins/clang/store/stylepolice.cxx create mode 100644 compilerplugins/clang/store/svstreamoutputoperators.cxx create mode 100644 compilerplugins/clang/store/test/deadclass.cxx create mode 100644 compilerplugins/clang/store/tutorial/tutorial1.cxx create mode 100644 compilerplugins/clang/store/tutorial/tutorial1.hxx create mode 100644 compilerplugins/clang/store/tutorial/tutorial1_example.cxx create mode 100644 compilerplugins/clang/store/tutorial/tutorial2.cxx create mode 100644 compilerplugins/clang/store/tutorial/tutorial2.hxx create mode 100644 compilerplugins/clang/store/tutorial/tutorial2_example.cxx create mode 100644 compilerplugins/clang/store/tutorial/tutorial3.cxx create mode 100644 compilerplugins/clang/store/tutorial/tutorial3.hxx create mode 100644 compilerplugins/clang/store/unusedcode.cxx create mode 100644 compilerplugins/clang/store/valueof.cxx create mode 100644 compilerplugins/clang/stringadd.cxx create mode 100644 compilerplugins/clang/stringconcatauto.cxx create mode 100644 compilerplugins/clang/stringconcatliterals.cxx create mode 100644 compilerplugins/clang/stringconstant.cxx create mode 100644 compilerplugins/clang/stringliteraldefine.cxx create mode 100644 compilerplugins/clang/stringliteralvar.cxx create mode 100644 compilerplugins/clang/stringloop.cxx create mode 100644 compilerplugins/clang/stringstatic.cxx create mode 100644 compilerplugins/clang/stringview.cxx create mode 100644 compilerplugins/clang/stringviewdangle.cxx create mode 100644 compilerplugins/clang/stringviewparam.cxx create mode 100644 compilerplugins/clang/stringviewvar.cxx create mode 100644 compilerplugins/clang/subtlezeroinit.cxx create mode 100644 compilerplugins/clang/test/badstatics.cxx create mode 100644 compilerplugins/clang/test/blockblock.cxx create mode 100644 compilerplugins/clang/test/bufferadd.cxx create mode 100644 compilerplugins/clang/test/buriedassign.cxx create mode 100644 compilerplugins/clang/test/casttovoid.cxx create mode 100644 compilerplugins/clang/test/classmemaccess.cxx create mode 100644 compilerplugins/clang/test/collapseif.cxx create mode 100644 compilerplugins/clang/test/commaoperator.cxx create mode 100644 compilerplugins/clang/test/conditionalstring.cxx create mode 100644 compilerplugins/clang/test/constfields.cxx create mode 100644 compilerplugins/clang/test/constmethod.cxx create mode 100644 compilerplugins/clang/test/constparams.cxx create mode 100644 compilerplugins/clang/test/consttobool.cxx create mode 100644 compilerplugins/clang/test/constvars.cxx create mode 100644 compilerplugins/clang/test/convertlong.cxx create mode 100644 compilerplugins/clang/test/cow_wrapper.cxx create mode 100644 compilerplugins/clang/test/cppunitassertequals.cxx create mode 100644 compilerplugins/clang/test/cppunitassertequals.hxx create mode 100644 compilerplugins/clang/test/cstylecast.cxx create mode 100644 compilerplugins/clang/test/datamembershadow.cxx create mode 100644 compilerplugins/clang/test/dbgunhandledexception.cxx create mode 100644 compilerplugins/clang/test/dodgyswitch.cxx create mode 100644 compilerplugins/clang/test/doubleconvert.cxx create mode 100644 compilerplugins/clang/test/elidestringvar.cxx create mode 100644 compilerplugins/clang/test/emptyif.cxx create mode 100644 compilerplugins/clang/test/expressionalwayszero.cxx create mode 100644 compilerplugins/clang/test/external.cxx create mode 100644 compilerplugins/clang/test/external.hxx create mode 100644 compilerplugins/clang/test/faileddyncast.cxx create mode 100644 compilerplugins/clang/test/fakebool.cxx create mode 100644 compilerplugins/clang/test/flatten.cxx create mode 100644 compilerplugins/clang/test/fragiledestructor.cxx create mode 100644 compilerplugins/clang/test/getstr.cxx create mode 100644 compilerplugins/clang/test/implicitboolconversion.cxx create mode 100644 compilerplugins/clang/test/indentation.cxx create mode 100644 compilerplugins/clang/test/intvsfloat.cxx create mode 100644 compilerplugins/clang/test/logexceptionnicely.cxx create mode 100644 compilerplugins/clang/test/loopvartoosmall.cxx create mode 100644 compilerplugins/clang/test/makeshared.cxx create mode 100644 compilerplugins/clang/test/mapindex.cxx create mode 100644 compilerplugins/clang/test/moveit.cxx create mode 100644 compilerplugins/clang/test/moveparam.cxx create mode 100644 compilerplugins/clang/test/namespaceindentation.cxx create mode 100644 compilerplugins/clang/test/noexcept.cxx create mode 100644 compilerplugins/clang/test/noexceptmove.cxx create mode 100644 compilerplugins/clang/test/nullptr.cxx create mode 100644 compilerplugins/clang/test/oncevar.cxx create mode 100644 compilerplugins/clang/test/optmove.cxx create mode 100644 compilerplugins/clang/test/oslendian-1.cxx create mode 100644 compilerplugins/clang/test/oslendian-2.cxx create mode 100644 compilerplugins/clang/test/oslendian-3.cxx create mode 100644 compilerplugins/clang/test/overridevirtual.cxx create mode 100644 compilerplugins/clang/test/passparamsbyref.cxx create mode 100644 compilerplugins/clang/test/passstuffbyref.cxx create mode 100644 compilerplugins/clang/test/pointerbool.cxx create mode 100644 compilerplugins/clang/test/putpoolitem.cxx create mode 100644 compilerplugins/clang/test/reducevarscope.cxx create mode 100644 compilerplugins/clang/test/redundantcast.cxx create mode 100644 compilerplugins/clang/test/redundantcast.hxx create mode 100644 compilerplugins/clang/test/redundantfcast.cxx create mode 100644 compilerplugins/clang/test/redundantinline.cxx create mode 100644 compilerplugins/clang/test/redundantinline.hxx create mode 100644 compilerplugins/clang/test/redundantpointerops.cxx create mode 100644 compilerplugins/clang/test/redundantpreprocessor.cxx create mode 100644 compilerplugins/clang/test/refassign.cxx create mode 100644 compilerplugins/clang/test/refcounting.cxx create mode 100644 compilerplugins/clang/test/referencecasting.cxx create mode 100644 compilerplugins/clang/test/returnconstval.cxx create mode 100644 compilerplugins/clang/test/salcall.cxx create mode 100644 compilerplugins/clang/test/sallogareas.cxx create mode 100644 compilerplugins/clang/test/salunicodeliteral.cxx create mode 100644 compilerplugins/clang/test/salunicodeliteral.hxx create mode 100644 compilerplugins/clang/test/selfinit.cxx create mode 100644 compilerplugins/clang/test/sequentialassign.cxx create mode 100644 compilerplugins/clang/test/shouldreturnbool.cxx create mode 100644 compilerplugins/clang/test/simplifyconstruct.cxx create mode 100644 compilerplugins/clang/test/simplifydynamiccast.cxx create mode 100644 compilerplugins/clang/test/simplifypointertobool.cxx create mode 100644 compilerplugins/clang/test/singlevalfields.cxx create mode 100644 compilerplugins/clang/test/staticconstfield.cxx create mode 100644 compilerplugins/clang/test/staticdynamic.cxx create mode 100644 compilerplugins/clang/test/staticvar.cxx create mode 100644 compilerplugins/clang/test/stdfunction.cxx create mode 100644 compilerplugins/clang/test/stringadd.cxx create mode 100644 compilerplugins/clang/test/stringbuffer.cxx create mode 100644 compilerplugins/clang/test/stringconcatauto.cxx create mode 100644 compilerplugins/clang/test/stringconcatliterals.cxx create mode 100644 compilerplugins/clang/test/stringconstant.cxx create mode 100644 compilerplugins/clang/test/stringliteraldefine.cxx create mode 100644 compilerplugins/clang/test/stringliteralvar.cxx create mode 100644 compilerplugins/clang/test/stringloop.cxx create mode 100644 compilerplugins/clang/test/stringstatic.cxx create mode 100644 compilerplugins/clang/test/stringstatic.hxx create mode 100644 compilerplugins/clang/test/stringview-c++03.cxx create mode 100644 compilerplugins/clang/test/stringview.cxx create mode 100644 compilerplugins/clang/test/stringviewdangle.cxx create mode 100644 compilerplugins/clang/test/stringviewparam.cxx create mode 100644 compilerplugins/clang/test/stringviewvar.cxx create mode 100644 compilerplugins/clang/test/trivialconstructor.cxx create mode 100644 compilerplugins/clang/test/trivialdestructor.cxx create mode 100644 compilerplugins/clang/test/typedefparam.cxx create mode 100644 compilerplugins/clang/test/typeidcomparison.cxx create mode 100644 compilerplugins/clang/test/unnecessarycatchthrow.cxx create mode 100644 compilerplugins/clang/test/unnecessarylocking.cxx create mode 100644 compilerplugins/clang/test/unnecessaryoverride-dtor.cxx create mode 100644 compilerplugins/clang/test/unnecessaryoverride-dtor.hxx create mode 100644 compilerplugins/clang/test/unnecessaryoverride.cxx create mode 100644 compilerplugins/clang/test/unnecessaryparen.cxx create mode 100644 compilerplugins/clang/test/unoany.cxx create mode 100644 compilerplugins/clang/test/unoquery.cxx create mode 100644 compilerplugins/clang/test/unreffun.cxx create mode 100644 compilerplugins/clang/test/unreffun.hxx create mode 100644 compilerplugins/clang/test/unsignedcompare.cxx create mode 100644 compilerplugins/clang/test/unusedcapturedefault.cxx create mode 100644 compilerplugins/clang/test/unusedenumconstants.cxx create mode 100644 compilerplugins/clang/test/unusedfields.cxx create mode 100644 compilerplugins/clang/test/unusedindex.cxx create mode 100644 compilerplugins/clang/test/unusedmember.cxx create mode 100644 compilerplugins/clang/test/unusedvariablecheck.cxx create mode 100644 compilerplugins/clang/test/unusedvariablemore.cxx create mode 100644 compilerplugins/clang/test/unusedvarsglobal.cxx create mode 100644 compilerplugins/clang/test/useuniqueptr.cxx create mode 100644 compilerplugins/clang/test/vclwidgets.cxx create mode 100644 compilerplugins/clang/test/weakbase.cxx create mode 100644 compilerplugins/clang/test/weakobject.cxx create mode 100644 compilerplugins/clang/test/writeonlyvars.cxx create mode 100644 compilerplugins/clang/test/xmlimport.cxx create mode 100644 compilerplugins/clang/toolslong.cxx create mode 100644 compilerplugins/clang/trivialconstructor.cxx create mode 100644 compilerplugins/clang/trivialdestructor.cxx create mode 100644 compilerplugins/clang/typedefparam.cxx create mode 100644 compilerplugins/clang/typeidcomparison.cxx create mode 100644 compilerplugins/clang/unicodetochar.cxx create mode 100644 compilerplugins/clang/unnecessarycatchthrow.cxx create mode 100644 compilerplugins/clang/unnecessarylocking.cxx create mode 100644 compilerplugins/clang/unnecessaryoverride.cxx create mode 100644 compilerplugins/clang/unnecessaryparen.cxx create mode 100644 compilerplugins/clang/unnecessaryvirtual-dead.results create mode 100644 compilerplugins/clang/unnecessaryvirtual.cxx create mode 100755 compilerplugins/clang/unnecessaryvirtual.py create mode 100644 compilerplugins/clang/unnecessaryvirtual.results create mode 100644 compilerplugins/clang/unoany.cxx create mode 100644 compilerplugins/clang/unoquery.cxx create mode 100644 compilerplugins/clang/unreffun.cxx create mode 100644 compilerplugins/clang/unsignedcompare.cxx create mode 100644 compilerplugins/clang/unusedcapturedefault.cxx create mode 100644 compilerplugins/clang/unusedenumconstants.cxx create mode 100755 compilerplugins/clang/unusedenumconstants.py create mode 100644 compilerplugins/clang/unusedenumconstants.readonly.results create mode 100644 compilerplugins/clang/unusedenumconstants.untouched.results create mode 100644 compilerplugins/clang/unusedenumconstants.writeonly.results create mode 100644 compilerplugins/clang/unusedfields.cxx create mode 100644 compilerplugins/clang/unusedfields.only-used-in-constructor.results create mode 100755 compilerplugins/clang/unusedfields.py create mode 100644 compilerplugins/clang/unusedfields.readonly.results create mode 100644 compilerplugins/clang/unusedfields.untouched.results create mode 100644 compilerplugins/clang/unusedfields.writeonly.results create mode 100644 compilerplugins/clang/unusedfieldsremove.cxx create mode 100644 compilerplugins/clang/unusedindex.cxx create mode 100644 compilerplugins/clang/unusedmember.cxx create mode 100644 compilerplugins/clang/unusedmethods.cxx create mode 100755 compilerplugins/clang/unusedmethods.py create mode 100644 compilerplugins/clang/unusedmethods.results create mode 100644 compilerplugins/clang/unusedmethods.unused-returns.results create mode 100644 compilerplugins/clang/unusedmethodsremove.cxx create mode 100644 compilerplugins/clang/unusedvariablecheck.cxx create mode 100644 compilerplugins/clang/unusedvariablecheck.hxx create mode 100644 compilerplugins/clang/unusedvariablemore.cxx create mode 100644 compilerplugins/clang/unusedvariableplus.cxx create mode 100644 compilerplugins/clang/unusedvarsglobal.cxx create mode 100755 compilerplugins/clang/unusedvarsglobal.py create mode 100644 compilerplugins/clang/unusedvarsglobal.untouched.results create mode 100644 compilerplugins/clang/unusedvarsglobal.writeonly.results create mode 100644 compilerplugins/clang/useuniqueptr.cxx create mode 100644 compilerplugins/clang/vclwidgets.cxx create mode 100644 compilerplugins/clang/virtualdead.cxx create mode 100755 compilerplugins/clang/virtualdead.py create mode 100644 compilerplugins/clang/virtualdead.results create mode 100644 compilerplugins/clang/virtualdead.unusedparams.results create mode 100644 compilerplugins/clang/virtualdown.cxx create mode 100755 compilerplugins/clang/virtualdown.py create mode 100644 compilerplugins/clang/virtualdown.results create mode 100644 compilerplugins/clang/weakbase.cxx create mode 100644 compilerplugins/clang/weakobject.cxx create mode 100644 compilerplugins/clang/writeonlyvars.cxx create mode 100644 compilerplugins/clang/xmlimport.cxx (limited to 'compilerplugins/clang') diff --git a/compilerplugins/clang/automem.cxx b/compilerplugins/clang/automem.cxx new file mode 100644 index 000000000..92478b9fb --- /dev/null +++ b/compilerplugins/clang/automem.cxx @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" + +/** + Find calls to "delete x" where x is a field on an object. + Should rather be using std::unique_ptr +*/ + +namespace { + +class AutoMem: + public loplugin::FilteringPlugin +{ +public: + explicit AutoMem(loplugin::InstantiationData const & data): FilteringPlugin(data), mbInsideDestructor(false) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool TraverseCXXDestructorDecl(CXXDestructorDecl* ); + bool VisitCXXDeleteExpr(const CXXDeleteExpr* ); +private: + bool mbInsideDestructor; +}; + +bool AutoMem::TraverseCXXDestructorDecl(CXXDestructorDecl* expr) +{ + mbInsideDestructor = true; + bool ret = RecursiveASTVisitor::TraverseCXXDestructorDecl(expr); + mbInsideDestructor = false; + return ret; +} + +bool AutoMem::VisitCXXDeleteExpr(const CXXDeleteExpr* expr) +{ + if (ignoreLocation( expr )) + return true; + StringRef aFileName = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc())); + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/salhelper/") + || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/osl/") + || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/salhelper/") + || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/store/") + || loplugin::hasPathnamePrefix(aFileName, SRCDIR "/sal/")) + return true; + + if (mbInsideDestructor) + return true; + + const ImplicitCastExpr* pCastExpr = dyn_cast(expr->getArgument()); + if (!pCastExpr) + return true; + const MemberExpr* pMemberExpr = dyn_cast(pCastExpr->getSubExpr()); + if (!pMemberExpr) + return true; + // ignore union games + const FieldDecl* pFieldDecl = dyn_cast(pMemberExpr->getMemberDecl()); + if (!pFieldDecl) + return true; + TagDecl const * td = dyn_cast(pFieldDecl->getDeclContext()); + if (td->isUnion()) + return true; + + report( + DiagnosticsEngine::Warning, + "calling delete on object field, rather use std::unique_ptr or std::scoped_ptr", + expr->getBeginLoc()) + << expr->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration< AutoMem > X("automem", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx new file mode 100644 index 000000000..3b80278a2 --- /dev/null +++ b/compilerplugins/clang/badstatics.cxx @@ -0,0 +1,282 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include + +#include "check.hxx" +#include "plugin.hxx" + +namespace { + +class BadStatics + : public loplugin::FilteringPlugin +{ + +public: + explicit BadStatics(loplugin::InstantiationData const& rData): + FilteringPlugin(rData) {} + + bool preRun() override { + return compiler.getLangOpts().CPlusPlus; // no non-trivial dtors in C + } + + void run() override { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + static std::pair> isBadStaticType( + QualType const& rpType, std::vector & chain, + std::vector const& rParents) + { + QualType pt; + if (rpType->isAnyPointerType()) { + pt = rpType->getPointeeType(); + } else if (auto at = rpType->getAsArrayTypeUnsafe()) { + pt = at->getElementType(); + } else if (auto rt = rpType->getAs()) { + pt = rt->getPointeeType(); + } + if (!pt.isNull()) { + QualType const pPointee(pt.getUnqualifiedType().getCanonicalType()); + auto const iter(std::find(rParents.begin(), rParents.end(), pPointee)); + if (iter == rParents.end()) + { + std::vector copy(rParents); + copy.push_back(rpType.getUnqualifiedType().getCanonicalType()); + return isBadStaticType(pt, chain, copy); + } else { + return std::make_pair(false, std::vector()); + } + } + RecordType const*const pRecordType(rpType->getAs()); + if (!pRecordType) { + return std::make_pair(false, std::vector()); + } + auto const type = loplugin::TypeCheck(rpType); + if ( type.Class("Image").GlobalNamespace() + || type.Class("Bitmap").GlobalNamespace() + || type.Class("BitmapEx").GlobalNamespace() + || type.Class("VclPtr").GlobalNamespace() + ) + { + return std::make_pair(true, chain); + } + if (type.Class("array").StdNamespace() + || type.Class("deque").StdNamespace() + || type.Class("forward_list").StdNamespace() + || type.Class("initializer_list").StdNamespace() + || type.Class("list").StdNamespace() + || type.Class("multiset").StdNamespace() + || type.Class("set").StdNamespace() + || type.Class("unordered_multiset").StdNamespace() + || type.Class("unordered_set").StdNamespace() + || type.Class("vector").StdNamespace()) + { + std::vector copy(rParents); + copy.push_back(rpType.getUnqualifiedType().getCanonicalType()); + auto ctsd = dyn_cast( + pRecordType->getDecl()); + assert(ctsd != nullptr); + auto const & args = ctsd->getTemplateArgs(); + assert(args.size() >= 1); + return isBadStaticType(args.get(0).getAsType(), chain, copy); + } + if (type.Class("map").StdNamespace() + || type.Class("multimap").StdNamespace() + || type.Class("unordered_map").StdNamespace() + || type.Class("unordered_multimap").StdNamespace()) + { + std::vector copy(rParents); + copy.push_back(rpType.getUnqualifiedType().getCanonicalType()); + auto ctsd = dyn_cast( + pRecordType->getDecl()); + assert(ctsd != nullptr); + auto const & args = ctsd->getTemplateArgs(); + assert(args.size() >= 2); + auto ret = isBadStaticType(args.get(0).getAsType(), chain, copy); + if (ret.first) { + return ret; + } + return isBadStaticType(args.get(1).getAsType(), chain, copy); + } + RecordDecl const*const pDefinition(pRecordType->getDecl()->getDefinition()); + if (!pDefinition) { // maybe no definition if it's a pointer/reference + return std::make_pair(false, std::vector()); + } + if ( type.Class("DeleteOnDeinit").Namespace("vcl").GlobalNamespace() + || type.Class("weak_ptr").StdNamespace() // not owning + || type.Class("ImplWallpaper").GlobalNamespace() // very odd static instance here + || type.Class("Application").GlobalNamespace() // numerous odd subclasses in vclmain::createApplication() + || type.Class("DemoMtfApp").AnonymousNamespace().GlobalNamespace() // one of these Application with own VclPtr + ) + { + return std::make_pair(false, std::vector()); + } + std::vector copy(rParents); + copy.push_back(rpType.getUnqualifiedType().getCanonicalType()); + CXXRecordDecl const*const pDecl(dyn_cast(pDefinition)); + assert(pDecl); + for (auto it = pDecl->field_begin(); it != pDecl->field_end(); ++it) { + chain.push_back(*it); + auto const ret(isBadStaticType((*it)->getType(), chain, copy)); + chain.pop_back(); + if (ret.first) { + return ret; + } + } + for (auto it = pDecl->bases_begin(); it != pDecl->bases_end(); ++it) { + auto const ret(isBadStaticType((*it).getType(), chain, copy)); + if (ret.first) { + return ret; + } + } + for (auto it = pDecl->vbases_begin(); it != pDecl->vbases_end(); ++it) { + auto const ret(isBadStaticType((*it).getType(), chain, copy)); + if (ret.first) { + return ret; + } + } + return std::make_pair(false, std::vector()); + } + + bool VisitVarDecl(VarDecl const*const pVarDecl) + { + if (ignoreLocation(pVarDecl)) { + return true; + } + + if (pVarDecl->hasGlobalStorage() + && pVarDecl->isThisDeclarationADefinition()) + { + auto const name(pVarDecl->getName()); + if ( name == "s_pPreviousView" // not an owning pointer + || name == "s_pDefCollapsed" // SvImpLBox::~SvImpLBox() + || name == "s_pDefExpanded" // SvImpLBox::~SvImpLBox() + || name == "g_pDDSource" // SvTreeListBox::dispose() + || name == "g_pDDTarget" // SvTreeListBox::dispose() + || name == "g_pSfxApplication" // SfxApplication::~SfxApplication() + || name == "s_SidebarResourceManagerInstance" // ResourceManager::disposeDecks() + || name == "s_pGallery" // this is not entirely clear but apparently the GalleryThemeCacheEntry are deleted by GalleryBrowser2::SelectTheme() or GalleryBrowser2::dispose() + || name == "s_ExtMgr" // TheExtensionManager::disposing() + || name == "s_pDocLockedInsertingLinks" // not owning + || name == "s_pVout" // FrameFinit() + || name == "s_pPaintQueue" // SwPaintQueue::Remove() + || name == "gProp" // only owned (VclPtr) member cleared again + || name == "g_OszCtrl" // SwCrsrOszControl::Exit() + || name == "g_pSpellIter" // SwEditShell::SpellEnd() + || name == "g_pConvIter" // SwEditShell::SpellEnd() + || name == "g_pHyphIter" // SwEditShell::HyphEnd() + || name == "xFieldEditEngine" // ScGlobal::Clear() + || name == "xDrawClipDocShellRef" // ScGlobal::Clear() + || name == "s_ImageTree" + // ImageTree::get(), ImageTree::shutDown() + || name == "s_pMouseFrame" + // vcl/osx/salframeview.mm, mouseEntered/Exited, not owning + || name == "pCurrentMenuBar" + // vcl/osx/salmenu.cxx, AquaSalMenu::set/unsetMainMenu, not + // owning + || name == "s_pCaptureFrame" // vcl/osx/salframe.cxx, not owning + || name == "pBlink" + // sw/source/core/text/blink.cxx, _TextFinit() + || name == "s_pIconCache" + // sd/source/ui/tools/IconCache.cxx, leaked + || name == "maInstanceMap" + // sd/source/ui/framework/tools/FrameworkHelper.cxx, would + // leak ViewShellBase* keys if that map is not empty at exit + || name == "theAddInAsyncTbl" + // sc/source/core/tool/adiasync.cxx, would leak + // ScAddInAsync* keys if that set is not empty at exit + || name == "g_aWindowList" + //vcl/unx/gtk3/a11y/atkutil.cxx, asserted empty at exit + || name == "gFontPreviewVirDevs" + //svtools/source/control/ctrlbox.cxx, empty at exit + || name == "aLogger" // FormulaLogger& FormulaLogger::get() in sc/source/core/tool/formulalogger.cxx + || name == "s_aUncommittedRegistrations" // sw/source/uibase/dbui/dbmgr.cxx + || (loplugin::DeclCheck(pVarDecl).Var("aAllListeners") + .Class("ScAddInListener").GlobalNamespace()) // not owning + || (loplugin::DeclCheck(pVarDecl).Var("maThreadSpecific") + .Class("ScDocument").GlobalNamespace()) // not owning + || name == "s_aLOKWindowsMap" // LOK only, guarded by assert, and LOK never tries to perform a VCL cleanup + || name == "s_aLOKWeldBuildersMap" // LOK only, similar case as above + || name == "s_aLOKPopupsMap" // LOK only, similar case as above + || name == "m_pNotebookBarWeldedWrapper" // LOK only, warning about map's key, no VCL cleanup performed + || name == "gStaticManager" // vcl/source/graphic/Manager.cxx - stores non-owning pointers + || name == "aThreadedInterpreterPool" // ScInterpreterContext(Pool), not owning + || name == "aNonThreadedInterpreterPool" // ScInterpreterContext(Pool), not owning + || name == "lcl_parserContext" // getParserContext(), the chain from this to a VclPtr is not owning + || name == "aReaderWriter" // /home/noel/libo/sw/source/filter/basflt/fltini.cxx, non-owning + || name == "aTwain" + // Windows-only extensions/source/scanner/scanwin.cxx, problematic + // Twain::mpThread -> ShimListenerThread::mxTopWindow released via Twain::Reset + // clearing mpThread + || name == "g_newReadOnlyDocs" + // sfx2/source/doc/docfile.cxx, warning about map's key + || name == "g_existingReadOnlyDocs" + // sfx2/source/doc/docfile.cxx, warning about map's key + || name == "gaFramesArr_Impl" + // sfx2/source/view/frame.cxx, vector of pointer, so not a problem, nothing is going to happen on shutdown + || name == "g_pOLELRU_Cache" || name == "s_aTableColumnsMap" + // TODO + || name == "SINGLETON" + // TheAquaA11yFocusTracker in vcl/osx/a11yfocustracker.cxx, + // AquaA11yFocusTracker::m_aDocumentWindowList elements symmetrically added and + // removed in AquaA11yFocusTracker::window_got_focus and + // AquaA11yFocusTracker::WindowEventHandler (TODO: is that guaranteed?) + ) // these variables appear unproblematic + { + return true; + } + // these two are fairly harmless because they're both empty objects + if ( name == "s_xEmptyController" // svx/source/fmcomp/gridcell.cxx + || name == "xCell" // svx/source/table/svdotable.cxx + ) + { + return true; + } + // ignore pointers, nothing happens to them on shutdown + QualType const pCanonical(pVarDecl->getType().getUnqualifiedType().getCanonicalType()); + if (pCanonical->isPointerType()) { + return true; + } + std::vector pad; + auto const ret(isBadStaticType(pVarDecl->getType(), pad, + std::vector())); + if (ret.first) { + report(DiagnosticsEngine::Warning, + "bad static variable causes crash on shutdown", + pVarDecl->getLocation()) + << pVarDecl->getSourceRange(); + if (!isUnitTestMode()) + { + for (auto i: ret.second) { + report(DiagnosticsEngine::Note, + "... due to this member of %0", + i->getLocation()) + << i->getParent() << i->getSourceRange(); + } + } + } + } + + return true; + } + +}; + +loplugin::Plugin::Registration badstatics("badstatics"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/blockblock.cxx b/compilerplugins/clang/blockblock.cxx new file mode 100644 index 000000000..bfcb0206d --- /dev/null +++ b/compilerplugins/clang/blockblock.cxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" + +/** + Check for places where we declare a block directly inside a block + */ +namespace { + +class BlockBlock: + public loplugin::FilteringPlugin +{ +public: + explicit BlockBlock(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual bool preRun() override + { + StringRef fn(handler.getMainFileName()); + if (loplugin::isSamePathname(fn, SRCDIR "/sal/osl/unx/file_misc.cxx")) + return false; + return true; + } + + void run() override { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitCompoundStmt(CompoundStmt const * ); + bool VisitCaseStmt(CaseStmt const * ); +}; + +bool BlockBlock::VisitCompoundStmt(CompoundStmt const * compound) +{ + if (ignoreLocation(compound)) + return true; + if (compound->size() != 1) + return true; + auto inner = *compound->body_begin(); + if (!isa(inner)) + return true; + if (compiler.getSourceManager().isMacroBodyExpansion(compound->getBeginLoc())) + return true; + if (compiler.getSourceManager().isMacroBodyExpansion(inner->getBeginLoc())) + return true; + if (containsPreprocessingConditionalInclusion(compound->getSourceRange())) { + return true; + } + report( + DiagnosticsEngine::Warning, + "block directly inside block", + compound->getBeginLoc()) + << compound->getSourceRange(); + report( + DiagnosticsEngine::Note, + "inner block here", + inner->getBeginLoc()) + << inner->getSourceRange(); + return true; +} + +bool BlockBlock::VisitCaseStmt(CaseStmt const * caseStmt) +{ + if (ignoreLocation(caseStmt)) + return true; + auto compoundStmt = dyn_cast(caseStmt->getSubStmt()); + if (!compoundStmt) + return true; + if (compoundStmt->size() != 2) + return true; + auto it = compoundStmt->body_begin(); + auto inner1 = *it; + if (!isa(inner1)) + return true; + ++it; + if (!isa(*it)) + return true; + report( + DiagnosticsEngine::Warning, + "block directly inside block", + compoundStmt->getBeginLoc()) + << compoundStmt->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration< BlockBlock > blockblock("blockblock", true); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/bufferadd.cxx b/compilerplugins/clang/bufferadd.cxx new file mode 100644 index 000000000..7b3eaf7e4 --- /dev/null +++ b/compilerplugins/clang/bufferadd.cxx @@ -0,0 +1,393 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +/** + Look for *StringBuffer append sequences which can be converted to *String + sequences. +*/ + +namespace +{ +class BufferAdd : public loplugin::FilteringPlugin +{ +public: + explicit BufferAdd(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/rtl/oustring/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/rtl/oustringbuffer/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/rtl/strings/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/OStringBuffer/")) + return false; + // some false + + if (loplugin::isSamePathname(fn, SRCDIR "/unoidl/source/sourcetreeprovider.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/writerfilter/source/dmapper/StyleSheetTable.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/writerfilter/source/dmapper/GraphicImport.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sdext/source/pdfimport/pdfparse/pdfparse.cxx")) + return false; + return true; + } + + void postRun() override + { + for (auto const& pair : goodMap) + if (!isa(pair.first) && + // reference types have slightly weird behaviour + !pair.first->getType()->isReferenceType() + && badMap.find(pair.first) == badMap.end()) + report(DiagnosticsEngine::Warning, + "convert this append sequence into a *String + sequence", + pair.first->getBeginLoc()) + << pair.first->getSourceRange(); + } + + virtual void run() override + { + if (!preRun()) + return; + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + postRun(); + } + + bool VisitStmt(Stmt const*); + bool VisitCallExpr(CallExpr const*); + bool VisitCXXConstructExpr(CXXConstructExpr const*); + bool VisitUnaryOperator(UnaryOperator const*); + +private: + void findBufferAssignOrAdd(const Stmt* parentStmt, Stmt const*); + Expr const* ignore(Expr const*); + bool isSideEffectFree(Expr const*); + bool isMethodOkToMerge(CXXMemberCallExpr const*); + void addToGoodMap(const VarDecl* varDecl, const Stmt* parentStmt); + + std::unordered_map goodMap; + std::unordered_set badMap; +}; + +bool BufferAdd::VisitStmt(Stmt const* stmt) +{ + if (ignoreLocation(stmt)) + return true; + + if (!isa(stmt) && !isa(stmt) && !isa(stmt) + && !isa(stmt) && !isa(stmt) && !isa(stmt) && !isa(stmt) + && !isa(stmt) && !isa(stmt)) + return true; + + for (auto it = stmt->child_begin(); it != stmt->child_end(); ++it) + if (*it) + findBufferAssignOrAdd(stmt, *it); + + return true; +} + +bool BufferAdd::VisitCallExpr(CallExpr const* callExpr) +{ + if (ignoreLocation(callExpr)) + return true; + + for (unsigned i = 0; i != callExpr->getNumArgs(); ++i) + { + auto a = ignore(callExpr->getArg(i)); + if (auto declRefExpr = dyn_cast(a)) + if (auto varDecl = dyn_cast(declRefExpr->getDecl())) + badMap.insert(varDecl); + } + return true; +} + +bool BufferAdd::VisitCXXConstructExpr(CXXConstructExpr const* callExpr) +{ + if (ignoreLocation(callExpr)) + return true; + + for (unsigned i = 0; i != callExpr->getNumArgs(); ++i) + { + auto a = ignore(callExpr->getArg(i)); + if (auto declRefExpr = dyn_cast(a)) + if (auto varDecl = dyn_cast(declRefExpr->getDecl())) + badMap.insert(varDecl); + } + return true; +} + +bool BufferAdd::VisitUnaryOperator(const UnaryOperator* unaryOp) +{ + if (ignoreLocation(unaryOp)) + return true; + if (unaryOp->getOpcode() != UO_AddrOf) + return true; + auto a = ignore(unaryOp->getSubExpr()); + if (auto declRefExpr = dyn_cast(a)) + if (auto varDecl = dyn_cast(declRefExpr->getDecl())) + badMap.insert(varDecl); + return true; +} + +void BufferAdd::findBufferAssignOrAdd(const Stmt* parentStmt, Stmt const* stmt) +{ + if (auto exprCleanup = dyn_cast(stmt)) + stmt = exprCleanup->getSubExpr(); + if (auto switchCase = dyn_cast(stmt)) + stmt = switchCase->getSubStmt(); + if (auto declStmt = dyn_cast(stmt)) + { + if (declStmt->isSingleDecl()) + if (auto varDeclLHS = dyn_cast_or_null(declStmt->getSingleDecl())) + { + auto tc = loplugin::TypeCheck(varDeclLHS->getType()); + if (!tc.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + && !tc.Class("OStringBuffer").Namespace("rtl").GlobalNamespace()) + return; + if (varDeclLHS->getStorageDuration() == SD_Static) + return; + if (!varDeclLHS->hasInit()) + return; + auto cxxConstructExpr = dyn_cast(ignore(varDeclLHS->getInit())); + if (cxxConstructExpr) + { + addToGoodMap(varDeclLHS, parentStmt); + return; + } + if (!isSideEffectFree(varDeclLHS->getInit())) + badMap.insert(varDeclLHS); + else + addToGoodMap(varDeclLHS, parentStmt); + } + return; + } + + // check for single calls to buffer method + + if (auto memberCallExpr = dyn_cast(stmt)) + { + if (auto declRefExprLHS + = dyn_cast(ignore(memberCallExpr->getImplicitObjectArgument()))) + { + auto methodDecl = memberCallExpr->getMethodDecl(); + if (methodDecl && methodDecl->getIdentifier()) + if (auto varDeclLHS = dyn_cast(declRefExprLHS->getDecl())) + { + auto tc = loplugin::TypeCheck(varDeclLHS->getType()); + if (tc.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + || tc.Class("OStringBuffer").Namespace("rtl").GlobalNamespace()) + { + if (isMethodOkToMerge(memberCallExpr)) + addToGoodMap(varDeclLHS, parentStmt); + else + badMap.insert(varDeclLHS); + } + } + return; + } + } + + // now check for chained append calls + + auto expr = dyn_cast(stmt); + if (!expr) + return; + auto tc = loplugin::TypeCheck(expr->getType()); + if (!tc.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + && !tc.Class("OStringBuffer").Namespace("rtl").GlobalNamespace()) + return; + + // unwrap the chain (which runs from right to left) + const VarDecl* varDeclLHS = nullptr; + bool good = true; + while (true) + { + auto memberCallExpr = dyn_cast(expr); + if (!memberCallExpr) + break; + good &= isMethodOkToMerge(memberCallExpr); + + if (auto declRefExprLHS + = dyn_cast(ignore(memberCallExpr->getImplicitObjectArgument()))) + { + varDeclLHS = dyn_cast(declRefExprLHS->getDecl()); + break; + } + expr = memberCallExpr->getImplicitObjectArgument(); + } + + if (varDeclLHS) + { + if (good) + addToGoodMap(varDeclLHS, parentStmt); + else + badMap.insert(varDeclLHS); + } +} + +void BufferAdd::addToGoodMap(const VarDecl* varDecl, const Stmt* parentStmt) +{ + // check that vars are all inside the same compoundstmt, if they are not, we cannot combine them + auto it = goodMap.find(varDecl); + if (it != goodMap.end()) + { + if (it->second == parentStmt) + return; + // don't treat these as parents, otherwise we eliminate .append.append sequences + if (isa(parentStmt)) + return; + if (isa(parentStmt)) + return; + badMap.insert(varDecl); + } + else + goodMap.emplace(varDecl, parentStmt); +} + +bool BufferAdd::isMethodOkToMerge(CXXMemberCallExpr const* memberCall) +{ + auto methodDecl = memberCall->getMethodDecl(); + if (methodDecl->getNumParams() == 0) + return true; + + if (auto const id = methodDecl->getIdentifier()) + { + auto name = id->getName(); + if (name == "appendUninitialized" || name == "setLength" || name == "remove" + || name == "insert" || name == "appendAscii" || name == "appendUtf32") + return false; + } + + auto rhs = memberCall->getArg(0); + if (!isSideEffectFree(rhs)) + return false; + return true; +} + +Expr const* BufferAdd::ignore(Expr const* expr) +{ + return expr->IgnoreImplicit()->IgnoreParens()->IgnoreImplicit(); +} + +bool BufferAdd::isSideEffectFree(Expr const* expr) +{ + expr = ignore(expr); + // I don't think the OUStringAppend functionality can handle this efficiently + if (isa(expr)) + return false; + // Multiple statements have a well defined evaluation order (sequence points between them) + // but a single expression may be evaluated in arbitrary order; + // if there are side effects in one of the sub-expressions that have an effect on another subexpression, + // the result may be incorrect, and you don't necessarily notice in tests because the order is compiler-dependent. + // for example see commit afd743141f7a7dd05914d0872c9afe079f16fe0c where such a refactoring introduced such a bug. + // So only consider simple RHS expressions. + if (!expr->HasSideEffects(compiler.getASTContext())) + return true; + + // check for chained adds which are side-effect free + if (auto operatorCall = dyn_cast(expr)) + { + auto op = operatorCall->getOperator(); + if (op == OO_PlusEqual || op == OO_Plus) + if (isSideEffectFree(operatorCall->getArg(0)) + && isSideEffectFree(operatorCall->getArg(1))) + return true; + } + + if (auto callExpr = dyn_cast(expr)) + { + // check for calls through OUString::number/OUString::unacquired + if (auto calleeMethodDecl = dyn_cast_or_null(callExpr->getCalleeDecl())) + if (calleeMethodDecl && calleeMethodDecl->getIdentifier()) + { + if (callExpr->getNumArgs() > 0) + { + auto tc = loplugin::TypeCheck(calleeMethodDecl->getParent()); + if (tc.Class("OUString") || tc.Class("OString")) + { + if (isSideEffectFree(callExpr->getArg(0))) + return true; + } + } + } + if (auto calleeFunctionDecl = dyn_cast_or_null(callExpr->getCalleeDecl())) + if (calleeFunctionDecl && calleeFunctionDecl->getIdentifier()) + { + auto name = calleeFunctionDecl->getName(); + // check for calls through OUStringToOString + if (name == "OUStringToOString" || name == "OStringToOUString") + if (isSideEffectFree(callExpr->getArg(0))) + return true; + // allowlist some known-safe methods + if (name.endswith("ResId") || name == "GetXMLToken") + if (isSideEffectFree(callExpr->getArg(0))) + return true; + } + // O[U]String::operator std::[u16]string_view: + if (auto const d = dyn_cast_or_null(callExpr->getCalleeDecl())) + { + auto tc = loplugin::TypeCheck(d->getParent()); + if (tc.Class("OString") || tc.Class("OUString")) + { + return true; + } + } + } + + // sometimes we have a constructor call on the RHS + if (auto constructExpr = dyn_cast(expr)) + { + auto dc = loplugin::DeclCheck(constructExpr->getConstructor()); + if (dc.MemberFunction().Class("OUString") || dc.MemberFunction().Class("OString") + || dc.MemberFunction().Class("OUStringBuffer") + || dc.MemberFunction().Class("OStringBuffer")) + if (constructExpr->getNumArgs() == 0 || isSideEffectFree(constructExpr->getArg(0))) + return true; + // Expr::HasSideEffects does not like stuff that passes through OUStringLiteral + auto dc2 = loplugin::DeclCheck(constructExpr->getConstructor()->getParent()); + if (dc2.Class("OUStringLiteral").Namespace("rtl").GlobalNamespace()) + return true; + } + + // when adding literals, we sometimes get this + if (auto functionalCastExpr = dyn_cast(expr)) + { + auto tc = loplugin::TypeCheck(functionalCastExpr->getType()); + if (tc.Class("OUStringLiteral").Namespace("rtl").GlobalNamespace()) + return isSideEffectFree(functionalCastExpr->getSubExpr()); + } + + return false; +} + +loplugin::Plugin::Registration bufferadd("bufferadd"); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/buriedassign.cxx b/compilerplugins/clang/buriedassign.cxx new file mode 100644 index 000000000..acc8bfe7d --- /dev/null +++ b/compilerplugins/clang/buriedassign.cxx @@ -0,0 +1,650 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +// This checker aims to pull buried assignments out of complex expressions, +// where they are quite hard to notice amidst the other conditional logic. + +namespace +{ +class BuriedAssign : public loplugin::FilteringPlugin +{ +public: + explicit BuriedAssign(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + + // code where I don't have a better alternative + if (fn == SRCDIR "/sal/osl/unx/profile.cxx") + return; + if (fn == SRCDIR "/sal/rtl/uri.cxx") + return; + if (fn == SRCDIR "/sal/osl/unx/process.cxx") + return; + if (fn == SRCDIR "/sal/rtl/bootstrap.cxx") + return; + if (fn == SRCDIR "/i18npool/source/textconversion/genconv_dict.cxx") + return; + if (fn == SRCDIR "/soltools/cpp/_macro.c") + return; + if (fn == SRCDIR "/stoc/source/inspect/introspection.cxx") + return; + if (fn == SRCDIR "/tools/source/fsys/urlobj.cxx") + return; + if (fn == SRCDIR "/sax/source/tools/fastserializer.cxx") + return; + if (fn == SRCDIR "/svl/source/crypto/cryptosign.cxx") + return; + if (fn == SRCDIR "/svl/source/numbers/zforfind.cxx") + return; + if (fn == SRCDIR "/svl/source/numbers/zformat.cxx") + return; + if (fn == SRCDIR "/svl/source/numbers/zforscan.cxx") + return; + if (fn == SRCDIR "/svl/source/numbers/zforlist.cxx") + return; + if (fn == SRCDIR "/vcl/source/window/debugevent.cxx") + return; + if (fn == SRCDIR "/vcl/source/control/scrbar.cxx") + return; + if (fn == SRCDIR "/vcl/source/gdi/bitmap3.cxx") + return; + if (fn == SRCDIR "/vcl/source/window/menu.cxx") + return; + if (fn == SRCDIR "/vcl/source/fontsubset/sft.cxx") + return; + if (fn == SRCDIR "/vcl/unx/generic/print/prtsetup.cxx") + return; + if (fn == SRCDIR "/svtools/source/brwbox/brwbox1.cxx") + return; + if (fn == SRCDIR "/svtools/source/control/valueset.cxx") + return; + if (fn == SRCDIR "/basic/source/runtime/iosys.cxx") + return; + if (fn == SRCDIR "/basic/source/runtime/runtime.cxx") + return; + if (fn == SRCDIR "/basic/source/sbx/sbxvalue.cxx") + return; + if (fn == SRCDIR "/basic/source/sbx/sbxvalue.cxx") + return; + if (fn == SRCDIR "/sfx2/source/dialog/templdlg.cxx") + return; + if (fn == SRCDIR "/sfx2/source/view/viewfrm.cxx") + return; + if (fn == SRCDIR "/connectivity/source/commontools/dbtools.cxx") + return; + if (fn == SRCDIR "/xmloff/source/style/xmlnumfi.cxx") + return; + if (fn == SRCDIR "/xmloff/source/style/xmlnumfe .cxx") + return; + if (fn == SRCDIR "/editeng/source/items/textitem.cxx") + return; + if (fn == SRCDIR "/editeng/source/rtf/rtfitem.cxx") + return; + if (fn == SRCDIR "/editeng/source/rtf/svxrtf.cxx") + return; + if (fn == SRCDIR "/editeng/source/misc/svxacorr.cxx") + return; + if (fn == SRCDIR "/svx/source/items/numfmtsh.cxx") + return; + if (fn == SRCDIR "/svx/source/dialog/hdft.cxx") + return; + if (fn == SRCDIR "/cui/source/dialogs/insdlg.cxx") + return; + if (fn == SRCDIR "/cui/source/tabpages/paragrph.cxx") + return; + if (fn == SRCDIR "/cui/source/tabpages/page.cxx") + return; + if (fn == SRCDIR "/cui/source/tabpages/border.cxx") + return; + if (fn == SRCDIR "/cui/source/tabpages/chardlg.cxx") + return; + if (fn == SRCDIR "/cui/source/tabpages/numpages.cxx") + return; + if (fn == SRCDIR "/cui/source/dialogs/SpellDialog.cxx") + return; + if (fn == SRCDIR "/oox/source/drawingml/diagram/diagramlayoutatoms.cxx") + return; + if (fn == SRCDIR "/dbaccess/source/core/dataaccess/intercept.cxx") + return; + if (fn == SRCDIR "/writerfilter/source/dmapper/DomainMapper.cxx") + return; + if (fn == SRCDIR "/writerfilter/source/dmapper/DomainMapper_Impl.cxx") + return; + if (fn == SRCDIR "/lotuswordpro/source/filter/lwptablelayout.cxx") + return; + if (fn == SRCDIR "/i18npool/source/characterclassification/cclass_unicode_parser.cxx") + return; + if (fn == SRCDIR "/sd/source/filter/eppt/pptx-animations.cxx") + return; + if (fn == SRCDIR "/sc/source/core/tool/address.cxx") + return; + if (fn == SRCDIR "/sc/source/core/tool/interpr1.cxx") + return; + if (fn == SRCDIR "/sc/source/core/tool/interpr4.cxx") + return; + if (fn == SRCDIR "/sc/source/core/tool/interpr5.cxx") + return; + if (fn == SRCDIR "/sc/source/core/tool/compiler.cxx") + return; + if (fn == SRCDIR "/sc/source/core/data/table4.cxx") + return; + if (fn == SRCDIR "/sc/source/ui/drawfunc/fudraw.cxx") + return; + if (fn == SRCDIR "/sc/source/filter/xml/xmlcelli.cxx") + return; + if (fn == SRCDIR "/sc/source/ui/miscdlgs/crnrdlg.cxx") + return; + if (fn == SRCDIR "/sc/source/ui/app/inputwin.cxx") + return; + if (fn == SRCDIR "/sc/source/ui/view/viewfun2.cxx") + return; + if (fn == SRCDIR "/sc/source/ui/unoobj/docuno.cxx") + return; + if (fn == SRCDIR "/sc/source/ui/view/gridwin.cxx") + return; + if (fn == SRCDIR "/sw/source/core/crsr/callnk.cxx") + return; + if (fn == SRCDIR "/sw/source/core/crsr/findtxt.cxx") + return; + if (fn == SRCDIR "/sw/source/core/crsr/crsrsh.cxx") + return; + if (fn == SRCDIR "/sw/source/core/crsr/crstrvl.cxx") + return; + if (fn == SRCDIR "/sw/source/core/doc/doccomp.cxx") + return; + if (fn == SRCDIR "/sw/source/core/doc/docedt.cxx") + return; + if (fn == SRCDIR "/sw/source/core/doc/docfly.cxx") + return; + if (fn == SRCDIR "/sw/source/core/doc/DocumentRedlineManager.cxx") + return; + if (fn == SRCDIR "/sw/source/core/doc/notxtfrm.cxx") + return; + if (fn == SRCDIR "/sw/source/core/docnode/node.cxx") + return; + if (fn == SRCDIR "/sw/source/core/layout/ftnfrm.cxx") + return; + if (fn == SRCDIR "/sw/source/core/table/swtable.cxx") + return; + if (fn == SRCDIR "/sw/source/core/unocore/unoframe.cxx") + return; + if (fn == SRCDIR "/sw/source/filter/xml/xmlimp.cxx") + return; + if (fn == SRCDIR "/sw/source/uibase/docvw/edtwin.cxx") + return; + if (fn == SRCDIR "/sw/source/uibase/shells/langhelper.cxx") + return; + if (fn == SRCDIR "/sw/source/uibase/shells/tabsh.cxx") + return; + if (fn == SRCDIR "/sw/source/uibase/shells/textsh1.cxx") + return; + if (fn == SRCDIR "/sw/source/uibase/uiview/view2.cxx") + return; + if (fn == SRCDIR "/starmath/source/mathtype.cxx") + return; + if (fn == SRCDIR "/starmath/source/mathmlexport.cxx") + return; + if (fn == SRCDIR "/starmath/source/view.cxx") + return; + if (fn == SRCDIR "/xmlhelp/source/treeview/tvread.cxx") + return; + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitBinaryOperator(BinaryOperator const*); + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const*); + bool VisitCompoundStmt(CompoundStmt const*); + bool VisitIfStmt(IfStmt const*); + bool VisitLabelStmt(LabelStmt const*); + bool VisitForStmt(ForStmt const*); + bool VisitCXXForRangeStmt(CXXForRangeStmt const*); + bool VisitWhileStmt(WhileStmt const*); + bool VisitDoStmt(DoStmt const*); + bool VisitCaseStmt(CaseStmt const*); + bool VisitDefaultStmt(DefaultStmt const*); + bool VisitVarDecl(VarDecl const*); + bool VisitCXXFoldExpr(CXXFoldExpr const*); + +private: + void MarkIfAssignment(Stmt const*); + void MarkAll(Stmt const*); + void MarkConditionForControlLoops(Expr const*); + + std::unordered_set m_handled; +}; + +static bool isAssignmentOp(clang::BinaryOperatorKind op) +{ + // We ignore BO_ShrAssign i.e. >>= because we use that everywhere for + // extracting data from css::uno::Any + return op == BO_Assign || op == BO_MulAssign || op == BO_DivAssign || op == BO_RemAssign + || op == BO_AddAssign || op == BO_SubAssign || op == BO_ShlAssign || op == BO_AndAssign + || op == BO_XorAssign || op == BO_OrAssign; +} + +static bool isAssignmentOp(clang::OverloadedOperatorKind Opc) +{ + // Same logic as CXXOperatorCallExpr::isAssignmentOp(), which our supported clang + // doesn't have yet. + // Except that we ignore OO_GreaterGreaterEqual i.e. >>= because we use that everywhere for + // extracting data from css::uno::Any + return Opc == OO_Equal || Opc == OO_StarEqual || Opc == OO_SlashEqual || Opc == OO_PercentEqual + || Opc == OO_PlusEqual || Opc == OO_MinusEqual || Opc == OO_LessLessEqual + || Opc == OO_AmpEqual || Opc == OO_CaretEqual || Opc == OO_PipeEqual; +} + +static const Expr* IgnoreImplicitAndConversionOperator(const Expr* expr) +{ + expr = expr->IgnoreImplicit(); + if (auto memberCall = dyn_cast(expr)) + { + if (auto conversionDecl = dyn_cast_or_null(memberCall->getMethodDecl())) + { + if (!conversionDecl->isExplicit()) + expr = memberCall->getImplicitObjectArgument()->IgnoreImplicit(); + } + } + return expr; +} + +bool BuriedAssign::VisitBinaryOperator(BinaryOperator const* binaryOp) +{ + if (ignoreLocation(binaryOp)) + return true; + if (binaryOp->getBeginLoc().isMacroID()) + return true; + if (!isAssignmentOp(binaryOp->getOpcode())) + return true; + auto expr = IgnoreImplicitAndConversionOperator(binaryOp->getRHS()); + if (auto rhs = dyn_cast(expr)) + { + // Ignore chained assignment. + // TODO limit this to only ordinary assignment + if (isAssignmentOp(rhs->getOpcode())) + m_handled.insert(rhs); + } + else if (auto rhs = dyn_cast(expr)) + { + // Ignore chained assignment. + // TODO limit this to only ordinary assignment + if (isAssignmentOp(rhs->getOperator())) + m_handled.insert(rhs); + } + else if (auto cxxConstruct = dyn_cast(expr)) + { + if (cxxConstruct->getNumArgs() == 1) + MarkIfAssignment(cxxConstruct->getArg(0)); + } + if (!m_handled.insert(binaryOp).second) + return true; + + // assignment in constructor + StringRef aFileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(binaryOp->getBeginLoc())); + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/comphelper/flagguard.hxx")) + return true; + + report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line", + binaryOp->getBeginLoc()) + << binaryOp->getSourceRange(); + //getParentStmt(getParentStmt(getParentStmt(getParentStmt(getParentStmt(getParentStmt(binaryOp))))))->dump(); + return true; +} + +bool BuriedAssign::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* cxxOper) +{ + if (ignoreLocation(cxxOper)) + return true; + if (cxxOper->getBeginLoc().isMacroID()) + return true; + if (!isAssignmentOp(cxxOper->getOperator())) + return true; + auto expr = IgnoreImplicitAndConversionOperator(cxxOper->getArg(1)); + if (auto rhs = dyn_cast(expr)) + { + // Ignore chained assignment. + // TODO limit this to only ordinary assignment + if (isAssignmentOp(rhs->getOpcode())) + m_handled.insert(rhs); + } + else if (auto rhs = dyn_cast(expr)) + { + // Ignore chained assignment. + // TODO limit this to only ordinary assignment + if (isAssignmentOp(rhs->getOperator())) + m_handled.insert(rhs); + } + else if (auto cxxConstruct = dyn_cast(expr)) + { + if (cxxConstruct->getNumArgs() == 1) + MarkIfAssignment(cxxConstruct->getArg(0)); + } + if (!m_handled.insert(cxxOper).second) + return true; + report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line", + cxxOper->getBeginLoc()) + << cxxOper->getSourceRange(); + //getParentStmt(getParentStmt(getParentStmt(getParentStmt(getParentStmt(cxxOper)))))->dump(); + return true; +} + +bool BuriedAssign::VisitCompoundStmt(CompoundStmt const* compoundStmt) +{ + if (ignoreLocation(compoundStmt)) + return true; + for (auto i = compoundStmt->child_begin(); i != compoundStmt->child_end(); ++i) + { + if (auto expr = dyn_cast(*i)) + { + expr = expr->IgnoreImplicit(); + if (auto binaryOp = dyn_cast(expr)) + { + // ignore comma-chained statements at this level + if (binaryOp->getOpcode() == BO_Comma) + { + MarkIfAssignment(binaryOp->getLHS()); + MarkIfAssignment(binaryOp->getRHS()); + continue; + } + } + MarkIfAssignment(expr); + } + } + return true; +} + +void BuriedAssign::MarkIfAssignment(Stmt const* stmt) +{ + if (auto expr = dyn_cast_or_null(stmt)) + { + expr = expr->IgnoreImplicit(); + if (auto binaryOp = dyn_cast(expr)) + { + if (isAssignmentOp(binaryOp->getOpcode())) + { + m_handled.insert(expr); + MarkIfAssignment(binaryOp->getRHS()); // in case it is chained + } + else if (binaryOp->getOpcode() == BO_Comma) + { + MarkIfAssignment(binaryOp->getLHS()); + MarkIfAssignment(binaryOp->getRHS()); + } + } + else if (auto cxxOper = dyn_cast(expr)) + { + if (isAssignmentOp(cxxOper->getOperator())) + { + m_handled.insert(expr); + MarkIfAssignment(cxxOper->getArg(1)); // in case it is chained + } + } + } +} + +void BuriedAssign::MarkAll(Stmt const* stmt) +{ + m_handled.insert(stmt); + for (auto it = stmt->child_begin(); it != stmt->child_end(); ++it) + MarkAll(*it); +} + +/** + * Restrict this to cases where the buried assignment is part of the first + * condition inside the if condition. Other cases tend to be too hard + * too extract (notably in sw/) + */ +bool BuriedAssign::VisitIfStmt(IfStmt const* ifStmt) +{ + if (ignoreLocation(ifStmt)) + return true; + MarkIfAssignment(ifStmt->getThen()); + MarkIfAssignment(ifStmt->getElse()); + + auto expr = ifStmt->getCond(); + expr = IgnoreImplicitAndConversionOperator(expr); + expr = expr->IgnoreParens(); + expr = IgnoreImplicitAndConversionOperator(expr); + MarkAll(expr); + + if (auto binaryOp = dyn_cast(expr)) + { + if (isAssignmentOp(binaryOp->getOpcode())) + { + report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line", + expr->getBeginLoc()) + << expr->getSourceRange(); + } + else if (binaryOp->isComparisonOp()) + { + if (auto binaryOp2 + = dyn_cast(binaryOp->getLHS()->IgnoreParenImpCasts())) + { + if (!binaryOp->getRHS()->isValueDependent() + && binaryOp->getRHS()->isCXX11ConstantExpr(compiler.getASTContext()) + && isAssignmentOp(binaryOp2->getOpcode())) + report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line", + expr->getBeginLoc()) + << expr->getSourceRange(); + } + if (auto binaryOp2 + = dyn_cast(binaryOp->getRHS()->IgnoreParenImpCasts())) + { + if (!binaryOp->getLHS()->isValueDependent() + && binaryOp->getLHS()->isCXX11ConstantExpr(compiler.getASTContext()) + && isAssignmentOp(binaryOp2->getOpcode())) + report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line", + expr->getBeginLoc()) + << expr->getSourceRange(); + } + } + else if (binaryOp->isLogicalOp()) + { + if (auto binaryOp2 + = dyn_cast(binaryOp->getLHS()->IgnoreParenImpCasts())) + { + if (isAssignmentOp(binaryOp2->getOpcode())) + report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line", + expr->getBeginLoc()) + << expr->getSourceRange(); + } + } + } + else if (auto operCall = dyn_cast(expr)) + { + // Ignore chained assignment. + // TODO limit this to only ordinary assignment + if (isAssignmentOp(operCall->getOperator())) + { + report(DiagnosticsEngine::Warning, "buried assignment, rather put on own line", + expr->getBeginLoc()) + << expr->getSourceRange(); + } + } + + return true; +} + +bool BuriedAssign::VisitCaseStmt(CaseStmt const* stmt) +{ + if (ignoreLocation(stmt)) + return true; + MarkIfAssignment(stmt->getSubStmt()); + return true; +} + +bool BuriedAssign::VisitDefaultStmt(DefaultStmt const* stmt) +{ + if (ignoreLocation(stmt)) + return true; + MarkIfAssignment(stmt->getSubStmt()); + return true; +} + +bool BuriedAssign::VisitWhileStmt(WhileStmt const* stmt) +{ + if (ignoreLocation(stmt)) + return true; + MarkConditionForControlLoops(stmt->getCond()); + MarkIfAssignment(stmt->getBody()); + return true; +} + +bool BuriedAssign::VisitDoStmt(DoStmt const* stmt) +{ + if (ignoreLocation(stmt)) + return true; + MarkConditionForControlLoops(stmt->getCond()); + MarkIfAssignment(stmt->getBody()); + return true; +} + +/** stuff like + * while ((x = foo()) + * and + * while ((x = foo() < 0) + * is considered idiomatic. + */ +void BuriedAssign::MarkConditionForControlLoops(Expr const* expr) +{ + if (!expr) + return; + expr = expr->IgnoreImplicit(); + + if (auto binaryOp = dyn_cast(expr)) + { + // ignore comma-chained statements at this level + if (binaryOp->getOpcode() == BO_Comma) + { + MarkConditionForControlLoops(binaryOp->getLHS()); + MarkConditionForControlLoops(binaryOp->getRHS()); + return; + } + } + + // unwrap conversion to bool + if (auto memberCall = dyn_cast(expr)) + { + if (memberCall->getMethodDecl() && isa(memberCall->getMethodDecl())) + { + // TODO check that the conversion is converting to bool + expr = memberCall->getImplicitObjectArgument()->IgnoreImplicit(); + } + } + + if (auto binaryOp = dyn_cast(expr)) + { + // handle: ((xxx = foo()) != error) + if (binaryOp->isComparisonOp()) + { + MarkIfAssignment(binaryOp->getLHS()->IgnoreImplicit()->IgnoreParens()); + MarkIfAssignment(binaryOp->getRHS()->IgnoreImplicit()->IgnoreParens()); + } + } + else if (auto cxxOper = dyn_cast(expr)) + { + // handle: ((xxx = foo()) != error) + if (cxxOper->isComparisonOp()) + { + MarkIfAssignment(cxxOper->getArg(0)->IgnoreImplicit()->IgnoreParens()); + MarkIfAssignment(cxxOper->getArg(1)->IgnoreImplicit()->IgnoreParens()); + } + // handle: (!(xxx = foo())) + else if (cxxOper->getOperator() == OO_Exclaim) + MarkIfAssignment(cxxOper->getArg(0)->IgnoreImplicit()->IgnoreParens()); + } + else if (auto parenExpr = dyn_cast(expr)) + { + // handle: ((xxx = foo())) + MarkIfAssignment(parenExpr->getSubExpr()->IgnoreImplicit()); + } + else if (auto unaryOp = dyn_cast(expr)) + { + // handle: (!(xxx = foo())) + MarkIfAssignment(unaryOp->getSubExpr()->IgnoreImplicit()->IgnoreParens()); + } + else + MarkIfAssignment(expr); +} + +bool BuriedAssign::VisitForStmt(ForStmt const* stmt) +{ + if (ignoreLocation(stmt)) + return true; + MarkIfAssignment(stmt->getInit()); + MarkConditionForControlLoops(stmt->getCond()); + MarkIfAssignment(stmt->getInc()); + MarkIfAssignment(stmt->getBody()); + return true; +} + +bool BuriedAssign::VisitCXXForRangeStmt(CXXForRangeStmt const* stmt) +{ + if (ignoreLocation(stmt)) + return true; + MarkIfAssignment(stmt->getBody()); + return true; +} + +bool BuriedAssign::VisitLabelStmt(LabelStmt const* stmt) +{ + if (ignoreLocation(stmt)) + return true; + MarkIfAssignment(stmt->getSubStmt()); + return true; +} + +bool BuriedAssign::VisitVarDecl(VarDecl const* stmt) +{ + if (ignoreLocation(stmt)) + return true; + if (stmt->getInit()) + { + auto expr = IgnoreImplicitAndConversionOperator(stmt->getInit()); + MarkIfAssignment(expr); + if (auto cxxConstruct = dyn_cast(expr)) + { + if (cxxConstruct->getNumArgs() == 1) + MarkIfAssignment(cxxConstruct->getArg(0)); + } + } + return true; +} + +bool BuriedAssign::VisitCXXFoldExpr(CXXFoldExpr const* stmt) +{ + if (ignoreLocation(stmt)) + return true; + MarkConditionForControlLoops(stmt->getLHS()); + MarkConditionForControlLoops(stmt->getRHS()); + return true; +} + +// off by default because it uses getParentStmt so it's more expensive to run +loplugin::Plugin::Registration X("buriedassign", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/casttovoid.cxx b/compilerplugins/clang/casttovoid.cxx new file mode 100644 index 000000000..bddfcb4da --- /dev/null +++ b/compilerplugins/clang/casttovoid.cxx @@ -0,0 +1,535 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#include "clang/AST/Attr.h" + +#include "check.hxx" +#include "plugin.hxx" + +namespace { + +bool isWarnUnusedType(QualType type) { + if (auto const t = type->getAs()) { + if (t->getDecl()->hasAttr()) { + return true; + } + } + if (auto const t = type->getAs()) { + if (t->getDecl()->hasAttr()) { + return true; + } + } + return loplugin::isExtraWarnUnusedType(type); +} + +Expr const * lookThroughInitListExpr(Expr const * expr) { + if (auto const ile = dyn_cast(expr->IgnoreParenImpCasts())) { + if (ile->getNumInits() == 1) { + return ile->getInit(0); + } + } + return expr; +} + +class CastToVoid final: + public loplugin::FilteringPlugin +{ +public: + explicit CastToVoid(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + bool TraverseCStyleCastExpr(CStyleCastExpr * expr) { + auto const dre = checkCast(expr); + if (dre != nullptr) { + castToVoid_.push({expr, dre}); + } + auto const ret = RecursiveASTVisitor::TraverseCStyleCastExpr(expr); + if (dre != nullptr) { + assert(!castToVoid_.empty()); + assert(castToVoid_.top().cast == expr); + assert(castToVoid_.top().sub == dre); + castToVoid_.pop(); + } + return ret; + } + + bool TraverseCXXStaticCastExpr(CXXStaticCastExpr * expr) { + auto const dre = checkCast(expr); + if (dre != nullptr) { + castToVoid_.push({expr, dre}); + } + auto const ret = RecursiveASTVisitor::TraverseCXXStaticCastExpr(expr); + if (dre != nullptr) { + assert(!castToVoid_.empty()); + assert(castToVoid_.top().cast == expr); + assert(castToVoid_.top().sub == dre); + castToVoid_.pop(); + } + return ret; + } + + bool TraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr * expr) { + auto const dre = checkCast(expr); + if (dre != nullptr) { + castToVoid_.push({expr, dre}); + } + auto const ret = RecursiveASTVisitor::TraverseCXXFunctionalCastExpr( + expr); + if (dre != nullptr) { + assert(!castToVoid_.empty()); + assert(castToVoid_.top().cast == expr); + assert(castToVoid_.top().sub == dre); + castToVoid_.pop(); + } + return ret; + } + + bool TraverseFunctionDecl(FunctionDecl * decl) { + returnTypes_.push(decl->getReturnType()); + auto const ret = RecursiveASTVisitor::TraverseFunctionDecl(decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl * decl) { + returnTypes_.push(decl->getReturnType()); + auto const ret = RecursiveASTVisitor::TraverseCXXDeductionGuideDecl( + decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseCXXMethodDecl(CXXMethodDecl * decl) { + returnTypes_.push(decl->getReturnType()); + auto const ret = RecursiveASTVisitor::TraverseCXXMethodDecl(decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseCXXConstructorDecl(CXXConstructorDecl * decl) { + returnTypes_.push(decl->getReturnType()); + auto const ret = RecursiveASTVisitor::TraverseCXXConstructorDecl(decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseCXXDestructorDecl(CXXDestructorDecl * decl) { + returnTypes_.push(decl->getReturnType()); + auto const ret = RecursiveASTVisitor::TraverseCXXDestructorDecl(decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseCXXConversionDecl(CXXConversionDecl * decl) { + returnTypes_.push(decl->getReturnType()); + auto const ret = RecursiveASTVisitor::TraverseCXXConversionDecl(decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseObjCMethodDecl(ObjCMethodDecl * decl) { + returnTypes_.push(decl->getReturnType()); + auto const ret = RecursiveASTVisitor::TraverseObjCMethodDecl(decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseConstructorInitializer(CXXCtorInitializer * init) { + if (auto const field = init->getAnyMember()) { + if (loplugin::TypeCheck(field->getType()).LvalueReference()) { + recordConsumption(lookThroughInitListExpr(init->getInit())); + } + } + return RecursiveASTVisitor::TraverseConstructorInitializer(init); + } + + bool TraverseLambdaExpr(LambdaExpr * expr, DataRecursionQueue * queue = nullptr) { + if (!shouldTraversePostOrder()) { + if (!WalkUpFromLambdaExpr(expr)) { + return false; + } + } + auto const n = expr->capture_size(); + for (unsigned i = 0; i != n; ++i) { + auto const c = expr->capture_begin() + i; + if (c->isExplicit() || shouldVisitImplicitCode()) { + if (!TraverseLambdaCapture(expr, c, expr->capture_init_begin()[i])) { + return false; + } + } + } + if (!TraverseCXXRecordDecl(expr->getLambdaClass())) { + return false; + } + if (!queue && shouldTraversePostOrder()) { + if (!WalkUpFromLambdaExpr(expr)) { + return false; + } + } + return true; + } + + bool VisitDeclRefExpr(DeclRefExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto const var = dyn_cast(expr->getDecl()); + if (var == nullptr) { + return true; + } + if (var->getType().isVolatileQualified()) { + return true; + } + auto & usage = vars_[var->getCanonicalDecl()]; + if (!castToVoid_.empty() && castToVoid_.top().sub == expr) { + usage.castToVoid.push_back(castToVoid_.top().cast); + } else { + usage.mentioned = true; + } + return true; + } + + bool VisitImplicitCastExpr(ImplicitCastExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (expr->getCastKind() != CK_LValueToRValue) { + return true; + } + recordConsumption(expr->getSubExpr()); + return true; + } + + bool VisitCallExpr(CallExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + unsigned firstArg = 0; + if (auto const cmce = dyn_cast(expr)) { + if (auto const e1 = cmce->getMethodDecl()) { + if (e1->isConst() || e1->isStatic()) { + recordConsumption(cmce->getImplicitObjectArgument()); + } + } else if (auto const e2 = dyn_cast( + cmce->getCallee()->IgnoreParenImpCasts())) + { + switch (e2->getOpcode()) { + case BO_PtrMemD: + case BO_PtrMemI: + if (e2->getRHS()->getType()->getAs() + ->getPointeeType()->getAs() + ->isConst()) + { + recordConsumption(e2->getLHS()); + } + break; + default: + break; + } + } + } else if (isa(expr)) { + if (auto const cmd = dyn_cast_or_null( + expr->getDirectCallee())) + { + if (!cmd->isStatic()) { + assert(expr->getNumArgs() != 0); + if (cmd->isConst()) { + recordConsumption(expr->getArg(0)); + } + firstArg = 1; + } + } + } + auto fun = expr->getDirectCallee(); + if (fun == nullptr) { + return true; + } + unsigned const n = std::min(fun->getNumParams(), expr->getNumArgs()); + for (unsigned i = firstArg; i < n; ++i) { + if (!loplugin::TypeCheck(fun->getParamDecl(i)->getType()) + .LvalueReference().Const()) + { + continue; + } + recordConsumption(lookThroughInitListExpr(expr->getArg(i))); + } + return true; + } + + bool VisitCXXConstructExpr(CXXConstructExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto const ctor = expr->getConstructor(); + unsigned const n = std::min(ctor->getNumParams(), expr->getNumArgs()); + for (unsigned i = 0; i != n; ++i) { + if (!loplugin::TypeCheck(ctor->getParamDecl(i)->getType()) + .LvalueReference().Const()) + { + continue; + } + recordConsumption(lookThroughInitListExpr(expr->getArg(i))); + } + return true; + } + + bool VisitReturnStmt(ReturnStmt const * stmt) { + if (ignoreLocation(stmt)) { + return true; + } + assert(!returnTypes_.empty()); + if (!loplugin::TypeCheck(returnTypes_.top()).LvalueReference().Const()) + { + return true; + } + auto const ret = stmt->getRetValue(); + if (ret == nullptr) { + return true; + } + recordConsumption(lookThroughInitListExpr(ret)); + return true; + } + + bool VisitVarDecl(VarDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + if (!loplugin::TypeCheck(decl->getType()).LvalueReference()) { + return true; + } + auto const init = decl->getInit(); + if (init == nullptr) { + return true; + } + recordConsumption(lookThroughInitListExpr(init)); + return true; + } + + bool VisitFieldDecl(FieldDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + if (!loplugin::TypeCheck(decl->getType()).LvalueReference()) { + return true; + } + auto const init = decl->getInClassInitializer(); + if (init == nullptr) { + return true; + } + recordConsumption(lookThroughInitListExpr(init)); + return true; + } + +private: + struct Usage { + std::vector castToVoid; + bool mentioned = false; + DeclRefExpr const * firstConsumption = nullptr; + }; + + struct Cast { + ExplicitCastExpr const * cast; + DeclRefExpr const * sub; + }; + + std::map vars_; + std::stack castToVoid_; + std::stack returnTypes_; + + void run() override { + if (compiler.getPreprocessor().getIdentifierInfo("NDEBUG")->hasMacroDefinition()) { + return; + } + if (!TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) { + return; + } + for (auto const & i: vars_) { + if (i.second.firstConsumption == nullptr) { + if (i.second.mentioned) { + continue; + } + if (isa(i.first)) { + if (!compiler.getLangOpts().CPlusPlus + || isSharedCAndCppCode(i.first)) + { + continue; + } + auto const ctxt = i.first->getDeclContext(); + if (dyn_cast_or_null(ctxt) != nullptr) { + continue; + } + auto const fun = dyn_cast_or_null(ctxt); + assert(fun != nullptr); + if (containsPreprocessingConditionalInclusion( + fun->getSourceRange())) + { + continue; + } + auto const meth = dyn_cast(fun); + report( + DiagnosticsEngine::Warning, + "unused%select{| virtual function}0 parameter name", + i.first->getLocation()) + << (meth != nullptr && meth->isVirtual()) + << i.first->getSourceRange(); + for (auto const j: i.second.castToVoid) { + report( + DiagnosticsEngine::Note, "cast to void here", + j->getExprLoc()) + << j->getSourceRange(); + } + } else if (!i.second.castToVoid.empty() + && !isWarnUnusedType(i.first->getType())) + { + auto const fun = dyn_cast_or_null(i.first->getDeclContext()); + assert(fun != nullptr); + if (containsPreprocessingConditionalInclusion(fun->getSourceRange())) { + continue; + } + report( + DiagnosticsEngine::Warning, + "unused variable %select{declaration|name}0", + i.first->getLocation()) + << i.first->isExceptionVariable() + << i.first->getSourceRange(); + for (auto const j: i.second.castToVoid) { + report( + DiagnosticsEngine::Note, "cast to void here", + j->getExprLoc()) + << j->getSourceRange(); + } + } + } else { + for (auto const j: i.second.castToVoid) { + report( + DiagnosticsEngine::Warning, "unnecessary cast to void", + j->getExprLoc()) + << j->getSourceRange(); + report( + DiagnosticsEngine::Note, "first consumption is here", + i.second.firstConsumption->getExprLoc()) + << i.second.firstConsumption->getSourceRange(); + } + } + } + } + + bool isFromCIncludeFile(SourceLocation spellingLocation) const { + return !compiler.getSourceManager().isInMainFile(spellingLocation) + && (StringRef( + compiler.getSourceManager().getPresumedLoc(spellingLocation) + .getFilename()) + .endswith(".h")); + } + + bool isSharedCAndCppCode(VarDecl const * decl) const { + auto loc = decl->getLocation(); + while (compiler.getSourceManager().isMacroArgExpansion(loc)) { + loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc); + } + // Assume that code is intended to be shared between C and C++ if it + // comes from an include file ending in .h, and is either in an extern + // "C" context or the body of a macro definition: + return + isFromCIncludeFile(compiler.getSourceManager().getSpellingLoc(loc)) + && (decl->isInExternCContext() + || compiler.getSourceManager().isMacroBodyExpansion(loc)); + } + + DeclRefExpr const * checkCast(ExplicitCastExpr const * expr) { + if (!loplugin::TypeCheck(expr->getTypeAsWritten()).Void()) { + return nullptr; + } + if (compiler.getSourceManager().isMacroBodyExpansion( + expr->getBeginLoc())) + { + return nullptr; + } + return dyn_cast(expr->getSubExpr()->IgnoreParenImpCasts()); + } + + void recordConsumption(Expr const * expr) { + for (;;) { + expr = expr->IgnoreParenImpCasts(); + if (auto const e = dyn_cast(expr)) { + expr = e->getBase(); + continue; + } + if (auto const e = dyn_cast(expr)) { + expr = e->getBase(); + continue; + } + if (auto const e = dyn_cast(expr)) { + if (e->getOpcode() == BO_PtrMemD) { + expr = e->getLHS(); + continue; + } + } + break; + } + auto const dre = dyn_cast(expr); + if (dre == nullptr) { + return; + } + // In C (but not in C++) + // + // (void) x + // + // contains an implicit lvalue-to-rvalue cast, so VisitImplicitCastExpr + // would record that as a consumption if we didn't filter it out here: + if (!castToVoid_.empty() && castToVoid_.top().sub == dre) { + return; + } + auto const var = dyn_cast(dre->getDecl()); + if (var == nullptr) { + return; + } + if (var->getType().isVolatileQualified()) { + return; + } + auto & usage = vars_[var->getCanonicalDecl()]; + if (usage.firstConsumption != nullptr) { + return; + } + auto const loc = dre->getBeginLoc(); + if (compiler.getSourceManager().isMacroArgExpansion(loc) + && (Lexer::getImmediateMacroNameForDiagnostics( + loc, compiler.getSourceManager(), compiler.getLangOpts()) + == "assert")) + { + return; + } + usage.firstConsumption = dre; + } +}; + +static loplugin::Plugin::Registration reg("casttovoid"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/changetoolsgen.cxx b/compilerplugins/clang/changetoolsgen.cxx new file mode 100644 index 000000000..f4b9b6168 --- /dev/null +++ b/compilerplugins/clang/changetoolsgen.cxx @@ -0,0 +1,376 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "plugin.hxx" +#include "check.hxx" +#include + +/** + * Changes calls to tools::Rectangle/Point/Size methods that return a ref to instead call the setter methods. + * + * run as: + * make COMPILER_PLUGIN_TOOL=changetoolsgen UPDATE_FILES=all FORCE_COMPILE=all + * or + * make COMPILER_PLUGIN_TOOL=changetoolsgen FORCE_COMPILE=all + */ + +namespace +{ +class ChangeToolsGen : public loplugin::FilteringRewritePlugin +{ +public: + explicit ChangeToolsGen(loplugin::InstantiationData const& data) + : FilteringRewritePlugin(data) + { + } + virtual void run() override; + bool VisitCXXMemberCallExpr(CXXMemberCallExpr const* call); + +private: + bool ChangeAssignment(Stmt const* parent, std::string const& methodName, + std::string const& setPrefix); + bool ChangeBinaryOperatorPlusMinus(BinaryOperator const* parent, CXXMemberCallExpr const* call, + std::string const& methodName); + bool ChangeBinaryOperatorOther(BinaryOperator const* parent, CXXMemberCallExpr const* call, + std::string const& methodName, std::string const& setPrefix); + bool ChangeUnaryOperator(UnaryOperator const* parent, CXXMemberCallExpr const* call, + std::string const& methodName); + std::string extractCode(SourceLocation startLoc, SourceLocation endLoc); +}; + +void ChangeToolsGen::run() { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + +bool ChangeToolsGen::VisitCXXMemberCallExpr(CXXMemberCallExpr const* call) +{ + if (ignoreLocation(call)) + return true; + const CXXMethodDecl* func = call->getMethodDecl(); + if (!func) + return true; + if (func->isConst()) + return true; + auto dc = loplugin::DeclCheck(func); + std::string methodName; + std::string setPrefix; + if (dc.Function("Top").Class("Rectangle").Namespace("tools").GlobalNamespace()) + { + methodName = "Top"; + setPrefix = "Set"; + } + else if (dc.Function("Bottom").Class("Rectangle").Namespace("tools").GlobalNamespace()) + { + methodName = "Bottom"; + setPrefix = "Set"; + } + else if (dc.Function("Left").Class("Rectangle").Namespace("tools").GlobalNamespace()) + { + methodName = "Left"; + setPrefix = "Set"; + } + else if (dc.Function("Right").Class("Rectangle").Namespace("tools").GlobalNamespace()) + { + methodName = "Right"; + setPrefix = "Set"; + } + else if (dc.Function("X").Class("Point").GlobalNamespace()) + { + methodName = "X"; + setPrefix = "set"; + } + else if (dc.Function("Y").Class("Point").GlobalNamespace()) + { + methodName = "Y"; + setPrefix = "set"; + } + else if (dc.Function("Width").Class("Size").GlobalNamespace()) + { + methodName = "Width"; + setPrefix = "set"; + } + else if (dc.Function("Height").Class("Size").GlobalNamespace()) + { + methodName = "Height"; + setPrefix = "set"; + } + else + return true; + if (!loplugin::TypeCheck(func->getReturnType()).LvalueReference()) + return true; + + auto parent = getParentStmt(call); + if (!parent) + return true; + if (auto unaryOp = dyn_cast(parent)) + { + if (!ChangeUnaryOperator(unaryOp, call, methodName)) + report(DiagnosticsEngine::Warning, "Could not fix, unary", call->getBeginLoc()); + return true; + } + auto binaryOp = dyn_cast(parent); + if (!binaryOp) + { + // normal getter + return true; + } + auto opcode = binaryOp->getOpcode(); + if (opcode == BO_Assign) + { + // Check for assignments embedded inside other expressions + auto parent2 = getParentStmt(parent); + if (dyn_cast_or_null(parent2)) + parent2 = getParentStmt(parent2); + if (parent2 && isa(parent2)) + { + report(DiagnosticsEngine::Warning, "Could not fix, embedded assign", + call->getBeginLoc()); + return true; + } + // Check for + // X.Width() = X.Height() = 1; + if (auto rhs = dyn_cast(binaryOp->getRHS()->IgnoreParenImpCasts())) + if (rhs->getOpcode() == BO_Assign) + { + report(DiagnosticsEngine::Warning, "Could not fix, double assign", + call->getBeginLoc()); + return true; + } + if (!ChangeAssignment(parent, methodName, setPrefix)) + report(DiagnosticsEngine::Warning, "Could not fix, assign", call->getBeginLoc()); + return true; + } + if (opcode == BO_AddAssign || opcode == BO_SubAssign) + { + if (!ChangeBinaryOperatorPlusMinus(binaryOp, call, methodName)) + report(DiagnosticsEngine::Warning, "Could not fix, assign-and-change", + call->getBeginLoc()); + return true; + } + else if (opcode == BO_RemAssign || opcode == BO_MulAssign || opcode == BO_DivAssign) + { + if (!ChangeBinaryOperatorOther(binaryOp, call, methodName, setPrefix)) + report(DiagnosticsEngine::Warning, "Could not fix, assign-and-change", + call->getBeginLoc()); + return true; + } + else + assert(false); + return true; +} + +bool ChangeToolsGen::ChangeAssignment(Stmt const* parent, std::string const& methodName, + std::string const& setPrefix) +{ + // Look for expressions like + // aRect.Left() = ...; + // and replace with + // aRect.SetLeft( ... ); + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = SM.getExpansionLoc(parent->getBeginLoc()); + SourceLocation endLoc = SM.getExpansionLoc(parent->getEndLoc()); + const char* p1 = SM.getCharacterData(startLoc); + const char* p2 = SM.getCharacterData(endLoc); + unsigned n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts()); + if (p2 < p1) // clang is misbehaving, appears to be macro constant related + return false; + std::string callText(p1, p2 - p1 + n); + auto originalLength = callText.size(); + + auto newText = std::regex_replace(callText, std::regex(methodName + " *\\( *\\) *="), + setPrefix + methodName + "("); + if (newText == callText) + return false; + newText += " )"; + + return replaceText(startLoc, originalLength, newText); +} + +bool ChangeToolsGen::ChangeBinaryOperatorPlusMinus(BinaryOperator const* binaryOp, + CXXMemberCallExpr const* call, + std::string const& methodName) +{ + // Look for expressions like + // aRect.Left() += ...; + // and replace with + // aRect.MoveLeft( ... ); + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = SM.getExpansionLoc(binaryOp->getBeginLoc()); + SourceLocation endLoc = SM.getExpansionLoc(binaryOp->getEndLoc()); + const char* p1 = SM.getCharacterData(startLoc); + const char* p2 = SM.getCharacterData(endLoc); + if (p2 < p1) // clang is misbehaving, appears to be macro constant related + return false; + unsigned n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts()); + std::string callText(p1, p2 - p1 + n); + auto originalLength = callText.size(); + + std::string newText; + if (binaryOp->getOpcode() == BO_AddAssign) + { + newText = std::regex_replace(callText, std::regex(methodName + " *\\( *\\) *\\+= *"), + "Adjust" + methodName + "("); + newText += " )"; + } + else + { + newText = std::regex_replace(callText, std::regex(methodName + " *\\( *\\) *\\-= *"), + "Adjust" + methodName + "( -("); + newText += ") )"; + } + + if (newText == callText) + { + report(DiagnosticsEngine::Warning, "binaryop-plusminus regex match failed", + call->getBeginLoc()); + return false; + } + + return replaceText(startLoc, originalLength, newText); +} + +bool ChangeToolsGen::ChangeBinaryOperatorOther(BinaryOperator const* binaryOp, + CXXMemberCallExpr const* call, + std::string const& methodName, + std::string const& setPrefix) +{ + // Look for expressions like + // aRect.Left() += ...; + // and replace with + // aRect.SetLeft( aRect.GetLeft() + ... ); + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = SM.getExpansionLoc(binaryOp->getBeginLoc()); + SourceLocation endLoc = SM.getExpansionLoc(binaryOp->getEndLoc()); + const char* p1 = SM.getCharacterData(startLoc); + const char* p2 = SM.getCharacterData(endLoc); + if (p2 < p1) // clang is misbehaving, appears to be macro constant related + return false; + unsigned n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts()); + std::string callText(p1, p2 - p1 + n); + auto originalLength = callText.size(); + + std::string regexOpname; + std::string replaceOpname; + switch (binaryOp->getOpcode()) + { + case BO_RemAssign: + regexOpname = "\\%="; + replaceOpname = "%"; + break; + case BO_MulAssign: + regexOpname = "\\*="; + replaceOpname = "*"; + break; + case BO_DivAssign: + regexOpname = "\\/="; + replaceOpname = "/"; + break; + default: + assert(false); + } + + auto implicitObjectText = extractCode(call->getImplicitObjectArgument()->getExprLoc(), + call->getImplicitObjectArgument()->getExprLoc()); + std::string reString(methodName + " *\\( *\\) *" + regexOpname); + auto newText = std::regex_replace(callText, std::regex(reString), + setPrefix + methodName + "( " + implicitObjectText + "." + + methodName + "() " + replaceOpname + " ("); + if (newText == callText) + { + report(DiagnosticsEngine::Warning, "binaryop-other regex match failed %0", + call->getBeginLoc()) + << reString; + return false; + } + // sometimes we end up with duplicate spaces after the opname + newText + = std::regex_replace(newText, std::regex(methodName + "\\(\\) \\" + replaceOpname + " "), + methodName + "() " + replaceOpname + " "); + newText += ") )"; + + return replaceText(startLoc, originalLength, newText); +} + +bool ChangeToolsGen::ChangeUnaryOperator(UnaryOperator const* unaryOp, + CXXMemberCallExpr const* call, + std::string const& methodName) +{ + // Look for expressions like + // aRect.Left()++; + // ++aRect.Left(); + // and replace with + // aRect.MoveLeft( 1 ); + + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = SM.getExpansionLoc(unaryOp->getBeginLoc()); + SourceLocation endLoc = SM.getExpansionLoc(unaryOp->getEndLoc()); + const char* p1 = SM.getCharacterData(startLoc); + const char* p2 = SM.getCharacterData(endLoc); + if (p2 < p1) // clang is misbehaving, appears to be macro constant related + return false; + unsigned n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts()); + std::string callText(p1, p2 - p1 + n); + auto originalLength = callText.size(); + + auto implicitObjectText = extractCode(call->getImplicitObjectArgument()->getExprLoc(), + call->getImplicitObjectArgument()->getExprLoc()); + auto op = unaryOp->getOpcode(); + std::string regexOpname; + std::string replaceOp; + switch (op) + { + case UO_PostInc: + case UO_PreInc: + replaceOp = "1"; + regexOpname = "\\+\\+"; + break; + case UO_PostDec: + case UO_PreDec: + replaceOp = "-1"; + regexOpname = "\\-\\-"; + break; + default: + assert(false); + } + std::string newText; + std::string reString; + if (op == UO_PostInc || op == UO_PostDec) + { + reString = methodName + " *\\( *\\) *" + regexOpname; + newText = std::regex_replace(callText, std::regex(reString), + "Adjust" + methodName + "( " + replaceOp); + } + else + { + newText = implicitObjectText + "." + "Adjust" + methodName + "( " + replaceOp; + } + if (newText == callText) + { + report(DiagnosticsEngine::Warning, "unaryop regex match failed %0", call->getBeginLoc()) + << reString; + return false; + } + newText += " )"; + return replaceText(startLoc, originalLength, newText); +} + +std::string ChangeToolsGen::extractCode(SourceLocation startLoc, SourceLocation endLoc) +{ + SourceManager& SM = compiler.getSourceManager(); + const char* p1 = SM.getCharacterData(SM.getExpansionLoc(startLoc)); + const char* p2 = SM.getCharacterData(SM.getExpansionLoc(endLoc)); + unsigned n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts()); + return std::string(p1, p2 - p1 + n); +} + +static loplugin::Plugin::Registration X("changetoolsgen", false); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/charrightshift.cxx b/compilerplugins/clang/charrightshift.cxx new file mode 100644 index 000000000..4168826ae --- /dev/null +++ b/compilerplugins/clang/charrightshift.cxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "plugin.hxx" + +namespace { + +class CharRightShift: + public loplugin::FilteringPlugin +{ +public: + explicit CharRightShift(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitBinaryOperator(BinaryOperator const * expr) { + if (expr->getOpcode() != BO_Shr) { + return true; + } + if (ignoreLocation(expr)) { + return true; + } + auto t = expr->getLHS()->IgnoreParenImpCasts()->getType(); + if (!loplugin::TypeCheck(t).Char()) { + return true; + } + if (!expr->getRHS()->getType()->isBuiltinType()) { + //TODO: in which case the expression should be an + // CXXOperatorCallExpr instead of a BinaryOperator? but at least + // recent Clang trunk reports + // + // '(' >> orExpression + // + // (connectivity/source/commontools/RowFunctionParser.cxx, the RHS + // being of type boost::spirit::rule) here + return true; + } + report( + DiagnosticsEngine::Warning, + ("right shift of %0 is implementation-defined when 'char' is signed" + " and value is negative"), + expr->getLHS()->getExprLoc()) + << t << expr->getSourceRange(); + return true; + } +}; + +loplugin::Plugin::Registration charrightshift("charrightshift"); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/check.cxx b/compilerplugins/clang/check.cxx new file mode 100644 index 000000000..93fd7c7f7 --- /dev/null +++ b/compilerplugins/clang/check.cxx @@ -0,0 +1,389 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include + +#include "check.hxx" + +namespace loplugin { + +TypeCheck TypeCheck::NonConst() const { + return !type_.isNull() && !type_.isConstQualified() + ? *this : TypeCheck(); + // returning TypeCheck(type_.getUnqualifiedType()) instead of *this + // may look tempting, but could remove sugar we might be interested in + // checking for +} + +TypeCheck TypeCheck::NonConstVolatile() const { + return + (!type_.isNull() && !type_.isConstQualified() + && !type_.isVolatileQualified()) + ? *this : TypeCheck(); + // returning TypeCheck(type_.getUnqualifiedType()) instead of *this + // may look tempting, but could remove sugar we might be interested in + // checking for +} + +TypeCheck TypeCheck::Const() const { + return + (!type_.isNull() && type_.isConstQualified() + && !type_.isVolatileQualified()) + ? *this : TypeCheck(); + // returning TypeCheck(type_.getUnqualifiedType()) instead of *this + // may look tempting, but could remove sugar we might be interested in + // checking for +} + +TypeCheck TypeCheck::Volatile() const { + return + (!type_.isNull() && !type_.isConstQualified() + && type_.isVolatileQualified()) + ? *this : TypeCheck(); + // returning TypeCheck(type_.getUnqualifiedType()) instead of *this + // may look tempting, but could remove sugar we might be interested in + // checking for +} + +TypeCheck TypeCheck::ConstVolatile() const { + return + (!type_.isNull() && type_.isConstQualified() + && type_.isVolatileQualified()) + ? *this : TypeCheck(); + // returning TypeCheck(type_.getUnqualifiedType()) instead of *this + // may look tempting, but could remove sugar we might be interested in + // checking for +} + +TypeCheck TypeCheck::ConstNonVolatile() const { + return + (!type_.isNull() && type_.isConstQualified() + && !type_.isVolatileQualified()) + ? *this : TypeCheck(); + // returning TypeCheck(type_.getUnqualifiedType()) instead of *this + // may look tempting, but could remove sugar we might be interested in + // checking for +} + +TerminalCheck TypeCheck::Void() const { + return TerminalCheck( + !type_.isNull() + && type_->isSpecificBuiltinType(clang::BuiltinType::Void)); +} + +TerminalCheck TypeCheck::Char() const { + return TerminalCheck( + !type_.isNull() + && (type_->isSpecificBuiltinType(clang::BuiltinType::Char_S) + || type_->isSpecificBuiltinType(clang::BuiltinType::Char_U))); +} + +TerminalCheck TypeCheck::AnyBoolean() const { + if (type_->isBooleanType()) { + return TerminalCheck(true); + } + auto t = type_->getAs(); + if (t == nullptr) { + return TerminalCheck(false); + } + auto n =t->getDecl()->getName(); + return TerminalCheck( + n == "sal_Bool" || n == "BOOL" || n == "Boolean" || n == "FT_Bool" + || n == "FcBool" || n == "GLboolean" || n == "NPBool" || n == "TW_BOOL" + || n == "UBool" || n == "boolean" || n == "dbus_bool_t" + || n == "gboolean" || n == "hb_bool_t" || n == "jboolean" || n == "my_bool"); +} + +TypeCheck TypeCheck::LvalueReference() const { + if (!type_.isNull()) { + auto const t = type_->getAs(); + if (t != nullptr) { + return TypeCheck(t->getPointeeType()); + } + } + return TypeCheck(); +} + +TypeCheck TypeCheck::RvalueReference() const { + if (!type_.isNull()) { + auto const t = type_->getAs(); + if (t != nullptr) { + return TypeCheck(t->getPointeeType()); + } + } + return TypeCheck(); +} + +TypeCheck TypeCheck::Pointer() const { + if (!type_.isNull()) { + auto const t = type_->getAs(); + if (t != nullptr) { + return TypeCheck(t->getPointeeType()); + } + } + return TypeCheck(); +} + +TerminalCheck TypeCheck::Enum() const { + if (!type_.isNull()) { + auto const t = type_->getAs(); + if (t != nullptr) { + return TerminalCheck(true); + } + } + return TerminalCheck(false); +} + +TypeCheck TypeCheck::Typedef() const { + if (!type_.isNull()) { + if (auto const t = type_->getAs()) { + return TypeCheck(t->desugar()); + } + } + return TypeCheck(); +} + +DeclCheck TypeCheck::TemplateSpecializationClass() const { + if (!type_.isNull()) { + if (auto const t = type_->getAs()) { + if (!t->isTypeAlias()) { + if (auto const d = llvm::dyn_cast_or_null( + t->getTemplateName().getAsTemplateDecl())) + { + return DeclCheck(d->getTemplatedDecl()); + } + } + } + } + return DeclCheck(); +} + +TypeCheck TypeCheck::NotSubstTemplateTypeParmType() const { + return + (!type_.isNull() + && type_->getAs() == nullptr) + ? *this : TypeCheck(); +} + +ContextCheck DeclCheck::Operator(clang::OverloadedOperatorKind op) const { + assert(op != clang::OO_None); + auto f = llvm::dyn_cast_or_null(decl_); + return ContextCheck( + f != nullptr && f->getOverloadedOperator() == op + ? f->getDeclContext() : nullptr); +} + +ContextCheck DeclCheck::MemberFunction() const { + auto m = llvm::dyn_cast_or_null(decl_); + return ContextCheck(m == nullptr ? nullptr : m->getParent()); +} + +namespace { + +bool isGlobalNamespace(clang::DeclContext const * context) { + assert(context != nullptr); + return context->getEnclosingNamespaceContext()->isTranslationUnit(); +} + +} + +TerminalCheck ContextCheck::GlobalNamespace() const { + return TerminalCheck(context_ != nullptr && isGlobalNamespace(context_)); +} + +TerminalCheck ContextCheck::StdNamespace() const { + return TerminalCheck( + context_ != nullptr && context_->isStdNamespace()); +} + +namespace { + +bool isStdOrNestedNamespace(clang::DeclContext const * context) { + assert(context != nullptr); + if (!context->isNamespace()) { + return false; + } + if (isGlobalNamespace(context)) { + return false; + } + if (context->isStdNamespace()) { + return true; + } + return isStdOrNestedNamespace(context->getParent()); +} + +} + +TerminalCheck ContextCheck::StdOrNestedNamespace() const { + return TerminalCheck(context_ != nullptr && isStdOrNestedNamespace(context_)); +} + +ContextCheck ContextCheck::AnonymousNamespace() const { + auto n = llvm::dyn_cast_or_null(context_); + return ContextCheck( + n != nullptr && n->isAnonymousNamespace() ? n->getParent() : nullptr); +} + +namespace { + +bool BaseCheckNotSomethingInterestingSubclass(const clang::CXXRecordDecl *BaseDefinition) { + if (BaseDefinition) { + auto tc = TypeCheck(BaseDefinition); + if (tc.Class("Dialog").GlobalNamespace() || tc.Class("SfxPoolItem").GlobalNamespace()) { + return false; + } + } + return true; +} + +bool isDerivedFromSomethingInteresting(const clang::CXXRecordDecl *decl) { + if (!decl) + return false; + auto tc = TypeCheck(decl); + if (tc.Class("Dialog")) + return true; + if (tc.Class("SfxPoolItem")) + return true; + if (!decl->hasDefinition()) { + return false; + } + if (// not sure what hasAnyDependentBases() does, + // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1 + !decl->hasAnyDependentBases() && + !decl->forallBases(BaseCheckNotSomethingInterestingSubclass)) { + return true; + } + return false; +} + +} + +bool isExtraWarnUnusedType(clang::QualType type) { + auto const rec = type->getAsCXXRecordDecl(); + if (rec == nullptr) { + return false; + } + auto const tc = TypeCheck(rec); + // Check some common non-LO types: + if (tc.Class("basic_string").StdNamespace() + || tc.Class("deque").StdNamespace() + || tc.Class("list").StdNamespace() + || tc.Class("map").StdNamespace() + || tc.Class("pair").StdNamespace() + || tc.Class("queue").StdNamespace() + || tc.Class("set").StdNamespace() + || tc.Class("stack").StdNamespace() + || tc.Class("unordered_map").StdNamespace() + || tc.Class("unordered_set").StdNamespace() + || tc.Class("vector").StdNamespace()) + { + return true; + } + return isDerivedFromSomethingInteresting(rec); +} + +namespace { + +// Make sure Foo and ::Foo are considered equal: +bool areSameSugaredType(clang::QualType type1, clang::QualType type2) { + auto t1 = type1.getLocalUnqualifiedType(); + if (auto const et = llvm::dyn_cast(t1)) { + t1 = et->getNamedType(); + } + auto t2 = type2.getLocalUnqualifiedType(); + if (auto const et = llvm::dyn_cast(t2)) { + t2 = et->getNamedType(); + } + return t1 == t2; +} + +bool isArithmeticOp(clang::Expr const * expr) { + expr = expr->IgnoreParenImpCasts(); + if (auto const e = llvm::dyn_cast(expr)) { + switch (e->getOpcode()) { + case clang::BO_Mul: + case clang::BO_Div: + case clang::BO_Rem: + case clang::BO_Add: + case clang::BO_Sub: + case clang::BO_Shl: + case clang::BO_Shr: + case clang::BO_And: + case clang::BO_Xor: + case clang::BO_Or: + return true; + case clang::BO_Comma: + return isArithmeticOp(e->getRHS()); + default: + return false; + } + } + return llvm::isa(expr) + || llvm::isa(expr); +} + +} + +bool isOkToRemoveArithmeticCast( + clang::ASTContext & context, clang::QualType t1, clang::QualType t2, const clang::Expr* subExpr) +{ + // Don't warn if the types are arithmetic (in the C++ meaning), and: either + // at least one is a typedef or decltype (and if both are, they're different), + // or the sub-expression involves some operation that is likely to change + // types through promotion, or the sub-expression is an integer literal (so + // its type generally depends on its value and suffix if any---even with a + // suffix like L it could still be either long or long long): + if ((t1->isIntegralType(context) + || t1->isRealFloatingType()) + && ((!areSameSugaredType(t1, t2) + && (loplugin::TypeCheck(t1).Typedef() + || loplugin::TypeCheck(t2).Typedef() + || llvm::isa(t1) || llvm::isa(t2))) + || isArithmeticOp(subExpr) + || llvm::isa(subExpr->IgnoreParenImpCasts()))) + { + return false; + } + return true; +} + + +static bool BaseCheckNotSubclass(const clang::CXXRecordDecl *BaseDefinition, void *p) { + if (!BaseDefinition) + return true; + auto const & base = *static_cast(p); + if (base(BaseDefinition)) { + return false; + } + return true; +} + +bool isDerivedFrom(const clang::CXXRecordDecl *decl, DeclChecker base) { + if (!decl) + return false; + if (base(decl)) + return true; + if (!decl->hasDefinition()) { + return false; + } + if (!decl->forallBases( + [&base](const clang::CXXRecordDecl *BaseDefinition) -> bool + { return BaseCheckNotSubclass(BaseDefinition, &base); })) + { + return true; + } + return false; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/check.hxx b/compilerplugins/clang/check.hxx new file mode 100644 index 000000000..9c35acff7 --- /dev/null +++ b/compilerplugins/clang/check.hxx @@ -0,0 +1,311 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include +#include +#include + +namespace loplugin { + +class ContextCheck; +class TerminalCheck; + +namespace detail { + +inline ContextCheck checkRecordDecl( + clang::Decl const * decl, clang::TagTypeKind tag, llvm::StringRef id); + +} + +class DeclCheck; + +class TypeCheck { +public: + explicit TypeCheck(clang::QualType type): type_(type) {} + + explicit TypeCheck(clang::Type const * type): type_(type, 0) {} + + explicit TypeCheck(clang::TypeDecl const * decl): type_(decl->getTypeForDecl(), 0) {} + + explicit operator bool() const { return !type_.isNull(); } + + TypeCheck NonConst() const; + + TypeCheck NonConstVolatile() const; + + TypeCheck Const() const; + + TypeCheck Volatile() const; + + TypeCheck ConstVolatile() const; + + TypeCheck ConstNonVolatile() const; + + TerminalCheck Void() const; + + TerminalCheck Char() const; + + TerminalCheck AnyBoolean() const; + + TypeCheck Pointer() const; + + TerminalCheck Enum() const; + + TypeCheck LvalueReference() const; + + TypeCheck RvalueReference() const; + + inline ContextCheck Class(llvm::StringRef id) const; + + inline ContextCheck Struct(llvm::StringRef id) const; + + inline ContextCheck ClassOrStruct(llvm::StringRef id) const; + + TypeCheck Typedef() const; + + inline ContextCheck Typedef(llvm::StringRef id) const; + + DeclCheck TemplateSpecializationClass() const; + + TypeCheck NotSubstTemplateTypeParmType() const; + +private: + TypeCheck() = default; + + clang::QualType const type_{}; +}; + +class DeclCheck { + friend TypeCheck; + +public: + explicit DeclCheck(clang::Decl const * decl): decl_(decl) {} + + explicit operator bool() const { return decl_ != nullptr; } + + inline ContextCheck Class(llvm::StringRef id) const; + + inline ContextCheck Struct(llvm::StringRef id) const; + + inline ContextCheck ClassOrStruct(llvm::StringRef id) const; + + inline ContextCheck Union(llvm::StringRef id) const; + + inline ContextCheck Function(llvm::StringRef id) const; + + ContextCheck Operator(clang::OverloadedOperatorKind op) const; + + inline ContextCheck Var(llvm::StringRef id) const; + + ContextCheck MemberFunction() const; + +private: + DeclCheck() = default; + + clang::Decl const * const decl_ = nullptr; +}; + +class ContextCheck { +public: + explicit ContextCheck(clang::DeclContext const * context = nullptr): + context_(context) {} + + explicit operator bool() const { return context_ != nullptr; } + + TerminalCheck GlobalNamespace() const; + + inline ContextCheck Namespace(llvm::StringRef id) const; + + TerminalCheck StdNamespace() const; + + TerminalCheck StdOrNestedNamespace() const; + + ContextCheck AnonymousNamespace() const; + + inline ContextCheck Class(llvm::StringRef id) const; + + inline ContextCheck Struct(llvm::StringRef id) const; + + explicit ContextCheck(const clang::NamespaceDecl * decl ) : context_( decl ) {} + +private: + clang::DeclContext const * const context_; +}; + +class TerminalCheck { +public: + explicit operator bool() const { return satisfied_; } + +private: + friend ContextCheck; + friend TypeCheck; + + explicit TerminalCheck(bool satisfied): satisfied_(satisfied) {} + + bool const satisfied_; +}; + + +typedef std::function DeclChecker; +// Returns true if the class has a base matching the checker, or if the class itself matches. +bool isDerivedFrom(const clang::CXXRecordDecl *decl, DeclChecker base); + + +namespace detail { + +ContextCheck checkRecordDecl( + clang::Decl const * decl, clang::TagTypeKind tag, llvm::StringRef id) +{ + auto r = llvm::dyn_cast_or_null(decl); + if (r != nullptr && r->getTagKind() == tag) { + auto const i = r->getIdentifier(); + if (i != nullptr && i->getName() == id) { + return ContextCheck(r->getDeclContext()); + } + } + return ContextCheck(); +} + +} + +ContextCheck TypeCheck::Class(llvm::StringRef id) + const +{ + if (!type_.isNull()) { + auto const t = type_->getAs(); + if (t != nullptr) { + return detail::checkRecordDecl(t->getDecl(), clang::TTK_Class, id); + } + } + return ContextCheck(); +} + +ContextCheck TypeCheck::Struct(llvm::StringRef id) const +{ + if (!type_.isNull()) { + auto const t = type_->getAs(); + if (t != nullptr) { + return detail::checkRecordDecl(t->getDecl(), clang::TTK_Struct, id); + } + } + return ContextCheck(); +} + +ContextCheck TypeCheck::ClassOrStruct(llvm::StringRef id) const +{ + auto const c1 = Class(id); + if (c1) { + return c1; + } + return Struct(id); +} + +ContextCheck TypeCheck::Typedef(llvm::StringRef id) const +{ + if (!type_.isNull()) { + if (auto const t = type_->getAs()) { + auto const d = t->getDecl(); + auto const i = d->getIdentifier(); + assert(i != nullptr); + if (i->getName() == id) { + return ContextCheck(d->getDeclContext()); + } + } + } + return ContextCheck(); +} + +ContextCheck DeclCheck::Class(llvm::StringRef id) const +{ + return detail::checkRecordDecl(decl_, clang::TTK_Class, id); +} + +ContextCheck DeclCheck::Struct(llvm::StringRef id) const +{ + return detail::checkRecordDecl(decl_, clang::TTK_Struct, id); +} + +ContextCheck DeclCheck::ClassOrStruct(llvm::StringRef id) const +{ + auto const c1 = Class(id); + if (c1) { + return c1; + } + return Struct(id); +} + +ContextCheck DeclCheck::Union(llvm::StringRef id) const +{ + return detail::checkRecordDecl(decl_, clang::TTK_Union, id); +} + +ContextCheck DeclCheck::Function(llvm::StringRef id) const +{ + auto f = llvm::dyn_cast_or_null(decl_); + if (f != nullptr) { + auto const i = f->getIdentifier(); + if (i != nullptr && i->getName() == id) { + return ContextCheck(f->getDeclContext()); + } + } + return ContextCheck(); +} + +ContextCheck DeclCheck::Var(llvm::StringRef id) const +{ + auto f = llvm::dyn_cast_or_null(decl_); + if (f != nullptr) { + auto const i = f->getIdentifier(); + if (i != nullptr && i->getName() == id) { + return ContextCheck(f->getDeclContext()); + } + } + return ContextCheck(); +} + +ContextCheck ContextCheck::Namespace(llvm::StringRef id) const +{ + if (context_) { + auto n = llvm::dyn_cast(context_); + if (n != nullptr) { + auto const i = n->getIdentifier(); + if (i != nullptr && i->getName() == id) { + return ContextCheck(n->getParent()); + } + } + } + return ContextCheck(); +} + +ContextCheck ContextCheck::Class(llvm::StringRef id) const +{ + return detail::checkRecordDecl( + llvm::dyn_cast_or_null(context_), clang::TTK_Class, id); +} + +ContextCheck ContextCheck::Struct(llvm::StringRef id) const +{ + return detail::checkRecordDecl( + llvm::dyn_cast_or_null(context_), clang::TTK_Struct, id); +} + +bool isExtraWarnUnusedType(clang::QualType type); + +bool isOkToRemoveArithmeticCast( + clang::ASTContext & context, clang::QualType t1, clang::QualType t2, + const clang::Expr* subExpr); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/checkconfigmacros.cxx b/compilerplugins/clang/checkconfigmacros.cxx new file mode 100644 index 000000000..aea60ed56 --- /dev/null +++ b/compilerplugins/clang/checkconfigmacros.cxx @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include +#include + +#include "plugin.hxx" + +#include "config_clang.h" + +#include + +namespace loplugin +{ + +/* +This is a compile check. + +Feature macros from config_XXX.h headers are always #defined (to 1 or 0 in case of yes/no +settings). It is a mistake to use #ifdef/#ifndef/defined to check them. + +Using 1/0 instead of defined/undefined avoids undetected problems when e.g. the necessary +#include of the config_XXX.h file is missing. +*/ + +class CheckConfigMacros + : public PPCallbacks + , public Plugin + { + public: + explicit CheckConfigMacros( const InstantiationData& data ); + virtual void run() override; + virtual void MacroDefined( const Token& macroToken, const MacroDirective* info ) override; + virtual void MacroUndefined( const Token& macroToken, MacroDefinition const &, MacroDirective const * ) override; + virtual void Ifdef( SourceLocation location, const Token& macroToken, MacroDefinition const & ) override; + virtual void Ifndef( SourceLocation location, const Token& macroToken, MacroDefinition const & ) override; + virtual void Defined( const Token& macroToken, MacroDefinition const &, SourceRange Range ) override; + enum { isPPCallback = true }; + private: + void checkMacro( const Token& macroToken, SourceLocation location ); + std::set< std::string > configMacros; + }; + +CheckConfigMacros::CheckConfigMacros( const InstantiationData& data ) + : Plugin( data ) + { + compiler.getPreprocessor().addPPCallbacks(std::unique_ptr(this)); + } + +void CheckConfigMacros::run() + { + // nothing, only check preprocessor usage + } + +void CheckConfigMacros::MacroDefined( const Token& macroToken, const MacroDirective* info ) + { + SourceLocation location = info->getLocation(); + const char* filename = compiler.getSourceManager().getPresumedLoc( location ).getFilename(); + if( filename != NULL + && ( hasPathnamePrefix(filename, BUILDDIR "/config_host/") + || hasPathnamePrefix(filename, BUILDDIR "/config_build/") )) + { +// fprintf(stderr,"DEF: %s %s\n", macroToken.getIdentifierInfo()->getName().data(), filename ); + StringRef macro = macroToken.getIdentifierInfo()->getName(); + // Skia #defines do not have values, but we set them in config_skia.h . + if( macro.startswith( "SK_" ) && loplugin::isSamePathname(filename, BUILDDIR "/config_host/config_skia.h")) + return; + configMacros.insert( macro.str()); + } + } + +void CheckConfigMacros::MacroUndefined( const Token& macroToken, MacroDefinition const &, MacroDirective const * ) + { + configMacros.erase( macroToken.getIdentifierInfo()->getName().str()); + } + +void CheckConfigMacros::Ifdef( SourceLocation location, const Token& macroToken, MacroDefinition const & ) + { + checkMacro( macroToken, location ); + } + +void CheckConfigMacros::Ifndef( SourceLocation location, const Token& macroToken, MacroDefinition const & ) + { + checkMacro( macroToken, location ); + } + +void CheckConfigMacros::Defined( const Token& macroToken, MacroDefinition const &, SourceRange ) + { + checkMacro( macroToken, macroToken.getLocation()); + } + +void CheckConfigMacros::checkMacro( const Token& macroToken, SourceLocation location ) + { + if( configMacros.find( macroToken.getIdentifierInfo()->getName().str()) != configMacros.end()) + { + const char* filename = compiler.getSourceManager().getPresumedLoc( location ).getFilename(); + if( filename == NULL + || ( !hasPathnamePrefix(filename, SRCDIR "/include/LibreOfficeKit/") + && !hasPathnamePrefix(filename, WORKDIR "/UnpackedTarball/" ))) + { + report( DiagnosticsEngine::Error, "checking whether a config macro %0 is defined", + location ) << macroToken.getIdentifierInfo()->getName(); + report( DiagnosticsEngine::Note, "use #if instead of #ifdef/#ifndef/defined", location ); + } + } + } + +static Plugin::Registration< CheckConfigMacros > X( "checkconfigmacros" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/checkunusedparams.cxx b/compilerplugins/clang/checkunusedparams.cxx new file mode 100644 index 000000000..2f4504963 --- /dev/null +++ b/compilerplugins/clang/checkunusedparams.cxx @@ -0,0 +1,502 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#include "config_clang.h" + +#include "plugin.hxx" + +/** +Find parameters that have no name, i.e. they are unused and we're worked around the "unused parameter" warning. + +Most of these can be removed. + +TODO look for places where we are working around the warning by doing + (void) param1; + */ +namespace { + +class CheckUnusedParams: public loplugin::FilteringPlugin { +public: + explicit CheckUnusedParams(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + void run() override; + bool VisitFunctionDecl(FunctionDecl const *); + bool VisitUnaryOperator(UnaryOperator const *); + bool VisitInitListExpr(InitListExpr const *); + bool VisitCallExpr(CallExpr const *); + bool VisitBinaryOperator(BinaryOperator const *); + bool VisitCXXConstructExpr(CXXConstructExpr const *); +private: + void checkForFunctionDecl(Expr const *, bool bCheckOnly = false); + std::set m_addressOfSet; + enum class PluginPhase { FindAddressOf, Warning }; + PluginPhase m_phase; +}; + +void CheckUnusedParams::run() +{ + StringRef fn(handler.getMainFileName()); + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/")) + return; + // Taking pointer to function + if (loplugin::isSamePathname(fn, SRCDIR "/l10ntools/source/xmlparse.cxx")) + return; + // macro magic which declares something needed by an external library + if (loplugin::isSamePathname(fn, SRCDIR "/svl/source/misc/gridprinter.cxx")) + return; + + // valid test/qa code + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/compilerplugins/clang/test/")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/cppu/qa/test_reference.cxx")) + return; + + // leave this alone for now + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/libreofficekit/")) + return; + // this has a certain pattern to its code which appears to include lots of unused params + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/xmloff/")) + return; + // I believe someone is busy working on this chunk of code + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/docshell/dataprovider.cxx")) + return; + // I think erack is working on stuff here + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/excel/xiformula.cxx")) + return; + // lots of callbacks here + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/lotus/op.cxx")) + return; + // template magic + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/html/htmlpars.cxx")) + return; + + m_phase = PluginPhase::FindAddressOf; + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + m_phase = PluginPhase::Warning; + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); +} + +bool CheckUnusedParams::VisitUnaryOperator(UnaryOperator const * op) { + if (op->getOpcode() != UO_AddrOf) { + return true; + } + if (m_phase != PluginPhase::FindAddressOf) + return true; + checkForFunctionDecl(op->getSubExpr()); + return true; +} + +bool CheckUnusedParams::VisitBinaryOperator(BinaryOperator const * binaryOperator) { + if (binaryOperator->getOpcode() != BO_Assign) { + return true; + } + if (m_phase != PluginPhase::FindAddressOf) + return true; + checkForFunctionDecl(binaryOperator->getRHS()); + return true; +} + +bool CheckUnusedParams::VisitCallExpr(CallExpr const * callExpr) { + if (m_phase != PluginPhase::FindAddressOf) + return true; + for (auto arg : callExpr->arguments()) + checkForFunctionDecl(arg); + return true; +} + +bool CheckUnusedParams::VisitCXXConstructExpr(CXXConstructExpr const * constructExpr) { + if (m_phase != PluginPhase::FindAddressOf) + return true; + for (auto arg : constructExpr->arguments()) + checkForFunctionDecl(arg); + return true; +} + +bool CheckUnusedParams::VisitInitListExpr(InitListExpr const * initListExpr) { + if (m_phase != PluginPhase::FindAddressOf) + return true; + for (auto subStmt : *initListExpr) + checkForFunctionDecl(dyn_cast(subStmt)); + return true; +} + +void CheckUnusedParams::checkForFunctionDecl(Expr const * expr, bool bCheckOnly) { + auto e1 = expr->IgnoreParenCasts(); + auto declRef = dyn_cast(e1); + if (!declRef) + return; + auto functionDecl = dyn_cast(declRef->getDecl()); + if (!functionDecl) + return; + if (bCheckOnly) + getParentStmt(expr)->dump(); + else + m_addressOfSet.insert(functionDecl->getCanonicalDecl()); +} + +static int noFieldsInRecord(RecordType const * recordType) { + auto recordDecl = recordType->getDecl(); + // if it's complicated, lets just assume it has fields + if (isa(recordDecl)) + return 1; + return std::distance(recordDecl->field_begin(), recordDecl->field_end()); +} +static bool startswith(const std::string& rStr, const char* pSubStr) { + return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; +} +static bool endswith(const std::string& rStr, const char* pSubStr) { + auto len = strlen(pSubStr); + if (len > rStr.size()) + return false; + return rStr.compare(rStr.size() - len, rStr.size(), pSubStr) == 0; +} + +bool CheckUnusedParams::VisitFunctionDecl(FunctionDecl const * decl) { + if (m_phase != PluginPhase::Warning) + return true; + if (m_addressOfSet.find(decl->getCanonicalDecl()) != m_addressOfSet.end()) + return true; + if (ignoreLocation(decl)) + return true; + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(decl->getLocation()))) + return true; + + auto cxxMethodDecl = dyn_cast(decl); + if (cxxMethodDecl) { + if (cxxMethodDecl->isVirtual()) + return true; + auto cxxConstructorDecl = dyn_cast(cxxMethodDecl); + if (cxxConstructorDecl && cxxConstructorDecl->isCopyOrMoveConstructor()) + return true; + } + if (!decl->isThisDeclarationADefinition()) + return true; + if (decl->isFunctionTemplateSpecialization()) + return true; + if (decl->isDeleted()) + return true; + if (decl->getTemplatedKind() != clang::FunctionDecl::TK_NonTemplate) + return true; + if (decl->isOverloadedOperator()) + return true; + if (decl->isExternC()) + return true; + + //TODO, filtering out any functions relating to class templates for now: + CXXRecordDecl const * r = dyn_cast(decl->getDeclContext()); + if (r != nullptr + && (r->getTemplateSpecializationKind() != TSK_Undeclared + || r->isDependentContext())) + { + return true; + } + FunctionDecl const * canon = decl->getCanonicalDecl(); + std::string fqn = canon->getQualifiedNameAsString(); // because sometimes clang returns nonsense for the filename of canon + if (ignoreLocation(canon)) + return true; + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(canon->getLocation()))) + return true; + StringRef fn = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(canon->getBeginLoc())); + // Some backwards compat magic. + // TODO Can probably be removed, but need to do some checking + if (loplugin::isSamePathname(fn, SRCDIR "/include/sax/fshelper.hxx")) + return true; + // Platform-specific code + if (loplugin::isSamePathname(fn, SRCDIR "/include/svl/svdde.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/include/vcl/svmain.hxx")) + return true; + // passing pointer to function + if (loplugin::isSamePathname(fn, SRCDIR "/include/vcl/BitmapReadAccess.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/inc/unx/gtk/gtkobject.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/inc/unx/gtk/gtksalframe.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/inc/unx/gtk/gtkframe.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/extensions/source/propctrlr/propertyeditor.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/solar/inc/navtoolbar.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/hwpfilter/source/grammar.cxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/hwpfilter/source/lexer.cxx")) + return true; + // marked with a TODO/FIXME + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/inc/sallayout.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/accessibility/inc/standard/vclxaccessiblelist.hxx")) + return true; + // these are "extern C" but clang doesn't seem to report that accurately + if (loplugin::isSamePathname(fn, SRCDIR "/sax/source/fastparser/fastparser.cxx")) + return true; + // these all follow the same pattern, seems a pity to break that + if (loplugin::isSamePathname(fn, SRCDIR "/include/vcl/graphicfilter.hxx")) + return true; + // looks like work in progress + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/filter/ipdf/pdfdocument.cxx")) + return true; + // macro magic + if (loplugin::isSamePathname(fn, SRCDIR "/basctl/source/inc/basidesh.hxx")) + return true; + // template magic + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/canvas/")) + return true; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/include/canvas/")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/include/comphelper/unwrapargs.hxx")) + return true; + // this looks like vaguely useful code (ParseError) that I'm loathe to remove + if (loplugin::isSamePathname(fn, SRCDIR "/connectivity/source/inc/RowFunctionParser.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/include/svx/EnhancedCustomShapeFunctionParser.hxx")) + return true; + // TODO marker parameter in constructor, should probably be using an enum + if (loplugin::isSamePathname(fn, SRCDIR "/framework/inc/uielement/uicommanddescription.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/SlideTransitionPane.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/animations/CustomAnimationPane.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/table/TableDesignPane.hxx")) + return true; + // debug stuff + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/core/data/column2.cxx")) + return true; + // weird stuff + if (loplugin::isSamePathname(fn, SRCDIR "/scaddins/source/analysis/analysishelper.hxx")) + return true; + // SFX_DECL_CHILDWINDOWCONTEXT macro stuff + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/NavigatorChildWindow.hxx")) + return true; + // TODO, need to remove this from the .sdi file too + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/SlideSorterViewShell.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/OutlineViewShell.hxx")) + return true; + // SFX_DECL_INTERFACE macro stuff + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/inc/ViewShellBase.hxx")) + return true; + // debug stuff + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/filter/ppt/pptinanimations.hxx")) + return true; + // takes pointer to fn + if (loplugin::isSamePathname(fn, SRCDIR "/include/sfx2/shell.hxx")) + return true; + // TODO, need to remove this from the .sdi file too + if (fqn == "SfxObjectShell::StateView_Impl") + return true; + // SFX_DECL_CHILDWINDOW_WITHID macro + if (loplugin::isSamePathname(fn, SRCDIR "/include/sfx2/infobar.hxx")) + return true; + // this looks like vaguely useful code (ParseError) that I'm loathe to remove + if (loplugin::isSamePathname(fn, SRCDIR "/slideshow/source/inc/slideshowexceptions.hxx")) + return true; + // SFX_DECL_VIEWFACTORY macro + if (loplugin::isSamePathname(fn, SRCDIR "/starmath/inc/view.hxx")) + return true; + // debugging + if (fqn == "BrowseBox::DoShowCursor" || fqn == "BrowseBox::DoHideCursor") + return true; + // if I change this one, it then overrides a superclass virtual method + if (fqn == "GalleryBrowser2::KeyInput") + return true; + // takes pointer to function + if (fqn == "cmis::AuthProvider::onedriveAuthCodeFallback" || fqn == "cmis::AuthProvider::gdriveAuthCodeFallback") + return true; + if (fqn == "ooo_mount_operation_ask_password") + return true; + // TODO tricky to remove because of default params + if (fqn == "xmloff::OAttribute2Property::addBooleanProperty") + return true; + // taking pointer to function + if (fqn == "sw::DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl" + || fqn == "sw::DocumentContentOperationsManager::DeleteRangeImpl" + || fqn == "SwTableFormula::GetFormulaBoxes" + || fqn == "SwFEShell::Drag" + || fqn == "GetASCWriter" || fqn == "GetHTMLWriter" || fqn == "GetXMLWriter" + || fqn == "SwWrtShell::UpdateLayoutFrame" || fqn == "SwWrtShell::DefaultDrag" + || fqn == "SwWrtShell::DefaultEndDrag" + || startswith(fqn, "SwWW8ImplReader::Read_")) + return true; + // WIN32 only + if (fqn == "SwFntObj::GuessLeading") + return true; + // SFX_DECL_CHILDWINDOW_WITHID macro + if (fqn == "SwSpellDialogChildWindow::SwSpellDialogChildWindow" + || fqn == "SwFieldDlgWrapper::SwFieldDlgWrapper" + || fqn == "SwInputChild::SwInputChild") + return true; + // SFX_DECL_VIEWFACTORY macro + if (fqn == "SwSrcView::SwSrcView") + return true; + // Serves to disambiguate two very similar methods + if (fqn == "MSWordStyles::BuildGetSlot") + return true; + // TODO there are just too many default params to make this worth fixing right now + if (fqn == "ScDocument::CopyMultiRangeFromClip") + return true; + // TODO looks like this needs fixing? + if (fqn == "ScTable::ExtendPrintArea") + return true; + // there is a FIXME in the code + if (fqn == "ScRangeUtil::IsAbsTabArea") + return true; + // SFX_DECL_CHILDWINDOW_WITHID + if (fqn == "ScInputWindowWrapper::ScInputWindowWrapper" + || fqn == "sc::SearchResultsDlgWrapper::SearchResultsDlgWrapper") + return true; + // ExecMethod in .sdi file + if (fqn == "ScChartShell::ExecuteExportAsGraphic") + return true; + // bool marker parameter + if (fqn == "SvxIconReplacementDialog::SvxIconReplacementDialog") + return true; + // used as pointer to fn + if (endswith(fqn, "_createInstance")) + return true; + // callback + if (startswith(fqn, "SbRtl_")) + return true; + // takes pointer to fn + if (fqn == "migration::BasicMigration_create" || fqn == "migration::WordbookMigration_create" + || fqn == "comp_CBlankNode::_create" || fqn == "comp_CURI::_create" + || fqn == "comp_CLiteral::_create" || fqn == "CDocumentBuilder::_getInstance" + || fqn == "DOM::CDocumentBuilder::_getInstance" + || fqn == "xml_security::serial_number_adapter::create" + || fqn == "desktop::splash::create" || fqn == "ScannerManager_CreateInstance" + || fqn == "formula::FormulaOpCodeMapperObj::create" + || fqn == "(anonymous namespace)::createInstance" + || fqn == "x_error_handler" + || fqn == "warning_func" + || fqn == "error_func" + || fqn == "ScaDateAddIn_CreateInstance" + || fqn == "ScaPricingAddIn_CreateInstance" + || fqn == "(anonymous namespace)::PDFSigningPKCS7PasswordCallback" + || fqn == "ContextMenuEventLink" + || fqn == "DelayedCloseEventLink" + || fqn == "GDIMetaFile::ImplColMonoFnc" + || fqn == "vcl::getGlyph0" + || fqn == "vcl::getGlyph6" + || fqn == "vcl::getGlyph12" + || fqn == "setPasswordCallback" + || fqn == "VCLExceptionSignal_impl" + || fqn == "getFontTable" + || fqn == "textconversiondlgs::ChineseTranslation_UnoDialog::create" + || fqn == "pcr::DefaultHelpProvider::Create" + || fqn == "pcr::DefaultFormComponentInspectorModel::Create" + || fqn == "pcr::ObjectInspectorModel::Create" + || fqn == "GraphicExportFilter::GraphicExportFilter" + || fqn == "CertificateContainer::CertificateContainer" + || startswith(fqn, "ParseCSS1_") + ) + return true; + // TODO + if (fqn == "FontSubsetInfo::CreateFontSubsetFromType1") + return true; + // used in template magic + if (fqn == "MtfRenderer::MtfRenderer" || fqn == "shell::sessioninstall::SyncDbusSessionHelper::SyncDbusSessionHelper" + || fqn == "dp_gui::LicenseDialog::LicenseDialog" + || fqn == "(anonymous namespace)::OGLTransitionFactoryImpl::OGLTransitionFactoryImpl") + return true; + // FIXME + if (fqn == "GtkSalDisplay::filterGdkEvent" || fqn == "SvXMLEmbeddedObjectHelper::ImplReadObject" + || fqn == "chart::CachedDataSequence::CachedDataSequence") + return true; + // used via macro + if (fqn == "framework::MediaTypeDetectionHelper::MediaTypeDetectionHelper" + || fqn == "framework::UriAbbreviation::UriAbbreviation" + || fqn == "framework::DispatchDisabler::DispatchDisabler" + || fqn == "framework::DispatchRecorderSupplier::DispatchRecorderSupplier") + return true; + // TODO Armin Le Grand is still working on this + if (fqn == "svx::frame::CreateDiagFrameBorderPrimitives" + || fqn == "svx::frame::CreateBorderPrimitives") + return true; + // marked with a TODO + if (fqn == "pcr::FormLinkDialog::getExistingRelation" + || fqn == "ooo::vba::DebugHelper::basicexception" + || fqn == "ScPrintFunc::DrawToDev") + return true; + // macros at work + if (fqn == "msfilter::lcl_PrintDigest") + return true; + // TODO something wrong here, the method that calls this (Normal::GenSlidingWindowFunction) cannot be correct + if (fqn == "sc::opencl::OpBase::Gen") + return true; + // Can't change this without conflicting with another constructor with the same signature + if (fqn == "XclExpSupbook::XclExpSupbook") + return true; + // ignore the LINK macros from include/tools/link.hxx + if (decl->getLocation().isMacroID()) + return true; + // debug code in sw/ + if (fqn == "lcl_dbg_out") + return true; + + for( auto it = decl->param_begin(); it != decl->param_end(); ++it) { + auto param = *it; + if (param->hasAttr()) + continue; + if (!param->getName().empty()) + continue; + // ignore params which are enum types with only a single enumerator, these are marker/tag types + auto paramType = param->getType(); + if (paramType->isEnumeralType()) { + auto enumType = paramType->getAs(); + int cnt = std::distance(enumType->getDecl()->enumerator_begin(), enumType->getDecl()->enumerator_end()); + if (cnt == 1) + continue; + } + // ignore params which are a reference to a struct which has no fields. + // These are either + // (a) marker/tag types + // (b) selective "friend" access + if (paramType->isReferenceType()) { + auto referenceType = paramType->getAs(); + if (referenceType->getPointeeType()->isRecordType()) { + auto recordType = referenceType->getPointeeType()->getAs(); + if (noFieldsInRecord(recordType) == 0) + continue; + } + } + else if (paramType->isRecordType()) { + if (noFieldsInRecord(paramType->getAs()) == 0) + continue; + } + report( DiagnosticsEngine::Warning, + "unused param %0 in %1", param->getBeginLoc()) + << param->getSourceRange() + << param->getName() + << fqn; + if (canon != decl) + { + unsigned idx = param->getFunctionScopeIndex(); + const ParmVarDecl* pOther = canon->getParamDecl(idx); + report( DiagnosticsEngine::Note, "declaration is here", + pOther->getBeginLoc()) + << pOther->getSourceRange(); + } + } + return true; +} + +loplugin::Plugin::Registration X("checkunusedparams", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/classmemaccess.cxx b/compilerplugins/clang/classmemaccess.cxx new file mode 100644 index 000000000..40132c36e --- /dev/null +++ b/compilerplugins/clang/classmemaccess.cxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "plugin.hxx" + +// Similar to GCC "warning: ‘void* memset(void*, int, size_t)’ writing to an object of non-trivial +// type ‘...’; use assignment instead [-Wclass-memaccess]", but looking through toplevel cast to +// void* and taking arrays into account in addition to pointers. (Clang has +// -Wdynamic-class-memaccess, but that only warns about memset overwriting a vtable pointer. GCC +// deliberately does not warn when there is a toplevel cast to void*, see +// "[8 Regression] cast to void* does not +// suppress -Wclass-memaccess".) + +namespace +{ +class ClassMemAccess final : public loplugin::FilteringPlugin +{ +public: + explicit ClassMemAccess(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool VisitCallExpr(CallExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const fdecl = expr->getDirectCallee(); + if (fdecl == nullptr) + { + return true; + } + auto dc = loplugin::DeclCheck(fdecl).Function("memset"); + if (!(dc.GlobalNamespace() || dc.StdNamespace())) + { + return true; + } + if (expr->getNumArgs() != 3) + { + if (isDebugMode()) + { + report(DiagnosticsEngine::Fatal, + "unexpected call to %0 with %1 instead of 3 arguments", expr->getExprLoc()) + << fdecl << expr->getNumArgs() << expr->getSourceRange(); + report(DiagnosticsEngine::Note, "%0 declared here", fdecl->getLocation()) + << fdecl << fdecl->getSourceRange(); + } + return true; + } + auto e = expr->getArg(0)->IgnoreParenImpCasts(); + while (auto const cast = dyn_cast(e)) + { + if (!loplugin::TypeCheck(cast->getTypeAsWritten()).Pointer().Void()) + { + break; + } + e = cast->getSubExprAsWritten()->IgnoreParenImpCasts(); + } + QualType t; + if (auto const t1 = e->getType()->getAs()) + { + t = t1->getPointeeType(); + } + else if (e->getType()->isArrayType()) + { + t = e->getType(); + while (auto const t2 = t->getAsArrayTypeUnsafe()) + { + t = t2->getElementType(); + } + } + else + { + if (isDebugMode()) + { + report(DiagnosticsEngine::Fatal, + "unexpected call to %0 with first argument of non-pointer type %1", + expr->getExprLoc()) + << fdecl << e->getType() << expr->getSourceRange(); + report(DiagnosticsEngine::Note, "%0 declared here", fdecl->getLocation()) + << fdecl << fdecl->getSourceRange(); + } + return true; + } + auto const decl = t->getAsCXXRecordDecl(); + if (decl == nullptr) + { + return true; + } + if (!decl->isCompleteDefinition()) + { + return true; // conservatively assume it may be trivial + } + if (decl->isTrivial()) + { + return true; + } + report(DiagnosticsEngine::Warning, + "%0 writing to an object of non-trivial type %1; use assignment instead", + expr->getExprLoc()) + << fdecl << decl << expr->getSourceRange(); + return true; + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + +private: + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } +}; + +loplugin::Plugin::Registration classmemaccess("classmemaccess"); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/collapseif.cxx b/compilerplugins/clang/collapseif.cxx new file mode 100644 index 000000000..c50bf3352 --- /dev/null +++ b/compilerplugins/clang/collapseif.cxx @@ -0,0 +1,129 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +/** + Look for nested if statements with relatively small conditions, where they can be collapsed into + one if statement. +*/ +namespace +{ +class CollapseIf : public loplugin::FilteringPlugin +{ +public: + explicit CollapseIf(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitIfStmt(IfStmt const*); + +private: + int getNoCharsInSourceCodeOfExpr(IfStmt const*); + bool containsComment(Stmt const* stmt); +}; + +bool CollapseIf::VisitIfStmt(IfStmt const* ifStmt) +{ + if (ignoreLocation(ifStmt)) + return true; + if (ifStmt->getElse()) + return true; + + IfStmt const* secondIfStmt = nullptr; + if (auto compoundStmt = dyn_cast(ifStmt->getThen())) + { + if (compoundStmt->size() != 1) + return true; + secondIfStmt = dyn_cast(*compoundStmt->body_begin()); + if (!secondIfStmt) + return true; + if (secondIfStmt->getElse()) + return true; + } + else + { + secondIfStmt = dyn_cast(ifStmt->getThen()); + if (!secondIfStmt) + return true; + } + + int noChars1 = getNoCharsInSourceCodeOfExpr(ifStmt); + int noChars2 = getNoCharsInSourceCodeOfExpr(secondIfStmt); + if (noChars1 + noChars2 > 40) + return true; + + // Sometimes there is a comment between the first and second if, so + // merging them would make the comment more awkward to write. + if (containsComment(ifStmt)) + return true; + + report(DiagnosticsEngine::Warning, "nested if should be collapsed into one statement %0 %1", + ifStmt->getBeginLoc()) + << noChars1 << noChars2 << ifStmt->getSourceRange(); + return true; +} + +int CollapseIf::getNoCharsInSourceCodeOfExpr(IfStmt const* ifStmt) +{ + // Measure the space between the "if" the beginning of the "then" block because + // measuring the size of the condition expression is unreliable, because clang + // does not report the location of the last token accurately. + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = ifStmt->getBeginLoc(); + SourceLocation endLoc = ifStmt->getThen()->getBeginLoc(); + char const* p1 = SM.getCharacterData(startLoc); + char const* p2 = SM.getCharacterData(endLoc); + + int count = 0; + for (auto p = p1; p < p2; ++p) + if (*p != ' ') + ++count; + + return count; +} + +bool CollapseIf::containsComment(Stmt const* stmt) +{ + SourceManager& SM = compiler.getSourceManager(); + auto range = stmt->getSourceRange(); + SourceLocation startLoc = range.getBegin(); + SourceLocation endLoc = range.getEnd(); + char const* p1 = SM.getCharacterData(startLoc); + char const* p2 = SM.getCharacterData(endLoc); + p2 += Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts()); + + // check for comments + constexpr char const comment1[] = "/*"; + constexpr char const comment2[] = "//"; + if (std::search(p1, p2, comment1, comment1 + strlen(comment1)) != p2) + return true; + if (std::search(p1, p2, comment2, comment2 + strlen(comment2)) != p2) + return true; + + return false; +} + +/** Off by default because some places are a judgement call if it should be collapsed or not. */ +loplugin::Plugin::Registration X("collapseif", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/colorcheck.cxx b/compilerplugins/clang/colorcheck.cxx new file mode 100644 index 000000000..55f9034c6 --- /dev/null +++ b/compilerplugins/clang/colorcheck.cxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include +#include + +#include "config_clang.h" + +#include "check.hxx" +#include "plugin.hxx" + +/** +*/ + +namespace +{ +class ColorCheck : public loplugin::FilteringPlugin +{ +public: + explicit ColorCheck(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXConstructExpr(const CXXConstructExpr*); +}; + +bool ColorCheck::VisitCXXConstructExpr(const CXXConstructExpr* constructExpr) +{ + if (ignoreLocation(constructExpr)) + return true; + + if (constructExpr->getNumArgs() != 1) + return true; + + auto tc = loplugin::TypeCheck(constructExpr->getType()); + if (!tc.Class("Color").GlobalNamespace()) + return true; + + StringRef aFileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(constructExpr->getBeginLoc())); + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/tools/color.hxx")) + return true; + + const CXXConstructorDecl* constructorDecl = constructExpr->getConstructor(); + constructorDecl = constructorDecl->getCanonicalDecl(); + + if (!loplugin::TypeCheck(constructorDecl->getParamDecl(0)->getType()) + .Typedef("sal_uInt32") + .GlobalNamespace()) + return true; + + auto arg0 = constructExpr->getArg(0); + if (arg0->isCXX11ConstantExpr(compiler.getASTContext())) + { + if (!arg0->isValueDependent()) + { + llvm::Optional xVal + = arg0->getIntegerConstantExpr(compiler.getASTContext()); + if (xVal && *xVal > 0xffffff) + report(DiagnosticsEngine::Warning, + "Rather use the ColorTransparency or ColorAlpha version of this constructor", + arg0->getExprLoc()); + return true; + } + } + report(DiagnosticsEngine::Warning, + "Rather use the ColorTransparency or ColorAlpha version of this constructor", + arg0->getExprLoc()); + + return true; +} + +loplugin::Plugin::Registration colorcheck("colorcheck"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/commaoperator.cxx b/compilerplugins/clang/commaoperator.cxx new file mode 100644 index 000000000..3ba1c89c4 --- /dev/null +++ b/compilerplugins/clang/commaoperator.cxx @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "plugin.hxx" + +/** +the comma operator is best used sparingly +*/ + +namespace { + +Stmt const * lookThroughExprWithCleanups(Stmt const * stmt) { + if (auto const e = dyn_cast_or_null(stmt)) { + return e->getSubExpr(); + } + return stmt; +} + +class CommaOperator: + public loplugin::FilteringPlugin +{ +public: + explicit CommaOperator(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool TraverseForStmt(ForStmt * stmt) { + auto const saved1 = ignore1_; + ignore1_ = lookThroughExprWithCleanups(stmt->getInit()); + auto const saved2 = ignore2_; + ignore2_ = lookThroughExprWithCleanups(stmt->getInc()); + auto const ret = RecursiveASTVisitor::TraverseForStmt(stmt); + ignore1_ = saved1; + ignore2_ = saved2; + return ret; + } + + bool TraverseWhileStmt(WhileStmt * stmt) { + auto const saved1 = ignore1_; + ignore1_ = lookThroughExprWithCleanups(stmt->getCond()); + auto const ret = RecursiveASTVisitor::TraverseWhileStmt(stmt); + ignore1_ = saved1; + return ret; + } + + bool TraverseParenExpr(ParenExpr * expr) { + auto const saved1 = ignore1_; + ignore1_ = expr->getSubExpr(); + auto const ret = RecursiveASTVisitor::TraverseParenExpr(expr); + ignore1_ = saved1; + return ret; + } + + bool TraverseBinaryOperator(BinaryOperator * expr) { + if (expr->getOpcode() != BO_Comma) { + return RecursiveASTVisitor::TraverseBinaryOperator(expr); + } + if (!WalkUpFromBinaryOperator(expr)) { + return false; + } + auto const saved1 = ignore1_; + ignore1_ = expr->getLHS(); + auto const ret = TraverseStmt(expr->getLHS()) + && TraverseStmt(expr->getRHS()); + ignore1_ = saved1; + return ret; + } + + bool VisitBinaryOperator(const BinaryOperator* ); + +private: + Stmt const * ignore1_ = nullptr; + Stmt const * ignore2_ = nullptr; +}; + +bool CommaOperator::VisitBinaryOperator(const BinaryOperator* binaryOp) +{ + if (binaryOp->getOpcode() != BO_Comma) { + return true; + } + if (binaryOp == ignore1_ || binaryOp == ignore2_) { + return true; + } + if (ignoreLocation(binaryOp)) { + return true; + } + // Ignore FD_SET expanding to "...} while(0, 0)" in some Microsoft + // winsock2.h (TODO: improve heuristic of determining that the whole + // binaryOp is part of a single macro body expansion): + if (compiler.getSourceManager().isMacroBodyExpansion( + binaryOp->getBeginLoc()) + && compiler.getSourceManager().isMacroBodyExpansion( + binaryOp->getOperatorLoc()) + && compiler.getSourceManager().isMacroBodyExpansion( + binaryOp->getEndLoc()) + && ignoreLocation( + compiler.getSourceManager().getSpellingLoc( + binaryOp->getOperatorLoc()))) + { + return true; + } + report( + DiagnosticsEngine::Warning, "comma operator hides code", + binaryOp->getOperatorLoc()) + << binaryOp->getSourceRange(); + return true; +} + + +loplugin::Plugin::Registration< CommaOperator > X("commaoperator", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/comparisonwithconstant.cxx b/compilerplugins/clang/comparisonwithconstant.cxx new file mode 100644 index 000000000..d796b7c3a --- /dev/null +++ b/compilerplugins/clang/comparisonwithconstant.cxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "compat.hxx" +#include "plugin.hxx" + +/** + Look for comparisons where the constant is on the left, it should be on the right. + */ + +namespace { + +class ComparisonWithConstant : + public loplugin::FilteringRewritePlugin +{ +public: + explicit ComparisonWithConstant(loplugin::InstantiationData const & data): FilteringRewritePlugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + // Deliberately drop RecursiveASTVisitor::TraverseBinaryOperator's DataRecursionQueue + // parameter; TraverseBinaryOperator must use stack instead of data recursion for any + // children's VisitBinaryOperator to see changes to occurrence_ by a parent + // VisitBinaryOperator: + bool TraverseBinaryOperator(BinaryOperator * S) + { + auto const op = S->getOpcode(); + if (op != BO_EQ && op != BO_NE) { + return RecursiveASTVisitor::TraverseBinaryOperator(S); + } + auto const saved = occurrence_; + auto const ret = RecursiveASTVisitor::TraverseBinaryOperator(S); + occurrence_ = saved; + return ret; + } + + bool VisitBinaryOperator(const BinaryOperator *); +private: + bool rewrite(const BinaryOperator *); + std::string getExprAsString(SourceRange range); + SourceRange ignoreMacroExpansions(SourceRange range); + + bool occurrence_ = false; +}; + +bool ComparisonWithConstant::VisitBinaryOperator(const BinaryOperator* binaryOp) +{ + if (ignoreLocation(binaryOp)) { + return true; + } + if (!(binaryOp->getOpcode() == BO_EQ || binaryOp->getOpcode() == BO_NE)) { + return true; + } + // protect against clang assert + if (binaryOp->getLHS()->isValueDependent() || binaryOp->getRHS()->isValueDependent()) { + return true; + } + if (!binaryOp->getLHS()->isEvaluatable(compiler.getASTContext())) { + return true; + } + if (binaryOp->getRHS()->isEvaluatable(compiler.getASTContext())) { + return true; + } + if (occurrence_ || !rewrite(binaryOp)) + { + report( + DiagnosticsEngine::Warning, "Rather put constant on right when comparing", + binaryOp->getSourceRange().getBegin()) + << binaryOp->getSourceRange(); + } + occurrence_ = true; + return true; +} + + +bool ComparisonWithConstant::rewrite(const BinaryOperator * binaryOp) { + if (rewriter == nullptr) { + return false; + } + + auto lhsRange = ignoreMacroExpansions(binaryOp->getLHS()->getSourceRange()); + if (!lhsRange.isValid()) { + return false; + } + auto rhsRange = ignoreMacroExpansions(binaryOp->getRHS()->getSourceRange()); + if (!rhsRange.isValid()) { + return false; + } + + const std::string lhsString = getExprAsString(lhsRange); + const std::string rhsString = getExprAsString(rhsRange); + + // switch LHS and RHS + if (!replaceText(lhsRange, rhsString)) { + return false; + } + if (!replaceText(rhsRange, lhsString)) { + return false; + } + + return true; +} + +// get the expression contents +std::string ComparisonWithConstant::getExprAsString(SourceRange range) +{ + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = range.getBegin(); + SourceLocation endLoc = range.getEnd(); + const char *p1 = SM.getCharacterData( startLoc ); + const char *p2 = SM.getCharacterData( endLoc ); + unsigned n = Lexer::MeasureTokenLength( endLoc, SM, compiler.getLangOpts()); + return std::string( p1, p2 - p1 + n); +} + +SourceRange ComparisonWithConstant::ignoreMacroExpansions(SourceRange range) { + while (compiler.getSourceManager().isMacroArgExpansion(range.getBegin())) { + range.setBegin( + compiler.getSourceManager().getImmediateMacroCallerLoc( + range.getBegin())); + } + if (range.getBegin().isMacroID()) { + SourceLocation loc; + if (Lexer::isAtStartOfMacroExpansion( + range.getBegin(), compiler.getSourceManager(), + compiler.getLangOpts(), &loc)) + { + range.setBegin(loc); + } + } + while (compiler.getSourceManager().isMacroArgExpansion(range.getEnd())) { + range.setEnd( + compiler.getSourceManager().getImmediateMacroCallerLoc( + range.getEnd())); + } + if (range.getEnd().isMacroID()) { + SourceLocation loc; + if (Lexer::isAtEndOfMacroExpansion( + range.getEnd(), compiler.getSourceManager(), + compiler.getLangOpts(), &loc)) + { + range.setEnd(loc); + } + } + return range.getBegin().isMacroID() || range.getEnd().isMacroID() + ? SourceRange() : range; +} + +loplugin::Plugin::Registration< ComparisonWithConstant > X("comparisonwithconstant", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/compat.hxx b/compilerplugins/clang/compat.hxx new file mode 100644 index 000000000..350263da6 --- /dev/null +++ b/compilerplugins/clang/compat.hxx @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/FileSystem.h" + +#include "config_clang.h" + +// Compatibility wrapper to abstract over (trivial) changes in the Clang API: +namespace compat { + +inline std::string toString(llvm::APSInt const & i, unsigned radix) { +#if CLANG_VERSION >= 130000 + return llvm::toString(i, radix); +#else + return i.toString(radix); +#endif +} + +inline std::pair getImmediateExpansionRange( + clang::SourceManager const & SM, clang::SourceLocation Loc) +{ + auto const csr = SM.getImmediateExpansionRange(Loc); + if (csr.isCharRange()) { /*TODO*/ } + return {csr.getBegin(), csr.getEnd()}; +} + +/// Utility method +inline clang::Expr const * IgnoreParenImplicit(clang::Expr const * expr) { + return expr->IgnoreImplicit()->IgnoreParens()->IgnoreImplicit(); +} + +#if CLANG_VERSION >= 130000 +constexpr clang::ExprValueKind VK_PRValue = clang::VK_PRValue; +#else +constexpr clang::ExprValueKind VK_PRValue = clang::VK_RValue; +#endif + +inline bool EvaluateAsInt(clang::Expr const * expr, llvm::APSInt& intRes, const clang::ASTContext& ctx) { + clang::Expr::EvalResult res; + bool b = expr->EvaluateAsInt(res, ctx); + if (b && res.Val.isInt()) + intRes = res.Val.getInt(); + return b; +} + +// Work around CastExpr::getSubExprAsWritten firing +// +// include/llvm/Support/Casting.h:269: typename llvm::cast_retty::ret_type llvm::cast(Y*) +// [with X = clang::CXXConstructExpr; Y = clang::Expr; +// typename llvm::cast_retty::ret_type = clang::CXXConstructExpr*]: Assertion +// `isa(Val) && "cast() argument of incompatible type!"' failed. +// +// for CastExprs involving ConstantExpr (introduced with +// "Create +// ConstantExpr class" towards LLVM 8) like +// +// CXXFunctionalCastExpr 0xc01c4e8 'class rtl::OStringLiteral<9>':'class rtl::OStringLiteral<9>' functional cast to OStringLiteral +// `-ConstantExpr 0xc01c380 'class rtl::OStringLiteral<9>':'class rtl::OStringLiteral<9>' +// |-value: Struct +// | |-fields: Int 1073741824, Int 8 +// | `-field: Array size=9 +// | |-elements: Int 46, Int 111, Int 115, Int 108 +// | |-elements: Int 45, Int 116, Int 109, Int 112 +// | `-element: Int 0 +// `-CXXConstructExpr 0xc01c350 'class rtl::OStringLiteral<9>':'class rtl::OStringLiteral<9>' 'void (const char (&)[9])' +// `-StringLiteral 0xc019ad8 'const char [9]' lvalue ".osl-tmp" +// +// Copies code from Clang's lib/AST/Expr.cpp: +namespace detail { + inline clang::Expr *skipImplicitTemporary(clang::Expr *expr) { + // Skip through reference binding to temporary. + if (clang::MaterializeTemporaryExpr *Materialize + = clang::dyn_cast(expr)) + expr = Materialize->getSubExpr(); + + // Skip any temporary bindings; they're implicit. + if (clang::CXXBindTemporaryExpr *Binder = clang::dyn_cast(expr)) + expr = Binder->getSubExpr(); + + return expr; + } +} +inline clang::Expr *getSubExprAsWritten(clang::CastExpr *This) { + clang::Expr *SubExpr = nullptr; + clang::CastExpr *E = This; + do { + SubExpr = detail::skipImplicitTemporary(E->getSubExpr()); + + // Conversions by constructor and conversion functions have a + // subexpression describing the call; strip it off. + if (E->getCastKind() == clang::CK_ConstructorConversion) + SubExpr = + detail::skipImplicitTemporary(clang::cast(SubExpr->IgnoreImplicit())->getArg(0)); + else if (E->getCastKind() == clang::CK_UserDefinedConversion) { + assert((clang::isa(SubExpr) || + clang::isa(SubExpr)) && + "Unexpected SubExpr for CK_UserDefinedConversion."); + if (clang::isa(SubExpr)) + SubExpr = clang::cast(SubExpr)->getImplicitObjectArgument(); + } + + // If the subexpression we're left with is an implicit cast, look + // through that, too. + } while ((E = clang::dyn_cast(SubExpr))); + + return SubExpr; +} +inline const clang::Expr *getSubExprAsWritten(const clang::CastExpr *This) { + return getSubExprAsWritten(const_cast(This)); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/conditionalstring.cxx b/compilerplugins/clang/conditionalstring.cxx new file mode 100644 index 000000000..cf858601e --- /dev/null +++ b/compilerplugins/clang/conditionalstring.cxx @@ -0,0 +1,459 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include + +#include "check.hxx" +#include "plugin.hxx" + +// Find uses of OUString in conditional expressions that could be rewritten as std::u16string_view, +// as in +// +// s += (b ? OUString("xy") : OUString(z"); + +namespace +{ +// Like Expr::IgnoreImplicit, but for an ImplicitCastExpr skips to getSubExprAsWritten (so skips a +// CXXConstructExpr where Expr::IgnoreImplicit would stop): +Expr const* ignoreImplicit(Expr const* expr) +{ + for (auto e = expr;;) + { + if (auto const e1 = dyn_cast(e)) + { + e = e1->getSubExprAsWritten(); + } + else if (auto const e2 = dyn_cast(e)) + { + e = e2->getSubExpr(); + } + else if (auto const e3 = dyn_cast(e)) + { + e = e3->getSubExpr(); + } + else if (auto const e4 = dyn_cast(e)) + { + e = e4->getSubExpr(); + } + else + { + return e; + } + } +} + +class ConditionalString final : public loplugin::FilteringPlugin +{ +public: + explicit ConditionalString(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool VisitCallExpr(CallExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const fn = expr->getDirectCallee(); + if (fn == nullptr) + { + return true; + } + //TODO: Instead of a hardcoded list of functions, check that `fn` has overloads taking + // OUString and std::u16string_view, respectively (and operator + is even more complicated + // than that, going via ToStringHelper specialization; the getNumArgs + // checks for the various functions are meant to guard against the unlikely case that the + // affected parameters get defaulted in the future; overloaded operators cannot generally + // have defaulted parameters): + loplugin::DeclCheck const dc(fn); + if (dc.Operator(OO_Equal).Class("OUString").Namespace("rtl").GlobalNamespace()) + { + assert(fn->getNumParams() == 1); + if (isa(expr)) + { + assert(expr->getNumArgs() == 2); + check(expr->getArg(1)); + } + else + { + assert(expr->getNumArgs() == 1); + check(expr->getArg(0)); + } + return true; + } + if (dc.Operator(OO_PlusEqual).Class("OUString").Namespace("rtl").GlobalNamespace()) + { + assert(fn->getNumParams() == 1); + if (isa(expr)) + { + assert(expr->getNumArgs() == 2); + check(expr->getArg(1)); + } + else + { + assert(expr->getNumArgs() == 1); + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("reverseCompareTo").Class("OUString").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 1) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("equalsIgnoreAsciiCase") + .Class("OUString") + .Namespace("rtl") + .GlobalNamespace() + && fn->getNumParams() == 1) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("match").Class("OUString").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 2) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("matchIgnoreAsciiCase").Class("OUString").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 2) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("startsWith").Class("OUString").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 2) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("startsWithIgnoreAsciiCase") + .Class("OUString") + .Namespace("rtl") + .GlobalNamespace() + && fn->getNumParams() == 2) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("endsWith").Class("OUString").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 2) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("endsWithIgnoreAsciiCase") + .Class("OUString") + .Namespace("rtl") + .GlobalNamespace() + && fn->getNumParams() == 2) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + if (dc.Operator(OO_EqualEqual) + .Namespace("rtl") + .GlobalNamespace()) //TODO: more precicse check + { + assert(fn->getNumParams() == 2); + assert(expr->getNumArgs() == 2); + check(expr->getArg(0)); + check(expr->getArg(1)); + return true; + } + if (dc.Operator(OO_ExclaimEqual) + .Namespace("rtl") + .GlobalNamespace()) //TODO: more precicse check + { + assert(fn->getNumParams() == 2); + assert(expr->getNumArgs() == 2); + check(expr->getArg(0)); + check(expr->getArg(1)); + return true; + } + if (dc.Operator(OO_Less).Namespace("rtl").GlobalNamespace()) //TODO: more precicse check + { + assert(fn->getNumParams() == 2); + assert(expr->getNumArgs() == 2); + check(expr->getArg(0)); + check(expr->getArg(1)); + return true; + } + if (dc.Operator(OO_LessEqual) + .Namespace("rtl") + .GlobalNamespace()) //TODO: more precicse check + { + assert(fn->getNumParams() == 2); + assert(expr->getNumArgs() == 2); + check(expr->getArg(0)); + check(expr->getArg(1)); + return true; + } + if (dc.Operator(OO_Greater).Namespace("rtl").GlobalNamespace()) //TODO: more precicse check + { + assert(fn->getNumParams() == 2); + assert(expr->getNumArgs() == 2); + check(expr->getArg(0)); + check(expr->getArg(1)); + return true; + } + if (dc.Operator(OO_GreaterEqual) + .Namespace("rtl") + .GlobalNamespace()) //TODO: more precicse check + { + assert(fn->getNumParams() == 2); + assert(expr->getNumArgs() == 2); + check(expr->getArg(0)); + check(expr->getArg(1)); + return true; + } + if (dc.Function("indexOf").Class("OUString").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 2) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("lastIndexOf").Class("OUString").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 1) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("replaceFirst").Class("OUString").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 3) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + if (expr->getNumArgs() >= 2) + { + check(expr->getArg(1)); + } + return true; + } + if (dc.Function("replaceAll").Class("OUString").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 2) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + if (expr->getNumArgs() >= 2) + { + check(expr->getArg(1)); + } + return true; + } + if (dc.Operator(OO_Plus).Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 2) //TODO: more precicse check + { + assert(expr->getNumArgs() == 2); + check(expr->getArg(0)); + check(expr->getArg(1)); + return true; + } + if (dc.Operator(OO_Equal).Class("OUStringBuffer").Namespace("rtl").GlobalNamespace()) + { + assert(fn->getNumParams() == 1); + if (isa(expr)) + { + assert(expr->getNumArgs() == 2); + check(expr->getArg(1)); + } + else + { + assert(expr->getNumArgs() == 1); + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("append").Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 1) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("insert").Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 2) + { + if (expr->getNumArgs() >= 2) + { + check(expr->getArg(1)); + } + return true; + } + if (dc.Function("indexOf").Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 2) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + if (dc.Function("lastIndexOf").Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + && fn->getNumParams() == 1) + { + if (expr->getNumArgs() >= 1) + { + check(expr->getArg(0)); + } + return true; + } + return true; + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + +private: + enum class Kind + { + OUStringFromLiteral, + StringViewOrVoid, + Other + }; + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + Kind getKind(Expr const* expr) + { + auto const tc = loplugin::TypeCheck(ignoreImplicit(expr)->getType()); + if (tc.ClassOrStruct("basic_string_view").StdNamespace() //TODO: check explicitly for + // std::basic_string_view + || tc.Void()) + { + return Kind::StringViewOrVoid; + } + if (loplugin::TypeCheck(expr->getType()) + .Class("OUString") + .Namespace("rtl") + .GlobalNamespace()) + { + // Check for both explicit + // + // OUString("...") + // + // and implicit + // + // "..." + // + // expressions: + auto e = expr->IgnoreParens(); + if (auto const e1 = dyn_cast(e)) + { + e = e1->getSubExpr(); + } + if (auto const e1 = dyn_cast(e->IgnoreImplicit()->IgnoreParens())) + { + if (e1->getNumArgs() != 0 //TODO + && isa(e1->getArg(0)->IgnoreParenImpCasts())) + { + return Kind::OUStringFromLiteral; + } + } + } + return Kind::Other; + } + + void check(Expr const* expr) + { + //TODO: skip `,`; handle ?: chains + auto const cond = dyn_cast(expr->IgnoreParenImpCasts()); + if (cond == nullptr) + { + return; + } + auto const k1 = getKind(cond->getTrueExpr()); + if (k1 == Kind::Other) + { + return; + } + auto const k2 = getKind(cond->getFalseExpr()); + if (k2 == Kind::Other || (k1 == Kind::StringViewOrVoid && k2 == Kind::StringViewOrVoid)) + { + return; + } + if (k1 == Kind::OUStringFromLiteral && k2 == Kind::OUStringFromLiteral) + { + report(DiagnosticsEngine::Warning, + ("replace both 2nd and 3rd operands of conditional expression with" + " `std::u16string_view`"), + cond->getExprLoc()) + << cond->getSourceRange(); + } + else + { + assert((k1 == Kind::OUStringFromLiteral && k2 == Kind::StringViewOrVoid) + || (k1 == Kind::StringViewOrVoid && k2 == Kind::OUStringFromLiteral)); + auto const second = k1 == Kind::OUStringFromLiteral; + auto const sub + = (second ? cond->getTrueExpr() : cond->getFalseExpr())->IgnoreParenImpCasts(); + report(DiagnosticsEngine::Warning, + ("replace %select{2nd|3rd}0 operand of conditional expression with" + " `std::u16string_view`"), + sub->getExprLoc()) + << (second ? 0 : 1) << sub->getSourceRange(); + report(DiagnosticsEngine::Note, "conditional expression is here", cond->getExprLoc()) + << cond->getSourceRange(); + } + } +}; + +loplugin::Plugin::Registration conditionalstring("conditionalstring"); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/constantparam.bitmask.results b/compilerplugins/clang/constantparam.bitmask.results new file mode 100644 index 000000000..5a78a996d --- /dev/null +++ b/compilerplugins/clang/constantparam.bitmask.results @@ -0,0 +1,54 @@ +codemaker/source/javamaker/classfile.hxx:152 + void codemaker::javamaker::ClassFile::ClassFile(enum codemaker::javamaker::ClassFile::AccessFlags,const class rtl::OString &,const class rtl::OString &,const class rtl::OString &) + enum codemaker::javamaker::ClassFile::AccessFlags accessFlags setBits=0x1 +codemaker/source/javamaker/classfile.hxx:167 + void codemaker::javamaker::ClassFile::addField(enum codemaker::javamaker::ClassFile::AccessFlags,const class rtl::OString &,const class rtl::OString &,unsigned short,const class rtl::OString &) + enum codemaker::javamaker::ClassFile::AccessFlags accessFlags setBits=0x1 +dbaccess/source/filter/xml/xmlExport.hxx:163 + void dbaxml::ODBExport::ODBExport(const class com::sun::star::uno::Reference &,const class rtl::OUString &,enum SvXMLExportFlags) + enum SvXMLExportFlags nExportFlag setBits=0x400 clearBits=0x200 +include/basegfx/polygon/b2dpolygontools.hxx:145 + enum CutFlagValue findCut(const class basegfx::B2DPoint &,const class basegfx::B2DVector &,const class basegfx::B2DPoint &,const class basegfx::B2DVector &,enum CutFlagValue,double *,double *) + enum CutFlagValue aCutFlags setBits=0x1 +include/framework/framelistanalyzer.hxx:185 + void framework::FrameListAnalyzer::FrameListAnalyzer(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,enum FrameAnalyzerFlags) + enum FrameAnalyzerFlags eDetectMode setBits=0x4 +include/sfx2/objsh.hxx:467 + void SfxObjectShell::FinishedLoading(enum SfxLoadedFlags) + enum SfxLoadedFlags nWhich setBits=0x1 +include/svtools/brwbox.hxx:510 + void BrowseBox::InsertDataColumn(unsigned short,const class rtl::OUString &,long,enum HeaderBarItemBits,unsigned short) + enum HeaderBarItemBits nBits setBits=0x400 clearBits=0x3ec +include/vcl/wizardmachine.hxx:139 + void vcl::WizardMachine::WizardMachine(class weld::Window *,enum WizardButtonFlags) + enum WizardButtonFlags _nButtonFlags setBits=0xf +sc/inc/rangelst.hxx:47 + void ScRangeList::Format(class rtl::OUString &,enum ScRefFlags,const class ScDocument &,enum formula::FormulaGrammar::AddressConvention,char16_t,_Bool) const + enum ScRefFlags nFlags setBits=0x8000 clearBits=0x7f80 +sc/inc/rangeutl.hxx:168 + void ScRangeStringConverter::GetStringFromAddress(class rtl::OUString &,const class ScAddress &,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t,_Bool,enum ScRefFlags) + enum ScRefFlags nFormatFlags setBits=0x8008 clearBits=0x7ff0 +sc/inc/xmlwrap.hxx:88 + _Bool ScXMLImportWrapper::Import(enum ImportFlags,class ErrCode &) + enum ImportFlags nMode setBits=0x1 +sc/source/ui/view/cellsh1.cxx:103 + enum InsertDeleteFlags FlagsFromString(const class rtl::OUString &,enum InsertDeleteFlags) + enum InsertDeleteFlags nFlagsMask setBits=0x87f clearBits=0x700 +sc/source/ui/view/cellsh1.cxx:126 + class rtl::OUString FlagsToString(enum InsertDeleteFlags,enum InsertDeleteFlags) + enum InsertDeleteFlags nFlagsMask setBits=0x87f clearBits=0x700 +sw/source/core/view/viewsh.cxx:719 + void lcl_InvalidateAllContent(class SwViewShell &,enum SwInvalidateFlags) + enum SwInvalidateFlags nInv setBits=0x2 +sw/source/filter/html/swhtml.hxx:689 + void SwHTMLParser::SetFrameFormatAttrs(class SfxItemSet &,enum HtmlFrameFormatFlags,class SfxItemSet &) + enum HtmlFrameFormatFlags nFlags setBits=0x1 +sw/source/filter/ww8/wrtw8esh.cxx:1545 + enum ShapeFlag AddMirrorFlags(enum ShapeFlag,const class SwMirrorGrf &) + enum ShapeFlag nFlags setBits=0xa00 clearBits=0x5ef +xmloff/inc/MetaExportComponent.hxx:31 + void XMLMetaExportComponent::XMLMetaExportComponent(const class com::sun::star::uno::Reference &,const class rtl::OUString &,enum SvXMLExportFlags) + enum SvXMLExportFlags nFlags setBits=0x1 +xmloff/source/text/XMLAutoTextEventExport.hxx:50 + void XMLAutoTextEventExport::XMLAutoTextEventExport(const class com::sun::star::uno::Reference &,const class rtl::OUString &,enum SvXMLExportFlags) + enum SvXMLExportFlags nFlags setBits=0x5ff clearBits=0x200 diff --git a/compilerplugins/clang/constantparam.booleans.results b/compilerplugins/clang/constantparam.booleans.results new file mode 100644 index 000000000..e34c49f41 --- /dev/null +++ b/compilerplugins/clang/constantparam.booleans.results @@ -0,0 +1,4308 @@ +accessibility/inc/standard/vclxaccessiblemenuitem.hxx:58 + void VCLXAccessibleMenuItem::VCLXAccessibleMenuItem(class Menu *,unsigned short,class Menu *) + class Menu * pMenu + 0 +accessibility/source/standard/vclxaccessibletoolbox.cxx:101 + void (anonymous namespace)::OToolBoxWindowItem::OToolBoxWindowItem(int,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &) + int _nIndexInParent + 0 +basctl/source/basicide/moduldlg.hxx:107 + void basctl::LibDialog::EnableReference(_Bool) + _Bool b + 0 +basctl/source/inc/scriptdocument.hxx:88 + void basctl::ScriptDocument::ScriptDocument(enum basctl::ScriptDocument::SpecialDocument) + enum basctl::ScriptDocument::SpecialDocument _eType + 0 +basegfx/source/polygon/b2dpolygon.cxx:61 + void (anonymous namespace)::CoordinateDataArray2D::CoordinateDataArray2D(unsigned int) + unsigned int nCount + 0 +basegfx/source/polygon/b3dpolygon.cxx:78 + void (anonymous namespace)::CoordinateDataArray3D::CoordinateDataArray3D(unsigned int) + unsigned int nCount + 0 +basic/source/inc/runtime.hxx:324 + void SbiRuntime::StepRESUME(unsigned int) + unsigned int + 1 +basic/source/inc/runtime.hxx:355 + _Bool SbiRuntime::IsMissing(class SbxVariable *,unsigned short) + unsigned short + 1 +basic/source/runtime/iosys.cxx:62 + void (anonymous namespace)::SbiInputDialog::SbiInputDialog(class weld::Window *,const class rtl::OUString &) + class weld::Window * + 0 +canvas/inc/parametricpolypolygon.hxx:139 + void canvas::ParametricPolyPolygon::ParametricPolyPolygon(const class com::sun::star::uno::Reference &,enum canvas::ParametricPolyPolygon::GradientType,const class com::sun::star::uno::Sequence > &,const class com::sun::star::uno::Sequence &) + enum canvas::ParametricPolyPolygon::GradientType eType + 0 +canvas/inc/spriteredrawmanager.hxx:108 + void canvas::SpriteRedrawManager::SpriteInfo::SpriteInfo(const class rtl::Reference &,const class basegfx::B2DRange &,_Bool,_Bool) + _Bool bNeedsUpdate + 1 +canvas/inc/verifyinput.hxx:147 + void verifyInput(const struct com::sun::star::geometry::RealBezierSegment2D &,const char *,const class com::sun::star::uno::Reference &,short) + short nArgPos + 0 +canvas/inc/verifyinput.hxx:279 + void verifyInput(const struct com::sun::star::rendering::IntegerBitmapLayout &,const char *,const class com::sun::star::uno::Reference &,short) + short nArgPos + 0 +canvas/inc/verifyinput.hxx:520 + void verifyRange(type-parameter-?-?,type-parameter-?-?,_Bool) + type-parameter-?-? bound + 1 +canvas/inc/verifyinput.hxx:520 + void verifyRange(type-parameter-?-?,type-parameter-?-?,_Bool) + _Bool bLowerBound + 1 +canvas/source/cairo/cairo_canvashelper.hxx:248 + void cairocanvas::CanvasHelper::useStates(const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,_Bool) + _Bool setColor + 1 +canvas/source/vcl/spritecanvashelper.hxx:44 + void vclcanvas::SpriteCanvasHelper::init(const class std::shared_ptr &,class vclcanvas::SpriteCanvas &,class canvas::SpriteRedrawManager &,_Bool,_Bool) + _Bool bProtect + 0 +canvas/source/vcl/spritecanvashelper.hxx:44 + void vclcanvas::SpriteCanvasHelper::init(const class std::shared_ptr &,class vclcanvas::SpriteCanvas &,class canvas::SpriteRedrawManager &,_Bool,_Bool) + _Bool bHaveAlpha + 0 +chart2/qa/extras/chart2dump/chart2dump.cxx:91 + void Chart2DumpTest::Chart2DumpTest(_Bool) + _Bool bDumpMode + 0 +chart2/qa/extras/chart2export.cxx:452 + void checkCommonTrendline(const class com::sun::star::uno::Reference &,double,double,_Bool,double,_Bool,_Bool) + _Bool aExpectedShowEquation + 1 +chart2/qa/extras/charttest.hxx:244 + class com::sun::star::uno::Reference getPivotChartDocFromSheet(int,const class com::sun::star::uno::Reference &) + int nSheet + 1 +chart2/qa/extras/charttest.hxx:250 + class com::sun::star::uno::Reference getPivotChartDocFromSheet(const class com::sun::star::uno::Reference &,int) + int nIndex + 0 +chart2/qa/extras/charttest.hxx:284 + class com::sun::star::uno::Reference getAxisFromDoc(const class com::sun::star::uno::Reference &,int,int,int) + int nCooSys + 0 +chart2/qa/extras/charttest.hxx:304 + int getNumberOfDataSeries(const class com::sun::star::uno::Reference &,int,int) + int nChartType + 0 +chart2/qa/extras/charttest.hxx:304 + int getNumberOfDataSeries(const class com::sun::star::uno::Reference &,int,int) + int nCooSys + 0 +chart2/qa/extras/charttest.hxx:314 + class com::sun::star::uno::Reference getDataSeriesFromDoc(const class com::sun::star::uno::Reference &,int,int,int) + int nCooSys + 0 +chart2/qa/extras/charttest.hxx:329 + class com::sun::star::uno::Reference getLabelDataSequenceFromDoc(const class com::sun::star::uno::Reference &,int,int) + int nChartType + 0 +chart2/qa/extras/charttest.hxx:351 + class com::sun::star::uno::Reference getDataSequenceFromDocByRole(const class com::sun::star::uno::Reference &,class std::basic_string_view >,int,int) + int nChartType + 0 +chart2/qa/extras/PivotChartTest.cxx:134 + void lclModifyColumnGrandTotal(const class com::sun::star::uno::Reference &,_Bool) + _Bool bTotal + 1 +chart2/qa/extras/PivotChartTest.cxx:140 + void lclModifyRowGrandTotal(const class com::sun::star::uno::Reference &,_Bool) + _Bool bTotal + 1 +chart2/qa/extras/PivotChartTest.cxx:177 + class com::sun::star::uno::Reference lclGetPivotTableByName(int,const class rtl::OUString &,const class com::sun::star::uno::Reference &) + int nIndex + 1 +chart2/qa/extras/PivotChartTest.cxx:219 + class com::sun::star::uno::Reference lclGetDataPilotTables(int,const class com::sun::star::uno::Reference &) + int nIndex + 0 +chart2/source/controller/dialogs/DialogModel.cxx:170 + struct (anonymous namespace)::lcl_DataSeriesContainerAppend & (anonymous namespace)::lcl_DataSeriesContainerAppend::operator++(int) + int + 0 +chart2/source/controller/dialogs/DialogModel.cxx:229 + struct (anonymous namespace)::lcl_RolesWithRangeAppend & (anonymous namespace)::lcl_RolesWithRangeAppend::operator++(int) + int + 0 +chart2/source/controller/inc/ChartController.hxx:367 + class chart::ChartController::TheModelRef & chart::ChartController::TheModelRef::operator=(class chart::ChartController::TheModel *) + ###1 + 0 +chart2/source/controller/inc/ViewElementListProvider.hxx:51 + class Graphic chart::ViewElementListProvider::GetSymbolGraphic(int,const class SfxItemSet *) const + int nStandardSymbol + 0 +chart2/source/inc/AxisHelper.hxx:193 + class com::sun::star::uno::Reference chart::AxisHelper::getChartTypeByIndex(const class com::sun::star::uno::Reference &,int) + int nIndex + 0 +chart2/source/inc/ChartTypeDialogController.hxx:64 + void chart::ChartTypeParameter::ChartTypeParameter(int,_Bool,_Bool,enum chart::GlobalStackMode,_Bool,_Bool,enum com::sun::star::chart2::CurveStyle) + enum com::sun::star::chart2::CurveStyle eCurveStyle + 0 +chart2/source/model/template/ColumnLineChartTypeTemplate.hxx:37 + void chart::ColumnLineChartTypeTemplate::ColumnLineChartTypeTemplate(const class com::sun::star::uno::Reference &,const class rtl::OUString &,enum chart::StackMode,int) + int nNumberOfLines + 1 +chart2/source/tools/InternalDataProvider.cxx:244 + void chart::(anonymous namespace)::lcl_setAnyAtLevelFromStringSequence::lcl_setAnyAtLevelFromStringSequence(int) + int nLevel + 0 +chart2/source/view/axes/VAxisProperties.hxx:149 + struct chart::TickmarkProperties chart::AxisProperties::makeTickmarkPropertiesForComplexCategories(int,int) const + int nTickStartDistanceToAxis + 0 +chart2/source/view/axes/VCartesianAxis.hxx:31 + void chart::VCartesianAxis::VCartesianAxis(const struct chart::AxisProperties &,const class com::sun::star::uno::Reference &,int,int,class chart::PlottingPositionHelper *) + int nDimensionIndex + 1 +chart2/source/view/charttypes/CategoryPositionHelper.hxx:27 + void chart::CategoryPositionHelper::CategoryPositionHelper(double,double) + double fSeriesCount + 1 +chart2/source/view/inc/PlottingPositionHelper.hxx:111 + void chart::PlottingPositionHelper::AllowShiftXAxisPos(_Bool) + _Bool bAllowShift + 1 +chart2/source/view/inc/PlottingPositionHelper.hxx:112 + void chart::PlottingPositionHelper::AllowShiftZAxisPos(_Bool) + _Bool bAllowShift + 1 +chart2/source/view/inc/Stripe.hxx:52 + void chart::Stripe::InvertNormal(_Bool) + _Bool bInvertNormal + 1 +chart2/source/view/main/ShapeFactory.cxx:705 + void appendAndCloseBezierCoords(struct com::sun::star::drawing::PolyPolygonBezierCoords &,const struct com::sun::star::drawing::PolyPolygonBezierCoords &,_Bool) + _Bool bAppendInverse + 1 +chart2/source/view/main/VButton.hxx:50 + void chart::VButton::showArrow(_Bool) + _Bool bShowArrow + 0 +codemaker/source/javamaker/classfile.hxx:119 + void codemaker::javamaker::ClassFile::Code::storeLocalReference(unsigned short) + unsigned short index + 1 +comphelper/source/misc/backupfilehelper.cxx:58 + unsigned int createCrc32(const class std::shared_ptr &,unsigned int) + unsigned int nOffset + 0 +connectivity/inc/sdbcx/VIndex.hxx:62 + void connectivity::sdbcx::OIndex::OIndex(_Bool) + _Bool _bCase + 1 +connectivity/inc/sdbcx/VIndex.hxx:63 + void connectivity::sdbcx::OIndex::OIndex(const class rtl::OUString &,const class rtl::OUString &,_Bool,_Bool,_Bool,_Bool) + _Bool _bCase + 1 +connectivity/inc/sdbcx/VKey.hxx:77 + void connectivity::sdbcx::OKey::OKey(_Bool) + _Bool _bCase + 1 +connectivity/inc/sdbcx/VKey.hxx:78 + void connectivity::sdbcx::OKey::OKey(const class rtl::OUString &,const class std::shared_ptr &,_Bool) + _Bool _bCase + 1 +connectivity/inc/sdbcx/VUser.hxx:61 + void connectivity::sdbcx::OUser::OUser(_Bool) + _Bool _bCase + 1 +connectivity/inc/sdbcx/VUser.hxx:62 + void connectivity::sdbcx::OUser::OUser(const class rtl::OUString &,_Bool) + _Bool _bCase + 1 +connectivity/source/drivers/postgresql/pq_connection.cxx:345 + void pq_sdbc_driver::(anonymous namespace)::cstr_vector::push_back(const char *,enum __sal_NoAcquire) + enum __sal_NoAcquire + 0 +connectivity/source/drivers/postgresql/pq_resultsetmetadata.hxx:88 + _Bool pq_sdbc_driver::ResultSetMetaData::getBoolColumnProperty(const class rtl::OUString &,int,_Bool) + _Bool def + 0 +connectivity/source/inc/dbase/DIndex.hxx:112 + _Bool connectivity::dbase::ODbaseIndex::Find(unsigned int,const class connectivity::ORowSetValue &) + unsigned int nRec + 0 +connectivity/source/inc/OColumn.hxx:67 + void connectivity::OColumn::OColumn(const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,int) + int _aScale + 0 +connectivity/source/inc/odbc/OTools.hxx:179 + void connectivity::odbc::OTools::getBindTypes(_Bool,_Bool,short,short &,short &) + _Bool _bUseWChar + 0 +connectivity/source/inc/odbc/OTools.hxx:216 + void connectivity::odbc::OTools::bindValue(const class connectivity::odbc::OConnection *,void *,int,short,short,const void *,void *,long *,const class com::sun::star::uno::Reference &,unsigned short,_Bool) + short _nMaxLen + 0 +cppcanvas/source/mtfrenderer/mtftools.cxx:285 + void appendRect(class basegfx::B2DPolyPolygon &,const class basegfx::B2DPoint &,const double,const double,const double,const double) + const double nX1 + 0 +cppu/qa/test_reference.cxx:88 + const class com::sun::star::uno::Type & (anonymous namespace)::Base1::static_type(void *) + void * + 0 +cppu/qa/test_unotype.cxx:63 + void (anonymous namespace)::DerivedInterface1::dummy(struct (anonymous namespace)::DerivedInterface1 *) + struct (anonymous namespace)::DerivedInterface1 * p + 0 +cppu/qa/test_unotype.cxx:74 + void (anonymous namespace)::DerivedInterface2::dummy(struct (anonymous namespace)::DerivedInterface2 *) + struct (anonymous namespace)::DerivedInterface2 * p + 0 +cui/source/inc/acccfg.hxx:43 + void TAccInfo::TAccInfo(int,int,const class vcl::KeyCode &) + int nListPos + 0 +cui/source/inc/cfg.hxx:336 + void SvxMenuEntriesListBox::set_text(int,const class rtl::OUString &,int) + int col + 0 +cui/source/inc/cfg.hxx:456 + void SvxConfigPage::InsertEntryIntoUI(class SvxConfigEntry *,class weld::TreeView &,class weld::TreeIter &,_Bool) + _Bool bMenu + 1 +cui/source/inc/cfgutil.hxx:130 + void CuiConfigFunctionListBox::append(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class weld::TreeIter *) + const class weld::TreeIter * pParent + 0 +cui/source/inc/cfgutil.hxx:145 + class std::unique_ptr > CuiConfigFunctionListBox::make_iterator(const class weld::TreeIter *) const + const class weld::TreeIter * pOrig + 0 +cui/source/inc/cuitabarea.hxx:725 + void SvxColorTabPage::SetPropertyList(enum XPropertyListType,const class rtl::Reference &) + enum XPropertyListType t + 0 +cui/source/inc/hangulhanjadlg.hxx:54 + void svx::SuggestionDisplay::SelectEntryPos(unsigned short) + unsigned short nPos + 0 +cui/source/inc/hangulhanjadlg.hxx:58 + class rtl::OUString svx::SuggestionDisplay::GetEntry(unsigned short) const + unsigned short nPos + 0 +cui/source/inc/scriptdlg.hxx:122 + void SvxScriptOrgDialog::insertEntry(const class rtl::OUString &,const class rtl::OUString &,const class weld::TreeIter *,_Bool,class std::unique_ptr > &&,const class rtl::OUString &,_Bool) + const class weld::TreeIter * pParent + 0 +cui/source/inc/scriptdlg.hxx:122 + void SvxScriptOrgDialog::insertEntry(const class rtl::OUString &,const class rtl::OUString &,const class weld::TreeIter *,_Bool,class std::unique_ptr > &&,const class rtl::OUString &,_Bool) + _Bool bChildrenOnDemand + 1 +cui/source/inc/scriptdlg.hxx:122 + void SvxScriptOrgDialog::insertEntry(const class rtl::OUString &,const class rtl::OUString &,const class weld::TreeIter *,_Bool,class std::unique_ptr > &&,const class rtl::OUString &,_Bool) + _Bool bSelect + 0 +cui/source/options/optjsearch.hxx:65 + void SvxJSearchOptionsPage::EnableSaveOptions(_Bool) + _Bool bVal + 0 +dbaccess/source/core/dataaccess/databasedocument.hxx:674 + void dbaccess::DocumentGuard::DocumentGuard(const class dbaccess::ODatabaseDocument &,enum dbaccess::DocumentGuard::DefaultMethod_) + enum dbaccess::DocumentGuard::DefaultMethod_ + 0 +dbaccess/source/core/dataaccess/databasedocument.hxx:692 + void dbaccess::DocumentGuard::DocumentGuard(const class dbaccess::ODatabaseDocument &,enum dbaccess::DocumentGuard::InitMethod_) + enum dbaccess::DocumentGuard::InitMethod_ + 0 +dbaccess/source/core/dataaccess/databasedocument.hxx:711 + void dbaccess::DocumentGuard::DocumentGuard(const class dbaccess::ODatabaseDocument &,enum dbaccess::DocumentGuard::MethodUsedDuringInit_) + enum dbaccess::DocumentGuard::MethodUsedDuringInit_ + 0 +dbaccess/source/core/dataaccess/databasedocument.hxx:726 + void dbaccess::DocumentGuard::DocumentGuard(const class dbaccess::ODatabaseDocument &,enum dbaccess::DocumentGuard::MethodWithoutInit_) + enum dbaccess::DocumentGuard::MethodWithoutInit_ + 0 +dbaccess/source/core/inc/column.hxx:167 + void dbaccess::OColumns::OColumns(class cppu::OWeakObject &,class osl::Mutex &,_Bool,const class std::__debug::vector > &,class dbaccess::IColumnFactory *,class connectivity::sdbcx::IRefreshableColumns *,_Bool,_Bool,_Bool) + _Bool _bDropColumn + 0 +dbaccess/source/core/inc/column.hxx:178 + void dbaccess::OColumns::OColumns(class cppu::OWeakObject &,class osl::Mutex &,const class com::sun::star::uno::Reference &,_Bool,const class std::__debug::vector > &,class dbaccess::IColumnFactory *,class connectivity::sdbcx::IRefreshableColumns *,_Bool,_Bool,_Bool) + _Bool _bUseHardRef + 1 +dbaccess/source/ui/control/tabletree.cxx:167 + class std::__debug::vector > lcl_getMetaDataStrings_throw(const class com::sun::star::uno::Reference &,int) + int _nColumnIndex + 1 +dbaccess/source/ui/inc/charsets.hxx:45 + class dbaui::OCharsetDisplay::ExtendedCharsetIterator dbaui::OCharsetDisplay::findEncoding(const unsigned short) const + const unsigned short _eEncoding + 0 +dbaccess/source/ui/inc/FieldDescControl.hxx:121 + void dbaui::OFieldDescControl::InitializeControl(class dbaui::OPropListBoxCtrl *,const class rtl::OString &,_Bool) + _Bool _bAddChangeHandler + 1 +dbaccess/source/ui/inc/imageprovider.hxx:77 + class com::sun::star::uno::Reference dbaui::ImageProvider::getXGraphic(const class rtl::OUString &,const int) + const int _nDatabaseObjectType + 0 +dbaccess/source/ui/inc/IUpdateHelper.hxx:32 + void dbaui::IUpdateHelper::updateInt(int,int) + int _nPos + 1 +dbaccess/source/ui/inc/WCopyTable.hxx:310 + void dbaui::OCopyTableWizard::OCopyTableWizard(class weld::Window *,const class rtl::OUString &,short,const class std::__debug::map > > &,const class std::__debug::vector >, class std::__debug::map > >, struct std::bidirectional_iterator_tag>, class std::allocator >, class std::__debug::map > >, struct std::bidirectional_iterator_tag> > > &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,class std::unique_ptr > (*)(class weld::Container *, class dbaui::OCopyTableWizard *, class SvStream &),class SvStream &,const class com::sun::star::uno::Reference &) + class weld::Window * pParent + 0 +dbaccess/source/ui/inc/WTypeSelect.hxx:122 + void dbaui::OWizTypeSelect::EnableAuto(_Bool) + _Bool bEnable + 0 +desktop/source/deployment/gui/dp_gui_updatedialog.hxx:102 + void dp_gui::UpdateDialog::addAdditional(struct dp_gui::UpdateDialog::Index *,_Bool) + _Bool bEnableCheckBox + 0 +desktop/source/lib/init.cxx:6412 + struct _LibreOfficeKit * libreofficekit_hook_2(const char *,const char *) + const char * user_profile_url + 0 +drawinglayer/source/processor2d/vclhelperbufferdevice.cxx:70 + class VclPtr (anonymous namespace)::VDevBuffer::alloc(class OutputDevice &,const class Size &,_Bool,_Bool) + _Bool bMonoChrome + 0 +editeng/source/editeng/editstt2.hxx:28 + void InternalEditStatus::TurnOnFlags(enum EEControlBits) + enum EEControlBits nFlags + 1 +editeng/source/editeng/editstt2.hxx:31 + void InternalEditStatus::TurnOffFlags(enum EEControlBits) + enum EEControlBits nFlags + 1 +editeng/source/editeng/impedit.hxx:896 + unsigned short ImpEditEngine::GetLineHeight(int,int) + int nLine + 0 +extensions/source/propctrlr/browserline.hxx:95 + void pcr::OBrowserLine::Show(_Bool) + _Bool bFlag + 0 +extensions/source/propctrlr/newdatatype.hxx:39 + void pcr::NewDataTypeDialog::NewDataTypeDialog(class weld::Window *,const class rtl::OUString &,const class std::__debug::vector > &) + class weld::Window * _pParent + 0 +extensions/source/propctrlr/propertyhandler.hxx:184 + void pcr::PropertyHandler::addDoublePropertyDescription(class std::__debug::vector > &,const class rtl::OUString &,short) const + short _nAttribs + 1 +extensions/source/propctrlr/propertyhandler.hxx:192 + void pcr::PropertyHandler::addDatePropertyDescription(class std::__debug::vector > &,const class rtl::OUString &,short) const + short _nAttribs + 1 +extensions/source/propctrlr/propertyhandler.hxx:200 + void pcr::PropertyHandler::addTimePropertyDescription(class std::__debug::vector > &,const class rtl::OUString &,short) const + short _nAttribs + 1 +extensions/source/propctrlr/propertyhandler.hxx:208 + void pcr::PropertyHandler::addDateTimePropertyDescription(class std::__debug::vector > &,const class rtl::OUString &,short) const + short _nAttribs + 1 +extensions/source/propctrlr/usercontrol.hxx:41 + void pcr::OFormatSampleControl::OFormatSampleControl(class std::unique_ptr >,class std::unique_ptr >,_Bool) + _Bool bReadOnly + 0 +extensions/source/propctrlr/usercontrol.hxx:91 + void pcr::OFormattedNumericControl::OFormattedNumericControl(class std::unique_ptr >,class std::unique_ptr >,_Bool) + _Bool bReadOnly + 0 +extensions/source/propctrlr/usercontrol.hxx:124 + void pcr::OFileUrlControl::OFileUrlControl(class std::unique_ptr >,class std::unique_ptr >,_Bool) + _Bool bReadOnly + 0 +extensions/source/scanner/grid.cxx:130 + void GridWindow::Init(double *,double *,int,_Bool,const class BitmapEx &) + _Bool bCutValues + 1 +extensions/source/scanner/grid.hxx:47 + void GridDialog::setBoundings(double,double,double,double) + double fMinX + 0 +filter/source/graphicfilter/icgm/cgm.hxx:88 + unsigned char CGM::ImplGetByte(unsigned int,unsigned int) + unsigned int nPrecision + 1 +filter/source/svg/svgfilter.hxx:258 + _Bool SVGFilter::implExportMasterPages(const class std::__debug::vector, class std::allocator > > &,int,int) + int nFirstPage + 0 +filter/source/svg/svgfilter.hxx:260 + void SVGFilter::implExportDrawPages(const class std::__debug::vector, class std::allocator > > &,int,int) + int nFirstPage + 0 +filter/source/svg/svgwriter.hxx:258 + void SVGTextWriter::startTextPosition(_Bool,_Bool) + _Bool bExportY + 1 +forms/source/component/DatabaseForm.hxx:232 + void frm::ODatabaseForm::fire(int *,const class com::sun::star::uno::Any *,const class com::sun::star::uno::Any *,int) + int nCount + 1 +forms/source/component/GroupManager.hxx:143 + const class com::sun::star::uno::Reference & frm::OGroup::GetObject(unsigned short) const + unsigned short nP + 0 +forms/source/inc/featuredispatcher.hxx:50 + void frm::IFeatureDispatcher::dispatchWithArgument(short,const char *,const class com::sun::star::uno::Any &) const + short _nFeatureId + 1 +formula/source/ui/dlg/structpg.hxx:58 + _Bool formula::StructPage::InsertEntry(const class rtl::OUString &,const class weld::TreeIter *,unsigned short,int,const class formula::FormulaToken *,class weld::TreeIter &) + int nPos + 0 +fpicker/source/office/autocmpledit.hxx:39 + void AutocompleteEdit::select_region(int,int) + int nStartPos + 0 +fpicker/source/office/fileview.hxx:161 + void SvtFileView::EnableDelete(_Bool) + _Bool bEnable + 1 +framework/inc/uielement/uicommanddescription.hxx:83 + void framework::UICommandDescription::UICommandDescription(const class com::sun::star::uno::Reference &,_Bool) + _Bool + 1 +helpcompiler/inc/HelpCompiler.hxx:58 + void fs::path::path(const class std::__cxx11::basic_string, class std::allocator > &,enum fs::convert) + enum fs::convert + 0 +hwpfilter/source/hfont.h:63 + const char * HWPFont::GetFontName(int,int) + int lang + 0 +hwpfilter/source/hwpfile.h:145 + void HWPFile::Read4b(void *,unsigned long) + unsigned long nmemb + 1 +i18npool/source/localedata/LocaleNode.hxx:74 + const class rtl::OUString & Attr::getValueByIndex(int) const + int idx + 0 +idlc/inc/errorhandler.hxx:86 + void ErrorHandler::warning0(enum WarningCode,const char *) + enum WarningCode e + 0 +idlc/source/errorhandler.cxx:399 + void errorHeader(enum ErrorCode,unsigned int) + enum ErrorCode eCode + 0 +include/avmedia/mediaplayer.hxx:51 + void avmedia::MediaFloater::setURL(const class rtl::OUString &,const class rtl::OUString &,_Bool) + _Bool bPlayImmediately + 1 +include/basegfx/DrawCommands.hxx:58 + void gfx::GradientInfo::GradientInfo(enum gfx::GradientType) + enum gfx::GradientType eType + 0 +include/basegfx/polygon/b2dpolygon.hxx:84 + void basegfx::B2DPolygon::insert(unsigned int,const class basegfx::B2DPoint &,unsigned int) + unsigned int nCount + 1 +include/basegfx/polygon/b2dpolygontools.hxx:91 + _Bool isInside(const class basegfx::B2DPolygon &,const class basegfx::B2DPolygon &,_Bool) + _Bool bWithBorder + 1 +include/basegfx/polygon/b2dpolygontools.hxx:299 + class basegfx::B2DPolygon createPolygonFromEllipse(const class basegfx::B2DPoint &,double,double,unsigned int) + unsigned int nStartQuadrant + 0 +include/basegfx/polygon/b2dpolygontools.hxx:367 + enum basegfx::B2VectorOrientation getOrientationForIndex(const class basegfx::B2DPolygon &,unsigned int) + unsigned int nIndex + 0 +include/basegfx/polygon/b2dpolygontools.hxx:374 + _Bool isPointOnPolygon(const class basegfx::B2DPolygon &,const class basegfx::B2DPoint &,_Bool) + _Bool bWithPoints + 1 +include/basegfx/polygon/b2dpolygontools.hxx:377 + _Bool isPointInTriangle(const class basegfx::B2DPoint &,const class basegfx::B2DPoint &,const class basegfx::B2DPoint &,const class basegfx::B2DPoint &,_Bool) + _Bool bWithBorder + 1 +include/basegfx/polygon/b2dpolypolygon.hxx:76 + void basegfx::B2DPolyPolygon::insert(unsigned int,const class basegfx::B2DPolygon &,unsigned int) + unsigned int nIndex + 0 +include/basegfx/polygon/b2dpolypolygon.hxx:76 + void basegfx::B2DPolyPolygon::insert(unsigned int,const class basegfx::B2DPolygon &,unsigned int) + unsigned int nCount + 1 +include/basegfx/polygon/b2dpolypolygon.hxx:77 + void basegfx::B2DPolyPolygon::append(const class basegfx::B2DPolygon &,unsigned int) + unsigned int nCount + 1 +include/basegfx/polygon/b2dpolypolygon.hxx:102 + void basegfx::B2DPolyPolygon::remove(unsigned int,unsigned int) + unsigned int nCount + 1 +include/basegfx/polygon/b2dpolypolygon.hxx:137 + shared_ptr basegfx::B2DPolyPolygon::addOrReplaceSystemDependentData(class basegfx::SystemDependentDataManager &,type-parameter-?-? &&...) const + ###3 + 0 +include/basegfx/polygon/b2dpolypolygon.hxx:137 + shared_ptr basegfx::B2DPolyPolygon::addOrReplaceSystemDependentData(class basegfx::SystemDependentDataManager &,type-parameter-?-? &&...) const + ###4 + 0 +include/basegfx/polygon/b2dpolypolygon.hxx:137 + shared_ptr basegfx::B2DPolyPolygon::addOrReplaceSystemDependentData(class basegfx::SystemDependentDataManager &,type-parameter-?-? &&...) const + ###5 + 0 +include/basegfx/polygon/b3dpolygon.hxx:71 + void basegfx::B3DPolygon::append(const class basegfx::B3DPoint &,unsigned int) + unsigned int nCount + 1 +include/basegfx/polygon/b3dpolygon.hxx:95 + void basegfx::B3DPolygon::append(const class basegfx::B3DPolygon &,unsigned int,unsigned int) + unsigned int nIndex + 0 +include/basegfx/polygon/b3dpolygon.hxx:95 + void basegfx::B3DPolygon::append(const class basegfx::B3DPolygon &,unsigned int,unsigned int) + unsigned int nCount + 0 +include/basegfx/polygon/b3dpolygon.hxx:98 + void basegfx::B3DPolygon::remove(unsigned int,unsigned int) + unsigned int nCount + 1 +include/basegfx/polygon/b3dpolygontools.hxx:100 + _Bool isInside(const class basegfx::B3DPolygon &,const class basegfx::B3DPoint &,_Bool) + _Bool bWithBorder + 0 +include/basegfx/polygon/b3dpolygontools.hxx:103 + _Bool isPointOnLine(const class basegfx::B3DPoint &,const class basegfx::B3DPoint &,const class basegfx::B3DPoint &,_Bool) + _Bool bWithPoints + 1 +include/basegfx/polygon/b3dpolypolygon.hxx:82 + void basegfx::B3DPolyPolygon::append(const class basegfx::B3DPolygon &,unsigned int) + unsigned int nCount + 1 +include/basegfx/range/b2ibox.hxx:71 + void basegfx::B2IBox::B2IBox(int,int,int,int) + int x1 + 0 +include/basegfx/range/b2ibox.hxx:71 + void basegfx::B2IBox::B2IBox(int,int,int,int) + int y1 + 0 +include/basegfx/utils/tools.hxx:118 + class basegfx::B2DPolyPolygon number2PolyPolygon(double,int,int,_Bool) + _Bool bLitSegments + 1 +include/basic/basmgr.hxx:138 + void BasicManager::BasicManager(class SotStorage &,const class rtl::OUString &,class StarBASIC *,const class rtl::OUString *,_Bool) + _Bool bDocMgr + 1 +include/basic/basrdll.hxx:37 + void BasicDLL::EnableBreak(_Bool) + _Bool bEnable + 1 +include/basic/sbstar.hxx:146 + class SbxVariable * StarBASIC::VBAFind(const class rtl::OUString &,enum SbxClassType) + enum SbxClassType t + 1 +include/basic/sbxobj.hxx:61 + class SbxVariable * SbxObject::FindQualified(const class rtl::OUString &,enum SbxClassType) + enum SbxClassType + 1 +include/basic/sbxobj.hxx:72 + void SbxObject::Remove(const class rtl::OUString &,enum SbxClassType) + enum SbxClassType + 1 +include/comphelper/configurationhelper.hxx:211 + class com::sun::star::uno::Any comphelper::ConfigurationHelper::readDirectKey(const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,enum comphelper::EConfigurationModes) + enum comphelper::EConfigurationModes eMode + 1 +include/comphelper/configurationhelper.hxx:227 + void comphelper::ConfigurationHelper::writeDirectKey(const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class com::sun::star::uno::Any &,enum comphelper::EConfigurationModes) + enum comphelper::EConfigurationModes eMode + 0 +include/comphelper/lok.hxx:47 + void setLocalRendering(_Bool) + _Bool bLocalRendering + 1 +include/comphelper/lok.hxx:72 + void setRangeHeaders(_Bool) + _Bool bTiledAnnotations + 1 +include/comphelper/parallelsort.hxx:285 + void s3sort(const type-parameter-?-?,const type-parameter-?-?,type-parameter-?-?,_Bool) + _Bool bThreaded + 1 +include/comphelper/profilezone.hxx:62 + void comphelper::ProfileZone::ProfileZone(const char *,_Bool) + _Bool bConsole + 0 +include/comphelper/property.hxx:52 + void ModifyPropertyAttributes(class com::sun::star::uno::Sequence &,const class rtl::OUString &,short,short) + short _nAddAttrib + 0 +include/comphelper/storagehelper.hxx:187 + class com::sun::star::uno::Reference comphelper::OStorageHelper::GetStorageAtPath(const class com::sun::star::uno::Reference &,const class rtl::OUString &,unsigned int,const class comphelper::LifecycleProxy &) + unsigned int nOpenMode + 1 +include/comphelper/unique_disposing_ptr.hxx:164 + void comphelper::unique_disposing_solar_mutex_reset_ptr::unique_disposing_solar_mutex_reset_ptr(const class com::sun::star::uno::Reference &,type-parameter-?-? *,_Bool) + _Bool bComponent + 1 +include/comphelper/unique_disposing_ptr.hxx:169 + void comphelper::unique_disposing_solar_mutex_reset_ptr::reset(type-parameter-?-? *) + type-parameter-?-? * p + 0 +include/connectivity/dbexception.hxx:312 + void throwSQLException(const class rtl::OUString &,enum dbtools::StandardSQLState,const class com::sun::star::uno::Reference &,const int) + const int _nErrorCode + 0 +include/connectivity/dbtools.hxx:331 + _Bool isDataSourcePropertyEnabled(const class com::sun::star::uno::Reference &,const class rtl::OUString &,_Bool) + _Bool _bDefault + 1 +include/connectivity/dbtools.hxx:623 + class rtl::OUString createStandardCreateStatement(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,class dbtools::ISQLStatementHelper *,class std::basic_string_view >) + class dbtools::ISQLStatementHelper * _pHelper + 0 +include/connectivity/sqlscan.hxx:49 + void connectivity::OSQLScanner::prepareScan(const class rtl::OUString &,const class connectivity::IParseContext *,_Bool) + _Bool bInternational + 1 +include/cppcanvas/color.hxx:61 + int makeColorARGB(unsigned char,unsigned char,unsigned char,unsigned char) + unsigned char nAlpha + 0 +include/cui/cuicharmap.hxx:147 + void SvxCharacterMap::SvxCharacterMap(class weld::Widget *,const class SfxItemSet *,const class com::sun::star::uno::Reference &) + const class SfxItemSet * pSet + 0 +include/drawinglayer/processor2d/hittestprocessor2d.hxx:78 + void drawinglayer::processor2d::HitTestProcessor2D::collectHitStack(_Bool) + _Bool bCollect + 1 +include/drawinglayer/XShapeDumper.hxx:23 + class rtl::OUString XShapeDumper::dump(const class com::sun::star::uno::Reference &,_Bool) + _Bool bDumpInteropProperties + 0 +include/drawinglayer/XShapeDumper.hxx:24 + class rtl::OUString XShapeDumper::dump(const class com::sun::star::uno::Reference &,_Bool) + _Bool bDumpInteropProperties + 0 +include/editeng/borderline.hxx:169 + class Color editeng::SvxBorderLine::GetColorOut(_Bool) const + _Bool bLeftOrTop + 1 +include/editeng/borderline.hxx:170 + class Color editeng::SvxBorderLine::GetColorIn(_Bool) const + _Bool bLeftOrTop + 1 +include/editeng/boxitem.hxx:114 + _Bool SvxBoxItem::HasBorder(_Bool) const + _Bool bTreatPaddingAsBorder + 1 +include/editeng/editeng.hxx:548 + void EditEngine::dumpAsXmlEditDoc(struct _xmlTextWriter *) const + struct _xmlTextWriter * pWriter + 0 +include/editeng/editeng.hxx:573 + class EditPaM EditEngine::CursorLeft(const class EditPaM &,unsigned short) + unsigned short nCharacterIteratorMode + 0 +include/editeng/editobj.hxx:120 + const class SvxFieldData * EditTextObject::GetFieldData(int,unsigned long,int) const + int nPara + 0 +include/editeng/editobj.hxx:120 + const class SvxFieldData * EditTextObject::GetFieldData(int,unsigned long,int) const + unsigned long nPos + 0 +include/editeng/editobj.hxx:120 + const class SvxFieldData * EditTextObject::GetFieldData(int,unsigned long,int) const + int nType + 1 +include/editeng/edtdlg.hxx:79 + enum editeng::HangulHanjaConversion::ConversionDirection AbstractHangulHanjaConversionDialog::GetDirection(enum editeng::HangulHanjaConversion::ConversionDirection) const + enum editeng::HangulHanjaConversion::ConversionDirection _eDefaultDirection + 0 +include/editeng/outliner.hxx:241 + void OutlinerView::SelectRange(int,int) + int nFirst + 0 +include/editeng/outliner.hxx:625 + _Bool Outliner::ImpCanDeleteSelectedPages(class OutlinerView *,int,int) + int nPages + 1 +include/editeng/pmdlitem.hxx:40 + void SvxPageModelItem::SvxPageModelItem(unsigned short) + unsigned short nWh + 0 +include/editeng/splwrap.hxx:73 + void SvxSpellWrapper::SvxSpellWrapper(class weld::Widget *,const _Bool,const _Bool) + const _Bool bIsAllRight + 0 +include/editeng/txtrange.hxx:61 + void TextRanger::TextRanger(const class basegfx::B2DPolyPolygon &,const class basegfx::B2DPolyPolygon *,unsigned short,unsigned short,unsigned short,_Bool,_Bool,_Bool) + _Bool bInner + 1 +include/editeng/txtrange.hxx:61 + void TextRanger::TextRanger(const class basegfx::B2DPolyPolygon &,const class basegfx::B2DPolyPolygon *,unsigned short,unsigned short,unsigned short,_Bool,_Bool,_Bool) + _Bool bVert + 0 +include/filter/msfilter/escherex.hxx:493 + void EscherExAtom::EscherExAtom(class SvStream &,const unsigned short,const unsigned short,const unsigned char) + const unsigned char nVersion + 0 +include/filter/msfilter/escherex.hxx:585 + void EscherGraphicProvider::WriteBlibStoreEntry(class SvStream &,unsigned int,unsigned int) + unsigned int nBlipId + 1 +include/filter/msfilter/escherex.hxx:795 + void EscherPropertyContainer::CreateFillProperties(const class com::sun::star::uno::Reference &,_Bool,const class com::sun::star::uno::Reference &) + _Bool bEdge + 1 +include/filter/msfilter/escherex.hxx:1139 + void EscherEx::EndAtom(unsigned short,int,int) + int nRecVersion + 0 +include/filter/msfilter/msdffimp.hxx:711 + void SvxMSDffManager::ExchangeInShapeOrder(const class SdrObject *,unsigned long,class SdrObject *) const + unsigned long nTxBx + 0 +include/filter/msfilter/msdffimp.hxx:764 + void SvxMSDffShapeInfo::SvxMSDffShapeInfo(unsigned long,unsigned int,unsigned short,unsigned short) + unsigned int nId + 0 +include/filter/msfilter/msdffimp.hxx:764 + void SvxMSDffShapeInfo::SvxMSDffShapeInfo(unsigned long,unsigned int,unsigned short,unsigned short) + unsigned short nSeqId + 0 +include/filter/msfilter/msdffimp.hxx:764 + void SvxMSDffShapeInfo::SvxMSDffShapeInfo(unsigned long,unsigned int,unsigned short,unsigned short) + unsigned short nBoxId + 0 +include/formula/FormulaCompiler.hxx:325 + void formula::FormulaCompiler::PushTokenArray(class formula::FormulaTokenArray *,_Bool) + _Bool + 1 +include/formula/token.hxx:234 + void formula::FormulaByteToken::FormulaByteToken(enum OpCode,unsigned char,enum formula::StackVar,enum formula::ParamClass) + enum formula::ParamClass c + 0 +include/formula/tokenarray.hxx:168 + void formula::FormulaTokenArrayReferencesIterator::FormulaTokenArrayReferencesIterator(const class formula::FormulaTokenArrayStandardRange &,enum formula::FormulaTokenArrayReferencesIterator::Dummy) + enum formula::FormulaTokenArrayReferencesIterator::Dummy + 0 +include/formula/vectortoken.hxx:50 + void formula::VectorRefArray::VectorRefArray(enum formula::VectorRefArray::InitInvalid) + enum formula::VectorRefArray::InitInvalid + 0 +include/i18nutil/widthfolding.hxx:48 + class rtl::OUString i18nutil::widthfolding::compose_ja_voiced_sound_marks(const class rtl::OUString &,int,int,class com::sun::star::uno::Sequence &,_Bool,int) + int startPos + 0 +include/linguistic/misc.hxx:131 + _Bool IsUpper(const class rtl::OUString &,int,int,struct o3tl::strong_int) + int nPos + 0 +include/o3tl/strong_int.hxx:86 + void o3tl::strong_int::strong_int(type-parameter-?-?,typename enable_if::value, int>::type) + typename enable_if::value, int>::type + 0 +include/o3tl/strong_int.hxx:110 + strong_int o3tl::strong_int::operator++(int) + ###1 + 0 +include/o3tl/unit_conversion.hxx:205 + auto convert(type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,_Bool &,long) + long nDefault + 0 +include/o3tl/unit_conversion.hxx:213 + auto convertSaturate(type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) + type-parameter-?-? from + 0 +include/oox/drawingml/shape.hxx:108 + void oox::drawingml::Shape::Shape(const char *,_Bool) + _Bool bDefaultHeight + 1 +include/oox/export/vmlexport.hxx:152 + const class rtl::OString & oox::vml::VMLExport::AddInlineSdrObject(const class SdrObject &,const _Bool) + const _Bool bOOxmlExport + 1 +include/oox/helper/attributelist.hxx:162 + long oox::AttributeList::getHyper(int,long) const + long nDefault + 0 +include/oox/helper/containerhelper.hxx:98 + void oox::Matrix::Matrix(typename vector >::size_type,typename vector >::size_type) + typename vector >::size_type nHeight + 1 +include/oox/helper/containerhelper.hxx:114 + typename vector >::const_reference oox::Matrix::operator()(typename vector >::size_type,typename vector >::size_type) const + typename vector >::size_type nY + 0 +include/oox/helper/helper.hxx:115 + type-parameter-?-? getIntervalValue(type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) + type-parameter-?-? nBegin + 0 +include/oox/mathml/importutils.hxx:212 + void oox::formulaimport::XmlStream::skipElementInternal(int,_Bool) + _Bool silent + 0 +include/oox/ole/olestorage.hxx:46 + void oox::ole::OleStorage::OleStorage(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,_Bool) + _Bool bBaseStreamAccess + 0 +include/oox/ole/olestorage.hxx:59 + void oox::ole::OleStorage::OleStorage(const class oox::ole::OleStorage &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,_Bool) + _Bool bReadOnly + 1 +include/oox/ole/vbacontrol.hxx:189 + void oox::ole::VbaUserForm::VbaUserForm(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class oox::GraphicHelper &,_Bool) + _Bool bDefaultColorBgr + 1 +include/oox/ole/vbaexport.hxx:90 + void VBACompressionChunk::SetFlagBit(unsigned long,_Bool,unsigned char &) + _Bool bVal + 1 +include/oox/vml/vmldrawing.hxx:69 + void oox::vml::OleObjectInfo::OleObjectInfo(_Bool) + _Bool bDmlShape + 0 +include/oox/vml/vmldrawing.hxx:96 + void oox::vml::Drawing::Drawing(class oox::core::XmlFilterBase &,const class com::sun::star::uno::Reference &,enum oox::vml::DrawingType) + enum oox::vml::DrawingType eType + 1 +include/oox/vml/vmlformatting.hxx:126 + int decodeMeasureToHmm(const class oox::GraphicHelper &,const class rtl::OUString &,int,_Bool,_Bool) + int nRefValue + 0 +include/opencl/openclwrapper.hxx:61 + _Bool buildProgramFromBinary(const char *,struct openclwrapper::GPUEnv *,const char *,int) + int idx + 0 +include/opencl/openclwrapper.hxx:86 + void setOpenCLCmdQueuePosition(int) + int nPos + 0 +include/package/Deflater.hxx:42 + int ZipUtils::Deflater::doDeflateBytes(class com::sun::star::uno::Sequence &,int,int) + int nNewOffset + 0 +include/sax/tools/converter.hxx:266 + _Bool sax::Converter::parseDateOrDateTime(struct com::sun::star::util::Date *,struct com::sun::star::util::DateTime &,_Bool &,class std::optional *,class std::basic_string_view >) + struct com::sun::star::util::Date * pDate + 0 +include/sax/tools/converter.hxx:266 + _Bool sax::Converter::parseDateOrDateTime(struct com::sun::star::util::Date *,struct com::sun::star::util::DateTime &,_Bool &,class std::optional *,class std::basic_string_view >) + class std::optional * pTimeZoneOffset + 0 +include/sax/tools/converter.hxx:280 + short sax::Converter::GetUnitFromString(class std::basic_string_view >,short) + short nDefaultUnit + 0 +include/sfx2/app.hxx:107 + void SfxApplication::RegisterInterface(const class SfxModule *) + const class SfxModule * pMod + 0 +include/sfx2/dispatch.hxx:151 + enum ToolbarId SfxDispatcher::GetObjectBarId(unsigned short) const + unsigned short nPos + 1 +include/sfx2/docfile.hxx:167 + void SfxMedium::DisableFileSync(_Bool) + _Bool bDisableFileSync + 1 +include/sfx2/event.hxx:239 + void SfxPrintingHint::SfxPrintingHint(enum com::sun::star::view::PrintableState,const class com::sun::star::uno::Sequence &,class SfxObjectShell *,const class com::sun::star::uno::Reference &) + enum com::sun::star::view::PrintableState nState + 0 +include/sfx2/fcontnr.hxx:109 + void SfxFilterMatcherIter::SfxFilterMatcherIter(const class SfxFilterMatcher &,enum SfxFilterFlags,enum SfxFilterFlags) + enum SfxFilterFlags nMask + 0 +include/sfx2/filedlghelper.hxx:96 + void sfx2::FileDialogHelper::FileDialogHelper(short,enum FileDialogFlags,const class rtl::OUString &,enum SfxFilterFlags,enum SfxFilterFlags,class weld::Window *) + enum SfxFilterFlags nDont + 0 +include/sfx2/lokhelper.hxx:106 + void SfxLokHelper::notifyDocumentSizeChangedAllViews(class vcl::ITiledRenderable *,_Bool) + _Bool bInvalidateAll + 1 +include/sfx2/module.hxx:61 + void SfxModule::RegisterInterface(const class SfxModule *) + const class SfxModule * pMod + 0 +include/sfx2/notebookbar/SfxNotebookBar.hxx:68 + void sfx2::SfxNotebookBar::ShowMenubar(const class SfxViewFrame *,_Bool) + _Bool bShow + 1 +include/sfx2/objsh.hxx:224 + void SfxObjectShell::RegisterInterface(const class SfxModule *) + const class SfxModule * pMod + 0 +include/sfx2/objsh.hxx:675 + void SfxObjectShell::AppendInfoBarWhenReady(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,enum InfobarType,_Bool) + _Bool bShowCloseButton + 1 +include/sfx2/opengrf.hxx:44 + void SvxOpenGraphicDialog::SetPath(const class rtl::OUString &,_Bool) + _Bool bLinkState + 1 +include/sfx2/opengrf.hxx:49 + void SvxOpenGraphicDialog::EnableLink(_Bool) + _Bool + 0 +include/sfx2/passwd.hxx:125 + void SfxPasswordDialog::ShowMinLengthText(_Bool) + _Bool bShow + 0 +include/sfx2/request.hxx:61 + void SfxRequest::SfxRequest(const class SfxSlot *,const class com::sun::star::uno::Sequence &,enum SfxCallMode,class SfxItemPool &) + enum SfxCallMode nCallMode + 1 +include/sfx2/request.hxx:64 + void SfxRequest::SfxRequest(unsigned short,enum SfxCallMode,const class SfxAllItemSet &,const class SfxAllItemSet &) + enum SfxCallMode nCallMode + 1 +include/sfx2/request.hxx:99 + void SfxRequest::AllowRecording(_Bool) + _Bool + 1 +include/sfx2/sfxdlg.hxx:133 + class VclPtr SfxAbstractDialogFactory::CreateEditObjectDialog(class weld::Window *,const class rtl::OUString &,const class com::sun::star::uno::Reference &) + class weld::Window * pParent + 0 +include/sfx2/sfxdlg.hxx:142 + void SfxAbstractDialogFactory::ShowAsyncScriptErrorDialog(class weld::Window *,const class com::sun::star::uno::Any &) + class weld::Window * pParent + 0 +include/sfx2/sidebar/FocusManager.hxx:110 + _Bool sfx2::sidebar::FocusManager::IsPanelTitleVisible(const int) const + const int nPanelIndex + 0 +include/sfx2/thumbnailview.hxx:228 + void ThumbnailView::ShowTooltips(_Bool) + _Bool bShowTooltips + 1 +include/sfx2/thumbnailview.hxx:230 + void ThumbnailView::DrawMnemonics(_Bool) + _Bool bDrawMnemonics + 1 +include/sfx2/viewfrm.hxx:77 + void SfxViewFrame::RegisterInterface(const class SfxModule *) + const class SfxModule * pMod + 0 +include/sfx2/viewsh.hxx:194 + void SfxViewShell::RegisterInterface(const class SfxModule *) + const class SfxModule * pMod + 0 +include/sfx2/weldutils.hxx:52 + void ToolbarUnoDispatcher::ToolbarUnoDispatcher(class weld::Toolbar &,class weld::Builder &,const class com::sun::star::uno::Reference &,_Bool) + _Bool bSideBar + 1 +include/sot/stg.hxx:158 + void Storage::Storage(const class rtl::OUString &,enum StreamMode,_Bool) + _Bool bDirect + 1 +include/sot/stg.hxx:250 + void UCBStorage::UCBStorage(const class ucbhelper::Content &,const class rtl::OUString &,enum StreamMode,_Bool,_Bool) + enum StreamMode nMode + 1 +include/sot/stg.hxx:250 + void UCBStorage::UCBStorage(const class ucbhelper::Content &,const class rtl::OUString &,enum StreamMode,_Bool,_Bool) + _Bool bDirect + 0 +include/sot/stg.hxx:250 + void UCBStorage::UCBStorage(const class ucbhelper::Content &,const class rtl::OUString &,enum StreamMode,_Bool,_Bool) + _Bool bIsRoot + 1 +include/sot/stg.hxx:256 + void UCBStorage::UCBStorage(const class rtl::OUString &,enum StreamMode,_Bool,_Bool) + _Bool bDirect + 1 +include/sot/stg.hxx:256 + void UCBStorage::UCBStorage(const class rtl::OUString &,enum StreamMode,_Bool,_Bool) + _Bool bIsRoot + 1 +include/sot/stg.hxx:261 + void UCBStorage::UCBStorage(const class rtl::OUString &,enum StreamMode,_Bool,_Bool,_Bool,const class com::sun::star::uno::Reference &) + _Bool bIsRoot + 0 +include/sot/stg.hxx:271 + void UCBStorage::UCBStorage(class SvStream &,_Bool) + _Bool bDirect + 0 +include/store/store.hxx:103 + storeError store::OStoreStream::writeAt(unsigned int,const void *,unsigned int,unsigned int &) + unsigned int nOffset + 0 +include/svl/adrparse.hxx:42 + const class rtl::OUString & SvAddressParser::GetEmailAddress(int) const + int nIndex + 0 +include/svl/gridprinter.hxx:29 + void svl::GridPrinter::GridPrinter(unsigned long,unsigned long,_Bool) + _Bool bPrint + 0 +include/svl/itempool.hxx:151 + const type-parameter-?-? & SfxItemPool::Put(unique_ptr >,unsigned short) + unsigned short nWhich + 0 +include/svl/itemset.hxx:172 + const type-parameter-?-? * SfxItemSet::GetItem(const class SfxItemSet *,TypedWhichId,_Bool) + _Bool bSearchInParent + 0 +include/svl/svdde.hxx:131 + void DdeLink::DdeLink(class DdeConnection &,const class rtl::OUString &,long) + long + 0 +include/svl/urihelper.hxx:51 + class rtl::OUString SmartRel2Abs(const class INetURLObject &,const class rtl::OUString &,const class Link &,_Bool,_Bool,enum INetURLObject::EncodeMechanism,enum INetURLObject::DecodeMechanism,unsigned short,enum FSysStyle) + enum INetURLObject::EncodeMechanism eEncodeMechanism + 1 +include/svl/urihelper.hxx:116 + class rtl::OUString FindFirstURLInText(const class rtl::OUString &,int &,int &,const class CharClass &,enum INetURLObject::EncodeMechanism,unsigned short) + enum INetURLObject::EncodeMechanism eMechanism + 1 +include/svl/urihelper.hxx:148 + class rtl::OUString removePassword(const class rtl::OUString &,enum INetURLObject::EncodeMechanism,enum INetURLObject::DecodeMechanism,unsigned short) + enum INetURLObject::EncodeMechanism eEncodeMechanism + 1 +include/svl/zforlist.hxx:906 + const class NfKeywordTable & SvNumberFormatter::GetKeywords(unsigned int) + unsigned int nKey + 0 +include/svl/zformat.hxx:300 + class rtl::OUString SvNumberformat::GetPercentString(unsigned short) const + unsigned short nNumFor + 0 +include/svl/zformat.hxx:411 + int SvNumberformat::GetQuoteEnd(const class rtl::OUString &,int,char16_t,char16_t) + char16_t cEscIn + 0 +include/svl/zformat.hxx:421 + int SvNumberformat::InsertBlanks(class rtl::OUString &,int,char16_t) + int nPos + 0 +include/svl/zformat.hxx:487 + _Bool SvNumberformat::IsIso8601(unsigned short) const + unsigned short nNumFor + 0 +include/svtools/HtmlWriter.hxx:37 + void HtmlWriter::prettyPrint(_Bool) + _Bool b + 0 +include/svtools/inettbc.hxx:80 + void SvtURLBox::select_entry_region(int,int) + int nStartPos + 0 +include/svtools/ruler.hxx:731 + void Ruler::SetWinPos(long,long) + long nWidth + 0 +include/svtools/stringtransfer.hxx:61 + void svt::OStringTransfer::StartStringDrag(const class rtl::OUString &,class vcl::Window *,signed char) + signed char _nDragSourceActions + 1 +include/svtools/valueset.hxx:320 + void ValueSet::EnableFullItemMode(_Bool) + _Bool bFullMode + 0 +include/svtools/valueset.hxx:358 + void ValueSet::SetItemColor(unsigned short,const class Color &) + unsigned short nItemId + 1 +include/svx/algitem.hxx:36 + void SvxOrientationItem::SvxOrientationItem(const enum SvxCellOrientation,const unsigned short) + const unsigned short nId + 0 +include/svx/algitem.hxx:40 + void SvxOrientationItem::SvxOrientationItem(struct o3tl::strong_int,_Bool,const unsigned short) + const unsigned short nId + 0 +include/svx/ctredlin.hxx:219 + void SvxTPFilter::SelectedAuthorPos(int) + int nPos + 0 +include/svx/ctredlin.hxx:242 + void SvxTPFilter::CheckAction(_Bool) + _Bool bFlag + 0 +include/svx/dlgctrl.hxx:137 + void SvxRectCtl::DoCompletelyDisable(_Bool) + _Bool bNew + 1 +include/svx/extrusionbar.hxx:39 + void svx::ExtrusionBar::RegisterInterface(const class SfxModule *) + const class SfxModule * pMod + 0 +include/svx/fmshell.hxx:93 + void FmFormShell::RegisterInterface(const class SfxModule *) + const class SfxModule * pMod + 0 +include/svx/fmtools.hxx:76 + void CursorWrapper::CursorWrapper(const class com::sun::star::uno::Reference &,_Bool) + _Bool bUseCloned + 0 +include/svx/fmtools.hxx:141 + void FmXDisposeListener::disposing(short) + short _nId + 0 +include/svx/fmview.hxx:88 + void FmFormView::createControlLabelPair(const class OutputDevice *,int,int,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,enum SdrObjKind,enum SdrInventor,enum SdrObjKind,class SdrModel &,class std::unique_ptr &,class std::unique_ptr &) + int _nYOffsetMM + 0 +include/svx/fontworkbar.hxx:41 + void svx::FontworkBar::RegisterInterface(const class SfxModule *) + const class SfxModule * pMod + 0 +include/svx/framelink.hxx:117 + void svx::frame::Style::Style(double,double,double,enum SvxBorderLineStyle,double) + double nD + 0 +include/svx/framelink.hxx:117 + void svx::frame::Style::Style(double,double,double,enum SvxBorderLineStyle,double) + double nS + 0 +include/svx/framelink.hxx:117 + void svx::frame::Style::Style(double,double,double,enum SvxBorderLineStyle,double) + enum SvxBorderLineStyle nType + 0 +include/svx/frmsel.hxx:144 + void svx::FrameSelector::SelectAllBorders(_Bool) + _Bool bSelect + 0 +include/svx/gridctrl.hxx:395 + void DbGridControl::RemoveRows(_Bool) + _Bool bNewCursor + 0 +include/svx/IAccessibleParent.hxx:81 + _Bool accessibility::IAccessibleParent::ReplaceChild(class accessibility::AccessibleShape *,const class com::sun::star::uno::Reference &,const long,const class accessibility::AccessibleShapeTreeInfo &) + const long _nIndex + 0 +include/svx/nbdtmg.hxx:130 + unsigned short svx::sidebar::NBOTypeMgrBase::GetNBOIndexForNumRule(class SvxNumRule &,unsigned short,unsigned short) + unsigned short nFromIndex + 0 +include/svx/nbdtmg.hxx:131 + void svx::sidebar::NBOTypeMgrBase::RelplaceNumRule(class SvxNumRule &,unsigned short,unsigned short) + unsigned short mLevel + 1 +include/svx/nbdtmg.hxx:133 + class rtl::OUString svx::sidebar::NBOTypeMgrBase::GetDescription(unsigned short,_Bool) + _Bool isDefault + 1 +include/svx/postattr.hxx:33 + void SvxPostItAuthorItem::SvxPostItAuthorItem(unsigned short) + unsigned short nWhich + 0 +include/svx/postattr.hxx:53 + void SvxPostItDateItem::SvxPostItDateItem(unsigned short) + unsigned short nWhich + 0 +include/svx/postattr.hxx:72 + void SvxPostItTextItem::SvxPostItTextItem(unsigned short) + unsigned short nWhich + 0 +include/svx/postattr.hxx:93 + void SvxPostItIdItem::SvxPostItIdItem(unsigned short) + unsigned short nWhich + 0 +include/svx/relfld.hxx:43 + void SvxRelativeField::EnableRelativeMode(unsigned short,unsigned short) + unsigned short nMin + 0 +include/svx/relfld.hxx:51 + int SvxRelativeField::get_min(enum FieldUnit) const + enum FieldUnit eValueUnit + 0 +include/svx/relfld.hxx:64 + void SvxRelativeField::SetFieldUnit(enum FieldUnit,_Bool) + _Bool bAll + 0 +include/svx/rulritem.hxx:123 + void SvxColumnDescription::SvxColumnDescription(long,long,_Bool) + _Bool bVis + 1 +include/svx/sdr/overlay/overlayobject.hxx:120 + void sdr::overlay::OverlayObject::allowAntiAliase(_Bool) + _Bool bNew + 0 +include/svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx:104 + void drawinglayer::primitive2d::SdrFrameBorderPrimitive2D::SdrFrameBorderPrimitive2D(class std::shared_ptr > > &,_Bool) + _Bool bForceToSingleDiscreteUnit + 1 +include/svx/svdhlpln.hxx:43 + void SdrHelpLine::SdrHelpLine(enum SdrHelpLineKind) + enum SdrHelpLineKind eNewKind + 0 +include/svx/svditer.hxx:51 + void SdrObjListIter::SdrObjListIter(const class SdrObjList *,_Bool,enum SdrIterMode,_Bool) + enum SdrIterMode eMode + 0 +include/svx/svditer.hxx:51 + void SdrObjListIter::SdrObjListIter(const class SdrObjList *,_Bool,enum SdrIterMode,_Bool) + _Bool bReverse + 0 +include/svx/svditer.hxx:55 + void SdrObjListIter::SdrObjListIter(const class SdrObject &,enum SdrIterMode,_Bool) + _Bool bReverse + 0 +include/svx/svdundo.hxx:101 + class SdrUndoAction * SdrUndoGroup::GetAction(int) const + int nNum + 0 +include/svx/svdview.hxx:178 + void SdrView::EnableExtendedKeyInputDispatcher(_Bool) + _Bool bOn + 0 +include/svx/svx3ditems.hxx:66 + void Svx3DReducedLineGeometryItem::Svx3DReducedLineGeometryItem(_Bool) + _Bool bVal + 0 +include/svx/svxdlg.hxx:82 + void AbstractSvxZoomDialog::HideButton(enum ZoomButtonId) + enum ZoomButtonId nBtnId + 1 +include/svx/SvxPresetListBox.hxx:57 + void SvxPresetListBox::FillPresetListBox(class XGradientList &,unsigned int) + unsigned int nStartIndex + 1 +include/svx/SvxPresetListBox.hxx:58 + void SvxPresetListBox::FillPresetListBox(class XHatchList &,unsigned int) + unsigned int nStartIndex + 1 +include/svx/SvxPresetListBox.hxx:59 + void SvxPresetListBox::FillPresetListBox(class XBitmapList &,unsigned int) + unsigned int nStartIndex + 1 +include/svx/SvxPresetListBox.hxx:60 + void SvxPresetListBox::FillPresetListBox(class XPatternList &,unsigned int) + unsigned int nStartIndex + 1 +include/svx/sxenditm.hxx:60 + void SdrEdgeNode1GlueDistItem::SdrEdgeNode1GlueDistItem(long) + long nVal + 0 +include/svx/sxenditm.hxx:66 + void SdrEdgeNode2GlueDistItem::SdrEdgeNode2GlueDistItem(long) + long nVal + 0 +include/svx/sxmtfitm.hxx:32 + void SdrMeasureTextIsFixedAngleItem::SdrMeasureTextIsFixedAngleItem(_Bool) + _Bool bOn + 0 +include/svx/sxmtritm.hxx:42 + void SdrMeasureTextUpsideDownItem::SdrMeasureTextUpsideDownItem(_Bool) + _Bool bOn + 0 +include/svx/unopool.hxx:44 + void SvxUnoDrawPool::SvxUnoDrawPool(class SdrModel *,int) + int nServiceId + 1 +include/svx/unoshtxt.hxx:54 + void SvxTextEditSource::SvxTextEditSource(class SdrObject &,class SdrText *,class SdrView &,const class OutputDevice &) + class SdrText * pText + 0 +include/svx/verttexttbxctrl.hxx:31 + void SvxVertCTLTextTbxCtrl_Base::ImplInheritanceHelper(const class com::sun::star::uno::Reference &,nullptr_t &&,class rtl::OUString &&) + nullptr_t && + 0 +include/svx/xflbmsli.hxx:29 + void XFillBmpSizeLogItem::XFillBmpSizeLogItem(_Bool) + _Bool bLog + 1 +include/svx/xflftrit.hxx:40 + void XFillFloatTransparenceItem::XFillFloatTransparenceItem(const class rtl::OUString &,const class XGradient &,_Bool) + _Bool bEnable + 1 +include/svx/xtable.hxx:217 + class rtl::Reference XPropertyList::CreatePropertyListFromURL(enum XPropertyListType,const class rtl::OUString &) + enum XPropertyListType t + 0 +include/test/sheet/xactivationbroadcaster.hxx:24 + class com::sun::star::uno::Reference apitest::XActivationBroadcaster::getXSpreadsheet(const short) + const short nNumber + 1 +include/test/sheet/xdocumentauditing.hxx:36 + _Bool apitest::XDocumentAuditing::hasRightAmountOfShapes(const class com::sun::star::uno::Reference &,int,int) + int nShapes + 1 +include/test/sheet/xnamedranges.hxx:39 + class com::sun::star::uno::Reference apitest::XNamedRanges::getXNamedRanges(int) + int nSheet + 1 +include/test/text/textcontent.hxx:25 + void apitest::TextContent::TextContent(const enum com::sun::star::text::TextContentAnchorType,const enum com::sun::star::text::TextContentAnchorType,const enum com::sun::star::text::WrapTextMode,const enum com::sun::star::text::WrapTextMode) + const enum com::sun::star::text::TextContentAnchorType aExpectedTCAT + 1 +include/test/text/textcontent.hxx:25 + void apitest::TextContent::TextContent(const enum com::sun::star::text::TextContentAnchorType,const enum com::sun::star::text::TextContentAnchorType,const enum com::sun::star::text::WrapTextMode,const enum com::sun::star::text::WrapTextMode) + const enum com::sun::star::text::TextContentAnchorType aNewTCAT + 1 +include/test/text/textcontent.hxx:25 + void apitest::TextContent::TextContent(const enum com::sun::star::text::TextContentAnchorType,const enum com::sun::star::text::TextContentAnchorType,const enum com::sun::star::text::WrapTextMode,const enum com::sun::star::text::WrapTextMode) + const enum com::sun::star::text::WrapTextMode aExpectedWTM + 0 +include/test/text/textcontent.hxx:25 + void apitest::TextContent::TextContent(const enum com::sun::star::text::TextContentAnchorType,const enum com::sun::star::text::TextContentAnchorType,const enum com::sun::star::text::WrapTextMode,const enum com::sun::star::text::WrapTextMode) + const enum com::sun::star::text::WrapTextMode aNewWTM + 0 +include/tools/color.hxx:87 + void Color::Color(enum ColorTransparencyTag,unsigned int) + enum ColorTransparencyTag + 0 +include/tools/color.hxx:97 + void Color::Color(enum ColorTransparencyTag,unsigned char,unsigned char,unsigned char,unsigned char) + enum ColorTransparencyTag + 0 +include/tools/color.hxx:101 + void Color::Color(enum ColorAlphaTag,unsigned char,unsigned char,unsigned char,unsigned char) + enum ColorAlphaTag + 0 +include/tools/date.hxx:71 + void Date::Date(enum Date::DateInitEmpty) + enum Date::DateInitEmpty + 0 +include/tools/date.hxx:72 + void Date::Date(enum Date::DateInitSystem) + enum Date::DateInitSystem + 0 +include/tools/datetime.hxx:42 + void DateTime::DateTime(enum DateTime::DateTimeInitEmpty) + enum DateTime::DateTimeInitEmpty + 0 +include/tools/datetime.hxx:43 + void DateTime::DateTime(enum DateTime::DateTimeInitSystem) + enum DateTime::DateTimeInitSystem + 0 +include/tools/fract.hxx:44 + void Fraction::Fraction(type-parameter-?-?,type-parameter-?-?,typename enable_if::value && std::is_integral::value, int>::type) + typename enable_if::value && std::is_integral::value, int>::type + 0 +include/tools/stream.hxx:670 + void SvMemoryStream::ObjectOwnsMemory(_Bool) + _Bool bOwn + 1 +include/tools/time.hxx:67 + void tools::Time::Time(enum tools::Time::TimeInitEmpty) + enum tools::Time::TimeInitEmpty + 0 +include/tools/time.hxx:69 + void tools::Time::Time(enum tools::Time::TimeInitSystem) + enum tools::Time::TimeInitSystem + 0 +include/tools/urlobj.hxx:344 + class rtl::OUString INetURLObject::GetAbsURL(const class rtl::OUString &,const class rtl::OUString &,enum INetURLObject::EncodeMechanism,enum INetURLObject::DecodeMechanism,unsigned short) + enum INetURLObject::EncodeMechanism eEncodeMechanism + 1 +include/tools/urlobj.hxx:344 + class rtl::OUString INetURLObject::GetAbsURL(const class rtl::OUString &,const class rtl::OUString &,enum INetURLObject::EncodeMechanism,enum INetURLObject::DecodeMechanism,unsigned short) + enum INetURLObject::DecodeMechanism eDecodeMechanism + 1 +include/tools/urlobj.hxx:351 + class rtl::OUString INetURLObject::GetRelURL(const class rtl::OUString &,const class rtl::OUString &,enum INetURLObject::EncodeMechanism,enum INetURLObject::DecodeMechanism,unsigned short,enum FSysStyle) + enum INetURLObject::EncodeMechanism eEncodeMechanism + 1 +include/tools/urlobj.hxx:826 + class rtl::OUString INetURLObject::encode(const class rtl::OUString &,enum INetURLObject::Part,enum INetURLObject::EncodeMechanism,unsigned short) + enum INetURLObject::EncodeMechanism eMechanism + 0 +include/unotools/calendarwrapper.hxx:61 + void CalendarWrapper::loadDefaultCalendar(const struct com::sun::star::lang::Locale &,_Bool) + _Bool bTimeZoneUTC + 1 +include/unotools/calendarwrapper.hxx:63 + void CalendarWrapper::loadCalendar(const class rtl::OUString &,const struct com::sun::star::lang::Locale &,_Bool) + _Bool bTimeZoneUTC + 1 +include/unotools/charclass.hxx:130 + class rtl::OUString CharClass::titlecase(const class rtl::OUString &,int,int) const + int nPos + 0 +include/unotools/charclass.hxx:173 + _Bool CharClass::isAlphaNumeric(const class rtl::OUString &,int) const + int nPos + 0 +include/unotools/cmdoptions.hxx:86 + _Bool SvtCommandOptions::HasEntries(enum SvtCommandOptions::CmdOption) const + enum SvtCommandOptions::CmdOption eOption + 0 +include/unotools/cmdoptions.hxx:96 + _Bool SvtCommandOptions::Lookup(enum SvtCommandOptions::CmdOption,const class rtl::OUString &) const + enum SvtCommandOptions::CmdOption eOption + 0 +include/unotools/confignode.hxx:254 + class utl::OConfigurationTreeRoot utl::OConfigurationTreeRoot::tryCreateWithComponentContext(const class com::sun::star::uno::Reference &,const class rtl::OUString &,int,enum utl::OConfigurationTreeRoot::CREATION_MODE) + enum utl::OConfigurationTreeRoot::CREATION_MODE _eMode + 1 +include/unotools/fontdefs.hxx:55 + void ConvertChar::RecodeString(class rtl::OUString &,int,int) const + int nIndex + 0 +include/unotools/historyoptions.hxx:93 + void SvtHistoryOptions::DeleteItem(enum EHistoryType,const class rtl::OUString &) + enum EHistoryType eHistory + 0 +include/unotools/localedatawrapper.hxx:305 + double LocaleDataWrapper::stringToDouble(const char16_t *,const char16_t *,_Bool,enum rtl_math_ConversionStatus *,const char16_t **) const + _Bool bUseGroupSep + 1 +include/unotools/mediadescriptor.hxx:258 + class com::sun::star::uno::Sequence utl::MediaDescriptor::requestAndVerifyDocPassword(class comphelper::IDocPasswordVerifier &,enum comphelper::DocPasswordRequestType,const class std::__debug::vector > *) + enum comphelper::DocPasswordRequestType eRequestType + 1 +include/unotools/nativenumberwrapper.hxx:46 + class rtl::OUString NativeNumberWrapper::getNativeNumberString(const class rtl::OUString &,const struct com::sun::star::lang::Locale &,short) const + short nNativeNumberMode + 0 +include/unotools/sharedunocomponent.hxx:162 + void utl::SharedUNOComponent::SharedUNOComponent(const class com::sun::star::uno::BaseReference &,enum com::sun::star::uno::UnoReference_QueryThrow) + enum com::sun::star::uno::UnoReference_QueryThrow _queryThrow + 0 +include/unotools/sharedunocomponent.hxx:179 + _Bool utl::SharedUNOComponent::set(const class com::sun::star::uno::BaseReference &,enum com::sun::star::uno::UnoReference_Query) + enum com::sun::star::uno::UnoReference_Query _query + 0 +include/unotools/sharedunocomponent.hxx:183 + void utl::SharedUNOComponent::set(const Reference &,enum com::sun::star::uno::UnoReference_SetThrow) + enum com::sun::star::uno::UnoReference_SetThrow _setThrow + 0 +include/unotools/sharedunocomponent.hxx:184 + void utl::SharedUNOComponent::set(const SharedUNOComponent &,enum com::sun::star::uno::UnoReference_SetThrow) + enum com::sun::star::uno::UnoReference_SetThrow _setThrow + 0 +include/unotools/transliterationwrapper.hxx:82 + class rtl::OUString utl::TransliterationWrapper::transliterate(const class rtl::OUString &,int,int) const + int nStart + 0 +include/unotools/transliterationwrapper.hxx:98 + _Bool utl::TransliterationWrapper::equals(const class rtl::OUString &,int,int,int &,const class rtl::OUString &,int,int,int &) const + int nPos1 + 0 +include/unotools/transliterationwrapper.hxx:98 + _Bool utl::TransliterationWrapper::equals(const class rtl::OUString &,int,int,int &,const class rtl::OUString &,int,int,int &) const + int nPos2 + 0 +include/vbahelper/vbaeventshelperbase.hxx:90 + void VbaEventsHelperBase::checkArgumentType(const class com::sun::star::uno::Sequence &,int) + int nIndex + 0 +include/vbahelper/vbahelper.hxx:119 + class rtl::OUString extractStringFromAny(const class com::sun::star::uno::Any &,const class rtl::OUString &,_Bool) + _Bool bUppercaseBool + 1 +include/vcl/accessibletableprovider.hxx:114 + _Bool vcl::IAccessibleTableProvider::GetGlyphBoundRects(const class Point &,const class rtl::OUString &,int,int,class std::__debug::vector > &) + int nIndex + 0 +include/vcl/alpha.hxx:52 + void AlphaMask::Replace(unsigned char,unsigned char) + unsigned char cSearchTransparency + 0 +include/vcl/BitmapBasicMorphologyFilter.hxx:46 + void BitmapErodeFilter::BitmapErodeFilter(int) + int nRadius + 1 +include/vcl/BitmapColor.hxx:31 + void BitmapColor::BitmapColor(enum ColorTransparencyTag,unsigned char,unsigned char,unsigned char,unsigned char) + enum ColorTransparencyTag + 0 +include/vcl/BitmapColor.hxx:32 + void BitmapColor::BitmapColor(enum ColorAlphaTag,unsigned char,unsigned char,unsigned char,unsigned char) + enum ColorAlphaTag + 0 +include/vcl/BitmapFilter.hxx:30 + void generateStripRanges(long,long,class std::function) + long nFirst + 0 +include/vcl/dibtools.hxx:40 + _Bool ReadDIB(class Bitmap &,class SvStream &,_Bool,_Bool) + _Bool bMSOFormat + 0 +include/vcl/dibtools.hxx:46 + _Bool ReadDIBBitmapEx(class BitmapEx &,class SvStream &,_Bool,_Bool) + _Bool bFileHeader + 1 +include/vcl/dibtools.hxx:46 + _Bool ReadDIBBitmapEx(class BitmapEx &,class SvStream &,_Bool,_Bool) + _Bool bMSOFormat + 0 +include/vcl/embeddedfontshelper.hxx:54 + class rtl::OUString EmbeddedFontsHelper::fontFileUrl(class std::basic_string_view >,enum FontFamily,enum FontItalic,enum FontWeight,enum FontPitch,enum EmbeddedFontsHelper::FontRights) + enum EmbeddedFontsHelper::FontRights rights + 0 +include/vcl/errcode.hxx:66 + void ErrCode::ErrCode(enum WarningFlag,enum ErrCodeArea,enum ErrCodeClass,unsigned short) + enum WarningFlag + 0 +include/vcl/fieldvalues.hxx:33 + _Bool TextToValue(const class rtl::OUString &,double &,long,unsigned short,const class LocaleDataWrapper &,enum FieldUnit) + long nBaseValue + 0 +include/vcl/filter/PDFiumLibrary.hxx:60 + class std::unique_ptr > vcl::pdf::PDFium::createBitmap(int,int,int) + int nAlpha + 1 +include/vcl/filter/PDFiumLibrary.hxx:69 + void vcl::pdf::PDFiumBitmap::fillRect(int,int,int,int,unsigned int) + int left + 0 +include/vcl/filter/PDFiumLibrary.hxx:69 + void vcl::pdf::PDFiumBitmap::fillRect(int,int,int,int,unsigned int) + int top + 0 +include/vcl/filter/PDFiumLibrary.hxx:70 + void vcl::pdf::PDFiumBitmap::renderPageBitmap(class vcl::pdf::PDFiumPage *,int,int,int,int) + int nStartX + 0 +include/vcl/filter/PDFiumLibrary.hxx:70 + void vcl::pdf::PDFiumBitmap::renderPageBitmap(class vcl::pdf::PDFiumPage *,int,int,int,int) + int nStartY + 0 +include/vcl/graphicfilter.hxx:334 + class ErrCode GraphicFilter::ImportGraphic(class Graphic &,const class rtl::OUString &,class SvStream &,unsigned short,unsigned short *,enum GraphicFilterImportFlags,const class com::sun::star::uno::Sequence *,const struct WmfExternal *) + const class com::sun::star::uno::Sequence * pFilterData + 0 +include/vcl/image.hxx:47 + void Image::Image(enum StockImage,const class rtl::OUString &) + enum StockImage + 0 +include/vcl/InterimItemWindow.hxx:42 + void InterimItemWindow::InterimItemWindow(class vcl::Window *,const class rtl::OUString &,const class rtl::OString &,_Bool,unsigned long) + unsigned long nLOKWindowId + 0 +include/vcl/mtfxmldump.hxx:37 + void MetafileXmlDump::filterActionType(const enum MetaActionType,_Bool) + _Bool bShouldFilter + 0 +include/vcl/outdev.hxx:535 + _Bool OutputDevice::SupportsOperation(enum OutDevSupportType) const + enum OutDevSupportType + 0 +include/vcl/outdev.hxx:1216 + void OutputDevice::ImplDrawWaveTextLine(long,long,long,long,long,enum FontLineStyle,class Color,_Bool) + long nY + 0 +include/vcl/outdev.hxx:1217 + void OutputDevice::ImplDrawStraightTextLine(long,long,long,long,long,enum FontLineStyle,class Color,_Bool) + long nY + 0 +include/vcl/outdev.hxx:1218 + void OutputDevice::ImplDrawStrikeoutLine(long,long,long,long,long,enum FontStrikeout,class Color) + long nY + 0 +include/vcl/outdev.hxx:1219 + void OutputDevice::ImplDrawStrikeoutChar(long,long,long,long,long,enum FontStrikeout,class Color) + long nY + 0 +include/vcl/outdev.hxx:1241 + void OutputDevice::RefreshFontData(const _Bool) + const _Bool bNewFontLists + 1 +include/vcl/outdev.hxx:1368 + _Bool OutputDevice::GetTextIsRTL(const class rtl::OUString &,int,int) const + int nIndex + 0 +include/vcl/outdev/ScopedStates.hxx:25 + void vcl::ScopedAntialiasing::ScopedAntialiasing(class OutputDevice &,_Bool) + _Bool bAAState + 1 +include/vcl/pdfread.hxx:33 + unsigned long RenderPDFBitmaps(const void *,int,class std::__debug::vector > &,unsigned long,int,const class basegfx::B2DTuple *) + int nPages + 1 +include/vcl/settings.hxx:693 + void AllSettings::SetLanguageTag(const class rtl::OUString &,_Bool) + _Bool bCanonicalize + 1 +include/vcl/splitwin.hxx:139 + void SplitWindow::InsertItem(unsigned short,long,unsigned short,unsigned short,enum SplitWindowItemFlags) + unsigned short nIntoSetId + 0 +include/vcl/splitwin.hxx:160 + long SplitWindow::GetItemSize(unsigned short,enum SplitWindowItemFlags) const + enum SplitWindowItemFlags nBits + 1 +include/vcl/status.hxx:36 + void DrawProgress(class vcl::Window *,class OutputDevice &,const class Point &,long,long,long,unsigned short,unsigned short,unsigned short,const class tools::Rectangle &) + unsigned short nPercent1 + 0 +include/vcl/syschild.hxx:51 + void SystemChildWindow::EnableEraseBackground(_Bool) + _Bool bEnable + 0 +include/vcl/TaskStopwatch.hxx:76 + void TaskStopwatch::TaskStopwatch(_Bool) + _Bool bConciderLastIterTime + 1 +include/vcl/texteng.hxx:258 + void TextEngine::UndoActionStart(unsigned short) + unsigned short nId + 0 +include/vcl/timer.hxx:55 + void Timer::Invoke(class Timer *) + class Timer * arg + 0 +include/vcl/toolbox.hxx:323 + void ToolBox::InsertWindow(struct o3tl::strong_int,class vcl::Window *,enum ToolBoxItemBits,unsigned long) + enum ToolBoxItemBits nBits + 0 +include/vcl/toolbox.hxx:372 + void ToolBox::SetItemWindowNonInteractive(struct o3tl::strong_int,_Bool) + _Bool bNonInteractive + 1 +include/vcl/toolbox.hxx:430 + class Size ToolBox::CalcWindowSizePixel(unsigned long,enum WindowAlign) + unsigned long nCalcLines + 1 +include/vcl/toolbox.hxx:451 + void ToolBox::EnableCustomize(_Bool) + _Bool bEnable + 1 +include/vcl/toolkit/edit.hxx:98 + void Edit::ImplClearBackground(class OutputDevice &,const class tools::Rectangle &,long,long) + long nXStart + 0 +include/vcl/toolkit/field.hxx:82 + void FormatterBase::EnableEmptyFieldValue(_Bool) + _Bool bEnable + 1 +include/vcl/toolkit/treelistbox.hxx:555 + class SvTreeListEntry * SvTreeListBox::InsertEntry(const class rtl::OUString &,class SvTreeListEntry *,_Bool,unsigned long,void *) + _Bool bChildrenOnDemand + 0 +include/vcl/toolkit/treelistbox.hxx:559 + class SvTreeListEntry * SvTreeListBox::InsertEntry(const class rtl::OUString &,const class Image &,const class Image &,class SvTreeListEntry *,_Bool,unsigned long,void *) + _Bool bChildrenOnDemand + 0 +include/vcl/toolkit/treelistbox.hxx:624 + void SvTreeListBox::MakeVisible(class SvTreeListEntry *,_Bool) + _Bool bMoveToTop + 1 +include/vcl/toolkit/treelistbox.hxx:640 + struct std::pair SvTreeListBox::GetItemPos(class SvTreeListEntry *,unsigned short) + unsigned short nTabIdx + 0 +include/vcl/toolkit/treelistbox.hxx:648 + unsigned long SvTreeListBox::SelectChildren(class SvTreeListEntry *,_Bool) + _Bool bSelect + 0 +include/vcl/toolkit/treelistbox.hxx:658 + void SvTreeListBox::SetHighlightRange(unsigned short,unsigned short) + unsigned short nFirstTab + 0 +include/vcl/toolkit/treelistentry.hxx:104 + void SvTreeListEntry::ReplaceItem(class std::unique_ptr >,unsigned long) + unsigned long nPos + 0 +include/vcl/vclptr.hxx:43 + _Bool isIncompleteOrDerivedFromVclReferenceBase(int (*)[sizeof(T)]) + int (*)[sizeof(T)] + 0 +include/vcl/vclptr.hxx:81 + void VclPtr::VclPtr(type-parameter-?-? *,enum __sal_NoAcquire) + enum __sal_NoAcquire + 0 +include/vcl/vclptr.hxx:94 + void VclPtr::VclPtr(const VclPtr &,typename enable_if::value, int>::type) + typename enable_if::value, int>::type + 0 +include/vcl/vclptr.hxx:341 + void ScopedVclPtr::ScopedVclPtr(const VclPtr &,typename enable_if::value, int>::type) + typename enable_if::value, int>::type + 0 +include/vcl/vclptr.hxx:388 + void ScopedVclPtr::ScopedVclPtr(type-parameter-?-? *,enum __sal_NoAcquire) + enum __sal_NoAcquire + 0 +include/vcl/vectorgraphicdata.hxx:89 + void VectorGraphicData::VectorGraphicData(const class rtl::OUString &,enum VectorGraphicDataType) + enum VectorGraphicDataType eVectorDataType + 0 +include/vcl/weld.hxx:387 + void weld::ScrolledWindow::hadjustment_configure(int,int,int,int,int,int) + int step_increment + 1 +include/vcl/weld.hxx:406 + void weld::ScrolledWindow::vadjustment_configure(int,int,int,int,int,int) + int lower + 0 +include/vcl/weld.hxx:418 + void weld::ScrolledWindow::vadjustment_set_lower(int) + int upper + 0 +include/vcl/weld.hxx:1007 + void weld::TreeView::set_image(int,class VirtualDevice &,int) + int col + 1 +include/vcl/weld.hxx:1012 + void weld::TreeView::set_text_emphasis(int,_Bool,int) + int col + 0 +include/vcl/weld.hxx:1013 + _Bool weld::TreeView::get_text_emphasis(int,int) const + int col + 0 +include/vcl/weld.hxx:1014 + void weld::TreeView::set_text_align(int,double,int) + int col + 0 +include/vcl/weld.hxx:1104 + _Bool weld::TreeView::get_text_emphasis(const class weld::TreeIter &,int) const + int col + 0 +include/vcl/weld.hxx:1242 + void weld::TreeView::set_column_custom_renderer(int,_Bool) + int nColumn + 0 +include/vcl/weld.hxx:1327 + class std::unique_ptr > weld::IconView::make_iterator(const class weld::TreeIter *) const + const class weld::TreeIter * pOrig + 0 +include/vcl/window.hxx:589 + void vcl::Window::ImplSetMouseTransparent(_Bool) + _Bool bTransparent + 1 +include/vcl/window.hxx:927 + void vcl::Window::Disable(_Bool) + _Bool bChild + 1 +include/vcl/wmf.hxx:33 + _Bool ConvertGraphicToWMF(const class Graphic &,class SvStream &,const class FilterConfigItem *,_Bool) + _Bool bPlaceable + 1 +include/xmloff/numehelp.hxx:93 + void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(class SvXMLExport &,const class rtl::OUString &,class std::basic_string_view >,_Bool,_Bool) + _Bool bExportTypeAttribute + 1 +include/xmloff/ProgressBarHelper.hxx:47 + void ProgressBarHelper::ProgressBarHelper(const class com::sun::star::uno::Reference &,const _Bool) + const _Bool bStrict + 1 +include/xmloff/SchXMLImportHelper.hxx:99 + class com::sun::star::uno::Reference SchXMLImportHelper::GetNewDataSeries(const class com::sun::star::uno::Reference &,int,const class rtl::OUString &,_Bool) + int nCoordinateSystemIndex + 0 +include/xmloff/styleexp.hxx:103 + void XMLStyleExport::exportStyleFamily(const char *,const class rtl::OUString &,const class rtl::Reference &,_Bool,enum XmlStyleFamily,const class rtl::OUString *) + const class rtl::OUString * pPrefix + 0 +include/xmloff/txtparae.hxx:222 + void XMLTextParagraphExport::exportText(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,_Bool,_Bool,_Bool) + _Bool bExportParagraph + 1 +include/xmloff/XMLEventExport.hxx:89 + void XMLEventExport::Export(const class com::sun::star::uno::Reference &,_Bool) + _Bool bUseWhitespace + 1 +include/xmloff/xmlnumi.hxx:70 + void SvxXMLListStyleContext::SetDefaultStyle(const class com::sun::star::uno::Reference &,short,_Bool) + _Bool bOrdered + 0 +l10ntools/inc/common.hxx:51 + void writePoEntry(const class rtl::OString &,class PoOfstream &,const class rtl::OString &,class std::basic_string_view >,const class rtl::OString &,const class rtl::OString &,const class rtl::OString &,const class rtl::OString &,const enum PoEntry::TYPE) + const enum PoEntry::TYPE eType + 0 +l10ntools/inc/po.hxx:112 + void PoOfstream::PoOfstream(const class rtl::OString &,enum PoOfstream::OpenMode) + enum PoOfstream::OpenMode aMode + 1 +libreofficekit/qa/gtktiledviewer/gtv-main-toolbar.hxx:52 + void gtv_main_toolbar_doc_loaded(struct GtvMainToolbar *,LibreOfficeKitDocumentType,_Bool) + _Bool bEditMode + 1 +libreofficekit/qa/tilebench/tilebench.cxx:72 + void dumpTile(const char *,const int,const int,const int,const unsigned char *,const int,const int,int) + const int nOffX + 0 +libreofficekit/qa/tilebench/tilebench.cxx:72 + void dumpTile(const char *,const int,const int,const int,const unsigned char *,const int,const int,int) + const int nOffY + 0 +libreofficekit/qa/tilebench/tilebench.cxx:148 + void testTile(class lok::Document *,int,int,_Bool) + _Bool dump + 1 +lotuswordpro/inc/xfilter/xfborders.hxx:90 + void XFBorder::SetDoubleLine(_Bool,_Bool) + _Bool dual + 1 +lotuswordpro/inc/xfilter/xfborders.hxx:90 + void XFBorder::SetDoubleLine(_Bool,_Bool) + _Bool bSameWidth + 0 +lotuswordpro/inc/xfilter/xfcellstyle.hxx:108 + void XFCellStyle::SetAlignType(enum enumXFAlignType,enum enumXFAlignType) + enum enumXFAlignType hori + 0 +lotuswordpro/inc/xfilter/xfdrawstyle.hxx:118 + void XFDrawStyle::SetFontWorkStyle(enum enumXFFWStyle,enum enumXFFWAdjust) + enum enumXFFWAdjust eAdjust + 0 +lotuswordpro/inc/xfilter/xfframestyle.hxx:127 + void XFFrameStyle::SetProtect(_Bool,_Bool,_Bool) + _Bool content + 1 +lotuswordpro/inc/xfilter/xfframestyle.hxx:127 + void XFFrameStyle::SetProtect(_Bool,_Bool,_Bool) + _Bool size + 1 +lotuswordpro/inc/xfilter/xfframestyle.hxx:127 + void XFFrameStyle::SetProtect(_Bool,_Bool,_Bool) + _Bool pos + 1 +lotuswordpro/inc/xfilter/xfindex.hxx:100 + void XFIndexTemplate::AddTabEntry(enum enumXFTab,double,char16_t,char16_t,const class rtl::OUString &) + double len + 0 +lotuswordpro/inc/xfilter/xfparastyle.hxx:173 + void XFParaStyle::SetDropCap(short,short,double) + double fDistance + 0 +lotuswordpro/inc/xfilter/xfutil.hxx:91 + class rtl::OUString GetColorMode(enum enumXFColorMode) + enum enumXFColorMode mode + 0 +lotuswordpro/source/filter/bento.hxx:203 + class OpenStormBento::CBenObject * OpenStormBento::LtcBenContainer::FindNextObjectWithProperty(class OpenStormBento::CBenObject *,unsigned int) + class OpenStormBento::CBenObject * pCurrObject + 0 +lotuswordpro/source/filter/clone.hxx:26 + char & detail::has_clone::check_sig(type-parameter-?-? *,test *) + type-parameter-?-? * + 0 +lotuswordpro/source/filter/clone.hxx:26 + char & detail::has_clone::check_sig(type-parameter-?-? *,test *) + test * + 0 +lotuswordpro/source/filter/lwpnumericfmt.hxx:112 + void LwpCurrencyInfo::LwpCurrencyInfo(const class rtl::OUString &,_Bool,_Bool) + _Bool bShowSpace_ + 1 +o3tl/qa/cow_wrapper_clients.hxx:41 + void o3tltests::cow_wrapper_client1::cow_wrapper_client1(int) + int nVal + 1 +oox/inc/drawingml/chart/typegroupconverter.hxx:153 + void oox::drawingml::chart::TypeGroupConverter::convertLineSmooth(class oox::PropertySet &,_Bool) const + _Bool bOoxSmooth + 1 +oox/inc/drawingml/textspacing.hxx:42 + void oox::drawingml::TextSpacing::TextSpacing(int) + int nPoints + 0 +oox/qa/unit/drawingml.cxx:38 + class com::sun::star::uno::Reference getChildShape(const class com::sun::star::uno::Reference &,int) + int nIndex + 0 +oox/source/drawingml/lineproperties.cxx:44 + void lclSetDashData(struct com::sun::star::drawing::LineDash &,short,int,short,int,int) + short nDots + 1 +oox/source/export/chartexport.cxx:259 + int lcl_getCategoryAxisType(const class com::sun::star::uno::Reference &,int,int) + int nDimensionIndex + 0 +oox/source/export/chartexport.cxx:481 + int lcl_getAlphaFromTransparenceGradient(const struct com::sun::star::awt::Gradient &,_Bool) + _Bool bStart + 1 +oox/source/ppt/pptshape.cxx:511 + _Bool Placeholders::hasByPrio(unsigned long) const + unsigned long aIndex + 0 +oox/source/ppt/timenodelistcontext.cxx:104 + void oox::ppt::(anonymous namespace)::AnimColor::AnimColor(short,int,int,int) + short cs + 0 +oox/source/ppt/timenodelistcontext.cxx:104 + void oox::ppt::(anonymous namespace)::AnimColor::AnimColor(short,int,int,int) + int o + 0 +oox/source/ppt/timenodelistcontext.cxx:104 + void oox::ppt::(anonymous namespace)::AnimColor::AnimColor(short,int,int,int) + int t + 0 +oox/source/ppt/timenodelistcontext.cxx:104 + void oox::ppt::(anonymous namespace)::AnimColor::AnimColor(short,int,int,int) + int th + 0 +oox/source/vml/vmlformatting.cxx:542 + long lclGetEmu(const class oox::GraphicHelper &,const class oox::OptValue &,long) + long nDefValue + 1 +oox/source/vml/vmlshapecontext.cxx:133 + _Bool lclDecodeVmlxBool(class std::basic_string_view >,_Bool) + _Bool bDefaultForEmpty + 1 +opencl/source/opencl_device.cxx:116 + double random(double,double) + double min + 0 +opencl/source/openclwrapper.cxx:529 + _Bool initOpenCLRunEnv(int) + int argc + 0 +pyuno/inc/pyuno.hxx:86 + void pyuno::PyRef::PyRef(struct _object *,enum __sal_NoAcquire) + enum __sal_NoAcquire + 0 +pyuno/inc/pyuno.hxx:88 + void pyuno::PyRef::PyRef(struct _object *,enum __sal_NoAcquire,enum pyuno::NotNull) + enum __sal_NoAcquire + 0 +pyuno/inc/pyuno.hxx:88 + void pyuno::PyRef::PyRef(struct _object *,enum __sal_NoAcquire,enum pyuno::NotNull) + enum pyuno::NotNull + 0 +pyuno/source/module/pyuno_impl.hxx:80 + void log(struct pyuno::RuntimeCargo *,int,class std::basic_string_view >) + int level + 1 +reportdesign/inc/RptModel.hxx:57 + void rptui::OReportModel::OReportModel(class reportdesign::OReportDefinition *) + class reportdesign::OReportDefinition * _pReportDefinition + 0 +reportdesign/source/core/inc/Tools.hxx:48 + void throwIllegallArgumentException(const class rtl::OUString &,const class com::sun::star::uno::Reference &,short) + short ArgumentPosition_ + 1 +reportdesign/source/filter/xml/xmlFixedContent.cxx:52 + void rptxml::(anonymous namespace)::OXMLCharContent::OXMLCharContent(class SvXMLImport &,class rptxml::OXMLFixedContent *,short) + short nControl + 1 +reportdesign/source/filter/xml/xmlFormattedField.hxx:34 + void rptxml::OXMLFormattedField::OXMLFormattedField(class rptxml::ORptFilter &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,class rptxml::OXMLTable *,_Bool) + _Bool _bPageCount + 0 +reportdesign/source/ui/inc/DesignView.hxx:228 + void rptui::ODesignView::setMarked(const class com::sun::star::uno::Sequence > &,_Bool) + _Bool _bMark + 1 +reportdesign/source/ui/inc/GeometryHandler.hxx:97 + void rptui::GeometryHandler::implCreateListLikeControl(const class com::sun::star::uno::Reference &,struct com::sun::star::inspection::LineDescriptor &,const char **,_Bool,_Bool) + _Bool _bReadOnlyControl + 0 +reportdesign/source/ui/inc/GeometryHandler.hxx:97 + void rptui::GeometryHandler::implCreateListLikeControl(const class com::sun::star::uno::Reference &,struct com::sun::star::inspection::LineDescriptor &,const char **,_Bool,_Bool) + _Bool _bTrueIfListBoxFalseIfComboBox + 1 +reportdesign/source/ui/inc/UITools.hxx:142 + class SdrObject * isOver(const class tools::Rectangle &,const class SdrPage &,const class SdrView &,_Bool,class std::unique_ptr *,int) + _Bool _bAllObjects + 1 +reportdesign/source/ui/report/SectionWindow.cxx:360 + void lcl_setOrigin(class vcl::Window &,long,long) + long _nY + 0 +sal/osl/unx/file.cxx:111 + void (anonymous namespace)::FileHandle_Impl::FileHandle_Impl(int,enum (anonymous namespace)::FileHandle_Impl::Kind,const char *) + enum (anonymous namespace)::FileHandle_Impl::Kind kind + 1 +sal/qa/osl/file/osl_File.cxx:437 + void osl_FileBase::getAbsoluteFileURL::check_getAbsoluteFileURL(const class rtl::OUString &,const class rtl::OString &,enum osl::FileBase::RC,const class rtl::OUString &) + enum osl::FileBase::RC _nAssumeError + 0 +sal/qa/osl/pipe/osl_Pipe.cxx:737 + void thread_sleep(unsigned int) + unsigned int _nSec + 1 +sal/qa/osl/process/osl_Thread.cxx:160 + void (anonymous namespace)::ThreadSafeValue::ThreadSafeValue(type-parameter-?-?) + type-parameter-?-? n + 0 +sal/qa/rtl/random/rtl_random.cxx:172 + void rtl_random::(anonymous namespace)::Statistics::addValue(unsigned char,int) + int _nValue + 1 +sc/inc/address.hxx:333 + void ScAddress::Format(class rtl::OStringBuffer &,enum ScRefFlags,const class ScDocument *,const struct ScAddress::Details &) const + const class ScDocument * pDocument + 0 +sc/inc/address.hxx:506 + void ScRange::ScRange(enum ScAddress::Uninitialized) + enum ScAddress::Uninitialized eUninitialized + 0 +sc/inc/address.hxx:509 + void ScRange::ScRange(enum ScAddress::InitializeInvalid) + enum ScAddress::InitializeInvalid eInvalid + 0 +sc/inc/attarray.hxx:142 + const class ScPatternAttr * ScAttrArray::SetPattern(int,class std::unique_ptr >,_Bool) + _Bool bPutToPool + 1 +sc/inc/attarray.hxx:144 + void ScAttrArray::SetPatternArea(int,int,class std::unique_ptr >,_Bool,class ScEditDataArray *) + _Bool bPutToPool + 1 +sc/inc/attarray.hxx:144 + void ScAttrArray::SetPatternArea(int,int,class std::unique_ptr >,_Bool,class ScEditDataArray *) + class ScEditDataArray * pDataArray + 0 +sc/inc/cellform.hxx:40 + class rtl::OUString ScCellFormat::GetString(class ScDocument &,const class ScAddress &,unsigned int,const class Color **,class SvNumberFormatter &,_Bool,_Bool) + _Bool bNullVals + 1 +sc/inc/cellform.hxx:40 + class rtl::OUString ScCellFormat::GetString(class ScDocument &,const class ScAddress &,unsigned int,const class Color **,class SvNumberFormatter &,_Bool,_Bool) + _Bool bFormula + 0 +sc/inc/ChartTools.hxx:47 + class SdrOle2Obj * getChartByIndex(class ScDocShell *,short,long,enum sc::tools::ChartSourceType) + enum sc::tools::ChartSourceType eChartSourceType + 1 +sc/inc/chgtrack.hxx:711 + void ScChangeActionContent::PutOldValueToDoc(class ScDocument *,short,int) const + short nDx + 0 +sc/inc/chgtrack.hxx:711 + void ScChangeActionContent::PutOldValueToDoc(class ScDocument *,short,int) const + int nDy + 0 +sc/inc/column.hxx:223 + _Bool ScColumn::HasDataAt(struct sc::ColumnBlockConstPosition &,int,_Bool,_Bool) const + _Bool bConsiderCellNotes + 0 +sc/inc/column.hxx:223 + _Bool ScColumn::HasDataAt(struct sc::ColumnBlockConstPosition &,int,_Bool,_Bool) const + _Bool bConsiderCellDrawObjects + 0 +sc/inc/column.hxx:225 + _Bool ScColumn::HasDataAt(struct sc::ColumnBlockPosition &,int,_Bool,_Bool) + _Bool bConsiderCellNotes + 0 +sc/inc/column.hxx:225 + _Bool ScColumn::HasDataAt(struct sc::ColumnBlockPosition &,int,_Bool,_Bool) + _Bool bConsiderCellDrawObjects + 0 +sc/inc/column.hxx:252 + void ScColumn::GetUnprotectedCells(int,int,class ScRangeList &) const + int nStartRow + 0 +sc/inc/column.hxx:339 + class ScFormulaCell * ScColumn::SetFormulaCell(int,class ScFormulaCell *,enum sc::StartListeningType,_Bool) + _Bool bInheritNumFormatIfNeeded + 1 +sc/inc/column.hxx:369 + void ScColumn::GetString(struct sc::ColumnBlockConstPosition &,int,class rtl::OUString &,const struct ScInterpreterContext *) const + const struct ScInterpreterContext * pContext + 0 +sc/inc/column.hxx:672 + void ScColumn::DetachFormulaCells(class sc::EndListeningContext &,int,int,class std::__debug::vector > *) + class std::__debug::vector > * pNewSharedRows + 0 +sc/inc/column.hxx:728 + void ScColumn::AttachNewFormulaCell(const class mdds::detail::mtv::iterator_base, struct mdds::mtv::noncopyable_managed_element_block<53, class EditTextObject>, struct mdds::mtv::noncopyable_managed_element_block<54, class ScFormulaCell> >, class sc::CellStoreEvent>::iterator_trait, struct mdds::detail::mtv::private_data_forward_update > > &,int,class ScFormulaCell &,const class std::__debug::vector > &,_Bool,enum sc::StartListeningType) + _Bool bJoin + 1 +sc/inc/columnspanset.hxx:59 + void sc::ColumnSpanSet::ColumnType::ColumnType(int,int,_Bool) + int nStart + 0 +sc/inc/columnspanset.hxx:59 + void sc::ColumnSpanSet::ColumnType::ColumnType(int,int,_Bool) + _Bool bInit + 0 +sc/inc/columnspanset.hxx:83 + void sc::ColumnSpanSet::ColumnAction::executeSum(int,int,_Bool,double &) + _Bool + 1 +sc/inc/columnspanset.hxx:91 + void sc::ColumnSpanSet::set(const class ScDocument &,short,short,int,_Bool) + _Bool bVal + 1 +sc/inc/columnspanset.hxx:93 + void sc::ColumnSpanSet::set(const class ScDocument &,const class ScRange &,_Bool) + _Bool bVal + 1 +sc/inc/columnspanset.hxx:95 + void sc::ColumnSpanSet::set(const class ScDocument &,short,short,const class sc::SingleColumnSpanSet &,_Bool) + _Bool bVal + 1 +sc/inc/columnspanset.hxx:101 + void sc::ColumnSpanSet::scan(const class ScDocument &,short,short,int,short,int,_Bool) + _Bool bVal + 1 +sc/inc/compiler.hxx:361 + void ScCompiler::ScCompiler(class sc::CompileFormulaContext &,const class ScAddress &,_Bool,_Bool,const struct ScInterpreterContext *) + _Bool bComputeII + 0 +sc/inc/compiler.hxx:361 + void ScCompiler::ScCompiler(class sc::CompileFormulaContext &,const class ScAddress &,_Bool,_Bool,const struct ScInterpreterContext *) + _Bool bMatrixFlag + 0 +sc/inc/compiler.hxx:361 + void ScCompiler::ScCompiler(class sc::CompileFormulaContext &,const class ScAddress &,_Bool,_Bool,const struct ScInterpreterContext *) + const struct ScInterpreterContext * pContext + 0 +sc/inc/compiler.hxx:366 + void ScCompiler::ScCompiler(class ScDocument &,const class ScAddress &,enum formula::FormulaGrammar::Grammar,_Bool,_Bool,const struct ScInterpreterContext *) + const struct ScInterpreterContext * pContext + 0 +sc/inc/compressedarray.hxx:188 + void ScBitMaskCompressedArray::ScBitMaskCompressedArray(type-parameter-?-?,const type-parameter-?-? &) + const type-parameter-?-? & rValue + 0 +sc/inc/compressedarray.hxx:198 + void ScBitMaskCompressedArray::CopyFromAnded(const ScBitMaskCompressedArray &,type-parameter-?-?,type-parameter-?-?,const type-parameter-?-? &) + type-parameter-?-? nStart + 0 +sc/inc/dapiuno.hxx:296 + void ScFieldIdentifier::ScFieldIdentifier(const class rtl::OUString &,_Bool) + _Bool bDataLayout + 1 +sc/inc/dociter.hxx:562 + void ScUsedAreaIterator::ScUsedAreaIterator(class ScDocument &,short,short,int,short,int) + short nCol1 + 0 +sc/inc/dociter.hxx:562 + void ScUsedAreaIterator::ScUsedAreaIterator(class ScDocument &,short,short,int,short,int) + int nRow1 + 0 +sc/inc/dociter.hxx:598 + void ScDocRowHeightUpdater::TabRanges::TabRanges(short,int) + short nTab + 0 +sc/inc/document.hxx:966 + void ScDocument::SetPendingRowHeights(short,_Bool) + _Bool bSet + 0 +sc/inc/document.hxx:970 + void ScDocument::SetScenario(short,_Bool) + _Bool bFlag + 1 +sc/inc/document.hxx:1166 + class rtl::OUString ScDocument::GetString(short,int,short,const struct ScInterpreterContext *) const + const struct ScInterpreterContext * pContext + 0 +sc/inc/document.hxx:1306 + void ScDocument::GetBorderLines(short,int,short,const class editeng::SvxBorderLine **,const class editeng::SvxBorderLine **,const class editeng::SvxBorderLine **,const class editeng::SvxBorderLine **) const + short nTab + 0 +sc/inc/document.hxx:1542 + void ScDocument::EnableUserInteraction(_Bool) + _Bool bVal + 0 +sc/inc/document.hxx:1629 + void ScDocument::CopyMultiRangeFromClip(const class ScAddress &,const class ScMarkData &,enum InsertDeleteFlags,class ScDocument *,_Bool,_Bool,_Bool,_Bool) + _Bool bResetCut + 1 +sc/inc/document.hxx:1678 + void ScDocument::UndoToDocument(short,int,short,short,int,short,enum InsertDeleteFlags,_Bool,class ScDocument &) + short nCol1 + 0 +sc/inc/document.hxx:1678 + void ScDocument::UndoToDocument(short,int,short,short,int,short,enum InsertDeleteFlags,_Bool,class ScDocument &) + _Bool bMarked + 0 +sc/inc/document.hxx:1685 + void ScDocument::UndoToDocument(const class ScRange &,enum InsertDeleteFlags,_Bool,class ScDocument &) + _Bool bMarked + 0 +sc/inc/document.hxx:1730 + const class ScPatternAttr * ScDocument::GetMostUsedPattern(short,int,int,short) const + int nStartRow + 0 +sc/inc/document.hxx:1893 + unsigned long ScDocument::GetColOffset(short,short,_Bool) const + _Bool bHiddenAsZero + 1 +sc/inc/document.hxx:1894 + unsigned long ScDocument::GetRowOffset(int,short,_Bool) const + _Bool bHiddenAsZero + 1 +sc/inc/document.hxx:1926 + void ScDocument::SetRowFlags(int,int,short,enum CRFlags) + int nStartRow + 0 +sc/inc/document.hxx:1931 + void ScDocument::GetAllRowBreaks(class std::__debug::set, class std::allocator > &,short,_Bool,_Bool) const + _Bool bPage + 0 +sc/inc/document.hxx:1931 + void ScDocument::GetAllRowBreaks(class std::__debug::set, class std::allocator > &,short,_Bool,_Bool) const + _Bool bManual + 1 +sc/inc/document.hxx:1932 + void ScDocument::GetAllColBreaks(class std::__debug::set, class std::allocator > &,short,_Bool,_Bool) const + _Bool bPage + 0 +sc/inc/document.hxx:1932 + void ScDocument::GetAllColBreaks(class std::__debug::set, class std::allocator > &,short,_Bool,_Bool) const + _Bool bManual + 1 +sc/inc/document.hxx:1935 + void ScDocument::SetRowBreak(int,short,_Bool,_Bool) + _Bool bPage + 0 +sc/inc/document.hxx:1935 + void ScDocument::SetRowBreak(int,short,_Bool,_Bool) + _Bool bManual + 1 +sc/inc/document.hxx:1936 + void ScDocument::SetColBreak(short,short,_Bool,_Bool) + _Bool bPage + 0 +sc/inc/document.hxx:1936 + void ScDocument::SetColBreak(short,short,_Bool,_Bool) + _Bool bManual + 1 +sc/inc/document.hxx:1937 + void ScDocument::RemoveRowBreak(int,short,_Bool,_Bool) + _Bool bPage + 0 +sc/inc/document.hxx:1937 + void ScDocument::RemoveRowBreak(int,short,_Bool,_Bool) + _Bool bManual + 1 +sc/inc/document.hxx:1938 + void ScDocument::RemoveColBreak(short,short,_Bool,_Bool) + _Bool bPage + 0 +sc/inc/document.hxx:1938 + void ScDocument::RemoveColBreak(short,short,_Bool,_Bool) + _Bool bManual + 1 +sc/inc/document.hxx:2259 + void ScDocument::UpdateBroadcastAreas(enum UpdateRefMode,const class ScRange &,short,int,short) + enum UpdateRefMode eUpdateRefMode + 0 +sc/inc/document.hxx:2289 + void ScDocument::CalcFormulaTree(_Bool,_Bool,_Bool) + _Bool bSetAllDirty + 1 +sc/inc/document.hxx:2511 + void ScDocument::StoreTabToCache(short,class SvStream &) const + short nTab + 0 +sc/inc/document.hxx:2512 + void ScDocument::RestoreTabFromCache(short,class SvStream &) + short nTab + 0 +sc/inc/document.hxx:2603 + void ScDocument::EndListeningIntersectedGroup(class sc::EndListeningContext &,const class ScAddress &,class std::__debug::vector > *) + class std::__debug::vector > * pGroupPos + 0 +sc/inc/document.hxx:2623 + void ScMutationDisable::ScMutationDisable(class ScDocument &,enum ScMutationGuardFlags) + enum ScMutationGuardFlags nFlags + 1 +sc/inc/document.hxx:2656 + void ScMutationGuard::ScMutationGuard(class ScDocument &,enum ScMutationGuardFlags) + enum ScMutationGuardFlags nFlags + 1 +sc/inc/documentimport.hxx:88 + void ScDocumentImport::setSheetName(short,const class rtl::OUString &) + short nTab + 0 +sc/inc/documentimport.hxx:123 + void ScDocumentImport::setRowsVisible(short,int,int,_Bool) + _Bool bVisible + 0 +sc/inc/documentlinkmgr.hxx:65 + _Bool sc::DocumentLinkManager::hasDdeOrOleOrWebServiceLinks(_Bool,_Bool,_Bool) const + _Bool bDde + 1 +sc/inc/dpdimsave.hxx:178 + class rtl::OUString ScDPDimensionSaveData::CreateDateGroupDimName(int,const class ScDPObject &,_Bool,const class std::__debug::vector > *) + _Bool bAllowSource + 1 +sc/inc/dpglobal.hxx:53 + void ScDPValue::Set(double,enum ScDPValue::Type) + enum ScDPValue::Type eT + 0 +sc/inc/dpsave.hxx:229 + void ScDPSaveDimension::Dump(int) const + int nIndent + 0 +sc/inc/dptabdat.hxx:130 + const class ScDPItemData * ScDPTableData::GetMemberByIndex(int,int) + int nIndex + 0 +sc/inc/dptabres.hxx:139 + void ScDPRelativePos::ScDPRelativePos(long,long) + long nBase + 0 +sc/inc/drwlayer.hxx:170 + class tools::Rectangle ScDrawLayer::GetCellRect(const class ScDocument &,const class ScAddress &,_Bool) + _Bool bMergedCell + 1 +sc/inc/filter.hxx:78 + class ErrCode ScFormatFilterPlugin::ScExportExcel5(class SfxMedium &,class ScDocument *,enum ExportFormatExcel,unsigned short) + unsigned short eDest + 1 +sc/inc/filter.hxx:81 + void ScFormatFilterPlugin::ScExportHTML(class SvStream &,const class rtl::OUString &,class ScDocument *,const class ScRange &,const unsigned short,_Bool,const class rtl::OUString &,class rtl::OUString &,const class rtl::OUString &) + const unsigned short eDest + 0 +sc/inc/filter.hxx:83 + void ScFormatFilterPlugin::ScExportRTF(class SvStream &,class ScDocument *,const class ScRange &,const unsigned short) + const unsigned short eDest + 0 +sc/inc/formulacell.hxx:189 + void ScFormulaCell::ScFormulaCell(class ScDocument &,const class ScAddress &,class std::unique_ptr >,const enum formula::FormulaGrammar::Grammar,enum ScMatrixMode) + enum ScMatrixMode cMatInd + 0 +sc/inc/formulacell.hxx:223 + class rtl::OUString ScFormulaCell::GetFormula(class sc::CompileFormulaContext &,const struct ScInterpreterContext *) const + const struct ScInterpreterContext * pContext + 0 +sc/inc/markarr.hxx:56 + void ScMarkArray::Reset(_Bool,unsigned long) + unsigned long nNeeded + 1 +sc/inc/miscuno.hxx:154 + short ScUnoHelpFunctions::GetShortProperty(const class com::sun::star::uno::Reference &,const class rtl::OUString &,short) + short nDefault + 0 +sc/inc/miscuno.hxx:159 + type-parameter-?-? ScUnoHelpFunctions::GetEnumProperty(const class com::sun::star::uno::Reference &,const class rtl::OUString &,type-parameter-?-?) + type-parameter-?-? nDefault + 0 +sc/inc/pivot.hxx:124 + void ScPivotField::ScPivotField(short) + short nNewCol + 0 +sc/inc/postit.hxx:166 + void ScPostIt::ScPostIt(class ScDocument &,const class ScAddress &,unsigned int) + unsigned int nPostItId + 0 +sc/inc/queryparam.hxx:59 + struct ScQueryEntry * ScQueryParamBase::FindEntryByField(int,_Bool) + _Bool bNew + 1 +sc/inc/rangeutl.hxx:58 + _Bool ScRangeUtil::IsAbsTabArea(const class rtl::OUString &,const class ScDocument *,class std::unique_ptr > *,unsigned short *,_Bool,const struct ScAddress::Details &) + _Bool bAcceptCellRef + 1 +sc/inc/rangeutl.hxx:126 + _Bool ScRangeStringConverter::GetAddressFromString(class ScAddress &,const class rtl::OUString &,const class ScDocument &,enum formula::FormulaGrammar::AddressConvention,int &,char16_t,char16_t) + enum formula::FormulaGrammar::AddressConvention eConv + 0 +sc/inc/rangeutl.hxx:150 + _Bool ScRangeStringConverter::GetAreaFromString(class ScArea &,const class rtl::OUString &,const class ScDocument &,enum formula::FormulaGrammar::AddressConvention,int &,char16_t) + enum formula::FormulaGrammar::AddressConvention eConv + 0 +sc/inc/rangeutl.hxx:184 + void ScRangeStringConverter::GetStringFromRangeList(class rtl::OUString &,const class ScRangeList *,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t) + enum formula::FormulaGrammar::AddressConvention eConv + 0 +sc/inc/rangeutl.hxx:191 + void ScRangeStringConverter::GetStringFromArea(class rtl::OUString &,const class ScArea &,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t,_Bool,enum ScRefFlags) + enum formula::FormulaGrammar::AddressConvention eConv + 0 +sc/inc/rangeutl.hxx:191 + void ScRangeStringConverter::GetStringFromArea(class rtl::OUString &,const class ScArea &,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t,_Bool,enum ScRefFlags) + _Bool bAppendStr + 1 +sc/inc/rangeutl.hxx:201 + void ScRangeStringConverter::GetStringFromAddress(class rtl::OUString &,const struct com::sun::star::table::CellAddress &,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t,_Bool) + enum formula::FormulaGrammar::AddressConvention eConv + 0 +sc/inc/rangeutl.hxx:201 + void ScRangeStringConverter::GetStringFromAddress(class rtl::OUString &,const struct com::sun::star::table::CellAddress &,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t,_Bool) + _Bool bAppendStr + 0 +sc/inc/rangeutl.hxx:216 + void ScRangeStringConverter::GetStringFromRangeList(class rtl::OUString &,const class com::sun::star::uno::Sequence &,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t) + enum formula::FormulaGrammar::AddressConvention eConv + 0 +sc/inc/scabstdlg.hxx:462 + class VclPtr ScAbstractDialogFactory::CreateScMetricInputDlg(class weld::Window *,const class rtl::OString &,long,long,enum FieldUnit,unsigned short,long,long) + long nMinimum + 0 +sc/inc/scmatrix.hxx:149 + void ScMatrix::IterateResult::IterateResult(double,double,unsigned long) + unsigned long nCount + 0 +sc/inc/scmatrix.hxx:329 + _Bool ScMatrix::IsEmptyResult(unsigned long,unsigned long) const + unsigned long nC + 0 +sc/inc/scmatrix.hxx:329 + _Bool ScMatrix::IsEmptyResult(unsigned long,unsigned long) const + unsigned long nR + 0 +sc/inc/scmatrix.hxx:368 + unsigned long ScMatrix::MatchDoubleInColumns(double,unsigned long,unsigned long) const + unsigned long nCol1 + 0 +sc/inc/scmatrix.hxx:368 + unsigned long ScMatrix::MatchDoubleInColumns(double,unsigned long,unsigned long) const + unsigned long nCol2 + 0 +sc/inc/scmatrix.hxx:369 + unsigned long ScMatrix::MatchStringInColumns(const class svl::SharedString &,unsigned long,unsigned long) const + unsigned long nCol1 + 0 +sc/inc/scmatrix.hxx:369 + unsigned long ScMatrix::MatchStringInColumns(const class svl::SharedString &,unsigned long,unsigned long) const + unsigned long nCol2 + 0 +sc/inc/scopetools.hxx:57 + void sc::UndoSwitch::UndoSwitch(class ScDocument &,_Bool) + _Bool bUndo + 1 +sc/inc/scopetools.hxx:67 + void sc::IdleSwitch::IdleSwitch(class ScDocument &,_Bool) + _Bool bEnableIdle + 0 +sc/inc/scopetools.hxx:78 + void sc::DelayFormulaGroupingSwitch::DelayFormulaGroupingSwitch(class ScDocument &,_Bool) + _Bool delay + 1 +sc/inc/stringutil.hxx:153 + class rtl::OUString ScStringUtil::GetQuotedToken(const class rtl::OUString &,int,const class rtl::OUString &,char16_t,int &) + int nToken + 0 +sc/inc/table.hxx:788 + void ScTable::SetOptimalHeightOnly(class sc::RowHeightContext &,int,int,class ScProgress *,unsigned long) + int nStartRow + 0 +sc/inc/table.hxx:904 + _Bool ScTable::RowHiddenLeaf(int,int *,int *) const + int * pFirstRow + 0 +sc/inc/table.hxx:909 + void ScTable::CopyColHidden(const class ScTable &,short,short) + short nStartCol + 0 +sc/inc/table.hxx:910 + void ScTable::CopyRowHidden(const class ScTable &,int,int) + int nStartRow + 0 +sc/inc/table.hxx:920 + _Bool ScTable::ColFiltered(short,short *,short *) const + short * pFirstCol + 0 +sc/inc/table.hxx:922 + void ScTable::CopyColFiltered(const class ScTable &,short,short) + short nStartCol + 0 +sc/inc/table.hxx:923 + void ScTable::CopyRowFiltered(const class ScTable &,int,int) + int nStartRow + 0 +sc/inc/token.hxx:267 + void ScRefListToken::ScRefListToken(_Bool) + _Bool bArrayResult + 1 +sc/inc/types.hxx:106 + void sc::MultiDataCellState::MultiDataCellState(enum sc::MultiDataCellState::StateType) + enum sc::MultiDataCellState::StateType eState + 1 +sc/qa/extras/new_cond_format.cxx:183 + void testShowValue(const class com::sun::star::uno::Reference &,_Bool) + _Bool bShowVal + 1 +sc/qa/extras/scpdfexport.cxx:54 + void ScPDFExportTest::setFont(class ScFieldEditEngine &,int,int,const class rtl::OUString &) + int nStart + 0 +sc/qa/unit/bugfix-test.cxx:92 + void lcl_AssertRectEqualWithTolerance(class std::basic_string_view >,const class tools::Rectangle &,const class tools::Rectangle &,const int) + const int nTolerance + 1 +sc/qa/unit/bugfix-test.cxx:124 + void lcl_AssertPointEqualWithTolerance(class std::basic_string_view >,const class Point,const class Point,const int) + const int nTolerance + 1 +sc/qa/unit/copy_paste_test.cxx:78 + class tools::SvRef ScCopyPasteTest::loadDocAndSetupModelViewController(class std::basic_string_view >,int,_Bool) + int nFormat + 0 +sc/qa/unit/copy_paste_test.cxx:78 + class tools::SvRef ScCopyPasteTest::loadDocAndSetupModelViewController(class std::basic_string_view >,int,_Bool) + _Bool bReadWrite + 1 +sc/qa/unit/copy_paste_test.cxx:453 + enum ScMF lcl_getMergeFlagOfCell(const class ScDocument &,short,int,short) + short nTab + 0 +sc/qa/unit/copy_paste_test.cxx:460 + class ScAddress lcl_getMergeSizeOfCell(const class ScDocument &,short,int,short) + short nTab + 0 +sc/qa/unit/helper/qahelper.hxx:197 + class tools::SvRef ScBootstrapFixture::saveAndReloadPassword(class ScDocShell *,int) + int nFormat + 0 +sc/qa/unit/helper/qahelper.hxx:217 + void testFormats(class ScBootstrapFixture *,class ScDocument *,int) + int nFormat + 0 +sc/qa/unit/mark_test.cxx:129 + void Test::testScMarkArraySearch_check(const class ScMarkArray &,int,_Bool,unsigned long) + _Bool expectStatus + 1 +sc/qa/unit/opencl-test.cxx:509 + _Bool ScOpenCLTest::initTestEnv(class std::basic_string_view >,int,_Bool) + _Bool bReadWrite + 0 +sc/qa/unit/parallelism.cxx:76 + class ScUndoCut * ScParallelismTest::cutToClip(class ScDocShell &,const class ScRange &,class ScDocument *,_Bool) + _Bool bCreateUndo + 0 +sc/qa/unit/subsequent_export-test.cxx:1656 + void setAttribute(class ScFieldEditEngine &,int,int,int,unsigned short,class Color) + int nPara + 0 +sc/qa/unit/subsequent_export-test.cxx:1713 + void setFont(class ScFieldEditEngine &,int,int,int,const class rtl::OUString &) + int nPara + 0 +sc/qa/unit/subsequent_export-test.cxx:1726 + void setEscapement(class ScFieldEditEngine &,int,int,int,short,unsigned char) + int nPara + 0 +sc/qa/unit/ucalc.hxx:50 + void Test::clearSheet(class ScDocument *,short) + short nTab + 0 +sc/source/core/data/dociter.cxx:1278 + void BoolResetter::BoolResetter(_Bool &,_Bool) + _Bool b + 1 +sc/source/core/data/drwlayer.cxx:2254 + void DeleteFirstUserDataOfType(class SdrObject *,unsigned short) + unsigned short nId + 1 +sc/source/core/data/postit.cxx:411 + void (anonymous namespace)::ScNoteCaptionCreator::ScNoteCaptionCreator(class ScDocument &,const class ScAddress &,class ScCaptionPtr &,_Bool) + _Bool bShown + 1 +sc/source/core/inc/interpre.hxx:438 + int ScInterpreter::GetInt32WithDefault(int) + int nDefault + 1 +sc/source/core/opencl/formulagroupcl.cxx:1071 + class std::__cxx11::basic_string, class std::allocator > sc::opencl::(anonymous namespace)::DynamicKernelSlidingArgument::GenSlidingWindowDeclRef(_Bool) const + _Bool nested + 0 +sc/source/core/opencl/opbase.hxx:128 + class std::__cxx11::basic_string, class std::allocator > sc::opencl::DynamicKernelArgument::GenDoubleSlidingWindowDeclRef(_Bool) const + _Bool + 0 +sc/source/core/opencl/opbase.hxx:131 + class std::__cxx11::basic_string, class std::allocator > sc::opencl::DynamicKernelArgument::GenStringSlidingWindowDeclRef(_Bool) const + _Bool + 0 +sc/source/core/tool/compiler.cxx:787 + void (anonymous namespace)::ConventionOOO_A1::ConventionOOO_A1(enum formula::FormulaGrammar::AddressConvention) + enum formula::FormulaGrammar::AddressConvention eConv + 1 +sc/source/filter/excel/xeformula.cxx:389 + void XclExpFmlaCompImpl::ConvertRefData(struct ScComplexRefData &,struct XclRange &,_Bool) const + _Bool bNatLangRef + 0 +sc/source/filter/excel/xeformula.cxx:407 + void XclExpFmlaCompImpl::Append(unsigned char,unsigned long) + unsigned char nData + 0 +sc/source/filter/excel/xeformula.cxx:409 + void XclExpFmlaCompImpl::Append(unsigned int) + unsigned int nData + 0 +sc/source/filter/excel/xeformula.cxx:449 + void XclExpFmlaCompImpl::AppendExt(unsigned char,unsigned long) + unsigned char nData + 0 +sc/source/filter/excel/xihelper.cxx:141 + class std::unique_ptr > lclCreateTextObject(const class XclImpRoot &,const class XclImpString &,enum XclFontItemType,unsigned short) + enum XclFontItemType eType + 1 +sc/source/filter/html/htmlpars.cxx:1617 + type-parameter-?-? getLimitedValue(const type-parameter-?-? &,const type-parameter-?-? &,const type-parameter-?-? &) + const type-parameter-?-? & rMin + 1 +sc/source/filter/inc/addressconverter.hxx:145 + _Bool oox::xls::AddressConverter::parseOoxRange2d(int &,int &,int &,int &,const class rtl::OUString &,int) + int nStart + 0 +sc/source/filter/inc/addressconverter.hxx:234 + _Bool oox::xls::AddressConverter::convertToCellAddress(class ScAddress &,const char *,short,_Bool) + _Bool bTrackOverflow + 1 +sc/source/filter/inc/addressconverter.hxx:245 + class ScAddress oox::xls::AddressConverter::createValidCellAddress(const class rtl::OUString &,short,_Bool) + _Bool bTrackOverflow + 0 +sc/source/filter/inc/addressconverter.hxx:375 + _Bool oox::xls::AddressConverter::convertToCellRange(class ScRange &,const class rtl::OUString &,short,_Bool,_Bool) + _Bool bAllowOverflow + 1 +sc/source/filter/inc/addressconverter.hxx:415 + _Bool oox::xls::AddressConverter::convertToCellRange(class ScRange &,const struct oox::xls::BinRange &,short,_Bool,_Bool) + _Bool bAllowOverflow + 1 +sc/source/filter/inc/addressconverter.hxx:431 + void oox::xls::AddressConverter::validateCellRangeList(class ScRangeList &,_Bool) + _Bool bTrackOverflow + 0 +sc/source/filter/inc/autofilterbuffer.hxx:50 + void oox::xls::ApiFilterSettings::appendField(_Bool,const class std::__debug::vector, class std::allocator > > &) + _Bool bAnd + 1 +sc/source/filter/inc/excrecds.hxx:179 + void XclExpSheetProtection::XclExpSheetProtection(_Bool,short) + _Bool bValue + 1 +sc/source/filter/inc/formel.hxx:100 + enum ConvErr ExcelConverterBase::Convert(class ScRangeListTabs &,class XclImpStream &,unsigned long,short,const enum FORMULA_TYPE) + const enum FORMULA_TYPE eFT + 1 +sc/source/filter/inc/formulabase.hxx:640 + class rtl::OUString oox::xls::FormulaProcessorBase::generateAddress2dString(const class ScAddress &,_Bool) + _Bool bAbsolute + 0 +sc/source/filter/inc/formulabase.hxx:772 + void oox::xls::FormulaProcessorBase::convertStringToStringList(class com::sun::star::uno::Sequence &,char16_t,_Bool) const + _Bool bTrimLeadingSpaces + 1 +sc/source/filter/inc/ftools.hxx:199 + class ScStyleSheet & ScfTools::MakeCellStyleSheet(class ScStyleSheetPool &,const class rtl::OUString &,_Bool) + _Bool bForceName + 1 +sc/source/filter/inc/ftools.hxx:206 + class ScStyleSheet & ScfTools::MakePageStyleSheet(class ScStyleSheetPool &,const class rtl::OUString &,_Bool) + _Bool bForceName + 0 +sc/source/filter/inc/htmlpars.hxx:189 + void ScHTMLLayoutParser::MakeColNoRef(class o3tl::sorted_vector, find_unique, true> *,unsigned short,unsigned short,unsigned short,unsigned short) + unsigned short nWidth + 0 +sc/source/filter/inc/htmlpars.hxx:189 + void ScHTMLLayoutParser::MakeColNoRef(class o3tl::sorted_vector, find_unique, true> *,unsigned short,unsigned short,unsigned short,unsigned short) + unsigned short nOffsetTol + 0 +sc/source/filter/inc/htmlpars.hxx:189 + void ScHTMLLayoutParser::MakeColNoRef(class o3tl::sorted_vector, find_unique, true> *,unsigned short,unsigned short,unsigned short,unsigned short) + unsigned short nWidthTol + 0 +sc/source/filter/inc/tool.h:37 + void SetFormat(struct LotusContext &,short,int,short,unsigned char,unsigned char) + short nTab + 0 +sc/source/filter/inc/workbookhelper.hxx:161 + class com::sun::star::uno::Reference oox::xls::WorkbookHelper::getStyleObject(const class rtl::OUString &,_Bool) const + _Bool bPageStyle + 1 +sc/source/filter/inc/workbookhelper.hxx:200 + class com::sun::star::uno::Reference oox::xls::WorkbookHelper::createStyleObject(class rtl::OUString &,_Bool) const + _Bool bPageStyle + 1 +sc/source/filter/inc/xechart.hxx:196 + void XclExpChFutureRecordBase::XclExpChFutureRecordBase(const class XclExpChRoot &,enum XclFutureRecType,unsigned short,unsigned long) + enum XclFutureRecType eRecType + 1 +sc/source/filter/inc/xechart.hxx:337 + void XclExpChFrameBase::SetDefaultFrameBase(const class XclExpChRoot &,enum XclChFrameType,_Bool) + enum XclChFrameType eDefFrameType + 1 +sc/source/filter/inc/xechart.hxx:365 + void XclExpChFrame::SetAutoFlags(_Bool,_Bool) + _Bool bAutoPos + 0 +sc/source/filter/inc/xechart.hxx:365 + void XclExpChFrame::SetAutoFlags(_Bool,_Bool) + _Bool bAutoSize + 0 +sc/source/filter/inc/xeextlst.hxx:199 + class XclExpExt * XclExtLst::GetItem(enum XclExpExtType) + enum XclExpExtType eType + 0 +sc/source/filter/inc/xehelper.hxx:109 + struct XclAddress XclExpAddressConverter::CreateValidAddress(const class ScAddress &,_Bool) + _Bool bWarn + 0 +sc/source/filter/inc/xehelper.hxx:149 + void XclExpAddressConverter::ValidateRangeList(class ScRangeList &,_Bool) + _Bool bWarn + 0 +sc/source/filter/inc/xehelper.hxx:281 + class std::shared_ptr XclExpStringHelper::CreateCellString(const class XclExpRoot &,const class rtl::OUString &,const class ScPatternAttr *,enum XclStrFlags,unsigned short) + enum XclStrFlags nFlags + 0 +sc/source/filter/inc/xehelper.hxx:297 + class std::shared_ptr XclExpStringHelper::CreateCellString(const class XclExpRoot &,const class EditTextObject &,const class ScPatternAttr *,class XclExpHyperlinkHelper &,enum XclStrFlags,unsigned short) + enum XclStrFlags nFlags + 0 +sc/source/filter/inc/xehelper.hxx:311 + class std::shared_ptr XclExpStringHelper::CreateString(const class XclExpRoot &,const class SdrTextObj &,enum XclStrFlags) + enum XclStrFlags nFlags + 0 +sc/source/filter/inc/xehelper.hxx:320 + class std::shared_ptr XclExpStringHelper::CreateString(const class XclExpRoot &,const class EditTextObject &,enum XclStrFlags) + enum XclStrFlags nFlags + 0 +sc/source/filter/inc/xepivot.hxx:270 + unsigned short XclExpPTField::GetItemIndex(class std::basic_string_view >,unsigned short) const + unsigned short nDefaultIdx + 0 +sc/source/filter/inc/xestream.hxx:300 + void XclExpXmlStream::WriteAttributes(int,type-parameter-?-? &&,type-parameter-?-? &&...) + ###27 + 0 +sc/source/filter/inc/xestring.hxx:78 + void XclExpString::Assign(char16_t) + char16_t cChar + 0 +sc/source/filter/inc/xestring.hxx:107 + void XclExpString::AppendTrailingFormat(unsigned short) + unsigned short nFontIdx + 0 +sc/source/filter/inc/xestring.hxx:145 + unsigned short XclExpString::GetChar(unsigned short) const + unsigned short nCharIdx + 0 +sc/source/filter/inc/xestyle.hxx:223 + unsigned short XclExpFontBuffer::Insert(const class SvxFont &,enum XclExpColorType) + enum XclExpColorType eColorType + 0 +sc/source/filter/inc/xestyle.hxx:229 + unsigned short XclExpFontBuffer::Insert(const class SfxItemSet &,short,enum XclExpColorType,_Bool) + enum XclExpColorType eColorType + 0 +sc/source/filter/inc/xetable.hxx:333 + void XclExpSingleCellBase::XclExpSingleCellBase(unsigned short,unsigned long,const struct XclAddress &,unsigned int) + unsigned long nContSize + 0 +sc/source/filter/inc/xetable.hxx:336 + void XclExpSingleCellBase::XclExpSingleCellBase(const class XclExpRoot &,unsigned short,unsigned long,const struct XclAddress &,const class ScPatternAttr *,short,unsigned int) + short nScript + 1 +sc/source/filter/inc/xiescher.hxx:478 + void XclImpControlHelper::ReadSourceRangeFormula(class XclImpStream &,_Bool) + _Bool bWithBoundSize + 1 +sc/source/filter/inc/xihelper.hxx:69 + class ScAddress XclImpAddressConverter::CreateValidAddress(const struct XclAddress &,short,_Bool) + _Bool bWarn + 0 +sc/source/filter/inc/xipage.hxx:58 + void XclImpPageSettings::SetPaperSize(unsigned short,_Bool) + unsigned short nXclPaperSize + 0 +sc/source/filter/inc/xipage.hxx:58 + void XclImpPageSettings::SetPaperSize(unsigned short,_Bool) + _Bool bPortrait + 0 +sc/source/filter/inc/xladdress.hxx:62 + void XclRange::XclRange(enum ScAddress::Uninitialized) + enum ScAddress::Uninitialized e + 0 +sc/source/filter/inc/xlescher.hxx:293 + class tools::Rectangle XclObjAnchor::GetRect(const class XclRoot &,short,enum MapUnit) const + enum MapUnit eMapUnit + 0 +sc/source/filter/inc/xlformula.hxx:380 + void XclTokenArray::XclTokenArray(_Bool) + _Bool bVolatile + 0 +sc/source/filter/inc/xlformula.hxx:442 + void XclTokenArrayIterator::XclTokenArrayIterator(const class ScTokenArray &,_Bool) + _Bool bSkipSpaces + 1 +sc/source/filter/inc/xlformula.hxx:444 + void XclTokenArrayIterator::XclTokenArrayIterator(const class XclTokenArrayIterator &,_Bool) + _Bool bSkipSpaces + 1 +sc/source/filter/inc/xltools.hxx:64 + void XclGuid::XclGuid(unsigned int,unsigned short,unsigned short,unsigned char,unsigned char,unsigned char,unsigned char,unsigned char,unsigned char,unsigned char,unsigned char) + unsigned char nData43 + 0 +sc/source/filter/inc/xltools.hxx:64 + void XclGuid::XclGuid(unsigned int,unsigned short,unsigned short,unsigned char,unsigned char,unsigned char,unsigned char,unsigned char,unsigned char,unsigned char,unsigned char) + unsigned char nData45 + 0 +sc/source/filter/oox/formulaparser.cxx:463 + struct com::sun::star::sheet::FormulaToken & oox::xls::FormulaParserImpl::getOperandToken(unsigned long,unsigned long) + unsigned long nOpIndex + 0 +sc/source/filter/oox/formulaparser.cxx:463 + struct com::sun::star::sheet::FormulaToken & oox::xls::FormulaParserImpl::getOperandToken(unsigned long,unsigned long) + unsigned long nTokenIndex + 0 +sc/source/filter/xml/XMLChangeTrackingImportHelper.hxx:74 + void ScMyGenerated::ScMyGenerated(class ScBigRange,unsigned int,class std::unique_ptr >) + unsigned int id + 0 +sc/source/filter/xml/XMLExportSharedData.hxx:68 + void ScMySharedData::SetDrawPageHasForms(const int,_Bool) + _Bool bHasForms + 1 +sc/source/ui/dbgui/csvgrid.cxx:58 + void (anonymous namespace)::Func_SetType::Func_SetType(int) + int nType + 0 +sc/source/ui/dbgui/csvgrid.cxx:66 + void (anonymous namespace)::Func_Select::Func_Select(_Bool) + _Bool bSelect + 0 +sc/source/ui/inc/AccessibleDocument.hxx:248 + void ScAccessibleDocument::RemoveChild(const class com::sun::star::uno::Reference &,_Bool) + _Bool bFireEvent + 1 +sc/source/ui/inc/AccessibleEditObject.hxx:55 + void ScAccessibleEditObject::ScAccessibleEditObject(const class com::sun::star::uno::Reference &,class EditView *,class vcl::Window *,const class rtl::OUString &,const class rtl::OUString &,enum ScAccessibleEditObject::EditObjectType) + enum ScAccessibleEditObject::EditObjectType eObjectType + 0 +sc/source/ui/inc/acredlin.hxx:119 + class std::unique_ptr > ScAcceptChgDlg::AppendFilteredAction(const class ScChangeAction *,enum ScChangeActionState,_Bool,const class weld::TreeIter *,_Bool,_Bool) + _Bool bDelMaster + 0 +sc/source/ui/inc/acredlin.hxx:119 + class std::unique_ptr > ScAcceptChgDlg::AppendFilteredAction(const class ScChangeAction *,enum ScChangeActionState,_Bool,const class weld::TreeIter *,_Bool,_Bool) + _Bool bDisabled + 0 +sc/source/ui/inc/anyrefdg.hxx:71 + void ScFormulaReferenceHelper::EnableSpreadsheets(_Bool) + _Bool bFlag + 1 +sc/source/ui/inc/anyrefdg.hxx:144 + void ScRefHdlrControllerImpl::ScRefHdlrControllerImpl(class weld::Window *,const class rtl::OUString &,const class rtl::OString &,const class SfxItemSet *,class SfxBindings *) + class SfxBindings * pB + 0 +sc/source/ui/inc/cliputil.hxx:22 + void PasteFromClipboard(class ScViewData &,class ScTabViewShell *,_Bool) + _Bool bShowDialog + 1 +sc/source/ui/inc/datatransformation.hxx:148 + void sc::NumberTransformation::NumberTransformation(const class std::__debug::set, class std::allocator > &,const enum sc::NUMBER_TRANSFORM_TYPE,int) + const enum sc::NUMBER_TRANSFORM_TYPE rType + 0 +sc/source/ui/inc/dbdocfun.hxx:79 + _Bool ScDBDocFunc::RepeatDB(const class rtl::OUString &,_Bool,_Bool,short) + _Bool bApi + 1 +sc/source/ui/inc/docfunc.hxx:101 + void ScDocFunc::SetValueCells(const class ScAddress &,const class std::__debug::vector > &,_Bool) + _Bool bInteraction + 1 +sc/source/ui/inc/docfunc.hxx:112 + _Bool ScDocFunc::SetFormulaCells(const class ScAddress &,class std::__debug::vector > &,_Bool) + _Bool bInteraction + 1 +sc/source/ui/inc/docfunc.hxx:113 + void ScDocFunc::PutData(const class ScAddress &,class ScEditEngineDefaulter &,_Bool) + _Bool bApi + 1 +sc/source/ui/inc/docfunc.hxx:114 + _Bool ScDocFunc::SetCellText(const class ScAddress &,const class rtl::OUString &,_Bool,_Bool,_Bool,const enum formula::FormulaGrammar::Grammar) + _Bool bApi + 1 +sc/source/ui/inc/docfunc.hxx:120 + void ScDocFunc::SetNoteText(const class ScAddress &,const class rtl::OUString &,_Bool) + _Bool bApi + 0 +sc/source/ui/inc/docfunc.hxx:143 + _Bool ScDocFunc::SetTabBgColor(class std::__debug::vector > &,_Bool) + _Bool bApi + 0 +sc/source/ui/inc/docfunc.hxx:145 + void ScDocFunc::SetTableVisible(short,_Bool,_Bool) + _Bool bApi + 1 +sc/source/ui/inc/docfunc.hxx:178 + _Bool ScDocFunc::FillSimple(const class ScRange &,const class ScMarkData *,enum FillDir,_Bool) + _Bool bApi + 0 +sc/source/ui/inc/docfunc.hxx:187 + _Bool ScDocFunc::FillAuto(class ScRange &,const class ScMarkData *,enum FillDir,enum FillCmd,enum FillDateCmd,unsigned long,double,double,_Bool,_Bool) + _Bool bRecord + 1 +sc/source/ui/inc/drawutil.hxx:31 + void ScDrawUtil::CalcScale(const class ScDocument &,short,short,int,short,int,const class OutputDevice *,const class Fraction &,const class Fraction &,double,double,class Fraction &,class Fraction &) + short nStartCol + 0 +sc/source/ui/inc/drawutil.hxx:31 + void ScDrawUtil::CalcScale(const class ScDocument &,short,short,int,short,int,const class OutputDevice *,const class Fraction &,const class Fraction &,double,double,class Fraction &,class Fraction &) + int nStartRow + 0 +sc/source/ui/inc/pvfundlg.hxx:151 + int ScDPSubtotalOptDlg::FindListBoxEntry(const class weld::ComboBox &,class std::basic_string_view >,int) const + int nStartPos + 1 +sc/source/ui/inc/RegressionDialog.hxx:56 + class rtl::OUString ScRegressionDialog::GetYVariableNameFormula(_Bool) + _Bool bWithLog + 0 +sc/source/ui/inc/spellparam.hxx:36 + void ScConversionParam::ScConversionParam(enum ScConversionType) + enum ScConversionType eConvType + 0 +sc/source/ui/inc/spellparam.hxx:39 + void ScConversionParam::ScConversionParam(enum ScConversionType,struct o3tl::strong_int,int,_Bool) + enum ScConversionType eConvType + 1 +sc/source/ui/inc/spellparam.hxx:39 + void ScConversionParam::ScConversionParam(enum ScConversionType,struct o3tl::strong_int,int,_Bool) + int nOptions + 0 +sc/source/ui/inc/spellparam.hxx:39 + void ScConversionParam::ScConversionParam(enum ScConversionType,struct o3tl::strong_int,int,_Bool) + _Bool bIsInteractive + 1 +sc/source/ui/inc/spellparam.hxx:46 + void ScConversionParam::ScConversionParam(enum ScConversionType,struct o3tl::strong_int,struct o3tl::strong_int,const class vcl::Font &,int,_Bool) + _Bool bIsInteractive + 0 +sc/source/ui/inc/TableFillingAndNavigationTools.hxx:69 + void AddressWalker::push(short,int,short) + short aRelativeTab + 0 +sc/source/ui/inc/tabview.hxx:379 + void ScTabView::ClickCursor(short,int,_Bool) + _Bool bControl + 0 +sc/source/ui/inc/tabview.hxx:420 + void ScTabView::MoveCursorAbs(short,int,enum ScFollowMode,_Bool,_Bool,_Bool,_Bool) + _Bool bControl + 0 +sc/source/ui/inc/tabview.hxx:431 + void ScTabView::MoveCursorScreen(short,int,enum ScFollowMode,_Bool) + short nMovX + 0 +sc/source/ui/inc/tabview.hxx:431 + void ScTabView::MoveCursorScreen(short,int,enum ScFollowMode,_Bool) + enum ScFollowMode eMode + 1 +sc/source/ui/inc/tabview.hxx:431 + void ScTabView::MoveCursorScreen(short,int,enum ScFollowMode,_Bool) + _Bool bShift + 0 +sc/source/ui/inc/undoblk.hxx:322 + void ScUndoSelectionAttr::ScUndoSelectionAttr(class ScDocShell *,const class ScMarkData &,short,int,short,short,int,short,class std::unique_ptr >,_Bool,const class ScPatternAttr *,const class SvxBoxItem *,const class SvxBoxInfoItem *,const class ScRange *) + const class SvxBoxItem * pNewOuter + 0 +sc/source/ui/inc/undoblk.hxx:322 + void ScUndoSelectionAttr::ScUndoSelectionAttr(class ScDocShell *,const class ScMarkData &,short,int,short,short,int,short,class std::unique_ptr >,_Bool,const class ScPatternAttr *,const class SvxBoxItem *,const class SvxBoxInfoItem *,const class ScRange *) + const class SvxBoxInfoItem * pNewInner + 0 +sc/source/ui/inc/undoblk.hxx:322 + void ScUndoSelectionAttr::ScUndoSelectionAttr(class ScDocShell *,const class ScMarkData &,short,int,short,short,int,short,class std::unique_ptr >,_Bool,const class ScPatternAttr *,const class SvxBoxItem *,const class SvxBoxInfoItem *,const class ScRange *) + const class ScRange * pRangeCover + 0 +sc/source/ui/inc/undotab.hxx:119 + void ScUndoRenameTab::ScUndoRenameTab(class ScDocShell *,short,const class rtl::OUString &,const class rtl::OUString &) + short nT + 0 +sc/source/ui/inc/undotab.hxx:199 + void ScUndoTabColor::ScUndoTabColor(class ScDocShell *,short,const class Color &,const class Color &) + short nT + 0 +sc/source/ui/inc/viewdata.hxx:145 + void ScPositionHelper::invalidateByPosition(long) + long nPos + 0 +sc/source/ui/inc/viewdata.hxx:599 + class Point ScViewData::GetScrPos(short,int,enum ScHSplitPos) const + int nWhereY + 0 +sc/source/ui/inc/viewdata.hxx:600 + class Point ScViewData::GetScrPos(short,int,enum ScVSplitPos) const + short nWhereX + 0 +sc/source/ui/inc/viewdata.hxx:676 + void ScViewData::AddPixelsWhileBackward(long &,long,int &,int,double,const class ScDocument *,short) + int nStartRow + 0 +sc/source/ui/inc/viewfunc.hxx:173 + void ScViewFunc::ApplyAttributes(const class SfxItemSet *,const class SfxItemSet *,_Bool) + _Bool bAdjustBlockHeight + 1 +sc/source/ui/inc/viewfunc.hxx:216 + _Bool ScViewFunc::AdjustRowHeight(int,int,_Bool) + _Bool bApi + 1 +sc/source/ui/inc/viewutil.hxx:68 + void ScViewUtil::SetFullScreen(const class SfxViewShell &,_Bool) + _Bool bSet + 0 +sc/source/ui/pagedlg/tptable.cxx:44 + _Bool lcl_PutScaleItem(unsigned short,class SfxItemSet &,const class SfxItemSet &,const class weld::ComboBox &,unsigned short,const class weld::MetricSpinButton &,unsigned short) + unsigned short nLBEntry + 0 +sc/source/ui/pagedlg/tptable.cxx:52 + _Bool lcl_PutScaleItem2(unsigned short,class SfxItemSet &,const class SfxItemSet &,const class weld::ComboBox &,unsigned short,const class weld::SpinButton &,unsigned short,const class weld::SpinButton &,unsigned short) + unsigned short nLBEntry + 1 +sc/source/ui/vba/vbacondition.hxx:43 + int ScVbaCondition::Operator(_Bool) + _Bool _bIncludeFormulaValue + 1 +sc/source/ui/vba/vbaeventshelper.hxx:53 + _Bool ScVbaEventsHelper::isSelectionChanged(const class com::sun::star::uno::Sequence &,int) + int nIndex + 0 +sc/source/ui/vba/vbaeventshelper.hxx:59 + class com::sun::star::uno::Any ScVbaEventsHelper::createWorksheet(const class com::sun::star::uno::Sequence &,int) const + int nIndex + 0 +sc/source/ui/vba/vbaeventshelper.hxx:64 + class com::sun::star::uno::Any ScVbaEventsHelper::createRange(const class com::sun::star::uno::Sequence &,int) const + int nIndex + 0 +sc/source/ui/vba/vbaeventshelper.hxx:69 + class com::sun::star::uno::Any ScVbaEventsHelper::createHyperlink(const class com::sun::star::uno::Sequence &,int) const + int nIndex + 0 +sc/source/ui/vba/vbaeventshelper.hxx:74 + class com::sun::star::uno::Any ScVbaEventsHelper::createWindow(const class com::sun::star::uno::Sequence &,int) const + int nIndex + 0 +sc/source/ui/vba/vbarange.hxx:107 + class com::sun::star::uno::Reference ScVbaRange::getArea(int) + int nIndex + 0 +sc/source/ui/view/olinewin.cxx:730 + _Bool lcl_RotateValue(unsigned long &,unsigned long,unsigned long,_Bool) + unsigned long nMin + 0 +sc/source/ui/view/prevloc.cxx:267 + struct ScPreviewLocationEntry * lcl_GetEntryByAddress(const class std::__debug::list >, class std::allocator > > > &,const class ScAddress &,const enum (anonymous namespace)::ScPreviewLocationType) + const enum (anonymous namespace)::ScPreviewLocationType eType + 0 +sc/source/ui/view/tabview.cxx:2447 + void (anonymous namespace)::ScRangeProvider::ScRangeProvider(const class tools::Rectangle &,_Bool,class ScViewData &) + _Bool bInPixels + 0 +scaddins/source/analysis/analysishelper.hxx:69 + int GetDiffDate360(const class com::sun::star::uno::Reference &,int,int,_Bool) + _Bool bUSAMethod + 1 +scaddins/source/analysis/analysishelper.hxx:83 + int GetDaysInYear(int,int,int) + int nNullDate + 0 +scaddins/source/analysis/analysishelper.hxx:83 + int GetDaysInYear(int,int,int) + int nDate + 0 +scaddins/source/analysis/analysishelper.hxx:262 + void sca::analysis::SortedIndividualInt32List::InsertHolidayList(const class sca::analysis::ScaAnyConverter &,const class com::sun::star::uno::Any &,int,_Bool) + _Bool bInsertOnWeekend + 0 +scaddins/source/analysis/analysishelper.hxx:900 + int sca::analysis::ScaAnyConverter::getInt32(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Any &,int) + int nDefault + 0 +sd/inc/CustomAnimationEffect.hxx:129 + class com::sun::star::uno::Any sd::CustomAnimationEffect::getProperty(int,class std::basic_string_view >,enum sd::EValue) + enum sd::EValue eValue + 0 +sd/inc/CustomAnimationEffect.hxx:130 + _Bool sd::CustomAnimationEffect::setProperty(int,class std::basic_string_view >,enum sd::EValue,const class com::sun::star::uno::Any &) + enum sd::EValue eValue + 0 +sd/inc/CustomAnimationEffect.hxx:132 + class com::sun::star::uno::Any sd::CustomAnimationEffect::getTransformationProperty(int,enum sd::EValue) + enum sd::EValue eValue + 1 +sd/inc/CustomAnimationEffect.hxx:133 + _Bool sd::CustomAnimationEffect::setTransformationProperty(int,enum sd::EValue,const class com::sun::star::uno::Any &) + enum sd::EValue eValue + 1 +sd/inc/shapelist.hxx:56 + void sd::ShapeList::seekShape(unsigned int) + unsigned int nIndex + 0 +sd/qa/unit/sdmodeltestbase.hxx:422 + class com::sun::star::uno::Reference SdModelTestBase::getTextFieldFromPage(int,int,int,int,class tools::SvRef) + int nRun + 0 +sd/qa/unit/sdmodeltestbase.hxx:422 + class com::sun::star::uno::Reference SdModelTestBase::getTextFieldFromPage(int,int,int,int,class tools::SvRef) + int nPara + 0 +sd/qa/unit/tiledrendering/LOKitSearchTest.cxx:865 + class rtl::OUString getShapeText(class SdXImpressDocument *,unsigned int,unsigned int) + unsigned int nShape + 0 +sd/qa/unit/uiimpress.cxx:63 + void SdUiImpressTest::insertStringToObject(unsigned short,const class std::__cxx11::basic_string, class std::allocator > &) + unsigned short nObj + 0 +sd/source/filter/eppt/epptbase.hxx:393 + unsigned int PPTWriterBase::GetMasterIndex(enum PageType) + enum PageType ePageType + 0 +sd/source/filter/eppt/pptexanimations.hxx:95 + void ppt::AnimationExporter::exportNode(class SvStream &,const class com::sun::star::uno::Reference &,const unsigned short,const unsigned short,const int,const _Bool,const short) + const unsigned short nInstance + 1 +sd/source/filter/eppt/text.hxx:106 + void FieldEntry::FieldEntry(unsigned int,unsigned int,unsigned int) + unsigned int nStart + 0 +sd/source/filter/ppt/pptinanimations.hxx:99 + void ppt::AnimationImporter::dump_atom_header(const class ppt::Atom *,_Bool,_Bool) + _Bool bAppend + 0 +sd/source/filter/ppt/pptinanimations.hxx:100 + void ppt::AnimationImporter::dump_atom(const class ppt::Atom *,_Bool) + _Bool bNewLine + 1 +sd/source/ui/inc/DrawDocShell.hxx:63 + void sd::DrawDocShell::DrawDocShell(enum SfxModelFlags,_Bool,enum DocumentType) + _Bool bSdDataObj + 0 +sd/source/ui/inc/DrawDocShell.hxx:68 + void sd::DrawDocShell::DrawDocShell(class SdDrawDocument *,enum SfxObjectCreateMode,_Bool,enum DocumentType) + enum SfxObjectCreateMode eMode + 0 +sd/source/ui/inc/DrawDocShell.hxx:68 + void sd::DrawDocShell::DrawDocShell(class SdDrawDocument *,enum SfxObjectCreateMode,_Bool,enum DocumentType) + _Bool bSdDataObj + 1 +sd/source/ui/inc/DrawViewShell.hxx:89 + void sd::DrawViewShell::DrawViewShell(class sd::ViewShellBase &,class vcl::Window *,enum PageKind,class sd::FrameView *) + enum PageKind ePageKind + 0 +sd/source/ui/inc/navigatr.hxx:108 + void SdNavigatorWin::SdNavigatorWin(class weld::Widget *,class SfxBindings *,class SfxNavigator *) + class SfxNavigator * pNavigatorDlg + 0 +sd/source/ui/inc/RemoteServer.hxx:39 + void sd::ClientInfo::ClientInfo(const class rtl::OUString &,const _Bool) + const _Bool bIsAlreadyAuthorised + 0 +sd/source/ui/inc/slideshow.hxx:147 + void sd::SlideShow::pause(_Bool) + _Bool bPause + 0 +sd/source/ui/inc/ToolBarManager.hxx:225 + void sd::ToolBarManager::SetToolBarShell(enum sd::ToolBarManager::ToolBarGroup,enum ToolbarId) + enum sd::ToolBarManager::ToolBarGroup eGroup + 1 +sd/source/ui/inc/tools/ConfigurationAccess.hxx:57 + void sd::tools::ConfigurationAccess::ConfigurationAccess(const class com::sun::star::uno::Reference &,const class rtl::OUString &,const enum sd::tools::ConfigurationAccess::WriteMode) + const enum sd::tools::ConfigurationAccess::WriteMode eMode + 1 +sd/source/ui/inc/unomodel.hxx:130 + void SdXImpressDocument::SdXImpressDocument(class SdDrawDocument *,_Bool) + _Bool bClipBoard + 1 +sd/source/ui/inc/View.hxx:171 + _Bool sd::View::IsPresObjSelected(_Bool,_Bool,_Bool,_Bool) const + _Bool bOnMasterPage + 1 +sd/source/ui/slidesorter/cache/SlsBitmapCache.cxx:43 + void sd::slidesorter::cache::BitmapCache::CacheEntry::CacheEntry(int,_Bool) + _Bool bIsPrecious + 1 +sdext/source/minimizer/configurationaccess.hxx:90 + short ConfigurationAccess::GetConfigProperty(const enum PPPOptimizerTokenEnum,const short) const + const short nDefault + 0 +sdext/source/minimizer/informationdialog.hxx:29 + class rtl::OUString InsertFixedText(class UnoDialog &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,_Bool,short) + _Bool bMultiLine + 1 +sdext/source/minimizer/informationdialog.hxx:29 + class rtl::OUString InsertFixedText(class UnoDialog &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,_Bool,short) + short nTabIndex + 0 +sdext/source/minimizer/informationdialog.hxx:32 + class rtl::OUString InsertImage(class UnoDialog &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,_Bool) + _Bool bScale + 0 +sdext/source/minimizer/informationdialog.hxx:35 + class rtl::OUString InsertCheckBox(class UnoDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,int,int,int,short) + short nTabIndex + 1 +sdext/source/minimizer/optimizerdialogcontrols.cxx:91 + class rtl::OUString InsertButton(class OptimizerDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,int,int,int,short,_Bool,enum PPPOptimizerTokenEnum,enum com::sun::star::awt::PushButtonType) + enum com::sun::star::awt::PushButtonType nPushButtonType + 0 +sdext/source/minimizer/optimizerdialogcontrols.cxx:200 + class rtl::OUString InsertFormattedField(class OptimizerDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,int,int,double,double,short) + double fEffectiveMin + 0 +sdext/source/minimizer/optimizerdialogcontrols.cxx:248 + class rtl::OUString InsertComboBox(class OptimizerDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const _Bool,const class com::sun::star::uno::Sequence &,int,int,short) + const _Bool bEnabled + 1 +sdext/source/minimizer/optimizerdialogcontrols.cxx:326 + class rtl::OUString InsertListBox(class OptimizerDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const _Bool,const class com::sun::star::uno::Sequence &,int,int,int,short) + const _Bool bEnabled + 1 +sdext/source/pdfimport/wrapper/wrapper.cxx:971 + oslFileError pdfi::(anonymous namespace)::Buffering::read(char *,short,unsigned long *) + short count + 1 +sdext/source/presenter/PresenterTextView.hxx:231 + void sdext::presenter::PresenterTextView::SetOffset(const double,const double) + const double nLeft + 0 +sfx2/source/inc/workwin.hxx:275 + void SfxWorkWindow::SetChildWindowVisible_Impl(unsigned int,_Bool,enum SfxVisibilityFlags) + _Bool + 1 +slideshow/source/engine/opengl/Operation.hxx:226 + class std::shared_ptr makeSEllipseTranslate(double,double,double,double,_Bool,double,double) + _Bool bInter + 1 +slideshow/source/engine/opengl/Operation.hxx:226 + class std::shared_ptr makeSEllipseTranslate(double,double,double,double,_Bool,double,double) + double T0 + 0 +slideshow/source/engine/opengl/Operation.hxx:226 + class std::shared_ptr makeSEllipseTranslate(double,double,double,double,_Bool,double,double) + double T1 + 1 +slideshow/source/engine/opengl/Operation.hxx:262 + class std::shared_ptr makeRotateAndScaleDepthByHeight(const struct glm::vec<3, float, glm::packed_highp> &,const struct glm::vec<3, float, glm::packed_highp> &,double,_Bool,_Bool,double,double) + _Bool bScale + 1 +slideshow/source/engine/opengl/Operation.hxx:262 + class std::shared_ptr makeRotateAndScaleDepthByHeight(const struct glm::vec<3, float, glm::packed_highp> &,const struct glm::vec<3, float, glm::packed_highp> &,double,_Bool,_Bool,double,double) + _Bool bInter + 1 +slideshow/source/engine/slide/layer.hxx:219 + void slideshow::internal::Layer::Layer(enum slideshow::internal::Layer::Dummy) + enum slideshow::internal::Layer::Dummy eFlag + 0 +slideshow/source/engine/transitions/spiralwipe.hxx:33 + void slideshow::internal::SpiralWipe::SpiralWipe(int,_Bool) + _Bool flipOnYAxis + 0 +slideshow/source/inc/animationfactory.hxx:108 + class std::shared_ptr createPairPropertyAnimation(const class std::shared_ptr &,const class std::shared_ptr &,const class basegfx::B2DVector &,short,int) + int nFlags + 0 +slideshow/source/inc/animationfactory.hxx:128 + class std::shared_ptr createPathMotionAnimation(const class rtl::OUString &,short,const class std::shared_ptr &,const class std::shared_ptr &,const class basegfx::B2DVector &,const class std::shared_ptr &,int) + int nFlags + 0 +slideshow/source/inc/animationfactory.hxx:136 + class std::shared_ptr createPhysicsAnimation(const class std::shared_ptr &,const double,const class std::shared_ptr &,const class basegfx::B2DVector &,const class basegfx::B2DVector &,const double,const double,int) + int nFlags + 0 +slideshow/source/inc/box2dtools.hxx:231 + void box2d::utils::box2DWorld::queueAngularVelocityUpdate(const class com::sun::star::uno::Reference &,const double,const int) + const int nDelayForSteps + 1 +starmath/inc/cfgitem.hxx:88 + class rtl::OUString SmFontFormatList::GetFontFormatId(const struct SmFontFormat &,_Bool) + _Bool bAdd + 1 +starmath/inc/mathml/mathmlimport.hxx:55 + void SmXMLImportWrapper::useHTMLMLEntities(_Bool) + _Bool bUseHTMLMLEntities + 1 +starmath/inc/rect.hxx:174 + class SmRect & SmRect::ExtendBy(const class SmRect &,enum RectCopyMBL,_Bool) + enum RectCopyMBL eCopyMode + 0 +starmath/inc/rect.hxx:174 + class SmRect & SmRect::ExtendBy(const class SmRect &,enum RectCopyMBL,_Bool) + _Bool bKeepVerAlignParams + 1 +store/source/object.hxx:55 + type-parameter-?-? * query(class store::OStoreObject *,type-parameter-?-? *) + type-parameter-?-? * + 0 +svl/source/crypto/cryptosign.cxx:394 + enum _SECStatus my_SEC_StringToOID(struct SECItemStr *,const char *,unsigned int) + unsigned int len + 0 +svl/source/crypto/cryptosign.cxx:487 + struct NSSCMSAttributeStr * my_NSS_CMSAttributeArray_FindAttrByOidTag(struct NSSCMSAttributeStr **,SECOidTag,int) + int only + 0 +svl/source/crypto/cryptosign.cxx:1643 + struct NSSCMSAttributeStr * CMSAttributeArray_FindAttrByOidData(struct NSSCMSAttributeStr **,const struct SECOidDataStr *,int) + int only + 1 +svl/source/crypto/cryptosign.cxx:1682 + enum _SECStatus StringToOID(struct SECItemStr *,const char *,unsigned int) + unsigned int len + 0 +svl/source/numbers/zforfind.hxx:241 + _Bool ImpSvNumberInputScan::StringPtrContains(const class rtl::OUString &,const char16_t *,int) + int nPos + 0 +svl/source/numbers/zforfind.hxx:394 + _Bool ImpSvNumberInputScan::IsDatePatternNumberOfType(unsigned short,char16_t) + unsigned short nNumber + 0 +svl/source/passwordcontainer/passwordcontainer.hxx:149 + void NamePassRecord::RemovePasswords(signed char) + signed char nStatus + 1 +svtools/source/control/valueimp.hxx:213 + void ValueItemAcc::FireAccessibleEvent(short,const class com::sun::star::uno::Any &,const class com::sun::star::uno::Any &) + short nEventId + 1 +svx/inc/sdginitm.hxx:34 + void SdrGrafInvertItem::SdrGrafInvertItem(_Bool) + _Bool bInvert + 0 +svx/inc/sxmtaitm.hxx:30 + void SdrMeasureTextAutoAngleItem::SdrMeasureTextAutoAngleItem(_Bool) + _Bool bOn + 1 +svx/inc/xftshtit.hxx:33 + void XFormTextShadowTranspItem::XFormTextShadowTranspItem(unsigned short) + unsigned short nShdwTransparence + 0 +svx/qa/unit/classicshapes.cxx:34 + class com::sun::star::uno::Reference (anonymous namespace)::ClassicshapesTest::getShape(unsigned char,unsigned char) + unsigned char nShapeIndex + 0 +svx/source/customshapes/EnhancedCustomShape3d.cxx:129 + enum com::sun::star::drawing::ShadeMode GetShadeMode(const class SdrCustomShapeGeometryItem &,const enum com::sun::star::drawing::ShadeMode) + const enum com::sun::star::drawing::ShadeMode eDefault + 0 +svx/source/customshapes/EnhancedCustomShape3d.cxx:138 + _Bool GetBool(const class SdrCustomShapeGeometryItem &,const class rtl::OUString &,const _Bool) + const _Bool bDefault + 0 +svx/source/dialog/srchdlg.cxx:745 + void (anonymous namespace)::ToggleSaveToModule::ToggleSaveToModule(class SvxSearchDialog &,_Bool) + _Bool bValue + 0 +svx/source/gallery2/galbrws1.hxx:87 + void GalleryBrowser1::SelectTheme(unsigned short) + unsigned short nThemePos + 0 +svx/source/inc/celltypes.hxx:58 + void sdr::table::RangeIterator::RangeIterator(const type-parameter-?-? &,const type-parameter-?-? &,_Bool) + const type-parameter-?-? & rStart + 0 +svx/source/inc/fmexpl.hxx:497 + signed char svxform::NavigatorTree::implExecuteDataTransfer(const class svxform::OControlTransferData &,signed char,const class Point &,_Bool) + _Bool _bDnD + 1 +svx/source/inc/fmshimp.hxx:256 + void FmXFormShell::didPrepareClose_Lock(_Bool) + _Bool bDid + 1 +svx/source/inc/fmvwimp.hxx:267 + _Bool FmXFormView::createControlLabelPair(const class OutputDevice &,int,int,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,enum SdrObjKind,class std::basic_string_view >,class std::unique_ptr &,class std::unique_ptr &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &,const int) + int _nXOffsetMM + 0 +svx/source/svdraw/svdoole2.cxx:629 + void SdrOle2ObjImpl::SdrOle2ObjImpl(_Bool,const class svt::EmbeddedObjectRef &) + _Bool bFrame + 0 +svx/source/tbxctrls/tbcontrl.cxx:144 + void (anonymous namespace)::SvxStyleBox_Base::insert_separator(int,const class rtl::OUString &) + int pos + 1 +sw/inc/authfld.hxx:167 + class rtl::OUString SwAuthorityField::ExpandCitation(enum ToxAuthorityField,const class SwRootFrame *) const + const class SwRootFrame * pLayout + 0 +sw/inc/calc.hxx:116 + void SwSbxValue::SwSbxValue(long) + long n + 0 +sw/inc/charfmt.hxx:30 + void SwCharFormat::SwCharFormat(class SwAttrPool &,const char *,class SwCharFormat *) + class SwCharFormat * pDerivedFrom + 0 +sw/inc/crsrsh.hxx:560 + _Bool SwCursorShell::GotoMark(const class sw::mark::IMark *const,_Bool) + _Bool bAtStart + 1 +sw/inc/crsrsh.hxx:824 + void SwCursorShell::FireSectionChangeEvent(unsigned short,unsigned short) + unsigned short nNewSection + 1 +sw/inc/crsrsh.hxx:825 + void SwCursorShell::FireColumnChangeEvent(unsigned short,unsigned short) + unsigned short nNewColumn + 1 +sw/inc/dbfld.hxx:83 + void SwDBField::ChgValue(double,_Bool) + _Bool bVal + 1 +sw/inc/doc.hxx:998 + void SwDoc::CorrAbs(const class SwNodeIndex &,const struct SwPosition &,const int,_Bool) + _Bool bMoveCursor + 1 +sw/inc/doc.hxx:1012 + void SwDoc::CorrAbs(const class SwPaM &,const struct SwPosition &,_Bool) + _Bool bMoveCursor + 1 +sw/inc/doc.hxx:1018 + void SwDoc::CorrRel(const class SwNodeIndex &,const struct SwPosition &,const int,_Bool) + const int nOffset + 0 +sw/inc/doc.hxx:1057 + void SwDoc::SetCounted(const class SwPaM &,_Bool,const class SwRootFrame *) + _Bool bCounted + 1 +sw/inc/doc.hxx:1126 + const class SwNumRule * SwDoc::SearchNumRule(const struct SwPosition &,const _Bool,const _Bool,const _Bool,int,class rtl::OUString &,const class SwRootFrame *,const _Bool) + const _Bool bForward + 0 +sw/inc/doc.hxx:1126 + const class SwNumRule * SwDoc::SearchNumRule(const struct SwPosition &,const _Bool,const _Bool,const _Bool,int,class rtl::OUString &,const class SwRootFrame *,const _Bool) + const _Bool bOutline + 0 +sw/inc/doc.hxx:1420 + const class SvNumberFormatter * SwDoc::GetNumberFormatter(_Bool) const + _Bool bCreate + 1 +sw/inc/doc.hxx:1635 + void SwDoc::dumpAsXml(struct _xmlTextWriter *) const + struct _xmlTextWriter * + 0 +sw/inc/docary.hxx:296 + _Bool SwExtraRedlineTable::DeleteTableRowRedline(class SwDoc *,const class SwTableLine &,_Bool,enum RedlineType) + _Bool bSaveInUndo + 1 +sw/inc/docary.hxx:297 + _Bool SwExtraRedlineTable::DeleteTableCellRedline(class SwDoc *,const class SwTableBox &,_Bool,enum RedlineType) + _Bool bSaveInUndo + 1 +sw/inc/docufld.hxx:287 + void SwHiddenTextFieldType::SwHiddenTextFieldType(_Bool) + _Bool bSetHidden + 1 +sw/inc/docufld.hxx:312 + void SwHiddenTextField::SwHiddenTextField(class SwHiddenTextFieldType *,_Bool,const class rtl::OUString &,const class rtl::OUString &,_Bool,enum SwFieldTypesEnum) + _Bool bConditional + 1 +sw/inc/docufld.hxx:312 + void SwHiddenTextField::SwHiddenTextField(class SwHiddenTextFieldType *,_Bool,const class rtl::OUString &,const class rtl::OUString &,_Bool,enum SwFieldTypesEnum) + _Bool bHidden + 0 +sw/inc/docufld.hxx:529 + void SwDocInfoField::SwDocInfoField(class SwDocInfoFieldType *,unsigned short,const class rtl::OUString &,const class rtl::OUString &,unsigned int) + unsigned int nFormat + 0 +sw/inc/fesh.hxx:420 + const class SwFrameFormat * SwFEShell::GetFlyNum(unsigned long,enum FlyCntType,_Bool) const + enum FlyCntType eType + 1 +sw/inc/fesh.hxx:420 + const class SwFrameFormat * SwFEShell::GetFlyNum(unsigned long,enum FlyCntType,_Bool) const + _Bool bIgnoreTextBoxes + 0 +sw/inc/fesh.hxx:422 + class std::__debug::vector > SwFEShell::GetFlyFrameFormats(enum FlyCntType,_Bool) + _Bool bIgnoreTextBoxes + 1 +sw/inc/fmtcol.hxx:74 + void SwTextFormatColl::SwTextFormatColl(class SwAttrPool &,const char *,class SwTextFormatColl *,unsigned short) + class SwTextFormatColl * pDerFrom + 0 +sw/inc/fmtcol.hxx:171 + void SwGrfFormatColl::SwGrfFormatColl(class SwAttrPool &,const char *,class SwGrfFormatColl *) + class SwGrfFormatColl * pDerFrom + 0 +sw/inc/frmfmt.hxx:86 + void SwFrameFormat::SwFrameFormat(class SwAttrPool &,const char *,class SwFrameFormat *,unsigned short,const unsigned short *) + const unsigned short * pWhichRange + 0 +sw/inc/IDocumentMarkAccess.hxx:100 + class IDocumentMarkAccess::iterator IDocumentMarkAccess::iterator::operator-(long) const + ###1 + 1 +sw/inc/IDocumentMarkAccess.hxx:346 + class sw::mark::IMark * IDocumentMarkAccess::makeAnnotationBookmark(const class SwPaM &,const class rtl::OUString &,enum IDocumentMarkAccess::MarkType,enum sw::mark::InsertMode,const struct SwPosition *) + enum sw::mark::InsertMode eMode + 0 +sw/inc/IDocumentMarkAccess.hxx:346 + class sw::mark::IMark * IDocumentMarkAccess::makeAnnotationBookmark(const class SwPaM &,const class rtl::OUString &,enum IDocumentMarkAccess::MarkType,enum sw::mark::InsertMode,const struct SwPosition *) + const struct SwPosition * pSepPos + 0 +sw/inc/IDocumentRedlineAccess.hxx:194 + _Bool IDocumentRedlineAccess::RejectRedline(unsigned long,_Bool) + _Bool bCallDelete + 1 +sw/inc/IDocumentUndoRedo.hxx:209 + unsigned long IDocumentUndoRedo::GetUndoActionCount(const _Bool) const + const _Bool bCurrentLevel + 1 +sw/inc/index.hxx:62 + int SwIndex::operator--(int) + ###1 + 0 +sw/inc/ndgrf.hxx:64 + void SwGrfNode::SwGrfNode(const class SwNodeIndex &,const class GraphicObject &,class SwGrfFormatColl *,const class SwAttrSet *) + const class SwAttrSet * pAutoAttr + 0 +sw/inc/ndindex.hxx:83 + unsigned long SwNodeIndex::operator++(int) + ###1 + 0 +sw/inc/ndindex.hxx:84 + unsigned long SwNodeIndex::operator--(int) + ###1 + 0 +sw/inc/ndindex.hxx:140 + void SwNodeRange::SwNodeRange(class SwNodes &,unsigned long,unsigned long) + unsigned long nEndIdx + 0 +sw/inc/ndole.hxx:96 + void SwOLENode::SwOLENode(const class SwNodeIndex &,const class svt::EmbeddedObjectRef &,class SwGrfFormatColl *,const class SwAttrSet *) + const class SwAttrSet * pAutoAttr + 0 +sw/inc/ndtxt.hxx:323 + void SwTextNode::CopyText(class SwTextNode *const,const class SwIndex &,const int,const _Bool) + const _Bool bForceCopyOfAllAttrs + 1 +sw/inc/ndtxt.hxx:693 + _Bool SwTextNode::CopyExpandText(class SwTextNode &,const class SwIndex *,int,int,const class SwRootFrame *,_Bool,_Bool,_Bool) const + _Bool bWithNum + 0 +sw/inc/ndtxt.hxx:703 + int SwTextNode::GetDropLen(int) const + int nWishLen + 0 +sw/inc/pam.hxx:149 + void SwPaM::SwPaM(const class SwNodeIndex &,const class SwNodeIndex &,long,long,class SwPaM *) + class SwPaM * pRing + 0 +sw/inc/pam.hxx:153 + void SwPaM::SwPaM(const class SwNodeIndex &,int,const class SwNodeIndex &,int,class SwPaM *) + class SwPaM * pRing + 0 +sw/inc/pam.hxx:158 + void SwPaM::SwPaM(const class SwNodeIndex &,int,class SwPaM *) + class SwPaM * pRing + 0 +sw/inc/shellio.hxx:514 + void SwWriter::SwWriter(class SvStream &,class SwCursorShell &,_Bool) + _Bool bWriteAll + 0 +sw/inc/shellio.hxx:516 + void SwWriter::SwWriter(class SvStream &,class SwPaM &,_Bool) + _Bool bWriteAll + 0 +sw/inc/shellio.hxx:520 + void SwWriter::SwWriter(class SfxMedium &,class SwCursorShell &,_Bool) + _Bool bWriteAll + 1 +sw/inc/swabstdlg.hxx:298 + void AbstractSwSelGlossaryDlg::SelectEntryPos(int) + int nIdx + 0 +sw/inc/swcrsr.hxx:124 + unsigned long SwCursor::FindFormat(const class SwTextFormatColl &,enum SwDocPositions,enum SwDocPositions,_Bool &,enum FindRanges,const class SwTextFormatColl *,const class SwRootFrame *const) + const class SwRootFrame *const pLayout + 0 +sw/inc/swcrsr.hxx:151 + _Bool SwCursor::SelectWordWT(const class SwViewShell *,short,const class Point *) + short nWordType + 1 +sw/inc/swmodule.hxx:159 + void SwModule::ApplyRulerMetric(enum FieldUnit,_Bool,_Bool) + _Bool bWeb + 0 +sw/inc/undobj.hxx:325 + void SwUndoInsLayFormat::SwUndoInsLayFormat(class SwFrameFormat *,unsigned long,int) + unsigned long nNodeIdx + 0 +sw/inc/undobj.hxx:325 + void SwUndoInsLayFormat::SwUndoInsLayFormat(class SwFrameFormat *,unsigned long,int) + int nCntIdx + 0 +sw/inc/undobj.hxx:348 + void SwUndoDelLayFormat::ChgShowSel(_Bool) + _Bool bNew + 0 +sw/inc/unocrsrhelper.hxx:157 + void SetPropertyValue(class SwPaM &,const class SfxItemPropertySet &,const class rtl::OUString &,const class com::sun::star::uno::Any &,const enum SetAttrMode) + const enum SetAttrMode nAttrMode + 0 +sw/qa/extras/ooxmlimport/ooxmlimport.cxx:96 + void FailTest::executeImportTest(const char *,const char *) + const char * + 0 +sw/qa/extras/ooxmlimport/ooxmlimport.cxx:749 + void lcl_countTextFrames(const class com::sun::star::uno::Reference &,int) + int nExpected + 1 +sw/qa/inc/swmodeltestbase.hxx:179 + void SwModelTestBase::executeImportTest(const char *,const char *) + const char * pPassword + 0 +sw/qa/inc/swmodeltestbase.hxx:193 + void SwModelTestBase::executeLoadReloadVerify(const char *,const char *) + const char * pPassword + 0 +sw/qa/inc/swmodeltestbase.hxx:201 + void SwModelTestBase::executeImportExport(const char *,const char *) + const char * pPassword + 0 +sw/source/core/access/accmap.cxx:455 + void SwAccessibleEvent_Impl::SwAccessibleEvent_Impl(enum SwAccessibleEvent_Impl::EventType,class SwAccessibleContext *,const class sw::access::SwAccessibleChild &,const enum AccessibleStates) + enum SwAccessibleEvent_Impl::EventType eT + 0 +sw/source/core/crsr/swcrsr.cxx:72 + void (anonymous namespace)::PercentHdl::PercentHdl(unsigned long,unsigned long,class SwDocShell *) + unsigned long nStt + 0 +sw/source/core/doc/doccomp.cxx:156 + void (anonymous namespace)::CompareMainText::CompareMainText(class SwDoc &,_Bool) + _Bool bRecordDiff + 0 +sw/source/core/inc/drawfont.hxx:107 + void SwDrawTextInfo::SwDrawTextInfo(const class SwViewShell *,class OutputDevice &,const class rtl::OUString &,const int,const int,unsigned short,_Bool) + unsigned short nWidth + 0 +sw/source/core/inc/drawfont.hxx:107 + void SwDrawTextInfo::SwDrawTextInfo(const class SwViewShell *,class OutputDevice &,const class rtl::OUString &,const int,const int,unsigned short,_Bool) + _Bool bBullet + 0 +sw/source/core/inc/ftnfrm.hxx:55 + class SwFootnoteFrame * SwFootnoteContFrame::AppendChained(class SwFrame *,_Bool) + _Bool bDefaultFormat + 1 +sw/source/core/inc/ftnfrm.hxx:56 + class SwFootnoteFrame * SwFootnoteContFrame::PrependChained(class SwFrame *,_Bool) + _Bool bDefaultFormat + 0 +sw/source/core/inc/rolbck.hxx:400 + void SwHistory::CopyAttr(const class SwpHints *,const unsigned long,const int,const int,const _Bool) + const int nStart + 0 +sw/source/core/inc/scriptinfo.hxx:388 + enum SwFontScript SwScriptInfo::WhichFont(int,const class rtl::OUString &) + int nIdx + 0 +sw/source/core/inc/swfont.hxx:287 + const class rtl::OUString & SwFont::GetName(const enum SwFontScript) const + const enum SwFontScript nWhich + 0 +sw/source/core/inc/txmsrt.hxx:113 + class rtl::OUString SwTOXInternational::ToUpper(const class rtl::OUString &,int) const + int nPos + 0 +sw/source/core/inc/UndoDelete.hxx:68 + void SwUndoDelete::SwUndoDelete(class SwPaM &,_Bool,_Bool) + _Bool bCalledByTableCpy + 0 +sw/source/core/inc/UndoTable.hxx:254 + void SwUndoTableNumFormat::SwUndoTableNumFormat(const class SwTableBox &,const class SfxItemSet *) + const class SfxItemSet * pNewSet + 0 +sw/source/core/inc/wrong.hxx:347 + void SwWrongList::InsertSubList(int,int,unsigned short,class SwWrongList *) + int nNewLen + 1 +sw/source/core/txtnode/txtedt.cxx:180 + _Bool lcl_MaskRedlinesAndHiddenText(const class SwTextNode &,class rtl::OUStringBuffer &,int,int,const char16_t) + int nStt + 0 +sw/source/core/undo/untbl.cxx:2174 + void (anonymous namespace)::RedlineFlagsInternGuard::RedlineFlagsInternGuard(class SwDoc &,enum RedlineFlags,enum RedlineFlags) + enum RedlineFlags eNewRedlineFlags + 0 +sw/source/filter/html/htmltab.cxx:480 + unsigned short HTMLTable::GetBottomCellSpace(unsigned short,unsigned short) const + unsigned short nRowSpan + 1 +sw/source/filter/html/htmltab.cxx:496 + class SwTableLine * HTMLTable::MakeTableLine(class SwTableBox *,unsigned short,unsigned short,unsigned short,unsigned short) + unsigned short nLeftCol + 0 +sw/source/filter/html/swhtml.hxx:834 + void SwHTMLParser::BuildTableCell(class HTMLTable *,_Bool,_Bool) + _Bool bReadOptions + 1 +sw/source/filter/html/wrthtml.hxx:471 + void SwHTMLWriter::OutBackground(const class SfxItemSet &,_Bool) + _Bool bGraphic + 0 +sw/source/filter/inc/fltshell.hxx:317 + void ImportProgress::ImportProgress(class SwDocShell *,long,long) + long nStartVal + 0 +sw/source/filter/inc/wrtswtbl.hxx:281 + unsigned short SwWriteTable::GetRelWidth(unsigned short,unsigned short) const + unsigned short nColSpan + 1 +sw/source/filter/ww8/docxattributeoutput.hxx:737 + void DocxAttributeOutput::CmdEndField_Impl(const class SwTextNode *,int,_Bool) + _Bool bWriteRun + 1 +sw/source/filter/ww8/needed_cast.hxx:27 + type-parameter-?-? checking_cast(type-parameter-?-?,type-parameter-?-?) + type-parameter-?-? + 0 +sw/source/filter/ww8/writerwordglue.cxx:330 + void myImplHelpers::(anonymous namespace)::IfBeforeStart::IfBeforeStart(int) + int nStart + 0 +sw/source/filter/ww8/wrtww8.hxx:181 + void WW8_SepInfo::WW8_SepInfo(const class SwPageDesc *,const class SwSectionFormat *,unsigned long,class std::optional,const class SwNode *,_Bool) + _Bool bIsFirstPara + 0 +sw/source/filter/ww8/wrtww8.hxx:641 + void MSWordExportBase::OutputItemSet(const class SfxItemSet &,_Bool,_Bool,unsigned short,_Bool) + unsigned short nScript + 1 +sw/source/filter/ww8/wrtww8.hxx:890 + void MSWordExportBase::NearestAnnotationMark(int &,const int,_Bool) + _Bool bNextPositionOnly + 0 +sw/source/filter/ww8/wrtww8.hxx:1374 + void WW8_WrMagicTable::Append(int,unsigned long) + int nCp + 0 +sw/source/filter/ww8/wrtww8.hxx:1374 + void WW8_WrMagicTable::Append(int,unsigned long) + unsigned long nData + 0 +sw/source/filter/ww8/ww8par.cxx:439 + class rtl::OUString (anonymous namespace)::Sttb::getStringAtIndex(unsigned int) + unsigned int + 1 +sw/source/filter/ww8/ww8par.hxx:1689 + _Bool SwWW8ImplReader::SetUpperSpacing(class SwPaM &,int) + int nSpace + 0 +sw/source/filter/ww8/ww8scan.hxx:169 + class rtl::OUString read_uInt8_BeltAndBracesString(class SvStream &,unsigned short) + unsigned short eEnc + 1 +sw/source/filter/ww8/ww8scan.hxx:469 + void WW8PLCFx_PCD::WW8PLCFx_PCD(const class WW8Fib &,class WW8PLCFpcd *,int,_Bool) + int nStartCp + 0 +sw/source/filter/ww8/ww8scan.hxx:676 + void WW8PLCFx_SEPX::WW8PLCFx_SEPX(class SvStream *,class SvStream *,const class WW8Fib &,int) + int nStartCp + 0 +sw/source/filter/ww8/ww8scan.hxx:704 + void WW8PLCFx_SubDoc::WW8PLCFx_SubDoc(class SvStream *,const class WW8Fib &,int,long,long,long,long,long) + int nStartCp + 0 +sw/source/filter/ww8/WW8TableInfo.hxx:303 + class ww8::WW8TableNodeInfo * ww8::WW8TableInfo::processTableLine(const class SwTable *,const class SwTableLine *,unsigned int,unsigned int,class ww8::WW8TableNodeInfo *,class std::__debug::map, class std::allocator > > &) + unsigned int nDepth + 1 +sw/source/filter/xml/xmlfmt.cxx:379 + void (anonymous namespace)::SwXMLCellStyleContext::XMLPropStyleContext(class SvXMLImport &,class SvXMLStylesContext &,enum XmlStyleFamily,_Bool) + _Bool + 0 +sw/source/ui/misc/impfnote.hxx:64 + void SwEndNoteOptionPage::SwEndNoteOptionPage(class weld::Container *,class weld::DialogController *,_Bool,const class SfxItemSet &) + _Bool bEndNote + 0 +sw/source/ui/table/instable.cxx:171 + void lcl_SetProperties(class SwTableAutoFormat *,_Bool) + _Bool bVal + 0 +sw/source/ui/vba/vbarangehelper.hxx:32 + void SwVbaRangeHelper::insertString(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,_Bool) + _Bool _bAbsorb + 1 +sw/source/uibase/inc/condedit.hxx:64 + void ConditionEdit::ShowBrackets(_Bool) + _Bool bShow + 0 +sw/source/uibase/inc/dbtree.hxx:59 + class std::unique_ptr > SwDBTreeList::make_iterator(const class weld::TreeIter *) const + const class weld::TreeIter * pOrig + 0 +sw/source/uibase/inc/edtwin.hxx:216 + void SwEditWin::StdDrawMode(enum SdrObjKind,_Bool) + enum SdrObjKind eSdrObjectKind + 0 +sw/source/uibase/inc/frmmgr.hxx:99 + void SwFlyFrameAttrMgr::SetLRSpace(long,long) + long nLeft + 0 +sw/source/uibase/inc/frmmgr.hxx:99 + void SwFlyFrameAttrMgr::SetLRSpace(long,long) + long nRight + 0 +sw/source/uibase/inc/frmmgr.hxx:101 + void SwFlyFrameAttrMgr::SetULSpace(long,long) + long nTop + 0 +sw/source/uibase/inc/frmmgr.hxx:101 + void SwFlyFrameAttrMgr::SetULSpace(long,long) + long nBottom + 0 +sw/source/uibase/inc/mmconfigitem.hxx:137 + void SwMailMergeConfigItem::SetIndividualGreeting(_Bool,_Bool) + _Bool bInEMail + 0 +sw/source/uibase/inc/numfmtlb.hxx:132 + void SwNumFormatTreeView::select(int) + int nPos + 0 +sw/source/uibase/inc/prcntfld.hxx:69 + int SwPercentField::get_min(enum FieldUnit) const + enum FieldUnit eOutUnit + 0 +sw/source/uibase/inc/swuipardlg.hxx:34 + void SwParaDlg::SwParaDlg(class weld::Window *,class SwView &,const class SfxItemSet &,unsigned char,const class rtl::OUString *,_Bool,const class rtl::OString &) + _Bool bDraw + 0 +sw/source/uibase/inc/wrtsh.hxx:120 + void SwWrtShell::EndDrag(const class Point *,_Bool) + _Bool bProp + 0 +sw/source/uibase/inc/wrtsh.hxx:121 + long SwWrtShell::KillSelection(const class Point *,_Bool) + const class Point * pPt + 0 +sw/source/uibase/inc/wrtsh.hxx:121 + long SwWrtShell::KillSelection(const class Point *,_Bool) + _Bool bProp + 0 +sw/source/uibase/inc/wrtsh.hxx:415 + _Bool SwWrtShell::GotoMark(const class sw::mark::IMark *const,_Bool) + _Bool bSelect + 0 +sw/source/uibase/inc/wrtsh.hxx:485 + const class SwRangeRedline * SwWrtShell::GotoRedline(unsigned long,_Bool) + _Bool bSelect + 1 +sw/source/uibase/inc/wrtsh.hxx:495 + void SwWrtShell::ToggleOutlineContentVisibility(class SwNode *,const _Bool) + const _Bool bForceNotVisible + 1 +test/source/sheet/xdatapilottable2.cxx:237 + struct com::sun::star::table::CellAddress getLastUsedCellAddress(const class com::sun::star::uno::Reference &,int,int) + int nCol + 0 +test/source/sheet/xdatapilottable2.cxx:237 + struct com::sun::star::table::CellAddress getLastUsedCellAddress(const class com::sun::star::uno::Reference &,int,int) + int nRow + 0 +ucb/source/ucp/tdoc/tdoc_provider.hxx:110 + class com::sun::star::uno::Reference tdoc_ucp::ContentProvider::queryOutputStream(const class rtl::OUString &,const class rtl::OUString &,_Bool) const + _Bool bTruncate + 1 +ucb/source/ucp/tdoc/tdoc_provider.hxx:117 + class com::sun::star::uno::Reference tdoc_ucp::ContentProvider::queryStream(const class rtl::OUString &,const class rtl::OUString &,_Bool) const + _Bool bTruncate + 0 +ucb/source/ucp/webdav-neon/DAVResourceAccess.hxx:105 + void webdav_ucp::DAVResourceAccess::PROPFIND(const enum webdav_ucp::Depth,class std::__debug::vector > &,const class com::sun::star::uno::Reference &) + const enum webdav_ucp::Depth nDepth + 0 +ucb/source/ucp/webdav-neon/DAVTypes.hxx:179 + void webdav_ucp::DAVOptionsCache::setHeadAllowed(const class rtl::OUString &,_Bool) + _Bool HeadAllowed + 0 +ucb/source/ucp/webdav-neon/NeonSession.hxx:250 + int webdav_ucp::NeonSession::GET0(struct ne_session_s *,const char *,_Bool,void *) + _Bool getheaders + 1 +vbahelper/source/vbahelper/vbacommandbarcontrols.hxx:36 + class com::sun::star::uno::Sequence ScVbaCommandBarControls::CreateMenuItemData(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,unsigned short,const class com::sun::star::uno::Any &,_Bool,_Bool) + _Bool isVisible + 1 +vbahelper/source/vbahelper/vbacommandbarcontrols.hxx:36 + class com::sun::star::uno::Sequence ScVbaCommandBarControls::CreateMenuItemData(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,unsigned short,const class com::sun::star::uno::Any &,_Bool,_Bool) + _Bool isEnabled + 1 +vbahelper/source/vbahelper/vbacommandbarcontrols.hxx:43 + class com::sun::star::uno::Sequence ScVbaCommandBarControls::CreateToolbarItemData(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,unsigned short,const class com::sun::star::uno::Any &,_Bool,int) + _Bool isVisible + 1 +vbahelper/source/vbahelper/vbacommandbarcontrols.hxx:43 + class com::sun::star::uno::Sequence ScVbaCommandBarControls::CreateToolbarItemData(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,unsigned short,const class com::sun::star::uno::Any &,_Bool,int) + int nStyle + 0 +vcl/backendtest/outputdevice/common.cxx:205 + enum vcl::test::TestResult checkDiamondLine(class Bitmap &,int,class Color) + int aLayerNumber + 1 +vcl/backendtest/VisualBackendTest.cxx:54 + void drawBitmapScaledAndCentered(const class tools::Rectangle &,class Bitmap,class OutputDevice &,enum BmpScaleFlag) + enum BmpScaleFlag aFlag + 1 +vcl/headless/svpgdi.cxx:398 + void (anonymous namespace)::BitmapHelper::BitmapHelper(const class SalBitmap &,const _Bool) + const _Bool bForceARGB32 + 1 +vcl/inc/driverblocklist.hxx:28 + _Bool IsDeviceBlocked(const class rtl::OUString &,enum DriverBlocklist::VersionType,class std::basic_string_view >,class std::basic_string_view >,const class rtl::OUString &) + enum DriverBlocklist::VersionType versionType + 1 +vcl/inc/FileDefinitionWidgetDraw.hxx:61 + void vcl::FileDefinitionWidgetDraw::drawPolyLine(class SalGraphics &,const class basegfx::B2DHomMatrix &,const class basegfx::B2DPolygon &,double,double,const class std::__debug::vector > *,enum basegfx::B2DLineJoin,enum com::sun::star::drawing::LineCap,double,_Bool) + const class std::__debug::vector > * i_pStroke + 0 +vcl/inc/FileDefinitionWidgetDraw.hxx:61 + void vcl::FileDefinitionWidgetDraw::drawPolyLine(class SalGraphics &,const class basegfx::B2DHomMatrix &,const class basegfx::B2DPolygon &,double,double,const class std::__debug::vector > *,enum basegfx::B2DLineJoin,enum com::sun::star::drawing::LineCap,double,_Bool) + enum com::sun::star::drawing::LineCap i_eLineCap + 1 +vcl/inc/FileDefinitionWidgetDraw.hxx:61 + void vcl::FileDefinitionWidgetDraw::drawPolyLine(class SalGraphics &,const class basegfx::B2DHomMatrix &,const class basegfx::B2DPolygon &,double,double,const class std::__debug::vector > *,enum basegfx::B2DLineJoin,enum com::sun::star::drawing::LineCap,double,_Bool) + _Bool bPixelSnapHairline + 0 +vcl/inc/jsdialog/jsdialogbuilder.hxx:294 + void JSWidget::JSWidget(class JSDialogSender *,type-parameter-?-? *,class SalInstanceBuilder *,const class com::sun::star::uno::Reference &,class std::function > (class vcl::Window *)>,void *,_Bool) + _Bool bTakeOwnership + 0 +vcl/inc/jsdialog/jsdialogbuilder.hxx:374 + void JSDialog::JSDialog(class JSDialogSender *,class Dialog *,class SalInstanceBuilder *,_Bool) + _Bool bTakeOwnership + 0 +vcl/inc/jsdialog/jsdialogbuilder.hxx:393 + void JSButton::JSButton(class JSDialogSender *,class Button *,class SalInstanceBuilder *,_Bool) + class SalInstanceBuilder * pBuilder + 0 +vcl/inc/jsdialog/jsdialogbuilder.hxx:393 + void JSButton::JSButton(class JSDialogSender *,class Button *,class SalInstanceBuilder *,_Bool) + _Bool bTakeOwnership + 0 +vcl/inc/jsdialog/jsdialogbuilder.hxx:463 + void JSMessageDialog::JSMessageDialog(class JSDialogSender *,class MessageDialog *,class SalInstanceBuilder *,_Bool) + _Bool bTakeOwnership + 0 +vcl/inc/jsdialog/jsdialogbuilder.hxx:465 + void JSMessageDialog::JSMessageDialog(class MessageDialog *,class SalInstanceBuilder *,_Bool) + class SalInstanceBuilder * pBuilder + 0 +vcl/inc/jsdialog/jsdialogbuilder.hxx:465 + void JSMessageDialog::JSMessageDialog(class MessageDialog *,class SalInstanceBuilder *,_Bool) + _Bool bTakeOwnership + 1 +vcl/inc/listbox.hxx:143 + class rtl::OUString ImplEntryList::GetSelectedEntry(int) const + int nIndex + 0 +vcl/inc/listbox.hxx:334 + void ImplListBoxWindow::EnableMouseMoveSelect(_Bool) + _Bool bMouseMoveSelect + 1 +vcl/inc/qt5/Qt5Graphics_Controls.hxx:94 + class QSize Qt5Graphics_Controls::downscale(const class QSize &,enum Qt5Graphics_Controls::Round) + enum Qt5Graphics_Controls::Round eRound + 1 +vcl/inc/qt5/Qt5Graphics_Controls.hxx:95 + class QSize Qt5Graphics_Controls::upscale(const class QSize &,enum Qt5Graphics_Controls::Round) + enum Qt5Graphics_Controls::Round eRound + 1 +vcl/inc/qt5/Qt5VirtualDevice.hxx:42 + void Qt5VirtualDevice::Qt5VirtualDevice(enum DeviceFormat,double) + double fScale + 1 +vcl/inc/qt5/Qt5Widget.hxx:49 + _Bool Qt5Widget::handleKeyEvent(class Qt5Frame &,const class QWidget &,class QKeyEvent *,const enum Qt5Widget::ButtonKeyState) + const enum Qt5Widget::ButtonKeyState + 1 +vcl/inc/salgdi.hxx:144 + void SalGraphics::GetFontMetric(class tools::SvRef &,int) + int nFallbackLevel + 0 +vcl/inc/salgdi.hxx:520 + void SalGraphics::copyArea(long,long,long,long,long,long,_Bool) + _Bool bWindowInvalidate + 1 +vcl/inc/salgdi.hxx:655 + _Bool SalGraphics::CreateTTFfontSubset(class vcl::AbstractTrueTypeFont &,const class rtl::OString &,const _Bool,const unsigned short *,const unsigned char *,int *,int) + const _Bool bVertical + 0 +vcl/inc/scrptrun.h:68 + void vcl::ScriptRun::reset(const char16_t *,int,int) + int start + 0 +vcl/inc/sft.hxx:478 + enum vcl::SFErrCodes OpenTTFontBuffer(const void *,unsigned int,unsigned int,class vcl::TrueTypeFont **,const class tools::SvRef) + unsigned int facenum + 0 +vcl/inc/sft.hxx:594 + enum vcl::SFErrCodes CreateT3FromTTGlyphs(class vcl::TrueTypeFont *,struct _IO_FILE *,const char *,const unsigned short *,unsigned char *,int,int) + int wmode + 0 +vcl/inc/skia/gdiimpl.hxx:225 + void SkiaSalGraphicsImpl::drawGenericLayout(const class GenericSalLayout &,class Color,const class SkFont &,enum SkiaSalGraphicsImpl::GlyphOrientation) + enum SkiaSalGraphicsImpl::GlyphOrientation glyphOrientation + 0 +vcl/inc/skia/utils.hxx:39 + void disableRenderMethod(enum SkiaHelper::RenderMethod) + enum SkiaHelper::RenderMethod method + 1 +vcl/inc/svimpbox.hxx:259 + void SvImpLBox::SelectEntry(class SvTreeListEntry *,_Bool) + _Bool bSelect + 0 +vcl/inc/unx/gendisp.hxx:45 + _Bool SalGenericDisplay::DispatchInternalEvent(_Bool) + _Bool bHandleAllCurrentEvent + 0 +vcl/inc/unx/gtk/gloactiongroup.h:51 + void g_lo_action_group_insert(struct GLOActionGroup *,const char *,int,int) + int submenu + 0 +vcl/inc/unx/gtk/gloactiongroup.h:56 + void g_lo_action_group_insert_stateful(struct GLOActionGroup *,const char *,int,int,const struct _GVariantType *,const struct _GVariantType *,struct _GVariant *,struct _GVariant *) + struct _GVariant * state_hint + 0 +vcl/inc/unx/gtk/glomenu.h:49 + void g_lo_menu_new_section(struct GLOMenu *,int,const char *) + const char * label + 0 +vcl/inc/unx/gtk/hudawareness.h:20 + unsigned int hud_awareness_register(struct _GDBusConnection *,const char *,void (*)(int, void *),void *,void (*)(void *),struct _GError **) + void (*)(void *) notify + 0 +vcl/inc/unx/gtk/hudawareness.h:20 + unsigned int hud_awareness_register(struct _GDBusConnection *,const char *,void (*)(int, void *),void *,void (*)(void *),struct _GError **) + struct _GError ** error + 0 +vcl/inc/unx/printergfx.hxx:226 + void psp::PrinterGfx::PSSetFont(const class rtl::OString &,unsigned short) + unsigned short nEncoding + 0 +vcl/inc/unx/printergfx.hxx:252 + void psp::PrinterGfx::PSHexString(const unsigned char *,short) + short nLen + 1 +vcl/inc/unx/salbmp.h:49 + class std::unique_ptr > X11SalBitmap::ImplCreateDIB(unsigned long,class SalX11Screen,long,long,long,long,long,_Bool) + long nX + 0 +vcl/inc/unx/salbmp.h:49 + class std::unique_ptr > X11SalBitmap::ImplCreateDIB(unsigned long,class SalX11Screen,long,long,long,long,long,_Bool) + long nY + 0 +vcl/inc/unx/wmadaptor.hxx:181 + const class tools::Rectangle & vcl_sal::WMAdaptor::getWorkArea(int) const + int n + 0 +vcl/inc/unx/x11/xrender_peer.hxx:45 + XRenderPictFormat * XRenderPeer::FindStandardFormat(int) const + int nFormat + 0 +vcl/inc/unx/x11/xrender_peer.hxx:61 + void XRenderPeer::CompositeTrapezoids(int,unsigned long,unsigned long,const XRenderPictFormat *,int,int,const struct _XTrapezoid *,int) const + int nXSrc + 0 +vcl/inc/unx/x11/xrender_peer.hxx:61 + void XRenderPeer::CompositeTrapezoids(int,unsigned long,unsigned long,const XRenderPictFormat *,int,int,const struct _XTrapezoid *,int) const + int nYSrc + 0 +vcl/inc/unx/x11/xrender_peer.hxx:64 + void XRenderPeer::CompositeTriangles(int,unsigned long,unsigned long,const XRenderPictFormat *,int,int,const struct _XTriangle *,int) const + int nXSrc + 0 +vcl/inc/unx/x11/xrender_peer.hxx:64 + void XRenderPeer::CompositeTriangles(int,unsigned long,unsigned long,const XRenderPictFormat *,int,int,const struct _XTriangle *,int) const + int nYSrc + 0 +vcl/inc/wizdlg.hxx:123 + _Bool vcl::RoadmapWizard::Finish(long) + long nResult + 1 +vcl/qa/cppunit/BitmapTest.cxx:67 + void assertColorsAreSimilar(int,const class std::__cxx11::basic_string, class std::allocator > &,const class BitmapColor &,const class BitmapColor &) + int maxDifference + 1 +vcl/qa/cppunit/PDFDocumentTest.cxx:174 + class vcl::filter::PDFObjectElement * addObjectElement(class std::__debug::vector >, class std::allocator > > > &,class vcl::filter::PDFDocument &,int,int) + int nObjectNumber + 1 +vcl/qa/cppunit/PDFDocumentTest.cxx:174 + class vcl::filter::PDFObjectElement * addObjectElement(class std::__debug::vector >, class std::allocator > > > &,class vcl::filter::PDFDocument &,int,int) + int nGenerationNumber + 0 +vcl/source/app/salvtables.cxx:1804 + void (anonymous namespace)::SalInstanceAssistant::SalInstanceAssistant(class vcl::RoadmapWizard *,class SalInstanceBuilder *,_Bool) + _Bool bTakeOwnership + 0 +vcl/source/app/salvtables.cxx:2002 + void (anonymous namespace)::SalInstanceFrame::SalInstanceFrame(class VclFrame *,class SalInstanceBuilder *,_Bool) + _Bool bTakeOwnership + 0 +vcl/source/app/salvtables.cxx:6649 + void (anonymous namespace)::SalInstancePopover::SalInstancePopover(class DockingWindow *,class SalInstanceBuilder *,_Bool) + _Bool bTakeOwnership + 0 +vcl/source/bitmap/BitmapBasicMorphologyFilter.cxx:225 + void runFilter(class Bitmap &,const long,const _Bool,_Bool,unsigned char) + const _Bool bParallel + 1 +vcl/source/bitmap/BitmapFilterStackBlur.cxx:147 + void (anonymous namespace)::SumFunction24::set(long *&,long) + long nConstant + 0 +vcl/source/bitmap/BitmapFilterStackBlur.cxx:205 + void (anonymous namespace)::SumFunction8::set(long *&,long) + long nConstant + 0 +vcl/source/bitmap/BitmapFilterStackBlur.cxx:478 + void runStackBlur(class Bitmap &,const long,const long,const long,void (*)(const struct (anonymous namespace)::BlurSharedData &, long, long),void (*)(const struct (anonymous namespace)::BlurSharedData &, long, long),const _Bool) + const _Bool bParallel + 1 +vcl/source/bitmap/bmpfast.cxx:34 + void (anonymous namespace)::BasePixelPtr::BasePixelPtr(unsigned char *) + unsigned char * p + 0 +vcl/source/control/imivctl.hxx:359 + const class Size & SvxIconChoiceCtrl_Impl::GetItemSize(enum IcnViewFieldType) const + enum IcnViewFieldType + 1 +vcl/source/control/imivctl.hxx:405 + void SvxIconChoiceCtrl_Impl::SetColumn(unsigned short,const class SvxIconChoiceCtrlColumnInfo &) + unsigned short nIndex + 0 +vcl/source/control/imivctl.hxx:406 + const class SvxIconChoiceCtrlColumnInfo * SvxIconChoiceCtrl_Impl::GetColumn(unsigned short) const + unsigned short nIndex + 0 +vcl/source/filter/eps/eps.cxx:92 + enum (anonymous namespace)::NMode operator|(enum (anonymous namespace)::NMode,enum (anonymous namespace)::NMode) + enum (anonymous namespace)::NMode a + 1 +vcl/source/filter/eps/eps.cxx:213 + void (anonymous namespace)::PSWriter::ImplWriteLineColor(enum (anonymous namespace)::NMode) + enum (anonymous namespace)::NMode nMode + 1 +vcl/source/filter/eps/eps.cxx:214 + void (anonymous namespace)::PSWriter::ImplWriteFillColor(enum (anonymous namespace)::NMode) + enum (anonymous namespace)::NMode nMode + 1 +vcl/source/filter/FilterConfigCache.hxx:89 + class rtl::OUString FilterConfigCache::GetExportWildcard(unsigned short,int) + int nEntry + 0 +vcl/source/filter/jpeg/Exif.cxx:170 + void write32(unsigned int,unsigned char (&)[4],_Bool) + unsigned int value + 1 +vcl/source/filter/wmf/wmfwr.hxx:162 + void WMFWriter::WMFRecord_SetBkMode(_Bool) + _Bool bTransparent + 1 +vcl/source/fontsubset/list.h:64 + int listSkipForward(struct list_ *,int) + int n + 1 +vcl/source/gdi/FileDefinitionWidgetDraw.cxx:102 + _Bool getSettingValueBool(class std::basic_string_view >,_Bool) + _Bool bDefault + 1 +vcl/source/window/menufloatingwindow.hxx:107 + void MenuFloatingWindow::EnableScrollMenu(_Bool) + _Bool b + 1 +vcl/source/window/menuitemlist.hxx:111 + struct MenuItemData * MenuItemList::Insert(unsigned short,enum MenuItemType,enum MenuItemBits,const class rtl::OUString &,class Menu *,unsigned long,const class rtl::OString &) + enum MenuItemType eType + 1 +vcl/source/window/window2.cxx:576 + void lcl_HandleScrollHelper(class ScrollBar *,double,_Bool) + _Bool isMultiplyByLineSize + 1 +vcl/unx/generic/app/randrwrapper.cxx:55 + void (anonymous namespace)::RandRWrapper::XRRSelectInput(struct _XDisplay *,unsigned long,int) + int i_nMask + 1 +vcl/unx/generic/print/psputil.hxx:50 + _Bool WritePS(class osl::File *,const char *,unsigned long) + unsigned long nInLength + 1 +vcl/unx/gtk3/gtk3gtkinst.cxx:4973 + void (anonymous namespace)::GtkInstanceMessageDialog::GtkInstanceMessageDialog(struct _GtkMessageDialog *,class (anonymous namespace)::GtkInstanceBuilder *,_Bool) + class (anonymous namespace)::GtkInstanceBuilder * pBuilder + 0 +vcl/unx/gtk3/gtk3gtkinst.cxx:4973 + void (anonymous namespace)::GtkInstanceMessageDialog::GtkInstanceMessageDialog(struct _GtkMessageDialog *,class (anonymous namespace)::GtkInstanceBuilder *,_Bool) + _Bool bTakeOwnership + 1 +vcl/unx/gtk3/gtk3gtkinst.cxx:15264 + int (anonymous namespace)::GtkInstanceComboBox::find_text_including_mru(class std::basic_string_view >,_Bool) const + _Bool bSearchMRU + 0 +workdir/../vcl/inc/qt5/Qt5Frame.hxx:210 + _Bool Qt5Frame::CallCallback(enum SalEvent,const void *) const + const void * pEvent + 0 +workdir/../vcl/inc/qt5/Qt5Instance.hxx:79 + _Bool Qt5Instance::ImplYieldSignal(_Bool,_Bool) + _Bool bWait + 0 +writerfilter/inc/dmapper/resourcemodel.hxx:237 + void writerfilter::Stream::text(const unsigned char *,unsigned long) + unsigned long len + 1 +writerfilter/inc/ooxml/OOXMLDocument.hxx:131 + void writerfilter::ooxml::OOXMLDocument::resolveFootnote(class writerfilter::Stream &,unsigned int,const int) + unsigned int aNoteType + 0 +writerfilter/inc/ooxml/OOXMLDocument.hxx:144 + void writerfilter::ooxml::OOXMLDocument::resolveEndnote(class writerfilter::Stream &,unsigned int,const int) + unsigned int aNoteType + 0 +writerfilter/source/dmapper/DomainMapper.hxx:120 + void writerfilter::dmapper::DomainMapper::hasControls(const _Bool) + const _Bool bSet + 1 +writerfilter/source/ooxml/OOXMLStreamImpl.hxx:62 + void writerfilter::ooxml::OOXMLStreamImpl::OOXMLStreamImpl(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,enum writerfilter::ooxml::OOXMLStream::StreamType_t,_Bool) + enum writerfilter::ooxml::OOXMLStream::StreamType_t nType + 1 +xmlhelp/source/cxxhelp/provider/databases.hxx:360 + void chelp::DataBaseIterator::DataBaseIterator(const class com::sun::star::uno::Reference &,class chelp::Databases &,const class rtl::OUString &,const class rtl::OUString &,_Bool) + _Bool bHelpText + 1 +xmlhelp/source/cxxhelp/provider/databases.hxx:365 + void chelp::DataBaseIterator::DataBaseIterator(class chelp::Databases &,const class rtl::OUString &,const class rtl::OUString &,_Bool) + _Bool bHelpText + 0 +xmloff/inc/txtflde.hxx:253 + void XMLTextFieldExport::ProcessIntegerDef(enum xmloff::token::XMLTokenEnum,int,int) + int nDefault + 0 +xmloff/inc/txtflde.hxx:324 + void XMLTextFieldExport::ProcessDateTime(enum xmloff::token::XMLTokenEnum,double,_Bool,_Bool,_Bool,unsigned short) + _Bool bOmitDurationIfZero + 1 +xmloff/inc/txtflde.hxx:333 + void XMLTextFieldExport::ProcessDateTime(enum xmloff::token::XMLTokenEnum,int,_Bool,_Bool) + _Bool bIsDuration + 1 +xmloff/source/chart/SchXMLTools.hxx:90 + void CreateCategories(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,int,int,class std::__debug::multimap, class com::sun::star::uno::Reference, struct std::less >, class std::allocator, class com::sun::star::uno::Reference > > > *) + int nCooSysIndex + 0 +xmloff/source/chart/SchXMLTools.hxx:121 + _Bool getXMLRangePropertyFromDataSequence(const class com::sun::star::uno::Reference &,class rtl::OUString &,_Bool) + _Bool bClearProp + 1 +xmloff/source/chart/transporttypes.hxx:183 + void DataRowPointStyle::DataRowPointStyle(enum DataRowPointStyle::StyleType,const class com::sun::star::uno::Reference &,int,int,const class rtl::OUString &,int) + int nPointRepeat + 1 +xmloff/source/chart/transporttypes.hxx:199 + void DataRowPointStyle::DataRowPointStyle(enum DataRowPointStyle::StyleType,const class rtl::OUString &,int) + int nAttachedAxis + 0 +xmloff/source/text/txtflde.cxx:276 + _Bool GetOptionalBoolProperty(const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,_Bool) + _Bool bDefault + 0 +xmloff/source/text/XMLIndexTemplateContext.hxx:86 + void XMLIndexTemplateContext::XMLIndexTemplateContext(class SvXMLImport &,class com::sun::star::uno::Reference &,const SvXMLEnumMapEntry *,enum xmloff::token::XMLTokenEnum,const char **,const _Bool *,_Bool) + _Bool bTOC_ + 0 +xmloff/source/text/XMLSectionExport.hxx:104 + _Bool XMLSectionExport::IsMuteSection(const class com::sun::star::uno::Reference &,_Bool) const + _Bool bDefault + 0 +xmloff/source/transform/TransformerBase.hxx:169 + const class XMLTransformerContext * XMLTransformerBase::GetAncestorContext(unsigned int) const + unsigned int i + 1 +xmlscript/source/xmldlg_imexp/exp_share.hxx:223 + void xmlscript::ElementDescriptor::read(const class rtl::OUString &,const class rtl::OUString &,_Bool) + _Bool forceAttribute + 0 +xmlsecurity/source/component/documentdigitalsignatures.cxx:95 + void (anonymous namespace)::DocumentDigitalSignatures::ImplViewSignatures(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,enum DocumentSignatureMode,_Bool) + _Bool bReadOnly + 1 diff --git a/compilerplugins/clang/constantparam.constructors.results b/compilerplugins/clang/constantparam.constructors.results new file mode 100644 index 000000000..c8348bc45 --- /dev/null +++ b/compilerplugins/clang/constantparam.constructors.results @@ -0,0 +1,1120 @@ +accessibility/source/extended/AccessibleBrowseBoxHeaderCell.cxx:120 + class tools::Rectangle getRectangle(class vcl::IAccessibleTableProvider *,int,_Bool,_Bool) + _Bool _bRowBar + isRowBarCell() +basctl/source/inc/dlged.hxx:202 + void basctl::DlgEditor::printPage(int,class Printer *,const class rtl::OUString &) + const class rtl::OUString & + CreateQualifiedName() +basic/inc/sbobjmod.hxx:88 + void SbUserFormModuleInstance::SbUserFormModuleInstance(class SbUserFormModule *,const class rtl::OUString &,const struct com::sun::star::script::ModuleInfo &,_Bool) + _Bool bIsVBACompat + IsVBACompat() +binaryurp/source/bridge.hxx:102 + class com::sun::star::uno::UnoInterfaceReference binaryurp::Bridge::registerIncomingInterface(const class rtl::OUString &,const class com::sun::star::uno::TypeDescription &) + const class rtl::OUString & oid + readOid() +bridges/source/jni_uno/nativethreadpool.cxx:40 + void (anonymous namespace)::Pool::Pool(const class rtl::Reference &,struct _jmethodID *,struct _uno_ThreadPool *) + struct _uno_ThreadPool * thePool + uno_threadpool_create() +chart2/source/controller/inc/CommandDispatchContainer.hxx:81 + void chart::CommandDispatchContainer::setChartDispatch(const class com::sun::star::uno::Reference &,const class o3tl::sorted_vector, find_unique, true> &) + const class o3tl::sorted_vector, find_unique, true> & rChartCommands + impl_getAvailableCommands() +chart2/source/view/axes/VCartesianAxis.cxx:416 + class rtl::OUString getTextLabelString(const class chart::FixedNumberFormatter &,const class com::sun::star::uno::Sequence *,const struct chart::TickInfo *,_Bool,class Color &,_Bool &) + _Bool bComplexCat + isComplexCategoryAxis() +connectivity/inc/sdbcx/VKeyColumn.hxx:37 + void connectivity::sdbcx::OKeyColumn::OKeyColumn(_Bool) + _Bool _bCase + isCaseSensitive() +connectivity/inc/sdbcx/VKeyColumn.hxx:38 + void connectivity::sdbcx::OKeyColumn::OKeyColumn(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,_Bool,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + _Bool _bCase + isCaseSensitive() +connectivity/source/commontools/TColumnsHelper.cxx:47 + void connectivity::OColumnsHelperImpl::OColumnsHelperImpl(_Bool) + _Bool _bCase + isCaseSensitive() +connectivity/source/drivers/evoab2/NTable.hxx:34 + void connectivity::evoab::OEvoabTable::OEvoabTable(class connectivity::sdbcx::OCollection *,class connectivity::evoab::OEvoabConnection *,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & SchemaName + "" +connectivity/source/drivers/evoab2/NTable.hxx:34 + void connectivity::evoab::OEvoabTable::OEvoabTable(class connectivity::sdbcx::OCollection *,class connectivity::evoab::OEvoabConnection *,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & CatalogName + "" +connectivity/source/inc/calc/CTable.hxx:55 + void connectivity::calc::OCalcTable::OCalcTable(class connectivity::sdbcx::OCollection *,class connectivity::calc::OCalcConnection *,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & Description + "" +connectivity/source/inc/calc/CTable.hxx:55 + void connectivity::calc::OCalcTable::OCalcTable(class connectivity::sdbcx::OCollection *,class connectivity::calc::OCalcConnection *,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & SchemaName + "" +connectivity/source/inc/calc/CTable.hxx:55 + void connectivity::calc::OCalcTable::OCalcTable(class connectivity::sdbcx::OCollection *,class connectivity::calc::OCalcConnection *,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & CatalogName + "" +connectivity/source/inc/dbase/DTable.hxx:145 + void connectivity::dbase::ODbaseTable::ODbaseTable(class connectivity::sdbcx::OCollection *,class connectivity::dbase::ODbaseConnection *,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & Description + "" +connectivity/source/inc/dbase/DTable.hxx:145 + void connectivity::dbase::ODbaseTable::ODbaseTable(class connectivity::sdbcx::OCollection *,class connectivity::dbase::ODbaseConnection *,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & SchemaName + "" +connectivity/source/inc/dbase/DTable.hxx:145 + void connectivity::dbase::ODbaseTable::ODbaseTable(class connectivity::sdbcx::OCollection *,class connectivity::dbase::ODbaseConnection *,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & CatalogName + "" +connectivity/source/inc/flat/ETable.hxx:76 + void connectivity::flat::OFlatTable::OFlatTable(class connectivity::sdbcx::OCollection *,class connectivity::flat::OFlatConnection *,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & Description + "" +connectivity/source/inc/flat/ETable.hxx:76 + void connectivity::flat::OFlatTable::OFlatTable(class connectivity::sdbcx::OCollection *,class connectivity::flat::OFlatConnection *,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & SchemaName + "" +connectivity/source/inc/flat/ETable.hxx:76 + void connectivity::flat::OFlatTable::OFlatTable(class connectivity::sdbcx::OCollection *,class connectivity::flat::OFlatConnection *,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & CatalogName + "" +connectivity/source/inc/hsqldb/HView.hxx:40 + void connectivity::hsqldb::HView::HView(const class com::sun::star::uno::Reference &,_Bool,const class rtl::OUString &,const class rtl::OUString &) + _Bool _bCaseSensitive + isCaseSensitive() +connectivity/source/inc/OColumn.hxx:67 + void connectivity::OColumn::OColumn(const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,int) + const class rtl::OUString & _aTableName + "" +connectivity/source/manager/mdrivermanager.cxx:144 + const class com::sun::star::uno::Reference & drivermanager::(anonymous namespace)::ExtractDriverFromAccess::operator()(const struct drivermanager::DriverAccess &) const + const struct drivermanager::DriverAccess & _rAccess + ExtractDriverFromAccess() +connectivity/source/manager/mdrivermanager.cxx:152 + const class com::sun::star::uno::Reference & drivermanager::(anonymous namespace)::ExtractDriverFromCollectionElement::operator()(const struct std::pair > &) const + const struct std::pair > & _rElement + ExtractDriverFromCollectionElement() +dbaccess/source/core/api/RowSetRow.hxx:39 + void dbaccess::ORowSetOldRowHelper::ORowSetOldRowHelper(const class rtl::Reference > &) + const class rtl::Reference > & _rRow + ORowSetRow() +dbaccess/source/core/inc/ModelImpl.hxx:311 + void dbaccess::ODatabaseModelImpl::modelIsDisposing(const _Bool,struct dbaccess::ODatabaseModelImpl::ResetModelAccess) + const _Bool _wasInitialized + impl_isInitialized() +dbaccess/source/core/inc/View.hxx:40 + void dbaccess::View::View(const class com::sun::star::uno::Reference &,_Bool,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + _Bool _bCaseSensitive + isCaseSensitive() +dbaccess/source/ui/inc/indexes.hxx:73 + void dbaui::OIndex::flagAsNew(const struct dbaui::GrantIndexAccess &) + const struct dbaui::GrantIndexAccess & + GrantIndexAccess() +dbaccess/source/ui/inc/indexes.hxx:74 + void dbaui::OIndex::flagAsCommitted(const struct dbaui::GrantIndexAccess &) + const struct dbaui::GrantIndexAccess & + GrantIndexAccess() +dbaccess/source/ui/inc/sqlmessage.hxx:88 + void dbaui::OSQLMessageBox::OSQLMessageBox(class weld::Window *,const class dbtools::SQLExceptionInfo &,enum dbaui::MessBoxStyle,const class rtl::OUString &) + const class rtl::OUString & _rHelpURL + "" +dbaccess/source/ui/inc/TableCopyHelper.hxx:98 + void dbaui::OTableCopyHelper::pasteTable(const class TransferableDataHelper &,class std::basic_string_view >,const class utl::SharedUNOComponent &) + const class utl::SharedUNOComponent & _xConnection + ensureConnection() +dbaccess/source/ui/inc/TableWindowData.hxx:65 + _Bool dbaui::OTableWindowData::init(const class com::sun::star::uno::Reference &,_Bool) + _Bool _bAllowQueries + allowQueries() +dbaccess/source/ui/inc/WCPage.hxx:56 + void dbaui::OCopyTable::OCopyTable(class weld::Container *,class dbaui::OCopyTableWizard *) + class weld::Container * pParent + CreatePageContainer() +dbaccess/source/ui/uno/copytablewizard.cxx:196 + void dbaui::(anonymous namespace)::CopyTableWizard::impl_dialogToAttributes_nothrow(const class dbaui::OCopyTableWizard &) + const class dbaui::OCopyTableWizard & _rDialog + impl_getDialog_throw() +desktop/source/deployment/gui/dp_gui_dependencydialog.hxx:38 + void dp_gui::DependencyDialog::DependencyDialog(class weld::Window *,const class std::__debug::vector > &) + class weld::Window * parent + activeDialog() +desktop/source/deployment/inc/dp_interact.h:57 + void dp_misc::ProgressLevel::update(const class com::sun::star::uno::Any &) const + const class com::sun::star::uno::Any & status + Any() +editeng/source/editeng/impedit3.cxx:152 + void lcl_DrawRedLines(class OutputDevice *,long,const class Point &,unsigned long,unsigned long,const long *,const class WrongList *,struct o3tl::strong_int,const class Point &,_Bool,_Bool) + _Bool bVertical + IsVertical() +editeng/source/misc/svxacorr.cxx:2807 + _Bool SvxAutocorrWordList::CompareSvxAutocorrWordList::operator()(const class SvxAutocorrWord &,const class SvxAutocorrWord &) const + const class SvxAutocorrWord & lhs + CompareSvxAutocorrWordList() +emfio/inc/mtftools.hxx:663 + void emfio::MtfTools::ExcludeClipRect(const class tools::Rectangle &) + const class tools::Rectangle & rRect + ReadRectangle() +extensions/source/dbpilots/controlwizard.hxx:110 + _Bool dbp::OControlWizard::updateContext(const struct dbp::OAccessRegulator &) + const struct dbp::OAccessRegulator & + OAccessRegulator() +extensions/source/dbpilots/controlwizard.hxx:111 + void dbp::OControlWizard::setFormConnection(const struct dbp::OAccessRegulator &,const class com::sun::star::uno::Reference &,_Bool) + const struct dbp::OAccessRegulator & + OAccessRegulator() +extensions/source/logging/consolehandler.cxx:93 + void logging::(anonymous namespace)::ConsoleHandler::enterMethod(class logging::ComponentMethodGuard::Access) + class logging::ComponentMethodGuard::Access + Access() +extensions/source/logging/consolehandler.cxx:94 + void logging::(anonymous namespace)::ConsoleHandler::leaveMethod(class logging::ComponentMethodGuard::Access) + class logging::ComponentMethodGuard::Access + Access() +extensions/source/logging/filehandler.cxx:110 + void logging::(anonymous namespace)::FileHandler::enterMethod(class logging::ComponentMethodGuard::Access) + class logging::ComponentMethodGuard::Access + Access() +extensions/source/logging/filehandler.cxx:111 + void logging::(anonymous namespace)::FileHandler::leaveMethod(class logging::ComponentMethodGuard::Access) + class logging::ComponentMethodGuard::Access + Access() +extensions/source/propctrlr/fontdialog.hxx:35 + void pcr::ControlCharacterDialog::ControlCharacterDialog(class weld::Window *,const class SfxItemSet &) + class weld::Window * pParent + impl_getDefaultDialogFrame_nothrow() +extensions/source/propctrlr/formlinkdialog.hxx:64 + void pcr::FormLinkDialog::FormLinkDialog(class weld::Window *,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + class weld::Window * _pParent + impl_getDefaultDialogFrame_nothrow() +extensions/source/propctrlr/formlinkdialog.hxx:64 + void pcr::FormLinkDialog::FormLinkDialog(class weld::Window *,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & _sExplanation + "" +extensions/source/propctrlr/formlinkdialog.hxx:64 + void pcr::FormLinkDialog::FormLinkDialog(class weld::Window *,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & _sDetailLabel + "" +extensions/source/propctrlr/formlinkdialog.hxx:64 + void pcr::FormLinkDialog::FormLinkDialog(class weld::Window *,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & _sMasterLabel + "" +extensions/source/propctrlr/listselectiondlg.hxx:37 + void pcr::ListSelectionDialog::ListSelectionDialog(class weld::Window *,const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &) + class weld::Window * _pParent + impl_getDefaultDialogFrame_nothrow() +extensions/source/propctrlr/taborder.hxx:58 + void pcr::TabOrderDialog::TabOrderDialog(class weld::Window *,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &) + class weld::Window * pParent + impl_getDefaultDialogFrame_nothrow() +extensions/source/propctrlr/taborder.hxx:58 + void pcr::TabOrderDialog::TabOrderDialog(class weld::Window *,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &) + const class com::sun::star::uno::Reference & _rxControlCont + impl_getContextControlContainer_nothrow() +extensions/source/update/check/updateprotocol.hxx:33 + _Bool checkForUpdates(struct UpdateInfo &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &) + const class com::sun::star::uno::Reference & rxProvider + createProvider() +forms/source/component/ListBox.cxx:1541 + class com::sun::star::uno::Any lcl_getSingleSelectedEntryAny(const class com::sun::star::uno::Sequence &,const class std::__debug::vector > &) + const class std::__debug::vector > & _rStringList + impl_getValues() +forms/source/component/ListBox.cxx:1557 + class com::sun::star::uno::Sequence lcl_getMultiSelectedEntriesAny(const class com::sun::star::uno::Sequence &,const class std::__debug::vector > &) + const class std::__debug::vector > & _rStringList + impl_getValues() +forms/source/xforms/computedexpression.hxx:74 + _Bool xforms::ComputedExpression::_evaluate(const class xforms::EvaluationContext &,const class rtl::OUString &) + const class rtl::OUString & sExpression + _getExpressionForEvaluation() +idl/inc/parser.hxx:66 + void SvIdlParser::Read(const class SvStringHashEntry *) + const class SvStringHashEntry * + SvHash_module() +include/avmedia/mediaplayer.hxx:51 + void avmedia::MediaFloater::setURL(const class rtl::OUString &,const class rtl::OUString &,_Bool) + const class rtl::OUString & rReferer + "" +include/basic/basmgr.hxx:138 + void BasicManager::BasicManager(class SotStorage &,const class rtl::OUString &,class StarBASIC *,const class rtl::OUString *,_Bool) + const class rtl::OUString & rBaseURL + "" +include/comphelper/propertybag.hxx:107 + void comphelper::PropertyBag::addVoidProperty(const class rtl::OUString &,const class com::sun::star::uno::Type &,int,int) + int _nHandle + findFreeHandle() +include/connectivity/dbtools.hxx:181 + class com::sun::star::uno::Reference getConnection_withFeedback(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &) + const class rtl::OUString & _rUser + "" +include/connectivity/dbtools.hxx:181 + class com::sun::star::uno::Reference getConnection_withFeedback(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &) + const class rtl::OUString & _rPwd + "" +include/connectivity/dbtools.hxx:699 + class com::sun::star::uno::Reference createSDBCXColumn(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,_Bool,_Bool,_Bool,_Bool,int) + _Bool _bCase + isCaseSensitive() +include/connectivity/PColumn.hxx:126 + void connectivity::parse::OOrderColumn::OOrderColumn(const class com::sun::star::uno::Reference &,const class rtl::OUString &,_Bool,_Bool) + _Bool _bCase + isCaseSensitive() +include/connectivity/PColumn.hxx:133 + void connectivity::parse::OOrderColumn::OOrderColumn(const class com::sun::star::uno::Reference &,_Bool,_Bool) + _Bool _bCase + isCaseSensitive() +include/connectivity/sdbcx/VView.hxx:65 + void connectivity::sdbcx::OView::OView(_Bool,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & _rCommand + "" +include/drawinglayer/tools/primitive2dxmldump.hxx:42 + class std::unique_ptr drawinglayer::Primitive2dXmlDump::dumpAndParse(const class drawinglayer::primitive2d::Primitive2DContainer &,const class rtl::OUString &) + const class rtl::OUString & rStreamName + "" +include/editeng/editview.hxx:358 + void EditView::InitLOKSpecialPositioning(enum MapUnit,const class tools::Rectangle &,const class Point &) + const class Point & rVisDocStartPos + Point() +include/editeng/scripttypeitem.hxx:36 + const class SfxPoolItem * SvxScriptSetItem::GetItemOfScript(unsigned short,const class SfxItemSet &,enum SvtScriptType) + unsigned short nSlotId + Which() +include/editeng/svxacorr.hxx:47 + _Bool CompareSvStringsISortDtor::operator()(const class rtl::OUString &,class std::basic_string_view >) const + const class rtl::OUString & lhs + Compare() +include/editeng/swafopt.hxx:47 + _Bool editeng::CompareAutoCompleteString::operator()(class editeng::IAutoCompleteString *const &,class editeng::IAutoCompleteString *const &) const + class editeng::IAutoCompleteString *const & lhs + Compare() +include/formula/FormulaCompiler.hxx:292 + void formula::FormulaCompiler::fillAddInToken(class std::__debug::vector > &,_Bool) const + _Bool _bIsEnglish + isEnglish() +include/o3tl/sorted_vector.hxx:331 + _Bool o3tl::less_ptr_to::operator()(type-parameter-?-? *const &,type-parameter-?-? *const &) const + type-parameter-?-? *const & lhs + Compare() +include/o3tl/sorted_vector.hxx:339 + _Bool o3tl::less_uniqueptr_to::operator()(const unique_ptr > &,const unique_ptr > &) const + const unique_ptr > & lhs + Compare() +include/o3tl/sorted_vector.hxx:353 + pair::value>::const_iterator, _Bool> o3tl::find_unique::operator()(typename sorted_vector::value>::const_iterator,typename sorted_vector::value>::const_iterator,const type-parameter-?-? &) + typename sorted_vector::value>::const_iterator first + Find_t() +include/o3tl/sorted_vector.hxx:370 + pair::value>::const_iterator, _Bool> o3tl::find_partialorder_ptrequals::operator()(typename sorted_vector::value>::const_iterator,typename sorted_vector::value>::const_iterator,const type-parameter-?-? &) + typename sorted_vector::value>::const_iterator first + Find_t() +include/oox/helper/attributelist.hxx:143 + class rtl::OUString oox::AttributeList::getXString(int,const class rtl::OUString &) const + const class rtl::OUString & rDefault + "" +include/oox/mathml/importutils.hxx:212 + void oox::formulaimport::XmlStream::skipElementInternal(int,_Bool) + int token + currentToken() +include/opencl/openclconfig.hxx:36 + void OpenCLConfig::ImplMatcher::ImplMatcher(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & rOSVersion + "" +include/opencl/openclconfig.hxx:36 + void OpenCLConfig::ImplMatcher::ImplMatcher(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & rDevice + "" +include/opencl/openclwrapper.hxx:61 + _Bool buildProgramFromBinary(const char *,struct openclwrapper::GPUEnv *,const char *,int) + const char * buildOption + "" +include/registry/registry.hxx:409 + enum RegError RegistryKey::getKeyNames(const class rtl::OUString &,class RegistryKeyNames &) + const class rtl::OUString & keyName + "" +include/registry/registry.hxx:435 + enum RegError RegistryKey::setValue(const class rtl::OUString &,enum RegValueType,void *,unsigned int) + const class rtl::OUString & keyName + "" +include/registry/registry.hxx:449 + enum RegError RegistryKey::setLongListValue(const class rtl::OUString &,const int *,unsigned int) + const class rtl::OUString & keyName + "" +include/registry/registry.hxx:462 + enum RegError RegistryKey::setStringListValue(const class rtl::OUString &,char **,unsigned int) + const class rtl::OUString & keyName + "" +include/registry/registry.hxx:475 + enum RegError RegistryKey::setUnicodeListValue(const class rtl::OUString &,char16_t **,unsigned int) + const class rtl::OUString & keyName + "" +include/registry/registry.hxx:488 + enum RegError RegistryKey::getValueInfo(const class rtl::OUString &,enum RegValueType *,unsigned int *) + const class rtl::OUString & keyName + "" +include/registry/registry.hxx:500 + enum RegError RegistryKey::getValue(const class rtl::OUString &,void *) + const class rtl::OUString & keyName + "" +include/registry/registry.hxx:511 + enum RegError RegistryKey::getLongListValue(const class rtl::OUString &,class RegistryValueList &) + const class rtl::OUString & keyName + "" +include/registry/registry.hxx:522 + enum RegError RegistryKey::getStringListValue(const class rtl::OUString &,class RegistryValueList &) + const class rtl::OUString & keyName + "" +include/registry/registry.hxx:533 + enum RegError RegistryKey::getUnicodeListValue(const class rtl::OUString &,class RegistryValueList &) + const class rtl::OUString & keyName + "" +include/registry/writer.hxx:72 + void typereg::Writer::Writer(enum typereg_Version,const class rtl::OUString &,const class rtl::OUString &,enum RTTypeClass,_Bool,const class rtl::OUString &,unsigned short,unsigned short,unsigned short,unsigned short) + const class rtl::OUString & fileName + "" +include/registry/writer.hxx:131 + void typereg::Writer::setFieldData(unsigned short,const class rtl::OUString &,const class rtl::OUString &,enum RTFieldAccess,const class rtl::OUString &,const class rtl::OUString &,const class RTConstValue &) + const class rtl::OUString & fileName + "" +include/sfx2/dinfdlg.hxx:86 + void SfxDocumentInfoItem::SfxDocumentInfoItem(const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Sequence &,_Bool,_Bool) + _Bool bUseUserData + IsUseUserData() +include/sfx2/dinfdlg.hxx:86 + void SfxDocumentInfoItem::SfxDocumentInfoItem(const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Sequence &,_Bool,_Bool) + _Bool bUseThumbnailSave + IsUseThumbnailSave() +include/sfx2/dinfdlg.hxx:385 + void CustomPropertiesWindow::AddLine(const class rtl::OUString &,const class com::sun::star::uno::Any &) + const class rtl::OUString & sName + "" +include/sfx2/docfile.hxx:257 + _Bool SfxMedium::SignContents_Impl(class weld::Window *,_Bool,_Bool,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class rtl::OUString &) + _Bool bHasValidDocumentSignature + HasValidSignatures() +include/sfx2/docfile.hxx:268 + _Bool SfxMedium::SignDocumentContentUsingCertificate(const class com::sun::star::uno::Reference &,_Bool,const class com::sun::star::uno::Reference &) + _Bool bHasValidDocumentSignature + HasValidSignatures() +include/sfx2/lokhelper.hxx:112 + void SfxLokHelper::notifyAllViews(int,const class rtl::OString &) + const class rtl::OString & rPayload + "" +include/sfx2/objsh.hxx:648 + void SfxObjectShell::DoDraw(class OutputDevice *,const class Point &,const class Size &,const class JobSetup &,unsigned short) + const class JobSetup & rSetup + JobSetup() +include/sfx2/sfxhelp.hxx:40 + _Bool SfxHelp::Start_Impl(const class rtl::OUString &,const class vcl::Window *,const class rtl::OUString &) + const class rtl::OUString & rKeyword + "" +include/sfx2/sidebar/ResourceManager.hxx:94 + void sfx2::sidebar::ResourceManager::StorePanelExpansionState(class std::basic_string_view >,const _Bool,const class sfx2::sidebar::Context &) + const class sfx2::sidebar::Context & rContext + maContextAccess() +include/svl/sharecontrolfile.hxx:62 + void svt::ShareControlFile::RemoveEntry(const class o3tl::enumarray &) + const class o3tl::enumarray & aOptionalSpecification + GenerateOwnEntry() +include/svtools/ehdl.hxx:35 + void SfxErrorContext::SfxErrorContext(unsigned short,class weld::Window *,const struct std::pair *,const class std::locale &) + const class std::locale & rResLocaleP + SvtResLocale() +include/svx/charmap.hxx:150 + void SvxShowCharSet::DrawChars_Impl(class OutputDevice &,int,int) + int n1 + FirstInView() +include/svx/charmap.hxx:150 + void SvxShowCharSet::DrawChars_Impl(class OutputDevice &,int,int) + int n2 + LastInView() +include/svx/colorwindow.hxx:114 + void ColorWindow::ColorWindow(const class rtl::OUString &,const class std::shared_ptr &,class ColorStatus &,unsigned short,const class com::sun::star::uno::Reference &,const class MenuOrToolMenuButton &,const class std::function &,const class std::function &)> &) + const class rtl::OUString & rCommand + "" +include/svx/svdtrans.hxx:63 + void RotateXPoly(class XPolyPolygon &,const class Point &,double,double) + const class Point & rRef + Point() +include/unotools/wincodepage.hxx:31 + unsigned short utl_getWinTextEncodingFromLangStr(const class rtl::OUString &,_Bool) + const class rtl::OUString & sLanguage + utl_getLocaleForGlobalDefaultEncoding() +include/vbahelper/vbahelper.hxx:119 + class rtl::OUString extractStringFromAny(const class com::sun::star::uno::Any &,const class rtl::OUString &,_Bool) + const class rtl::OUString & rDefault + "" +include/vcl/accessibletable.hxx:87 + class tools::Rectangle vcl::table::IAccessibleTable::calcHeaderRect(_Bool) + _Bool _bIsColumnBar + isColumnBar() +include/vcl/dockwin.hxx:39 + void DockingData::DockingData(const class Point &,const class tools::Rectangle &,_Bool) + _Bool b + IsFloatingMode() +include/vcl/dockwin.hxx:50 + void EndDockingData::EndDockingData(const class tools::Rectangle &,_Bool,_Bool) + _Bool b + IsFloatingMode() +include/vcl/dockwin.hxx:50 + void EndDockingData::EndDockingData(const class tools::Rectangle &,_Bool,_Bool) + _Bool bCancelled + IsDockingCanceled() +include/vcl/FilterConfigItem.hxx:79 + class rtl::OUString FilterConfigItem::ReadString(const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & rDefault + "" +include/vcl/graphictools.hxx:278 + void SvtGraphicFill::SvtGraphicFill(const class tools::PolyPolygon &,class Color,double,enum SvtGraphicFill::FillRule,enum SvtGraphicFill::FillType,const struct SvtGraphicFill::Transform &,_Bool,enum SvtGraphicFill::HatchType,class Color,enum SvtGraphicFill::GradientType,class Color,class Color,int,const class Graphic &) + class Color aFillColor + Color() +include/vcl/opengl/OpenGLHelper.hxx:54 + int OpenGLHelper::LoadShaders(const class rtl::OUString &,const class rtl::OUString &,class std::basic_string_view >,class std::basic_string_view >) + class std::basic_string_view > rDigest + "" +include/vcl/outdev.hxx:1589 + class Bitmap OutputDevice::GetDownsampledBitmap(const class Size &,const class Point &,const class Size &,const class Bitmap &,long,long) + const class Point & rSrcPt + Point() +include/vcl/print.hxx:640 + class com::sun::star::uno::Any vcl::PrinterOptionsHelper::setSubgroupControlOpt(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const struct vcl::PrinterOptionsHelper::UIControlOptions &) + const class rtl::OUString & i_rHelpId + "" +include/vcl/print.hxx:656 + class com::sun::star::uno::Any vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(const class com::sun::star::uno::Sequence &,const class rtl::OUString &,const class com::sun::star::uno::Sequence &,const class rtl::OUString &,const class com::sun::star::uno::Sequence &,int,const class com::sun::star::uno::Sequence &,const struct vcl::PrinterOptionsHelper::UIControlOptions &) + const class rtl::OUString & i_rTitle + "" +include/vcl/print.hxx:667 + class com::sun::star::uno::Any vcl::PrinterOptionsHelper::setRangeControlOpt(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,const struct vcl::PrinterOptionsHelper::UIControlOptions &) + const class rtl::OUString & i_rTitle + "" +include/vcl/print.hxx:675 + class com::sun::star::uno::Any vcl::PrinterOptionsHelper::setEditControlOpt(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const struct vcl::PrinterOptionsHelper::UIControlOptions &) + const class rtl::OUString & i_rTitle + "" +include/vcl/toolbox.hxx:420 + void ToolBox::SetHelpText(struct o3tl::strong_int,const class rtl::OUString &) + const class rtl::OUString & rText + "" +include/vcl/toolkit/field.hxx:313 + class tools::Time TimeFormatter::SpinTime(_Bool,const class tools::Time &,enum TimeFieldFormat,_Bool,const class rtl::OUString &,int,const class LocaleDataWrapper &) + _Bool bDuration + IsDuration() +include/vcl/toolkit/field.hxx:313 + class tools::Time TimeFormatter::SpinTime(_Bool,const class tools::Time &,enum TimeFieldFormat,_Bool,const class rtl::OUString &,int,const class LocaleDataWrapper &) + const class LocaleDataWrapper & rLocaleDataWrapper + ImplGetLocaleDataWrapper() +include/vcl/toolkit/field.hxx:418 + int DateFormatter::GetDateArea(enum ExtDateFieldFormat,const class rtl::OUString &,int,const class LocaleDataWrapper &) + const class LocaleDataWrapper & rLocaleDataWrapper + ImplGetLocaleDataWrapper() +include/vcl/toolkit/svlbitm.hxx:115 + void SvLBoxString::SvLBoxString(const class rtl::OUString &) + const class rtl::OUString & rText + "" +include/vcl/toolkit/unowrap.hxx:70 + class com::sun::star::uno::Reference UnoWrapperBase::CreateAccessible(class Menu *,_Bool) + _Bool bIsMenuBar + IsMenuBar() +include/vcl/transfer.hxx:320 + class com::sun::star::uno::Any TransferableDataHelper::GetAny(enum SotClipboardFormatId,const class rtl::OUString &) const + const class rtl::OUString & rDestDoc + "" +include/vcl/transfer.hxx:358 + class com::sun::star::uno::Sequence TransferableDataHelper::GetSequence(enum SotClipboardFormatId,const class rtl::OUString &) + const class rtl::OUString & rDestDoc + "" +include/vcl/virdev.hxx:164 + _Bool VirtualDevice::SetOutputSizePixelScaleOffsetAndLOKBuffer(const class Size &,const class Fraction &,const class Point &,unsigned char *) + const class Point & rNewOffset + Point() +include/vcl/weld.hxx:635 + void weld::ComboBoxEntry::ComboBoxEntry(const class rtl::OUString &) + const class rtl::OUString & rString + "" +include/vcl/weld.hxx:713 + void weld::ComboBox::append(const class rtl::OUString &,const class rtl::OUString &,class VirtualDevice &) + const class rtl::OUString & rId + "" +include/vcl/weld.hxx:2334 + void weld::Toolbar::append_separator(const class rtl::OUString &) + const class rtl::OUString & rId + "" +include/xmloff/txtparae.hxx:407 + void XMLTextParagraphExport::exportTextStyles(_Bool,_Bool) + _Bool bProg + IsShowProgress() +include/xmloff/txtparae.hxx:457 + void XMLTextParagraphExport::collectTextAutoStyles(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,_Bool) + _Bool bIsProgress + IsShowProgress() +include/xmloff/txtparae.hxx:487 + void XMLTextParagraphExport::exportText(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,_Bool) + _Bool bIsProgress + IsShowProgress() +include/xmloff/xmlexp.hxx:279 + void SvXMLExport::SvXMLExport(const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const enum FieldUnit,enum SvXMLExportFlags) + const class rtl::OUString & implementationName + "" +include/xmloff/xmlexp.hxx:279 + void SvXMLExport::SvXMLExport(const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const enum FieldUnit,enum SvXMLExportFlags) + const class rtl::OUString & rFileName + "" +include/xmloff/XMLFontStylesContext.hxx:51 + void XMLFontStylesContext::XMLFontStylesContext(class SvXMLImport &,unsigned short) + unsigned short eDfltEnc + osl_getThreadTextEncoding() +lotuswordpro/inc/lwpoverride.hxx:189 + void LwpBulletOverride::OverrideSkip(_Bool) + _Bool bOver + IsSkip() +lotuswordpro/inc/lwpoverride.hxx:190 + void LwpBulletOverride::OverrideRightAligned(_Bool) + _Bool bOver + IsRightAligned() +lotuswordpro/inc/lwpoverride.hxx:399 + void LwpIndentOverride::OverrideUseRelative(_Bool) + _Bool use + IsUseRelative() +lotuswordpro/source/filter/lwpbreaksoverride.hxx:121 + void LwpBreaksOverride::OverridePageBreakBefore(_Bool) + _Bool bVal + IsPageBreakBefore() +lotuswordpro/source/filter/lwpbreaksoverride.hxx:122 + void LwpBreaksOverride::OverridePageBreakAfter(_Bool) + _Bool bVal + IsPageBreakAfter() +lotuswordpro/source/filter/lwpbreaksoverride.hxx:123 + void LwpBreaksOverride::OverridePageBreakWithin(_Bool) + _Bool bVal + IsPageBreakWithin() +lotuswordpro/source/filter/lwpbreaksoverride.hxx:124 + void LwpBreaksOverride::OverrideColumnBreakBefore(_Bool) + _Bool bVal + IsColumnBreakBefore() +lotuswordpro/source/filter/lwpbreaksoverride.hxx:125 + void LwpBreaksOverride::OverrideColumnBreakAfter(_Bool) + _Bool bVal + IsColumnBreakAfter() +lotuswordpro/source/filter/lwpbreaksoverride.hxx:126 + void LwpBreaksOverride::OverrideKeepWithNext(_Bool) + _Bool bVal + IsKeepWithNext() +lotuswordpro/source/filter/lwpbreaksoverride.hxx:127 + void LwpBreaksOverride::OverrideKeepWithPrevious(_Bool) + _Bool bVal + IsKeepWithPrevious() +lotuswordpro/source/filter/lwpbreaksoverride.hxx:128 + void LwpBreaksOverride::OverrideUseNextStyle(_Bool) + _Bool bVal + IsUseNextStyle() +opencl/source/opencl_device.cxx:432 + void (anonymous namespace)::LogWriter::text(const class rtl::OString &) + const class rtl::OString & rText + "" +opencl/source/openclwrapper.cxx:707 + struct _cl_device_id * findDeviceIdByDeviceString(class std::basic_string_view >,const class std::__debug::vector > &) + const class std::__debug::vector > & rPlatforms + fillOpenCLInfo() +reportdesign/source/ui/dlg/Condition.hxx:129 + void rptui::Condition::setConditionIndex(unsigned long,unsigned long) + unsigned long _nCondCount + impl_getConditionCount() +sal/qa/osl/file/osl_File.cxx:377 + class rtl::OString outputError(const class rtl::OString &,const class rtl::OString &,const char *) + const char * msg + "" +sc/inc/rangeseq.hxx:99 + _Bool ScByteSequenceToString::GetString(class rtl::OUString &,const class com::sun::star::uno::Any &,unsigned short) + unsigned short nEncoding + osl_getThreadTextEncoding() +sc/inc/table.hxx:788 + void ScTable::SetOptimalHeightOnly(class sc::RowHeightContext &,int,int,class ScProgress *,unsigned long) + int nEndRow + MaxRow() +sc/inc/typedstrdata.hxx:42 + _Bool ScTypedStrData::LessCaseInsensitive::operator()(const class ScTypedStrData &,const class ScTypedStrData &) const + const class ScTypedStrData & left + LessCaseInsensitive() +sc/qa/extras/check_xcell_ranges_query.cxx:38 + void sc_apitest::CheckXCellRangesQuery::_queryEmptyCells(const class rtl::OUString &) + const class rtl::OUString & expected + "" +sc/qa/unit/helper/qahelper.hxx:193 + class tools::SvRef ScBootstrapFixture::saveAndReload(class ScDocShell *,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,enum SfxFilterFlags,const class rtl::OUString *) + const class rtl::OUString & rUserData + "" +sc/source/core/data/documen3.cxx:1755 + _Bool lcl_AddTwipsWhile(long &,long,int &,int,const class ScTable *,_Bool) + int nEndRow + MaxRow() +sc/source/core/tool/token.cxx:4818 + void appendTokenByType(struct ScSheetLimits &,struct sc::TokenStringContext &,class rtl::OUStringBuffer &,const class formula::FormulaToken &,const class ScAddress &,_Bool) + _Bool bFromRangeName + IsFromRangeName() +sc/source/filter/excel/xeformula.cxx:150 + void (anonymous namespace)::XclExpFuncData::FinishParam(unsigned short) + unsigned short nTokPos + PopOperandPos() +sc/source/filter/excel/xltoolbar.hxx:46 + _Bool ScTBC::ImportToolBarControl(class ScCTBWrapper &,const class com::sun::star::uno::Reference &,class CustomToolBarImportHelper &,_Bool) + _Bool bIsMenuBar + IsMenuToolbar() +sc/source/filter/inc/workbookhelper.hxx:166 + class ScRangeData * oox::xls::WorkbookHelper::createNamedRangeObject(class rtl::OUString &,const class com::sun::star::uno::Sequence &,int,int) const + const class com::sun::star::uno::Sequence & rTokens + ApiTokenSequence() +sc/source/filter/inc/workbookhelper.hxx:175 + class ScRangeData * oox::xls::WorkbookHelper::createLocalNamedRangeObject(class rtl::OUString &,const class com::sun::star::uno::Sequence &,int,int,int) const + const class com::sun::star::uno::Sequence & rTokens + ApiTokenSequence() +sc/source/filter/inc/xechart.hxx:798 + void XclExpChChart3d::Convert(const class ScfPropertySet &,_Bool) + _Bool b3dWallChart + Is3dWallChart() +sc/source/filter/inc/xestream.hxx:287 + void XclExpXmlStream::XclExpXmlStream(const class com::sun::star::uno::Reference &,_Bool,_Bool) + _Bool bExportTemplate + isExportTemplate() +sc/source/filter/inc/xestyle.hxx:145 + _Bool CheckItems(const class XclExpRoot &,const class SfxItemSet &,short,_Bool) + _Bool bDeep + IsStyleXF() +sc/source/filter/inc/xichart.hxx:893 + class com::sun::star::uno::Reference XclImpChType::CreateCoordSystem(_Bool) const + _Bool b3dChart + Is3dChart() +sc/source/filter/inc/xichart.hxx:896 + class com::sun::star::uno::Reference XclImpChType::CreateChartType(const class com::sun::star::uno::Reference &,_Bool) const + _Bool b3dChart + Is3dChart() +sc/source/filter/inc/xichart.hxx:913 + void XclImpChChart3d::Convert(class ScfPropertySet &,_Bool) const + _Bool b3dWallChart + Is3dWallChart() +sc/source/filter/inc/xistream.hxx:445 + void XclImpStream::IgnoreUniString(unsigned short,unsigned char) + unsigned char nFlags + ReaduInt8() +sc/source/filter/inc/xlescher.hxx:423 + _Bool XclControlHelper::FillMacroDescriptor(struct com::sun::star::script::ScriptEventDescriptor &,enum XclTbxEventType,const class rtl::OUString &,class SfxObjectShell *) + enum XclTbxEventType eEventType + DoGetEventType() +sc/source/filter/oox/formulabuffer.cxx:317 + void processSheetFormulaCells(class ScDocumentImport &,struct oox::xls::FormulaBuffer::SheetItem &,class SvNumberFormatter &,const class com::sun::star::uno::Sequence &,_Bool) + _Bool bGeneratorKnownGood + isGeneratorKnownGood() +sc/source/ui/inc/AccessibleCsvControl.hxx:445 + void ScAccessibleCsvCell::ScAccessibleCsvCell(class ScCsvGrid &,const class rtl::OUString &,int,int) + class ScCsvGrid & rGrid + implGetGrid() +sc/source/ui/vba/vbasheetobject.hxx:174 + void ScVbaButton::ScVbaButton(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &) + const class com::sun::star::uno::Reference & rxFormIC + createForm() +sc/source/ui/vba/vbawindows.cxx:106 + void (anonymous namespace)::WindowEnumImpl::WindowEnumImpl(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Any &) + const class com::sun::star::uno::Any & aApplication + Application() +sd/source/filter/eppt/eppt.hxx:177 + unsigned int PPTWriter::ImplInsertBookmarkURL(const class rtl::OUString &,const unsigned int,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) + const class rtl::OUString & rStringVer2 + "" +sd/source/filter/eppt/pptx-animations.cxx:563 + void (anonymous namespace)::NodeContext::initValid(_Bool,_Bool) + _Bool bHasValidChild + initChildNodes() +sd/source/filter/xml/sdxmlwrp.cxx:136 + const struct (anonymous namespace)::XML_SERVICES * getServices(_Bool,_Bool,unsigned long) + _Bool bDraw + IsDraw() +sd/source/ui/annotations/annotationtag.cxx:164 + void sd::(anonymous namespace)::AnnotationHdl::AnnotationHdl(const class rtl::Reference &,const class com::sun::star::uno::Reference &,const class Point &) + const class Point & rPnt + Point() +sd/source/ui/slidesorter/cache/SlsRequestFactory.hxx:31 + void sd::slidesorter::cache::RequestFactory::operator()(class sd::slidesorter::cache::RequestQueue &,const class std::shared_ptr &) + class sd::slidesorter::cache::RequestQueue & rRequestQueue + RequestFactory() +sdext/source/pdfimport/inc/contentsink.hxx:130 + void pdfi::ContentSink::strokePath(const class com::sun::star::uno::Reference &) + const class com::sun::star::uno::Reference & rPath + readPath() +sdext/source/pdfimport/inc/contentsink.hxx:132 + void pdfi::ContentSink::fillPath(const class com::sun::star::uno::Reference &) + const class com::sun::star::uno::Reference & rPath + readPath() +sdext/source/pdfimport/inc/contentsink.hxx:134 + void pdfi::ContentSink::eoFillPath(const class com::sun::star::uno::Reference &) + const class com::sun::star::uno::Reference & rPath + readPath() +sdext/source/pdfimport/inc/contentsink.hxx:137 + void pdfi::ContentSink::intersectClip(const class com::sun::star::uno::Reference &) + const class com::sun::star::uno::Reference & rPath + readPath() +sdext/source/pdfimport/inc/contentsink.hxx:139 + void pdfi::ContentSink::intersectEoClip(const class com::sun::star::uno::Reference &) + const class com::sun::star::uno::Reference & rPath + readPath() +sdext/source/pdfimport/inc/contentsink.hxx:151 + void pdfi::ContentSink::drawMask(const class com::sun::star::uno::Sequence &,_Bool) + const class com::sun::star::uno::Sequence & xBitmap + readImageImpl() +sdext/source/presenter/PresenterConfigurationAccess.hxx:116 + class com::sun::star::uno::Reference sdext::presenter::PresenterConfigurationAccess::GetNodeProperties(const class com::sun::star::uno::Reference &,const class rtl::OUString &) + const class rtl::OUString & rsPathToNode + "" +sfx2/source/inc/versdlg.hxx:51 + void SfxVersionDialog::SfxVersionDialog(class weld::Window *,class SfxViewFrame *,_Bool) + _Bool + IsSaveVersionOnClose() +slideshow/source/engine/opengl/TransitionImpl.cxx:636 + class std::shared_ptr makeSimpleTransition(const class std::__debug::vector > &,const class std::__debug::vector > &,const class std::__debug::vector, class std::allocator > > &,const struct TransitionSettings &) + const struct TransitionSettings & rSettings + TransitionSettings() +slideshow/source/engine/opengl/TransitionImpl.cxx:2033 + class std::shared_ptr makeGlitterTransition(const class std::__debug::vector > &,const class std::__debug::vector > &,const struct TransitionSettings &) + const struct TransitionSettings & rSettings + TransitionSettings() +slideshow/source/inc/transitionfactory.hxx:61 + class std::shared_ptr createShapeTransition(const struct slideshow::internal::ActivitiesFactory::CommonParameters &,const class std::shared_ptr &,const class std::shared_ptr &,const class basegfx::B2DVector &,const class com::sun::star::uno::Reference &) + const struct slideshow::internal::ActivitiesFactory::CommonParameters & rParms + fillCommonParameters() +soltools/cpp/cpp.h:212 + void peektokens(struct tokenrow *,char *) + char * + "" +starmath/inc/cursor.hxx:185 + void SmCursor::Draw(class OutputDevice &,class Point,_Bool) + _Bool isCaretVisible + IsCursorVisible() +starmath/inc/token.hxx:199 + void SmColorTokenTableEntry::SmColorTokenTableEntry(const char *,enum SmTokenType,unsigned int) + const char * name + "" +store/source/lockbyte.cxx:269 + void store::(anonymous namespace)::FileHandle::CloseFile::operator()(struct store::(anonymous namespace)::FileHandle &) const + struct store::(anonymous namespace)::FileHandle & rFile + destructor_type() +store/source/lockbyte.cxx:495 + void store::(anonymous namespace)::FileMapping::UnmapFile::operator()(struct store::(anonymous namespace)::FileMapping &) const + struct store::(anonymous namespace)::FileMapping & rMapping + destructor_type() +store/source/lockbyte.cxx:827 + void store::(anonymous namespace)::ResourceHolder::ResourceHolder(const type-parameter-?-? &) + const type-parameter-?-? & value + T() +svx/inc/dragmt3d.hxx:91 + void E3dDragRotate::E3dDragRotate(class SdrDragView &,const class SdrMarkList &,enum E3dDragConstraint,_Bool) + _Bool bFull + IsSolidDragging() +svx/inc/dragmt3d.hxx:108 + void E3dDragMove::E3dDragMove(class SdrDragView &,const class SdrMarkList &,enum SdrHdlKind,enum E3dDragConstraint,_Bool) + _Bool bFull + IsSolidDragging() +svx/source/inc/treevisitor.hxx:29 + void TreeVisitor::TreeVisitor(type-parameter-?-?) + type-parameter-?-? _nodeInfo + FormHierarchyComparator() +svx/source/inc/xmlxtexp.hxx:46 + _Bool SvxXMLXTableExportComponent::save(const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,class rtl::OUString *) + const class com::sun::star::uno::Reference & xTable + createInstance() +svx/source/inc/xmlxtimp.hxx:42 + _Bool SvxXMLXTableImport::load(const class rtl::OUString &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,_Bool *) + const class com::sun::star::uno::Reference & xTable + createInstance() +svx/source/svdraw/svdmodel.cxx:1817 + void addPair(class std::__debug::vector, class std::allocator > > &,const class rtl::OUString &,const type-parameter-?-?) + const type-parameter-?-? val + IsAnchoredTextOverflowLegacy() +sw/inc/ftnidx.hxx:38 + _Bool CompareSwFootnoteIdxs::operator()(class SwTextFootnote *const &,class SwTextFootnote *const &) const + class SwTextFootnote *const & lhs + Compare() +sw/inc/ndarr.hxx:73 + _Bool CompareSwOutlineNodes::operator()(class SwNode *const &,class SwNode *const &) const + class SwNode *const & lhs + Compare() +sw/inc/shellio.hxx:165 + void SwReader::SwReader(class SvStream &,const class rtl::OUString &,const class rtl::OUString &,class SwPaM &) + const class rtl::OUString & rFilename + "" +sw/inc/shellio.hxx:167 + void SwReader::SwReader(const class com::sun::star::uno::Reference &,const class rtl::OUString &,class SwPaM &) + const class rtl::OUString & rFilename + "" +sw/inc/shellio.hxx:461 + class SvStream & Writer::OutLong(class SvStream &,long) + class SvStream & rStrm + Strm() +sw/inc/shellio.hxx:462 + class SvStream & Writer::OutULong(class SvStream &,unsigned long) + class SvStream & rStrm + Strm() +sw/inc/tblsel.hxx:47 + _Bool CompareSwSelBoxes::operator()(class SwTableBox *const &,class SwTableBox *const &) const + class SwTableBox *const & lhs + Compare() +sw/inc/tox.hxx:188 + class SwContentFrame * SwTOXType::FindContentFrame(const class SwDoc &,const class SwRootFrame &,const _Bool) const + const _Bool isReadOnlyAvailable + IsReadOnlyAvailable() +sw/source/core/access/acctable.cxx:102 + void SwAccessibleTableData_Impl::SwAccessibleTableData_Impl(class SwAccessibleMap &,const class SwTabFrame *,_Bool,_Bool) + _Bool bIsInPagePreview + IsInPagePreview() +sw/source/core/crsr/crstrvl.cxx:628 + void lcl_MakeFieldLst(class SetGetExpFields &,const class SwFieldType &,const _Bool,const _Bool) + const _Bool bInReadOnly + IsReadOnlyAvailable() +sw/source/core/graphic/grfatr.cxx:48 + _Bool lcl_IsHoriOnEvenPages(enum MirrorGraph,_Bool) + _Bool bToggle + IsGrfToggle() +sw/source/core/inc/anchoredobjectposition.hxx:182 + long objectpositioning::SwAnchoredObjectPosition::AdjustVertRelPos(const long,const _Bool,const _Bool,const class SwFrame &,const long,const _Bool,const _Bool) const + const _Bool bFollowTextFlow + DoesObjFollowsTextFlow() +sw/source/core/inc/layact.hxx:200 + void SwLayIdle::SwLayIdle(class SwRootFrame *,class SwViewShellImp *) + class SwViewShellImp * pImp + Imp() +sw/source/core/inc/swfont.hxx:77 + void SwSubFont::DrawText_(class SwDrawTextInfo &,const _Bool) + const _Bool bGrey + IsGreyWave() +sw/source/core/inc/wrong.hxx:83 + void SwWrongArea::SwWrongArea(const class rtl::OUString &,const class com::sun::star::uno::Reference &,int,int,class SwWrongList *) + const class rtl::OUString & rType + "" +sw/source/core/inc/wrong.hxx:325 + void SwWrongList::Insert(const class rtl::OUString &,const class com::sun::star::uno::Reference &,int,int,unsigned short) + const class rtl::OUString & rType + "" +sw/source/core/layout/laycache.cxx:950 + _Bool (anonymous namespace)::SdrObjectCompare::operator()(const class SdrObject *,const class SdrObject *) const + const class SdrObject * pF1 + Compare() +sw/source/core/layout/laycache.cxx:958 + _Bool (anonymous namespace)::FlyCacheCompare::operator()(const class SwFlyCache *,const class SwFlyCache *) const + const class SwFlyCache * pC1 + Compare() +sw/source/core/text/guess.hxx:47 + _Bool SwTextGuess::Guess(const class SwTextPortion &,class SwTextFormatInfo &,const unsigned short) + const unsigned short nHeight + Height() +sw/source/core/text/inftxt.hxx:401 + void SwTextPaintInfo::DrawPostIts(_Bool) const + _Bool bScript + IsScript() +sw/source/core/text/inftxt.hxx:542 + void SwTextFormatInfo::Left(const long) + const long nNew + Left() +sw/source/core/text/inftxt.hxx:544 + void SwTextFormatInfo::Right(const long) + const long nNew + Right() +sw/source/core/text/inftxt.hxx:546 + void SwTextFormatInfo::First(const long) + const long nNew + FirstLeft() +sw/source/core/text/inftxt.hxx:566 + void SwTextFormatInfo::ChkNoHyph(const unsigned char,const unsigned char) + const unsigned char bEnd + CntEndHyph() +sw/source/core/text/inftxt.hxx:566 + void SwTextFormatInfo::ChkNoHyph(const unsigned char,const unsigned char) + const unsigned char bMid + CntMidHyph() +sw/source/core/text/itrpaint.hxx:48 + void SwTextPainter::DrawTextLine(const class SwRect &,class SwSaveClip &,const _Bool) + const _Bool bUnderSz + IsUndersized() +sw/source/core/txtnode/modeltoviewhelper.cxx:52 + _Bool (anonymous namespace)::sortfieldresults::operator()(const struct (anonymous namespace)::FieldResult &,const struct (anonymous namespace)::FieldResult &) const + const struct (anonymous namespace)::FieldResult & rOne + Compare() +sw/source/filter/html/swcss1.hxx:84 + void SwCSS1Parser::SwCSS1Parser(class SwDoc *,const class SwHTMLParser &,const unsigned int *,const class rtl::OUString &,_Bool) + _Bool bNewDoc + IsNewDoc() +sw/source/filter/html/swhtml.hxx:914 + void SwHTMLParser::SwHTMLParser(class SwDoc *,class SwPaM &,class SvStream &,const class rtl::OUString &,const class rtl::OUString &,_Bool,class SfxMedium *,_Bool,_Bool,const class rtl::OUString &) + _Bool bReadUTF8 + IsReadUTF8() +sw/source/filter/inc/wrtswtbl.hxx:204 + _Bool SwWriteTableColLess::operator()(const class std::unique_ptr > &,const class std::unique_ptr > &) + const class std::unique_ptr > & lhs + Compare() +sw/source/filter/ww8/docxattributeoutput.cxx:6338 + _Bool (anonymous namespace)::OUStringIgnoreCase::operator()(const class rtl::OUString &,class std::basic_string_view >) const + const class rtl::OUString & lhs + Compare() +sw/source/filter/ww8/docxexport.hxx:276 + void DocxExport::DocxExport(class DocxExportFilter &,class SwDoc &,class std::shared_ptr &,class SwPaM &,_Bool,_Bool) + _Bool bTemplate + isExportTemplate() +sw/source/filter/ww8/wrtww8.hxx:269 + void WW8_WrPlcSepx::WriteSepx(class SvStream &) const + class SvStream & rStrm + Strm() +sw/source/filter/ww8/ww8scan.hxx:1538 + void WW8Fib::Write(class SvStream &) + class SvStream & rStrm + Strm() +sw/source/filter/xml/xmlimp.hxx:126 + void SwXMLImport::InsertStyles(_Bool) + _Bool bAuto + IsAutomaticStyle() +sw/source/filter/xml/xmltble.cxx:92 + _Bool (anonymous namespace)::SwXMLTableColumnCmpWidth_Impl::operator()(class SwXMLTableColumn_Impl *const &,class SwXMLTableColumn_Impl *const &) const + class SwXMLTableColumn_Impl *const & lhs + Compare() +sw/source/filter/xml/xmltexti.hxx:38 + void SwXMLTextImportHelper::SwXMLTextImportHelper(const class com::sun::star::uno::Reference &,class SvXMLImport &,const class com::sun::star::uno::Reference &,_Bool,_Bool,_Bool,_Bool) + _Bool bInsertM + IsInsertMode() +sw/source/filter/xml/xmltexti.hxx:38 + void SwXMLTextImportHelper::SwXMLTextImportHelper(const class com::sun::star::uno::Reference &,class SvXMLImport &,const class com::sun::star::uno::Reference &,_Bool,_Bool,_Bool,_Bool) + _Bool bStylesOnlyM + IsStylesOnlyMode() +sw/source/filter/xml/xmltexti.hxx:38 + void SwXMLTextImportHelper::SwXMLTextImportHelper(const class com::sun::star::uno::Reference &,class SvXMLImport &,const class com::sun::star::uno::Reference &,_Bool,_Bool,_Bool,_Bool) + _Bool bBlockM + IsBlockMode() +sw/source/ui/vba/vbadocuments.cxx:52 + void (anonymous namespace)::DocumentEnumImpl::DocumentEnumImpl(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Any &) + const class com::sun::star::uno::Any & aApplication + Application() +sw/source/uibase/inc/swuipardlg.hxx:34 + void SwParaDlg::SwParaDlg(class weld::Window *,class SwView &,const class SfxItemSet &,unsigned char,const class rtl::OUString *,_Bool,const class rtl::OString &) + const class rtl::OString & sDefPage + "" +sw/source/uibase/lingu/sdrhhcwrap.hxx:42 + void SdrHHCWrapper::SdrHHCWrapper(class SwView *,struct o3tl::strong_int,struct o3tl::strong_int,const class vcl::Font *,int,_Bool) + _Bool bInteractive + IsInteractive() +toolkit/inc/helper/unopropertyarrayhelper.hxx:38 + void UnoPropertyArrayHelper::UnoPropertyArrayHelper(const class com::sun::star::uno::Sequence &) + const class com::sun::star::uno::Sequence & rIDs + ImplGetPropertyIds() +vbahelper/source/vbahelper/vbacommandbarcontrols.hxx:36 + class com::sun::star::uno::Sequence ScVbaCommandBarControls::CreateMenuItemData(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,unsigned short,const class com::sun::star::uno::Any &,_Bool,_Bool) + const class rtl::OUString & sHelpURL + "" +vbahelper/source/vbahelper/vbacommandbarcontrols.hxx:43 + class com::sun::star::uno::Sequence ScVbaCommandBarControls::CreateToolbarItemData(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,unsigned short,const class com::sun::star::uno::Any &,_Bool,int) + const class rtl::OUString & sHelpURL + "" +vcl/inc/fontinstance.hxx:78 + _Bool LogicalFontInstance::GetGlyphBoundRect(unsigned short,class tools::Rectangle &,_Bool) const + _Bool + IsVertical() +vcl/inc/fontinstance.hxx:79 + _Bool LogicalFontInstance::GetGlyphOutline(unsigned short,class basegfx::B2DPolyPolygon &,_Bool) const + _Bool + IsVertical() +vcl/inc/unx/fc_fontoptions.hxx:33 + void FontConfigFontOptions::SyncPattern(const class rtl::OString &,unsigned int,unsigned int,_Bool) + _Bool bEmbolden + NeedsArtificialBold() +vcl/inc/WidgetDrawInterface.hxx:88 + _Bool vcl::WidgetDrawInterface::getNativeControlRegion(enum ControlType,enum ControlPart,const class tools::Rectangle &,enum ControlState,const class ImplControlValue &,const class rtl::OUString &,class tools::Rectangle &,class tools::Rectangle &) + const class rtl::OUString & aCaption + "" +vcl/skia/gdiimpl.cxx:936 + _Bool (anonymous namespace)::LessThan::operator()(const class basegfx::B2DPoint &,const class basegfx::B2DPoint &) const + const class basegfx::B2DPoint & point1 + Compare() +vcl/source/control/field2.cxx:393 + void ImplPatternProcessStrictModify(class Edit *,const class rtl::OString &,const class rtl::OUString &,_Bool) + _Bool bSameMask + ImplIsSameMask() +vcl/source/control/field2.cxx:1230 + _Bool ImplDateProcessKeyInput(const class KeyEvent &,enum ExtDateFieldFormat,const class LocaleDataWrapper &) + const class LocaleDataWrapper & rLocaleDataWrapper + ImplGetLocaleDataWrapper() +vcl/source/control/field2.cxx:2228 + _Bool ImplTimeProcessKeyInput(const class KeyEvent &,_Bool,_Bool,enum TimeFieldFormat,const class LocaleDataWrapper &) + _Bool bStrictFormat + IsStrictFormat() +vcl/source/control/field2.cxx:2228 + _Bool ImplTimeProcessKeyInput(const class KeyEvent &,_Bool,_Bool,enum TimeFieldFormat,const class LocaleDataWrapper &) + _Bool bDuration + IsDuration() +vcl/source/control/field2.cxx:2228 + _Bool ImplTimeProcessKeyInput(const class KeyEvent &,_Bool,_Bool,enum TimeFieldFormat,const class LocaleDataWrapper &) + const class LocaleDataWrapper & rLocaleDataWrapper + ImplGetLocaleDataWrapper() +vcl/source/control/field.cxx:916 + _Bool ImplMetricProcessKeyInput(const class KeyEvent &,_Bool,const class LocaleDataWrapper &) + _Bool bUseThousandSep + IsUseThousandSep() +vcl/source/control/field.cxx:916 + _Bool ImplMetricProcessKeyInput(const class KeyEvent &,_Bool,const class LocaleDataWrapper &) + const class LocaleDataWrapper & rWrapper + ImplGetLocaleDataWrapper() +vcl/source/control/field.cxx:1638 + _Bool ImplCurrencyProcessKeyInput(const class KeyEvent &,_Bool,const class LocaleDataWrapper &) + _Bool bUseThousandSep + IsUseThousandSep() +vcl/source/control/field.cxx:1638 + _Bool ImplCurrencyProcessKeyInput(const class KeyEvent &,_Bool,const class LocaleDataWrapper &) + const class LocaleDataWrapper & rWrapper + ImplGetLocaleDataWrapper() +vcl/source/control/field.cxx:1645 + _Bool ImplCurrencyGetValue(const class rtl::OUString &,long &,unsigned short,const class LocaleDataWrapper &) + const class LocaleDataWrapper & rWrapper + ImplGetLocaleDataWrapper() +vcl/source/control/imivctl.hxx:405 + void SvxIconChoiceCtrl_Impl::SetColumn(unsigned short,const class SvxIconChoiceCtrlColumnInfo &) + const class SvxIconChoiceCtrlColumnInfo & + SvxIconChoiceCtrlColumnInfo() +vcl/source/edit/vclmedit.cxx:101 + void ImpVclMEdit::Enable(_Bool) + _Bool bEnable + IsEnabled() +vcl/source/treelist/iconview.cxx:246 + void lcl_DumpEntryAndSiblings(class tools::JsonWriter &,class SvTreeListEntry *,class SvTreeListBox *) + class SvTreeListEntry * pEntry + First() +vcl/unx/gtk3/gtk3gtkinst.cxx:9811 + _Bool (anonymous namespace)::CompareGtkTreePath::operator()(const struct _GtkTreePath *,const struct _GtkTreePath *) const + const struct _GtkTreePath * lhs + Compare() +vcl/unx/kf5/KF5SalFrame.hxx:32 + void KF5SalFrame::KF5SalFrame(class KF5SalFrame *,enum SalFrameStyleFlags,_Bool) + _Bool bUseCairo + useCairo() +writerfilter/source/rtftok/rtflookahead.hxx:28 + void writerfilter::rtftok::RTFLookahead::RTFLookahead(class SvStream &,unsigned long) + class SvStream & rStream + Strm() +writerperfect/qa/unit/WpftLoader.hxx:70 + void writerperfect::test::WpftLoader::WpftLoader(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &) + const class com::sun::star::uno::Reference & rxInputStream + createDummyInput() +xmlhelp/source/cxxhelp/provider/urlparameter.cxx:292 + void (anonymous namespace)::InputStreamTransformer::InputStreamTransformer(class chelp::URLParameter *,class chelp::Databases *,_Bool) + _Bool isRoot + isRoot() +xmlhelp/source/cxxhelp/provider/urlparameter.hxx:214 + _Bool chelp::URLParameter::name(_Bool) + _Bool modulePresent + module() +xmloff/source/style/xmlexppr.cxx:97 + _Bool (anonymous namespace)::ComparePropertyState::operator()(const struct XMLPropertyState &,const struct XMLPropertyState &) + const struct XMLPropertyState & lhs + Compare() +xmloff/source/style/XMLFontAutoStylePool.cxx:122 + _Bool (anonymous namespace)::XMLFontAutoStylePoolEntryCmp_Impl::operator()(const class std::unique_ptr > &,const class std::unique_ptr > &) const + const class std::unique_ptr > & r1 + Compare() +xmloff/source/text/XMLTextListAutoStylePool.cxx:123 + _Bool (anonymous namespace)::XMLTextListAutoStylePoolEntryCmp_Impl::operator()(const class std::unique_ptr > &,const class std::unique_ptr > &) const + const class std::unique_ptr > & r1 + Compare() diff --git a/compilerplugins/clang/constantparam.cxx b/compilerplugins/clang/constantparam.cxx new file mode 100644 index 000000000..5fd472954 --- /dev/null +++ b/compilerplugins/clang/constantparam.cxx @@ -0,0 +1,296 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#include "plugin.hxx" +#include "compat.hxx" +#include "check.hxx" +#include "functionaddress.hxx" + +/* + Find params on methods where the param is only ever passed as a single constant value. + + The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='constantparam' check + $ ./compilerplugins/clang/constantparam.py + + TODO look for OUString and OString params and check for call-params that are always either "" or default constructed + + FIXME this plugin manages to trigger crashes inside clang, when calling EvaluateAsInt, so I end up disabling it for a handful of files + here and there. +*/ + +namespace { + +struct MyCallSiteInfo +{ + std::string returnType; + std::string nameAndParams; + std::string paramName; + std::string paramType; + int paramIndex; // because in some declarations the names are empty + std::string callValue; + std::string sourceLocation; +}; +bool operator < (const MyCallSiteInfo &lhs, const MyCallSiteInfo &rhs) +{ + return std::tie(lhs.sourceLocation, lhs.paramIndex, lhs.callValue) + < std::tie(rhs.sourceLocation, rhs.paramIndex, rhs.callValue); +} + + +// try to limit the voluminous output a little +static std::set callSet; + +class ConstantParam: + public loplugin::FunctionAddress> +{ +public: + explicit ConstantParam(loplugin::InstantiationData const & data): FunctionAddress(data) {} + + virtual void run() override + { + // ignore some files that make clang crash inside EvaluateAsInt + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + if (loplugin::isSamePathname(fn, SRCDIR "/basegfx/source/matrix/b2dhommatrix.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/basegfx/source/matrix/b3dhommatrix.cxx")) + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + // this catches places that take the address of a method + for (auto functionDecl : getFunctionsWithAddressTaken()) + { + for (unsigned i = 0; i < functionDecl->getNumParams(); ++i) + addToCallSet(functionDecl, i, functionDecl->getParamDecl(i)->getName(), "unknown3"); + } + + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + + std::string output; + for (const MyCallSiteInfo & s : callSet) + output += s.returnType + "\t" + s.nameAndParams + "\t" + s.sourceLocation + "\t" + + s.paramName + "\t" + s.paramType + "\t" + s.callValue + "\n"; + std::ofstream myfile; + myfile.open( WORKDIR "/loplugin.constantparam.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + + bool shouldVisitTemplateInstantiations () const { return true; } + bool shouldVisitImplicitCode () const { return true; } + + bool VisitCallExpr( const CallExpr* ); + bool VisitCXXConstructExpr( const CXXConstructExpr* ); +private: + void addToCallSet(const FunctionDecl* functionDecl, int paramIndex, llvm::StringRef paramName, const std::string& callValue); + std::string getCallValue(const Expr* arg); +}; + +void ConstantParam::addToCallSet(const FunctionDecl* functionDecl, int paramIndex, llvm::StringRef paramName, const std::string& callValue) +{ + if (functionDecl->getInstantiatedFromMemberFunction()) + functionDecl = functionDecl->getInstantiatedFromMemberFunction(); + else if (functionDecl->getTemplateInstantiationPattern()) + functionDecl = functionDecl->getTemplateInstantiationPattern(); + + if (!functionDecl->getNameInfo().getLoc().isValid()) + return; + if (functionDecl->isVariadic()) + return; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) + return; + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( functionDecl->getLocation() ); + StringRef filename = getFilenameOfLocation(expansionLoc); + if (!loplugin::hasPathnamePrefix(filename, SRCDIR "/")) + return; + filename = filename.substr(strlen(SRCDIR)+1); + + MyCallSiteInfo aInfo; + aInfo.returnType = functionDecl->getReturnType().getCanonicalType().getAsString(); + + if (isa(functionDecl)) { + const CXXRecordDecl* recordDecl = dyn_cast(functionDecl)->getParent(); + aInfo.nameAndParams += recordDecl->getQualifiedNameAsString(); + aInfo.nameAndParams += "::"; + } + aInfo.nameAndParams += functionDecl->getNameAsString() + "("; + bool bFirst = true; + for (const ParmVarDecl *pParmVarDecl : functionDecl->parameters()) { + if (bFirst) + bFirst = false; + else + aInfo.nameAndParams += ","; + aInfo.nameAndParams += pParmVarDecl->getType().getCanonicalType().getAsString(); + } + aInfo.nameAndParams += ")"; + if (isa(functionDecl) && dyn_cast(functionDecl)->isConst()) { + aInfo.nameAndParams += " const"; + } + aInfo.paramName = paramName.str(); + aInfo.paramIndex = paramIndex; + if (paramIndex < (int)functionDecl->getNumParams()) + aInfo.paramType = functionDecl->getParamDecl(paramIndex)->getType().getCanonicalType().getAsString(); + + aInfo.callValue = callValue; + aInfo.sourceLocation = filename.str() + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(aInfo.sourceLocation); + + callSet.insert(aInfo); +} + +std::string ConstantParam::getCallValue(const Expr* arg) +{ + arg = arg->IgnoreParenCasts(); + if (isa(arg)) { + arg = dyn_cast(arg)->getExpr(); + } + arg = arg->IgnoreParenCasts(); + // ignore this, it seems to trigger an infinite recursion + if (isa(arg)) + return "unknown1"; + if (arg->isValueDependent()) + return "unknown2"; + APSInt x1; + if (compat::EvaluateAsInt(arg, x1, compiler.getASTContext())) + { + return compat::toString(x1, 10); + } + if (isa(arg)) { + return "0"; + } + if (isa(arg)) + { + const CXXBindTemporaryExpr* strippedArg = dyn_cast_or_null(arg->IgnoreParenCasts()); + if (strippedArg) + { + auto temp = dyn_cast(strippedArg->getSubExpr()); + if (temp->getNumArgs() == 0) + { + if (loplugin::TypeCheck(temp->getType()).Class("OUString").Namespace("rtl").GlobalNamespace()) { + return "\"\""; + } + if (loplugin::TypeCheck(temp->getType()).Class("OString").Namespace("rtl").GlobalNamespace()) { + return "\"\""; + } + return "defaultConstruct"; + } + } + } + + // Get the expression contents. + // This helps us find params which are always initialised with something like "OUString()". + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = arg->getBeginLoc(); + SourceLocation endLoc = arg->getEndLoc(); + const char *p1 = SM.getCharacterData( startLoc ); + const char *p2 = SM.getCharacterData( endLoc ); + if (!p1 || !p2 || (p2 - p1) < 0 || (p2 - p1) > 40) { + return "unknown"; + } + unsigned n = Lexer::MeasureTokenLength( endLoc, SM, compiler.getLangOpts()); + std::string s( p1, p2 - p1 + n); + // sanitize call value, makes using command line tools (and python) much less error prone + for (auto const & ch : s) + if (ch < 32) + return "sanitised"; + + // now normalize the value. For some params, like OUString, we can pass it as OUString() or "" and they are the same thing + if (s == "OUString()") + s = "\"\""; + else if (s == "OString()") + s = "\"\""; + return s; +} + +bool ConstantParam::VisitCallExpr(const CallExpr * callExpr) { + if (ignoreLocation(callExpr)) { + return true; + } + const FunctionDecl* functionDecl; + if (isa(callExpr)) { + functionDecl = dyn_cast(callExpr)->getMethodDecl(); + } + else { + functionDecl = callExpr->getDirectCallee(); + } + if (!functionDecl) + return true; + functionDecl = functionDecl->getCanonicalDecl(); + // method overrides don't always specify the same default params (although they probably should) + // so we need to work our way up to the root method + while (isa(functionDecl)) { + const CXXMethodDecl* methodDecl = dyn_cast(functionDecl); + if (methodDecl->size_overridden_methods()==0) + break; + functionDecl = *methodDecl->begin_overridden_methods(); + } + // work our way back to the root definition for template methods + if (functionDecl->getInstantiatedFromMemberFunction()) + functionDecl = functionDecl->getInstantiatedFromMemberFunction(); + else if (functionDecl->getTemplateInstantiationPattern()) + functionDecl = functionDecl->getTemplateInstantiationPattern(); + + unsigned len = std::max(callExpr->getNumArgs(), functionDecl->getNumParams()); + for (unsigned i = 0; i < len; ++i) { + const Expr* valExpr; + if (i < callExpr->getNumArgs()) + valExpr = callExpr->getArg(i); + else if (i < functionDecl->getNumParams() && functionDecl->getParamDecl(i)->hasDefaultArg()) + valExpr = functionDecl->getParamDecl(i)->getDefaultArg(); + else + // can happen in template code + continue; + std::string callValue = getCallValue(valExpr); + std::string paramName = i < functionDecl->getNumParams() + ? functionDecl->getParamDecl(i)->getName().str() + : "###" + std::to_string(i); + addToCallSet(functionDecl, i, paramName, callValue); + } + return true; +} + +bool ConstantParam::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr ) +{ + const CXXConstructorDecl* constructorDecl = constructExpr->getConstructor(); + constructorDecl = constructorDecl->getCanonicalDecl(); + + unsigned len = std::max(constructExpr->getNumArgs(), constructorDecl->getNumParams()); + for (unsigned i = 0; i < len; ++i) { + const Expr* valExpr; + if (i < constructExpr->getNumArgs()) + valExpr = constructExpr->getArg(i); + else if (i < constructorDecl->getNumParams() && constructorDecl->getParamDecl(i)->hasDefaultArg()) + valExpr = constructorDecl->getParamDecl(i)->getDefaultArg(); + else + // can happen in template code + continue; + std::string callValue = getCallValue(valExpr); + std::string paramName = i < constructorDecl->getNumParams() + ? constructorDecl->getParamDecl(i)->getName().str() + : "###" + std::to_string(i); + addToCallSet(constructorDecl, i, paramName, callValue); + } + return true; +} + + +loplugin::Plugin::Registration< ConstantParam > X("constantparam", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/constantparam.numbers.results b/compilerplugins/clang/constantparam.numbers.results new file mode 100644 index 000000000..34a326010 --- /dev/null +++ b/compilerplugins/clang/constantparam.numbers.results @@ -0,0 +1,3424 @@ +basctl/source/inc/dlged.hxx:77 + void basctl::DlgEdHint::DlgEdHint(enum basctl::DlgEdHint::Kind,class basctl::DlgEdObj *) + enum basctl::DlgEdHint::Kind + 2 +basctl/source/inc/sbxitem.hxx:47 + void basctl::SbxItem::SbxItem(unsigned short,const class basctl::ScriptDocument &,const class rtl::OUString &,const class rtl::OUString &,enum basctl::ItemType) + unsigned short nWhich + 30799 +basctl/source/inc/sbxitem.hxx:48 + void basctl::SbxItem::SbxItem(unsigned short,const class basctl::ScriptDocument &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,enum basctl::ItemType) + unsigned short nWhich + 30799 +basic/source/classes/sbunoobj.cxx:3206 + class com::sun::star::uno::Reference getTypeDescriptorEnumeration(const class rtl::OUString &,const class com::sun::star::uno::Sequence &,enum com::sun::star::reflection::TypeDescriptionSearchDepth) + enum com::sun::star::reflection::TypeDescriptionSearchDepth depth + -1 +basic/source/inc/expr.hxx:177 + void SbiExpression::SbiExpression(class SbiParser *,double,enum SbxDataType) + enum SbxDataType + 2 +basic/source/inc/runtime.hxx:347 + _Bool SbiRuntime::IsImageFlag(enum SbiImageFlags) const + enum SbiImageFlags n + 2 +basic/source/inc/sbjsmeth.hxx:31 + void SbJScriptMethod::SbJScriptMethod(enum SbxDataType) + enum SbxDataType + 12 +canvas/inc/verifyinput.hxx:103 + void verifyInput(const struct com::sun::star::geometry::Matrix2D &,const char *,const class com::sun::star::uno::Reference &,short) + short nArgPos + 2 +canvas/workben/canvasdemo.cxx:143 + void (anonymous namespace)::DemoRenderer::drawStringAt(class rtl::OString,double,double) + double y + 15 +canvas/workben/canvasdemo.cxx:482 + void (anonymous namespace)::DemoRenderer::drawRegularPolygon(double,double,int,double) + double centery + 35 +canvas/workben/canvasdemo.cxx:482 + void (anonymous namespace)::DemoRenderer::drawRegularPolygon(double,double,int,double) + double r + 15 +chart2/qa/extras/chart2export.cxx:522 + void checkPolynomialTrendline(const class com::sun::star::uno::Reference &,const class rtl::OUString &,int,double,double,double) + int aExpectedDegree + 3 +chart2/qa/extras/chart2export.cxx:544 + void checkMovingAverageTrendline(const class com::sun::star::uno::Reference &,const class rtl::OUString &,int) + int aExpectedPeriod + 3 +chart2/qa/extras/chart2export.cxx:1057 + void ::change(const class com::sun::star::uno::Reference &,short) + short nNumFmtTypeFlag + 16 +chart2/qa/extras/PivotChartTest.cxx:78 + void lclModifyFunction(const class com::sun::star::uno::Reference &,class std::basic_string_view >,enum com::sun::star::sheet::GeneralFunction) + enum com::sun::star::sheet::GeneralFunction eFunction + 2 +chart2/source/controller/inc/AccessibleBase.hxx:145 + void chart::AccessibleBase::RemoveState(short) + short aState + 23 +chart2/source/inc/LinePropertiesHelper.hxx:62 + void SetLineColor(const class com::sun::star::uno::Reference &,int) + int nColor + 14540253 +chart2/source/inc/ObjectIdentifier.hxx:180 + class rtl::OUString chart::ObjectIdentifier::createSeriesSubObjectStub(enum chart::ObjectType,const class rtl::OUString &,class std::basic_string_view >,class std::basic_string_view >) + enum chart::ObjectType eSubObjectType + 12 +chart2/source/inc/StatisticsHelper.hxx:75 + class com::sun::star::uno::Reference addErrorBars(const class com::sun::star::uno::Reference &,int,_Bool) + int nStyle + 2 +chart2/source/tools/RangeHighlighter.cxx:48 + void lcl_fillRanges(class com::sun::star::uno::Sequence &,const class com::sun::star::uno::Sequence &,class Color,int) + int nIndex + -1 +codemaker/source/javamaker/classfile.cxx:86 + void writeU4(class FileStream &,unsigned int) + unsigned int data + 3405691582 +comphelper/qa/unit/variadictemplates.cxx:57 + void extract(const class com::sun::star::uno::Sequence &,int,optional &,const class com::sun::star::uno::Reference &) + int nArg + 4 +connectivity/source/drivers/firebird/StatementCommonBase.hxx:92 + short connectivity::firebird::OStatementCommonBase::getSqlInfoItem(char) + char aInfoItem + 21 +connectivity/source/drivers/firebird/Util.hxx:121 + class rtl::OUString escapeWith(const class rtl::OUString &,const char,const char) + const char aKey + 39 +connectivity/source/drivers/firebird/Util.hxx:121 + class rtl::OUString escapeWith(const class rtl::OUString &,const char,const char) + const char aEscapeChar + 39 +connectivity/source/drivers/postgresql/pq_connection.cxx:363 + void properties2arrays(const class com::sun::star::uno::Sequence &,const class com::sun::star::uno::Reference &,unsigned short,class pq_sdbc_driver::(anonymous namespace)::cstr_vector &,class pq_sdbc_driver::(anonymous namespace)::cstr_vector &) + unsigned short enc + 76 +connectivity/source/drivers/postgresql/pq_statics.cxx:80 + void pq_sdbc_driver::(anonymous namespace)::PropertyDefEx::PropertyDefEx(const class rtl::OUString &,const class com::sun::star::uno::Type &,int) + int a + 16 +connectivity/source/inc/java/sql/ConnectionLog.hxx:105 + void connectivity::java::sql::ConnectionLog::log(const int,const class rtl::OUString &,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const + const int _nLogLevel + 300 +connectivity/source/inc/java/sql/ConnectionLog.hxx:111 + void connectivity::java::sql::ConnectionLog::log(const int,const class rtl::OUString &,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const + const int _nLogLevel + 300 +connectivity/source/inc/java/sql/ConnectionLog.hxx:117 + void connectivity::java::sql::ConnectionLog::log(const int,const class rtl::OUString &,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const + const int _nLogLevel + 300 +connectivity/source/inc/mysql/YTable.hxx:83 + void connectivity::mysql::OMySQLTable::OMySQLTable(class connectivity::sdbcx::OCollection *,const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,int) + int _nPrivileges + 511 +connectivity/source/inc/odbc/OPreparedStatement.hxx:75 + void connectivity::odbc::OPreparedStatement::setParameter(int,int,const class com::sun::star::uno::Sequence &) + int _nType + -2 +connectivity/source/inc/odbc/OTools.hxx:197 + class com::sun::star::uno::Sequence connectivity::odbc::OTools::getBytesValue(const class connectivity::odbc::OConnection *,void *,int,short,_Bool &,const class com::sun::star::uno::Reference &) + short _fSqlType + -2 +cppcanvas/source/inc/implrenderer.hxx:181 + _Bool cppcanvas::internal::ImplRenderer::isActionContained(class GDIMetaFile &,const char *,enum MetaActionType) + enum MetaActionType nType + 147 +cui/source/inc/autocdlg.hxx:308 + void OfaQuoteTabPage::CreateEntry(class weld::TreeView &,const class rtl::OUString &,unsigned short,unsigned short) + unsigned short nCol + 2 +cui/source/inc/autocdlg.hxx:308 + void OfaQuoteTabPage::CreateEntry(class weld::TreeView &,const class rtl::OUString &,unsigned short,unsigned short) + unsigned short nTextCol + 2 +cui/source/inc/chardlg.hxx:272 + void SvxCharPositionPage::UpdatePreview_Impl(unsigned char,unsigned char,short) + unsigned char nProp + 100 +cui/source/inc/cuihyperdlg.hxx:49 + void SvxHlinkCtrl::SvxHlinkCtrl(unsigned short,class SfxBindings &,class SvxHpLinkDlg *) + unsigned short nId + 10361 +cui/source/inc/optlingu.hxx:145 + void SvxLinguTabPage::HideGroups(unsigned short) + unsigned short nGrp + 8 +cui/source/inc/SpellDialog.hxx:110 + void svx::SentenceEditWindow_Impl::UndoActionStart(unsigned short) + unsigned short nId + 205 +cui/source/inc/SvxToolbarConfigPage.hxx:63 + void SvxToolbarConfigPage::AddFunction(int) + int nTarget + -1 +cui/source/options/cfgchart.hxx:89 + void SvxChartColorTableItem::SvxChartColorTableItem(unsigned short,const class SvxChartColorTable &) + unsigned short nWhich + 10437 +cui/source/options/connpoolsettings.hxx:75 + void offapp::DriverPoolingSettingsItem::DriverPoolingSettingsItem(unsigned short,const class offapp::DriverPoolingSettings &) + unsigned short _nId + 17148 +cui/source/options/dbregistersettings.hxx:67 + void svx::DatabaseMapItem::DatabaseMapItem(unsigned short,const class std::__debug::map, class std::allocator > > &) + unsigned short _nId + 17149 +cui/source/tabpages/align.cxx:60 + void lcl_MaybeResetAlignToDistro(class weld::ComboBox &,unsigned short,const class SfxItemSet &,unsigned short,unsigned short,type-parameter-?-?) + type-parameter-?-? eBlock + 4 +dbaccess/source/core/dataaccess/documentdefinition.hxx:183 + void dbaccess::ODocumentDefinition::firePropertyChange(int,const class com::sun::star::uno::Any &,const class com::sun::star::uno::Any &,_Bool,const struct dbaccess::ODocumentDefinition::NotifierAccess &) + int i_nHandle + 7 +dbaccess/source/core/inc/columnsettings.hxx:39 + void dbaccess::IPropertyContainer::registerMayBeVoidProperty(const class rtl::OUString &,int,int,class com::sun::star::uno::Any *,const class com::sun::star::uno::Type &) + int _nAttributes + 3 +dbaccess/source/ui/dlg/adminpages.hxx:219 + void dbaui::OGenericAdministrationPage::fillString(class SfxItemSet &,const class dbaui::OConnectionURLEdit *,unsigned short,_Bool &) + unsigned short _nID + 3 +dbaccess/source/ui/dlg/dsnItem.hxx:38 + void dbaui::DbuTypeCollectionItem::DbuTypeCollectionItem(short,class dbaccess::ODsnTypeCollection *) + short nWhich + 5 +dbaccess/source/ui/inc/charsetlistbox.hxx:36 + _Bool dbaui::CharSetListBox::StoreSelectedCharSet(class SfxItemSet &,const unsigned short) + const unsigned short _nItemId + 11 +dbaccess/source/ui/inc/FieldDescControl.hxx:139 + void dbaui::OFieldDescControl::CellModified(int,unsigned short) + int nRow + -1 +dbaccess/source/ui/inc/JAccess.hxx:57 + void dbaui::OJoinDesignViewAccess::notifyAccessibleEvent(const short,const class com::sun::star::uno::Any &,const class com::sun::star::uno::Any &) + const short _nEventId + 7 +dbaccess/source/ui/querydesign/SelectionBrowseBox.hxx:88 + class rtl::Reference dbaui::OSelectionBrowseBox::InsertField(const class rtl::Reference &,unsigned short,_Bool,_Bool) + unsigned short _nColumnPosition + 65535 +drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx:111 + class drawinglayer::primitive3d::Primitive3DContainer getLineTubeSegments(unsigned int,const class drawinglayer::attribute::MaterialAttribute3D &) + unsigned int nSegments + 8 +drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx:189 + class drawinglayer::primitive3d::Primitive3DContainer getLineCapSegments(unsigned int,const class drawinglayer::attribute::MaterialAttribute3D &) + unsigned int nSegments + 8 +drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx:285 + class drawinglayer::primitive3d::Primitive3DContainer getLineCapRoundSegments(unsigned int,const class drawinglayer::attribute::MaterialAttribute3D &) + unsigned int nSegments + 8 +drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx:294 + class drawinglayer::primitive3d::Primitive3DContainer getLineJoinSegments(unsigned int,const class drawinglayer::attribute::MaterialAttribute3D &,double,double,enum basegfx::B2DLineJoin) + unsigned int nSegments + 8 +editeng/source/editeng/impedit.hxx:699 + _Bool ImpEditEngine::HasScriptType(int,unsigned short) const + unsigned short nType + 3 +editeng/source/editeng/impedit.hxx:1017 + void ImpEditEngine::SetLanguageAndFont(const struct ESelection &,struct o3tl::strong_int,unsigned short,const class vcl::Font *,unsigned short) + unsigned short nLangWhichId + 4040 +editeng/source/editeng/impedit.hxx:1017 + void ImpEditEngine::SetLanguageAndFont(const struct ESelection &,struct o3tl::strong_int,unsigned short,const class vcl::Font *,unsigned short) + unsigned short nFontWhichId + 4042 +editeng/source/editeng/textconv.hxx:87 + void TextConvWrapper::SetLanguageAndFont(const struct ESelection &,struct o3tl::strong_int,unsigned short,const class vcl::Font *,unsigned short) + unsigned short nLangWhichId + 4040 +editeng/source/editeng/textconv.hxx:87 + void TextConvWrapper::SetLanguageAndFont(const struct ESelection &,struct o3tl::strong_int,unsigned short,const class vcl::Font *,unsigned short) + unsigned short nFontWhichId + 4042 +editeng/source/outliner/outlundo.hxx:31 + void OutlinerUndoBase::OutlinerUndoBase(unsigned short,class Outliner *) + unsigned short nId + 200 +filter/source/config/cache/filtercache.hxx:330 + _Bool filter::config::FilterCache::isFillState(enum filter::config::FilterCache::EFillState) const + enum filter::config::FilterCache::EFillState eRequired + 2 +filter/source/msfilter/mscodec.cxx:57 + void lclRotateLeft(type-parameter-?-? &,unsigned char,unsigned char) + unsigned char nWidth + 15 +filter/source/msfilter/mscodec.cxx:72 + unsigned short lclGetKey(const unsigned char *,unsigned long) + unsigned long nBufferSize + 16 +filter/source/msfilter/mscodec.cxx:97 + unsigned short lclGetHash(const unsigned char *,unsigned long) + unsigned long nBufferSize + 16 +forms/source/richtext/richtextcontrol.cxx:83 + void implAdjustTriStateFlag(const class com::sun::star::uno::Reference &,const class rtl::OUString &,long &,long,long) + long _nPositiveFlag + 256 +forms/source/richtext/richtextcontrol.cxx:83 + void implAdjustTriStateFlag(const class com::sun::star::uno::Reference &,const class rtl::OUString &,long &,long,long) + long nNegativeFlag + 512 +forms/source/richtext/rtattributes.hxx:51 + void frm::AttributeState::AttributeState(enum frm::AttributeCheckState) + enum frm::AttributeCheckState _eCheckState + 2 +formula/source/core/api/FormulaCompiler.cxx:254 + const char16_t * lcl_UnicodeStrChr(const char16_t *,char16_t) + char16_t c + 34 +fpicker/source/office/autocmpledit.hxx:39 + void AutocompleteEdit::select_region(int,int) + int nEndPos + -1 +fpicker/source/office/iodlg.hxx:205 + void SvtFileDialog::displayIOException(const class rtl::OUString &,enum com::sun::star::ucb::IOErrorCode) + enum com::sun::star::ucb::IOErrorCode _eCode + 5 +framework/inc/uielement/macrosmenucontroller.hxx:50 + void framework::MacrosMenuController::addScriptItems(class PopupMenu *,unsigned short) + unsigned short startItemId + 4 +framework/source/uielement/thesaurusmenucontroller.cxx:48 + void (anonymous namespace)::ThesaurusMenuController::getMeanings(class std::__debug::vector > &,const class rtl::OUString &,const struct com::sun::star::lang::Locale &,unsigned long) + unsigned long nMaxSynonms + 7 +hwpfilter/source/hgzip.h:90 + int gz_flush(struct gz_stream *,int) + int flush + 4 +hwpfilter/source/hwpfile.h:253 + _Bool HWPFile::already_importing_type(unsigned char) const + unsigned char scflag + 16 +hwpfilter/source/lexer.cxx:202 + struct (anonymous namespace)::yy_buffer_state * yy_create_buffer(struct _IO_FILE *,int) + int size + 16384 +hwpfilter/source/mzstring.h:124 + int MzString::rfind(char) + char c + 125 +hwpfilter/source/mzstring.h:128 + void MzString::replace(int,char) + char c + 32 +idlc/inc/astattribute.hxx:39 + void AstAttribute::AstAttribute(enum NodeType,unsigned int,const class AstType *,const class rtl::OString &,class AstScope *) + enum NodeType nodeType + 12 +idlc/inc/astconstant.hxx:30 + void AstConstant::AstConstant(const enum ExprType,const enum NodeType,class AstExpression *,const class rtl::OString &,class AstScope *) + const enum ExprType type + 2 +idlc/inc/astconstant.hxx:30 + void AstConstant::AstConstant(const enum ExprType,const enum NodeType,class AstExpression *,const class rtl::OString &,class AstScope *) + const enum NodeType nodeType + 20 +idlc/inc/astexpression.hxx:97 + void AstExpression::AstExpression(int,enum ExprType) + enum ExprType et + 10 +idlc/inc/astmember.hxx:37 + void AstMember::AstMember(enum NodeType,const class AstType *,const class rtl::OString &,class AstScope *) + enum NodeType type + 14 +idlc/inc/astservice.hxx:35 + void AstService::AstService(const enum NodeType,const class rtl::OString &,class AstScope *) + const enum NodeType type + 24 +idlc/inc/aststruct.hxx:41 + void AstStruct::AstStruct(const enum NodeType,const class rtl::OString &,const class AstStruct *,class AstScope *) + const enum NodeType type + 10 +idlc/inc/errorhandler.hxx:83 + void ErrorHandler::error3(enum ErrorCode,const class AstDeclaration *,const class AstDeclaration *,const class AstDeclaration *) + enum ErrorCode e + 3 +include/basegfx/curve/b2dbeziertools.hxx:44 + void basegfx::B2DCubicBezierHelper::B2DCubicBezierHelper(const class basegfx::B2DCubicBezier &,unsigned int) + unsigned int nDivisions + 9 +include/basegfx/range/b2ibox.hxx:71 + void basegfx::B2IBox::B2IBox(int,int,int,int) + int x2 + 10 +include/basegfx/range/b2ibox.hxx:71 + void basegfx::B2IBox::B2IBox(int,int,int,int) + int y2 + 10 +include/basegfx/utils/tools.hxx:118 + class basegfx::B2DPolyPolygon number2PolyPolygon(double,int,int,_Bool) + int nTotalDigits + 10 +include/basegfx/utils/tools.hxx:118 + class basegfx::B2DPolyPolygon number2PolyPolygon(double,int,int,_Bool) + int nDecPlaces + 3 +include/basic/sbxcore.hxx:65 + _Bool SbxBase::IsReset(enum SbxFlagBits) const + enum SbxFlagBits n + 256 +include/comphelper/docpasswordhelper.hxx:268 + class rtl::OUString comphelper::DocPasswordHelper::GetOoxHashAsBase64(const class rtl::OUString &,const class rtl::OUString &,unsigned int,enum comphelper::Hash::IterCount,class std::basic_string_view >) + enum comphelper::Hash::IterCount eIterCount + 2 +include/comphelper/docpasswordhelper.hxx:324 + class com::sun::star::uno::Sequence comphelper::DocPasswordHelper::GenerateRandomByteSequence(int) + int nLength + 16 +include/comphelper/propagg.hxx:124 + void comphelper::OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper(const class com::sun::star::uno::Sequence &,const class com::sun::star::uno::Sequence &,class comphelper::IPropertyInfoService *,int) + int _nFirstAggregateId + 10000 +include/comphelper/propagg.hxx:290 + void comphelper::OPropertySetAggregationHelper::declareForwardedProperty(int) + int _nHandle + 194 +include/comphelper/property.hxx:52 + void ModifyPropertyAttributes(class com::sun::star::uno::Sequence &,const class rtl::OUString &,short,short) + short _nRemoveAttrib + 8 +include/comphelper/seqstream.hxx:104 + void comphelper::OSequenceOutputStream::OSequenceOutputStream(class com::sun::star::uno::Sequence &,double,int) + int _nMinimumResize + 128 +include/comphelper/storagehelper.hxx:118 + class com::sun::star::uno::Reference comphelper::OStorageHelper::GetStorageFromStream(const class com::sun::star::uno::Reference &,int,const class com::sun::star::uno::Reference &) + int nStorageMode + 7 +include/connectivity/dbtools.hxx:303 + class com::sun::star::sdbc::SQLException prependErrorInfo(const class com::sun::star::sdbc::SQLException &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,const enum dbtools::StandardSQLState) + const enum dbtools::StandardSQLState _eSQLState + 2147483647 +include/connectivity/sqlerror.hxx:82 + class rtl::OUString connectivity::SQLError::getErrorMessage(const int) const + const int _eCondition + 300 +include/connectivity/sqlerror.hxx:93 + int connectivity::SQLError::getErrorCode(const int) + const int _eCondition + 550 +include/connectivity/sqlerror.hxx:161 + void connectivity::SQLError::raiseException(const int) const + const int _eCondition + 200 +include/connectivity/sqlerror.hxx:186 + void connectivity::SQLError::raiseTypedException(const int,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Type &) const + const int _eCondition + 100 +include/dbaccess/genericcontroller.hxx:311 + _Bool dbaui::OGenericUnoController::isFeatureSupported(int) + int _nId + 5502 +include/drawinglayer/attribute/fillhatchattribute.hxx:51 + void drawinglayer::attribute::FillHatchAttribute::FillHatchAttribute(enum drawinglayer::attribute::HatchStyle,double,double,const class basegfx::BColor &,unsigned int,_Bool) + unsigned int nMinimalDiscreteDistance + 3 +include/drawinglayer/primitive2d/mediaprimitive2d.hxx:63 + void drawinglayer::primitive2d::MediaPrimitive2D::MediaPrimitive2D(const class basegfx::B2DHomMatrix &,const class rtl::OUString &,const class basegfx::BColor &,unsigned int,const class Graphic &) + unsigned int nDiscreteBorder + 4 +include/editeng/AccessibleParaManager.hxx:128 + void accessibility::AccessibleParaManager::FireEvent(int,const short) const + const short nEventId + 21 +include/editeng/AccessibleParaManager.hxx:242 + void accessibility::AccessibleParaManager::SetState(int,const short) + const short nStateId + 11 +include/editeng/AccessibleParaManager.hxx:244 + void accessibility::AccessibleParaManager::UnSetState(int,const short) + const short nStateId + 11 +include/editeng/bulletitem.hxx:60 + void SvxBulletItem::SvxBulletItem(unsigned short) + unsigned short nWhich + 4017 +include/editeng/editeng.hxx:299 + struct ESelection EditEngine::GetWord(const struct ESelection &,unsigned short) const + unsigned short nWordType + 2 +include/editeng/editeng.hxx:311 + void EditEngine::InsertParagraph(int,const class EditTextObject &,const _Bool) + int nPara + 2147483647 +include/editeng/editeng.hxx:344 + void EditEngine::UndoActionStart(unsigned short,const struct ESelection &) + unsigned short nId + 111 +include/editeng/editstat.hxx:89 + void SetFlags(enum EVControlBits &,enum EVControlBits,_Bool) + enum EVControlBits nMask + 16 +include/editeng/editund2.hxx:39 + void EditUndoManager::EditUndoManager(unsigned short) + unsigned short nMaxUndoActionCount + 20 +include/editeng/editview.hxx:256 + void EditView::RemoveCharAttribs(int,unsigned short) + unsigned short nWhich + 4029 +include/editeng/editview.hxx:358 + void EditView::InitLOKSpecialPositioning(enum MapUnit,const class tools::Rectangle &,const class Point &) + enum MapUnit eUnit + 9 +include/editeng/fhgtitem.hxx:72 + void SvxFontHeightItem::SetHeight(unsigned int,unsigned short,enum MapUnit,enum MapUnit) + enum MapUnit eUnit + 8 +include/editeng/flditem.hxx:73 + void SvxFieldItem::SvxFieldItem(class std::unique_ptr >,const unsigned short) + const unsigned short nId + 4061 +include/editeng/flditem.hxx:74 + void SvxFieldItem::SvxFieldItem(const class SvxFieldData &,const unsigned short) + const unsigned short nId + 4061 +include/editeng/justifyitem.hxx:33 + void SvxHorJustifyItem::SvxHorJustifyItem(const unsigned short) + const unsigned short nId + 1059 +include/editeng/justifyitem.hxx:60 + void SvxVerJustifyItem::SvxVerJustifyItem(const unsigned short) + const unsigned short nId + 1060 +include/editeng/legacyitem.hxx:172 + void Create(class SvxFormatBreakItem &,class SvStream &,unsigned short) + unsigned short nItemVersion + 5050 +include/editeng/legacyitem.hxx:179 + void Create(class SvxFormatKeepItem &,class SvStream &,unsigned short) + unsigned short nItemVersion + 5050 +include/editeng/legacyitem.hxx:186 + void Create(class SvxShadowItem &,class SvStream &,unsigned short) + unsigned short nItemVersion + 5050 +include/editeng/nhypitem.hxx:29 + void SvxNoHyphenItem::SvxNoHyphenItem(const unsigned short) + const unsigned short nId + 19 +include/editeng/opaqitem.hxx:36 + void SvxOpaqueItem::SvxOpaqueItem(const unsigned short,const _Bool) + const unsigned short nId + 99 +include/editeng/outliner.hxx:154 + void Paragraph::RemoveFlag(enum ParaFlag) + enum ParaFlag nFlag + 256 +include/editeng/outliner.hxx:373 + void OutlinerViewShell::NotifyOtherView(class OutlinerViewShell *,int,const class rtl::OString &,const class rtl::OString &) + int nType + 25 +include/editeng/outliner.hxx:846 + void Outliner::SetParaFlag(class Paragraph *,enum ParaFlag) + enum ParaFlag nFlag + 256 +include/editeng/outliner.hxx:847 + _Bool Outliner::HasParaFlag(const class Paragraph *,enum ParaFlag) + enum ParaFlag nFlag + 256 +include/editeng/outlobj.hxx:111 + void OutlinerParaObject::SetStyleSheets(unsigned short,const class rtl::OUString &,const enum SfxStyleFamily &) + const enum SfxStyleFamily & rNewFamily + 8 +include/editeng/prntitem.hxx:38 + void SvxPrintItem::SvxPrintItem(const unsigned short,const _Bool) + const unsigned short nId + 98 +include/editeng/svxrtf.hxx:223 + class rtl::OUString & SvxRTFParser::DelCharAtEnd(class rtl::OUString &,const char16_t) + const char16_t cDel + 59 +include/editeng/txtrange.hxx:61 + void TextRanger::TextRanger(const class basegfx::B2DPolyPolygon &,const class basegfx::B2DPolyPolygon *,unsigned short,unsigned short,unsigned short,_Bool,_Bool,_Bool) + unsigned short nCacheSize + 30 +include/editeng/txtrange.hxx:61 + void TextRanger::TextRanger(const class basegfx::B2DPolyPolygon &,const class basegfx::B2DPolyPolygon *,unsigned short,unsigned short,unsigned short,_Bool,_Bool,_Bool) + unsigned short nLeft + 2 +include/editeng/txtrange.hxx:61 + void TextRanger::TextRanger(const class basegfx::B2DPolyPolygon &,const class basegfx::B2DPolyPolygon *,unsigned short,unsigned short,unsigned short,_Bool,_Bool,_Bool) + unsigned short nRight + 2 +include/editeng/unoedhlp.hxx:45 + void SvxEditSourceHint::SvxEditSourceHint(enum SfxHintId) + enum SfxHintId nId + 30 +include/editeng/unoedhlp.hxx:46 + void SvxEditSourceHint::SvxEditSourceHint(enum SfxHintId,unsigned long,int,int) + enum SfxHintId nId + 29 +include/editeng/writingmodeitem.hxx:31 + void SvxWritingModeItem::SvxWritingModeItem(enum com::sun::star::text::WritingMode,unsigned short) + unsigned short nWhich + 1162 +include/filter/msfilter/dffpropset.hxx:64 + class rtl::OUString DffPropSet::GetPropertyString(unsigned int,class SvStream &) const + unsigned int nId + 896 +include/filter/msfilter/escherex.hxx:726 + void EscherPropertyContainer::Commit(class SvStream &,unsigned short,unsigned short) + unsigned short nVersion + 3 +include/filter/msfilter/msdffimp.hxx:568 + _Bool SvxMSDffManager::SeekToRec2(unsigned short,unsigned short,unsigned long) const + unsigned short nRecId1 + 4008 +include/filter/msfilter/msdffimp.hxx:568 + _Bool SvxMSDffManager::SeekToRec2(unsigned short,unsigned short,unsigned long) const + unsigned short nRecId2 + 4000 +include/filter/msfilter/rtfutil.hxx:28 + class rtl::OString OutHex(unsigned long,unsigned char) + unsigned char nLen + 2 +include/filter/msfilter/rtfutil.hxx:64 + class rtl::OString WriteHex(const unsigned char *,unsigned int,class SvStream *,unsigned int) + unsigned int nLimit + 64 +include/filter/msfilter/util.hxx:103 + _Bool msfilter::util::WW8ReadFieldParams::GetTokenSttFromTo(int *,int *,int) + int _nMax + 9 +include/formula/tokenarray.hxx:286 + unsigned short formula::FormulaTokenArray::RemoveToken(unsigned short,unsigned short) + unsigned short nCount + 2 +include/formula/tokenarray.hxx:534 + void formula::FormulaTokenIterator::Item::Item(const class formula::FormulaTokenArray *,short,short) + short pc + -1 +include/formula/tokenarray.hxx:534 + void formula::FormulaTokenIterator::Item::Item(const class formula::FormulaTokenArray *,short,short) + short stop + 32767 +include/formula/tokenarray.hxx:657 + void formula::FormulaTokenArrayPlainIterator::AfterRemoveToken(unsigned short,unsigned short) + unsigned short nCount + 2 +include/linguistic/spelldta.hxx:87 + class com::sun::star::uno::Reference linguistic::SpellAlternatives::CreateSpellAlternatives(const class rtl::OUString &,struct o3tl::strong_int,short,const class com::sun::star::uno::Sequence &) + short nTypeP + 4 +include/o3tl/typed_flags_set.hxx:135 + typename typed_flags::Wrap operator^(type-parameter-?-?,typename typed_flags::Wrap) + type-parameter-?-? lhs + 1535 +include/o3tl/unit_conversion.hxx:213 + auto convertSaturate(type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) + type-parameter-?-? to + 7 +include/oox/core/contexthandler2.hxx:168 + _Bool oox::core::ContextHandler2Helper::isParentElement(int,int) const + int nElement + 525391 +include/oox/core/contexthandler2.hxx:168 + _Bool oox::core::ContextHandler2Helper::isParentElement(int,int) const + int nCountBack + 4 +include/oox/drawingml/drawingmltypes.hxx:226 + void oox::drawingml::EmuRectangle::EmuRectangle(long,long,long,long) + long nX + -1 +include/oox/drawingml/drawingmltypes.hxx:226 + void oox::drawingml::EmuRectangle::EmuRectangle(long,long,long,long) + long nY + -1 +include/oox/drawingml/drawingmltypes.hxx:226 + void oox::drawingml::EmuRectangle::EmuRectangle(long,long,long,long) + long nWidth + -1 +include/oox/drawingml/drawingmltypes.hxx:226 + void oox::drawingml::EmuRectangle::EmuRectangle(long,long,long,long) + long nHeight + -1 +include/oox/export/drawingml.hxx:183 + _Bool oox::drawingml::DrawingML::HasEnhancedCustomShapeSegmentCommand(const class com::sun::star::uno::Reference &,const short) + const short nCommand + 6 +include/oox/export/drawingml.hxx:209 + void oox::drawingml::DrawingML::WriteSolidFill(const class Color,const class com::sun::star::uno::Sequence &,int) + int nAlpha + 100000 +include/oox/export/drawingml.hxx:222 + void oox::drawingml::DrawingML::WriteBlipFill(const class com::sun::star::uno::Reference &,const class rtl::OUString &,int) + int nXmlNamespace + 421 +include/oox/export/vmlexport.hxx:167 + void oox::vml::VMLExport::AddShapeAttribute(int,const class rtl::OString &) + int nAttribute + 5459 +include/oox/helper/attributelist.hxx:101 + class oox::drawingml::Color oox::AttributeList::getHighlightColor(int) const + int nAttrToken + 988640 +include/oox/helper/attributelist.hxx:145 + const char * oox::AttributeList::getChar(int) const + int nAttrToken + 4180 +include/oox/helper/attributelist.hxx:168 + unsigned int oox::AttributeList::getUnsignedHex(int,unsigned int) const + int nAttrToken + 4319 +include/oox/helper/attributelist.hxx:168 + unsigned int oox::AttributeList::getUnsignedHex(int,unsigned int) const + unsigned int nDefault + 4294967295 +include/oox/helper/binaryoutputstream.hxx:86 + void oox::BinaryOutputStream::writeCharArrayUC(class std::basic_string_view >,unsigned short) + unsigned short eTextEnc + 12 +include/oox/helper/binarystreambase.hxx:103 + void oox::BinaryStreamBase::alignToBlock(int,long) + int nBlockSize + 4 +include/oox/helper/containerhelper.hxx:193 + class rtl::OUString oox::ContainerHelper::insertByUnusedName(const class com::sun::star::uno::Reference &,const class rtl::OUString &,char16_t,const class com::sun::star::uno::Any &) + char16_t cSeparator + 32 +include/oox/helper/helper.hxx:115 + type-parameter-?-? getIntervalValue(type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) + type-parameter-?-? nEnd + 360 +include/oox/helper/propertyset.hxx:110 + _Bool oox::PropertySet::setProperty(int,class Color) + int nPropId + 515 +include/oox/helper/textinputstream.hxx:42 + void oox::TextInputStream::TextInputStream(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,unsigned short) + unsigned short eTextEnc + 76 +include/oox/mathml/importutils.hxx:123 + class rtl::OUString & oox::formulaimport::XmlStream::AttributeList::operator[](int) + ###1 + 1512928 +include/oox/mathml/importutils.hxx:136 + void oox::formulaimport::XmlStream::Tag::Tag(int,const class com::sun::star::uno::Reference &) + int token + -1 +include/oox/mathml/importutils.hxx:151 + _Bool oox::formulaimport::XmlStream::Tag::attribute(int,_Bool) const + int token + 1512928 +include/oox/mathml/importutils.hxx:155 + char16_t oox::formulaimport::XmlStream::Tag::attribute(int,char16_t) const + int token + 1512928 +include/oox/ole/axcontrol.hxx:949 + type-parameter-?-? & oox::ole::EmbeddedControl::createModel(const type-parameter-?-? &) + const type-parameter-?-? & rParam + 6 +include/oox/ole/olehelper.hxx:77 + void oox::ole::StdFontInfo::StdFontInfo(const class rtl::OUString &,unsigned int) + unsigned int nHeight + 82500 +include/oox/ole/vbaproject.hxx:154 + void oox::ole::VbaProject::addDummyModule(const class rtl::OUString &,int) + int nType + 4 +include/sfx2/app.hxx:85 + void SfxLinkItem::SfxLinkItem(unsigned short,const class Link &) + unsigned short nWhichId + 5646 +include/sfx2/ctrlitem.hxx:91 + void SfxStatusForwarder::SfxStatusForwarder(unsigned short,class SfxControllerItem &) + unsigned short nSlotId + 10930 +include/sfx2/evntconf.hxx:72 + void SfxEventNamesItem::SfxEventNamesItem(const unsigned short) + const unsigned short nId + 6101 +include/sfx2/fcontnr.hxx:54 + class std::shared_ptr SfxFilterContainer::GetAnyFilter(enum SfxFilterFlags,enum SfxFilterFlags) const + enum SfxFilterFlags nMust + 3 +include/sfx2/fcontnr.hxx:54 + class std::shared_ptr SfxFilterContainer::GetAnyFilter(enum SfxFilterFlags,enum SfxFilterFlags) const + enum SfxFilterFlags nDont + 393216 +include/sfx2/fcontnr.hxx:55 + class std::shared_ptr SfxFilterContainer::GetFilter4EA(const class rtl::OUString &,enum SfxFilterFlags,enum SfxFilterFlags) const + enum SfxFilterFlags nMust + 2 +include/sfx2/fcontnr.hxx:55 + class std::shared_ptr SfxFilterContainer::GetFilter4EA(const class rtl::OUString &,enum SfxFilterFlags,enum SfxFilterFlags) const + enum SfxFilterFlags nDont + 393216 +include/sfx2/fcontnr.hxx:56 + class std::shared_ptr SfxFilterContainer::GetFilter4Extension(const class rtl::OUString &,enum SfxFilterFlags,enum SfxFilterFlags) const + enum SfxFilterFlags nDont + 393216 +include/sfx2/fcontnr.hxx:57 + class std::shared_ptr SfxFilterContainer::GetFilter4FilterName(const class rtl::OUString &,enum SfxFilterFlags,enum SfxFilterFlags) const + enum SfxFilterFlags nDont + 393216 +include/sfx2/fcontnr.hxx:88 + class std::shared_ptr SfxFilterMatcher::GetFilter4Mime(const class rtl::OUString &,enum SfxFilterFlags,enum SfxFilterFlags) const + enum SfxFilterFlags nDont + 393216 +include/sfx2/fcontnr.hxx:109 + void SfxFilterMatcherIter::SfxFilterMatcherIter(const class SfxFilterMatcher &,enum SfxFilterFlags,enum SfxFilterFlags) + enum SfxFilterFlags nNotMask + 393216 +include/sfx2/frame.hxx:192 + void SfxUnoFrameItem::SfxUnoFrameItem(unsigned short,const class com::sun::star::uno::Reference &) + unsigned short nWhich + 6516 +include/sfx2/linkmgr.hxx:65 + _Bool sfx2::LinkManager::InsertLink(class sfx2::SvBaseLink *,enum sfx2::SvBaseLinkObjectType,enum SfxLinkUpdateMode,const class rtl::OUString *) + enum SfxLinkUpdateMode nUpdateType + 3 +include/sfx2/lokhelper.hxx:33 + void LokMouseEventData::LokMouseEventData(int,class Point,int,enum MouseEventModifiers,int,int) + enum MouseEventModifiers eModifiers + 256 +include/sfx2/lokhelper.hxx:87 + void SfxLokHelper::notifyOtherViews(const class SfxViewShell *,int,const class boost::property_tree::basic_ptree, class std::allocator >, class std::__cxx11::basic_string, class std::allocator >, struct std::less, class std::allocator > > > &) + int nType + 24 +include/sfx2/lokhelper.hxx:112 + void SfxLokHelper::notifyAllViews(int,const class rtl::OString &) + int nType + 38 +include/sfx2/objsh.hxx:675 + void SfxObjectShell::AppendInfoBarWhenReady(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,enum InfobarType,_Bool) + enum InfobarType aInfobarType + 2 +include/sfx2/opengrf.hxx:38 + void SvxOpenGraphicDialog::SvxOpenGraphicDialog(const class rtl::OUString &,class weld::Window *,short) + short nDialogType + 13 +include/sfx2/request.hxx:64 + void SfxRequest::SfxRequest(unsigned short,enum SfxCallMode,const class SfxAllItemSet &,const class SfxAllItemSet &) + unsigned short nSlot + 5904 +include/sfx2/sfxhtml.hxx:64 + _Bool SfxHTMLParser::ParseAreaOptions(class ImageMap *,const class rtl::OUString &,enum SvMacroItemId,enum SvMacroItemId) + enum SvMacroItemId nEventMouseOver + 5100 +include/sfx2/sfxhtml.hxx:64 + _Bool SfxHTMLParser::ParseAreaOptions(class ImageMap *,const class rtl::OUString &,enum SvMacroItemId,enum SvMacroItemId) + enum SvMacroItemId nEventMouseOut + 5102 +include/sfx2/sidebar/SidebarController.hxx:132 + _Bool sfx2::sidebar::SidebarController::IsDeckOpen(const int) + const int nIndex + -1 +include/sfx2/tabdlg.hxx:51 + void SfxTabDialogItem::SfxTabDialogItem(unsigned short,const class SfxItemSet &) + unsigned short nId + 11022 +include/sot/stg.hxx:99 + class BaseStorage * BaseStorage::OpenUCBStorage(const class rtl::OUString &,enum StreamMode,_Bool) + enum StreamMode + 2050 +include/sot/stg.hxx:102 + class BaseStorage * BaseStorage::OpenOLEStorage(const class rtl::OUString &,enum StreamMode,_Bool) + enum StreamMode + 2050 +include/sot/storage.hxx:44 + void SotTempStream::SotTempStream(const class rtl::OUString &,enum StreamMode) + enum StreamMode + 2051 +include/store/store.h:62 + storeError store_createMemoryFile(unsigned short,void **) + unsigned short nPageSize + 1024 +include/store/store.h:79 + storeError store_openFile(struct _rtl_uString *,enum storeAccessMode,unsigned short,void **) + unsigned short nPageSize + 1024 +include/svl/globalnameitem.hxx:34 + void SfxGlobalNameItem::SfxGlobalNameItem(unsigned short,const class SvGlobalName &) + unsigned short nWhich + 5561 +include/svl/int64item.hxx:21 + void SfxInt64Item::SfxInt64Item(unsigned short,long) + unsigned short nWhich + 11141 +include/svl/int64item.hxx:21 + void SfxInt64Item::SfxInt64Item(unsigned short,long) + long nVal + 75 +include/svl/itemset.hxx:206 + void SfxItemSet::PutExtended(const class SfxItemSet &,enum SfxItemState,enum SfxItemState) + enum SfxItemState eDontCareAs + 16 +include/svl/languageoptions.hxx:120 + _Bool SvtSystemLanguageOptions::isKeyboardLayoutTypeInstalled(short) const + short scriptType + 2 +include/svl/svdde.hxx:157 + void DdePoke::DdePoke(class DdeConnection &,const class rtl::OUString &,const class DdeData &,long) + long + 30000 +include/svl/svdde.hxx:164 + void DdeExecute::DdeExecute(class DdeConnection &,const class rtl::OUString &,long) + long + 30000 +include/svl/urihelper.hxx:51 + class rtl::OUString SmartRel2Abs(const class INetURLObject &,const class rtl::OUString &,const class Link &,_Bool,_Bool,enum INetURLObject::EncodeMechanism,enum INetURLObject::DecodeMechanism,unsigned short,enum FSysStyle) + unsigned short eCharset + 76 +include/svl/urihelper.hxx:51 + class rtl::OUString SmartRel2Abs(const class INetURLObject &,const class rtl::OUString &,const class Link &,_Bool,_Bool,enum INetURLObject::EncodeMechanism,enum INetURLObject::DecodeMechanism,unsigned short,enum FSysStyle) + enum FSysStyle eStyle + 7 +include/svl/urihelper.hxx:116 + class rtl::OUString FindFirstURLInText(const class rtl::OUString &,int &,int &,const class CharClass &,enum INetURLObject::EncodeMechanism,unsigned short) + unsigned short eCharset + 76 +include/svl/urihelper.hxx:148 + class rtl::OUString removePassword(const class rtl::OUString &,enum INetURLObject::EncodeMechanism,enum INetURLObject::DecodeMechanism,unsigned short) + enum INetURLObject::DecodeMechanism eDecodeMechanism + 3 +include/svl/urihelper.hxx:148 + class rtl::OUString removePassword(const class rtl::OUString &,enum INetURLObject::EncodeMechanism,enum INetURLObject::DecodeMechanism,unsigned short) + unsigned short eCharset + 76 +include/svl/zformat.hxx:396 + _Bool SvNumberformat::IsInQuote(const class rtl::OUString &,int,char16_t,char16_t,char16_t) + char16_t cEscOut + 92 +include/svl/zformat.hxx:411 + int SvNumberformat::GetQuoteEnd(const class rtl::OUString &,int,char16_t,char16_t) + char16_t cQuote + 34 +include/svtools/brwbox.hxx:643 + void BrowseBox::commitBrowseBoxEvent(short,const class com::sun::star::uno::Any &,const class com::sun::star::uno::Any &) + short nEventId + 7 +include/svtools/ctrlbox.hxx:382 + void FontNameBox::set_size_request(int,int) + int nHeight + -1 +include/svtools/ctrlbox.hxx:462 + void FontSizeBox::EnableRelativeMode(unsigned short,unsigned short,unsigned short) + unsigned short nMin + 5 +include/svtools/ctrlbox.hxx:462 + void FontSizeBox::EnableRelativeMode(unsigned short,unsigned short,unsigned short) + unsigned short nMax + 995 +include/svtools/ctrlbox.hxx:462 + void FontSizeBox::EnableRelativeMode(unsigned short,unsigned short,unsigned short) + unsigned short nStep + 5 +include/svtools/ctrlbox.hxx:463 + void FontSizeBox::EnablePtRelativeMode(short,short,short) + short nStep + 10 +include/svtools/htmlout.hxx:69 + class SvStream & HTMLOutFuncs::Out_Hex(class SvStream &,unsigned long,unsigned char) + unsigned char nLen + 2 +include/svtools/unitconv.hxx:42 + long ControlToItem(long,enum FieldUnit,enum MapUnit) + enum FieldUnit eCtrl + 5 +include/svx/AccessibleShape.hxx:208 + _Bool accessibility::AccessibleShape::GetState(short) + short aState + 11 +include/svx/chrtitem.hxx:83 + void SvxChartRegressItem::SvxChartRegressItem(enum SvxChartRegress,unsigned short) + unsigned short nId + 90 +include/svx/chrtitem.hxx:94 + void SvxChartTextOrderItem::SvxChartTextOrderItem(enum SvxChartTextOrder,unsigned short) + unsigned short nId + 68 +include/svx/chrtitem.hxx:108 + void SvxChartKindErrorItem::SvxChartKindErrorItem(enum SvxChartKindError,unsigned short) + unsigned short nId + 20 +include/svx/chrtitem.hxx:119 + void SvxChartIndicateItem::SvxChartIndicateItem(enum SvxChartIndicate,unsigned short) + unsigned short nId + 25 +include/svx/dbaexchange.hxx:57 + void svx::OColumnTransferable::OColumnTransferable(enum ColumnTransferFormatFlags) + enum ColumnTransferFormatFlags nFormats + 7 +include/svx/dbaexchange.hxx:97 + void svx::OColumnTransferable::OColumnTransferable(const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,enum ColumnTransferFormatFlags) + enum ColumnTransferFormatFlags _nFormats + 5 +include/svx/dlgctrl.hxx:106 + void SvxRectCtl::SetControlSettings(enum RectPoint,unsigned short) + enum RectPoint eRpt + 4 +include/svx/dlgctrl.hxx:106 + void SvxRectCtl::SetControlSettings(enum RectPoint,unsigned short) + unsigned short nBorder + 240 +include/svx/drawitem.hxx:59 + void SvxGradientListItem::SvxGradientListItem(const class rtl::Reference &,unsigned short) + unsigned short nWhich + 10180 +include/svx/drawitem.hxx:83 + void SvxHatchListItem::SvxHatchListItem(const class rtl::Reference &,unsigned short) + unsigned short nWhich + 10181 +include/svx/drawitem.hxx:108 + void SvxBitmapListItem::SvxBitmapListItem(const class rtl::Reference &,unsigned short) + unsigned short nWhich + 10182 +include/svx/drawitem.hxx:133 + void SvxPatternListItem::SvxPatternListItem(const class rtl::Reference &,unsigned short) + unsigned short nWhich + 10183 +include/svx/drawitem.hxx:157 + void SvxDashListItem::SvxDashListItem(const class rtl::Reference &,unsigned short) + unsigned short nWhich + 10184 +include/svx/drawitem.hxx:182 + void SvxLineEndListItem::SvxLineEndListItem(const class rtl::Reference &,unsigned short) + unsigned short nWhich + 10185 +include/svx/float3d.hxx:266 + void Svx3DCtrlItem::Svx3DCtrlItem(unsigned short,class SfxBindings *) + unsigned short + 10645 +include/svx/fmgridcl.hxx:43 + void FmGridHeader::FmGridHeader(class BrowseBox *,long) + long nWinBits + 1051648 +include/svx/fmview.hxx:88 + void FmFormView::createControlLabelPair(const class OutputDevice *,int,int,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,enum SdrObjKind,enum SdrInventor,enum SdrObjKind,class SdrModel &,class std::unique_ptr &,class std::unique_ptr &) + enum SdrInventor _nInventor + 827609170 +include/svx/fmview.hxx:88 + void FmFormView::createControlLabelPair(const class OutputDevice *,int,int,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,enum SdrObjKind,enum SdrInventor,enum SdrObjKind,class SdrModel &,class std::unique_ptr &,class std::unique_ptr &) + enum SdrObjKind _nLabelObjectID + 501 +include/svx/fontworkgallery.hxx:60 + void svx::FontWorkGalleryDialog::initFavorites(unsigned short) + unsigned short nThemeId + 37 +include/svx/fontworkgallery.hxx:62 + void svx::FontWorkGalleryDialog::fillFavorites(unsigned short) + unsigned short nThemeId + 37 +include/svx/framelink.hxx:117 + void svx::frame::Style::Style(double,double,double,enum SvxBorderLineStyle,double) + double nP + 3 +include/svx/gallery.hxx:110 + _Bool GalleryExplorer::FillObjListTitle(const unsigned int,class std::__debug::vector > &) + const unsigned int nThemeId + 16 +include/svx/gallery.hxx:117 + _Bool GalleryExplorer::GetGraphicObj(unsigned int,unsigned int,class Graphic *) + unsigned int nThemeId + 3 +include/svx/galmisc.hxx:188 + void GalleryHint::GalleryHint(enum GalleryHintType,const class rtl::OUString &,const class rtl::OUString &) + enum GalleryHintType nType + 2 +include/svx/grfcrop.hxx:33 + void SvxGrfCrop::SvxGrfCrop(unsigned short) + unsigned short + 134 +include/svx/langbox.hxx:72 + void SvxLanguageBox::InsertLanguage(const struct o3tl::strong_int,short) + short nType + 4 +include/svx/numinf.hxx:33 + void SvxNumberInfoItem::SvxNumberInfoItem(const unsigned short) + const unsigned short nId + 10086 +include/svx/numinf.hxx:38 + void SvxNumberInfoItem::SvxNumberInfoItem(class SvNumberFormatter *,const double &,const unsigned short) + const unsigned short nId + 10086 +include/svx/numinf.hxx:41 + void SvxNumberInfoItem::SvxNumberInfoItem(class SvNumberFormatter *,const double &,const class rtl::OUString &,const unsigned short) + const unsigned short nId + 10086 +include/svx/ofaitem.hxx:32 + void OfaPtrItem::OfaPtrItem(unsigned short,void *) + unsigned short nWhich + 11021 +include/svx/ofaitem.hxx:46 + void OfaRefItem::OfaRefItem(unsigned short,const Reference &) + unsigned short _nWhich + 10441 +include/svx/optgrid.hxx:77 + void SvxGridItem::SvxGridItem(unsigned short) + unsigned short _nWhich + 10298 +include/svx/relfld.hxx:43 + void SvxRelativeField::EnableRelativeMode(unsigned short,unsigned short) + unsigned short nMax + 999 +include/svx/ruler.hxx:244 + _Bool SvxRuler::IsActLastColumn(_Bool,unsigned short) const + unsigned short nAct + 65535 +include/svx/ruler.hxx:247 + _Bool SvxRuler::IsActFirstColumn(_Bool,unsigned short) const + unsigned short nAct + 65535 +include/svx/sdtaitm.hxx:38 + void SdrTextVertAdjustItem::SdrTextVertAdjustItem(enum SdrTextVertAdjust,unsigned short) + unsigned short nWhich + 130 +include/svx/svdetc.hxx:104 + class std::unique_ptr > RemoveWhichRange(const unsigned short *,unsigned short,unsigned short) + unsigned short nRangeBeg + 4006 +include/svx/svdetc.hxx:104 + class std::unique_ptr > RemoveWhichRange(const unsigned short *,unsigned short,unsigned short) + unsigned short nRangeEnd + 4061 +include/svx/svdhdl.hxx:349 + void SdrHdlLine::SdrHdlLine(class SdrHdl &,class SdrHdl &,enum SdrHdlKind) + enum SdrHdlKind eNewKind + 14 +include/svx/svdhdl.hxx:362 + void SdrHdlBezWgt::SdrHdlBezWgt(const class SdrHdl *,enum SdrHdlKind) + enum SdrHdlKind eNewKind + 10 +include/svx/svdhdl.hxx:393 + void ImpEdgeHdl::ImpEdgeHdl(const class Point &,enum SdrHdlKind) + enum SdrHdlKind eNewKind + 9 +include/svx/svdhdl.hxx:409 + void ImpMeasureHdl::ImpMeasureHdl(const class Point &,enum SdrHdlKind) + enum SdrHdlKind eNewKind + 20 +include/svx/svdmodel.hxx:119 + void SdrHint::SdrHint(enum SdrHintKind,const class SdrPage *) + enum SdrHintKind eNewHint + 2 +include/svx/svdmrkv.hxx:292 + _Bool SdrMarkView::PickMarkedObj(const class Point &,class SdrObject *&,class SdrPageView *&,enum SdrSearchOptions) const + enum SdrSearchOptions nOptions + 128 +include/svx/svdpage.hxx:114 + void SdrObjList::InsertObjectThenMakeNameUnique(class SdrObject *,class std::__debug::unordered_set, struct std::equal_to, class std::allocator > &,unsigned long) + unsigned long nPos + 18446744073709551615 +include/svx/txencbox.hxx:151 + int SvxTextEncodingTreeView::get_height_rows(int) const + int nRows + 6 +include/svx/txencbox.hxx:155 + void SvxTextEncodingTreeView::set_size_request(int,int) + int nWidth + -1 +include/svx/unoapi.hxx:44 + class rtl::Reference CreateSvxShapeByTypeAndInventor(unsigned short,enum SdrInventor,const class rtl::OUString &) + enum SdrInventor nInventor + 1917081171 +include/svx/xflclit.hxx:37 + void XFillColorItem::XFillColorItem(int,const class Color &) + int nIndex + -1 +include/svx/xflgrit.hxx:39 + void XFillGradientItem::XFillGradientItem(int,const class XGradient &) + int nIndex + -1 +include/svx/xlnclit.hxx:33 + void XLineColorItem::XLineColorItem(int,const class Color &) + int nIndex + -1 +include/svx/xpoly.hxx:74 + void XPolygon::Insert(unsigned short,const class XPolygon &) + unsigned short nPos + 65535 +include/test/helper/form.hxx:40 + class com::sun::star::uno::Reference createCommandButton(const class com::sun::star::uno::Reference &,const int,const int,const int,const int) + const int nX + 15000 +include/test/helper/form.hxx:40 + class com::sun::star::uno::Reference createCommandButton(const class com::sun::star::uno::Reference &,const int,const int,const int,const int) + const int nY + 10000 +include/test/helper/form.hxx:40 + class com::sun::star::uno::Reference createCommandButton(const class com::sun::star::uno::Reference &,const int,const int,const int,const int) + const int nHeight + 3000 +include/test/helper/form.hxx:40 + class com::sun::star::uno::Reference createCommandButton(const class com::sun::star::uno::Reference &,const int,const int,const int,const int) + const int nWidth + 4500 +include/test/helper/shape.hxx:55 + class com::sun::star::uno::Reference createLine(const class com::sun::star::uno::Reference &,const int,const int,const int,const int) + const int nX + 7500 +include/test/helper/shape.hxx:55 + class com::sun::star::uno::Reference createLine(const class com::sun::star::uno::Reference &,const int,const int,const int,const int) + const int nY + 10000 +include/test/helper/shape.hxx:55 + class com::sun::star::uno::Reference createLine(const class com::sun::star::uno::Reference &,const int,const int,const int,const int) + const int nWidth + 5000 +include/test/helper/shape.hxx:55 + class com::sun::star::uno::Reference createLine(const class com::sun::star::uno::Reference &,const int,const int,const int,const int) + const int nHeight + 3500 +include/test/helper/shape.hxx:69 + class com::sun::star::uno::Reference createRectangle(const class com::sun::star::uno::Reference &,const int,const int,const int,const int) + const int nY + 5000 +include/test/helper/shape.hxx:69 + class com::sun::star::uno::Reference createRectangle(const class com::sun::star::uno::Reference &,const int,const int,const int,const int) + const int nWidth + 5000 +include/test/unoapi_property_testers.hxx:85 + void testLongOptionalProperty(const class com::sun::star::uno::Reference &,const class rtl::OUString &,const int &) + const int & nValue + 42 +include/test/unoapi_property_testers.hxx:166 + void testColorProperty(const class com::sun::star::uno::Reference &,const class rtl::OUString &,const int &) + const int & rValue + 305419896 +include/toolkit/controls/unocontrolbase.hxx:47 + int UnoControlBase::ImplGetPropertyValue_INT32(unsigned short) + unsigned short nProp + 74 +include/tools/b3dtrans.hxx:113 + void B3dTransformationSet::SetDeviceRectangle(double,double,double,double) + double fL + -2 +include/tools/b3dtrans.hxx:113 + void B3dTransformationSet::SetDeviceRectangle(double,double,double,double) + double fR + 2 +include/tools/b3dtrans.hxx:113 + void B3dTransformationSet::SetDeviceRectangle(double,double,double,double) + double fB + -2 +include/tools/b3dtrans.hxx:113 + void B3dTransformationSet::SetDeviceRectangle(double,double,double,double) + double fT + 2 +include/tools/datetime.hxx:87 + class DateTime operator+(const class DateTime &,int) + int nDays + 10 +include/tools/fract.hxx:70 + class Fraction & Fraction::operator*=(double) + ###1 + -1 +include/tools/fract.hxx:103 + class Fraction operator+(double,const class Fraction &) + double v1 + 21600 +include/tools/fract.hxx:104 + class Fraction operator-(double,const class Fraction &) + double v1 + 21600 +include/tools/gen.hxx:92 + class Point & Point::operator*=(const long) + ###1 + -1 +include/tools/gen.hxx:93 + class Point & Point::operator/=(const long) + ###1 + 2 +include/tools/gen.hxx:97 + class Point operator*(const class Point &,const long) + const long nVal2 + -1 +include/tools/gen.hxx:203 + void Size::extendBy(long,long) + long x + 10 +include/tools/gen.hxx:203 + void Size::extendBy(long,long) + long y + 10 +include/tools/poly.hxx:96 + void tools::Polygon::Polygon(const class Point &,const class Point &,const class Point &,const class Point &,unsigned short) + unsigned short nPoints + 25 +include/tools/urlobj.hxx:271 + class rtl::OUString INetURLObject::GetURLNoMark(enum INetURLObject::DecodeMechanism,unsigned short) const + unsigned short eCharset + 76 +include/tools/urlobj.hxx:276 + class rtl::OUString INetURLObject::getAbbreviated(const class com::sun::star::uno::Reference &,int,enum INetURLObject::DecodeMechanism,unsigned short) const + enum INetURLObject::DecodeMechanism eMechanism + 3 +include/tools/urlobj.hxx:276 + class rtl::OUString INetURLObject::getAbbreviated(const class com::sun::star::uno::Reference &,int,enum INetURLObject::DecodeMechanism,unsigned short) const + unsigned short eCharset + 76 +include/tools/urlobj.hxx:294 + _Bool INetURLObject::SetURL(const class rtl::OUString &,enum INetURLObject::EncodeMechanism,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:344 + class rtl::OUString INetURLObject::GetAbsURL(const class rtl::OUString &,const class rtl::OUString &,enum INetURLObject::EncodeMechanism,enum INetURLObject::DecodeMechanism,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:351 + class rtl::OUString INetURLObject::GetRelURL(const class rtl::OUString &,const class rtl::OUString &,enum INetURLObject::EncodeMechanism,enum INetURLObject::DecodeMechanism,unsigned short,enum FSysStyle) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:351 + class rtl::OUString INetURLObject::GetRelURL(const class rtl::OUString &,const class rtl::OUString &,enum INetURLObject::EncodeMechanism,enum INetURLObject::DecodeMechanism,unsigned short,enum FSysStyle) + enum FSysStyle eStyle + 7 +include/tools/urlobj.hxx:362 + _Bool INetURLObject::translateToExternal(const class rtl::OUString &,class rtl::OUString &,enum INetURLObject::DecodeMechanism,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:369 + _Bool INetURLObject::translateToInternal(const class rtl::OUString &,class rtl::OUString &,enum INetURLObject::DecodeMechanism,unsigned short) + enum INetURLObject::DecodeMechanism eDecodeMechanism + 3 +include/tools/urlobj.hxx:369 + _Bool INetURLObject::translateToInternal(const class rtl::OUString &,class rtl::OUString &,enum INetURLObject::DecodeMechanism,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:416 + class rtl::OUString INetURLObject::GetUser(enum INetURLObject::DecodeMechanism,unsigned short) const + unsigned short eCharset + 76 +include/tools/urlobj.hxx:421 + class rtl::OUString INetURLObject::GetPass(enum INetURLObject::DecodeMechanism,unsigned short) const + unsigned short eCharset + 76 +include/tools/urlobj.hxx:438 + class rtl::OUString INetURLObject::GetHost(enum INetURLObject::DecodeMechanism,unsigned short) const + unsigned short eCharset + 76 +include/tools/urlobj.hxx:443 + class rtl::OUString INetURLObject::GetHostPort(enum INetURLObject::DecodeMechanism,unsigned short) const + enum INetURLObject::DecodeMechanism eMechanism + 2 +include/tools/urlobj.hxx:443 + class rtl::OUString INetURLObject::GetHostPort(enum INetURLObject::DecodeMechanism,unsigned short) const + unsigned short eCharset + 76 +include/tools/urlobj.hxx:462 + _Bool INetURLObject::SetURLPath(const class rtl::OUString &,enum INetURLObject::EncodeMechanism,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:516 + _Bool INetURLObject::removeSegment(int,_Bool) + int nIndex + -1 +include/tools/urlobj.hxx:586 + _Bool INetURLObject::setName(const class rtl::OUString &,enum INetURLObject::EncodeMechanism,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:606 + class rtl::OUString INetURLObject::getBase(int,_Bool,enum INetURLObject::DecodeMechanism,unsigned short) const + int nIndex + -1 +include/tools/urlobj.hxx:606 + class rtl::OUString INetURLObject::getBase(int,_Bool,enum INetURLObject::DecodeMechanism,unsigned short) const + unsigned short eCharset + 76 +include/tools/urlobj.hxx:630 + _Bool INetURLObject::setBase(const class rtl::OUString &,int,enum INetURLObject::EncodeMechanism,unsigned short) + int nIndex + -1 +include/tools/urlobj.hxx:630 + _Bool INetURLObject::setBase(const class rtl::OUString &,int,enum INetURLObject::EncodeMechanism,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:659 + class rtl::OUString INetURLObject::getExtension(int,_Bool,enum INetURLObject::DecodeMechanism,unsigned short) const + int nIndex + -1 +include/tools/urlobj.hxx:659 + class rtl::OUString INetURLObject::getExtension(int,_Bool,enum INetURLObject::DecodeMechanism,unsigned short) const + unsigned short eCharset + 76 +include/tools/urlobj.hxx:683 + _Bool INetURLObject::setExtension(const class rtl::OUString &,int,_Bool,unsigned short) + int nIndex + -1 +include/tools/urlobj.hxx:683 + _Bool INetURLObject::setExtension(const class rtl::OUString &,int,_Bool,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:702 + _Bool INetURLObject::removeExtension(int,_Bool) + int nIndex + -1 +include/tools/urlobj.hxx:735 + class rtl::OUString INetURLObject::GetParam(unsigned short) const + unsigned short eCharset + 76 +include/tools/urlobj.hxx:739 + _Bool INetURLObject::SetParam(const class rtl::OUString &,enum INetURLObject::EncodeMechanism,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:747 + class rtl::OUString INetURLObject::GetMark(enum INetURLObject::DecodeMechanism,unsigned short) const + unsigned short eCharset + 76 +include/tools/urlobj.hxx:752 + _Bool INetURLObject::SetMark(const class rtl::OUString &,enum INetURLObject::EncodeMechanism,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:897 + _Bool INetURLObject::Append(const class rtl::OUString &,enum INetURLObject::EncodeMechanism,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:1031 + _Bool INetURLObject::setUser(const class rtl::OUString &,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:1037 + _Bool INetURLObject::setPassword(const class rtl::OUString &,unsigned short) + unsigned short eCharset + 76 +include/tools/urlobj.hxx:1052 + _Bool INetURLObject::setHost(const class rtl::OUString &,unsigned short) + unsigned short eCharset + 76 +include/ucbhelper/simpleinteractionrequest.hxx:79 + void ucbhelper::SimpleInteractionRequest::SimpleInteractionRequest(const class com::sun::star::uno::Any &,const enum ContinuationFlags) + const enum ContinuationFlags nContinuations + 12 +include/unotools/compatibility.hxx:210 + void SvtCompatibilityOptions::SetDefault(enum SvtCompatibilityEntry::Index,_Bool) + enum SvtCompatibilityEntry::Index rIdx + 12 +include/unotools/confignode.hxx:254 + class utl::OConfigurationTreeRoot utl::OConfigurationTreeRoot::tryCreateWithComponentContext(const class com::sun::star::uno::Reference &,const class rtl::OUString &,int,enum utl::OConfigurationTreeRoot::CREATION_MODE) + int _nDepth + -1 +include/unotools/configvaluecontainer.hxx:83 + void utl::OConfigurationValueContainer::OConfigurationValueContainer(const class com::sun::star::uno::Reference &,class osl::Mutex &,const char *,const int) + const int _nLevels + 2 +include/unotools/fontdefs.hxx:43 + class rtl::OUString GetSubsFontName(const class rtl::OUString &,enum SubsFontFlags) + enum SubsFontFlags nFlags + 3 +include/unotools/useroptions.hxx:90 + void SvtUserOptions::SetBoolValue(enum UserOptToken,_Bool) + enum UserOptToken nToken + 19 +include/vcl/accessiblefactory.hxx:113 + class com::sun::star::uno::Reference vcl::IAccessibleFactory::createAccessibleBrowseBoxHeaderBar(const class com::sun::star::uno::Reference &,class vcl::IAccessibleTableProvider &,enum AccessibleBrowseBoxObjType) const + enum AccessibleBrowseBoxObjType _eObjType + 3 +include/vcl/bitmap.hxx:539 + _Bool Bitmap::ImplConvertDown(enum vcl::PixelFormat,const class Color *) + enum vcl::PixelFormat ePixelFormat + 8 +include/vcl/BitmapAlphaClampFilter.hxx:21 + void BitmapAlphaClampFilter::BitmapAlphaClampFilter(unsigned char) + unsigned char cThreshold + 253 +include/vcl/BitmapBasicMorphologyFilter.hxx:50 + void BitmapErodeFilter::BitmapErodeFilter(int,unsigned char) + unsigned char nValueOutside + 255 +include/vcl/bitmapex.hxx:52 + void BitmapEx::BitmapEx(class Size,enum vcl::PixelFormat) + enum vcl::PixelFormat ePixelFormat + 24 +include/vcl/bitmapex.hxx:452 + void BitmapEx::CombineMaskOr(class Color,unsigned char) + unsigned char nTol + 9 +include/vcl/errinf.hxx:187 + void TwoStringErrorInfo::TwoStringErrorInfo(class ErrCode,const class rtl::OUString &,const class rtl::OUString &,enum DialogMask) + enum DialogMask nMask + 4097 +include/vcl/fieldvalues.hxx:60 + double ConvertDoubleValue(long,unsigned short,enum FieldUnit,enum MapUnit) + enum MapUnit eOutUnit + 9 +include/vcl/fieldvalues.hxx:66 + double ConvertDoubleValue(long,unsigned short,enum MapUnit,enum FieldUnit) + enum MapUnit eInUnit + 9 +include/vcl/filter/PDFiumLibrary.hxx:216 + _Bool vcl::pdf::PDFiumDocument::saveWithVersion(class SvMemoryStream &,int) + int nFileVersion + 16 +include/vcl/font.hxx:94 + void vcl::Font::IncreaseQualityBy(int) + int + 50 +include/vcl/font.hxx:95 + void vcl::Font::DecreaseQualityBy(int) + int + 100 +include/vcl/font/Feature.hxx:75 + void vcl::font::FeatureDefinition::FeatureDefinition(unsigned int,const char *,class std::__debug::vector >) + unsigned int nCode + 1718772067 +include/vcl/imap.hxx:117 + unsigned long ImageMap::Read(class SvStream &,enum IMapFormat) + enum IMapFormat nFormat + 15 +include/vcl/outdev.hxx:1193 + int OutputDevice::GetTextBreak(const class rtl::OUString &,long,char16_t,int &,int,int,long,const class vcl::TextLayoutCache *) const + char16_t nExtraChar + 45 +include/vcl/print.hxx:667 + class com::sun::star::uno::Any vcl::PrinterOptionsHelper::setRangeControlOpt(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,const struct vcl::PrinterOptionsHelper::UIControlOptions &) + int i_nMinValue + 10 +include/vcl/print.hxx:667 + class com::sun::star::uno::Any vcl::PrinterOptionsHelper::setRangeControlOpt(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,const struct vcl::PrinterOptionsHelper::UIControlOptions &) + int i_nMaxValue + 1000 +include/vcl/svapp.hxx:752 + struct ImplSVEvent * Application::PostGestureEvent(enum VclEventId,class vcl::Window *,const class GestureEvent *) + enum VclEventId nEvent + 130 +include/vcl/texteng.hxx:132 + class TextPaM TextEngine::ImpInsertText(const class TextSelection &,char16_t,_Bool) + char16_t c + 9 +include/vcl/toolbox.hxx:328 + void ToolBox::InsertBreak(unsigned long) + unsigned long nPos + 18446744073709551615 +include/vcl/toolkit/lstbox.hxx:117 + void ListBox::ListBox(enum WindowType) + enum WindowType nType + 331 +include/vcl/toolkit/svtabbx.hxx:85 + class rtl::OUString SvTabListBox::GetEntryText(unsigned long,unsigned short) const + unsigned short nCol + 65535 +include/vcl/toolkit/svtabbx.hxx:90 + void SvTabListBox::SetTabJustify(unsigned short,enum SvTabJustify) + enum SvTabJustify + 8 +include/vcl/toolkit/treelistbox.hxx:498 + class SvLBoxTab * SvTreeListBox::GetFirstTab(enum SvLBoxTabFlags,unsigned short &) + enum SvLBoxTabFlags nFlagMask + 16 +include/vcl/toolkit/treelistbox.hxx:499 + void SvTreeListBox::GetLastTab(enum SvLBoxTabFlags,unsigned short &) + enum SvLBoxTabFlags nFlagMask + 16 +include/vcl/toolkit/treelistbox.hxx:658 + void SvTreeListBox::SetHighlightRange(unsigned short,unsigned short) + unsigned short nLastTab + 65535 +include/vcl/transfer.hxx:228 + void TransferableHelper::RemoveFormat(enum SotClipboardFormatId) + enum SotClipboardFormatId nFormat + 59 +include/vcl/transfer.hxx:326 + _Bool TransferableDataHelper::GetBitmapEx(enum SotClipboardFormatId,class BitmapEx &) + enum SotClipboardFormatId nFormat + 2 +include/vcl/transfer.hxx:337 + _Bool TransferableDataHelper::GetGDIMetaFile(enum SotClipboardFormatId,class GDIMetaFile &,unsigned long) + enum SotClipboardFormatId nFormat + 3 +include/vcl/transfer.hxx:343 + _Bool TransferableDataHelper::GetImageMap(enum SotClipboardFormatId,class ImageMap &) + enum SotClipboardFormatId nFormat + 13 +include/vcl/transfer.hxx:358 + class com::sun::star::uno::Sequence TransferableDataHelper::GetSequence(enum SotClipboardFormatId,const class rtl::OUString &) + enum SotClipboardFormatId nFormat + 59 +include/vcl/TypeSerializer.hxx:29 + unsigned int createMagic(char,char,char,char) + char char4 + 48 +include/vcl/uitest/logger.hxx:51 + void UITestLogger::logAction(class vcl::Window *const &,enum VclEventId) + enum VclEventId nEvent + 85 +include/vcl/weld.hxx:958 + void weld::TreeView::insert_separator(int,const class rtl::OUString &) + int pos + -1 +include/vcl/weld.hxx:998 + void weld::TreeView::set_sensitive(int,_Bool,int) + int col + -1 +include/vcl/window.hxx:1507 + void vcl::Window::SimulateKeyPress(unsigned short) const + unsigned short nKeyCode + 1312 +include/vcl/wrkwin.hxx:61 + void WorkWindow::WorkWindow(enum WindowType) + enum WindowType nType + 369 +include/vcl/wrkwin.hxx:67 + void WorkWindow::WorkWindow(class vcl::Window *,const class com::sun::star::uno::Any &,long) + long nStyle + 1312 +include/xmloff/txtparae.hxx:349 + void XMLTextParagraphExport::exportListAndSectionChange(class com::sun::star::uno::Reference &,class MultiPropertySetHelper &,short,const class com::sun::star::uno::Reference &,const class XMLTextNumRuleInfo &,const class XMLTextNumRuleInfo &,_Bool) + short nTextSectionId + 5 +include/xmloff/txtparae.hxx:381 + void XMLTextParagraphExport::Add(enum XmlStyleFamily,class MultiPropertySetHelper &,const class com::sun::star::uno::Reference &) + enum XmlStyleFamily nFamily + 100 +include/xmloff/xmlaustp.hxx:94 + void SvXMLAutoStylePoolP::SetFamilyPropSetMapper(enum XmlStyleFamily,const class rtl::Reference &) + enum XmlStyleFamily nFamily + 203 +include/xmloff/xmlaustp.hxx:101 + void SvXMLAutoStylePoolP::RegisterDefinedName(enum XmlStyleFamily,const class rtl::OUString &) + enum XmlStyleFamily nFamily + 204 +include/xmloff/xmlerror.hxx:135 + void XMLErrors::ThrowErrorAsSAXException(int) + int nIdMask + 1073741824 +include/xmloff/xmlexp.hxx:272 + void SvXMLExport::SvXMLExport(const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class rtl::OUString &,const short,const class com::sun::star::uno::Reference &) + const short eDefaultMeasureUnit + 3 +include/xmloff/xmlexp.hxx:337 + void SvXMLExport::AddAttributeASCII(unsigned short,const char *,const char *) + unsigned short nPrefix + 34 +include/xmloff/xmlexp.hxx:512 + void SvXMLExport::SetError(int,const class com::sun::star::uno::Sequence &) + int nId + 1074266113 +include/xmloff/xmlexppr.hxx:135 + void SvXMLExportPropertyMapper::exportXML(class SvXMLExport &,const class std::__debug::vector > &,enum SvXmlExportFlags,_Bool) const + enum SvXmlExportFlags nFlags + 8 +include/xmloff/xmlnumfi.hxx:205 + _Bool SvXMLNumFormatContext::ReplaceNfKeyword(unsigned short,unsigned short) + unsigned short nOld + 24 +include/xmloff/xmlnumfi.hxx:205 + _Bool SvXMLNumFormatContext::ReplaceNfKeyword(unsigned short,unsigned short) + unsigned short nNew + 25 +include/xmloff/XMLSettingsExportContext.hxx:37 + void xmloff::XMLSettingsExportContext::AddAttribute(enum xmloff::token::XMLTokenEnum,const class rtl::OUString &) + enum xmloff::token::XMLTokenEnum i_eName + 1250 +include/xmloff/XMLSettingsExportContext.hxx:39 + void xmloff::XMLSettingsExportContext::AddAttribute(enum xmloff::token::XMLTokenEnum,enum xmloff::token::XMLTokenEnum) + enum xmloff::token::XMLTokenEnum i_eName + 1907 +libreofficekit/qa/tilebench/tilebench.cxx:72 + void dumpTile(const char *,const int,const int,const int,const unsigned char *,const int,const int,int) + int nTotalWidth + -1 +libreofficekit/qa/tilebench/tilebench.cxx:345 + int testJoinsAt(class lok::Document *,long,long,const long,const long) + const long nTilePixelSize + 256 +lotuswordpro/inc/xfilter/xfdrawstyle.hxx:95 + void XFDrawStyle::SetLineDashStyle(enum enumXFLineStyle,double,double,double) + enum enumXFLineStyle style + 3 +lotuswordpro/inc/xfilter/xfdrawstyle.hxx:118 + void XFDrawStyle::SetFontWorkStyle(enum enumXFFWStyle,enum enumXFFWAdjust) + enum enumXFFWStyle eStyle + 4 +lotuswordpro/inc/xfilter/xffont.hxx:203 + void XFFont::SetPosition(_Bool,short,short) + short pos + 33 +lotuswordpro/inc/xfilter/xffont.hxx:203 + void XFFont::SetPosition(_Bool,short,short) + short scale + 58 +lotuswordpro/inc/xfilter/xfindex.hxx:100 + void XFIndexTemplate::AddTabEntry(enum enumXFTab,double,char16_t,char16_t,const class rtl::OUString &) + enum enumXFTab type + 3 +lotuswordpro/inc/xfilter/xfindex.hxx:100 + void XFIndexTemplate::AddTabEntry(enum enumXFTab,double,char16_t,char16_t,const class rtl::OUString &) + char16_t delimiter + 100 +lotuswordpro/source/filter/bento.hxx:215 + void OpenStormBento::LtcBenContainer::SeekFromEnd(long) + long Offset + -24 +lotuswordpro/source/filter/tocread.hxx:87 + enum OpenStormBento::BenError OpenStormBento::CBenTOCReader::GetData(void *,unsigned long) + unsigned long Amt + 4 +o3tl/qa/cow_wrapper_clients.hxx:69 + void o3tltests::cow_wrapper_client2::cow_wrapper_client2(int) + int nVal + 4 +o3tl/qa/cow_wrapper_clients.hxx:100 + void o3tltests::cow_wrapper_client3::cow_wrapper_client3(int) + int nVal + 7 +o3tl/qa/cow_wrapper_clients.hxx:132 + void o3tltests::cow_wrapper_client4::cow_wrapper_client4(int) + int + 4 +oox/source/core/xmlfilterbase.cxx:595 + void writeElement(const class std::shared_ptr &,int,const class com::sun::star::uno::Sequence &) + int nXmlElement + 93653875 +oox/source/core/xmlfilterbase.cxx:612 + void writeElement(const class std::shared_ptr &,int,const class LanguageTag &) + int nXmlElement + 110103439 +oox/source/export/vmlexport.cxx:333 + void impl_AddInt(class sax_fastparser::FastAttributeList *,int,unsigned int) + int nElement + 5723 +package/inc/ThreadedDeflater.hxx:55 + void ZipUtils::ThreadedDeflater::ThreadedDeflater(int) + int nSetLevel + -1 +reportdesign/source/filter/xml/xmlExport.hxx:124 + void rptxml::ORptExport::collectStyleNames(enum XmlStyleFamily,const class std::__debug::vector > &,class std::__debug::vector > &) + enum XmlStyleFamily _nFamily + 202 +reportdesign/source/filter/xml/xmlExport.hxx:125 + void rptxml::ORptExport::collectStyleNames(enum XmlStyleFamily,const class std::__debug::vector > &,const class std::__debug::vector > &,class std::__debug::vector > &) + enum XmlStyleFamily _nFamily + 203 +reportdesign/source/filter/xml/xmlStyleImport.hxx:59 + void rptxml::OControlStyleContext::AddProperty(short,const class com::sun::star::uno::Any &) + short nContextID + 28673 +reportdesign/source/ui/inc/UITools.hxx:142 + class SdrObject * isOver(const class tools::Rectangle &,const class SdrPage &,const class SdrView &,_Bool,class std::unique_ptr *,int) + int _nIgnoreListLength + 2 +sal/osl/unx/file_path_helper.cxx:173 + void (anonymous namespace)::path_list_iterator::path_list_iterator(const class rtl::OUString &,char16_t) + char16_t list_separator + 58 +sal/osl/unx/file_url.cxx:503 + _Bool _islastchr(char16_t *,char16_t) + char16_t Chr + 47 +sal/osl/unx/file_url.hxx:36 + int TextToUnicode(const char *,unsigned long,char16_t *,int) + int unic_text_buffer_size + 4096 +sal/osl/unx/nlsupport.cxx:106 + char * compose_locale(struct _rtl_Locale *,char *,unsigned long) + unsigned long n + 64 +sal/osl/unx/profile.cxx:137 + void osl_ProfileGenerateExtension(const char *,const char *,char *,int) + int BufferMaxLen + 4096 +sal/osl/unx/readwrite_helper.hxx:22 + _Bool safeRead(int,void *,unsigned long) + unsigned long count + 511 +sal/osl/unx/uunxapi.hxx:78 + int mkdir(const class rtl::OString &,unsigned int) + unsigned int aMode + 511 +sal/qa/osl/file/osl_File.cxx:106 + _Bool t_compareTime(struct TimeValue *,struct TimeValue *,int) + int nDelta + 2000 +sax/inc/xml2utf.hxx:96 + int sax_expatwrap::XMLFile2UTFConverter::readAndConvert(class com::sun::star::uno::Sequence &,int) + int nMaxToRead + 16384 +sax/source/tools/converter.cxx:56 + long toInt64_WithLength(const char16_t *,short,int) + short radix + 10 +sax/source/tools/converter.cxx:60 + long toInt64_WithLength(const char *,short,int) + short radix + 10 +sax/source/tools/converter.cxx:1175 + enum sax::(anonymous namespace)::Result readUnsignedNumberMaxDigits(int,type-parameter-?-?,unsigned long &,int &) + int maxDigits + 9 +sc/inc/address.hxx:333 + void ScAddress::Format(class rtl::OStringBuffer &,enum ScRefFlags,const class ScDocument *,const struct ScAddress::Details &) const + enum ScRefFlags nFlags + 32768 +sc/inc/autoform.hxx:81 + void ScAfVersions::Write(class SvStream &,unsigned short) + unsigned short fileVersion + 5050 +sc/inc/autoform.hxx:162 + void ScAutoFormatData::CopyItem(unsigned short,unsigned short,unsigned short) + unsigned short nWhich + 150 +sc/inc/autoform.hxx:172 + _Bool ScAutoFormatData::Save(class SvStream &,unsigned short) + unsigned short fileVersion + 5050 +sc/inc/cellsuno.hxx:491 + void ScCellRangeObj::SetArrayFormula_Impl(const class rtl::OUString &,const enum formula::FormulaGrammar::Grammar) + const enum formula::FormulaGrammar::Grammar eGrammar + 16908294 +sc/inc/chgtrack.hxx:219 + void ScChangeAction::ScChangeAction(enum ScChangeActionType,const class ScBigRange &,const unsigned long) + enum ScChangeActionType + 8 +sc/inc/colcontainer.hxx:33 + void ScColContainer::ScColContainer(const struct ScSheetLimits &,const unsigned long) + const unsigned long nSize + 64 +sc/inc/column.hxx:266 + void ScColumn::DeleteRanges(const class std::__debug::vector > &,enum InsertDeleteFlags) + enum InsertDeleteFlags nDelFlag + 2071 +sc/inc/column.hxx:527 + unsigned short ScColumn::GetOptimalColWidth(class OutputDevice *,double,double,const class Fraction &,const class Fraction &,_Bool,unsigned short,const class ScMarkData *,const struct ScColWidthParam *) const + unsigned short nOldWidth + 1167 +sc/inc/column.hxx:614 + void ScColumn::BroadcastRows(int,int,enum SfxHintId) + enum SfxHintId nHint + 52 +sc/inc/compressedarray.hxx:192 + void ScBitMaskCompressedArray::AndValue(type-parameter-?-?,const type-parameter-?-? &) + const type-parameter-?-? & rValueToAnd + 7 +sc/inc/compressedarray.hxx:198 + void ScBitMaskCompressedArray::CopyFromAnded(const ScBitMaskCompressedArray &,type-parameter-?-?,type-parameter-?-?,const type-parameter-?-? &) + const type-parameter-?-? & rValueToAnd + 8 +sc/inc/compressedarray.hxx:205 + type-parameter-?-? ScBitMaskCompressedArray::GetLastAnyBitAccess(const type-parameter-?-? &) const + const type-parameter-?-? & rBitMask + 15 +sc/inc/document.hxx:1334 + _Bool ScDocument::CompileErrorCells(enum FormulaError) + enum FormulaError nErrCode + 525 +sc/inc/document.hxx:1678 + void ScDocument::UndoToDocument(short,int,short,short,int,short,enum InsertDeleteFlags,_Bool,class ScDocument &) + enum InsertDeleteFlags nFlags + 2303 +sc/inc/document.hxx:1868 + void ScDocument::DeleteSelectionTab(short,enum InsertDeleteFlags,const class ScMarkData &) + enum InsertDeleteFlags nDelFlag + 2303 +sc/inc/document.hxx:1926 + void ScDocument::SetRowFlags(int,int,short,enum CRFlags) + enum CRFlags nNewFlags + 8 +sc/inc/document.hxx:2254 + void ScDocument::BroadcastCells(const class ScRange &,enum SfxHintId,_Bool) + enum SfxHintId nHint + 31 +sc/inc/dpsave.hxx:317 + class ScDPSaveDimension * ScDPSaveData::GetFirstDimension(enum com::sun::star::sheet::DataPilotFieldOrientation) + enum com::sun::star::sheet::DataPilotFieldOrientation eOrientation + 4 +sc/inc/externalrefmgr.hxx:796 + void ScExternalRefManager::purgeStaleSrcDocument(int) + int nTimeOut + 30000 +sc/inc/formulacell.hxx:376 + void ScFormulaCell::AddRecalcMode(enum ScRecalcMode) + enum ScRecalcMode + 4 +sc/inc/global.hxx:639 + void ScGlobal::AddQuotes(class rtl::OUString &,char16_t,_Bool) + char16_t cQuote + 34 +sc/inc/global.hxx:662 + const char16_t * ScGlobal::FindUnquoted(const char16_t *,char16_t) + char16_t cChar + 46 +sc/inc/nameuno.hxx:63 + void ScNamedRangeObj::Modify_Impl(const class rtl::OUString *,const class ScTokenArray *,const class rtl::OUString *,const class ScAddress *,const enum ScRangeData::Type *,const enum formula::FormulaGrammar::Grammar) + const enum formula::FormulaGrammar::Grammar eGrammar + 16908294 +sc/inc/optutil.hxx:43 + void ScLinkConfigItem::ScLinkConfigItem(const class rtl::OUString &,enum ConfigItemMode) + enum ConfigItemMode nMode + 2 +sc/inc/rangeutl.hxx:110 + int ScRangeStringConverter::GetTokenCount(const class rtl::OUString &,char16_t) + char16_t cSeparator + 32 +sc/inc/rangeutl.hxx:126 + _Bool ScRangeStringConverter::GetAddressFromString(class ScAddress &,const class rtl::OUString &,const class ScDocument &,enum formula::FormulaGrammar::AddressConvention,int &,char16_t,char16_t) + char16_t cSeparator + 32 +sc/inc/rangeutl.hxx:126 + _Bool ScRangeStringConverter::GetAddressFromString(class ScAddress &,const class rtl::OUString &,const class ScDocument &,enum formula::FormulaGrammar::AddressConvention,int &,char16_t,char16_t) + char16_t cQuote + 39 +sc/inc/rangeutl.hxx:142 + _Bool ScRangeStringConverter::GetRangeListFromString(class ScRangeList &,const class rtl::OUString &,const class ScDocument &,enum formula::FormulaGrammar::AddressConvention,char16_t,char16_t) + char16_t cQuote + 39 +sc/inc/rangeutl.hxx:150 + _Bool ScRangeStringConverter::GetAreaFromString(class ScArea &,const class rtl::OUString &,const class ScDocument &,enum formula::FormulaGrammar::AddressConvention,int &,char16_t) + char16_t cSeparator + 32 +sc/inc/rangeutl.hxx:159 + _Bool ScRangeStringConverter::GetRangeFromString(struct com::sun::star::table::CellRangeAddress &,const class rtl::OUString &,const class ScDocument &,enum formula::FormulaGrammar::AddressConvention,int &,char16_t) + char16_t cSeparator + 32 +sc/inc/rangeutl.hxx:184 + void ScRangeStringConverter::GetStringFromRangeList(class rtl::OUString &,const class ScRangeList *,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t) + char16_t cSeparator + 32 +sc/inc/rangeutl.hxx:191 + void ScRangeStringConverter::GetStringFromArea(class rtl::OUString &,const class ScArea &,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t,_Bool,enum ScRefFlags) + char16_t cSeparator + 32 +sc/inc/rangeutl.hxx:191 + void ScRangeStringConverter::GetStringFromArea(class rtl::OUString &,const class ScArea &,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t,_Bool,enum ScRefFlags) + enum ScRefFlags nFormatFlags + 32776 +sc/inc/rangeutl.hxx:201 + void ScRangeStringConverter::GetStringFromAddress(class rtl::OUString &,const struct com::sun::star::table::CellAddress &,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t,_Bool) + char16_t cSeparator + 32 +sc/inc/rangeutl.hxx:208 + void ScRangeStringConverter::GetStringFromRange(class rtl::OUString &,const struct com::sun::star::table::CellRangeAddress &,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t,_Bool,enum ScRefFlags) + enum ScRefFlags nFormatFlags + 32776 +sc/inc/rangeutl.hxx:216 + void ScRangeStringConverter::GetStringFromRangeList(class rtl::OUString &,const class com::sun::star::uno::Sequence &,const class ScDocument *,enum formula::FormulaGrammar::AddressConvention,char16_t) + char16_t cSeparator + 32 +sc/inc/scmod.hxx:241 + void ScModule::RegisterRefController(unsigned short,class std::shared_ptr &,class weld::Window *) + unsigned short nSlotId + 26161 +sc/inc/scmod.hxx:242 + void ScModule::UnregisterRefController(unsigned short,const class std::shared_ptr &) + unsigned short nSlotId + 26161 +sc/inc/scmod.hxx:243 + class std::shared_ptr ScModule::Find1RefWindow(unsigned short,const class weld::Window *) + unsigned short nSlotId + 26161 +sc/inc/simpleformulacalc.hxx:38 + void ScSimpleFormulaCalculator::ScSimpleFormulaCalculator(class ScDocument &,const class ScAddress &,const class rtl::OUString &,_Bool,enum formula::FormulaGrammar::Grammar) + enum formula::FormulaGrammar::Grammar eGram + 65539 +sc/inc/stlpool.hxx:53 + class ScStyleSheet * ScStyleSheetPool::FindCaseIns(const class rtl::OUString &,enum SfxStyleFamily) + enum SfxStyleFamily eFam + 2 +sc/inc/stringutil.hxx:150 + _Bool ScStringUtil::parseSimpleNumber(const char *,unsigned long,char,char,double &) + char dsep + 46 +sc/inc/stringutil.hxx:150 + _Bool ScStringUtil::parseSimpleNumber(const char *,unsigned long,char,char,double &) + char gsep + 44 +sc/inc/table.hxx:419 + void ScTable::SetFormula(short,int,const class ScTokenArray &,enum formula::FormulaGrammar::Grammar) + enum formula::FormulaGrammar::Grammar eGram + 65539 +sc/inc/table.hxx:682 + _Bool ScTable::HasAttribSelection(const class ScMarkData &,enum HasAttrFlags) const + enum HasAttrFlags nMask + 8 +sc/inc/tokenarray.hxx:261 + void ScTokenArray::WrapReference(const class ScAddress &,short,int) + short nMaxCol + 255 +sc/inc/tokenarray.hxx:261 + void ScTokenArray::WrapReference(const class ScAddress &,short,int) + int nMaxRow + 65535 +sc/inc/zforauto.hxx:38 + void ScNumFormatAbbrev::Save(class SvStream &,unsigned short) const + unsigned short eByteStrSet + 76 +sc/qa/extras/new_cond_format.cxx:375 + void testColorScaleEntries(const class com::sun::star::uno::Reference &,int,int,const class rtl::OUString &,class Color,int,const class rtl::OUString &,class Color,int,const class rtl::OUString &,class Color) + int nMediumType + 2 +sc/qa/extras/scpdfexport.cxx:54 + void ScPDFExportTest::setFont(class ScFieldEditEngine &,int,int,const class rtl::OUString &) + int nEnd + 4 +sc/qa/unit/filters-test.cxx:531 + void impl_testLegacyCellAnchoredRotatedShape(class ScDocument &,const class tools::Rectangle &,const class ScDrawObjData &,long) + long TOLERANCE + 30 +sc/qa/unit/parallelism.cxx:404 + void lcl_setupCommon(class ScDocument *,unsigned long,unsigned long) + unsigned long nNumRows + 1048 +sc/qa/unit/parallelism.cxx:404 + void lcl_setupCommon(class ScDocument *,unsigned long,unsigned long) + unsigned long nConstCellValue + 20 +sc/qa/unit/parallelism.cxx:534 + void lcl_setupMultipleFGColumn(class ScDocument *,unsigned long,unsigned long,unsigned long) + unsigned long nNumRowsInBlock + 200 +sc/qa/unit/parallelism.cxx:534 + void lcl_setupMultipleFGColumn(class ScDocument *,unsigned long,unsigned long,unsigned long) + unsigned long nNumFG + 50 +sc/qa/unit/parallelism.cxx:534 + void lcl_setupMultipleFGColumn(class ScDocument *,unsigned long,unsigned long,unsigned long) + unsigned long nOffset + 100 +sc/qa/unit/subsequent_export-test.cxx:212 + class std::unique_ptr ScExportTest::testTdf95640(class std::basic_string_view >,int,int) + int nDestFormat + 2 +sc/qa/unit/subsequent_export-test.cxx:1817 + _Bool ::isOverline(const struct editeng::Section &,enum FontLineStyle) + enum FontLineStyle eStyle + 2 +sc/qa/unit/subsequent_export-test.cxx:1824 + _Bool ::isUnderline(const struct editeng::Section &,enum FontLineStyle) + enum FontLineStyle eStyle + 2 +sc/qa/unit/ucalc.cxx:1198 + _Bool checkRelativeRefToken(class ScDocument &,const class ScAddress &,short,int) + short nRelCol + -1 +sc/qa/unit/ucalc.hxx:31 + void FormulaGrammarSwitch::FormulaGrammarSwitch(class ScDocument *,enum formula::FormulaGrammar::Grammar) + enum formula::FormulaGrammar::Grammar eGrammar + 17104900 +sc/qa/unit/ucalc.hxx:56 + void Test::pasteOneCellFromClip(class ScDocument *,const class ScRange &,class ScDocument *,enum InsertDeleteFlags) + enum InsertDeleteFlags eFlags + 2303 +sc/qa/unit/ucalc_formula.cxx:8496 + void (anonymous namespace)::ColumnTest::ColumnTest(class ScDocument *,int,int,int,int,int) + int nTotalRows + 330 +sc/qa/unit/ucalc_formula.cxx:8496 + void (anonymous namespace)::ColumnTest::ColumnTest(class ScDocument *,int,int,int,int,int) + int nStart1 + 9 +sc/qa/unit/ucalc_formula.cxx:8496 + void (anonymous namespace)::ColumnTest::ColumnTest(class ScDocument *,int,int,int,int,int) + int nEnd1 + 159 +sc/qa/unit/ucalc_formula.cxx:8496 + void (anonymous namespace)::ColumnTest::ColumnTest(class ScDocument *,int,int,int,int,int) + int nStart2 + 169 +sc/qa/unit/ucalc_formula.cxx:8496 + void (anonymous namespace)::ColumnTest::ColumnTest(class ScDocument *,int,int,int,int,int) + int nEnd2 + 319 +sc/source/core/data/documen8.cxx:512 + void (anonymous namespace)::IdleCalcTextWidthScope::incCol(short) + short nInc + -1 +sc/source/core/data/dpoutput.cxx:317 + void lcl_SetFrame(class ScDocument *,short,short,int,short,int,unsigned short) + unsigned short nWidth + 20 +sc/source/core/tool/compiler.cxx:1289 + void (anonymous namespace)::ConventionXL_A1::ConventionXL_A1(enum formula::FormulaGrammar::AddressConvention) + enum formula::FormulaGrammar::AddressConvention eConv + 4 +sc/source/core/tool/compiler.cxx:2051 + _Bool lcl_isUnicodeIgnoreAscii(const char16_t *,const char *,unsigned long) + unsigned long n + 4 +sc/source/core/tool/editutil.cxx:84 + class rtl::OUString lcl_GetDelimitedString(const class EditTextObject &,const char) + const char c + 10 +sc/source/core/tool/scmatrix.cxx:355 + unsigned long GetElementsMax(unsigned long) + unsigned long nMemory + 6442450944 +sc/source/filter/excel/xechart.cxx:134 + void lclSaveRecord(class XclExpStream &,const class rtl::Reference &,unsigned short,type-parameter-?-?) + unsigned short nRecId + 4129 +sc/source/filter/excel/xechart.cxx:144 + void lclSaveRecord(class XclExpStream &,type-parameter-?-? *,unsigned short,type-parameter-?-?) + unsigned short nRecId + 4124 +sc/source/filter/excel/xechart.cxx:561 + class rtl::Reference lclCreateLineFormat(const class XclExpChRoot &,const class ScfPropertySet &,enum XclChObjectType) + enum XclChObjectType eObjType + 9 +sc/source/filter/excel/xelink.cxx:297 + void (anonymous namespace)::XclExpSupbook::XclExpSupbook(const class XclExpRoot &,const class rtl::OUString &,enum XclSupbookType) + enum XclSupbookType + 5 +sc/source/filter/excel/xepage.cxx:376 + void (anonymous namespace)::XclExpXmlStartHeaderFooterElementRecord::XclExpXmlStartHeaderFooterElementRecord(const int,const _Bool) + const int nElement + 2614 +sc/source/filter/excel/xepivotxml.cxx:711 + void WriteGrabBagItemToStream(class XclExpXmlStream &,int,const class com::sun::star::uno::Any &) + int tokenId + 4010 +sc/source/filter/inc/addressconverter.hxx:489 + void oox::xls::AddressConverter::initializeMaxPos(short,int,int) + short nMaxXlsTab + 32767 +sc/source/filter/inc/addressconverter.hxx:489 + void oox::xls::AddressConverter::initializeMaxPos(short,int,int) + int nMaxXlsCol + 16383 +sc/source/filter/inc/addressconverter.hxx:489 + void oox::xls::AddressConverter::initializeMaxPos(short,int,int) + int nMaxXlsRow + 1048575 +sc/source/filter/inc/formulabase.hxx:276 + void oox::xls::ApiTokenVector::reserve(unsigned long) + unsigned long n + 8192 +sc/source/filter/inc/formulabase.hxx:772 + void oox::xls::FormulaProcessorBase::convertStringToStringList(class com::sun::star::uno::Sequence &,char16_t,_Bool) const + char16_t cStringSep + 44 +sc/source/filter/inc/ftools.hxx:48 + type-parameter-?-? llimit_cast(type-parameter-?-?,type-parameter-?-?) + type-parameter-?-? nMin + 8 +sc/source/filter/inc/pivottablebuffer.hxx:117 + void oox::xls::PivotTableField::PivotTableField(class oox::xls::PivotTable &,int) + int nFieldIndex + -2 +sc/source/filter/inc/tokstack.hxx:255 + _Bool TokenPool::IsSingleOp(const struct TokenId &,const enum OpCode) const + const enum OpCode eId + 13 +sc/source/filter/inc/unitconverter.hxx:70 + double oox::xls::UnitConverter::scaleValue(double,enum oox::xls::Unit,enum oox::xls::Unit) const + enum oox::xls::Unit eToUnit + 3 +sc/source/filter/inc/unitconverter.hxx:75 + double oox::xls::UnitConverter::scaleFromMm100(int,enum oox::xls::Unit) const + enum oox::xls::Unit eUnit + 6 +sc/source/filter/inc/xechart.hxx:196 + void XclExpChFutureRecordBase::XclExpChFutureRecordBase(const class XclExpChRoot &,enum XclFutureRecType,unsigned short,unsigned long) + unsigned short nRecId + 2155 +sc/source/filter/inc/xechart.hxx:196 + void XclExpChFutureRecordBase::XclExpChFutureRecordBase(const class XclExpChRoot &,enum XclFutureRecType,unsigned short,unsigned long) + unsigned long nRecSize + 4 +sc/source/filter/inc/xeescher.hxx:151 + void XclExpImgData::XclExpImgData(const class Graphic &,unsigned short) + unsigned short nRecId + 233 +sc/source/filter/inc/xeformula.hxx:63 + class std::shared_ptr XclExpFormulaCompiler::CreateFormula(enum XclFormulaType,const class ScAddress &) + enum XclFormulaType eType + 7 +sc/source/filter/inc/xeformula.hxx:69 + class std::shared_ptr XclExpFormulaCompiler::CreateFormula(enum XclFormulaType,const class ScRangeList &) + enum XclFormulaType eType + 5 +sc/source/filter/inc/xehelper.hxx:245 + class std::shared_ptr XclExpStringHelper::CreateString(const class XclExpRoot &,char16_t,enum XclStrFlags,unsigned short) + enum XclStrFlags nFlags + 2 +sc/source/filter/inc/xehelper.hxx:245 + class std::shared_ptr XclExpStringHelper::CreateString(const class XclExpRoot &,char16_t,enum XclStrFlags,unsigned short) + unsigned short nMaxLen + 32767 +sc/source/filter/inc/xelink.hxx:173 + unsigned short XclExpLinkManager::FindExtSheet(char16_t) + char16_t cCode + 4 +sc/source/filter/inc/xepivot.hxx:234 + void XclExpPTItem::XclExpPTItem(unsigned short,unsigned short) + unsigned short nCacheIdx + 65535 +sc/source/filter/inc/xepivot.hxx:336 + unsigned short XclExpPivotTable::GetDataFieldIndex(const class rtl::OUString &,unsigned short) const + unsigned short nDefaultIdx + 65535 +sc/source/filter/inc/xerecord.hxx:397 + void XclExpSubStream::XclExpSubStream(unsigned short) + unsigned short nSubStrmType + 32 +sc/source/filter/inc/xestream.hxx:300 + void XclExpXmlStream::WriteAttributes(int,type-parameter-?-? &&,type-parameter-?-? &&...) + ###26 + 4072 +sc/source/filter/inc/xestring.hxx:55 + void XclExpString::XclExpString(enum XclStrFlags,unsigned short) + unsigned short nMaxLen + 32767 +sc/source/filter/inc/xestyle.hxx:588 + unsigned int XclExpXFBuffer::InsertWithFont(const class ScPatternAttr *,short,unsigned short,_Bool) + short nScript + 4 +sc/source/filter/inc/xetable.hxx:80 + void XclExpRangeFmlaBase::XclExpRangeFmlaBase(unsigned short,unsigned int,const class ScRange &) + unsigned short nRecId + 545 +sc/source/filter/inc/xiescher.hxx:1197 + unsigned int XclImpDffPropSet::GetPropertyValue(unsigned short) const + unsigned short nPropId + 384 +sc/source/filter/inc/xiformula.hxx:40 + void XclImpFormulaCompiler::CreateRangeList(class ScRangeList &,enum XclFormulaType,const class XclTokenArray &,class XclImpStream &) + enum XclFormulaType eType + 7 +sc/source/filter/inc/xiformula.hxx:47 + class std::unique_ptr > XclImpFormulaCompiler::CreateFormula(enum XclFormulaType,const class XclTokenArray &) + enum XclFormulaType eType + 6 +sc/source/filter/inc/xipivot.hxx:223 + void XclImpPTField::XclImpPTField(const class XclImpPivotTable &,unsigned short) + unsigned short nCacheIdx + 65534 +sc/source/filter/inc/xlformula.hxx:517 + _Bool XclTokenArrayHelper::GetStringList(class rtl::OUString &,const class ScTokenArray &,char16_t) + char16_t cSep + 10 +sc/source/filter/inc/xlformula.hxx:525 + void XclTokenArrayHelper::ConvertStringToList(class ScTokenArray &,class svl::SharedStringPool &,char16_t) + char16_t cStringSep + 10 +sc/source/filter/xcl97/XclExpChangeTrack.cxx:1374 + void (anonymous namespace)::EndXmlElement::EndXmlElement(int) + int nElement + 2622 +sc/source/filter/xml/xmlfonte.cxx:41 + void (anonymous namespace)::ScXMLFontAutoStylePool_Impl::AddFontItems(const unsigned short *,unsigned char,const class SfxItemPool *,const _Bool) + unsigned char nIdCount + 3 +sc/source/filter/xml/xmlstyli.cxx:267 + void (anonymous namespace)::XMLTableCellPropsContext::XMLTableCellPropsContext(class SvXMLImport &,int,const class com::sun::star::uno::Reference &,unsigned int,class std::__debug::vector > &,const class rtl::Reference &) + unsigned int nFamily + 196608 +sc/source/ui/Accessibility/AccessibleCsvControl.cxx:218 + int lcl_ExpandSequence(class com::sun::star::uno::Sequence &,int) + int nExp + 7 +sc/source/ui/dbgui/pvfundlg.cxx:72 + _Bool lclFillListBox(class weld::ComboBox &,const class std::__debug::vector > &,int) + int nEmptyPos + 2 +sc/source/ui/inc/AccessibleCell.hxx:156 + void ScAccessibleCell::AddRelation(const class ScAddress &,const unsigned short,class utl::AccessibleRelationSetHelper *) + const unsigned short aRelationType + 4 +sc/source/ui/inc/AccessibleSpreadsheet.hxx:83 + _Bool ScAccessibleSpreadsheet::CalcScRangeListDifferenceMax(class ScRangeList *,class ScRangeList *,int,class std::__debug::vector > &) + int nMax + 10 +sc/source/ui/inc/content.hxx:150 + void ScContentTree::SelectEntryByName(const enum ScContentId,class std::basic_string_view >) + const enum ScContentId nRoot + 8 +sc/source/ui/inc/datatransformation.hxx:82 + void sc::SplitColumnTransformation::SplitColumnTransformation(short,char16_t) + short nCol + 2 +sc/source/ui/inc/datatransformation.hxx:82 + void sc::SplitColumnTransformation::SplitColumnTransformation(short,char16_t) + char16_t cSeparator + 44 +sc/source/ui/inc/datatransformation.hxx:148 + void sc::NumberTransformation::NumberTransformation(const class std::__debug::set, class std::allocator > &,const enum sc::NUMBER_TRANSFORM_TYPE,int) + int nPrecision + 4 +sc/source/ui/inc/docfunc.hxx:114 + _Bool ScDocFunc::SetCellText(const class ScAddress &,const class rtl::OUString &,_Bool,_Bool,_Bool,const enum formula::FormulaGrammar::Grammar) + const enum formula::FormulaGrammar::Grammar eGrammar + 16908294 +sc/source/ui/inc/imoptdlg.hxx:31 + void ScImportOptions::ScImportOptions(char16_t,char16_t,unsigned short) + char16_t nTextSep + 34 +sc/source/ui/inc/pvfundlg.hxx:44 + int ScDPFunctionListBox::get_height_rows(int) const + int nRows + 8 +sc/source/ui/inc/pvfundlg.hxx:45 + void ScDPFunctionListBox::set_size_request(int,int) + int nWidth + -1 +sc/source/ui/inc/select.hxx:33 + void ScViewSelectionEngine::ScViewSelectionEngine(class vcl::Window *,class ScTabView *,enum ScSplitPos) + enum ScSplitPos eSplitPos + 2 +sc/source/ui/inc/spellparam.hxx:46 + void ScConversionParam::ScConversionParam(enum ScConversionType,struct o3tl::strong_int,struct o3tl::strong_int,const class vcl::Font &,int,_Bool) + enum ScConversionType eConvType + 2 +sc/source/ui/inc/TableFillingAndNavigationTools.hxx:44 + void FormulaTemplate::applyRangeList(class std::basic_string_view >,const class ScRangeList &,char16_t) + char16_t cDelimiter + 59 +sc/source/ui/inc/tabview.hxx:425 + void ScTabView::MoveCursorPage(short,int,enum ScFollowMode,_Bool,_Bool) + enum ScFollowMode eMode + 2 +sc/source/ui/inc/tabview.hxx:427 + void ScTabView::MoveCursorArea(short,int,enum ScFollowMode,_Bool,_Bool) + enum ScFollowMode eMode + 3 +sc/source/ui/inc/uiitems.hxx:54 + void ScInputStatusItem::ScInputStatusItem(unsigned short,const class ScAddress &,const class ScAddress &,const class ScAddress &,const class rtl::OUString &,const class EditTextObject *) + unsigned short nWhich + 26100 +sc/source/ui/inc/uiitems.hxx:119 + void ScIndexHint::ScIndexHint(enum SfxHintId,unsigned short) + enum SfxHintId nNewId + 43 +sc/source/ui/inc/uiitems.hxx:130 + void ScSortItem::ScSortItem(unsigned short,class ScViewData *,const struct ScSortParam *) + unsigned short nWhich + 1102 +sc/source/ui/inc/uiitems.hxx:133 + void ScSortItem::ScSortItem(unsigned short,const struct ScSortParam *) + unsigned short nWhich + 1102 +sc/source/ui/inc/uiitems.hxx:151 + void ScQueryItem::ScQueryItem(unsigned short,class ScViewData *,const struct ScQueryParam *) + unsigned short nWhich + 1103 +sc/source/ui/inc/uiitems.hxx:250 + void ScSolveItem::ScSolveItem(unsigned short,const struct ScSolveParam *) + unsigned short nWhich + 1107 +sc/source/ui/inc/uiitems.hxx:265 + void ScTabOpItem::ScTabOpItem(unsigned short,const struct ScTabOpParam *) + unsigned short nWhich + 26345 +sc/source/ui/inc/viewdata.hxx:652 + _Bool ScViewData::SetLOKSheetFreezeIndex(const int,_Bool,short) + short nForTab + -1 +sc/source/ui/pagedlg/tptable.cxx:62 + _Bool lcl_PutScaleItem3(unsigned short,class SfxItemSet &,const class SfxItemSet &,const class weld::ComboBox &,unsigned short,const class weld::SpinButton &,unsigned short) + unsigned short nLBEntry + 2 +sc/source/ui/unoobj/cellsuno.cxx:1232 + _Bool lcl_PutFormulaArray(class ScDocShell &,const class ScRange &,const class com::sun::star::uno::Sequence > &,const enum formula::FormulaGrammar::Grammar) + const enum formula::FormulaGrammar::Grammar eGrammar + 16908294 +sc/source/ui/vba/vbarange.hxx:159 + class com::sun::star::uno::Reference ScVbaRange::getRangeObjectForName(const class com::sun::star::uno::Reference &,const class rtl::OUString &,class ScDocShell *,enum formula::FormulaGrammar::AddressConvention) + enum formula::FormulaGrammar::AddressConvention eConv + 3 +sc/source/ui/view/printfun.cxx:79 + unsigned short lcl_GetUShort(const class SfxItemSet *,unsigned short) + unsigned short nWhich + 176 +sc/source/ui/view/tabview.cxx:2500 + void (anonymous namespace)::ScRangeProvider::calculateDimensionBounds(const long,const long,_Bool,int &,int &,long &,long &,int,class ScViewData &) + int nEnlarge + 2 +sc/source/ui/view/viewfun3.cxx:832 + _Bool lcl_SelHasAttrib(const class ScDocument &,short,int,short,int,const class ScMarkData &,enum HasAttrFlags) + enum HasAttrFlags nMask + 4 +scaddins/source/analysis/analysishelper.hxx:95 + double ConvertToDec(const class rtl::OUString &,unsigned short,unsigned short) + unsigned short nCharLim + 10 +scaddins/source/analysis/analysishelper.hxx:98 + class rtl::OUString ConvertFromDec(double,double,double,unsigned short,int,int,_Bool) + int nMaxPlaces + 10 +scaddins/source/analysis/analysishelper.hxx:104 + class rtl::OUString GetString(double,_Bool,unsigned short) + unsigned short nMaxNumOfDigits + 15 +scaddins/source/analysis/analysishelper.hxx:537 + void sca::analysis::ConvertDataLinear::ConvertDataLinear(const char *,double,double,enum sca::analysis::ConvertDataClass,_Bool) + enum sca::analysis::ConvertDataClass eClass + 8 +sccomp/source/solver/DifferentialEvolution.hxx:48 + void DifferentialEvolutionAlgorithm::DifferentialEvolutionAlgorithm(type-parameter-?-? &,unsigned long) + unsigned long nPopulationSize + 50 +sccomp/source/solver/ParticelSwarmOptimization.hxx:67 + void ParticleSwarmOptimizationAlgorithm::ParticleSwarmOptimizationAlgorithm(type-parameter-?-? &,unsigned long) + unsigned long nNumOfParticles + 100 +sd/inc/Annotation.hxx:62 + void LOKCommentNotify(enum sd::CommentNotificationType,const class SfxViewShell *,const class com::sun::star::uno::Reference &) + enum sd::CommentNotificationType nType + 2 +sd/inc/CustomAnimationEffect.hxx:74 + void sd::CustomAnimationEffect::setPresetClassAndId(short,const class rtl::OUString &) + short nPresetClass + 4 +sd/inc/sdpage.hxx:347 + class SdStyleSheet * SdPage::getPresentationStyle(unsigned int) const + unsigned int nHelpId + 59865 +sd/qa/unit/tiledrendering/CallbackRecorder.hxx:20 + class std::__debug::vector > lcl_convertSeparated(const class rtl::OUString &,char16_t) + char16_t nSeparator + 59 +sd/qa/unit/tiledrendering/tiledrendering.cxx:260 + class std::__debug::vector > lcl_convertSeparated(const class rtl::OUString &,char16_t) + char16_t nSeparator + 59 +sd/source/core/sdpage.cxx:1208 + enum PresObjKind operator|(enum PresObjKind,int) + int x + 32768 +sd/source/filter/eppt/pptexanimations.hxx:83 + void ppt::AnimationExporter::exportAnimPropertyByte(class SvStream &,const unsigned short,const unsigned char) + const unsigned short nPropertyId + 13 +sd/source/ui/animations/STLPropertySet.hxx:61 + void sd::STLPropertySet::setPropertyState(int,enum sd::STLPropertyState) + enum sd::STLPropertyState nState + 3 +sd/source/ui/inc/animobjs.hxx:152 + void sd::AnimationControllerItem::AnimationControllerItem(unsigned short,class sd::AnimationWindow *,class SfxBindings *) + unsigned short + 27112 +sd/source/ui/inc/assclass.hxx:46 + void Assistent::Assistent(int) + int nNoOfPage + 6 +sd/source/ui/inc/assclass.hxx:48 + _Bool Assistent::IsEnabled(int) const + int nPage + 4 +sd/source/ui/inc/assclass.hxx:49 + void Assistent::EnablePage(int) + int nPage + 4 +sd/source/ui/inc/assclass.hxx:50 + void Assistent::DisablePage(int) + int nPage + 4 +sd/source/ui/inc/CustomAnimationList.hxx:109 + int sd::CustomAnimationList::get_height_rows(int) + int nRows + 8 +sd/source/ui/inc/navigatr.hxx:172 + void SdNavigatorControllerItem::SdNavigatorControllerItem(unsigned short,class SdNavigatorWin *,class SfxBindings *,const class std::function &) + unsigned short + 27288 +sd/source/ui/inc/navigatr.hxx:190 + void SdPageNameControllerItem::SdPageNameControllerItem(unsigned short,class SdNavigatorWin *,class SfxBindings *) + unsigned short + 27287 +sd/source/ui/inc/sdtreelb.hxx:193 + int SdPageObjsTLV::get_height_rows(int) const + int nRows + 12 +sd/source/ui/inc/smarttag.hxx:161 + void sd::SmartHdl::SmartHdl(const class rtl::Reference &,const class Point &,enum SdrHdlKind) + enum SdrHdlKind eNewKind + 23 +sd/source/ui/inc/tools/TimerBasedTaskExecution.hxx:50 + class std::shared_ptr sd::tools::TimerBasedTaskExecution::Create(const class std::shared_ptr &,unsigned int,unsigned int) + unsigned int nMillisecondsBetweenSteps + 5 +sd/source/ui/inc/tools/TimerBasedTaskExecution.hxx:50 + class std::shared_ptr sd::tools::TimerBasedTaskExecution::Create(const class std::shared_ptr &,unsigned int,unsigned int) + unsigned int nMaxTimePerStep + 50 +sd/source/ui/inc/ViewShellManager.hxx:154 + class SfxShell * sd::ViewShellManager::GetShell(enum ToolbarId) const + enum ToolbarId nId + 23016 +sd/source/ui/remotecontrol/AvahiNetworkService.hxx:19 + void sd::AvahiNetworkService::AvahiNetworkService(const class std::__cxx11::basic_string, class std::allocator > &,unsigned int) + unsigned int aport + 1599 +sd/source/ui/remotecontrol/ImagePreparer.hxx:36 + class com::sun::star::uno::Sequence sd::ImagePreparer::preparePreview(unsigned int,unsigned int,unsigned int,unsigned long &) + unsigned int aWidth + 320 +sd/source/ui/remotecontrol/ImagePreparer.hxx:36 + class com::sun::star::uno::Sequence sd::ImagePreparer::preparePreview(unsigned int,unsigned int,unsigned int,unsigned long &) + unsigned int aHeight + 240 +sd/source/ui/sidebar/LayoutMenu.hxx:138 + class SfxRequest sd::sidebar::LayoutMenu::CreateRequest(unsigned short,enum AutoLayout) + unsigned short nSlotId + 27014 +sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx:109 + void sd::slidesorter::controller::SelectionFunction::EventDescriptor::EventDescriptor(unsigned int,const struct AcceptDropEvent &,const signed char,const class sd::slidesorter::SlideSorter &) + unsigned int nEventType + 2048 +sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx:135 + class tools::Rectangle sd::slidesorter::view::PageObjectLayouter::CalculatePreviewBoundingBox(class Size &,const class Size &,const int,const int) + const int nFocusIndicatorWidth + 3 +sd/source/ui/slidesorter/view/SlsLayeredDevice.hxx:61 + void sd::slidesorter::view::LayeredDevice::RemovePainter(const class std::shared_ptr &,const int) + const int nLayer + 2 +sd/source/ui/slidesorter/view/SlsLayouter.cxx:145 + int sd::slidesorter::view::Layouter::Implementation::ResolvePositionInGap(int,enum sd::slidesorter::view::Layouter::Implementation::GapMembership,int,int) + int nGap + 4 +sdext/source/minimizer/configurationaccess.hxx:90 + short ConfigurationAccess::GetConfigProperty(const enum PPPOptimizerTokenEnum,const short) const + const enum PPPOptimizerTokenEnum + 38 +sdext/source/minimizer/informationdialog.hxx:29 + class rtl::OUString InsertFixedText(class UnoDialog &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,_Bool,short) + int nXPos + 35 +sdext/source/minimizer/informationdialog.hxx:29 + class rtl::OUString InsertFixedText(class UnoDialog &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,_Bool,short) + int nYPos + 6 +sdext/source/minimizer/informationdialog.hxx:29 + class rtl::OUString InsertFixedText(class UnoDialog &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,_Bool,short) + int nWidth + 199 +sdext/source/minimizer/informationdialog.hxx:29 + class rtl::OUString InsertFixedText(class UnoDialog &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,_Bool,short) + int nHeight + 24 +sdext/source/minimizer/informationdialog.hxx:32 + class rtl::OUString InsertImage(class UnoDialog &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,_Bool) + int nPosX + 5 +sdext/source/minimizer/informationdialog.hxx:32 + class rtl::OUString InsertImage(class UnoDialog &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,_Bool) + int nPosY + 5 +sdext/source/minimizer/informationdialog.hxx:32 + class rtl::OUString InsertImage(class UnoDialog &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,_Bool) + int nWidth + 25 +sdext/source/minimizer/informationdialog.hxx:32 + class rtl::OUString InsertImage(class UnoDialog &,const class rtl::OUString &,const class rtl::OUString &,int,int,int,int,_Bool) + int nHeight + 25 +sdext/source/minimizer/informationdialog.hxx:35 + class rtl::OUString InsertCheckBox(class UnoDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,int,int,int,short) + int nXPos + 35 +sdext/source/minimizer/informationdialog.hxx:35 + class rtl::OUString InsertCheckBox(class UnoDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,int,int,int,short) + int nYPos + 42 +sdext/source/minimizer/informationdialog.hxx:35 + class rtl::OUString InsertCheckBox(class UnoDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,int,int,int,short) + int nWidth + 199 +sdext/source/minimizer/informationdialog.hxx:39 + class rtl::OUString InsertButton(class UnoDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,int,int,int,short,const class rtl::OUString &) + int nXPos + 95 +sdext/source/minimizer/informationdialog.hxx:39 + class rtl::OUString InsertButton(class UnoDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,int,int,int,short,const class rtl::OUString &) + int nWidth + 50 +sdext/source/minimizer/informationdialog.hxx:39 + class rtl::OUString InsertButton(class UnoDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,int,int,int,short,const class rtl::OUString &) + short nTabIndex + 2 +sdext/source/minimizer/optimizerdialog.hxx:108 + void OptimizerDialog::EnablePage(short) + short nStep + 4 +sdext/source/minimizer/optimizerdialog.hxx:109 + void OptimizerDialog::DisablePage(short) + short nStep + 4 +sdext/source/minimizer/optimizerdialogcontrols.cxx:163 + class rtl::OUString InsertCheckBox(class OptimizerDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,int,int,int,short) + int nXPos + 97 +sdext/source/minimizer/optimizerdialogcontrols.cxx:200 + class rtl::OUString InsertFormattedField(class OptimizerDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,int,int,double,double,short) + int nXPos + 197 +sdext/source/minimizer/optimizerdialogcontrols.cxx:200 + class rtl::OUString InsertFormattedField(class OptimizerDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,int,int,double,double,short) + int nYPos + 46 +sdext/source/minimizer/optimizerdialogcontrols.cxx:200 + class rtl::OUString InsertFormattedField(class OptimizerDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,int,int,double,double,short) + double fEffectiveMax + 100 +sdext/source/minimizer/optimizerdialogcontrols.cxx:248 + class rtl::OUString InsertComboBox(class OptimizerDialog &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const _Bool,const class com::sun::star::uno::Sequence &,int,int,short) + int nXPos + 197 +sfx2/inc/SfxRedactionHelper.hxx:63 + class rtl::OUString SfxRedactionHelper::getStringParam(const class SfxRequest &,unsigned short) + unsigned short nParamId + 6734 +sfx2/source/dialog/filedlghelper.cxx:1917 + void SetToken(class rtl::OUString &,int,char16_t,const class rtl::OUString &) + char16_t cTok + 32 +sfx2/source/dialog/mgetempl.hxx:83 + _Bool SfxManageStyleSheetPage::Execute_Impl(unsigned short,const class rtl::OUString &,unsigned short) + unsigned short nId + 5550 +sfx2/source/doc/oleprops.cxx:100 + void (anonymous namespace)::SfxOleStringPropertyBase::SfxOleStringPropertyBase(int,int,const class SfxOleTextEncoding &) + int nPropType + 30 +sfx2/source/doc/oleprops.cxx:103 + void (anonymous namespace)::SfxOleStringPropertyBase::SfxOleStringPropertyBase(int,int,const class SfxOleTextEncoding &,const class rtl::OUString &) + int nPropType + 30 +sfx2/source/doc/oleprops.cxx:106 + void (anonymous namespace)::SfxOleStringPropertyBase::SfxOleStringPropertyBase(int,int,unsigned short) + int nPropType + 31 +sfx2/source/doc/oleprops.cxx:106 + void (anonymous namespace)::SfxOleStringPropertyBase::SfxOleStringPropertyBase(int,int,unsigned short) + unsigned short eTextEnc + 65535 +sfx2/source/doc/oleprops.hxx:306 + void SfxOleSection::SetThumbnailValue(int,const class com::sun::star::uno::Sequence &) + int nPropId + 17 +sfx2/source/doc/syspath.hxx:27 + _Bool GetUserTemplateLocation(char16_t *,int) + int nSize + 16000 +slideshow/source/engine/eventmultiplexer.cxx:107 + void slideshow::internal::ListenerOperations::pruneListeners(type-parameter-?-? &,unsigned long) + unsigned long nSizeThreshold + 16 +slideshow/source/engine/opengl/Operation.hxx:262 + class std::shared_ptr makeRotateAndScaleDepthByHeight(const struct glm::vec<3, float, glm::packed_highp> &,const struct glm::vec<3, float, glm::packed_highp> &,double,_Bool,_Bool,double,double) + double Angle + -120 +slideshow/source/engine/opengl/TransitionImpl.cxx:1825 + class std::shared_ptr makeVortexTransition(const class std::__debug::vector > &,const class std::__debug::vector > &,const struct TransitionSettings &,int,int) + int NX + 96 +slideshow/source/engine/opengl/TransitionImpl.cxx:1825 + class std::shared_ptr makeVortexTransition(const class std::__debug::vector > &,const class std::__debug::vector > &,const struct TransitionSettings &,int,int) + int NY + 96 +slideshow/source/engine/opengl/TransitionImpl.cxx:1939 + void createHexagon(class Primitive &,const int,const int,const int,const int) + const int NX + 80 +slideshow/source/engine/opengl/TransitionImpl.cxx:1939 + void createHexagon(class Primitive &,const int,const int,const int,const int) + const int NY + 106 +slideshow/source/engine/opengl/TransitionImpl.hxx:254 + class std::shared_ptr makeRevolvingCircles(unsigned short,unsigned short) + unsigned short nCircles + 8 +slideshow/source/engine/opengl/TransitionImpl.hxx:254 + class std::shared_ptr makeRevolvingCircles(unsigned short,unsigned short) + unsigned short nPointsOnCircles + 128 +slideshow/source/engine/opengl/TransitionImpl.hxx:255 + class std::shared_ptr makeHelix(unsigned short) + unsigned short nRows + 20 +slideshow/source/inc/box2dtools.hxx:257 + double box2d::utils::box2DWorld::stepAmount(const double,const float,const int,const int) + const int nVelocityIterations + 6 +slideshow/source/inc/box2dtools.hxx:257 + double box2d::utils::box2DWorld::stepAmount(const double,const float,const int,const int) + const int nPositionIterations + 2 +slideshow/source/inc/listenercontainer.hxx:103 + void slideshow::internal::ListenerOperations::pruneListeners(type-parameter-?-? &,unsigned long) + unsigned long + 16 +solenv/bin/concat-deps.c:443 + struct hash * hash_create(unsigned int) + unsigned int size + 4096 +sot/source/sdstor/stgdir.hxx:60 + void StgDirEntry::StgDirEntry(const void *,unsigned int,unsigned long,_Bool *) + unsigned int nBufferLen + 128 +sot/source/sdstor/stgstrms.hxx:80 + _Bool StgStrm::Copy(int,int) + int nFrom + -1 +sot/source/sdstor/stgstrms.hxx:141 + void StgSmallStrm::StgSmallStrm(class StgIo &,int) + int nBgn + -2 +starmath/inc/node.hxx:893 + void SmSpecialNode::SmSpecialNode(enum SmNodeType,const struct SmToken &,unsigned short) + unsigned short _nFontDesc + 7 +starmath/inc/node.hxx:1193 + void SmLineNode::SmLineNode(enum SmNodeType,const struct SmToken &) + enum SmNodeType eNodeType + 21 +starmath/inc/rect.hxx:172 + void SmRect::ExtendBy(const class SmRect &,enum RectCopyMBL,long) + enum RectCopyMBL eCopyMode + 2 +starmath/inc/view.hxx:135 + void SmGraphicController::SmGraphicController(class SmGraphicWindow &,unsigned short,class SfxBindings &) + unsigned short + 30357 +starmath/inc/view.hxx:146 + void SmEditController::SmEditController(class SmEditWindow &,unsigned short,class SfxBindings &) + unsigned short + 30356 +store/source/storbase.hxx:260 + void store::PageData::location(unsigned int) + unsigned int nAddr + -1 +store/source/stordir.cxx:46 + unsigned long convertTextToUnicode(void *,const char *,unsigned long,char16_t *,unsigned long) + unsigned long nDstLength + 255 +svl/source/items/itemset.cxx:1552 + unsigned short * AddRanges_Impl(unsigned short *,long,unsigned short) + unsigned short nIncr + 10 +svl/source/numbers/zforfind.hxx:394 + _Bool ImpSvNumberInputScan::IsDatePatternNumberOfType(unsigned short,char16_t) + char16_t cType + 89 +svl/source/numbers/zforscan.hxx:283 + _Bool ImpSvNumberformatScan::InsertSymbol(unsigned short &,enum svt::NfSymbolType,const class rtl::OUString &) + enum svt::NfSymbolType eType + -7 +svtools/inc/table/tablecontrol.hxx:125 + void svt::table::TableControl::commitCellEventIfAccessibleAlive(const short,const class com::sun::star::uno::Any &,const class com::sun::star::uno::Any &) + const short i_eventID + 4 +svtools/inc/table/tablecontrolinterface.hxx:218 + void svt::table::ITableControl::showTracking(const class tools::Rectangle &,const enum ShowTrackFlags) + const enum ShowTrackFlags i_flags + 4099 +svtools/source/dialogs/ServerDetailsControls.hxx:73 + void HostDetailsContainer::HostDetailsContainer(class PlaceEditDialog *,unsigned short,const class rtl::OUString &) + unsigned short nPort + 80 +svtools/source/misc/sampletext.cxx:567 + class rtl::OUString makeMinimalTextForScript(enum UScriptCode) + enum UScriptCode eScript + 19 +svtools/source/svhtml/htmlout.cxx:394 + unsigned long lcl_FlushContext(struct HTMLOutContext &,char *,unsigned int) + unsigned int nFlags + 6161 +svtools/source/svrtf/rtfout.cxx:29 + class SvStream & Out_Hex(class SvStream &,unsigned long,unsigned char) + unsigned char nLen + 2 +svtools/source/table/tablecontrol_impl.hxx:241 + void svt::table::TableControl_Impl::commitAccessibleEvent(const short) + const short i_eventID + 9 +svx/inc/AccessibleTableShape.hxx:121 + _Bool accessibility::AccessibleTableShape::ResetStateDirectly(short) + short aState + 11 +svx/inc/sxmoitm.hxx:30 + void SdrMeasureOverhangItem::SdrMeasureOverhangItem(long) + long nVal + 600 +svx/inc/xpolyimp.hxx:41 + void ImpXPolygon::ImpXPolygon(unsigned short,unsigned short) + unsigned short nResize + 16 +svx/qa/unit/customshapes.cxx:100 + void lcl_AssertRectEqualWithTolerance(class std::basic_string_view >,const class tools::Rectangle &,const class tools::Rectangle &,const int) + const int nTolerance + 3 +svx/source/dialog/fntctrl.cxx:495 + void SetPrevFontEscapement(class SvxFont &,unsigned char,unsigned char,short) + unsigned char nProp + 100 +svx/source/inc/AccessibleFrameSelector.hxx:111 + void svx::a11y::AccFrameSelectorChild::NotifyAccessibleEvent(const short,const class com::sun::star::uno::Any &,const class com::sun::star::uno::Any &) + const short _nEventId + 4 +svx/source/inc/charmapacc.hxx:209 + void svx::SvxShowCharSetItemAcc::fireEvent(const short,const class com::sun::star::uno::Any &,const class com::sun::star::uno::Any &) + const short _nEventId + 4 +svx/source/inc/fmcontrolbordermanager.hxx:70 + void svxform::UnderlineDescriptor::UnderlineDescriptor(short,class Color) + short _nUnderlineType + 10 +svx/source/inc/fmshimp.hxx:467 + void FmXFormShell::UpdateSlot_Lock(short) + short nId + 10636 +svx/source/inc/GraphCtlAccessibleContext.hxx:157 + void SvxGraphCtrlAccessibleContext::CommitChange(short,const class com::sun::star::uno::Any &,const class com::sun::star::uno::Any &) + short aEventId + 7 +svx/source/unodialogs/textconversiondlgs/chinese_dictionarydialog.hxx:68 + void textconversiondlgs::DictionaryList::set_size_request(int,int) + int nWidth + -1 +svx/source/unodialogs/textconversiondlgs/chinese_dictionarydialog.hxx:78 + int textconversiondlgs::DictionaryList::get_height_rows(int) const + int nRows + 8 +sw/inc/authfld.hxx:131 + void SwAuthorityFieldType::SetSortKeys(unsigned short,const struct SwTOXSortKey *) + unsigned short nKeyCount + 3 +sw/inc/crsrsh.hxx:824 + void SwCursorShell::FireSectionChangeEvent(unsigned short,unsigned short) + unsigned short nOldSection + 2 +sw/inc/crsrsh.hxx:825 + void SwCursorShell::FireColumnChangeEvent(unsigned short,unsigned short) + unsigned short nOldColumn + 2 +sw/inc/docary.hxx:295 + _Bool SwExtraRedlineTable::DeleteAllTableRedlines(class SwDoc &,const class SwTable &,_Bool,enum RedlineType) + enum RedlineType nRedlineTypeToDelete + 65535 +sw/inc/docary.hxx:296 + _Bool SwExtraRedlineTable::DeleteTableRowRedline(class SwDoc *,const class SwTableLine &,_Bool,enum RedlineType) + enum RedlineType nRedlineTypeToDelete + 65535 +sw/inc/docary.hxx:297 + _Bool SwExtraRedlineTable::DeleteTableCellRedline(class SwDoc *,const class SwTableBox &,_Bool,enum RedlineType) + enum RedlineType nRedlineTypeToDelete + 65535 +sw/inc/editsh.hxx:162 + void SwEditShell::Insert(char16_t,_Bool) + char16_t + 32 +sw/inc/editsh.hxx:239 + class std::__debug::vector > >, class std::allocator > > > > SwEditShell::GetItemWithPaM(unsigned short) + unsigned short nWhich + 8 +sw/inc/fesh.hxx:532 + _Bool SwFEShell::BeginCreate(enum SdrObjKind,enum SdrInventor,const class Point &) + enum SdrInventor eObjInventor + 825249094 +sw/inc/fmtcol.hxx:74 + void SwTextFormatColl::SwTextFormatColl(class SwAttrPool &,const char *,class SwTextFormatColl *,unsigned short) + unsigned short nFormatWh + 157 +sw/inc/fmteiro.hxx:32 + void SwFormatEditInReadonly::SwFormatEditInReadonly(unsigned short,_Bool) + unsigned short nId + 112 +sw/inc/frmfmt.hxx:86 + void SwFrameFormat::SwFrameFormat(class SwAttrPool &,const char *,class SwFrameFormat *,unsigned short,const unsigned short *) + unsigned short nFormatWhich + 155 +sw/inc/IDocumentMarkAccess.hxx:346 + class sw::mark::IMark * IDocumentMarkAccess::makeAnnotationBookmark(const class SwPaM &,const class rtl::OUString &,enum IDocumentMarkAccess::MarkType,enum sw::mark::InsertMode,const struct SwPosition *) + enum IDocumentMarkAccess::MarkType eMark + 2 +sw/inc/IDocumentRedlineAccess.hxx:164 + _Bool IDocumentRedlineAccess::DeleteRedline(const class SwStartNode &,_Bool,enum RedlineType) + enum RedlineType nDelType + 65535 +sw/inc/ndtxt.hxx:160 + void SwTextNode::SetLanguageAndFont(const class SwPaM &,struct o3tl::strong_int,unsigned short,const class vcl::Font *,unsigned short) + unsigned short nLangWhichId + 24 +sw/inc/ndtxt.hxx:160 + void SwTextNode::SetLanguageAndFont(const class SwPaM &,struct o3tl::strong_int,unsigned short,const class vcl::Font *,unsigned short) + unsigned short nFontWhichId + 22 +sw/inc/swfltopt.hxx:31 + void SwFilterOptions::SwFilterOptions(unsigned short,const char **,unsigned long *) + unsigned short nCnt + 13 +sw/inc/tblafmt.hxx:249 + _Bool SwTableAutoFormat::Save(class SvStream &,unsigned short) const + unsigned short fileVersion + 5050 +sw/inc/unostyle.hxx:97 + void sw::ICoreFrameStyle::SetItem(unsigned short,const class SfxPoolItem &) + unsigned short eAtr + 108 +sw/inc/unostyle.hxx:98 + const class SfxPoolItem * sw::ICoreFrameStyle::GetItem(unsigned short) + unsigned short eAtr + 108 +sw/inc/unotextcursor.hxx:86 + void SwXTextCursor::SwXTextCursor(const class com::sun::star::uno::Reference &,const class SwPaM &,const enum CursorType) + const enum CursorType eType + 7 +sw/qa/core/Test-BigPtrArray.cxx:55 + void fillBigPtrArray(class BigPtrArray &,unsigned long) + unsigned long numEntries + 10 +sw/source/core/access/accmap.cxx:419 + void SwAccessibleEvent_Impl::SwAccessibleEvent_Impl(enum SwAccessibleEvent_Impl::EventType,const class sw::access::SwAccessibleChild &) + enum SwAccessibleEvent_Impl::EventType eT + 5 +sw/source/core/access/accmap.cxx:430 + void SwAccessibleEvent_Impl::SwAccessibleEvent_Impl(enum SwAccessibleEvent_Impl::EventType) + enum SwAccessibleEvent_Impl::EventType eT + 4 +sw/source/core/access/accmap.cxx:469 + void SwAccessibleEvent_Impl::SwAccessibleEvent_Impl(enum SwAccessibleEvent_Impl::EventType,const class SwFrame *,const class sw::access::SwAccessibleChild &,const class SwRect &) + enum SwAccessibleEvent_Impl::EventType eT + 3 +sw/source/core/crsr/bookmark.cxx:160 + void lcl_SetFieldMarks(class sw::mark::Fieldmark &,class SwDoc &,const char16_t,const char16_t,const struct SwPosition *const) + const char16_t aStartMark + 7 +sw/source/core/crsr/bookmark.cxx:216 + void lcl_RemoveFieldMarks(const class sw::mark::Fieldmark &,class SwDoc &,const char16_t,const char16_t) + const char16_t aStartMark + 7 +sw/source/core/doc/doclay.cxx:96 + _Bool lcl_IsItemSet(const class SwContentNode &,unsigned short) + unsigned short which + 64 +sw/source/core/doc/docredln.cxx:300 + void lcl_LOKInvalidateFrames(const class sw::BroadcastingModify &,const class SwRootFrame *,const enum SwFrameType,const class Point *) + const enum SwFrameType nFrameType + 49152 +sw/source/core/doc/DocumentStylePoolManager.cxx:121 + void lcl_SetDfltFont(enum DefaultFontType,class SfxItemSet &) + enum DefaultFontType nFntType + 4 +sw/source/core/doc/DocumentStylePoolManager.cxx:144 + void lcl_SetDfltFont(enum DefaultFontType,enum DefaultFontType,enum DefaultFontType,class SfxItemSet &) + enum DefaultFontType nLatinFntType + 2000 +sw/source/core/doc/DocumentStylePoolManager.cxx:144 + void lcl_SetDfltFont(enum DefaultFontType,enum DefaultFontType,enum DefaultFontType,class SfxItemSet &) + enum DefaultFontType nCJKFntType + 3000 +sw/source/core/doc/DocumentStylePoolManager.cxx:144 + void lcl_SetDfltFont(enum DefaultFontType,enum DefaultFontType,enum DefaultFontType,class SfxItemSet &) + enum DefaultFontType nCTLFntType + 4000 +sw/source/core/doc/SwStyleNameMapper.cxx:90 + class std::__debug::unordered_map, struct std::equal_to, class std::allocator > > HashFromRange(unsigned short,unsigned short,unsigned short,const class std::__debug::vector > &(*)(void),type-parameter-?-?...) + ###16 + 12288 +sw/source/core/doc/SwStyleNameMapper.cxx:90 + class std::__debug::unordered_map, struct std::equal_to, class std::allocator > > HashFromRange(unsigned short,unsigned short,unsigned short,const class std::__debug::vector > &(*)(void),type-parameter-?-?...) + ###17 + 12293 +sw/source/core/doc/tblafmt.cxx:179 + void SwAfVersions::Write(class SvStream &,unsigned short) + unsigned short fileVersion + 5050 +sw/source/core/inc/swcache.hxx:113 + void SwCache::DecreaseMax(const unsigned short) + const unsigned short nSub + 100 +sw/source/core/inc/txtfrm.hxx:496 + long SwTextFrame::GrowTst(const long) + const long nGrow + 9223372036854775807 +sw/source/core/inc/UndoAttribute.hxx:72 + void SwUndoResetAttr::SwUndoResetAttr(const struct SwPosition &,unsigned short) + unsigned short nFormatId + 47 +sw/source/core/inc/UndoCore.hxx:250 + class rtl::OUString ShortenString(const class rtl::OUString &,int,const class rtl::OUString &) + int nLength + 20 +sw/source/core/inc/UndoNumbering.hxx:39 + void SwUndoInsNum::SwUndoInsNum(const class SwNumRule &,const class SwNumRule &,const class SwDoc &,enum SwUndoId) + enum SwUndoId nUndoId + 10 +sw/source/core/layout/dbg_lay.cxx:493 + void lcl_Padded(class rtl::OStringBuffer &,const long,unsigned long) + unsigned long length + 5 +sw/source/core/layout/objectformattertxtfrm.hxx:96 + class SwAnchoredObject * SwObjectFormatterTextFrame::GetFirstObjWithMovedFwdAnchor(const short,unsigned int &,_Bool &) + const short _nWrapInfluenceOnPosition + 2 +sw/source/core/txtnode/txtedt.cxx:180 + _Bool lcl_MaskRedlinesAndHiddenText(const class SwTextNode &,class rtl::OUStringBuffer &,int,int,const char16_t) + const char16_t cChar + 65529 +sw/source/core/undo/untbl.cxx:2174 + void (anonymous namespace)::RedlineFlagsInternGuard::RedlineFlagsInternGuard(class SwDoc &,enum RedlineFlags,enum RedlineFlags) + enum RedlineFlags eRedlineFlagsMask + 2 +sw/source/filter/html/htmlatr.cxx:1149 + _Bool (anonymous namespace)::HTMLEndPosLst::IsHTMLMode(unsigned long) const + unsigned long nMode + 32 +sw/source/filter/html/svxcss1.hxx:159 + void SvxCSS1PropertyInfo::SetBoxItem(class SfxItemSet &,unsigned short,const class SvxBoxItem *) + unsigned short nMinBorderDist + 28 +sw/source/filter/html/swhtml.hxx:639 + void SwHTMLParser::NewStdAttr(enum HtmlTokenId) + enum HtmlTokenId nToken + 414 +sw/source/filter/inc/fltshell.hxx:174 + class SfxPoolItem * SwFltControlStack::GetFormatStackAttr(unsigned short,unsigned short *) + unsigned short nWhich + 6 +sw/source/filter/inc/fltshell.hxx:175 + const class SfxPoolItem * SwFltControlStack::GetOpenStackAttr(const struct SwPosition &,unsigned short) + unsigned short nWhich + 14 +sw/source/filter/ww8/docxattributeoutput.cxx:3766 + class rtl::OString lcl_padStartToLength(const class rtl::OString &,int,char) + int nLen + 4 +sw/source/filter/ww8/docxattributeoutput.cxx:3766 + class rtl::OString lcl_padStartToLength(const class rtl::OString &,int,char) + char cFill + 48 +sw/source/filter/ww8/docxexport.hxx:192 + void DocxExport::WriteOutliner(const class OutlinerParaObject &,unsigned char) + unsigned char nTyp + 5 +sw/source/filter/ww8/escher.hxx:124 + void SwBasicEscherEx::WriteEmptyFlyFrame(const class SwFrameFormat &,unsigned int) + unsigned int nShapeId + 1025 +sw/source/filter/ww8/writerhelper.hxx:473 + const type-parameter-?-? * HasItem(const class std::__debug::map > > &,unsigned short) + unsigned short eType + 52 +sw/source/filter/ww8/wrtww8.hxx:1359 + void WW8_WrPlcField::WW8_WrPlcField(unsigned short,unsigned char) + unsigned short nStructSz + 2 +sw/source/filter/ww8/wrtww8.hxx:1416 + void SwWW8WrGrf::WritePICBulletFHeader(class SvStream &,const class Graphic &,unsigned short,unsigned short,unsigned short) + unsigned short mm + 100 +sw/source/filter/ww8/wrtww8.hxx:1529 + void SwWW8AttrIter::handleToggleProperty(class SfxItemSet &,const class SwFormatCharFormat *,unsigned short,const class SfxPoolItem *) + unsigned short nWhich + 15 +sw/source/filter/ww8/ww8glsy.hxx:63 + void WW8Glossary::WW8Glossary(class tools::SvRef &,unsigned char,class SotStorage *) + unsigned char nVersion + 8 +sw/source/filter/ww8/ww8par.hxx:1600 + class std::unique_ptr > SwWW8ImplReader::ImportAsOutliner(class rtl::OUString &,int,int,enum ManTypes) + enum ManTypes eType + 4 +sw/source/filter/ww8/ww8scan.cxx:7193 + _Bool readS16(const unsigned char *,unsigned long,const unsigned char *,short *) + unsigned long offset + 2 +sw/source/filter/ww8/ww8scan.hxx:996 + struct SprmResult WW8PLCFMan::HasCharSprm(unsigned short) const + unsigned short nId + 2138 +sw/source/filter/ww8/ww8scan.hxx:1535 + void WW8Fib::WW8Fib(unsigned char,_Bool) + unsigned char nVersion + 8 +sw/source/filter/xml/xmlbrshi.hxx:58 + void SwXMLBrushItemImportContext::SwXMLBrushItemImportContext(class SvXMLImport &,int,const class com::sun::star::uno::Reference &,const class SvXMLUnitConverter &,unsigned short) + unsigned short nWhich + 105 +sw/source/uibase/inc/frmmgr.hxx:121 + void SwFlyFrameAttrMgr::DelAttr(unsigned short) + unsigned short nId + 89 +sw/source/uibase/inc/mailmergehelper.hxx:99 + void SwAddressPreview::SetLayout(unsigned short,unsigned short) + unsigned short nColumns + 2 +sw/source/uibase/inc/numpara.hxx:61 + _Bool SwParagraphNumTabPage::ExecuteEditNumStyle_Impl(unsigned short,const class rtl::OUString &,enum SfxStyleFamily) + unsigned short nId + 5550 +sw/source/uibase/inc/numpara.hxx:61 + _Bool SwParagraphNumTabPage::ExecuteEditNumStyle_Impl(unsigned short,const class rtl::OUString &,enum SfxStyleFamily) + enum SfxStyleFamily nFamily + 16 +sw/source/uibase/inc/prcntfld.hxx:66 + void SwPercentField::set_min(int,enum FieldUnit) + enum FieldUnit eInUnit + 5 +sw/source/uibase/inc/prcntfld.hxx:67 + void SwPercentField::set_max(int,enum FieldUnit) + enum FieldUnit eInUnit + 5 +sw/source/uibase/inc/swuipardlg.hxx:34 + void SwParaDlg::SwParaDlg(class weld::Window *,class SwView &,const class SfxItemSet &,unsigned char,const class rtl::OUString *,_Bool,const class rtl::OString &) + unsigned char nDialogMode + 2 +toolkit/inc/helper/btndlg.hxx:61 + void ButtonDialog::RemoveButton(unsigned short) + unsigned short nId + 10 +toolkit/inc/helper/btndlg.hxx:64 + void ButtonDialog::ButtonDialog(enum WindowType) + enum WindowType nType + 304 +toolkit/source/awt/vclxspinbutton.cxx:40 + void lcl_modifyStyle(class vcl::Window *,long,_Bool) + long _nStyleBits + 4096 +toolkit/source/awt/vclxwindows.cxx:6548 + void lcl_setWinBits(class vcl::Window *,long,_Bool) + long _nBits + 68719476736 +tools/source/stream/strmunx.cxx:104 + class ErrCode GetSvError(int) + int nErrno + 21 +ucbhelper/source/provider/resultset.cxx:100 + void ucbhelper_impl::(anonymous namespace)::PropertySetInfo::PropertySetInfo(const struct ucbhelper_impl::(anonymous namespace)::PropertyInfo *,int) + int nProps + 2 +unotools/source/config/useroptions.cxx:98 + _Bool SvtUserOptions::Impl::GetBoolValue(enum UserOptToken) const + enum UserOptToken nToken + 19 +unotools/source/misc/datetime.cxx:72 + _Bool convertNumber64(long &,const class rtl::OUString &,long,long) + long + -1 +vcl/backendtest/outputdevice/rectangle.cxx:23 + void drawInvertOffset(class OutputDevice &,const class tools::Rectangle &,int,enum InvertFlags) + int nOffset + 2 +vcl/inc/driverblocklist.hxx:156 + unsigned long OpenGLVersion(unsigned int,unsigned int,unsigned int,unsigned int) + unsigned int a + 10 +vcl/inc/driverblocklist.hxx:156 + unsigned long OpenGLVersion(unsigned int,unsigned int,unsigned int,unsigned int) + unsigned int b + 20 +vcl/inc/driverblocklist.hxx:156 + unsigned long OpenGLVersion(unsigned int,unsigned int,unsigned int,unsigned int) + unsigned int c + 30 +vcl/inc/driverblocklist.hxx:156 + unsigned long OpenGLVersion(unsigned int,unsigned int,unsigned int,unsigned int) + unsigned int d + 40 +vcl/inc/FileDefinitionWidgetDraw.hxx:61 + void vcl::FileDefinitionWidgetDraw::drawPolyLine(class SalGraphics &,const class basegfx::B2DHomMatrix &,const class basegfx::B2DPolygon &,double,double,const class std::__debug::vector > *,enum basegfx::B2DLineJoin,enum com::sun::star::drawing::LineCap,double,_Bool) + enum basegfx::B2DLineJoin i_eLineJoin + 4 +vcl/inc/fontsubset.hxx:54 + void FontSubsetInfo::LoadFont(enum FontType,const unsigned char *,int) + enum FontType eInFontType + 32 +vcl/inc/headless/svpgdi.hxx:253 + void SvpSalGraphics::drawBitmap(const struct SalTwoRect &,const struct BitmapBuffer *,enum _cairo_operator) + enum _cairo_operator eOp + 2 +vcl/inc/listbox.hxx:486 + void ImplListBox::SetMRUEntries(const class rtl::OUString &,char16_t) + char16_t cSep + 59 +vcl/inc/listbox.hxx:487 + class rtl::OUString ImplListBox::GetMRUEntries(char16_t) const + char16_t cSep + 59 +vcl/inc/skia/utils.hxx:46 + class sk_sp createSkSurface(const class Size &,enum SkColorType,enum SkAlphaType) + enum SkAlphaType alpha + 2 +vcl/inc/test/outputdevice.hxx:77 + void vcl::test::OutputDeviceTestCommon::createDiamondPoints(class tools::Rectangle,int,class Point &,class Point &,class Point &,class Point &) + int nOffset + 4 +vcl/inc/unx/gendisp.hxx:44 + void SalGenericDisplay::CancelInternalEvent(class SalFrame *,void *,enum SalEvent) + enum SalEvent nEvent + 21 +vcl/inc/unx/saldata.hxx:47 + void X11SalData::X11SalData(enum GenericUnixSalDataType,class SalInstance *) + enum GenericUnixSalDataType t + 3 +vcl/inc/unx/x11/xrender_peer.hxx:51 + void XRenderPeer::ChangePicture(unsigned long,unsigned long,const struct _XRenderPictureAttributes *) const + unsigned long nValueMask + 64 +vcl/inc/unx/x11/xrender_peer.hxx:54 + void XRenderPeer::CompositePicture(int,unsigned long,unsigned long,unsigned long,int,int,int,int,unsigned int,unsigned int) const + int nOp + 3 +vcl/inc/unx/x11/xrender_peer.hxx:61 + void XRenderPeer::CompositeTrapezoids(int,unsigned long,unsigned long,const XRenderPictFormat *,int,int,const struct _XTrapezoid *,int) const + int nOp + 3 +vcl/inc/unx/x11/xrender_peer.hxx:64 + void XRenderPeer::CompositeTriangles(int,unsigned long,unsigned long,const XRenderPictFormat *,int,int,const struct _XTriangle *,int) const + int nOp + 3 +vcl/inc/WidgetDrawInterface.hxx:47 + _Bool vcl::WidgetDrawInterface::hitTestNativeControl(enum ControlType,enum ControlPart,const class tools::Rectangle &,const class Point &,_Bool &) + enum ControlType eType + 60 +vcl/inc/wizdlg.hxx:88 + long vcl::RoadmapWizard::LogicalCoordinateToPixel(int) + int iCoordinate + 6 +vcl/inc/wizdlg.hxx:288 + void vcl::RoadmapWizard::implConstruct(const enum WizardButtonFlags) + const enum WizardButtonFlags _nButtonFlags + 31 +vcl/qa/cppunit/BitmapScaleTest.cxx:74 + void assertColorsAreSimilar(int,int,const class BitmapColor &,const class BitmapColor &) + int maxDifference + 2 +vcl/qa/cppunit/jpeg/JpegReaderTest.cxx:54 + _Bool checkRect(class Bitmap &,int,long,long,class Color,int) + long nAreaHeight + 8 +vcl/qa/cppunit/jpeg/JpegReaderTest.cxx:54 + _Bool checkRect(class Bitmap &,int,long,long,class Color,int) + long nAreaWidth + 8 +vcl/qa/cppunit/timer.cxx:37 + void (anonymous namespace)::WatchDog::WatchDog(int) + int nSeconds + 120 +vcl/qa/cppunit/timer.cxx:343 + void (anonymous namespace)::YieldTimer::YieldTimer(unsigned long) + unsigned long nMS + 5 +vcl/qa/cppunit/timer.cxx:373 + void (anonymous namespace)::SlowCallbackTimer::SlowCallbackTimer(unsigned long,_Bool &) + unsigned long nMS + 250 +vcl/source/filter/eps/eps.cxx:92 + enum (anonymous namespace)::NMode operator|(enum (anonymous namespace)::NMode,enum (anonymous namespace)::NMode) + enum (anonymous namespace)::NMode b + 4 +vcl/source/filter/eps/eps.cxx:187 + void (anonymous namespace)::PSWriter::ImplCurveTo(const class Point &,const class Point &,const class Point &,enum (anonymous namespace)::NMode) + enum (anonymous namespace)::NMode nMode + 4 +vcl/source/filter/idxf/dxf2mtf.hxx:111 + _Bool DXF2GDIMetaFile::Convert(const class DXFRepresentation &,class GDIMetaFile &,unsigned short,unsigned short) + unsigned short nMinPercent + 60 +vcl/source/filter/idxf/dxf2mtf.hxx:111 + _Bool DXF2GDIMetaFile::Convert(const class DXFRepresentation &,class GDIMetaFile &,unsigned short,unsigned short) + unsigned short nMaxPercent + 100 +vcl/source/filter/jpeg/JpegReader.cxx:55 + long StreamRead(class SvStream *,void *,long) + long nBufferSize + 4096 +vcl/source/filter/wmf/emfwr.hxx:57 + void EMFWriter::ImplBeginCommentRecord(int) + int nCommentType + 726027589 +vcl/source/filter/wmf/wmfwr.hxx:144 + void WMFWriter::WMFRecord_Escape(unsigned int,unsigned int,const signed char *) + unsigned int nEsc + 2 +vcl/source/fontsubset/ttcr.hxx:61 + void TrueTypeCreatorNewEmpty(unsigned int,struct vcl::TrueTypeCreator **) + unsigned int tag + 1953658213 +vcl/source/fontsubset/ttcr.hxx:174 + struct vcl::TrueTypeTable * TrueTypeTableNew_post(int,int,short,short,unsigned int) + int format + 196608 +vcl/source/fontsubset/ttcr.hxx:185 + void cmapAdd(struct vcl::TrueTypeTable *,unsigned int,unsigned int,unsigned int) + unsigned int id + 65536 +vcl/source/gdi/pdfwriter_impl.hxx:1021 + _Bool vcl::PDFWriterImpl::computeODictionaryValue(const unsigned char *,const unsigned char *,class std::__debug::vector > &,int) + int i_nKeyLength + 16 +vcl/source/gdi/pdfwriter_impl.hxx:1069 + void vcl::PDFWriterImpl::insertError(enum vcl::PDFWriter::ErrorCode) + enum vcl::PDFWriter::ErrorCode eErr + 3 +vcl/source/graphic/GraphicObject.cxx:134 + void lclImplAdjust(class BitmapEx &,const class GraphicAttr &,enum GraphicAdjustmentFlags) + enum GraphicAdjustmentFlags nAdjustmentFlags + 31 +vcl/source/graphic/GraphicObject.cxx:185 + void lclImplAdjust(class GDIMetaFile &,const class GraphicAttr &,enum GraphicAdjustmentFlags) + enum GraphicAdjustmentFlags nAdjustmentFlags + 31 +vcl/source/graphic/GraphicObject.cxx:236 + void lclImplAdjust(class Animation &,const class GraphicAttr &,enum GraphicAdjustmentFlags) + enum GraphicAdjustmentFlags nAdjustmentFlags + 31 +vcl/source/opengl/OpenGLHelper.cxx:171 + class rtl::OString getHexString(const unsigned char *,unsigned int) + unsigned int nLength + 16 +vcl/source/window/impldockingwrapper.hxx:108 + void ImplDockingWindowWrapper::ShowTitleButton(enum TitleButton,_Bool) + enum TitleButton nButton + 4 +vcl/source/window/menu.cxx:545 + void ImplCopyItem(class Menu *,const class Menu &,unsigned short,unsigned short) + unsigned short nNewPos + 65535 +vcl/unx/generic/app/saldisp.cxx:660 + unsigned int GetKeySymMask(struct _XDisplay *,unsigned long) + unsigned long nKeySym + 65509 +vcl/unx/generic/dtrans/X11_selection.hxx:382 + unsigned long x11::SelectionManager::createCursor(const unsigned char *,const unsigned char *,int,int,int,int) + int width + 32 +vcl/unx/generic/dtrans/X11_selection.hxx:382 + unsigned long x11::SelectionManager::createCursor(const unsigned char *,const unsigned char *,int,int,int,int) + int height + 32 +workdir/../vcl/inc/qt5/Qt5Frame.hxx:210 + _Bool Qt5Frame::CallCallback(enum SalEvent,const void *) const + enum SalEvent nEvent + 37 +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:173 + void writerfilter::ooxml::OOXMLFastContextHandler::sendPropertiesWithId(unsigned int) + unsigned int nId + 92465 +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:512 + void writerfilter::ooxml::OOXMLFastContextHandlerWrapper::addToken(int) + int Element + 2167928 +writerfilter/source/rtftok/rtfdocumentimpl.hxx:664 + class tools::SvRef getNestedSprm(class writerfilter::rtftok::RTFSprms &,unsigned int,unsigned int) + unsigned int nParent + 92165 +writerfilter/source/rtftok/rtfsprm.hxx:58 + void writerfilter::rtftok::RTFSprms::eraseLast(unsigned int) + unsigned int nKeyword + 92680 +xmloff/inc/txtflde.hxx:253 + void XMLTextFieldExport::ProcessIntegerDef(enum xmloff::token::XMLTokenEnum,int,int) + enum xmloff::token::XMLTokenEnum eXmlName + 1350 +xmloff/inc/txtflde.hxx:279 + void XMLTextFieldExport::ProcessString(enum xmloff::token::XMLTokenEnum,unsigned short,const class rtl::OUString &,class std::basic_string_view >) + enum xmloff::token::XMLTokenEnum eXmlName + 833 +xmloff/inc/txtflde.hxx:279 + void XMLTextFieldExport::ProcessString(enum xmloff::token::XMLTokenEnum,unsigned short,const class rtl::OUString &,class std::basic_string_view >) + unsigned short nValuePrefix + 30 +xmloff/inc/txtflde.hxx:292 + void XMLTextFieldExport::ProcessString(enum xmloff::token::XMLTokenEnum,enum xmloff::token::XMLTokenEnum,enum xmloff::token::XMLTokenEnum) + enum xmloff::token::XMLTokenEnum eXmlName + 1477 +xmloff/inc/txtflde.hxx:292 + void XMLTextFieldExport::ProcessString(enum xmloff::token::XMLTokenEnum,enum xmloff::token::XMLTokenEnum,enum xmloff::token::XMLTokenEnum) + enum xmloff::token::XMLTokenEnum eDefault + 1813 +xmloff/inc/txtflde.hxx:324 + void XMLTextFieldExport::ProcessDateTime(enum xmloff::token::XMLTokenEnum,double,_Bool,_Bool,_Bool,unsigned short) + unsigned short nPrefix + 2 +xmloff/inc/txtflde.hxx:340 + void XMLTextFieldExport::ProcessDateTime(enum xmloff::token::XMLTokenEnum,const struct com::sun::star::util::DateTime &) + enum xmloff::token::XMLTokenEnum eXMLName + 532 +xmloff/inc/txtflde.hxx:345 + void XMLTextFieldExport::ProcessTimeOrDateTime(enum xmloff::token::XMLTokenEnum,const struct com::sun::star::util::DateTime &) + enum xmloff::token::XMLTokenEnum eXMLName + 1866 +xmloff/inc/XMLBase64Export.hxx:38 + _Bool XMLBase64Export::exportElement(const class com::sun::star::uno::Reference &,enum xmloff::token::XMLTokenEnum) + enum xmloff::token::XMLTokenEnum eName + 2076 +xmloff/source/chart/transporttypes.hxx:199 + void DataRowPointStyle::DataRowPointStyle(enum DataRowPointStyle::StyleType,const class rtl::OUString &,int) + enum DataRowPointStyle::StyleType eType + 5 +xmloff/source/draw/ximpcustomshape.cxx:87 + void GetInt32(class std::__debug::vector > &,class std::basic_string_view >,const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum) + const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum eDestProp + 80 +xmloff/source/draw/ximpcustomshape.cxx:100 + void GetDouble(class std::__debug::vector > &,class std::basic_string_view >,const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum) + const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum eDestProp + 65 +xmloff/source/draw/ximpcustomshape.cxx:113 + void GetString(class std::__debug::vector > &,const class rtl::OUString &,const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum) + const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum eDestProp + 61 +xmloff/source/draw/ximpcustomshape.cxx:123 + void GetEnum(class std::__debug::vector > &,class std::basic_string_view >,const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum,const SvXMLEnumMapEntry &) + const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum eDestProp + 114 +xmloff/source/draw/ximpcustomshape.cxx:427 + void GetPosition3D(class std::__debug::vector > &,class std::basic_string_view >,const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum,class SvXMLUnitConverter &) + const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum eDestProp + 96 +xmloff/source/draw/ximpcustomshape.cxx:441 + void GetDoubleSequence(class std::__debug::vector > &,const class rtl::OUString &,const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum) + const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum eDestProp + 113 +xmloff/source/draw/ximpcustomshape.cxx:466 + void GetSizeSequence(class std::__debug::vector > &,const class rtl::OUString &,const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum) + const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum eDestProp + 120 +xmloff/source/draw/ximpcustomshape.cxx:532 + int GetEnhancedParameterPairSequence(class std::__debug::vector > &,const class rtl::OUString &,const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum) + const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum eDestProp + 112 +xmloff/source/draw/ximpcustomshape.cxx:554 + void GetEnhancedRectangleSequence(class std::__debug::vector > &,const class rtl::OUString &,const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum) + const enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum eDestProp + 111 +xmloff/source/forms/elementimport.cxx:1361 + void xmloff::(anonymous namespace)::EqualHandle::EqualHandle(int) + int _nHandle + 2 +xmloff/source/forms/property_description.hxx:80 + void xmloff::PropertyDescription::PropertyDescription(const class rtl::OUString &,const unsigned short,const enum xmloff::token::XMLTokenEnum,class rtl::Reference (*const)(enum xmloff::PropertyId),const enum xmloff::PropertyId) + const unsigned short i_namespacePrefix + 15 +xmloff/source/script/xmlbasicscript.hxx:36 + _Bool xmloff::BasicElementBase::getBoolAttr(_Bool *,int,const class com::sun::star::uno::Reference &) + int nToken + 1968665 +xmloff/source/style/xmlbahdl.hxx:50 + void XMLNumberNonePropHdl::XMLNumberNonePropHdl(enum xmloff::token::XMLTokenEnum,signed char) + enum xmloff::token::XMLTokenEnum eZeroString + 418 +xmloff/source/style/xmlbahdl.hxx:50 + void XMLNumberNonePropHdl::XMLNumberNonePropHdl(enum xmloff::token::XMLTokenEnum,signed char) + signed char nB + 2 +xmloff/source/style/xmlbahdl.hxx:116 + void XMLMeasurePxPropHdl::XMLMeasurePxPropHdl(signed char) + signed char nB + 4 +xmloff/source/text/XMLIndexMarkExport.cxx:182 + void lcl_ExportPropertyBool(class SvXMLExport &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,enum xmloff::token::XMLTokenEnum,class com::sun::star::uno::Any &) + enum xmloff::token::XMLTokenEnum eToken + 2186 +xmloff/source/transform/TransformerContext.hxx:57 + _Bool XMLTransformerContext::HasNamespace(unsigned short) const + unsigned short nPrefix + 15 +xmlsecurity/inc/xsecctl.hxx:85 + void InternalSignatureInformation::addReference(enum SignatureReferenceType,int,const class rtl::OUString &,int,const class rtl::OUString &) + int keeperId + -1 +xmlsecurity/source/framework/elementmark.hxx:56 + void ElementMark::ElementMark(int,int) + int nSecurityId + -1 diff --git a/compilerplugins/clang/constantparam.py b/compilerplugins/clang/constantparam.py new file mode 100755 index 000000000..4a363eade --- /dev/null +++ b/compilerplugins/clang/constantparam.py @@ -0,0 +1,198 @@ +#!/usr/bin/python3 + +import sys +import re +import io + +callDict = dict() # callInfo tuple -> callValue + +# clang does not always use exactly the same numbers in the type-parameter vars it generates +# so I need to substitute them to ensure we can match correctly. +normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") +def normalizeTypeParams( line ): + return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) + +# reading as binary (since we known it is pure ascii) is much faster than reading as unicode +with io.open("workdir/loplugin.constantparam.log", "r") as txt: + line_no = 1; + try: + for line in txt: + tokens = line.strip().split("\t") + returnType = normalizeTypeParams(tokens[0]) + nameAndParams = normalizeTypeParams(tokens[1]) + sourceLocation = tokens[2] + paramName = tokens[3] + paramType = normalizeTypeParams(tokens[4]) + callValue = tokens[5] + callInfo = (returnType, nameAndParams, paramName, paramType, sourceLocation) + if not callInfo in callDict: + callDict[callInfo] = set() + callDict[callInfo].add(callValue) + line_no += 1 + except (IndexError,UnicodeDecodeError): + print("problem with line " + str(line_no)) + raise + +def RepresentsInt(s): + try: + int(s) + return True + except ValueError: + return False + +constructor_regex = re.compile(r"^\w+\(\)$") + +tmp1list = list() +tmp2list = list() +tmp3list = list() +tmp4list = list() +for callInfo, callValues in iter(callDict.items()): + nameAndParams = callInfo[1] + if len(callValues) != 1: + continue + callValue = next(iter(callValues)) + if "unknown" in callValue: + continue + sourceLoc = callInfo[4] + functionSig = callInfo[0] + " " + callInfo[1] + + # try to ignore setter methods + if ("," not in nameAndParams) and (("::set" in nameAndParams) or ("::Set" in nameAndParams)): + continue + # ignore code that follows a common pattern + if sourceLoc.startswith("sw/inc/swatrset.hxx"): continue + if sourceLoc.startswith("sw/inc/format.hxx"): continue + # template generated code + if sourceLoc.startswith("include/sax/fshelper.hxx"): continue + # debug code + if sourceLoc.startswith("include/oox/dump"): continue + # part of our binary API + if sourceLoc.startswith("include/LibreOfficeKit"): continue + + # ignore methods generated by SFX macros + if "RegisterInterface(class SfxModule *)" in nameAndParams: continue + if "RegisterChildWindow(_Bool,class SfxModule *,enum SfxChildWindowFlags)" in nameAndParams: continue + if "RegisterControl(unsigned short,class SfxModule *)" in nameAndParams: continue + + if RepresentsInt(callValue): + if callValue == "0" or callValue == "1": + tmp1list.append((sourceLoc, functionSig, callInfo[3] + " " + callInfo[2], callValue)) + else: + tmp2list.append((sourceLoc, functionSig, callInfo[3] + " " + callInfo[2], callValue)) + # look for places where the callsite is always a constructor invocation + elif constructor_regex.match(callValue) or callValue == "\"\"": + if callValue.startswith("Get"): continue + if callValue.startswith("get"): continue + if "operator=" in functionSig: continue + if "&&" in functionSig: continue + if callInfo[2] == "###0" and callValue == "InitData()": continue + if callInfo[2] == "###0" and callValue == "InitAggregate()": continue + if callValue == "shared_from_this()": continue + tmp3list.append((sourceLoc, functionSig, callInfo[3] + " " + callInfo[2], callValue)) + else: + tmp4list.append((sourceLoc, functionSig, callInfo[3] + " " + callInfo[2], callValue)) + + +# sort results by filename:lineno +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[0]) + [v[1]] +tmp1list.sort(key=lambda v: v_sort_key(v)) +tmp2list.sort(key=lambda v: v_sort_key(v)) +tmp3list.sort(key=lambda v: v_sort_key(v)) +tmp4list.sort(key=lambda v: v_sort_key(v)) + +# print out the results +with open("compilerplugins/clang/constantparam.booleans.results", "wt") as f: + for v in tmp1list: + f.write(v[0] + "\n") + f.write(" " + v[1] + "\n") + f.write(" " + v[2] + "\n") + f.write(" " + v[3] + "\n") +with open("compilerplugins/clang/constantparam.numbers.results", "wt") as f: + for v in tmp2list: + f.write(v[0] + "\n") + f.write(" " + v[1] + "\n") + f.write(" " + v[2] + "\n") + f.write(" " + v[3] + "\n") +with open("compilerplugins/clang/constantparam.constructors.results", "wt") as f: + for v in tmp3list: + f.write(v[0] + "\n") + f.write(" " + v[1] + "\n") + f.write(" " + v[2] + "\n") + f.write(" " + v[3] + "\n") +with open("compilerplugins/clang/constantparam.others.results", "wt") as f: + for v in tmp4list: + f.write(v[0] + "\n") + f.write(" " + v[1] + "\n") + f.write(" " + v[2] + "\n") + f.write(" " + v[3] + "\n") + +# ------------------------------------------------------------- +# Now a fun set of heuristics to look for methods that +# take bitmask parameters where one or more of the bits in the +# bitmask is always one or always zero + +# integer to hex str +def hex(i): + return "0x%x" % i +# I can't use python's ~ operator, because that produces negative numbers +def negate(i): + return (1 << 32) - 1 - i + +tmp2list = list() +for callInfo, callValues in iter(callDict.items()): + nameAndParams = callInfo[1] + if len(callValues) < 2: + continue + # we are only interested in enum parameters + if not "enum" in callInfo[3]: continue + if not "Flag" in callInfo[3] and not "flag" in callInfo[3] and not "Bit" in callInfo[3] and not "State" in callInfo[3]: continue + # try to ignore setter methods + if ("," not in nameAndParams) and (("::set" in nameAndParams) or ("::Set" in nameAndParams)): + continue + + setBits = 0 + clearBits = 0 + continue_flag = False + first = True + for callValue in callValues: + if "unknown" == callValue or not callValue.isdigit(): + continue_flag = True + break + if first: + setBits = int(callValue) + clearBits = negate(int(callValue)) + first = False + else: + setBits = setBits & int(callValue) + clearBits = clearBits & negate(int(callValue)) + + # estimate allBits by using the highest bit we have seen + # TODO dump more precise information about the allBits values of enums + allBits = (1 << setBits.bit_length()) - 1 + clearBits = clearBits & allBits + if continue_flag or (setBits == 0 and clearBits == 0): continue + + sourceLoc = callInfo[4] + functionSig = callInfo[0] + " " + callInfo[1] + + v2 = callInfo[3] + " " + callInfo[2] + if setBits != 0: v2 += " setBits=" + hex(setBits) + if clearBits != 0: v2 += " clearBits=" + hex(clearBits) + tmp2list.append((sourceLoc, functionSig, v2)) + + +# sort results by filename:lineno +tmp2list.sort(key=lambda v: v_sort_key(v)) + +# print out the results +with open("compilerplugins/clang/constantparam.bitmask.results", "wt") as f: + for v in tmp2list: + f.write(v[0] + "\n") + f.write(" " + v[1] + "\n") + f.write(" " + v[2] + "\n") diff --git a/compilerplugins/clang/constfields.cxx b/compilerplugins/clang/constfields.cxx new file mode 100644 index 000000000..692c84dae --- /dev/null +++ b/compilerplugins/clang/constfields.cxx @@ -0,0 +1,596 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if !defined _WIN32 //TODO, #include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config_clang.h" + +#include "plugin.hxx" +#include "check.hxx" + +#include "clang/AST/ParentMapContext.h" + +/** +Look for fields that are only assigned to in the constructor using field-init, and can therefore be const. + +The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='constfields' check + $ ./compilerplugins/clang/constfields.py + +and then + $ for dir in *; do make $dir FORCE_COMPILE=all UPDATE_FILES=$dir COMPILER_PLUGIN_TOOL='constfieldsrewrite' $dir; done +to auto-remove the method declarations + +*/ + +namespace +{ +struct MyFieldInfo +{ + const RecordDecl* parentRecord; + std::string parentClass; + std::string fieldName; + std::string fieldType; + std::string sourceLocation; + std::string access; +}; +bool operator<(const MyFieldInfo& lhs, const MyFieldInfo& rhs) +{ + return std::tie(lhs.parentClass, lhs.fieldName) < std::tie(rhs.parentClass, rhs.fieldName); +} + +// try to limit the voluminous output a little +static std::set cannotBeConstSet; +static std::set definitionSet; + +/** + * Wrap the different kinds of callable and callee objects in the clang AST so I can define methods that handle everything. + */ +class CallerWrapper +{ + const CallExpr* m_callExpr; + const CXXConstructExpr* m_cxxConstructExpr; + +public: + CallerWrapper(const CallExpr* callExpr) + : m_callExpr(callExpr) + , m_cxxConstructExpr(nullptr) + { + } + CallerWrapper(const CXXConstructExpr* cxxConstructExpr) + : m_callExpr(nullptr) + , m_cxxConstructExpr(cxxConstructExpr) + { + } + unsigned getNumArgs() const + { + return m_callExpr ? m_callExpr->getNumArgs() : m_cxxConstructExpr->getNumArgs(); + } + const Expr* getArg(unsigned i) const + { + return m_callExpr ? m_callExpr->getArg(i) : m_cxxConstructExpr->getArg(i); + } +}; +class CalleeWrapper +{ + const FunctionDecl* m_calleeFunctionDecl = nullptr; + const CXXConstructorDecl* m_cxxConstructorDecl = nullptr; + const FunctionProtoType* m_functionPrototype = nullptr; + +public: + explicit CalleeWrapper(const FunctionDecl* calleeFunctionDecl) + : m_calleeFunctionDecl(calleeFunctionDecl) + { + } + explicit CalleeWrapper(const CXXConstructExpr* cxxConstructExpr) + : m_cxxConstructorDecl(cxxConstructExpr->getConstructor()) + { + } + explicit CalleeWrapper(const FunctionProtoType* functionPrototype) + : m_functionPrototype(functionPrototype) + { + } + unsigned getNumParams() const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getNumParams(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getNumParams(); + else if (m_functionPrototype->param_type_begin() == m_functionPrototype->param_type_end()) + // FunctionProtoType will assert if we call getParamTypes() and it has no params + return 0; + else + return m_functionPrototype->getParamTypes().size(); + } + const QualType getParamType(unsigned i) const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getParamDecl(i)->getType(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getParamDecl(i)->getType(); + else + return m_functionPrototype->getParamTypes()[i]; + } + std::string getNameAsString() const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getNameAsString(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getNameAsString(); + else + return ""; + } + CXXMethodDecl const* getAsCXXMethodDecl() const + { + if (m_calleeFunctionDecl) + return dyn_cast(m_calleeFunctionDecl); + return nullptr; + } +}; + +class ConstFields : public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit ConstFields(loplugin::InstantiationData const& data) + : Plugin(data) + { + } + + virtual void run() override; + + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitFieldDecl(const FieldDecl*); + bool VisitMemberExpr(const MemberExpr*); + bool TraverseCXXConstructorDecl(CXXConstructorDecl*); + bool TraverseCXXMethodDecl(CXXMethodDecl*); + bool TraverseFunctionDecl(FunctionDecl*); + bool TraverseIfStmt(IfStmt*); + +private: + MyFieldInfo niceName(const FieldDecl*); + void check(const FieldDecl* fieldDecl, const Expr* memberExpr); + bool isSomeKindOfZero(const Expr* arg); + bool IsPassedByNonConst(const FieldDecl* fieldDecl, const Stmt* child, CallerWrapper callExpr, + CalleeWrapper calleeFunctionDecl); + llvm::Optional getCallee(CallExpr const*); + + RecordDecl* insideMoveOrCopyDeclParent = nullptr; + // For reasons I do not understand, parentFunctionDecl() is not reliable, so + // we store the parent function on the way down the AST. + FunctionDecl* insideFunctionDecl = nullptr; + std::vector insideConditionalCheckOfMemberSet; +}; + +void ConstFields::run() +{ + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + if (!isUnitTestMode()) + { + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + std::string output; + for (const MyFieldInfo& s : cannotBeConstSet) + output += "write-outside-constructor:\t" + s.parentClass + "\t" + s.fieldName + "\n"; + for (const MyFieldInfo& s : definitionSet) + output += "definition:\t" + s.access + "\t" + s.parentClass + "\t" + s.fieldName + "\t" + + s.fieldType + "\t" + s.sourceLocation + "\n"; + std::ofstream myfile; + myfile.open(WORKDIR "/loplugin.constfields.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + else + { + for (const MyFieldInfo& s : cannotBeConstSet) + report(DiagnosticsEngine::Warning, "notconst %0", s.parentRecord->getBeginLoc()) + << s.fieldName; + } +} + +MyFieldInfo ConstFields::niceName(const FieldDecl* fieldDecl) +{ + MyFieldInfo aInfo; + + const RecordDecl* recordDecl = fieldDecl->getParent(); + + if (const CXXRecordDecl* cxxRecordDecl = dyn_cast(recordDecl)) + { + if (cxxRecordDecl->getTemplateInstantiationPattern()) + cxxRecordDecl = cxxRecordDecl->getTemplateInstantiationPattern(); + aInfo.parentRecord = cxxRecordDecl; + aInfo.parentClass = cxxRecordDecl->getQualifiedNameAsString(); + } + else + { + aInfo.parentRecord = recordDecl; + aInfo.parentClass = recordDecl->getQualifiedNameAsString(); + } + + aInfo.fieldName = fieldDecl->getNameAsString(); + // sometimes the name (if it's an anonymous thing) contains the full path of the build folder, which we don't need + size_t idx = aInfo.fieldName.find(SRCDIR); + if (idx != std::string::npos) + { + aInfo.fieldName = aInfo.fieldName.replace(idx, strlen(SRCDIR), ""); + } + aInfo.fieldType = fieldDecl->getType().getAsString(); + + SourceLocation expansionLoc + = compiler.getSourceManager().getExpansionLoc(fieldDecl->getLocation()); + StringRef name = getFilenameOfLocation(expansionLoc); + aInfo.sourceLocation + = std::string(name.substr(strlen(SRCDIR) + 1)) + ":" + + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(aInfo.sourceLocation); + + switch (fieldDecl->getAccess()) + { + case AS_public: + aInfo.access = "public"; + break; + case AS_private: + aInfo.access = "private"; + break; + case AS_protected: + aInfo.access = "protected"; + break; + default: + aInfo.access = "unknown"; + break; + } + + return aInfo; +} + +bool ConstFields::VisitFieldDecl(const FieldDecl* fieldDecl) +{ + fieldDecl = fieldDecl->getCanonicalDecl(); + if (ignoreLocation(fieldDecl)) + { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocation()))) + { + return true; + } + definitionSet.insert(niceName(fieldDecl)); + return true; +} + +bool ConstFields::TraverseCXXConstructorDecl(CXXConstructorDecl* cxxConstructorDecl) +{ + auto copy = insideMoveOrCopyDeclParent; + if (!ignoreLocation(cxxConstructorDecl) && cxxConstructorDecl->isThisDeclarationADefinition()) + { + if (cxxConstructorDecl->isCopyOrMoveConstructor()) + insideMoveOrCopyDeclParent = cxxConstructorDecl->getParent(); + } + bool ret = RecursiveASTVisitor::TraverseCXXConstructorDecl(cxxConstructorDecl); + insideMoveOrCopyDeclParent = copy; + return ret; +} + +bool ConstFields::TraverseCXXMethodDecl(CXXMethodDecl* cxxMethodDecl) +{ + auto copy1 = insideMoveOrCopyDeclParent; + auto copy2 = insideFunctionDecl; + if (!ignoreLocation(cxxMethodDecl) && cxxMethodDecl->isThisDeclarationADefinition()) + { + if (cxxMethodDecl->isCopyAssignmentOperator() || cxxMethodDecl->isMoveAssignmentOperator()) + insideMoveOrCopyDeclParent = cxxMethodDecl->getParent(); + } + insideFunctionDecl = cxxMethodDecl; + bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl); + insideMoveOrCopyDeclParent = copy1; + insideFunctionDecl = copy2; + return ret; +} + +bool ConstFields::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + auto copy2 = insideFunctionDecl; + insideFunctionDecl = functionDecl; + bool ret = RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); + insideFunctionDecl = copy2; + return ret; +} + +bool ConstFields::TraverseIfStmt(IfStmt* ifStmt) +{ + FieldDecl const* memberFieldDecl = nullptr; + if (Expr const* cond = ifStmt->getCond()) + { + if (auto memberExpr = dyn_cast(cond->IgnoreParenImpCasts())) + { + if ((memberFieldDecl = dyn_cast(memberExpr->getMemberDecl()))) + insideConditionalCheckOfMemberSet.push_back(memberFieldDecl); + } + } + bool ret = RecursiveASTVisitor::TraverseIfStmt(ifStmt); + if (memberFieldDecl) + insideConditionalCheckOfMemberSet.pop_back(); + return ret; +} + +bool ConstFields::VisitMemberExpr(const MemberExpr* memberExpr) +{ + const ValueDecl* decl = memberExpr->getMemberDecl(); + const FieldDecl* fieldDecl = dyn_cast(decl); + if (!fieldDecl) + { + return true; + } + fieldDecl = fieldDecl->getCanonicalDecl(); + if (ignoreLocation(fieldDecl)) + { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocation()))) + { + return true; + } + + check(fieldDecl, memberExpr); + + return true; +} + +void ConstFields::check(const FieldDecl* fieldDecl, const Expr* memberExpr) +{ + auto parentsRange = compiler.getASTContext().getParents(*memberExpr); + const Stmt* child = memberExpr; + const Stmt* parent + = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get(); + // walk up the tree until we find something interesting + bool bCannotBeConst = false; + bool bDump = false; + auto walkUp = [&]() { + child = parent; + auto parentsRange = compiler.getASTContext().getParents(*parent); + parent = parentsRange.begin() == parentsRange.end() ? nullptr + : parentsRange.begin()->get(); + }; + do + { + if (!parent) + { + // check if we have an expression like + // int& r = m_field; + auto parentsRange = compiler.getASTContext().getParents(*child); + if (parentsRange.begin() != parentsRange.end()) + { + auto varDecl = dyn_cast_or_null(parentsRange.begin()->get()); + // The isImplicit() call is to avoid triggering when we see the vardecl which is part of a for-range statement, + // which is of type 'T&&' and also an l-value-ref ? + if (varDecl && !varDecl->isImplicit() + && loplugin::TypeCheck(varDecl->getType()).LvalueReference().NonConst()) + { + bCannotBeConst = true; + } + } + break; + } + if (isa(parent)) + { + // once we see one of these, there is not much useful we can know + bCannotBeConst = true; + break; + } + else if (isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent)) + { + walkUp(); + } + else if (auto unaryOperator = dyn_cast(parent)) + { + UnaryOperator::Opcode op = unaryOperator->getOpcode(); + if (op == UO_AddrOf || op == UO_PostInc || op == UO_PostDec || op == UO_PreInc + || op == UO_PreDec) + { + bCannotBeConst = true; + } + walkUp(); + } + else if (auto operatorCallExpr = dyn_cast(parent)) + { + auto callee = getCallee(operatorCallExpr); + if (callee) + { + // if calling a non-const operator on the field + auto calleeMethodDecl = callee->getAsCXXMethodDecl(); + if (calleeMethodDecl && operatorCallExpr->getArg(0) == child + && !calleeMethodDecl->isConst()) + { + bCannotBeConst = true; + } + else if (IsPassedByNonConst(fieldDecl, child, operatorCallExpr, *callee)) + { + bCannotBeConst = true; + } + } + else + bCannotBeConst = true; // conservative, could improve + walkUp(); + } + else if (auto cxxMemberCallExpr = dyn_cast(parent)) + { + const CXXMethodDecl* calleeMethodDecl = cxxMemberCallExpr->getMethodDecl(); + if (calleeMethodDecl) + { + // if calling a non-const method on the field + const Expr* tmp = dyn_cast(child); + if (tmp->isBoundMemberFunction(compiler.getASTContext())) + { + tmp = dyn_cast(tmp)->getBase(); + } + if (cxxMemberCallExpr->getImplicitObjectArgument() == tmp + && !calleeMethodDecl->isConst()) + { + bCannotBeConst = true; + break; + } + if (IsPassedByNonConst(fieldDecl, child, cxxMemberCallExpr, + CalleeWrapper(calleeMethodDecl))) + bCannotBeConst = true; + } + else + bCannotBeConst = true; // can happen in templates + walkUp(); + } + else if (auto cxxConstructExpr = dyn_cast(parent)) + { + if (IsPassedByNonConst(fieldDecl, child, cxxConstructExpr, + CalleeWrapper(cxxConstructExpr))) + bCannotBeConst = true; + walkUp(); + } + else if (auto callExpr = dyn_cast(parent)) + { + auto callee = getCallee(callExpr); + if (callee) + { + if (IsPassedByNonConst(fieldDecl, child, callExpr, *callee)) + bCannotBeConst = true; + } + else + bCannotBeConst = true; // conservative, could improve + walkUp(); + } + else if (auto binaryOp = dyn_cast(parent)) + { + BinaryOperator::Opcode op = binaryOp->getOpcode(); + const bool assignmentOp = op == BO_Assign || op == BO_MulAssign || op == BO_DivAssign + || op == BO_RemAssign || op == BO_AddAssign + || op == BO_SubAssign || op == BO_ShlAssign + || op == BO_ShrAssign || op == BO_AndAssign + || op == BO_XorAssign || op == BO_OrAssign; + if (assignmentOp) + { + if (binaryOp->getLHS() == child) + bCannotBeConst = true; + else if (loplugin::TypeCheck(binaryOp->getLHS()->getType()) + .LvalueReference() + .NonConst()) + // if the LHS is a non-const reference, we could write to the field later on + bCannotBeConst = true; + } + walkUp(); + } + else if (isa(parent)) + { + if (insideFunctionDecl) + { + auto tc = loplugin::TypeCheck(insideFunctionDecl->getReturnType()); + if (tc.LvalueReference().NonConst()) + bCannotBeConst = true; + } + break; + } + else if (isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) || isa(parent) + || isa(parent)) + { + break; + } + else + { + walkUp(); + } + } while (true); + + if (bDump) + { + report(DiagnosticsEngine::Warning, "oh dear, what can the matter be? writtenTo=%0", + memberExpr->getBeginLoc()) + << bCannotBeConst << memberExpr->getSourceRange(); + if (parent) + { + report(DiagnosticsEngine::Note, "parent over here", parent->getBeginLoc()) + << parent->getSourceRange(); + parent->dump(); + } + memberExpr->dump(); + fieldDecl->getType()->dump(); + } + + if (bCannotBeConst) + { + cannotBeConstSet.insert(niceName(fieldDecl)); + } +} + +bool ConstFields::IsPassedByNonConst(const FieldDecl* fieldDecl, const Stmt* child, + CallerWrapper callExpr, CalleeWrapper calleeFunctionDecl) +{ + unsigned len = std::min(callExpr.getNumArgs(), calleeFunctionDecl.getNumParams()); + // if it's an array, passing it by value to a method typically means the + // callee takes a pointer and can modify the array + if (fieldDecl->getType()->isConstantArrayType()) + { + for (unsigned i = 0; i < len; ++i) + if (callExpr.getArg(i) == child) + if (loplugin::TypeCheck(calleeFunctionDecl.getParamType(i)).Pointer().NonConst()) + return true; + } + else + { + for (unsigned i = 0; i < len; ++i) + if (callExpr.getArg(i) == child) + if (loplugin::TypeCheck(calleeFunctionDecl.getParamType(i)) + .LvalueReference() + .NonConst()) + return true; + } + return false; +} + +llvm::Optional ConstFields::getCallee(CallExpr const* callExpr) +{ + FunctionDecl const* functionDecl = callExpr->getDirectCallee(); + if (functionDecl) + return CalleeWrapper(functionDecl); + + // Extract the functionprototype from a type + clang::Type const* calleeType = callExpr->getCallee()->getType().getTypePtr(); + if (auto pointerType = calleeType->getUnqualifiedDesugaredType()->getAs()) + { + if (auto prototype = pointerType->getPointeeType() + ->getUnqualifiedDesugaredType() + ->getAs()) + { + return CalleeWrapper(prototype); + } + } + + return llvm::Optional(); +} + +loplugin::Plugin::Registration X("constfields", false); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/constfields.py b/compilerplugins/clang/constfields.py new file mode 100755 index 000000000..e81d3f304 --- /dev/null +++ b/compilerplugins/clang/constfields.py @@ -0,0 +1,87 @@ +#!/usr/bin/python + +import sys +import re +import io + +definitionSet = set() +definitionToSourceLocationMap = dict() +definitionToTypeMap = dict() +writeFromOutsideConstructorSet = set() + +# clang does not always use exactly the same numbers in the type-parameter vars it generates +# so I need to substitute them to ensure we can match correctly. +normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") +def normalizeTypeParams( line ): + return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) + +def parseFieldInfo( tokens ): + if len(tokens) == 3: + return (normalizeTypeParams(tokens[1]), tokens[2]) + else: + return (normalizeTypeParams(tokens[1]), "") + +with io.open("workdir/loplugin.constfields.log", "rb", buffering=1024*1024) as txt: + for line in txt: + tokens = line.strip().split("\t") + if tokens[0] == "definition:": + access = tokens[1] + fieldInfo = (normalizeTypeParams(tokens[2]), tokens[3]) + srcLoc = tokens[5] + # ignore external source code + if (srcLoc.startswith("external/")): + continue + # ignore build folder + if (srcLoc.startswith("workdir/")): + continue + definitionSet.add(fieldInfo) + definitionToTypeMap[fieldInfo] = tokens[4] + definitionToSourceLocationMap[fieldInfo] = tokens[5] + elif tokens[0] == "write-outside-constructor:": + writeFromOutsideConstructorSet.add(parseFieldInfo(tokens)) + else: + print( "unknown line: " + line) + +# Calculate can-be-const-field set +canBeConstFieldSet = set() +for d in definitionSet: + if d in writeFromOutsideConstructorSet: + continue + srcLoc = definitionToSourceLocationMap[d]; + fieldType = definitionToTypeMap[d] + if fieldType.startswith("const "): + continue + if "std::unique_ptr" in fieldType: + continue + if "std::shared_ptr" in fieldType: + continue + if "Reference<" in fieldType: + continue + if "VclPtr<" in fieldType: + continue + if "osl::Mutex" in fieldType: + continue + if "::sfx2::sidebar::ControllerItem" in fieldType: + continue + canBeConstFieldSet.add((d[0] + " " + d[1] + " " + fieldType, srcLoc)) + + +# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[1]) + [v[0]] + +# sort results by name and line number +tmp6list = sorted(canBeConstFieldSet, key=lambda v: v_sort_key(v)) + +# print out the results +with open("compilerplugins/clang/constfields.results", "wt") as f: + for t in tmp6list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) + + diff --git a/compilerplugins/clang/constfieldsrewrite.cxx b/compilerplugins/clang/constfieldsrewrite.cxx new file mode 100644 index 000000000..d72bb43aa --- /dev/null +++ b/compilerplugins/clang/constfieldsrewrite.cxx @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if !defined _WIN32 //TODO, #include + +#include +#include +#include +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include +#include +#include +#include +#include +#include +#include + +/** + This is intended to be run as the second stage of the "constfields" clang plugin. +*/ + +namespace +{ +class ConstFieldsRewrite : public RecursiveASTVisitor, + public loplugin::RewritePlugin +{ +public: + explicit ConstFieldsRewrite(loplugin::InstantiationData const& data); + ~ConstFieldsRewrite(); + + virtual void run() override + { + if (rewriter) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitFieldDecl(const FieldDecl* var); + +private: + // I use a brute-force approach - mmap the results file and do a linear search on it + // It works surprisingly well, because the file is small enough to fit into L2 cache on modern CPU's + size_t mmapFilesize; + int mmapFD; + char* mmappedData; +}; + +size_t getFilesize(const char* filename) +{ + struct stat st; + stat(filename, &st); + return st.st_size; +} + +ConstFieldsRewrite::ConstFieldsRewrite(loplugin::InstantiationData const& data) + : RewritePlugin(data) +{ + static const char sInputFile[] = SRCDIR "/compilerplugins/clang/constfields.results"; + mmapFilesize = getFilesize(sInputFile); + //Open file + mmapFD = open(sInputFile, O_RDONLY, 0); + assert(mmapFD != -1); + //Execute mmap + mmappedData = static_cast(mmap(NULL, mmapFilesize, PROT_READ, MAP_PRIVATE, mmapFD, 0)); + assert(mmappedData != NULL); +} + +ConstFieldsRewrite::~ConstFieldsRewrite() +{ + //Cleanup + int rc = munmap(mmappedData, mmapFilesize); + assert(rc == 0); + (void)rc; + close(mmapFD); +} + +bool ConstFieldsRewrite::VisitFieldDecl(const FieldDecl* fieldDecl) +{ + if (ignoreLocation(fieldDecl)) + return true; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( + fieldDecl->getCanonicalDecl()->getLocation()))) + return true; + // in case we've already processed this field + if (fieldDecl->getType().isConstQualified()) + return true; + // TODO rewriting T& is a bit trickier + if (loplugin::TypeCheck(fieldDecl->getType()).LvalueReference()) + return true; + + const RecordDecl* recordDecl = fieldDecl->getParent(); + std::string parentClassName; + if (const CXXRecordDecl* cxxRecordDecl = dyn_cast(recordDecl)) + { + if (cxxRecordDecl->getTemplateInstantiationPattern()) + cxxRecordDecl = cxxRecordDecl->getTemplateInstantiationPattern(); + parentClassName = cxxRecordDecl->getQualifiedNameAsString(); + } + else + { + parentClassName = recordDecl->getQualifiedNameAsString(); + } + // the extra spaces match the formatting in the results file, and help avoid false+ + std::string aNiceName = " " + parentClassName + " " + fieldDecl->getNameAsString() + " " + + fieldDecl->getType().getAsString() + "\n"; + + // search mmap'ed file for field + const char* aNiceNameStr = aNiceName.c_str(); + char* found = std::search(mmappedData, mmappedData + mmapFilesize, aNiceNameStr, + aNiceNameStr + aNiceName.size()); + if (!(found < mmappedData + mmapFilesize)) + return true; + + SourceManager& SM = compiler.getSourceManager(); + auto endLoc = fieldDecl->getTypeSourceInfo()->getTypeLoc().getEndLoc(); + endLoc = endLoc.getLocWithOffset(Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts())); + + // Calculate how much space is available after the type declaration that we can use to + // overwrite with the " const". This reduces the amount of formatting fixups I need to do. + char const* p1 = SM.getCharacterData(endLoc); + bool success = false; + if (*p1 != ' ') + { + // Sometimes there is no space at all e.g. in + // FastTokenHandlerBase *mpTokenHandler; + // between the "*" and the "mpTokenHandler", so add an extra space. + success = insertText(endLoc, " const "); + } + else + { + int spaceAvailable = 1; + ++p1; + for (; spaceAvailable < 6; ++spaceAvailable) + { + if (*p1 != ' ') + break; + ++p1; + } + if (spaceAvailable < 6) + success = replaceText(endLoc, spaceAvailable - 1, " const"); + else + success = replaceText(endLoc, spaceAvailable, " const"); + } + + if (!success) + { + report(DiagnosticsEngine::Warning, "Could not mark field as const", + fieldDecl->getBeginLoc()) + << fieldDecl->getSourceRange(); + } + return true; +} + +loplugin::Plugin::Registration X("constfieldsrewrite", false); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/constmethod.cxx b/compilerplugins/clang/constmethod.cxx new file mode 100644 index 000000000..bd9c4db18 --- /dev/null +++ b/compilerplugins/clang/constmethod.cxx @@ -0,0 +1,563 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "config_clang.h" + +#include "plugin.hxx" +#include "check.hxx" +#include "functionaddress.hxx" + +#include "clang/AST/ParentMapContext.h" + +/** + Find methods that can be declared const. + + This analysis attempts to implement "logical const" as opposed to "technical const", which means + we ignore always-const nature of std::unique_ptr::operator-> + + This is not a sophisticated analysis. It deliberately skips all of the hard cases for now. + It is an exercise in getting the most benefit for the least effort. +*/ +namespace +{ + +class ConstMethod: + public loplugin::FunctionAddress> +{ +public: + explicit ConstMethod(loplugin::InstantiationData const & data): FunctionAddress(data) {} + + virtual void run() override { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + // things I'm not sure about + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/svl/unx/source/svdde/ddedummy.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/svl/source/numbers/zformat.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/svl/source/numbers/zforscan.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/svl/source/numbers/zforlist.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/source/gdi/impgraph.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/source/image/ImplImage.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/source/filter/wmf/wmfwr.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/unx/generic/app/i18n_im.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/unx/generic/app/randrwrapper.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/unx/gtk3/gtkinst.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/unx/gtk3/gtkframe.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/skia/gdiimpl.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/qt5/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/package/source/xstor/owriteablestream.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/package/source/zippackage/ZipPackage.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/toolkit/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/canvas/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/accessibility/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/framework/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/basic/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/sfx2/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/xmloff/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/connectivity/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/editeng/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/scripting/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/ucb/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/svx/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/basctl/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/chart2/") + ) + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + for (const CXXMethodDecl *pMethodDecl : interestingMethodSet) { + if (methodCannotBeConstSet.find(pMethodDecl) != methodCannotBeConstSet.end()) + continue; + auto canonicalDecl = pMethodDecl->getCanonicalDecl(); + if (getFunctionsWithAddressTaken().find((FunctionDecl const *)canonicalDecl) + != getFunctionsWithAddressTaken().end()) + continue; + // things that I don't think should be logically const + std::string fqn = pMethodDecl->getQualifiedNameAsString(); + if (fqn == "comphelper::EmbeddedObjectContainer::CommitImageSubStorage" + || fqn == "SvtLinguConfig::SetProperty" + || fqn == "SvtLinguConfig::ReplaceSetProperties" + || fqn == "SystemWindow::UpdatePositionData" + || fqn == "OutputDevice::SelectClipRegion" + || fqn == "OutputDevice::BlendBitmap") + continue; + StringRef aFileName = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(canonicalDecl->getBeginLoc())); + // leave the kit API alone + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/LibreOfficeKit/LibreOfficeKit.hxx")) + continue; + // don't feel like touching this right now + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/vcl/weld.hxx")) + continue; + report( + DiagnosticsEngine::Warning, + "this method can be const", + pMethodDecl->getBeginLoc()) + << pMethodDecl->getSourceRange(); + if (canonicalDecl->getLocation() != pMethodDecl->getLocation()) { + report( + DiagnosticsEngine::Note, + "canonical method declaration here", + canonicalDecl->getBeginLoc()) + << canonicalDecl->getSourceRange(); + } + } + } + + bool TraverseCXXMethodDecl(CXXMethodDecl *); + bool TraverseCXXConversionDecl(CXXConversionDecl *); + bool VisitCXXMethodDecl(const CXXMethodDecl *); + bool VisitCXXThisExpr(const CXXThisExpr *); + +private: + bool isPointerOrReferenceToConst(const QualType& qt); + bool isPointerOrReferenceToNonConst(const QualType& qt); + bool checkIfCanBeConst(const Stmt*, const CXXMethodDecl*); + + std::unordered_set interestingMethodSet; + std::unordered_set methodCannotBeConstSet; + CXXMethodDecl const * currCXXMethodDecl; +}; + +bool ConstMethod::TraverseCXXMethodDecl(CXXMethodDecl * cxxMethodDecl) +{ + currCXXMethodDecl = cxxMethodDecl; + bool rv = RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl); + currCXXMethodDecl = nullptr; + return rv; +} + +bool ConstMethod::TraverseCXXConversionDecl(CXXConversionDecl * cxxConversionDecl) +{ + currCXXMethodDecl = cxxConversionDecl; + bool rv = RecursiveASTVisitor::TraverseCXXConversionDecl(cxxConversionDecl); + currCXXMethodDecl = nullptr; + return rv; +} + +bool ConstMethod::VisitCXXMethodDecl(const CXXMethodDecl * cxxMethodDecl) +{ + if (ignoreLocation(cxxMethodDecl) || !cxxMethodDecl->isThisDeclarationADefinition()) { + return true; + } + if (cxxMethodDecl->isConst()) + return true; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(cxxMethodDecl)) { + return true; + } + // TODO ignore template stuff for now + if (cxxMethodDecl->getTemplatedKind() != FunctionDecl::TK_NonTemplate) { + return true; + } + if (cxxMethodDecl->isDeleted()) + return true; + if (cxxMethodDecl->isStatic()) + return true; + if (cxxMethodDecl->isOverloadedOperator()) + return true; + if (isa(cxxMethodDecl)) + return true; + if (isa(cxxMethodDecl)) + return true; + if (cxxMethodDecl->getParent()->getDescribedClassTemplate() != nullptr ) { + return true; + } + // ignore virtual methods + if (cxxMethodDecl->isVirtual() ) { + return true; + } + // ignore macro expansions so we can ignore the IMPL_LINK macros from include/tools/link.hxx + // TODO make this more precise + if (cxxMethodDecl->getLocation().isMacroID()) + return true; + + if (!cxxMethodDecl->getIdentifier()) + return true; +// if (cxxMethodDecl->getNumParams() > 0) +// return true; + // returning pointers or refs to non-const stuff, and then having the whole method + // be const doesn't seem like a good idea + auto tc = loplugin::TypeCheck(cxxMethodDecl->getReturnType()); + if (tc.Pointer().NonConst()) + return true; + if (tc.LvalueReference().NonConst()) + return true; + // a Get method that returns void is probably doing something that has side-effects + if (tc.Void()) + return true; + +// StringRef name = cxxMethodDecl->getName(); +// if (!name.startswith("get") && !name.startswith("Get") +// && !name.startswith("is") && !name.startswith("Is") +// && !name.startswith("has") && !name.startswith("Has")) +// return true; + + // something lacking in my analysis here + if (loplugin::DeclCheck(cxxMethodDecl).Function("GetDescr").Class("SwRangeRedline").GlobalNamespace()) + return true; + + interestingMethodSet.insert(cxxMethodDecl); + + return true; +} + +bool ConstMethod::VisitCXXThisExpr( const CXXThisExpr* cxxThisExpr ) +{ + if (!currCXXMethodDecl) + return true; + if (ignoreLocation(cxxThisExpr)) + return true; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(cxxThisExpr->getBeginLoc())) + return true; + if (interestingMethodSet.find(currCXXMethodDecl) == interestingMethodSet.end()) + return true; + // no need to check again if we have already eliminated this one + if (methodCannotBeConstSet.find(currCXXMethodDecl) != methodCannotBeConstSet.end()) + return true; + if (!checkIfCanBeConst(cxxThisExpr, currCXXMethodDecl)) + methodCannotBeConstSet.insert(currCXXMethodDecl); + + return true; +} + +// Walk up from a statement that contains a CXXThisExpr, checking if the usage means that the +// related CXXMethodDecl can be const. +bool ConstMethod::checkIfCanBeConst(const Stmt* stmt, const CXXMethodDecl* cxxMethodDecl) +{ + const Stmt* parent = getParentStmt( stmt ); + if (!parent) { + auto parentsRange = compiler.getASTContext().getParents(*stmt); + if ( parentsRange.begin() == parentsRange.end()) + return true; + auto varDecl = dyn_cast_or_null(parentsRange.begin()->get()); + if (!varDecl) + { + report( + DiagnosticsEngine::Warning, + "no parent?", + stmt->getBeginLoc()) + << stmt->getSourceRange(); + return false; + } + return varDecl->getType()->isIntegralOrEnumerationType() + || loplugin::TypeCheck(varDecl->getType()).Pointer().Const() + || loplugin::TypeCheck(varDecl->getType()).LvalueReference().Const(); + } + + if (auto unaryOperator = dyn_cast(parent)) { + UnaryOperator::Opcode op = unaryOperator->getOpcode(); + if (op == UO_PreInc || op == UO_PostInc + || op == UO_PreDec || op == UO_PostDec) { + return false; + } + if (op == UO_Deref || op == UO_AddrOf) { + return checkIfCanBeConst(parent, cxxMethodDecl); + } + return true; + } else if (auto binaryOp = dyn_cast(parent)) { + BinaryOperator::Opcode op = binaryOp->getOpcode(); + if (binaryOp->getRHS() == stmt) { + return true; + } + if (op == BO_Assign || op == BO_PtrMemD || op == BO_PtrMemI || op == BO_MulAssign + || op == BO_DivAssign || op == BO_RemAssign || op == BO_AddAssign + || op == BO_SubAssign || op == BO_ShlAssign || op == BO_ShrAssign + || op == BO_AndAssign || op == BO_XorAssign || op == BO_OrAssign) { + return false; + } +// // for pointer arithmetic need to check parent +// if (binaryOp->getType()->isPointerType()) { +// return checkIfCanBeConst(parent, cxxMethodDecl); +// } + return true; + } else if (auto constructExpr = dyn_cast(parent)) { + const CXXConstructorDecl * constructorDecl = constructExpr->getConstructor(); + for (unsigned i = 0; i < constructExpr->getNumArgs(); ++i) { + if (constructExpr->getArg(i) == stmt) { + return isPointerOrReferenceToConst(constructorDecl->getParamDecl(i)->getType()); + } + } + return false; // TODO ?? + } else if (auto operatorCallExpr = dyn_cast(parent)) { + const CXXMethodDecl* calleeMethodDecl = dyn_cast_or_null(operatorCallExpr->getDirectCallee()); + if (calleeMethodDecl) { + // unary operator + if (calleeMethodDecl->getNumParams() == 0) { + // some classes like std::unique_ptr do not do a very good job with their operator-> which is always const + if (operatorCallExpr->getOperator() == OO_Arrow || operatorCallExpr->getOperator() == OO_Star) { + return checkIfCanBeConst(parent, cxxMethodDecl); + } + return calleeMethodDecl->isConst(); + } + // some classes like std::unique_ptr do not do a very good job with their operator[] which is always const + if (calleeMethodDecl->getNumParams() == 1 && operatorCallExpr->getArg(0) == stmt) { + if (operatorCallExpr->getOperator() == OO_Subscript) { + return false; + } + } + // binary operator + if (operatorCallExpr->getArg(0) == stmt) { + return calleeMethodDecl->isConst(); + } + unsigned const n = std::min( + operatorCallExpr->getNumArgs(), + calleeMethodDecl->getNumParams()); + for (unsigned i = 1; i < n; ++i) + if (operatorCallExpr->getArg(i) == stmt) { + return isPointerOrReferenceToConst(calleeMethodDecl->getParamDecl(i - 1)->getType()); + } + } else { + const Expr* callee = operatorCallExpr->getCallee()->IgnoreParenImpCasts(); + const DeclRefExpr* dr = dyn_cast(callee); + const FunctionDecl* calleeFunctionDecl = nullptr; + if (dr) { + calleeFunctionDecl = dyn_cast(dr->getDecl()); + } + if (calleeFunctionDecl) { + for (unsigned i = 0; i < operatorCallExpr->getNumArgs(); ++i) { + if (operatorCallExpr->getArg(i) == stmt) { + return isPointerOrReferenceToConst(calleeFunctionDecl->getParamDecl(i)->getType()); + } + } + } + } + return false; // TODO ??? + } else if (auto callExpr = dyn_cast(parent)) { + QualType functionType = callExpr->getCallee()->getType(); + if (functionType->isFunctionPointerType()) { + functionType = functionType->getPointeeType(); + } + if (const FunctionProtoType* prototype = functionType->getAs()) { + // TODO could do better + if (prototype->isVariadic()) { + return false; + } + if (callExpr->getCallee() == stmt) { + return true; + } + for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) { + if (callExpr->getArg(i) == stmt) { + return isPointerOrReferenceToConst(prototype->getParamType(i)); + } + } + } + const FunctionDecl* calleeFunctionDecl = callExpr->getDirectCallee(); + if (calleeFunctionDecl) + { + if (auto memberCallExpr = dyn_cast(parent)) { + const MemberExpr* memberExpr = dyn_cast(stmt); + if (memberExpr && memberCallExpr->getImplicitObjectArgument() == memberExpr->getBase()) + { + const CXXMethodDecl* calleeMethodDecl = dyn_cast(calleeFunctionDecl); + // some classes like std::unique_ptr do not do a very good job with their get() which is always const + if (calleeMethodDecl->getIdentifier() && calleeMethodDecl->getName() == "get") { + return checkIfCanBeConst(parent, cxxMethodDecl); + } + // VclPtr's implicit conversion to T* + if (isa(calleeMethodDecl)) { + if (loplugin::DeclCheck(calleeMethodDecl->getParent()).Class("OWeakObject").Namespace("cppu").GlobalNamespace()) + return false; + return checkIfCanBeConst(parent, cxxMethodDecl); + } + return calleeMethodDecl->isConst(); + } + } + // TODO could do better + if (calleeFunctionDecl->isVariadic()) { + return false; + } + if (callExpr->getCallee() == stmt) { + return true; + } + for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) { + if (i >= calleeFunctionDecl->getNumParams()) // can happen in template code + return false; + if (callExpr->getArg(i) == stmt) { + return isPointerOrReferenceToConst(calleeFunctionDecl->getParamDecl(i)->getType()); + } + } + } + return false; // TODO ???? +// } else if (auto callExpr = dyn_cast(parent)) { +// if (callExpr->getInstanceReceiver() == stmt) { +// return true; +// } +// if (auto const method = callExpr->getMethodDecl()) { +// // TODO could do better +// if (method->isVariadic()) { +// return false; +// } +// assert(method->param_size() == callExpr->getNumArgs()); +// for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) { +// if (callExpr->getArg(i) == stmt) { +// return isPointerOrReferenceToConst( +// method->param_begin()[i]->getType()); +// } +// } +// } +// return false; // TODO ???? + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return checkIfCanBeConst(parent, cxxMethodDecl); + } else if (isa(parent)) { + return checkIfCanBeConst(parent, cxxMethodDecl); + } else if (isa(parent)) { + return checkIfCanBeConst(parent, cxxMethodDecl); + } else if (isa(parent)) { + return checkIfCanBeConst(parent, cxxMethodDecl); + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return checkIfCanBeConst(parent, cxxMethodDecl); +// } else if (isa(parent)) { // all other cast expression subtypes +// if (auto e = dyn_cast(parent)) { +// if (loplugin::TypeCheck(e->getTypeAsWritten()).Void()) { +// if (auto const sub = dyn_cast( +// e->getSubExpr()->IgnoreParenImpCasts())) +// { +// if (sub->getDecl() == cxxMethodDecl) { +// return false; +// } +// } +// } +// } +// return checkIfCanBeConst(parent, cxxMethodDecl); + } else if (isa(parent)) { + return checkIfCanBeConst(parent, cxxMethodDecl); + } else if (auto arraySubscriptExpr = dyn_cast(parent)) { + if (arraySubscriptExpr->getIdx() == stmt) + return true; + return checkIfCanBeConst(parent, cxxMethodDecl); + } else if (isa(parent)) { + return checkIfCanBeConst(parent, cxxMethodDecl); + } else if (auto declStmt = dyn_cast(parent)) { + for (Decl const * decl : declStmt->decls()) + if (auto varDecl = dyn_cast(decl)) { + if (varDecl->getInit() == stmt) { + auto tc = loplugin::TypeCheck(varDecl->getType()); + if (tc.LvalueReference() && !tc.LvalueReference().Const()) + return false; + if (tc.Pointer() && !tc.Pointer().Const()) + return false; + return true; + } + } + // fall through + } else if (isa(parent)) { + return !isPointerOrReferenceToNonConst(cxxMethodDecl->getReturnType()); + } else if (isa(parent)) { + return false; // TODO could be improved + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return false; +// } else if (isa(parent)) { +// return false; + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return checkIfCanBeConst(parent, cxxMethodDecl); + } else if (auto conditionalExpr = dyn_cast(parent)) { + if (conditionalExpr->getCond() == stmt) + return true; + return checkIfCanBeConst(parent, cxxMethodDecl); +// } else if (isa(parent)) { +// return false; // ??? + } else if (isa(parent)) { +// for (auto pa : cxxNewExpr->placement_arguments()) +// if (pa == stmt) +// return false; + return true; // because the Stmt must be a parameter to the expression, probably an array length +// } else if (auto lambdaExpr = dyn_cast(parent)) { +//// for (auto it = lambdaExpr->capture_begin(); it != lambdaExpr->capture_end(); ++it) +//// { +//// if (it->capturesVariable() && it->getCapturedVar() == cxxMethodDecl) +//// return it->getCaptureKind() != LCK_ByRef; +//// } +// return true; +// } else if (isa(parent)) { +// return true; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return false; +// } else if (isa(parent)) { +// return false; +// } else if (isa(parent)) { +// return false; + } else if (isa(parent)) { + return checkIfCanBeConst(parent, cxxMethodDecl); +// } else if (isa(parent)) { +// return true; +// } else if (isa(parent)) { +// return false; +// } else if (isa(parent)) { +// return false; +// } else if (isa(parent)) { +// return checkIfCanBeConst(parent, cxxMethodDecl); + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return true; + } + if (parent) + parent->dump(); +// if (cxxMethodDecl) +// cxxMethodDecl->dump(); + report( + DiagnosticsEngine::Warning, + "oh dear, what can the matter be?", + parent->getBeginLoc()) + << parent->getSourceRange(); + return false; +} + +bool ConstMethod::isPointerOrReferenceToConst(const QualType& qt) { + auto const type = loplugin::TypeCheck(qt); + if (type.Pointer()) { + return bool(type.Pointer().Const()); + } else if (type.LvalueReference()) { + return bool(type.LvalueReference().Const()); + } + return false; +} + +bool ConstMethod::isPointerOrReferenceToNonConst(const QualType& qt) { + auto const type = loplugin::TypeCheck(qt); + if (type.Pointer()) { + return !bool(type.Pointer().Const()); + } else if (type.LvalueReference()) { + return !bool(type.LvalueReference().Const()); + } + return false; +} + +loplugin::Plugin::Registration< ConstMethod > X("constmethod", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/constparams.cxx b/compilerplugins/clang/constparams.cxx new file mode 100644 index 000000000..dac7322d0 --- /dev/null +++ b/compilerplugins/clang/constparams.cxx @@ -0,0 +1,618 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "config_clang.h" + +#include "plugin.hxx" +#include "compat.hxx" +#include "check.hxx" +#include "functionaddress.hxx" + +#include "clang/AST/ParentMapContext.h" + +/** + Find pointer and reference params that can be declared const. + + This is not a sophisticated analysis. It deliberately skips all of the hard cases for now. + It is an exercise in getting the most benefit for the least effort. +*/ +namespace +{ + +class ConstParams: + public loplugin::FunctionAddress> +{ +public: + explicit ConstParams(loplugin::InstantiationData const & data): FunctionAddress(data) {} + + virtual void run() override { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/") + || fn == SRCDIR "/jurt/source/pipe/staticsalhack.cxx" + || loplugin::hasPathnamePrefix(fn, SRCDIR "/bridges/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/binaryurp/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/stoc/") + || loplugin::hasPathnamePrefix(fn, WORKDIR "/YaccTarget/unoidl/source/sourceprovider-parser.cxx") + // some weird calling through a function pointer + || loplugin::hasPathnamePrefix(fn, SRCDIR "/svtools/source/table/defaultinputhandler.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/sdext/source/pdfimport/test/pdfunzip.cxx") + // windows only + || loplugin::hasPathnamePrefix(fn, SRCDIR "/basic/source/sbx/sbxdec.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/sfx2/source/doc/syspath.cxx") + // ignore this for now + || loplugin::hasPathnamePrefix(fn, SRCDIR "/libreofficekit") + // FunctionAddress not working well enough here + || loplugin::hasPathnamePrefix(fn, SRCDIR "/pyuno/source/module/pyuno_struct.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/pyuno/source/module/pyuno.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/filter/ascii/ascatr.cxx") + // TODO this plugin doesn't handle it well when we take the address of a pointer + || loplugin::hasPathnamePrefix(fn, SRCDIR "/svl/source/misc/sharedstringpool.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/registry/source/regkey.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/cppu/source/uno/lbenv.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/cppuhelper/source/implbase_ex.cxx") + ) + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + for (const ParmVarDecl *pParmVarDecl : interestingParamSet) { + auto functionDecl = parmToFunction[pParmVarDecl]; + auto canonicalDecl = functionDecl->getCanonicalDecl(); + if (getFunctionsWithAddressTaken().find(canonicalDecl) + != getFunctionsWithAddressTaken().end()) + { + continue; + } + std::string fname = functionDecl->getQualifiedNameAsString(); + report( + DiagnosticsEngine::Warning, + "this parameter can be const %0", + pParmVarDecl->getBeginLoc()) + << fname << pParmVarDecl->getSourceRange(); + if (canonicalDecl->getLocation() != functionDecl->getLocation()) { + unsigned idx = pParmVarDecl->getFunctionScopeIndex(); + const ParmVarDecl* pOther = canonicalDecl->getParamDecl(idx); + report( + DiagnosticsEngine::Note, + "canonical parameter declaration here", + pOther->getBeginLoc()) + << pOther->getSourceRange(); + } + //functionDecl->dump(); + } + } + + bool TraverseFunctionDecl(FunctionDecl *); + bool TraverseCXXMethodDecl(CXXMethodDecl * f); + bool TraverseCXXConstructorDecl(CXXConstructorDecl * f); + bool VisitDeclRefExpr(const DeclRefExpr *); + bool VisitLambdaExpr(const LambdaExpr*); + +private: + bool CheckTraverseFunctionDecl(FunctionDecl *); + bool checkIfCanBeConst(const Stmt*, const ParmVarDecl*); + // integral or enumeration or const * or const & + bool isOkForParameter(const QualType& qt); + bool isPointerOrReferenceToNonConst(const QualType& qt); + + std::unordered_set interestingParamSet; + std::unordered_map parmToFunction; + FunctionDecl* currentFunctionDecl = nullptr; +}; + +bool ConstParams::TraverseFunctionDecl(FunctionDecl * functionDecl) +{ + // We cannot short-circuit the traverse here entirely without breaking the + // loplugin::FunctionAddress stuff. + auto prev = currentFunctionDecl; + if (CheckTraverseFunctionDecl(functionDecl)) + currentFunctionDecl = functionDecl; + auto rv = FunctionAddress::TraverseFunctionDecl(functionDecl); + currentFunctionDecl = prev; + return rv; +} +bool ConstParams::TraverseCXXMethodDecl(CXXMethodDecl * f) +{ + auto prev = currentFunctionDecl; + if (CheckTraverseFunctionDecl(f)) + currentFunctionDecl = f; + auto rv = FunctionAddress::TraverseCXXMethodDecl(f); + currentFunctionDecl = prev; + return rv; +} +bool ConstParams::TraverseCXXConstructorDecl(CXXConstructorDecl * f) +{ + auto prev = currentFunctionDecl; + if (CheckTraverseFunctionDecl(f)) + currentFunctionDecl = f; + auto rv = FunctionAddress::TraverseCXXConstructorDecl(f); + currentFunctionDecl = prev; + return rv; +} + +bool ConstParams::CheckTraverseFunctionDecl(FunctionDecl * functionDecl) +{ + if (ignoreLocation(functionDecl) || !functionDecl->isThisDeclarationADefinition()) { + return false; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) { + return false; + } + if (functionDecl->isDeleted()) + return false; + // ignore virtual methods + if (isa(functionDecl) + && dyn_cast(functionDecl)->isVirtual() ) { + return false; + } + // ignore C main + if (functionDecl->isMain()) { + return false; + } + if (functionDecl->getTemplatedKind() != FunctionDecl::TK_NonTemplate) + return false; + + // ignore the macros from include/tools/link.hxx + auto canonicalDecl = functionDecl->getCanonicalDecl(); + if (compiler.getSourceManager().isMacroBodyExpansion(canonicalDecl->getBeginLoc()) + || compiler.getSourceManager().isMacroArgExpansion(canonicalDecl->getBeginLoc())) { + StringRef name { Lexer::getImmediateMacroName( + canonicalDecl->getBeginLoc(), compiler.getSourceManager(), compiler.getLangOpts()) }; + if (name.startswith("DECL_LINK") || name.startswith("DECL_STATIC_LINK")) + return false; + auto loc2 = compat::getImmediateExpansionRange(compiler.getSourceManager(), canonicalDecl->getBeginLoc()).first; + if (compiler.getSourceManager().isMacroBodyExpansion(loc2)) + { + StringRef name2 { Lexer::getImmediateMacroName( + loc2, compiler.getSourceManager(), compiler.getLangOpts()) }; + if (name2.startswith("DECL_DLLPRIVATE_LINK")) + return false; + } + } + + if (functionDecl->getIdentifier()) + { + StringRef name = functionDecl->getName(); + if ( name == "file_write" + || name == "SalMainPipeExchangeSignal_impl" + || name.startswith("SbRtl_") + || name == "GoNext" + || name == "GoPrevious" + || name.startswith("Read_F_") + // UNO component entry points + || name.endswith("component_getFactory") + || name.endswith("_get_implementation") + // callback for some external code? + || name == "ScAddInAsyncCallBack" + // used as function pointers + || name == "Read_Footnote" + || name == "Read_Field" + || name == "Read_And" + // passed as a LINK<> to another method + || name == "GlobalBasicErrorHdl_Impl" + // template + || name == "extract_throw" || name == "readProp" + // callbacks + || name == "signalDragDropReceived" || name == "signal_column_clicked" || name == "signal_key_press" + ) + return false; + + } + + std::string fqn = functionDecl->getQualifiedNameAsString(); + if ( fqn == "connectivity::jdbc::GlobalRef::set" + || fqn == "(anonymous namespace)::ReorderNotifier::operator()" + || fqn == "static_txtattr_cast") + return false; + + // calculate the ones we want to check + bool foundInterestingParam = false; + for (const ParmVarDecl *pParmVarDecl : functionDecl->parameters()) { + // ignore unused params + if (pParmVarDecl->getName().empty() + || pParmVarDecl->hasAttr()) + continue; + auto const type = loplugin::TypeCheck(pParmVarDecl->getType()); + if (!( type.Pointer().NonConst() + || type.LvalueReference().NonConst())) + continue; + // since we normally can't change typedefs, just ignore them + if (isa(pParmVarDecl->getType())) + continue; + // some typedefs turn into these + if (isa(pParmVarDecl->getType())) + continue; + // TODO ignore these for now, has some effects I don't understand + if (type.Pointer().Pointer()) + continue; + // const is meaningless when applied to function pointer types + if (pParmVarDecl->getType()->isFunctionPointerType()) + continue; + interestingParamSet.insert(pParmVarDecl); + parmToFunction[pParmVarDecl] = functionDecl; + foundInterestingParam = true; + } + return foundInterestingParam; +} + +bool ConstParams::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) +{ + if (!currentFunctionDecl) + return true; + const ParmVarDecl* parmVarDecl = dyn_cast_or_null(declRefExpr->getDecl()); + if (!parmVarDecl) + return true; + if (interestingParamSet.find(parmVarDecl) == interestingParamSet.end()) + return true; + if (!checkIfCanBeConst(declRefExpr, parmVarDecl)) + interestingParamSet.erase(parmVarDecl); + return true; +} + +bool ConstParams::VisitLambdaExpr(const LambdaExpr* lambdaExpr) +{ + if (ignoreLocation(lambdaExpr)) + return true; + for (auto captureIt = lambdaExpr->capture_begin(); captureIt != lambdaExpr->capture_end(); + ++captureIt) + { + const LambdaCapture& capture = *captureIt; + if (capture.capturesVariable()) + { + if (auto varDecl = dyn_cast(capture.getCapturedVar())) + interestingParamSet.erase(varDecl); + } + } + return true; +} + +// Walk up from a statement that contains a DeclRefExpr, checking if the usage means that the +// related ParamVarDecl can be const. +bool ConstParams::checkIfCanBeConst(const Stmt* stmt, const ParmVarDecl* parmVarDecl) +{ + const Stmt* parent = getParentStmt( stmt ); + if (!parent) + { + // check if we're inside a CXXCtorInitializer + auto parentsRange = compiler.getASTContext().getParents(*stmt); + auto it = parentsRange.begin(); + if ( parentsRange.begin() != parentsRange.end()) + { + const Decl *decl = it->get(); + if (auto cxxConstructorDecl = dyn_cast_or_null(decl)) + { + for ( auto cxxCtorInitializer : cxxConstructorDecl->inits()) + { + if ( cxxCtorInitializer->getInit() == stmt) + { + if (cxxCtorInitializer->isAnyMemberInitializer()) + { + // if the member is not pointer-to-const or ref-to-const or value, we cannot make the param const + auto fieldDecl = cxxCtorInitializer->getAnyMember(); + auto tc = loplugin::TypeCheck(fieldDecl->getType()); + if (tc.Pointer() || tc.LvalueReference()) + return tc.Pointer().Const() || tc.LvalueReference().Const(); + else + return true; + } + else + { + // probably base initialiser, but no simple way to look up the relevant constructor decl + return false; + } + } + } + } + if (auto varDecl = dyn_cast_or_null(decl)) + { + return isOkForParameter(varDecl->getType()); + } + } +// parmVarDecl->dump(); +// stmt->dump(); +// report( +// DiagnosticsEngine::Warning, +// "no parent?", +// stmt->getBeginLoc()) +// << stmt->getSourceRange(); + return false; + } + + if (auto unaryOperator = dyn_cast(parent)) { + UnaryOperator::Opcode op = unaryOperator->getOpcode(); + if (op == UO_PreInc || op == UO_PostInc + || op == UO_PreDec || op == UO_PostDec) { + return false; + } + if (op == UO_Deref || op == UO_AddrOf) { + return checkIfCanBeConst(parent, parmVarDecl); + } + return true; + } else if (auto binaryOp = dyn_cast(parent)) { + BinaryOperator::Opcode op = binaryOp->getOpcode(); + if (binaryOp->getRHS() == stmt && op == BO_Assign) { + return isOkForParameter(binaryOp->getLHS()->getType()); + } + if (binaryOp->getRHS() == stmt) { + return true; + } + if (op == BO_Assign || op == BO_PtrMemD || op == BO_PtrMemI || op == BO_MulAssign + || op == BO_DivAssign || op == BO_RemAssign || op == BO_AddAssign + || op == BO_SubAssign || op == BO_ShlAssign || op == BO_ShrAssign + || op == BO_AndAssign || op == BO_XorAssign || op == BO_OrAssign) { + return false; + } + // for pointer arithmetic need to check parent + if (binaryOp->getType()->isPointerType()) { + return checkIfCanBeConst(parent, parmVarDecl); + } + return true; + } else if (auto constructExpr = dyn_cast(parent)) { + const CXXConstructorDecl * constructorDecl = constructExpr->getConstructor(); + for (unsigned i = 0; i < constructExpr->getNumArgs(); ++i) { + if (constructExpr->getArg(i) == stmt) { + return isOkForParameter(constructorDecl->getParamDecl(i)->getType()); + } + } + } else if (auto operatorCallExpr = dyn_cast(parent)) { + const CXXMethodDecl* calleeMethodDecl = dyn_cast_or_null(operatorCallExpr->getDirectCallee()); + if (calleeMethodDecl) { + // unary operator + if (calleeMethodDecl->getNumParams() == 0) + return calleeMethodDecl->isConst(); + // Same logic as CXXOperatorCallExpr::isAssignmentOp(), which our supported clang + // doesn't have yet. + auto Opc = operatorCallExpr->getOperator(); + if (Opc == OO_Equal || Opc == OO_StarEqual || + Opc == OO_SlashEqual || Opc == OO_PercentEqual || + Opc == OO_PlusEqual || Opc == OO_MinusEqual || + Opc == OO_LessLessEqual || Opc == OO_GreaterGreaterEqual || + Opc == OO_AmpEqual || Opc == OO_CaretEqual || + Opc == OO_PipeEqual) + { + if (operatorCallExpr->getArg(0) == stmt) // assigning to the param + return false; + // not all operator= take a const& + return isOkForParameter(calleeMethodDecl->getParamDecl(0)->getType()); + } + if (operatorCallExpr->getOperator() == OO_Subscript && operatorCallExpr->getArg(1) == stmt) + return true; + if (operatorCallExpr->getOperator() == OO_EqualEqual || operatorCallExpr->getOperator() == OO_ExclaimEqual) + return true; + // binary operator + if (operatorCallExpr->getArg(0) == stmt) + return calleeMethodDecl->isConst(); + unsigned const n = std::min( + operatorCallExpr->getNumArgs(), + calleeMethodDecl->getNumParams() + 1); + for (unsigned i = 1; i < n; ++i) + if (operatorCallExpr->getArg(i) == stmt) { + auto qt = calleeMethodDecl->getParamDecl(i - 1)->getType(); + return isOkForParameter(qt); + } + } else { + const Expr* callee = operatorCallExpr->getCallee()->IgnoreParenImpCasts(); + const DeclRefExpr* dr = dyn_cast(callee); + const FunctionDecl* calleeFunctionDecl = nullptr; + if (dr) { + calleeFunctionDecl = dyn_cast(dr->getDecl()); + } + if (calleeFunctionDecl) { + for (unsigned i = 0; i < operatorCallExpr->getNumArgs(); ++i) { + if (operatorCallExpr->getArg(i) == stmt) { + return isOkForParameter(calleeFunctionDecl->getParamDecl(i)->getType()); + } + } + } + } + return false; + } else if (auto callExpr = dyn_cast(parent)) { + QualType functionType = callExpr->getCallee()->getType(); + if (functionType->isFunctionPointerType()) { + functionType = functionType->getPointeeType(); + } + if (const FunctionProtoType* prototype = functionType->getAs()) { + // TODO could do better + if (prototype->isVariadic()) { + return false; + } + if (callExpr->getCallee() == stmt) { + return true; + } + for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) { + if (callExpr->getArg(i) == stmt) { + return isOkForParameter(prototype->getParamType(i)); + } + } + } + const FunctionDecl* calleeFunctionDecl = callExpr->getDirectCallee(); + if (calleeFunctionDecl) + { + if (auto memberCallExpr = dyn_cast(parent)) { + const MemberExpr* memberExpr = dyn_cast(stmt); + if (memberExpr && memberCallExpr->getImplicitObjectArgument() == memberExpr->getBase()) + { + const CXXMethodDecl* calleeMethodDecl = dyn_cast(calleeFunctionDecl); + return calleeMethodDecl->isConst(); + } + } + // TODO could do better + if (calleeFunctionDecl->isVariadic()) { + return false; + } + if (callExpr->getCallee() == stmt) { + return true; + } + for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) { + if (i >= calleeFunctionDecl->getNumParams()) // can happen in template code + return false; + if (callExpr->getArg(i) == stmt) { + return isOkForParameter(calleeFunctionDecl->getParamDecl(i)->getType()); + } + } + } + return false; + } else if (auto callExpr = dyn_cast(parent)) { + if (callExpr->getInstanceReceiver() == stmt) { + return true; + } + if (auto const method = callExpr->getMethodDecl()) { + // TODO could do better + if (method->isVariadic()) { + return false; + } + assert(method->param_size() == callExpr->getNumArgs()); + for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) { + if (callExpr->getArg(i) == stmt) { + return isOkForParameter( + method->param_begin()[i]->getType()); + } + } + } + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { // all other cast expression subtypes + if (auto e = dyn_cast(parent)) { + if (loplugin::TypeCheck(e->getTypeAsWritten()).Void()) { + if (auto const sub = dyn_cast( + e->getSubExpr()->IgnoreParenImpCasts())) + { + if (sub->getDecl() == parmVarDecl) + return false; + } + } + } + return checkIfCanBeConst(parent, parmVarDecl); + } else if (isa(parent)) { + return checkIfCanBeConst(parent, parmVarDecl); + } else if (auto arraySubscriptExpr = dyn_cast(parent)) { + if (arraySubscriptExpr->getIdx() == stmt) + return true; + return checkIfCanBeConst(parent, parmVarDecl); + } else if (isa(parent)) { + return checkIfCanBeConst(parent, parmVarDecl); + } else if (isa(parent)) { + // TODO could do better here, but would require tracking the target(s) + //return false; + } else if (isa(parent)) { + return !isPointerOrReferenceToNonConst(currentFunctionDecl->getReturnType()); + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return checkIfCanBeConst(parent, parmVarDecl); + } else if (auto conditionalExpr = dyn_cast(parent)) { + if (conditionalExpr->getCond() == stmt) + return true; + return checkIfCanBeConst(parent, parmVarDecl); + } else if (isa(parent)) { + return false; // ??? + } else if (auto cxxNewExpr = dyn_cast(parent)) { + for (unsigned i = 0; i < cxxNewExpr->getNumPlacementArgs(); ++i) + if (cxxNewExpr->getPlacementArg(i) == stmt) + return false; + return true; // ??? + } else if (auto lambdaExpr = dyn_cast(parent)) { + for (auto it = lambdaExpr->capture_begin(); it != lambdaExpr->capture_end(); ++it) + { + if (it->capturesVariable() && it->getCapturedVar() == parmVarDecl) + return it->getCaptureKind() != LCK_ByRef; + } + return false; + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return false; // could be improved, seen in constructors when calling base class constructor + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return checkIfCanBeConst(parent, parmVarDecl); + } else if (isa(parent)) { + return true; + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return false; + } else if (isa(parent)) { + return checkIfCanBeConst(parent, parmVarDecl); + } + parent->dump(); + parmVarDecl->dump(); + report( + DiagnosticsEngine::Warning, + "oh dear, what can the matter be?", + parent->getBeginLoc()) + << parent->getSourceRange(); + return true; +} + +bool ConstParams::isOkForParameter(const QualType& qt) { + if (qt->isIntegralOrEnumerationType()) + return true; + auto const type = loplugin::TypeCheck(qt); + if (type.Pointer()) { + return bool(type.Pointer().Const()); + } else if (type.LvalueReference().Const().Pointer()) { + // If we have a method that takes (T* t) and it calls std::vector::push_back + // then the type of push_back is T * const & + // There is probably a more elegant way to check this, but it will probably require + // recalculating types while walking up the AST. + return false; + } else if (type.LvalueReference()) { + return bool(type.LvalueReference().Const()); + } + return false; +} + +bool ConstParams::isPointerOrReferenceToNonConst(const QualType& qt) { + auto const type = loplugin::TypeCheck(qt); + if (type.Pointer()) { + return !bool(type.Pointer().Const()); + } else if (type.LvalueReference()) { + return !bool(type.LvalueReference().Const()); + } + return false; +} + +loplugin::Plugin::Registration< ConstParams > X("constparams", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/conststringvar.cxx b/compilerplugins/clang/conststringvar.cxx new file mode 100644 index 000000000..99cfb01c0 --- /dev/null +++ b/compilerplugins/clang/conststringvar.cxx @@ -0,0 +1,156 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include + +#include "check.hxx" +#include "plugin.hxx" + +// Find non-const vars of 'char const *' type initialized with a const expr, +// that could likely be const (and will then probably trigger further +// loplugin:stringconstant findings). + +namespace { + +class ConstStringVar: + public loplugin::FilteringPlugin +{ +public: + explicit ConstStringVar(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + bool preRun() override { + return compiler.getLangOpts().CPlusPlus; + // clang::Expr::isCXX11ConstantExpr only works for C++ + } + + void postRun() override { + for (auto v: vars_) { + report( + DiagnosticsEngine::Warning, + "variable is only used as rvalue, should be const", + v->getLocation()) + << v->getSourceRange(); + } + } + + void run() override { + if (preRun() && TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) { + postRun(); + } + } + + bool PreTraverseImplicitCastExpr(ImplicitCastExpr * expr) { + bool match; + switch (expr->getCastKind()) { + case CK_NoOp: + // OString CharPtrDetector ctor: + match = bool( + loplugin::TypeCheck(expr->getType()).Const().Pointer().Const() + .Char()); + break; + case CK_LValueToRValue: + match = true; + break; + default: + match = false; + break; + } + bool pushed = false; + if (match) { + if (auto dr = dyn_cast( + expr->getSubExpr()->IgnoreParenImpCasts())) + { + if (auto vd = dyn_cast(dr->getDecl())) { + if (vars_.find(vd->getCanonicalDecl()) != vars_.end()) { + casted_.push(dr); + pushed = true; + } + } + } + } + pushed_.push(pushed); + return true; + } + bool PostTraverseImplicitCastExpr(ImplicitCastExpr *, bool) { + bool pushed = pushed_.top(); + pushed_.pop(); + if (pushed) { + casted_.pop(); + } + return true; + } + bool TraverseImplicitCastExpr(ImplicitCastExpr * expr) { + bool ret = true; + if (PreTraverseImplicitCastExpr(expr)) + { + ret = FilteringPlugin::TraverseImplicitCastExpr(expr); + PostTraverseImplicitCastExpr(expr, ret); + } + return ret; + } + + bool VisitVarDecl(VarDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + if (decl != decl->getCanonicalDecl()) { + return true; + } + if (isa(decl) || loplugin::hasExternalLinkage(decl)) { + return true; + } + if (!loplugin::TypeCheck(decl->getType()).NonConstVolatile().Pointer() + .Const().Char()) + { + return true; + } + auto init = decl->getAnyInitializer(); + if (init == nullptr) { + return true; + } + if (init->isInstantiationDependent()) { + // avoid problems with isCXX11ConstantExpr in template code + return true; + } + APValue v; + if (!init->isCXX11ConstantExpr(compiler.getASTContext(), &v)) { + return true; + } + vars_.insert(decl); + return true; + } + + bool VisitDeclRefExpr(DeclRefExpr const * expr) { + if (!casted_.empty() && expr == casted_.top()) { + return true; + } + auto vd = dyn_cast(expr->getDecl()); + if (vd == nullptr) { + return true; + } + vars_.erase(vd->getCanonicalDecl()); + return true; + } + +private: + std::set vars_; + std::stack casted_; + std::stack pushed_; +}; + +loplugin::Plugin::Registration conststringvar("conststringvar"); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/consttobool.cxx b/compilerplugins/clang/consttobool.cxx new file mode 100644 index 000000000..d20a0d5c9 --- /dev/null +++ b/compilerplugins/clang/consttobool.cxx @@ -0,0 +1,291 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +//TODO: Make this a shared plugin for Clang 12 (and possibly even for older Clang) again. + +#include +#include +#include + +#include "clang/Basic/Builtins.h" + +#include "check.hxx" +#include "plugin.hxx" + +// Find implicit conversions from non-'bool' constants (e.g., 'sal_False') to 'bool'. + +namespace +{ +class ConstToBool final : public loplugin::FilteringPlugin +{ +public: + explicit ConstToBool(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool PreTraverseLinkageSpecDecl(LinkageSpecDecl*) + { + assert(externCContexts_ != std::numeric_limits::max()); //TODO + ++externCContexts_; + return true; + } + + bool PostTraverseLinkageSpecDecl(LinkageSpecDecl*, bool) + { + assert(externCContexts_ != 0); + --externCContexts_; + return true; + } + + bool TraverseLinkageSpecDecl(LinkageSpecDecl* decl) + { + bool ret = true; + if (PreTraverseLinkageSpecDecl(decl)) + { + ret = FilteringPlugin::TraverseLinkageSpecDecl(decl); + PostTraverseLinkageSpecDecl(decl, ret); + } + return ret; + } + + bool PreTraverseUnaryOperator(UnaryOperator* expr) + { + if (expr->getOpcode() == UO_LNot) + { + ignoredInAssert_.push(expr->getSubExpr()); + } + return true; + } + + bool PostTraverseUnaryOperator(UnaryOperator* expr, bool) + { + if (expr->getOpcode() == UO_LNot) + { + assert(!ignoredInAssert_.empty()); + ignoredInAssert_.pop(); + } + return true; + } + + bool TraverseUnaryOperator(UnaryOperator* expr) + { + bool ret = true; + if (PreTraverseUnaryOperator(expr)) + { + ret = FilteringPlugin::TraverseUnaryOperator(expr); + PostTraverseUnaryOperator(expr, ret); + } + return ret; + } + + bool PreTraverseBinaryOperator(BinaryOperator* expr) + { + if (expr->getOpcode() == BO_LAnd) + { + ignoredInAssert_.push(expr->getRHS()); + } + return true; + } + + bool PostTraverseBinaryOperator(BinaryOperator* expr, bool) + { + if (expr->getOpcode() == BO_LAnd) + { + assert(!ignoredInAssert_.empty()); + ignoredInAssert_.pop(); + } + return true; + } + + bool TraverseBinaryOperator(BinaryOperator* expr) + { + bool ret = true; + if (PreTraverseBinaryOperator(expr)) + { + ret = FilteringPlugin::TraverseBinaryOperator(expr); + PostTraverseBinaryOperator(expr, ret); + } + return ret; + } + + bool VisitImplicitCastExpr(ImplicitCastExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + if (!expr->getType()->isBooleanType()) + { + return true; + } + auto const sub = expr->getSubExpr(); + auto const t = sub->getType(); + if (t->isBooleanType()) + { + return true; + } + if (sub->isValueDependent()) + { + return true; + } + APValue res; + if (!sub->isCXX11ConstantExpr(compiler.getASTContext(), &res)) + { + return true; + } + auto const l = expr->getExprLoc(); + if (!ignoredInAssert_.empty() && expr == ignoredInAssert_.top()) + { + if (auto const e = dyn_cast(sub->IgnoreParenImpCasts())) + { + if (e->isAscii()) // somewhat randomly restrict to plain literals + { + if (compiler.getSourceManager().isMacroArgExpansion(l) + && Lexer::getImmediateMacroName(l, compiler.getSourceManager(), + compiler.getLangOpts()) + == "assert") + { + //TODO: only ignore outermost '!"..."' or '... && "..."' + return true; + } + } + } + } + auto l1 = l; + if (compiler.getSourceManager().isMacroBodyExpansion(l1)) + { + auto const n = Lexer::getImmediateMacroName(l1, compiler.getSourceManager(), + compiler.getLangOpts()); + if (n == "FALSE" || n == "TRUE" || n == "sal_False" || n == "sal_True") + { + l1 = compiler.getSourceManager().getImmediateMacroCallerLoc(l1); + } + // For example, /usr/include/glib-2.0/glib/gmacros.h from + // glib2-devel-2.62.1-1.fc31.x86_64 has + // + // #define TRUE (!FALSE) + // + // so handle that wrapped macro body expansion, too: + if (compiler.getSourceManager().isMacroBodyExpansion(l1) + && Lexer::getImmediateMacroName(l1, compiler.getSourceManager(), + compiler.getLangOpts()) + == "TRUE") + { + l1 = compiler.getSourceManager().getImmediateMacroCallerLoc(l1); + } + } + if (isSharedCAndCppCode(l1)) + { + // Cover just enough cases to handle things like `while (0)` or the use of `sal_True` in + // + // #define OSL_FAIL(m) SAL_DETAIL_WARN_IF_FORMAT(sal_True, "legacy.osl", "%s", m) + // + // in include/osl/diagnose.h: + if (auto const t1 = t->getAs()) + { + if (t1->getKind() == BuiltinType::Int) + { + auto const& v = res.getInt(); + if (v == 0 || v == 1) + { + return true; + } + } + } + if (loplugin::TypeCheck(t).Typedef("sal_Bool").GlobalNamespace()) + { + return true; + } + } + if (auto const e = dyn_cast(sub->IgnoreParenImpCasts())) + { + // Ignore use of `long __builtin_expect(long, long)`, as found in the definition of + // `assert` on macOS: + if (e->getBuiltinCallee() == Builtin::BI__builtin_expect) + { + return true; + } + } + bool suggestion; + bool replacement = {}; + if (res.isInt()) + { + suggestion = true; + replacement = res.getInt() != 0; + } + else if (res.isFloat()) + { + suggestion = true; + replacement = !res.getFloat().isZero(); + } + else if (res.isNullPointer()) + { + suggestion = true; + replacement = false; + } + else if (res.isLValue()) + { + suggestion = true; + replacement = true; + } + else + { + suggestion = false; + } + report(DiagnosticsEngine::Warning, + "implicit conversion of constant %0 of type %1 to 'bool'%select{|; use " + "'%select{false|true}3' instead}2", + l) + << res.getAsString(compiler.getASTContext(), t) << t << suggestion << replacement + << expr->getSourceRange(); + return true; + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + +private: + std::stack ignoredInAssert_; + unsigned int externCContexts_ = 0; + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool isFromCIncludeFile(SourceLocation spellingLocation) const + { + return !compiler.getSourceManager().isInMainFile(spellingLocation) + && (StringRef( + compiler.getSourceManager().getPresumedLoc(spellingLocation).getFilename()) + .endswith(".h")); + } + + bool isSharedCAndCppCode(SourceLocation location) const + { + while (compiler.getSourceManager().isMacroArgExpansion(location)) + { + location = compiler.getSourceManager().getImmediateMacroCallerLoc(location); + } + // Assume that code is intended to be shared between C and C++ if it comes from an include + // file ending in .h, and is either in an extern "C" context or the body of a macro + // definition: + return isFromCIncludeFile(compiler.getSourceManager().getSpellingLoc(location)) + && (externCContexts_ != 0 + || compiler.getSourceManager().isMacroBodyExpansion(location)); + } +}; + +loplugin::Plugin::Registration consttobool("consttobool"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/constvars.cxx b/compilerplugins/clang/constvars.cxx new file mode 100644 index 000000000..2b06f54ea --- /dev/null +++ b/compilerplugins/clang/constvars.cxx @@ -0,0 +1,558 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if !defined _WIN32 //TODO, #include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" + +#include "clang/AST/ParentMapContext.h" + +/** +Look for static vars that are only assigned to once, and never written to, they can be const. +*/ + +namespace +{ +/** + * Wrap the different kinds of callable and callee objects in the clang AST so I can define methods that handle everything. + */ +class CallerWrapper +{ + const CallExpr* m_callExpr; + const CXXConstructExpr* m_cxxConstructExpr; + +public: + CallerWrapper(const CallExpr* callExpr) + : m_callExpr(callExpr) + , m_cxxConstructExpr(nullptr) + { + } + CallerWrapper(const CXXConstructExpr* cxxConstructExpr) + : m_callExpr(nullptr) + , m_cxxConstructExpr(cxxConstructExpr) + { + } + unsigned getNumArgs() const + { + return m_callExpr ? m_callExpr->getNumArgs() : m_cxxConstructExpr->getNumArgs(); + } + const Expr* getArg(unsigned i) const + { + return m_callExpr ? m_callExpr->getArg(i) : m_cxxConstructExpr->getArg(i); + } +}; +class CalleeWrapper +{ + const FunctionDecl* m_calleeFunctionDecl = nullptr; + const CXXConstructorDecl* m_cxxConstructorDecl = nullptr; + const FunctionProtoType* m_functionPrototype = nullptr; + +public: + explicit CalleeWrapper(const FunctionDecl* calleeFunctionDecl) + : m_calleeFunctionDecl(calleeFunctionDecl) + { + } + explicit CalleeWrapper(const CXXConstructExpr* cxxConstructExpr) + : m_cxxConstructorDecl(cxxConstructExpr->getConstructor()) + { + } + explicit CalleeWrapper(const FunctionProtoType* functionPrototype) + : m_functionPrototype(functionPrototype) + { + } + unsigned getNumParams() const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getNumParams(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getNumParams(); + else if (m_functionPrototype->param_type_begin() == m_functionPrototype->param_type_end()) + // FunctionProtoType will assert if we call getParamTypes() and it has no params + return 0; + else + return m_functionPrototype->getParamTypes().size(); + } + const QualType getParamType(unsigned i) const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getParamDecl(i)->getType(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getParamDecl(i)->getType(); + else + return m_functionPrototype->getParamTypes()[i]; + } + std::string getNameAsString() const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getNameAsString(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getNameAsString(); + else + return ""; + } + CXXMethodDecl const* getAsCXXMethodDecl() const + { + if (m_calleeFunctionDecl) + return dyn_cast(m_calleeFunctionDecl); + return nullptr; + } +}; + +class ConstVars : public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit ConstVars(loplugin::InstantiationData const& data) + : Plugin(data) + { + } + + virtual void run() override; + + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitVarDecl(const VarDecl*); + bool VisitCXXForRangeStmt(const CXXForRangeStmt*); + bool VisitDeclRefExpr(const DeclRefExpr*); + bool TraverseCXXConstructorDecl(CXXConstructorDecl*); + bool TraverseCXXMethodDecl(CXXMethodDecl*); + bool TraverseFunctionDecl(FunctionDecl*); + bool TraverseIfStmt(IfStmt*); + +private: + void check(const VarDecl* varDecl, const Expr* memberExpr); + bool isSomeKindOfZero(const Expr* arg); + bool IsPassedByNonConst(const VarDecl* varDecl, const Stmt* child, CallerWrapper callExpr, + CalleeWrapper calleeFunctionDecl); + llvm::Optional getCallee(CallExpr const*); + + RecordDecl* insideMoveOrCopyDeclParent = nullptr; + // For reasons I do not understand, parentFunctionDecl() is not reliable, so + // we store the parent function on the way down the AST. + FunctionDecl* insideFunctionDecl = nullptr; + std::vector insideConditionalCheckOfVarSet; + + std::set cannotBeConstSet; + std::set definitionSet; +}; + +void ConstVars::run() +{ + // clang::Expr::isCXX11ConstantExpr only works for C++ + if (!compiler.getLangOpts().CPlusPlus) + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + SourceManager& SM = compiler.getSourceManager(); + for (VarDecl const* v : definitionSet) + { + if (cannotBeConstSet.find(v) != cannotBeConstSet.end()) + continue; + llvm::StringRef sourceString(SM.getCharacterData(v->getSourceRange().getEnd()), 50); + // Implement a marker that disables this plugins warning at a specific site + if (sourceString.contains("loplugin:constvars:ignore")) + continue; + report(DiagnosticsEngine::Warning, "var can be const", v->getBeginLoc()); + } +} + +bool ConstVars::VisitVarDecl(const VarDecl* varDecl) +{ + varDecl = varDecl->getCanonicalDecl(); + if (varDecl->getLocation().isValid() && ignoreLocation(varDecl)) + return true; + if (!varDecl->hasGlobalStorage()) + return true; + if (isa(varDecl)) + return true; + if (varDecl->getLinkageAndVisibility().getLinkage() == ExternalLinkage) + return true; + if (varDecl->getType().isConstQualified()) + return true; + if (isa(varDecl->getType())) + return true; + if (loplugin::TypeCheck(varDecl->getType()).Pointer().Const()) + return true; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(varDecl->getLocation()))) + return true; + + if (!varDecl->getInit()) + return true; + if (varDecl->getInit()->isInstantiationDependent()) + return true; + if (!varDecl->getInit()->isCXX11ConstantExpr(compiler.getASTContext())) + return true; + + definitionSet.insert(varDecl); + return true; +} + +bool ConstVars::VisitCXXForRangeStmt(const CXXForRangeStmt* forStmt) +{ + if (forStmt->getBeginLoc().isValid() && ignoreLocation(forStmt)) + return true; + const VarDecl* varDecl = forStmt->getLoopVariable(); + if (!varDecl) + return true; + // we don't handle structured assignment properly + if (isa(varDecl)) + return true; + auto tc = loplugin::TypeCheck(varDecl->getType()); + if (!tc.LvalueReference()) + return true; + if (tc.LvalueReference().Const()) + return true; + + definitionSet.insert(varDecl); + return true; +} + +bool ConstVars::TraverseCXXConstructorDecl(CXXConstructorDecl* cxxConstructorDecl) +{ + auto copy = insideMoveOrCopyDeclParent; + if (!ignoreLocation(cxxConstructorDecl) && cxxConstructorDecl->isThisDeclarationADefinition()) + { + if (cxxConstructorDecl->isCopyOrMoveConstructor()) + insideMoveOrCopyDeclParent = cxxConstructorDecl->getParent(); + } + bool ret = RecursiveASTVisitor::TraverseCXXConstructorDecl(cxxConstructorDecl); + insideMoveOrCopyDeclParent = copy; + return ret; +} + +bool ConstVars::TraverseCXXMethodDecl(CXXMethodDecl* cxxMethodDecl) +{ + auto copy1 = insideMoveOrCopyDeclParent; + auto copy2 = insideFunctionDecl; + if (!ignoreLocation(cxxMethodDecl) && cxxMethodDecl->isThisDeclarationADefinition()) + { + if (cxxMethodDecl->isCopyAssignmentOperator() || cxxMethodDecl->isMoveAssignmentOperator()) + insideMoveOrCopyDeclParent = cxxMethodDecl->getParent(); + } + insideFunctionDecl = cxxMethodDecl; + bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl); + insideMoveOrCopyDeclParent = copy1; + insideFunctionDecl = copy2; + return ret; +} + +bool ConstVars::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + auto copy2 = insideFunctionDecl; + insideFunctionDecl = functionDecl; + bool ret = RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); + insideFunctionDecl = copy2; + return ret; +} + +bool ConstVars::TraverseIfStmt(IfStmt* ifStmt) +{ + VarDecl const* varDecl = nullptr; + if (Expr const* cond = ifStmt->getCond()) + { + if (auto declRefExpr = dyn_cast(cond->IgnoreParenImpCasts())) + { + if ((varDecl = dyn_cast(declRefExpr->getDecl()))) + insideConditionalCheckOfVarSet.push_back(varDecl); + } + } + bool ret = RecursiveASTVisitor::TraverseIfStmt(ifStmt); + if (varDecl) + insideConditionalCheckOfVarSet.pop_back(); + return ret; +} + +bool ConstVars::VisitDeclRefExpr(const DeclRefExpr* declRefExpr) +{ + const VarDecl* varDecl = dyn_cast(declRefExpr->getDecl()); + if (!varDecl) + return true; + varDecl = varDecl->getCanonicalDecl(); + if (ignoreLocation(varDecl)) + return true; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(varDecl->getLocation()))) + return true; + + if (definitionSet.find(varDecl) != definitionSet.end()) + check(varDecl, declRefExpr); + + return true; +} + +void ConstVars::check(const VarDecl* varDecl, const Expr* memberExpr) +{ + auto parentsRange = compiler.getASTContext().getParents(*memberExpr); + const Stmt* child = memberExpr; + const Stmt* parent + = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get(); + + // walk up the tree until we find something interesting + + bool bCannotBeConst = false; + bool bDump = false; + auto walkUp = [&]() { + child = parent; + auto parentsRange = compiler.getASTContext().getParents(*parent); + parent = parentsRange.begin() == parentsRange.end() ? nullptr + : parentsRange.begin()->get(); + }; + do + { + if (!parent) + { + // check if we have an expression like + // int& r = var; + auto parentsRange = compiler.getASTContext().getParents(*child); + if (parentsRange.begin() != parentsRange.end()) + { + auto varDecl = dyn_cast_or_null(parentsRange.begin()->get()); + if (varDecl) + { + if (varDecl->isImplicit()) + { + // so we can walk up from inside a for-range stmt + parentsRange = compiler.getASTContext().getParents(*varDecl); + if (parentsRange.begin() != parentsRange.end()) + parent = parentsRange.begin()->get(); + } + else if (loplugin::TypeCheck(varDecl->getType()).LvalueReference().NonConst()) + { + bCannotBeConst = true; + break; + } + } + } + } + if (!parent) + break; + if (isa(parent)) + { + // once we see one of these, there is not much useful we can know + bCannotBeConst = true; + break; + } + else if (isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent)) + { + walkUp(); + } + else if (auto unaryOperator = dyn_cast(parent)) + { + UnaryOperator::Opcode op = unaryOperator->getOpcode(); + if (op == UO_AddrOf || op == UO_PostInc || op == UO_PostDec || op == UO_PreInc + || op == UO_PreDec) + { + bCannotBeConst = true; + } + walkUp(); + } + else if (auto operatorCallExpr = dyn_cast(parent)) + { + auto callee = getCallee(operatorCallExpr); + if (callee) + { + // if calling a non-const operator on the var + auto calleeMethodDecl = callee->getAsCXXMethodDecl(); + if (calleeMethodDecl && operatorCallExpr->getArg(0) == child + && !calleeMethodDecl->isConst()) + { + bCannotBeConst = true; + } + else if (IsPassedByNonConst(varDecl, child, operatorCallExpr, *callee)) + { + bCannotBeConst = true; + } + } + else + bCannotBeConst = true; // conservative, could improve + walkUp(); + } + else if (auto cxxMemberCallExpr = dyn_cast(parent)) + { + const CXXMethodDecl* calleeMethodDecl = cxxMemberCallExpr->getMethodDecl(); + if (calleeMethodDecl) + { + // if calling a non-const method on the var + const Expr* tmp = dyn_cast(child); + if (tmp->isBoundMemberFunction(compiler.getASTContext())) + { + tmp = dyn_cast(tmp)->getBase(); + } + if (cxxMemberCallExpr->getImplicitObjectArgument() == tmp + && !calleeMethodDecl->isConst()) + { + bCannotBeConst = true; + break; + } + if (IsPassedByNonConst(varDecl, child, cxxMemberCallExpr, + CalleeWrapper(calleeMethodDecl))) + bCannotBeConst = true; + } + else + bCannotBeConst = true; // can happen in templates + walkUp(); + } + else if (auto cxxConstructExpr = dyn_cast(parent)) + { + if (IsPassedByNonConst(varDecl, child, cxxConstructExpr, + CalleeWrapper(cxxConstructExpr))) + bCannotBeConst = true; + walkUp(); + } + else if (auto callExpr = dyn_cast(parent)) + { + auto callee = getCallee(callExpr); + if (callee) + { + if (IsPassedByNonConst(varDecl, child, callExpr, *callee)) + bCannotBeConst = true; + } + else + bCannotBeConst = true; // conservative, could improve + walkUp(); + } + else if (auto binaryOp = dyn_cast(parent)) + { + BinaryOperator::Opcode op = binaryOp->getOpcode(); + const bool assignmentOp = op == BO_Assign || op == BO_MulAssign || op == BO_DivAssign + || op == BO_RemAssign || op == BO_AddAssign + || op == BO_SubAssign || op == BO_ShlAssign + || op == BO_ShrAssign || op == BO_AndAssign + || op == BO_XorAssign || op == BO_OrAssign; + if (assignmentOp) + { + if (binaryOp->getLHS() == child) + bCannotBeConst = true; + else if (loplugin::TypeCheck(binaryOp->getLHS()->getType()) + .LvalueReference() + .NonConst()) + // if the LHS is a non-const reference, we could write to the var later on + bCannotBeConst = true; + } + walkUp(); + } + else if (isa(parent)) + { + if (insideFunctionDecl) + { + auto tc = loplugin::TypeCheck(insideFunctionDecl->getReturnType()); + if (tc.LvalueReference().NonConst()) + bCannotBeConst = true; + } + break; + } + else if (auto rangeStmt = dyn_cast(parent)) + { + if (rangeStmt->getRangeStmt() == child) + { + auto tc = loplugin::TypeCheck(rangeStmt->getLoopVariable()->getType()); + if (tc.LvalueReference().NonConst()) + bCannotBeConst = true; + } + break; + } + else if (isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) || isa(parent)) + { + break; + } + else + { + walkUp(); + } + } while (true); + + if (bDump) + { + report(DiagnosticsEngine::Warning, "oh dear, what can the matter be? writtenTo=%0", + memberExpr->getBeginLoc()) + << bCannotBeConst << memberExpr->getSourceRange(); + if (parent) + { + report(DiagnosticsEngine::Note, "parent over here", parent->getBeginLoc()) + << parent->getSourceRange(); + parent->dump(); + } + memberExpr->dump(); + varDecl->getType()->dump(); + } + + if (bCannotBeConst) + cannotBeConstSet.insert(varDecl); +} + +bool ConstVars::IsPassedByNonConst(const VarDecl* varDecl, const Stmt* child, + CallerWrapper callExpr, CalleeWrapper calleeFunctionDecl) +{ + unsigned len = std::min(callExpr.getNumArgs(), calleeFunctionDecl.getNumParams()); + // if it's an array, passing it by value to a method typically means the + // callee takes a pointer and can modify the array + if (varDecl->getType()->isConstantArrayType()) + { + for (unsigned i = 0; i < len; ++i) + if (callExpr.getArg(i) == child) + if (loplugin::TypeCheck(calleeFunctionDecl.getParamType(i)).Pointer().NonConst()) + return true; + } + else + { + for (unsigned i = 0; i < len; ++i) + if (callExpr.getArg(i) == child) + { + auto tc = loplugin::TypeCheck(calleeFunctionDecl.getParamType(i)); + if (tc.LvalueReference().NonConst() || tc.Pointer().NonConst()) + return true; + } + } + return false; +} + +llvm::Optional ConstVars::getCallee(CallExpr const* callExpr) +{ + FunctionDecl const* functionDecl = callExpr->getDirectCallee(); + if (functionDecl) + return CalleeWrapper(functionDecl); + + // Extract the functionprototype from a type + clang::Type const* calleeType = callExpr->getCallee()->getType().getTypePtr(); + if (auto pointerType = calleeType->getUnqualifiedDesugaredType()->getAs()) + { + if (auto prototype = pointerType->getPointeeType() + ->getUnqualifiedDesugaredType() + ->getAs()) + { + return CalleeWrapper(prototype); + } + } + + return llvm::Optional(); +} + +/** off by default because it is very expensive, it walks up the AST a lot */ +loplugin::Plugin::Registration X("constvars", false); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/convertlong.cxx b/compilerplugins/clang/convertlong.cxx new file mode 100644 index 000000000..87b65a43f --- /dev/null +++ b/compilerplugins/clang/convertlong.cxx @@ -0,0 +1,139 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" +#include "check.hxx" + +/** + plugin to help to when converting code from + + sal_uIntPtr/sal_uLong/sal_Long/long/unsigned long + + to something more precise. + */ +namespace +{ +class ConvertLong : public loplugin::FilteringPlugin +{ +public: + explicit ConvertLong(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + // using sal_uIntPtr as in-between type when converting void* to rtl_TextEncoding + if (fn == SRCDIR "/sal/osl/unx/thread.cxx") + return; + // too much magic + if (fn == SRCDIR "/sal/rtl/alloc_arena.cxx") + return; + if (fn == SRCDIR "/sal/rtl/alloc_cache.cxx") + return; + // TODO not sure what is going on here + if (fn == SRCDIR "/tools/source/generic/bigint.cxx") + return; + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitVarDecl(VarDecl const*); + bool TraverseFunctionDecl(FunctionDecl*); + +private: + bool isInterestingType(QualType qt); +}; + +bool ConvertLong::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + // ignore template stuff + if (functionDecl->getTemplatedKind() != FunctionDecl::TK_NonTemplate) + { + return true; + } + return RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); +} + +bool ConvertLong::VisitVarDecl(VarDecl const* varDecl) +{ + if (ignoreLocation(varDecl)) + return true; + StringRef fileName{ getFilenameOfLocation(varDecl->getLocation()) }; + if (loplugin::isSamePathname(fileName, SRCDIR "/include/tools/bigint.hxx")) + return true; + if (loplugin::isSamePathname(fileName, SRCDIR "/include/tools/solar.h")) + return true; + if (!varDecl->hasInit()) + return true; + if (isa(varDecl->getInit()->IgnoreParenImpCasts())) + return true; + // ignore int x = -1; + if (isa(varDecl->getInit()->IgnoreParenImpCasts())) + return true; + auto lhsType = varDecl->getType(); + auto rhsType = varDecl->getInit()->IgnoreParenImpCasts()->getType(); + if (lhsType.getLocalUnqualifiedType() == rhsType) + return true; + if (!rhsType.getTypePtrOrNull()) + return true; + if (isInterestingType(rhsType)) + return true; + if (!isInterestingType(lhsType)) + return true; + if (rhsType->isFloatingType()) // TODO + return true; + report(DiagnosticsEngine::Warning, "rather replace type of decl %0 with %1", + varDecl->getLocation()) + << lhsType << rhsType << varDecl->getSourceRange(); + //lhsType->dump(); + //varDecl->dump(); + return true; +} + +bool ConvertLong::isInterestingType(QualType qt) +{ + auto tc = loplugin::TypeCheck(qt); + if (tc.Typedef()) + { + TypedefType const* typedefType = qt->getAs(); + auto name = typedefType->getDecl()->getName(); + if (name == "sal_uLong") + return true; + // because this is a typedef to long on 64-bit Linux + if (name == "sal_Int64" || name == "sal_uInt64" || name.find("size_t") != StringRef::npos) + return false; + } + if (isa(qt.getTypePtr())) + return false; + auto unqual = qt.getUnqualifiedType(); + if (unqual->isSpecificBuiltinType(BuiltinType::Kind::Long) + || unqual->isSpecificBuiltinType(BuiltinType::Kind::ULong)) + { + return true; + } + if (!tc.Typedef()) + return false; + TypedefType const* typedefType = qt->getAs(); + auto name = typedefType->getDecl()->getName(); + return name == "sal_uIntPtr" || name == "sal_IntPtr"; +} + +loplugin::Plugin::Registration X("convertlong", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/countusersofdefaultparams.cxx b/compilerplugins/clang/countusersofdefaultparams.cxx new file mode 100644 index 000000000..c336509b3 --- /dev/null +++ b/compilerplugins/clang/countusersofdefaultparams.cxx @@ -0,0 +1,250 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#include "clang/AST/Attr.h" + +#include "config_clang.h" + +#include "plugin.hxx" + +/* + Count call sites that are actually using the defaulted values on params on methods that declare such. + + The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='countusersofdefaultparams' check + $ ./compilerplugins/clang/countusersofdefaultparams.py +*/ + +namespace { + +struct MyFuncInfo +{ + std::string access; + std::string returnType; + std::string nameAndParams; + std::string sourceLocation; +}; +bool operator < (const MyFuncInfo &lhs, const MyFuncInfo &rhs) +{ + return std::tie(lhs.returnType, lhs.nameAndParams) + < std::tie(rhs.returnType, rhs.nameAndParams); +} +struct MyCallInfo : public MyFuncInfo +{ + std::string sourceLocationOfCall; +}; +bool operator < (const MyCallInfo &lhs, const MyCallInfo &rhs) +{ + return std::tie(lhs.returnType, lhs.nameAndParams, lhs.sourceLocationOfCall) + < std::tie(rhs.returnType, rhs.nameAndParams, rhs.sourceLocationOfCall); +} + + +// try to limit the voluminous output a little +static std::set callSet; +static std::set definitionSet; + +class CountUsersOfDefaultParams: + public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit CountUsersOfDefaultParams(loplugin::InstantiationData const & data): Plugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + + std::string output; + for (const MyFuncInfo & s : definitionSet) + output += "defn:\t" + s.access + "\t" + s.returnType + "\t" + s.nameAndParams + "\t" + s.sourceLocation + "\n"; + for (const MyCallInfo & s : callSet) + output += "call:\t" + s.returnType + "\t" + s.nameAndParams + "\t" + s.sourceLocationOfCall + "\n"; + std::ofstream myfile; + myfile.open( WORKDIR "/loplugin.countusersofdefaultparams.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + + bool shouldVisitTemplateInstantiations () const { return true; } + + bool VisitCallExpr( const CallExpr * ); + bool VisitFunctionDecl( const FunctionDecl* ); + bool VisitCXXConstructExpr( const CXXConstructExpr * ); +private: + void niceName(const FunctionDecl* functionDecl, MyFuncInfo&); + std::string locationToString(const SourceLocation&); +}; + +void CountUsersOfDefaultParams::niceName(const FunctionDecl* functionDecl, MyFuncInfo& aInfo) +{ + if (functionDecl->getInstantiatedFromMemberFunction()) + functionDecl = functionDecl->getInstantiatedFromMemberFunction(); + else if (functionDecl->getTemplateInstantiationPattern()) + functionDecl = functionDecl->getTemplateInstantiationPattern(); + + switch (functionDecl->getAccess()) + { + case AS_public: aInfo.access = "public"; break; + case AS_private: aInfo.access = "private"; break; + case AS_protected: aInfo.access = "protected"; break; + default: aInfo.access = "unknown"; break; + } + aInfo.returnType = functionDecl->getReturnType().getCanonicalType().getAsString(); + + if (isa(functionDecl)) { + const CXXRecordDecl* recordDecl = dyn_cast(functionDecl)->getParent(); + aInfo.nameAndParams += recordDecl->getQualifiedNameAsString(); + aInfo.nameAndParams += "::"; + } + aInfo.nameAndParams += functionDecl->getNameAsString() + "("; + bool bFirst = true; + for (const ParmVarDecl *pParmVarDecl : functionDecl->parameters()) { + if (bFirst) + bFirst = false; + else + aInfo.nameAndParams += ","; + aInfo.nameAndParams += pParmVarDecl->getType().getCanonicalType().getAsString(); + } + aInfo.nameAndParams += ")"; + if (isa(functionDecl) && dyn_cast(functionDecl)->isConst()) { + aInfo.nameAndParams += " const"; + } + + aInfo.sourceLocation = locationToString(functionDecl->getLocation()); + loplugin::normalizeDotDotInFilePath(aInfo.sourceLocation); +} + +bool CountUsersOfDefaultParams::VisitCallExpr(const CallExpr * callExpr) { + if (ignoreLocation(callExpr)) { + return true; + } + const FunctionDecl* functionDecl; + if (isa(callExpr)) { + functionDecl = dyn_cast(callExpr)->getMethodDecl(); + } + else { + functionDecl = callExpr->getDirectCallee(); + } + if (functionDecl == nullptr) { + return true; + } + functionDecl = functionDecl->getCanonicalDecl(); + // work our way up to the root method + while (isa(functionDecl)) { + const CXXMethodDecl* methodDecl = dyn_cast(functionDecl); + if (methodDecl->size_overridden_methods()==0) + break; + functionDecl = *methodDecl->begin_overridden_methods(); + } + // work our way back to the root definition for template methods + if (functionDecl->getInstantiatedFromMemberFunction()) + functionDecl = functionDecl->getInstantiatedFromMemberFunction(); + else if (functionDecl->getTemplateInstantiationPattern()) + functionDecl = functionDecl->getTemplateInstantiationPattern(); + int n = functionDecl->getNumParams() - 1; + if (n < 0 || !functionDecl->getParamDecl(n)->hasDefaultArg()) { + return true; + } + while (n > 0 && functionDecl->getParamDecl(n-1)->hasDefaultArg()) { + --n; + } + // look for callsites that are actually using the defaulted values + if ( n < (int)callExpr->getNumArgs() && callExpr->getArg(n)->isDefaultArgument()) { + MyCallInfo callInfo; + niceName(functionDecl, callInfo); + callInfo.sourceLocationOfCall = locationToString(callExpr->getBeginLoc()); + callSet.insert(callInfo); + } + return true; +} + +bool CountUsersOfDefaultParams::VisitCXXConstructExpr(const CXXConstructExpr * constructExpr) { + if (ignoreLocation(constructExpr)) { + return true; + } + const CXXConstructorDecl* constructorDecl = constructExpr->getConstructor()->getCanonicalDecl(); + // work our way back to the root definition for template methods + if (constructorDecl->getInstantiatedFromMemberFunction()) + constructorDecl = dyn_cast(constructorDecl->getInstantiatedFromMemberFunction()); + else if (constructorDecl->getTemplateInstantiationPattern()) + constructorDecl = dyn_cast(constructorDecl->getTemplateInstantiationPattern()); + int n = constructorDecl->getNumParams() - 1; + if (n < 0 || !constructorDecl->getParamDecl(n)->hasDefaultArg()) { + return true; + } + while (n > 0 && constructorDecl->getParamDecl(n-1)->hasDefaultArg()) { + --n; + } + // look for callsites that are actually using the defaulted values + if ( n < (int)constructExpr->getNumArgs() && constructExpr->getArg(n)->isDefaultArgument()) { + MyCallInfo callInfo; + niceName(constructorDecl, callInfo); + callInfo.sourceLocationOfCall = locationToString(constructExpr->getBeginLoc()); + callSet.insert(callInfo); + } + return true; +} + +std::string CountUsersOfDefaultParams::locationToString(const SourceLocation& sourceLoc) +{ + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( sourceLoc ); + StringRef name = getFilenameOfLocation(expansionLoc); + return std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); +} + +bool CountUsersOfDefaultParams::VisitFunctionDecl( const FunctionDecl* functionDecl ) +{ + functionDecl = functionDecl->getCanonicalDecl(); + if( !functionDecl || !functionDecl->getLocation().isValid() || ignoreLocation( functionDecl )) { + return true; + } + const CXXMethodDecl* methodDecl = dyn_cast_or_null(functionDecl); + + // ignore method overrides, since the call will show up as being directed to the root method + if (methodDecl && (methodDecl->size_overridden_methods() != 0 || methodDecl->hasAttr())) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) { + return true; + } + if (isa(functionDecl)) { + return true; + } + if (functionDecl->isDeleted()) { + return true; + } + auto n = functionDecl->getNumParams(); + if (n == 0 || !functionDecl->getParamDecl(n - 1)->hasDefaultArg()) { + return true; + } + + if( functionDecl->getLocation().isValid() ) + { + MyFuncInfo funcInfo; + niceName(functionDecl, funcInfo); + definitionSet.insert(funcInfo); + } + return true; +} + +loplugin::Plugin::Registration< CountUsersOfDefaultParams > X("countusersofdefaultparams", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/countusersofdefaultparams.py b/compilerplugins/clang/countusersofdefaultparams.py new file mode 100755 index 000000000..a53c17283 --- /dev/null +++ b/compilerplugins/clang/countusersofdefaultparams.py @@ -0,0 +1,81 @@ +#!/usr/bin/python + +import sys +import re +import io + +definitionToSourceLocationMap = dict() +callDict = dict() + +# clang does not always use exactly the same numbers in the type-parameter vars it generates +# so I need to substitute them to ensure we can match correctly. +normalizeTypeParamsRegex1 = re.compile(r"type-parameter-\d+-\d+") +normalizeTypeParamsRegex2 = re.compile(r"typename enable_if<.*") +def normalizeTypeParams( line ): + line = normalizeTypeParamsRegex1.sub("type-parameter-?-?", line) + return normalizeTypeParamsRegex2.sub("type-parameter-?-?", line) + +with io.open("workdir/loplugin.countusersofdefaultparams.log", "rb", buffering=1024*1024) as txt: + for line in txt: + tokens = line.strip().split("\t") + if tokens[0] == "defn:": + access = tokens[1] + returnType = tokens[2] + nameAndParams = tokens[3] + sourceLocation = tokens[4] + funcInfo = normalizeTypeParams(returnType) + " " + normalizeTypeParams(nameAndParams) + definitionToSourceLocationMap[funcInfo] = sourceLocation + if not funcInfo in callDict: + callDict[funcInfo] = set() + elif tokens[0] == "call:": + returnType = tokens[1] + nameAndParams = tokens[2] + sourceLocationOfCall = tokens[3] + funcInfo = normalizeTypeParams(returnType) + " " + normalizeTypeParams(nameAndParams) + if not funcInfo in callDict: + callDict[funcInfo] = set() + callDict[funcInfo].add(sourceLocationOfCall) + else: + print( "unknown line: " + line) + +tmp1list = list() +for k,v in callDict.iteritems(): + if len(v) >= 1: + continue + # created by macros + if k.endswith("::RegisterInterface(class SfxModule *)"): + continue + if k.endswith("::RegisterChildWindow(_Bool,class SfxModule *,enum SfxChildWindowFlags)"): + continue + if k.endswith("::RegisterControl(unsigned short,class SfxModule *)"): + continue + if k.endswith("::RegisterFactory(unsigned short)"): + continue + # windows-only stuff + if "ShutdownIcon::OpenURL" in k: + continue + # template magic + if k.startswith("void VclPtr::VclPtr(const VclPtr &,typename UpCast<"): + continue + if k in definitionToSourceLocationMap: + tmp1list.append((k, definitionToSourceLocationMap[k])) + +# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[1]) + [v[0]] + +# sort results by name and line number +tmp1list.sort(key=lambda v: v_sort_key(v)) + +# print out the results +with open("loplugin.countusersofdefaultparams.report", "wt") as f: + for t in tmp1list: + f.write(t[1] + "\n") + f.write(" " + t[0] + "\n") + + diff --git a/compilerplugins/clang/cow_wrapper.cxx b/compilerplugins/clang/cow_wrapper.cxx new file mode 100644 index 000000000..c98f70cbe --- /dev/null +++ b/compilerplugins/clang/cow_wrapper.cxx @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include +#include +#include "plugin.hxx" +#include "check.hxx" + +/* +Look for places where we are using cow_wrapper, but we are calling a const method on the impl object +with a non-const pointer, which means we will unnecessarily trigger a copy. +*/ + +namespace +{ +class Cow_Wrapper : public loplugin::FilteringPlugin +{ +public: + explicit Cow_Wrapper(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual bool preRun() override { return true; } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr*); +}; + +bool Cow_Wrapper::VisitCXXMemberCallExpr(const CXXMemberCallExpr* memberCallExpr) +{ + if (ignoreLocation(memberCallExpr)) + return true; + auto methodDecl = memberCallExpr->getMethodDecl(); + if (!methodDecl || !methodDecl->isConst()) + return true; + + auto expr = memberCallExpr->getImplicitObjectArgument()->IgnoreImplicit()->IgnoreParens(); + auto operatorCallExpr = dyn_cast(expr); + + if (operatorCallExpr && operatorCallExpr->getOperator() == OO_Arrow) + { + auto arrowMethodDecl = dyn_cast_or_null(operatorCallExpr->getDirectCallee()); + if (!arrowMethodDecl) + return true; + if (arrowMethodDecl->isConst()) + return true; + auto dc = loplugin::DeclCheck(arrowMethodDecl->getParent()) + .Class("cow_wrapper") + .Namespace("o3tl") + .GlobalNamespace(); + if (!dc) + return true; + } + else if (operatorCallExpr) + { + auto methodDecl2 = dyn_cast_or_null(operatorCallExpr->getDirectCallee()); + if (!methodDecl2) + return true; + auto dc = loplugin::DeclCheck(methodDecl2->getParent()) + .Class("cow_wrapper") + .Namespace("o3tl") + .GlobalNamespace(); + if (!dc) + return true; + } + else if (auto callExpr = dyn_cast(expr)) + { + if (!isa(callExpr->getCallee())) // std::as_const shows up as this + return true; + if (callExpr->getNumArgs() < 1) + return true; + auto arg0 = dyn_cast(callExpr->getArg(0)); + if (!arg0) + return true; + auto starMethodDecl = dyn_cast_or_null(arg0->getDirectCallee()); + if (!starMethodDecl) + return true; + auto dc = loplugin::DeclCheck(starMethodDecl->getParent()) + .Class("cow_wrapper") + .Namespace("o3tl") + .GlobalNamespace(); + if (!dc) + return true; + } + else + return true; + + report(DiagnosticsEngine::Warning, + "calling const method on o3tl::cow_wrapper impl class via non-const pointer, rather use " + "std::as_const to prevent triggering an unnecessary copy", + memberCallExpr->getBeginLoc()) + << memberCallExpr->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration cow_wrapper("cow_wrapper", true); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/cppunitassertequals.cxx b/compilerplugins/clang/cppunitassertequals.cxx new file mode 100644 index 000000000..56f13b822 --- /dev/null +++ b/compilerplugins/clang/cppunitassertequals.cxx @@ -0,0 +1,240 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" +#include "check.hxx" +#include "compat.hxx" +#include + +/** + Check for + (*) calls to CPPUNIT_ASSERT when it should be using CPPUNIT_ASSERT_EQUALS + (*) calls to CPPUNIT_ASSERT_EQUALS where the constant is the second param +*/ + +namespace { + +class CppunitAssertEquals: + public loplugin::FilteringPlugin +{ +public: + explicit CppunitAssertEquals(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual bool preRun() override + { + return compiler.getLangOpts().CPlusPlus; + } + + virtual void run() override + { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitCallExpr(const CallExpr*); + +private: + void checkExpr( + SourceRange range, StringRef name, Expr const * expr, bool negated); + + void reportEquals( + SourceRange range, StringRef name, bool negative, Expr const * lhs, Expr const * rhs); + + bool isCompileTimeConstant(Expr const * expr); +}; + +bool CppunitAssertEquals::VisitCallExpr(const CallExpr* callExpr) +{ + auto const decl = callExpr->getDirectCallee(); + if (!decl) + return true; + /* + calls to CPPUNIT_ASSERT when it should be using CPPUNIT_ASSERT_EQUALS + */ + if (loplugin::DeclCheck(decl).Function("failIf").Struct("Asserter") + .Namespace("CppUnit").GlobalNamespace()) + { + // Don't use callExpr->getLocStart() or callExpr->getExprLoc(), as those + // fall into a nested use of the CPPUNIT_NS macro; CallExpr::getRParenLoc + // happens to be readily available and cause good results: + auto loc = callExpr->getRParenLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(loc)) { + loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc); + } + if (!compiler.getSourceManager().isMacroBodyExpansion(loc) + || ignoreLocation( + compiler.getSourceManager().getImmediateMacroCallerLoc(loc))) + { + return true; + } + auto name = Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()); + if (name != "CPPUNIT_ASSERT" && name != "CPPUNIT_ASSERT_MESSAGE") { + return true; + } + if (decl->getNumParams() != 3) { + report( + DiagnosticsEngine::Warning, + ("TODO: suspicious CppUnit::Asserter::failIf call with %0" + " parameters"), + callExpr->getExprLoc()) + << decl->getNumParams() << callExpr->getSourceRange(); + return true; + } + auto const e1 = callExpr->getArg(0)->IgnoreParenImpCasts(); + Expr const * e2 = nullptr; + if (auto const e3 = dyn_cast(e1)) { + if (e3->getOpcode() == UO_LNot) { + e2 = e3->getSubExpr(); + } + } else if (auto const e4 = dyn_cast(e1)) { + if (e4->getOperator() == OO_Exclaim) { + e2 = e4->getArg(0); + } + } + if (e2 == nullptr) { + report( + DiagnosticsEngine::Warning, + ("TODO: suspicious CppUnit::Asserter::failIf call not wrapping" + " !(...)"), + callExpr->getExprLoc()) + << callExpr->getSourceRange(); + return true; + } + auto range = compat::getImmediateExpansionRange(compiler.getSourceManager(), loc); + checkExpr( + SourceRange(range.first, range.second), name, + e2->IgnoreParenImpCasts(), false); + } + + /** + Check for calls to CPPUNIT_ASSERT_EQUALS where the constant is the second param + */ + if (loplugin::DeclCheck(decl).Function("assertEquals"). + Namespace("CppUnit").GlobalNamespace()) + { + // can happen in template test code that both params are compile time constants + if (isCompileTimeConstant(callExpr->getArg(0))) + return true; + if (isCompileTimeConstant(callExpr->getArg(1))) + report( + DiagnosticsEngine::Warning, + "CPPUNIT_ASSERT_EQUALS parameters look switched, expected value should be first param", + callExpr->getExprLoc()) + << callExpr->getSourceRange(); + } + return true; +} + +// copied from stringconcat.cxx +Expr const * stripConstructor(Expr const * expr) { + auto e0 = expr; + auto const e1 = dyn_cast(e0); + if (e1 != nullptr) { + e0 = e1->getSubExpr()->IgnoreParenImpCasts(); + } + auto const e2 = dyn_cast(e0); + if (e2 == nullptr) { + return expr; + } + auto const e3 = dyn_cast( + e2->getSubExpr()->IgnoreParenImpCasts()); + if (e3 == nullptr) { + return expr; + } + auto qt = loplugin::DeclCheck(e3->getConstructor()); + if (!((qt.MemberFunction().Class("OString").Namespace("rtl") + .GlobalNamespace()) + || (qt.MemberFunction().Class("OUString").Namespace("rtl") + .GlobalNamespace()))) + { + return expr; + } + if (e3->getNumArgs() != 2) { + return expr; + } + return e3->getArg(0)->IgnoreParenImpCasts(); +} + +bool CppunitAssertEquals::isCompileTimeConstant(Expr const * expr) +{ + if (expr->isIntegerConstantExpr(compiler.getASTContext())) + return true; + // is string literal ? + expr = expr->IgnoreParenImpCasts(); + expr = stripConstructor(expr); + return isa(expr); +} + +void CppunitAssertEquals::checkExpr( + SourceRange range, StringRef name, Expr const * expr, bool negated) +{ + if (auto const e = dyn_cast(expr)) { + if (e->getOpcode() == UO_LNot) { + checkExpr( + range, name, e->getSubExpr()->IgnoreParenImpCasts(), !negated); + } + return; + } + if (auto const e = dyn_cast(expr)) { + auto const op = e->getOpcode(); + if ((!negated && op == BO_EQ) || (negated && op == BO_NE)) { + reportEquals(range, name, op == BO_NE, e->getLHS(), e->getRHS()); + return; + } + if ((!negated && op == BO_LAnd) || (negated && op == BO_LOr)) { + report( + DiagnosticsEngine::Warning, + "rather split into two %0", e->getExprLoc()) + << name << range; + return; + } + return; + } + if (auto const e = dyn_cast(expr)) { + auto const op = e->getOperator(); + if ((!negated && op == OO_EqualEqual) + || (negated && op == OO_ExclaimEqual)) + { + reportEquals(range, name, op == OO_ExclaimEqual, e->getArg(0), e->getArg(1)); + return; + } + return; + } +} + +void CppunitAssertEquals::reportEquals( + SourceRange range, StringRef name, bool negative, Expr const * lhs, Expr const * rhs) +{ + if (lhs->IgnoreImpCasts()->getType()->isNullPtrType() + != rhs->IgnoreImpCasts()->getType()->isNullPtrType()) + { + return; + } + report( + DiagnosticsEngine::Warning, + ("rather call" + " %select{CPPUNIT_ASSERT_EQUAL|CPPUNIT_ASSERT_EQUAL_MESSAGE}0 when comparing %1 and %2 (or" + " rewrite as an explicit operator %select{==|!=}3 call when the" + " operator itself is the topic)"), + range.getBegin()) + << (name == "CPPUNIT_ASSERT_MESSAGE") << lhs->IgnoreImpCasts()->getType() + << rhs->IgnoreImpCasts()->getType() << negative << range; +} + +loplugin::Plugin::Registration< CppunitAssertEquals > cppunitassertequals("cppunitassertequals"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/cstylecast.cxx b/compilerplugins/clang/cstylecast.cxx new file mode 100644 index 000000000..35292ecd8 --- /dev/null +++ b/compilerplugins/clang/cstylecast.cxx @@ -0,0 +1,707 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "compat.hxx" +#include "plugin.hxx" + +// +// We don't like using C-style casts in C++ code. Similarly, warn about function-style casts (which +// are semantically equivalent to C-style casts) that are not semantically equivalent to static_cast +// and should rather be written as const_cast or reinterpret_cast. +// + +namespace { + +bool areSimilar(QualType type1, QualType type2) { + auto t1 = type1.getCanonicalType().getTypePtr(); + auto t2 = type2.getCanonicalType().getTypePtr(); + for (;;) { + if (t1->isPointerType()) { + if (!t2->isPointerType()) { + return false; + } + auto t1a = t1->getAs(); + auto t2a = t2->getAs(); + t1 = t1a->getPointeeType().getTypePtr(); + t2 = t2a->getPointeeType().getTypePtr(); + } else if (t1->isMemberPointerType()) { + if (!t2->isMemberPointerType()) { + return false; + } + auto t1a = t1->getAs(); + auto t2a = t2->getAs(); + if (t1a->getClass()->getCanonicalTypeInternal() + != t2a->getClass()->getCanonicalTypeInternal()) + { + return false; + } + t1 = t1a->getPointeeType().getTypePtr(); + t2 = t2a->getPointeeType().getTypePtr(); + } else if (t1->isConstantArrayType()) { + if (!t2->isConstantArrayType()) { + return false; + } + auto t1a = static_cast( + t1->getAsArrayTypeUnsafe()); + auto t2a = static_cast( + t2->getAsArrayTypeUnsafe()); + if (t1a->getSize() != t2a->getSize()) { + return false; + } + t1 = t1a->getElementType().getTypePtr(); + t2 = t2a->getElementType().getTypePtr(); + } else if (t1->isIncompleteArrayType()) { + if (!t2->isIncompleteArrayType()) { + return false; + } + auto t1a = static_cast( + t1->getAsArrayTypeUnsafe()); + auto t2a = static_cast( + t2->getAsArrayTypeUnsafe()); + t1 = t1a->getElementType().getTypePtr(); + t2 = t2a->getElementType().getTypePtr(); + } else { + return false; + } + if (t1 == t2) { + return true; + } + } +} + +QualType resolvePointers(QualType type) { + while (type->isPointerType()) { + type = type->getAs()->getPointeeType(); + } + return type; +} + +bool isLiteralLike(Expr const * expr) { + expr = expr->IgnoreParenImpCasts(); + if (isa(expr) || isa(expr) || isa(expr) + || isa(expr) || isa(expr) + || isa(expr) || isa(expr)) + { + return true; + } + if (auto const e = dyn_cast(expr)) { + auto const d = e->getDecl(); + if (isa(d)) { + return true; + } + if (auto const v = dyn_cast(d)) { + if (d->getType().isConstQualified()) { + if (auto const init = v->getAnyInitializer()) { + return isLiteralLike(init); + } + } + } + return false; + } + if (auto const e = dyn_cast(expr)) { + auto const k = e->getKind(); + return k == UETT_SizeOf || k == UETT_AlignOf; + } + if (auto const e = dyn_cast(expr)) { + auto const k = e->getOpcode(); + if (k == UO_Plus || k == UO_Minus || k == UO_Not || k == UO_LNot) { + return isLiteralLike(e->getSubExpr()); + } + return false; + } + if (auto const e = dyn_cast(expr)) { + auto const k = e->getOpcode(); + if (k == BO_Mul || k == BO_Div || k == BO_Rem || k == BO_Add || k == BO_Sub || k == BO_Shl + || k == BO_Shr || k == BO_And || k == BO_Xor || k == BO_Or) + { + return isLiteralLike(e->getLHS()) && isLiteralLike(e->getRHS()); + } + return false; + } + if (auto const e = dyn_cast(expr)) { + auto const t = e->getTypeAsWritten(); + return (t->isArithmeticType() || t->isEnumeralType()) + && isLiteralLike(e->getSubExprAsWritten()); + } + return false; +} + +bool canBeUsedForFunctionalCast(TypeSourceInfo const * info) { + // Must be or , lets approximate that here: + assert(info != nullptr); + auto const type = info->getType(); + if (type.hasLocalQualifiers()) { + return false; + } + if (auto const t = dyn_cast(type)) { + if (!(t->isInteger() || t->isFloatingPoint())) { + return false; + } + auto const loc = info->getTypeLoc().castAs(); + return + (int(loc.hasWrittenSignSpec()) + int(loc.hasWrittenWidthSpec()) + + int(loc.hasWrittenTypeSpec())) + == 1; + } + if (isa(type) || isa(type) || isa(type) + || isa(type) || isa(type)) + { + return true; + } + if (auto const t = dyn_cast(type)) { + return t->getKeyword() == ETK_None; + } + return false; +} + +class CStyleCast: + public loplugin::FilteringRewritePlugin +{ +public: + explicit CStyleCast(loplugin::InstantiationData const & data): FilteringRewritePlugin(data) + {} + + virtual void run() override { + if (compiler.getLangOpts().CPlusPlus) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool TraverseInitListExpr(InitListExpr * expr, DataRecursionQueue * queue = nullptr) { + return WalkUpFromInitListExpr(expr) + && TraverseSynOrSemInitListExpr( + expr->isSemanticForm() ? expr : expr->getSemanticForm(), queue); + } + + bool TraverseLinkageSpecDecl(LinkageSpecDecl * decl); + + bool VisitCStyleCastExpr(const CStyleCastExpr * expr); + + bool VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const * expr); + +private: + bool isConstCast(QualType from, QualType to); + + bool isFromCIncludeFile(SourceLocation spellingLocation) const; + + bool isSharedCAndCppCode(SourceLocation location) const; + + bool isLastTokenOfImmediateMacroBodyExpansion( + SourceLocation loc, SourceLocation * macroEnd = nullptr) const; + + bool rewriteArithmeticCast(CStyleCastExpr const * expr, char const ** replacement); + + void reportCast(ExplicitCastExpr const * expr, char const * performsHint); + + unsigned int externCContexts_ = 0; + std::set rewritten_; + // needed when rewriting in macros, in general to avoid "double code replacement, possible + // plugin error" warnings, and in particular to avoid adding multiple sets of parens around + // sub-exprs + std::set rewrittenSubExprs_; +}; + +const char * recommendedFix(clang::CastKind ck) { + switch(ck) { + case CK_IntegralToPointer: return "reinterpret_cast"; + case CK_PointerToIntegral: return "reinterpret_cast"; + case CK_BaseToDerived: return "static_cast"; + default: return nullptr; + } +} + +bool CStyleCast::TraverseLinkageSpecDecl(LinkageSpecDecl * decl) { + assert(externCContexts_ != std::numeric_limits::max()); //TODO + ++externCContexts_; + bool ret = RecursiveASTVisitor::TraverseLinkageSpecDecl(decl); + assert(externCContexts_ != 0); + --externCContexts_; + return ret; +} + +bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) { + if (ignoreLocation(expr)) { + return true; + } + // casting to void is typically used when a parameter or field is only used in + // debug mode, and we want to eliminate an "unused" warning + if( expr->getCastKind() == CK_ToVoid ) { + return true; + } + if (isSharedCAndCppCode(expr->getBeginLoc())) { + return true; + } + char const * perf = nullptr; + if( expr->getCastKind() == CK_IntegralCast ) { + if (rewriteArithmeticCast(expr, &perf)) { + return true; + } + } else if( expr->getCastKind() == CK_NoOp ) { + if (!((expr->getSubExpr()->getType()->isPointerType() + && expr->getType()->isPointerType()) + || expr->getTypeAsWritten()->isReferenceType())) + { + if (rewriteArithmeticCast(expr, &perf)) { + return true; + } + } + if (isConstCast( + expr->getSubExprAsWritten()->getType(), + expr->getTypeAsWritten())) + { + perf = "const_cast"; + } + } + reportCast(expr, perf); + return true; +} + +bool CStyleCast::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + char const * perf = nullptr; + switch (expr->getCastKind()) { + case CK_ConstructorConversion: + case CK_Dependent: //TODO: really filter out all of these? + case CK_IntegralCast: + case CK_IntegralToBoolean: + case CK_ToVoid: + return true; + case CK_NoOp: + if (isConstCast( + expr->getSubExprAsWritten()->getType(), + expr->getTypeAsWritten())) + { + perf = "const_cast"; + break; + } + return true; //TODO: really filter out all of these? + default: + break; + } + reportCast(expr, perf); + return true; +} + +bool CStyleCast::isConstCast(QualType from, QualType to) { + if (to->isReferenceType() + && to->getAs()->getPointeeType()->isObjectType()) + { + if (!from->isObjectType()) { + return false; + } + from = compiler.getASTContext().getPointerType(from); + to = compiler.getASTContext().getPointerType( + to->getAs()->getPointeeType()); + } else { + if (from->isArrayType()) { + from = compiler.getASTContext().getPointerType( + from->getAsArrayTypeUnsafe()->getElementType()); + } else if (from->isFunctionType()) { + compiler.getASTContext().getPointerType(from); + } + } + return areSimilar(from, to); +} + +bool CStyleCast::isFromCIncludeFile(SourceLocation spellingLocation) const { + return !compiler.getSourceManager().isInMainFile(spellingLocation) + && (StringRef( + compiler.getSourceManager().getPresumedLoc(spellingLocation) + .getFilename()) + .endswith(".h")); +} + +bool CStyleCast::isSharedCAndCppCode(SourceLocation location) const { + while (compiler.getSourceManager().isMacroArgExpansion(location)) { + location = compiler.getSourceManager().getImmediateMacroCallerLoc( + location); + } + // Assume that code is intended to be shared between C and C++ if it comes + // from an include file ending in .h, and is either in an extern "C" context + // or the body of a macro definition: + return + isFromCIncludeFile(compiler.getSourceManager().getSpellingLoc(location)) + && (externCContexts_ != 0 + || compiler.getSourceManager().isMacroBodyExpansion(location)); +} + +bool CStyleCast::isLastTokenOfImmediateMacroBodyExpansion( + SourceLocation loc, SourceLocation * macroEnd) const +{ + assert(compiler.getSourceManager().isMacroBodyExpansion(loc)); + auto const spell = compiler.getSourceManager().getSpellingLoc(loc); + auto name = Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()); + while (name.startswith("\\\n")) { + name = name.drop_front(2); + while (!name.empty() + && (name.front() == ' ' || name.front() == '\t' || name.front() == '\n' + || name.front() == '\v' || name.front() == '\f')) + { + name = name.drop_front(1); + } + } + auto const MI + = (compiler.getPreprocessor().getMacroDefinitionAtLoc( + &compiler.getASTContext().Idents.get(name), spell) + .getMacroInfo()); + assert(MI != nullptr); + if (spell == MI->getDefinitionEndLoc()) { + if (macroEnd != nullptr) { + *macroEnd = compat::getImmediateExpansionRange(compiler.getSourceManager(), loc).second; + } + return true; + } + return false; +} + +bool CStyleCast::rewriteArithmeticCast(CStyleCastExpr const * expr, char const ** replacement) { + assert(replacement != nullptr); + auto const sub = expr->getSubExprAsWritten(); + auto const functional = isLiteralLike(sub) + && canBeUsedForFunctionalCast(expr->getTypeInfoAsWritten()); + *replacement = functional ? "functional cast" : "static_cast"; + if (rewriter == nullptr) { + return false; + } + // Doing modifications for a chain of C-style casts as in + // + // (foo)(bar)(baz)x + // + // leads to unpredictable results, so only rewrite them one at a time, starting with the + // outermost: + if (auto const e = dyn_cast(sub)) { + rewrittenSubExprs_.insert(e); + } + if (rewrittenSubExprs_.find(expr) != rewrittenSubExprs_.end()) { + return false; + } + // Two or four ranges to replace: + // First is the CStyleCast's LParen, plus following whitespace, replaced with either "" or + // "static_cast<". (TODO: insert space before "static_cast<" when converting "else(int)...".) + // Second is the CStyleCast's RParen, plus preceding and following whitespace, replaced with + // either "" or ">". + // If the sub expr is not a ParenExpr, third is the sub expr's begin, inserting "(", and fourth + // is the sub expr's end, inserting ")". + // (The reason the second and third are not combined is in case there's a comment between them.) + auto firstBegin = expr->getLParenLoc(); + auto secondBegin = expr->getRParenLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(firstBegin) + && compiler.getSourceManager().isMacroArgExpansion(secondBegin) + && (compat::getImmediateExpansionRange(compiler.getSourceManager(), firstBegin) + == compat::getImmediateExpansionRange(compiler.getSourceManager(), secondBegin))) + { + firstBegin = compiler.getSourceManager().getImmediateSpellingLoc(firstBegin); + secondBegin = compiler.getSourceManager().getImmediateSpellingLoc(secondBegin); + } + if (compiler.getSourceManager().isMacroBodyExpansion(firstBegin) + && compiler.getSourceManager().isMacroBodyExpansion(secondBegin) + && (compiler.getSourceManager().getImmediateMacroCallerLoc(firstBegin) + == compiler.getSourceManager().getImmediateMacroCallerLoc(secondBegin))) + { + firstBegin = compiler.getSourceManager().getSpellingLoc(firstBegin); + secondBegin = compiler.getSourceManager().getSpellingLoc(secondBegin); + } + auto third = sub->getBeginLoc(); + auto fourth = sub->getEndLoc(); + bool macro = false; + // Ensure that + // + // #define FOO(x) (int)x + // FOO(y) + // + // is changed to + // + // #define FOO(x) static_cast(x) + // FOO(y) + // + // instead of + // + // #define FOO(x) static_castx + // FOO((y)) + while (compiler.getSourceManager().isMacroArgExpansion(third) + && compiler.getSourceManager().isMacroArgExpansion(fourth) + && (compat::getImmediateExpansionRange(compiler.getSourceManager(), third) + == compat::getImmediateExpansionRange(compiler.getSourceManager(), fourth)) + && compiler.getSourceManager().isAtStartOfImmediateMacroExpansion(third)) + //TODO: check fourth is at end of immediate macro expansion, but + // SourceManager::isAtEndOfImmediateMacroExpansion requires a location pointing at the + // character end of the last token + { + auto const range = compat::getImmediateExpansionRange(compiler.getSourceManager(), third); + third = range.first; + fourth = range.second; + macro = true; + assert(third.isValid()); + } + while (compiler.getSourceManager().isMacroArgExpansion(third) + && compiler.getSourceManager().isMacroArgExpansion(fourth) + && (compat::getImmediateExpansionRange(compiler.getSourceManager(), third) + == compat::getImmediateExpansionRange(compiler.getSourceManager(), fourth))) + { + third = compiler.getSourceManager().getImmediateSpellingLoc(third); + fourth = compiler.getSourceManager().getImmediateSpellingLoc(fourth); + } + if (isa(sub)) { + // Ensure that with + // + // #define FOO (x) + // + // a cast like + // + // (int) FOO + // + // is changed to + // + // static_cast(FOO) + // + // instead of + // + // static_castFOO + for (;; macro = true) { + if (!(compiler.getSourceManager().isMacroBodyExpansion(third) + && compiler.getSourceManager().isMacroBodyExpansion(fourth) + && (compiler.getSourceManager().getImmediateMacroCallerLoc(third) + == compiler.getSourceManager().getImmediateMacroCallerLoc(fourth)) + && compiler.getSourceManager().isAtStartOfImmediateMacroExpansion(third) + && isLastTokenOfImmediateMacroBodyExpansion(fourth))) + { + if (!macro) { + third = fourth = SourceLocation(); + } + break; + } + auto const range = compat::getImmediateExpansionRange( + compiler.getSourceManager(), third); + third = range.first; + fourth = range.second; + assert(third.isValid()); + } + if (third.isValid() && compiler.getSourceManager().isMacroBodyExpansion(third) + && compiler.getSourceManager().isMacroBodyExpansion(fourth) + && (compiler.getSourceManager().getImmediateMacroCallerLoc(third) + == compiler.getSourceManager().getImmediateMacroCallerLoc(fourth))) + { + third = compiler.getSourceManager().getSpellingLoc(third); + fourth = compiler.getSourceManager().getSpellingLoc(fourth); + assert(third.isValid()); + } + } else { + // Ensure that a cast like + // + // (int)LONG_MAX + // + // (where LONG_MAX expands to __LONG_MAX__, which in turn is a built-in expanding to a value + // like 9223372036854775807L) is changed to + // + // int(LONG_MAX) + // + // instead of trying to add the parentheses to the built-in __LONG_MAX__ definition: + for (;;) { + if (!(compiler.getSourceManager().isMacroBodyExpansion(third) + && compiler.getSourceManager().isMacroBodyExpansion(fourth) + && (compiler.getSourceManager().getImmediateMacroCallerLoc(third) + == compiler.getSourceManager().getImmediateMacroCallerLoc(fourth)) + && compiler.getSourceManager().isAtStartOfImmediateMacroExpansion(third))) + // TODO: check that fourth is at end of immediate macro expansion (but + // SourceManager::isAtEndOfImmediateMacroExpansion wants a location pointing at the + // character end) + { + break; + } + auto const range = compat::getImmediateExpansionRange( + compiler.getSourceManager(), third); + third = range.first; + fourth = range.second; + } + // ...and additionally asymmetrically unwind macros only at the start or end, for code like + // + // (long)ubidi_getVisualIndex(...) + // + // (in editeng/source/editeng/impedit2.cxx) where ubidi_getVisualIndex is an object-like + // macro, or + // + // #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + // + // (in hwpfilter/source/lexer.cxx): + if (!fourth.isMacroID()) { + while (compiler.getSourceManager().isMacroBodyExpansion(third) + && compiler.getSourceManager().isAtStartOfImmediateMacroExpansion(third, &third)) + {} + } else if (compiler.getSourceManager().isMacroBodyExpansion(fourth)) { + while (compiler.getSourceManager().isMacroArgExpansion(third) + && compiler.getSourceManager().isAtStartOfImmediateMacroExpansion(third, &third)) {} + } + if (!third.isMacroID()) { + while (compiler.getSourceManager().isMacroBodyExpansion(fourth) + && isLastTokenOfImmediateMacroBodyExpansion(fourth, &fourth)) + {} + } else if (compiler.getSourceManager().isMacroBodyExpansion(third)) { + while (compiler.getSourceManager().isMacroArgExpansion(fourth, &fourth)) {} + } + if (compiler.getSourceManager().isMacroBodyExpansion(third) + && compiler.getSourceManager().isMacroBodyExpansion(fourth) + && (compiler.getSourceManager().getImmediateMacroCallerLoc(third) + == compiler.getSourceManager().getImmediateMacroCallerLoc(fourth))) + { + third = compiler.getSourceManager().getSpellingLoc(third); + fourth = compiler.getSourceManager().getSpellingLoc(fourth); + } + assert(third.isValid()); + } + if (firstBegin.isMacroID() || secondBegin.isMacroID() || (third.isValid() && third.isMacroID()) + || (fourth.isValid() && fourth.isMacroID())) + { + if (isDebugMode()) { + report( + DiagnosticsEngine::Fatal, + "TODO: cannot rewrite C-style cast in macro, needs investigation", + expr->getExprLoc()) + << expr->getSourceRange(); + } + return false; + } + unsigned firstLen = Lexer::MeasureTokenLength( + firstBegin, compiler.getSourceManager(), compiler.getLangOpts()); + for (auto l = firstBegin.getLocWithOffset(std::max(firstLen, 1));; + l = l.getLocWithOffset(1)) + { + unsigned n = Lexer::MeasureTokenLength( + l, compiler.getSourceManager(), compiler.getLangOpts()); + if (n != 0) { + break; + } + ++firstLen; + } + unsigned secondLen = Lexer::MeasureTokenLength( + secondBegin, compiler.getSourceManager(), compiler.getLangOpts()); + for (auto l = secondBegin.getLocWithOffset(std::max(secondLen, 1));; + l = l.getLocWithOffset(1)) + { + unsigned n = Lexer::MeasureTokenLength( + l, compiler.getSourceManager(), compiler.getLangOpts()); + if (n != 0) { + break; + } + ++secondLen; + } + for (;;) { + auto l = secondBegin.getLocWithOffset(-1); + auto const c = compiler.getSourceManager().getCharacterData(l)[0]; + if (c == '\n') { + if (compiler.getSourceManager().getCharacterData(l.getLocWithOffset(-1))[0] == '\\') { + break; + } + } else if (!(c == ' ' || c == '\t' || c == '\v' || c == '\f')) { + break; + } + secondBegin = l; + ++secondLen; + } + if (rewritten_.insert(firstBegin).second) { + if (!replaceText(firstBegin, firstLen, functional ? "" : "static_cast<")) { + if (isDebugMode()) { + report( + DiagnosticsEngine::Fatal, "TODO: cannot rewrite #1, needs investigation", + firstBegin); + report( + DiagnosticsEngine::Note, "when rewriting this C-style cast", expr->getExprLoc()) + << expr->getSourceRange(); + } + return false; + } + if (!replaceText(secondBegin, secondLen, functional ? "" : ">")) { + //TODO: roll back + if (isDebugMode()) { + report( + DiagnosticsEngine::Fatal, "TODO: cannot rewrite #2, needs investigation", + secondBegin); + report( + DiagnosticsEngine::Note, "when rewriting this C-style cast", expr->getExprLoc()) + << expr->getSourceRange(); + } + return false; + } + } + if (third.isValid()) { + if (rewritten_.insert(third).second) { + if (!insertTextBefore(third, "(")) { + //TODO: roll back + if (isDebugMode()) { + report( + DiagnosticsEngine::Fatal, "TODO: cannot rewrite #3, needs investigation", + third); + report( + DiagnosticsEngine::Note, "when rewriting this C-style cast", + expr->getExprLoc()) + << expr->getSourceRange(); + } + return false; + } + if (!insertTextAfterToken(fourth, ")")) { + //TODO: roll back + if (isDebugMode()) { + report( + DiagnosticsEngine::Fatal, "TODO: cannot rewrite #4, needs investigation", + third); + report( + DiagnosticsEngine::Note, "when rewriting this C-style cast", + expr->getExprLoc()) + << expr->getSourceRange(); + } + return false; + } + } + } + return true; +} + +void CStyleCast::reportCast(ExplicitCastExpr const * expr, char const * performsHint) { + std::string incompFrom; + std::string incompTo; + if( expr->getCastKind() == CK_BitCast ) { + if (resolvePointers(expr->getSubExprAsWritten()->getType()) + ->isIncompleteType()) + { + incompFrom = "incomplete "; + } + if (resolvePointers(expr->getType())->isIncompleteType()) { + incompTo = "incomplete "; + } + } + if (performsHint == nullptr) { + performsHint = recommendedFix(expr->getCastKind()); + } + std::string performs; + if (performsHint != nullptr) { + performs = std::string(" (performs: ") + performsHint + ")"; + } + report( + DiagnosticsEngine::Warning, "%select{C|Function}0-style cast from %1%2 to %3%4%5 (%6)", + expr->getSourceRange().getBegin()) + << isa(expr) + << incompFrom << expr->getSubExprAsWritten()->getType() + << incompTo << expr->getTypeAsWritten() << performs + << expr->getCastKindName() + << expr->getSourceRange(); +} + +loplugin::Plugin::Registration< CStyleCast > X("cstylecast", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/data.cxx b/compilerplugins/clang/data.cxx new file mode 100644 index 000000000..9cff5426f --- /dev/null +++ b/compilerplugins/clang/data.cxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" + +// For std::array or std::vector x, replace &x[0] with x.data(). + +namespace +{ +class Data final : public loplugin::FilteringPlugin +{ +public: + explicit Data(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool VisitUnaryOperator(UnaryOperator const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + if (expr->getOpcode() != UO_AddrOf) + { + return true; + } + auto const e1 = dyn_cast(expr->getSubExpr()->IgnoreParenImpCasts()); + if (e1 == nullptr) + { + return true; + } + if (e1->getOperator() != OO_Subscript) + { + return true; + } + auto const t = e1->getArg(0)->getType(); + auto const chk = loplugin::TypeCheck(t); + if (!(chk.Class("array").StdNamespace() || chk.Class("vector").StdNamespace())) + { + return true; + } + auto const e2 = e1->getArg(1); + if (e2->isValueDependent()) + { + return true; + } + APSInt v; + if (!compat::EvaluateAsInt(e2, v, compiler.getASTContext())) + { + return true; + } + if (v != 0) + { + return true; + } + report(DiagnosticsEngine::Warning, + "use 'data' member function to access first element of %0", expr->getExprLoc()) + << t << expr->getSourceRange(); + return true; + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } +}; + +static loplugin::Plugin::Registration data("data"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/datamembershadow.cxx b/compilerplugins/clang/datamembershadow.cxx new file mode 100644 index 000000000..93f65de66 --- /dev/null +++ b/compilerplugins/clang/datamembershadow.cxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include + +#include "plugin.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" + +/** + * Check for data member being shadowed. + * + * @TODO check for any members in superclass hierarchy with duplicate names, + * regardless of their visibility, + * more specific names will make the code easier to read + */ +namespace +{ + +class DataMemberShadow: + public loplugin::FilteringPlugin +{ +public: + explicit DataMemberShadow(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitFieldDecl(FieldDecl const *); +}; + +bool DataMemberShadow::VisitFieldDecl(FieldDecl const * fieldDecl) +{ + if (ignoreLocation(fieldDecl)) { + return true; + } + StringRef aFileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(fieldDecl->getBeginLoc())); + + // FIXME complex stuff to fix later + + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/chart2/source/")) + return true; + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/sfx2/recentdocsview.hxx")) + return true; + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/sfx2/templatelocalview.hxx")) + return true; + if (loplugin::isSamePathname(aFileName, SRCDIR "/store/source/stortree.hxx") + || loplugin::isSamePathname(aFileName, SRCDIR "/store/source/stordata.hxx")) + return true; + if (loplugin::isSamePathname(aFileName, SRCDIR "/sw/source/uibase/inc/dbtree.hxx")) + return true; + + const CXXRecordDecl* parentCXXRecordDecl = dyn_cast(fieldDecl->getDeclContext()); + if (!parentCXXRecordDecl) { + return true; + } + + fieldDecl = fieldDecl->getCanonicalDecl(); + + auto BaseMatchesCallback = [&](const CXXBaseSpecifier *cxxBaseSpecifier, CXXBasePath& Paths) + { + if (!cxxBaseSpecifier->getType().getTypePtr()) + return false; + const CXXRecordDecl* baseCXXRecordDecl = cxxBaseSpecifier->getType()->getAsCXXRecordDecl(); + if (!baseCXXRecordDecl) + return false; + if (baseCXXRecordDecl->isInvalidDecl()) + return false; + for (const FieldDecl* baseFieldDecl : baseCXXRecordDecl->fields()) + { + // TODO look for overlaps even with private fields + + if (baseFieldDecl->getAccess() == AS_private + || !baseFieldDecl->getDeclName().isIdentifier() + || fieldDecl->getName() != baseFieldDecl->getName()) { + continue; + } + std::string sPath; + for (CXXBasePathElement const & pathElement : Paths) { + if (!sPath.empty()) { + sPath += "->"; + } + sPath += pathElement.Class->getNameAsString(); + } + sPath += "->"; + sPath += baseCXXRecordDecl->getNameAsString(); + report(DiagnosticsEngine::Warning, + "data member %0 is shadowing member in superclass, through inheritance path %1", + fieldDecl->getBeginLoc()) + << fieldDecl->getName() + << sPath + << fieldDecl->getSourceRange(); + report(DiagnosticsEngine::Note, + "superclass member here", + baseFieldDecl->getBeginLoc()) + << baseFieldDecl->getSourceRange(); + } + return false; + }; + + CXXBasePaths aPaths; + parentCXXRecordDecl->lookupInBases(BaseMatchesCallback, aPaths); + return true; +} + +loplugin::Plugin::Registration< DataMemberShadow > datamembershadow("datamembershadow", true); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/dbgunhandledexception.cxx b/compilerplugins/clang/dbgunhandledexception.cxx new file mode 100644 index 000000000..e6c1f157c --- /dev/null +++ b/compilerplugins/clang/dbgunhandledexception.cxx @@ -0,0 +1,128 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "plugin.hxx" +#include +#include +#include + +namespace loplugin +{ +/* +This is a compile check. + +Check that DBG_UNHANDLED_EXCEPTION is always the first statement in a catch block, otherwise +it does not work properly. +*/ + +class DbgUnhandledException : public loplugin::FilteringPlugin +{ +public: + explicit DbgUnhandledException(InstantiationData const& data); + virtual void run() override; + bool VisitCallExpr(CallExpr const* call); + bool TraverseCXXCatchStmt(CXXCatchStmt*); + bool PreTraverseCXXCatchStmt(CXXCatchStmt*); + bool PostTraverseCXXCatchStmt(CXXCatchStmt*, bool traverseOk); + +private: + std::stack currCatchStmt; +}; + +DbgUnhandledException::DbgUnhandledException(const InstantiationData& data) + : FilteringPlugin(data) +{ +} + +void DbgUnhandledException::run() +{ + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); +} + +bool DbgUnhandledException::PreTraverseCXXCatchStmt(CXXCatchStmt* catchStmt) +{ + currCatchStmt.push(catchStmt); + return true; +} + +bool DbgUnhandledException::PostTraverseCXXCatchStmt(CXXCatchStmt* catchStmt, bool) +{ + assert(currCatchStmt.top() == catchStmt); + (void)catchStmt; + currCatchStmt.pop(); + return true; +} + +bool DbgUnhandledException::TraverseCXXCatchStmt(CXXCatchStmt* catchStmt) +{ + if (!PreTraverseCXXCatchStmt(catchStmt)) + return false; + bool ret = RecursiveASTVisitor::TraverseCXXCatchStmt(catchStmt); + if (!PostTraverseCXXCatchStmt(catchStmt, ret)) + return false; + return ret; +} + +bool DbgUnhandledException::VisitCallExpr(const CallExpr* call) +{ + if (ignoreLocation(call)) + return true; + const FunctionDecl* func = call->getDirectCallee(); + if (!func) + return true; + + if (!func->getIdentifier() || func->getName() != "DbgUnhandledException") + return true; + + if (currCatchStmt.empty()) + { + report(DiagnosticsEngine::Warning, "DBG_UNHANDLED_EXCEPTION outside catch block", + call->getBeginLoc()); + return true; + } + auto catchBlock = dyn_cast(currCatchStmt.top()->getHandlerBlock()); + if (!catchBlock) + { + report(DiagnosticsEngine::Warning, + "something wrong with DBG_UNHANDLED_EXCEPTION, no CompoundStmt?", + call->getBeginLoc()); + return true; + } + if (catchBlock->size() < 1) + { + report(DiagnosticsEngine::Warning, + "something wrong with DBG_UNHANDLED_EXCEPTION, CompoundStmt size == 0?", + call->getBeginLoc()); + return true; + } + + Stmt const* firstStmt = *catchBlock->body_begin(); + if (auto exprWithCleanups = dyn_cast(firstStmt)) + firstStmt = exprWithCleanups->getSubExpr(); + if (firstStmt != call) + { + report(DiagnosticsEngine::Warning, + "DBG_UNHANDLED_EXCEPTION must be first statement in catch block", + call->getBeginLoc()); + } + return true; +} + +static Plugin::Registration dbgunhandledexception("dbgunhandledexception"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/derefnullptr.cxx b/compilerplugins/clang/derefnullptr.cxx new file mode 100644 index 000000000..35c4c7adc --- /dev/null +++ b/compilerplugins/clang/derefnullptr.cxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" + +namespace { + +class DerefNullPtr: + public loplugin::FilteringPlugin +{ +public: + explicit DerefNullPtr(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitUnaryOperator(UnaryOperator const * op); +}; + +bool DerefNullPtr::VisitUnaryOperator(UnaryOperator const * op) { + if (op->getOpcode() != UO_Deref) { + return true; + } + if (!ignoreLocation(op) + && (op->getSubExpr()->IgnoreParenCasts()->isNullPointerConstant( + compiler.getASTContext(), Expr::NPC_ValueDependentIsNotNull/*TODO*/) + != Expr::NPCK_NotNull)) + { + report( + DiagnosticsEngine::Warning, "null pointer dereference", + op->getBeginLoc()) + << op->getSourceRange(); + } + return true; +} + +loplugin::Plugin::Registration derefnullptr("derefnullptr"); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/dllprivate.cxx b/compilerplugins/clang/dllprivate.cxx new file mode 100644 index 000000000..5fbace101 --- /dev/null +++ b/compilerplugins/clang/dllprivate.cxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" + +namespace { + +class DllPrivate final: + public loplugin::FilteringPlugin +{ +public: + explicit DllPrivate(loplugin::InstantiationData const & data): FilteringPlugin(data) + {} + + bool VisitNamedDecl(NamedDecl const * decl) { + if (!decl->getLocation().isInvalid()&&ignoreLocation(decl)) { + return true; + } + auto a = decl->getAttr(); + if (a == nullptr || a->getVisibility() != VisibilityAttr::Hidden) { + return true; + } + if (compiler.getSourceManager().isMacroBodyExpansion( + decl->getLocation()) + && (Lexer::getImmediateMacroName( + decl->getLocation(), compiler.getSourceManager(), + compiler.getLangOpts()) + == "Q_OBJECT")) // from /usr/include/QtCore/qobjectdefs.h + { + return true; + } + auto p = dyn_cast(decl->getDeclContext()); + if (p == nullptr) { + report( + DiagnosticsEngine::Warning, + "top-level declaration redundantly marked as DLLPRIVATE", + a->getLocation()) + << decl->getSourceRange(); + } else if (p->getVisibility() == HiddenVisibility) { + report( + DiagnosticsEngine::Warning, + ("declaration nested in DLLPRIVATE declaration redundantly" + " marked as DLLPRIVATE"), + a->getLocation()) + << decl->getSourceRange(); + report( + DiagnosticsEngine::Note, "parent declaration is here", + p->getLocation()) + << p->getSourceRange(); + } + return true; + } + + bool preRun() override { + // DISABLE_DYNLOADING makes SAL_DLLPUBLIC_{EXPORT,IMPORT,TEMPLATE} expand + // to visibility("hidden") attributes, which would cause bogus warnings + // here (e.g., in UBSan builds that explicitly define DISABLE_DYNLOADING + // in jurt/source/pipe/staticsalhack.cxx); alternatively, change + // include/sal/types.h to make those SAL_DLLPUBLIC_* expand to nothing + // for DISABLE_DYNLOADING: + return !compiler.getPreprocessor().getIdentifierInfo("DISABLE_DYNLOADING") + ->hasMacroDefinition(); + } + + void run() override { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } +}; + +static loplugin::Plugin::Registration dllprivate("dllprivate"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/dodgyswitch.cxx b/compilerplugins/clang/dodgyswitch.cxx new file mode 100644 index 000000000..43958f136 --- /dev/null +++ b/compilerplugins/clang/dodgyswitch.cxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include "plugin.hxx" + +namespace { + +class DodgySwitch: + public loplugin::FilteringPlugin +{ +public: + explicit DodgySwitch(loplugin::InstantiationData const & data): FilteringPlugin(data) + {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitDefaultStmt(DefaultStmt const * ); + bool VisitCaseStmt(CaseStmt const * ); +private: + bool IsParentSwitch(Stmt const * ); +}; + +bool DodgySwitch::VisitDefaultStmt(DefaultStmt const * defaultStmt) +{ + if (ignoreLocation(defaultStmt)) + return true; + if (!IsParentSwitch(defaultStmt)) + report( + DiagnosticsEngine::Warning, "default statement not directly under switch", + defaultStmt->getBeginLoc()) + << defaultStmt->getSourceRange(); + return true; +} + +bool DodgySwitch::VisitCaseStmt(CaseStmt const * caseStmt) +{ + if (ignoreLocation(caseStmt)) + return true; + if (!IsParentSwitch(caseStmt)) + { + //parentStmt(parentStmt(caseStmt))->dump(); + report( + DiagnosticsEngine::Warning, "case statement not directly under switch", + caseStmt->getBeginLoc()) + << caseStmt->getSourceRange(); + } + return true; +} + +bool DodgySwitch::IsParentSwitch(Stmt const * stmt) +{ + auto parent = getParentStmt(stmt); + if (isa(parent) || isa(parent)) // daisy chain + return true; + auto compoundStmt = dyn_cast(parent); + if (!compoundStmt) + return false; + return isa(getParentStmt(compoundStmt)); +} + +loplugin::Plugin::Registration< DodgySwitch > X("dodgyswitch", false); + +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/doubleconvert.cxx b/compilerplugins/clang/doubleconvert.cxx new file mode 100644 index 000000000..6f9cc88df --- /dev/null +++ b/compilerplugins/clang/doubleconvert.cxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "plugin.hxx" + +/** + * Look for places where we are converting from type A through a conversion operator and back to type A, + * which is redundant. At the moment only look for Color, to aid my ColorData->Color conversion + */ +namespace +{ +class DoubleConvert final : public loplugin::FilteringPlugin +{ +public: + explicit DoubleConvert(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXConstructExpr(CXXConstructExpr const*); +}; + +/** + The AST looks like: + + CXXOperatorCallExpr 0x8e5b840 'class Color' lvalue +|-ImplicitCastExpr 0x8e5b828 'class Color &(*)(class Color &&) noexcept' +| `-DeclRefExpr 0x8e5b800 'class Color &(class Color &&) noexcept' lvalue CXXMethod 0x8e59a08 'operator=' 'class Color &(class Color &&) noexcept' +|-DeclRefExpr 0x8e5b678 'class Color' lvalue Var 0x8e5b5d0 'col2' 'class Color' +`-MaterializeTemporaryExpr 0x8e5b7e8 'class Color' xvalue + `-CXXConstructExpr 0x8e5b7b0 'class Color' 'void (ColorData)' + `-ImplicitCastExpr 0x8e5b798 'ColorData':'unsigned int' + `-CXXFunctionalCastExpr 0x8e5b770 'sal_Int32':'int' functional cast to sal_Int32 + `-ImplicitCastExpr 0x8e5b758 'sal_Int32':'int' + `-CXXMemberCallExpr 0x8e5b730 'sal_Int32':'int' + `-MemberExpr 0x8e5b6f8 '' .operator int 0x8e51048 + `-ImplicitCastExpr 0x8e5b6e0 'const class Color' lvalue + `-DeclRefExpr 0x8e5b6b0 'class Color' lvalue Var 0x8e5b518 'col1' 'class Color' +*/ +bool DoubleConvert::VisitCXXConstructExpr(CXXConstructExpr const* cxxConstruct) +{ + if (ignoreLocation(cxxConstruct)) + return true; + if (cxxConstruct->getNumArgs() == 0) + return true; + auto cxxMemberCallExpr + = dyn_cast(cxxConstruct->getArg(0)->IgnoreParenCasts()); + if (!cxxMemberCallExpr) + return true; + if (!isa_and_nonnull(cxxMemberCallExpr->getMethodDecl())) + return true; + if (cxxConstruct->getType().getCanonicalType().getTypePtr() + != cxxMemberCallExpr->getImplicitObjectArgument() + ->getType() + .getCanonicalType() + .getTypePtr()) + return true; + if (!loplugin::TypeCheck(cxxConstruct->getType().getCanonicalType()) + .Class("Color") + .GlobalNamespace()) + return true; + + report(DiagnosticsEngine::Warning, "redundant double conversion", cxxConstruct->getExprLoc()) + << cxxConstruct->getSourceRange(); + return true; +} + +static loplugin::Plugin::Registration doubleconvert("doubleconvert"); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/duplicate-defines.cxx b/compilerplugins/clang/duplicate-defines.cxx new file mode 100644 index 000000000..74a95f2cc --- /dev/null +++ b/compilerplugins/clang/duplicate-defines.cxx @@ -0,0 +1,136 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include +#include +#include + +#include "plugin.hxx" + +#include +#include +#include +#include +#include + +/// Finds duplicated preprocessor defines, which generally indicate that some definition +/// needs to be centralised somewhere. + +namespace +{ +struct Entry +{ + clang::SourceLocation m_aLoc; +}; + +class DuplicateDefines : public clang::PPCallbacks, public loplugin::Plugin +{ +public: + explicit DuplicateDefines(const loplugin::InstantiationData& data); + virtual void run() override; + void MacroDefined(const Token& MacroNameTok, const MacroDirective* MD) override; + void MacroUndefined(const Token& MacroNameTok, const MacroDefinition& MD, + const MacroDirective* Undef) override; + enum + { + isPPCallback = true + }; + +private: + clang::Preprocessor& m_rPP; + std::unordered_map m_aDefMap; +}; + +DuplicateDefines::DuplicateDefines(const loplugin::InstantiationData& data) + : Plugin(data) + , m_rPP(compiler.getPreprocessor()) +{ + compiler.getPreprocessor().addPPCallbacks(std::unique_ptr(this)); +} + +void DuplicateDefines::run() +{ + // nothing, only check preprocessor usage +} + +void DuplicateDefines::MacroDefined(const Token& rMacroNameTok, const MacroDirective*) +{ + auto aLoc = rMacroNameTok.getLocation(); + if (ignoreLocation(aLoc)) + return; + + std::string aMacroName = m_rPP.getSpelling(rMacroNameTok); + + // some testing macro + if (aMacroName == "RTL_STRING_CONST_FUNCTION") + return; + if (aMacroName == "rtl") + return; + // we replicate these macros in all the .hrc files + if (aMacroName == "NC_" || aMacroName == "NNC_") + return; + // We define this prior to including : + if (aMacroName == "WIN32_LEAN_AND_MEAN") + { + return; + } + // TODO no obvious fix for these + if (aMacroName == "FID_SEARCH_NOW" || aMacroName == "FID_SVX_START" || aMacroName == "FN_PARAM") + return; + // ignore for now, requires adding too many includes to sw/ + if (aMacroName == "MM50") + return; + + // ignore for now, we have the same define in svx and sw, but I can't remove one of them because + // they reference strings in different resource bundles + if (aMacroName == "STR_UNDO_COL_DELETE" || aMacroName == "STR_UNDO_ROW_DELETE" + || aMacroName == "STR_TABLE_NUMFORMAT" || aMacroName == "STR_DELETE") + return; + + if (m_aDefMap.emplace(aMacroName, Entry{ aLoc }).second) + { + return; + } + + // Happens e.g. with macros defined in include/premac.h, which is intended to be included + // (without include guards) multiple times: + auto const other = m_aDefMap[aMacroName].m_aLoc; + assert(aLoc == compiler.getSourceManager().getSpellingLoc(aLoc)); + assert(other == compiler.getSourceManager().getSpellingLoc(other)); + if ((compiler.getSourceManager().getFilename(aLoc) + == compiler.getSourceManager().getFilename(other)) + && (compiler.getSourceManager().getSpellingLineNumber(aLoc) + == compiler.getSourceManager().getSpellingLineNumber(other)) + && (compiler.getSourceManager().getSpellingColumnNumber(aLoc) + == compiler.getSourceManager().getSpellingColumnNumber(other))) + { + return; + } + + report(DiagnosticsEngine::Warning, "duplicate defines", aLoc); + report(DiagnosticsEngine::Note, "previous define", other); +} + +void DuplicateDefines::MacroUndefined(const Token& rMacroNameTok, const MacroDefinition& /*MD*/, + const MacroDirective* /*Undef*/) +{ + auto aLoc = rMacroNameTok.getLocation(); + if (ignoreLocation(aLoc)) + return; + + std::string aMacroName = m_rPP.getSpelling(rMacroNameTok); + m_aDefMap.erase(aMacroName); +} + +loplugin::Plugin::Registration X("duplicatedefines", true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/dyncastvisibility.cxx b/compilerplugins/clang/dyncastvisibility.cxx new file mode 100644 index 000000000..7259374c9 --- /dev/null +++ b/compilerplugins/clang/dyncastvisibility.cxx @@ -0,0 +1,209 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include "config_clang.h" + +#include "plugin.hxx" + +namespace { + +using Bases = std::set; + +Visibility getTypeVisibility(CXXRecordDecl const * decl) { + assert(decl->isThisDeclarationADefinition()); + if (auto const opt = decl->getExplicitVisibility( + NamedDecl::VisibilityForType)) + { + return *opt; + } + if (auto const opt = decl->getExplicitVisibility( + NamedDecl::VisibilityForValue)) + { + return *opt; + } + auto const visi = decl->getVisibility(); + return visi == DefaultVisibility && decl->isInAnonymousNamespace() + ? HiddenVisibility : visi; +} + +// Check whether 'decl' is derived from 'base', gathering any 'bases' between +// 'decl' and 'base', and whether any of those 'bases' or 'base' are 'hidden' +// (i.e., have non-default visibility): +bool isDerivedFrom( + CXXRecordDecl const * decl, CXXRecordDecl const * base, Bases * bases, + bool * hidden) +{ + bool derived = false; + for (auto const & i: decl->bases()) { + auto const bd + = (cast(i.getType()->getAs()->getDecl()) + ->getDefinition()); + assert(bd != nullptr); + if (bd == base) { + *hidden |= getTypeVisibility(base) != DefaultVisibility; + derived = true; + } + else if (bd->isDerivedFrom(base)) { + if (bases->insert(bd).second) { + auto const d = isDerivedFrom(bd, base, bases, hidden); + assert(d); + (void)d; + *hidden |= getTypeVisibility(bd) != DefaultVisibility; + } + derived = true; + } + } + return derived; +} + +StringRef vis(Visibility v) { + switch (v) { + case HiddenVisibility: + return "hidden"; + case ProtectedVisibility: + return "protected"; + case DefaultVisibility: + return "default"; + } + llvm_unreachable("unknown visibility"); +} + +class DynCastVisibility final: + public loplugin::FilteringPlugin +{ +public: + explicit DynCastVisibility(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + bool shouldVisitTemplateInstantiations() const { return true; } + + bool VisitCXXDynamicCastExpr(CXXDynamicCastExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto td = expr->getTypeAsWritten(); + if (auto const t = td->getAs()) { + td = t->getPointeeType(); + } + while (auto const t = td->getAs()) { + td = t->getPointeeType(); + } + auto const rtd = td->getAs(); + if (rtd == nullptr) { + return true; + } + auto const rdd = cast(rtd->getDecl())->getDefinition(); + assert(rdd != nullptr); + if (getTypeVisibility(rdd) != DefaultVisibility) { + // Heuristic to find problematic dynamic_cast with hidden type T is: T is defined in + // include/M1/ while the compilation unit is in module M2/ with M1 != M2. There are + // legitimate cases where T is a hidden type in dynamic_cast, e.g., when both the + // type and the cast are in the same library. This heuristic appears to be conservative + // enough to produce only a few false positives (which have been addressed with + // preceding commits, marking the relevant types in global include files as + // SAL_DLLPUBLIC_RTTI after all, to be on the safe side) and aggressive enough to find + // at least some interesting cases (though it would still not be aggressive enough to + // have found ff570b4b58dbf274d3094d21d974f18b613e9b4b "DocumentSettingsSerializer must + // be SAL_DLLPUBLIC_RTTI for dynamic_cast"): + auto const file = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(rdd->getLocation())); + if (loplugin::hasPathnamePrefix(file, SRCDIR "/include/")) { + std::size_t const n1 = std::strlen(SRCDIR "/include/"); + std::size_t n2 = file.find('/', n1); +#if defined _WIN32 + n2 = std::min(n2, file.find('\\', n1)); +#endif + auto const seg = n2 >= file.size() ? file.substr(n1) : file.substr(n1, n2 - n1); + auto prefix = std::string(SRCDIR "/"); + prefix += seg; + if (!loplugin::hasPathnamePrefix( + handler.getMainFileName(), prefix)) + { + report( + DiagnosticsEngine::Warning, + "Suspicious dynamic_cast to %0 with %1 type visibility", expr->getExprLoc()) + << td << vis(getTypeVisibility(rdd)) << expr->getSourceRange(); + report(DiagnosticsEngine::Note, "class %0 defined here", rdd->getLocation()) + << td << rdd->getSourceRange(); + } + } + return true; + } + auto ts = expr->getSubExpr()->getType(); + while (auto const t = ts->getAs()) { + ts = t->getPointeeType(); + } + auto const rts = ts->getAs(); + if (rts == nullptr) { // in case it's a dependent type + return true; + } + auto const rds = cast(rts->getDecl())->getDefinition(); + assert(rds != nullptr); + Bases bs; + bool hidden = false; + if (!(isDerivedFrom(rdd, rds, &bs, &hidden) && hidden)) { + return true; + } + report( + DiagnosticsEngine::Warning, + ("dynamic_cast from %0 with %1 type visibility to %2 with %3 type" + " visibility"), + expr->getExprLoc()) + << ts << vis(getTypeVisibility(rds)) << td + << vis(getTypeVisibility(rdd)) << expr->getSourceRange(); + report( + DiagnosticsEngine::Note, + "base class %0 with %1 type visibility defined here", + rds->getLocation()) + << ts << vis(getTypeVisibility(rds)) << rds->getSourceRange(); + for (auto const i: bs) { + if (getTypeVisibility(i) != DefaultVisibility) { + report( + DiagnosticsEngine::Note, + ("intermediary class %0 with %1 type visibility defined" + " here"), + i->getLocation()) + << i << vis(getTypeVisibility(i)) << i->getSourceRange(); + } + } + report( + DiagnosticsEngine::Note, + "derived class %0 with %1 type visibility defined here", + rdd->getLocation()) + << td << vis(getTypeVisibility(rdd)) << rdd->getSourceRange(); + return true; + } + + virtual bool preRun() override { + return compiler.getLangOpts().CPlusPlus; + } +private: + void run() override { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } +}; + +static loplugin::Plugin::Registration dyncastvisibility( + "dyncastvisibility"); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/dynexcspec.cxx b/compilerplugins/clang/dynexcspec.cxx new file mode 100644 index 000000000..af733ec4f --- /dev/null +++ b/compilerplugins/clang/dynexcspec.cxx @@ -0,0 +1,186 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include + +#include "clang/AST/Comment.h" + +#include "plugin.hxx" + +// Remove dynamic exception specifications. See the mail thread starting at +// +// "Dynamic Exception Specifications" for details. + +namespace { + +bool isOverriding(FunctionDecl const * decl) { + if (decl->hasAttr()) { + return true; + } + auto m = dyn_cast(decl); + return m != nullptr + && m->begin_overridden_methods() != m->end_overridden_methods(); +} + +bool isDtorOrDealloc(FunctionDecl const * decl) { + if (isa(decl)) { + return true; + } + switch (decl->getOverloadedOperator()) { + case OO_Delete: + case OO_Array_Delete: + return true; + default: + return false; + } +} + +class DynExcSpec: + public loplugin::FilteringRewritePlugin +{ +public: + explicit DynExcSpec(loplugin::InstantiationData const & data): + FilteringRewritePlugin(data) {} + + bool preRun() override { + return compiler.getLangOpts().CPlusPlus; + } + + void run() override { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitFunctionDecl(FunctionDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + auto proto = decl->getType()->getAs(); + if (proto == nullptr || proto->getExceptionSpecType() != EST_Dynamic) { + return true; + } + if (decl->isCanonicalDecl() && !isOverriding(decl) + && !anyRedeclHasThrowsDocumentation(decl)) + { + report( + DiagnosticsEngine::Warning, + ("function declaration has dynamic exception specification but" + " no corresponding documentation comment"), + decl->getLocation()) + << decl->getSourceRange(); + } + if (rewriter != nullptr) { + if (!(decl->isDefined() || decl->isPure())) { + return true; + } + if (auto m = dyn_cast(decl)) { + for (auto i = m->begin_overridden_methods(); + i != m->end_overridden_methods(); ++i) + { + auto proto2 = (*i)->getType()->getAs(); + assert(proto2 != nullptr); + if (proto2->getExceptionSpecType() == EST_Dynamic) { + return true; + } + } + } + } + bool dtorOrDealloc = isDtorOrDealloc(decl); + auto const source = decl->getExceptionSpecSourceRange(); + if (rewriter != nullptr && source.isValid()) { + if (dtorOrDealloc) { + if (replaceText(source, "noexcept(false)")) { + return true; + } + } else { + auto beg = source.getBegin(); + if (beg.isFileID()) { + for (;;) { + auto prev = Lexer::GetBeginningOfToken( + beg.getLocWithOffset(-1), + compiler.getSourceManager(), + compiler.getLangOpts()); + auto n = Lexer::MeasureTokenLength( + prev, compiler.getSourceManager(), + compiler.getLangOpts()); + auto s = StringRef( + compiler.getSourceManager().getCharacterData(prev), + n); + while (s.startswith("\\\n")) { + s = s.drop_front(2); + while (!s.empty() + && (s.front() == ' ' || s.front() == '\t' + || s.front() == '\n' || s.front() == '\v' + || s.front() == '\f')) + { + s = s.drop_front(1); + } + } + if (!s.empty() && s != "\\") { + if (s.startswith("//")) { + beg = source.getBegin(); + } + break; + } + beg = prev; + } + } + if (removeText(SourceRange(beg, source.getEnd()))) { + return true; + } + } + } + report( + DiagnosticsEngine::Warning, + (dtorOrDealloc + ? "replace dynamic exception specification with 'noexcept(false)'" + : "remove dynamic exception specification"), + source.isValid() ? source.getBegin() : decl->getLocation()) + << (source.isValid() ? source : decl->getSourceRange()); + return true; + } + +private: + bool hasThrowsDocumentation(FunctionDecl const * decl) { + if (auto cmt = compiler.getASTContext().getCommentForDecl( + decl, &compiler.getPreprocessor())) + { + for (auto i = cmt->child_begin(); i != cmt->child_end(); ++i) { + if (auto bcc = dyn_cast(*i)) { + if (compiler.getASTContext().getCommentCommandTraits() + .getCommandInfo(bcc->getCommandID())->IsThrowsCommand) + { + return true; + } + } + } + } + return false; + } + + bool anyRedeclHasThrowsDocumentation(FunctionDecl const * decl) { + return std::any_of( + decl->redecls_begin(), decl->redecls_end(), + [this](FunctionDecl * d) { return hasThrowsDocumentation(d); }); + // std::bind( + // &DynExcSpec::hasThrowsDocumentation, this, + // std::placeholders::_1)); + } +}; + +loplugin::Plugin::Registration dynexcspec("dynexcspec"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/elidestringvar.cxx b/compilerplugins/clang/elidestringvar.cxx new file mode 100644 index 000000000..89e740d21 --- /dev/null +++ b/compilerplugins/clang/elidestringvar.cxx @@ -0,0 +1,460 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include + +#include "check.hxx" +#include "plugin.hxx" + +// Find cases where a variable of a OString/OUString type is initialized +// with a literal value (incl. as an empty string) and used only once. Conservatively this only +// covers local non-static variables that are not defined outside of the loop (if any) in which they +// are used, as other cases may deliberately use the variable for performance (or even correctness, +// if addresses are taken and compared) reasons. +// +// For one, the historically heavy syntax for such uses of string literals +// (RTL_CONSTASCII_USTRINGPARAM etc.) probably explains many of these redundant variables, which can +// now be considered cargo-cult baggage. For another, some of those variables are used as arguments +// to functions which also have more efficient overloads directly taking string literals. And for +// yet another, some cases with default-initialized variables turned out to be effectively unused +// code that could be removed completely (d073cca5f7c04de3e1bcedda334d864e98ac7835 "Clean up dead +// code", 91345e7dde6100496a7c9e815b72b2821ae82bc2 "Clean up dead code", +// 868b0763ac47f765cb48c277897274a595b831d0 "Upcoming loplugin:elidestringvar: dbaccess" in +// dbaccess/source/ui/app/AppController.cxx, bde0aac4ccf7b830b5ef21d5b9e75e62aee6aaf9 "Clean up dead +// code", 354aefec42de856b4ab6201ada54a3a3c630b4bd "Upcoming loplugin:elidestringvar: cui" in +// cui/source/dialogs/SpellDialog.cxx). + +namespace +{ +bool isStringType(QualType type) +{ + loplugin::TypeCheck const c(type); + return c.Class("OString").Namespace("rtl").GlobalNamespace() + || c.Class("OUString").Namespace("rtl").GlobalNamespace(); +} + +class ElideStringVar : public loplugin::FilteringPlugin +{ +public: + explicit ElideStringVar(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + + void postRun() override + { + for (auto const& var : vars_) + { + if (!var.second.singleUse || *var.second.singleUse == nullptr) + { + continue; + } + if (containsPreprocessingConditionalInclusion( + SourceRange(var.first->getBeginLoc(), (*var.second.singleUse)->getEndLoc()))) + { + // This is not perfect, as additional uses can be hidden in conditional blocks that + // only start after the (would-be) single use (as was the case in + // 3bc5057f9689e024957cfa898a221ee2c4c4afe7 "Upcoming loplugin:elidestringvar: + // testtools" when built with --enable-debug, but where also fixing the hidden + // additional use was trivial). If this ever becomes a real problem, we can extend + // the above check to cover more of the current function body's remainder. + continue; + } + report(DiagnosticsEngine::Warning, + "replace single use of literal %0 variable with a literal", + (*var.second.singleUse)->getExprLoc()) + << var.first->getType() << (*var.second.singleUse)->getSourceRange(); + report(DiagnosticsEngine::Note, "literal %0 variable defined here", + var.first->getLocation()) + << var.first->getType() << var.first->getSourceRange(); + } + } + + bool VisitVarDecl(VarDecl const* decl) + { + if (ignoreLocation(decl)) + { + return true; + } + if (!decl->isThisDeclarationADefinition()) + { + return true; + } + if (isa(decl)) + { + return true; + } + if (decl->getStorageDuration() != SD_Automatic) + { + return true; + } + if (!isStringType(decl->getType())) + { + return true; + } + if (!decl->hasInit()) + { + return true; + } + auto const e1 = dyn_cast(decl->getInit()->IgnoreParenImpCasts()); + if (e1 == nullptr) + { + return true; + } + if (!isStringType(e1->getType())) + { + return true; + } + switch (e1->getNumArgs()) + { + case 0: + break; + case 1: + { + auto const e2 = e1->getArg(0); + loplugin::TypeCheck const c(e2->getType()); + if (c.Class("OStringLiteral").Namespace("rtl").GlobalNamespace() + || c.Class("OUStringLiteral").Namespace("rtl").GlobalNamespace()) + { + break; + } + if (!e2->isValueDependent() && e2->isIntegerConstantExpr(compiler.getASTContext())) + { + break; + } + return true; + } + case 2: + { + auto const e2 = e1->getArg(0); + auto const t = e2->getType(); + if (!(t.isConstQualified() && t->isConstantArrayType())) + { + return true; + } + if (isa(e2->IgnoreParenImpCasts())) + { + return true; + } + auto const e3 = e1->getArg(1); + if (!(isa(e3) + && loplugin::TypeCheck(e3->getType()) + .Struct("Dummy") + .Namespace("libreoffice_internal") + .Namespace("rtl") + .GlobalNamespace())) + { + return true; + } + break; + } + default: + return true; + } + auto const ok = vars_.emplace(decl, Data(getInnermostLoop())); + assert(ok.second); + (void)ok; + return true; + } + + bool VisitDeclRefExpr(DeclRefExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const var = dyn_cast(expr->getDecl()); + if (var == nullptr) + { + return true; + } + auto const i = vars_.find(var); + if (i == vars_.end()) + { + return true; + } + i->second.singleUse + = i->second.singleUse || i->second.innermostLoop != getInnermostLoop() ? nullptr : expr; + return true; + } + + bool VisitMemberExpr(MemberExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const e = dyn_cast(expr->getBase()->IgnoreParenImpCasts()); + if (e == nullptr) + { + return true; + } + auto const var = dyn_cast(e->getDecl()); + if (var == nullptr) + { + return true; + } + auto const i = vars_.find(var); + if (i == vars_.end()) + { + return true; + } + i->second.singleUse = nullptr; + return true; + } + + bool VisitUnaryOperator(UnaryOperator const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + if (expr->getOpcode() != UO_AddrOf) + { + return true; + } + auto const e = dyn_cast(expr->getSubExpr()->IgnoreParenImpCasts()); + if (e == nullptr) + { + return true; + } + auto const var = dyn_cast(e->getDecl()); + if (var == nullptr) + { + return true; + } + auto const i = vars_.find(var); + if (i == vars_.end()) + { + return true; + } + i->second.singleUse = nullptr; + return true; + } + + bool VisitCallExpr(CallExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const fun = expr->getDirectCallee(); + if (fun == nullptr) + { + return true; + } + unsigned const n = std::min(fun->getNumParams(), expr->getNumArgs()); + for (unsigned i = 0; i != n; ++i) + { + if (!loplugin::TypeCheck(fun->getParamDecl(i)->getType()) + .LvalueReference() + .NonConstVolatile()) + { + continue; + } + auto const e = dyn_cast(expr->getArg(i)->IgnoreParenImpCasts()); + if (e == nullptr) + { + continue; + } + auto const var = dyn_cast(e->getDecl()); + if (var == nullptr) + { + continue; + } + auto const j = vars_.find(var); + if (j == vars_.end()) + { + continue; + } + j->second.singleUse = nullptr; + } + return true; + } + + bool VisitCXXConstructExpr(CXXConstructExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const ctor = expr->getConstructor(); + unsigned const n = std::min(ctor->getNumParams(), expr->getNumArgs()); + for (unsigned i = 0; i != n; ++i) + { + if (!loplugin::TypeCheck(ctor->getParamDecl(i)->getType()) + .LvalueReference() + .NonConstVolatile()) + { + continue; + } + auto const e = dyn_cast(expr->getArg(i)->IgnoreParenImpCasts()); + if (e == nullptr) + { + continue; + } + auto const var = dyn_cast(e->getDecl()); + if (var == nullptr) + { + continue; + } + auto const j = vars_.find(var); + if (j == vars_.end()) + { + continue; + } + j->second.singleUse = nullptr; + } + return true; + } + + bool TraverseWhileStmt(WhileStmt* stmt) + { + bool ret = true; + if (PreTraverseWhileStmt(stmt)) + { + ret = FilteringPlugin::TraverseWhileStmt(stmt); + PostTraverseWhileStmt(stmt, ret); + } + return ret; + } + + bool PreTraverseWhileStmt(WhileStmt* stmt) + { + innermostLoop_.push(stmt); + return true; + } + + bool PostTraverseWhileStmt(WhileStmt* stmt, bool) + { + assert(!innermostLoop_.empty()); + assert(innermostLoop_.top() == stmt); + (void)stmt; + innermostLoop_.pop(); + return true; + } + + bool TraverseDoStmt(DoStmt* stmt) + { + bool ret = true; + if (PreTraverseDoStmt(stmt)) + { + ret = FilteringPlugin::TraverseDoStmt(stmt); + PostTraverseDoStmt(stmt, ret); + } + return ret; + } + + bool PreTraverseDoStmt(DoStmt* stmt) + { + innermostLoop_.push(stmt); + return true; + } + + bool PostTraverseDoStmt(DoStmt* stmt, bool) + { + assert(!innermostLoop_.empty()); + assert(innermostLoop_.top() == stmt); + (void)stmt; + innermostLoop_.pop(); + return true; + } + + bool TraverseForStmt(ForStmt* stmt) + { + bool ret = true; + if (PreTraverseForStmt(stmt)) + { + ret = FilteringPlugin::TraverseForStmt(stmt); + PostTraverseForStmt(stmt, ret); + } + return ret; + } + + bool PreTraverseForStmt(ForStmt* stmt) + { + innermostLoop_.push(stmt); + return true; + } + + bool PostTraverseForStmt(ForStmt* stmt, bool) + { + assert(!innermostLoop_.empty()); + assert(innermostLoop_.top() == stmt); + (void)stmt; + innermostLoop_.pop(); + return true; + } + + bool TraverseCXXForRangeStmt(CXXForRangeStmt* stmt) + { + bool ret = true; + if (PreTraverseCXXForRangeStmt(stmt)) + { + ret = FilteringPlugin::TraverseCXXForRangeStmt(stmt); + PostTraverseCXXForRangeStmt(stmt, ret); + } + return ret; + } + + bool PreTraverseCXXForRangeStmt(CXXForRangeStmt* stmt) + { + innermostLoop_.push(stmt); + return true; + } + + bool PostTraverseCXXForRangeStmt(CXXForRangeStmt* stmt, bool) + { + assert(!innermostLoop_.empty()); + assert(innermostLoop_.top() == stmt); + (void)stmt; + innermostLoop_.pop(); + return true; + } + +private: + void run() override + { + if (preRun() && TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) + { + postRun(); + } + } + + Stmt const* getInnermostLoop() const + { + return innermostLoop_.empty() ? nullptr : innermostLoop_.top(); + } + + struct Data + { + Data(Stmt const* theInnermostLoop) + : innermostLoop(theInnermostLoop) + { + } + Stmt const* innermostLoop; + llvm::Optional singleUse; + }; + + std::stack innermostLoop_; + std::map vars_; +}; + +loplugin::Plugin::Registration elidestringvar("elidestringvar"); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/empty.cxx b/compilerplugins/clang/empty.cxx new file mode 100644 index 000000000..d5129d29d --- /dev/null +++ b/compilerplugins/clang/empty.cxx @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include + +#include "check.hxx" +#include "plugin.hxx" + +// Warn about checks whether a container is empty done via an (expensive) call to obtain the +// container's size. For now only handles cases involving strlen. + +namespace +{ +BinaryOperatorKind reverse(BinaryOperatorKind op) +{ + switch (op) + { + case BO_LT: + return BO_GE; + case BO_GT: + return BO_LE; + case BO_LE: + return BO_GT; + case BO_GE: + return BO_LT; + case BO_EQ: + case BO_NE: + return op; + default: + abort(); + } +} + +class Empty : public loplugin::FilteringPlugin +{ +public: + explicit Empty(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool VisitBinaryOperator(BinaryOperator const* expr) + { + if (expr->isRelationalOp() || expr->isEqualityOp()) + { + visitComparison(expr); + } + return true; + } + +private: + void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + void visitComparison(BinaryOperator const* expr, CallExpr const* lhs, Expr const* rhs, + BinaryOperatorKind op) + { + auto const fdecl = lhs->getDirectCallee(); + if (fdecl == nullptr) + { + return; + } + loplugin::DeclCheck dc(fdecl); + if (!(dc.Function("strlen").StdNamespace() || dc.Function("strlen").GlobalNamespace())) + { + return; + } + if (rhs->isValueDependent()) + { + return; + } + auto const val = rhs->getIntegerConstantExpr(compiler.getASTContext()); + if (!val) + { + return; + } + switch (op) + { + case BO_LT: + if (val->getExtValue() == 1) + { + report(DiagnosticsEngine::Warning, + "replace a comparison like 'strlen(e) < 1' with 'e[0] == '\\0''", + expr->getExprLoc()) + << expr->getSourceRange(); + } + break; + case BO_GT: + if (val->getExtValue() == 0) + { + report(DiagnosticsEngine::Warning, + "replace a comparison like 'strlen(e) > 0' with 'e[0] != '\\0''", + expr->getExprLoc()) + << expr->getSourceRange(); + } + break; + case BO_LE: + if (val->getExtValue() == 0) + { + report(DiagnosticsEngine::Warning, + "replace a comparison like 'strlen(e) <= 0' with 'e[0] == '\\0''", + expr->getExprLoc()) + << expr->getSourceRange(); + } + break; + case BO_GE: + if (val->getExtValue() == 1) + { + report(DiagnosticsEngine::Warning, + "replace a comparison like 'strlen(e) >= 1' with 'e[0] != '\\0''", + expr->getExprLoc()) + << expr->getSourceRange(); + } + break; + case BO_EQ: + if (val->getExtValue() == 0) + { + report(DiagnosticsEngine::Warning, + "replace a comparison like 'strlen(e) == 0' with 'e[0] == '\\0''", + expr->getExprLoc()) + << expr->getSourceRange(); + } + break; + case BO_NE: + if (val->getExtValue() == 0) + { + report(DiagnosticsEngine::Warning, + "replace a comparison like 'strlen(e) != 0' with 'e[0] != '\\0''", + expr->getExprLoc()) + << expr->getSourceRange(); + } + break; + default: + assert(false); + } + } + + void visitComparison(BinaryOperator const* expr) + { + if (ignoreLocation(expr)) + { + return; + } + if (auto const call = dyn_cast(expr->getLHS()->IgnoreParenImpCasts())) + { + visitComparison(expr, call, expr->getRHS(), expr->getOpcode()); + } + else if (auto const call = dyn_cast(expr->getRHS()->IgnoreParenImpCasts())) + { + visitComparison(expr, call, expr->getLHS(), reverse(expr->getOpcode())); + } + } +}; + +loplugin::Plugin::Registration emptyRegistration("empty"); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/emptyif.cxx b/compilerplugins/clang/emptyif.cxx new file mode 100644 index 000000000..5412188f8 --- /dev/null +++ b/compilerplugins/clang/emptyif.cxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include +#include "plugin.hxx" + +/** + Check for places where we do + if (xxx) ; + or + if (xxx) {} + */ +namespace +{ +class EmptyIf : public loplugin::FilteringRewritePlugin +{ +public: + explicit EmptyIf(loplugin::InstantiationData const& data) + : FilteringRewritePlugin(data) + { + } + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitIfStmt(IfStmt const*); + +private: + bool ContainsComment(Stmt const*); +}; + +static bool empty(Stmt const* stmt) +{ + if (isa(stmt)) + return true; + auto compoundStmt = dyn_cast(stmt); + if (!compoundStmt) + return false; + return compoundStmt->size() == 0; +} + +bool EmptyIf::ContainsComment(Stmt const* stmt) +{ + auto range = stmt->getSourceRange(); + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = range.getBegin(); + SourceLocation endLoc = range.getEnd(); + char const* p1 = SM.getCharacterData(startLoc); + char const* p2 = SM.getCharacterData(endLoc); + p2 += Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts()); + auto s = llvm::StringRef(p1, p2 - p1); + return s.find("//") != llvm::StringRef::npos || s.find("/*") != llvm::StringRef::npos + || s.find("#if") != llvm::StringRef::npos; +} + +bool EmptyIf::VisitIfStmt(IfStmt const* ifStmt) +{ + if (ignoreLocation(ifStmt)) + return true; + + if (ifStmt->getElse() && empty(ifStmt->getElse()) && !ContainsComment(ifStmt->getElse())) + { + report(DiagnosticsEngine::Warning, "empty else body", ifStmt->getElse()->getBeginLoc()) + << ifStmt->getElse()->getSourceRange(); + return true; + } + + if (!ifStmt->getElse() && empty(ifStmt->getThen()) && !ContainsComment(ifStmt->getThen())) + { + report(DiagnosticsEngine::Warning, "empty if body", ifStmt->getBeginLoc()) + << ifStmt->getSourceRange(); + } + + return true; +} + +loplugin::Plugin::Registration emptyif("emptyif", true); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/expandablemethods.cxx b/compilerplugins/clang/expandablemethods.cxx new file mode 100644 index 000000000..5b09345d4 --- /dev/null +++ b/compilerplugins/clang/expandablemethods.cxx @@ -0,0 +1,325 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include + + +#include "clang/AST/Attr.h" + +#include "config_clang.h" + +#include "plugin.hxx" + +/** + Find methods that are only called from inside their own class, and are only called from one spot. + They are candidates to be removed and have their code inlined into the call site. + + + TODO if a method has only one call-site, and that call site is inside a constructor + then it's probably worth inlining, since it's probably an old method that was intended to be shared amongst + multiple constructors +*/ + +namespace { + +struct MyFuncInfo +{ + std::string access; + std::string returnType; + std::string nameAndParams; + std::string sourceLocation; + +}; +bool operator < (const MyFuncInfo &lhs, const MyFuncInfo &rhs) +{ + return std::tie(lhs.returnType, lhs.nameAndParams) + < std::tie(rhs.returnType, rhs.nameAndParams); +} + +// try to limit the voluminous output a little + +static std::set> calledFromSet; +static std::set definitionSet; +static std::set calledFromOutsideSet; +static std::set largeFunctionSet; +static std::set addressOfSet; + + +class ExpandableMethods: + public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit ExpandableMethods(loplugin::InstantiationData const & data): + Plugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + + std::string output; + for (const MyFuncInfo & s : definitionSet) + output += "definition:\t" + s.access + "\t" + s.returnType + "\t" + s.nameAndParams + "\t" + s.sourceLocation + "\n"; + for (const MyFuncInfo & s : calledFromOutsideSet) + output += "outside:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; + for (const std::pair & s : calledFromSet) + output += "calledFrom:\t" + s.first + + "\t" + s.second.returnType + "\t" + s.second.nameAndParams + "\n"; + for (const MyFuncInfo & s : largeFunctionSet) + output += "large:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; + for (const MyFuncInfo & s : addressOfSet) + output += "addrof:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; + std::ofstream myfile; + myfile.open( WORKDIR "/loplugin.expandablemethods.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + + bool shouldVisitTemplateInstantiations () const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitFunctionDecl( const FunctionDecl* ); + bool VisitDeclRefExpr( const DeclRefExpr* ); + bool VisitMemberExpr( const MemberExpr* ); + // interception methods for FunctionDecl and all its subclasses + bool TraverseFunctionDecl( FunctionDecl* ); + bool TraverseCXXMethodDecl( CXXMethodDecl* ); + bool TraverseCXXConstructorDecl( CXXConstructorDecl* ); + bool TraverseCXXConversionDecl( CXXConversionDecl* ); + bool TraverseCXXDestructorDecl( CXXDestructorDecl* ); + +private: + MyFuncInfo niceName(const FunctionDecl* functionDecl); + std::string toString(SourceLocation loc); + void functionTouchedFromExpr( const FunctionDecl* calleeFunctionDecl, const Expr* expr ); + bool isCalleeFunctionInteresting( const FunctionDecl* ); + + // I use traverse and a member variable because I cannot find a reliable way of walking back up the AST tree using the parentStmt() stuff + std::vector maTraversingFunctions; +}; + +MyFuncInfo ExpandableMethods::niceName(const FunctionDecl* functionDecl) +{ + if (functionDecl->getInstantiatedFromMemberFunction()) + functionDecl = functionDecl->getInstantiatedFromMemberFunction(); + else if (functionDecl->getTemplateInstantiationPattern()) + functionDecl = functionDecl->getTemplateInstantiationPattern(); + + MyFuncInfo aInfo; + switch (functionDecl->getAccess()) + { + case AS_public: aInfo.access = "public"; break; + case AS_private: aInfo.access = "private"; break; + case AS_protected: aInfo.access = "protected"; break; + default: aInfo.access = "unknown"; break; + } + if (!isa(functionDecl)) { + aInfo.returnType = functionDecl->getReturnType().getCanonicalType().getAsString(); + } else { + aInfo.returnType = ""; + } + + if (isa(functionDecl)) { + const CXXRecordDecl* recordDecl = dyn_cast(functionDecl)->getParent(); + aInfo.nameAndParams += recordDecl->getQualifiedNameAsString(); + aInfo.nameAndParams += "::"; + } + aInfo.nameAndParams += functionDecl->getNameAsString() + "("; + bool bFirst = true; + for (const ParmVarDecl *pParmVarDecl : functionDecl->parameters()) { + if (bFirst) + bFirst = false; + else + aInfo.nameAndParams += ","; + aInfo.nameAndParams += pParmVarDecl->getType().getCanonicalType().getAsString(); + } + aInfo.nameAndParams += ")"; + if (isa(functionDecl) && dyn_cast(functionDecl)->isConst()) { + aInfo.nameAndParams += " const"; + } + + aInfo.sourceLocation = toString( functionDecl->getLocation() ); + + return aInfo; +} + +std::string ExpandableMethods::toString(SourceLocation loc) +{ + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( loc ); + StringRef name = getFilenameOfLocation(expansionLoc); + std::string sourceLocation = std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(sourceLocation); + return sourceLocation; +} + +bool ExpandableMethods::VisitFunctionDecl( const FunctionDecl* functionDecl ) +{ + const FunctionDecl* canonicalFunctionDecl = functionDecl->getCanonicalDecl(); + if (!isCalleeFunctionInteresting(canonicalFunctionDecl)) { + return true; + } + definitionSet.insert(niceName(canonicalFunctionDecl)); + + if (functionDecl->doesThisDeclarationHaveABody()) { + bool bLargeFunction = false; + if (const CompoundStmt* compoundStmt = dyn_cast(functionDecl->getBody())) { + if (compoundStmt->size() > 1) { + bLargeFunction = true; + } + if (!bLargeFunction) { + auto s1 = compiler.getSourceManager().getCharacterData(compoundStmt->getLBracLoc()); + auto s2 = compiler.getSourceManager().getCharacterData(compoundStmt->getRBracLoc()); + bLargeFunction = (s2 - s1) > 40; + // any function that uses a parameter more than once + if (!bLargeFunction) { + StringRef bodyText(s1, s2-s1); + for (const ParmVarDecl* param : functionDecl->parameters()) { + StringRef name = param->getName(); + if (name.empty()) + continue; + size_t idx = bodyText.find(name); + if (idx != StringRef::npos && bodyText.find(name, idx+1) != StringRef::npos) { + bLargeFunction = true; + break; + } + } + } + } + } + if (bLargeFunction) { + largeFunctionSet.insert(niceName(canonicalFunctionDecl)); + } + } + return true; +} + +bool ExpandableMethods::TraverseFunctionDecl( FunctionDecl* p ) +{ + maTraversingFunctions.push_back(p); + bool ret = RecursiveASTVisitor::TraverseFunctionDecl(p); + maTraversingFunctions.pop_back(); + return ret; +} +bool ExpandableMethods::TraverseCXXMethodDecl( CXXMethodDecl* p ) +{ + maTraversingFunctions.push_back(p); + bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(p); + maTraversingFunctions.pop_back(); + return ret; +} +bool ExpandableMethods::TraverseCXXConstructorDecl( CXXConstructorDecl* p ) +{ + maTraversingFunctions.push_back(p); + bool ret = RecursiveASTVisitor::TraverseCXXConstructorDecl(p); + maTraversingFunctions.pop_back(); + return ret; +} +bool ExpandableMethods::TraverseCXXConversionDecl( CXXConversionDecl* p ) +{ + maTraversingFunctions.push_back(p); + bool ret = RecursiveASTVisitor::TraverseCXXConversionDecl(p); + maTraversingFunctions.pop_back(); + return ret; +} +bool ExpandableMethods::TraverseCXXDestructorDecl( CXXDestructorDecl* p ) +{ + maTraversingFunctions.push_back(p); + bool ret = RecursiveASTVisitor::TraverseCXXDestructorDecl(p); + maTraversingFunctions.pop_back(); + return ret; +} + +bool ExpandableMethods::VisitMemberExpr( const MemberExpr* memberExpr ) +{ + const FunctionDecl* functionDecl = dyn_cast(memberExpr->getMemberDecl()); + if (functionDecl) { + functionTouchedFromExpr(functionDecl, memberExpr); + } + return true; +} + +bool ExpandableMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) +{ + const FunctionDecl* functionDecl = dyn_cast(declRefExpr->getDecl()); + if (functionDecl) { + functionTouchedFromExpr(functionDecl, declRefExpr); + } + return true; +} + +void ExpandableMethods::functionTouchedFromExpr( const FunctionDecl* calleeFunctionDecl, const Expr* expr ) +{ + const FunctionDecl* canonicalFunctionDecl = calleeFunctionDecl->getCanonicalDecl(); + if (!isCalleeFunctionInteresting(canonicalFunctionDecl)) { + return; + } + + calledFromSet.emplace(toString(expr->getBeginLoc()), niceName(canonicalFunctionDecl)); + + if (const UnaryOperator* unaryOp = dyn_cast_or_null(getParentStmt(expr))) { + if (unaryOp->getOpcode() == UO_AddrOf) { + addressOfSet.insert(niceName(canonicalFunctionDecl)); + } + } + + const CXXMethodDecl* calleeMethodDecl = dyn_cast(calleeFunctionDecl); + if (maTraversingFunctions.empty()) + { + calledFromOutsideSet.insert(niceName(canonicalFunctionDecl)); + } + else + { + const CXXMethodDecl* callsiteParentMethodDecl = dyn_cast(maTraversingFunctions.back()); + if (!callsiteParentMethodDecl + || calleeMethodDecl->getParent() != callsiteParentMethodDecl->getParent()) + { + calledFromOutsideSet.insert(niceName(canonicalFunctionDecl)); + } + } +} + +bool ExpandableMethods::isCalleeFunctionInteresting(const FunctionDecl* functionDecl) +{ + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) { + return false; + } + if (isa(functionDecl)) { + return false; + } + if (functionDecl->isDeleted() || functionDecl->isDefaulted()) { + return false; + } + if (isa(functionDecl) + && dyn_cast(functionDecl)->isCopyOrMoveConstructor()) + { + return false; + } + if (!functionDecl->getLocation().isValid() || ignoreLocation(functionDecl)) { + return false; + } + const CXXMethodDecl* methodDecl = dyn_cast(functionDecl); + if (!methodDecl || methodDecl->isVirtual()) { + return false; + } + return true; +} + +loplugin::Plugin::Registration< ExpandableMethods > X("expandablemethods", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/expandablemethods.py b/compilerplugins/clang/expandablemethods.py new file mode 100755 index 000000000..0fa61747d --- /dev/null +++ b/compilerplugins/clang/expandablemethods.py @@ -0,0 +1,150 @@ +#!/usr/bin/python + +import sys +import re +import io + +# -------------------------------------------------------------------------------------------- +# globals +# -------------------------------------------------------------------------------------------- + +definitionSet = set() # set of tuple(return_type, name_and_params) +definitionToSourceLocationMap = dict() +calledFromDict = dict() +calledFromOutsideSet = set() +largeFunctionSet = set() # set of tuple(return_type, name_and_params) +addressOfSet = set() # set of tuple(return_type, name_and_params) + +# clang does not always use exactly the same numbers in the type-parameter vars it generates +# so I need to substitute them to ensure we can match correctly. +normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") +def normalizeTypeParams( line ): + return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) + +# -------------------------------------------------------------------------------------------- +# primary input loop +# -------------------------------------------------------------------------------------------- + +with io.open("workdir/loplugin.expandablemethods.log", "rb", buffering=1024*1024) as txt: + for line in txt: + tokens = line.strip().split("\t") + if tokens[0] == "definition:": + access = tokens[1] + returnType = tokens[2] + nameAndParams = tokens[3] + sourceLocation = tokens[4] + funcInfo = (normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams)) + definitionSet.add(funcInfo) + definitionToSourceLocationMap[funcInfo] = sourceLocation + elif tokens[0] == "calledFrom:": + calleeLocation = tokens[1] + returnType = tokens[2] + nameAndParams = tokens[3] + funcInfo = (normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams)) + if not funcInfo in calledFromDict: + calledFromDict[funcInfo] = set() + calledFromDict[funcInfo].add(calleeLocation) + elif tokens[0] == "outside:": + returnType = tokens[1] + nameAndParams = tokens[2] + calledFromOutsideSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))) + elif tokens[0] == "large:": + returnType = tokens[1] + nameAndParams = tokens[2] + largeFunctionSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))) + elif tokens[0] == "addrof:": + returnType = tokens[1] + nameAndParams = tokens[2] + addressOfSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))) + else: + print( "unknown line: " + line) + +# Invert the definitionToSourceLocationMap. +# If we see more than one method at the same sourceLocation, it's being autogenerated as part of a template +# and we should just ignore it. +sourceLocationToDefinitionMap = {} +for k, v in definitionToSourceLocationMap.iteritems(): + sourceLocationToDefinitionMap[v] = sourceLocationToDefinitionMap.get(v, []) + sourceLocationToDefinitionMap[v].append(k) +for k, definitions in sourceLocationToDefinitionMap.iteritems(): + if len(definitions) > 1: + for d in definitions: + definitionSet.remove(d) + +def isOtherConstness( d, callSet ): + method = d[0] + " " + d[1] + # if this method is const, and there is a non-const variant of it, and the non-const variant is in use, then leave it alone + if d[0].startswith("const ") and d[1].endswith(" const"): + if ((d[0][6:],d[1][:-6]) in callSet): + return True + elif method.endswith(" const"): + method2 = method[:len(method)-6] # strip off " const" + if ((d[0],method2) in callSet): + return True + if method.endswith(" const") and ("::iterator" in method): + method2 = method[:len(method)-6] # strip off " const" + method2 = method2.replace("::const_iterator", "::iterator") + if ((d[0],method2) in callSet): + return True + # if this method is non-const, and there is a const variant of it, and the const variant is in use, then leave it alone + if (not method.endswith(" const")) and ((d[0],"const " + method + " const") in callSet): + return True + if (not method.endswith(" const")) and ("::iterator" in method): + method2 = method.replace("::iterator", "::const_iterator") + " const" + if ((d[0],method2) in callSet): + return True + return False + +# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[1]) + [v[0]] +def sort_set_by_natural_key(s): + return sorted(s, key=lambda v: v_sort_key(v)) + + +# -------------------------------------------------------------------------------------------- +# Methods that are only called from inside their own class, and are only called from one spot +# -------------------------------------------------------------------------------------------- + +tmp4set = set() +for d in definitionSet: + if d in calledFromOutsideSet: + continue + if isOtherConstness(d, calledFromOutsideSet): + continue + if d not in definitionToSourceLocationMap: + print("warning, method has no location: " + d[0] + " " + d[1]) + continue + # ignore external code + if definitionToSourceLocationMap[d].startswith("external/"): + continue + # ignore constructors, calledFromOutsideSet does not provide accurate info for them + tokens = d[1].split("(")[0].split("::") + if len(tokens)>1 and tokens[-2] == tokens[-1]: + continue + # ignore large methods, which make the code clearer by being out of line + if d in largeFunctionSet: + continue + # ignore methods whose address we take + if d in addressOfSet: + continue + # ignore unused methods, leave them to the dedicated analysis + if d not in calledFromDict: + continue + # ignore methods called from more than one site + if len(calledFromDict[d]) > 1: + continue + + method = d[0] + " " + d[1] + tmp4set.add((method, definitionToSourceLocationMap[d])) + +# print output, sorted by name and line number +with open("loplugin.expandablemethods.report", "wt") as f: + for t in sort_set_by_natural_key(tmp4set): + f.write(t[1] + "\n") + f.write(" " + t[0] + "\n") diff --git a/compilerplugins/clang/expressionalwayszero.cxx b/compilerplugins/clang/expressionalwayszero.cxx new file mode 100644 index 000000000..f741d30c4 --- /dev/null +++ b/compilerplugins/clang/expressionalwayszero.cxx @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#include "plugin.hxx" +#include "compat.hxx" +#include "check.hxx" + +/** + Look for & and operator& expressions where the result is always zero. + Generally a mistake when people meant to use | or operator| +*/ + +namespace +{ +class ExpressionAlwaysZero : public loplugin::FilteringPlugin +{ +public: + explicit ExpressionAlwaysZero(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + // don't use getMainFileID, it may return "" + std::string fn(handler.getMainFileName()); + + loplugin::normalizeDotDotInFilePath(fn); + // encoding of constant value for binary file format + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/package/source/zipapi/ZipFile.cxx")) + return; + // some auto-generated static data + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/textenc/tables.cxx")) + return; + // nested conditional defines that are not worth cleaning up + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/opencl/source/openclwrapper.cxx")) + return; + // some kind of matrix calculation, the compiler will optimise it out anyway + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/source/gdi/bitmap4.cxx")) + return; + // code follows a pattern + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/svx/source/svdraw/svdhdl.cxx")) + return; + // looks like some kind of TODO marker + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/chart2/source/view/main/PropertyMapper.cxx") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/core/data/formulacell.cxx")) + return; + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitBinaryOperator(BinaryOperator const*); + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const*); + bool TraverseStaticAssertDecl(StaticAssertDecl*); + +private: + // note, abusing std::unique_ptr as a std::optional lookalike + std::unique_ptr getExprValue(const Expr* arg); +}; + +bool ExpressionAlwaysZero::VisitBinaryOperator(BinaryOperator const* binaryOperator) +{ + if (ignoreLocation(binaryOperator)) + return true; + if (binaryOperator->getBeginLoc().isMacroID()) + return true; + + auto op = binaryOperator->getOpcode(); + if (!(op == BO_And || op == BO_AndAssign || op == BO_LAnd)) + return true; + + auto lhsValue = getExprValue(binaryOperator->getLHS()); + auto rhsValue = getExprValue(binaryOperator->getRHS()); + if (lhsValue && lhsValue->getExtValue() == 0) + ; // ok + else if (rhsValue && rhsValue->getExtValue() == 0) + ; // ok + else if (lhsValue && rhsValue && (lhsValue->getExtValue() & rhsValue->getExtValue()) == 0) + ; // ok + else + return true; + report(DiagnosticsEngine::Warning, "expression always evaluates to zero, lhs=%0 rhs=%1", + binaryOperator->getBeginLoc()) + << (lhsValue ? compat::toString(*lhsValue, 10) : "unknown") + << (rhsValue ? compat::toString(*rhsValue, 10) : "unknown") + << binaryOperator->getSourceRange(); + return true; +} + +bool ExpressionAlwaysZero::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* cxxOperatorCallExpr) +{ + if (ignoreLocation(cxxOperatorCallExpr)) + return true; + if (cxxOperatorCallExpr->getBeginLoc().isMacroID()) + return true; + + auto op = cxxOperatorCallExpr->getOperator(); + if (!(op == OO_Amp || op == OO_AmpEqual || op == OO_AmpAmp)) + return true; + + if (cxxOperatorCallExpr->getNumArgs() != 2) + return true; + auto lhsValue = getExprValue(cxxOperatorCallExpr->getArg(0)); + auto rhsValue = getExprValue(cxxOperatorCallExpr->getArg(1)); + if (lhsValue && lhsValue->getExtValue() == 0) + ; // ok + else if (rhsValue && rhsValue->getExtValue() == 0) + ; // ok + else if (lhsValue && rhsValue && (lhsValue->getExtValue() & rhsValue->getExtValue()) == 0) + ; // ok + else + return true; + report(DiagnosticsEngine::Warning, "expression always evaluates to zero, lhs=%0 rhs=%1", + cxxOperatorCallExpr->getBeginLoc()) + << (lhsValue ? compat::toString(*lhsValue, 10) : "unknown") + << (rhsValue ? compat::toString(*rhsValue, 10) : "unknown") + << cxxOperatorCallExpr->getSourceRange(); + return true; +} + +std::unique_ptr ExpressionAlwaysZero::getExprValue(Expr const* expr) +{ + expr = expr->IgnoreParenCasts(); + // ignore this, it seems to trigger an infinite recursion + if (isa(expr)) + { + return std::unique_ptr(); + } + APSInt x1; + if (!expr->isValueDependent() && compat::EvaluateAsInt(expr, x1, compiler.getASTContext())) + return std::unique_ptr(new APSInt(x1)); + return std::unique_ptr(); +} + +// these will often evaluate to zero harmlessly +bool ExpressionAlwaysZero::TraverseStaticAssertDecl(StaticAssertDecl*) { return true; } + +loplugin::Plugin::Registration X("expressionalwayszero", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/external.cxx b/compilerplugins/clang/external.cxx new file mode 100644 index 000000000..e3bc67f19 --- /dev/null +++ b/compilerplugins/clang/external.cxx @@ -0,0 +1,608 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include "clang/Sema/SemaDiagnostic.h" + +#include "check.hxx" +#include "plugin.hxx" + +namespace +{ +bool derivesFromTestFixture(CXXRecordDecl const* decl) +{ + static auto const pred = [](CXXBaseSpecifier const& spec) { + if (auto const t = spec.getType()->getAs()) + { // (may be a template parameter) + return derivesFromTestFixture(dyn_cast(t->getDecl())); + } + return false; + }; + return loplugin::DeclCheck(decl).Class("TestFixture").Namespace("CppUnit").GlobalNamespace() + || std::any_of(decl->bases_begin(), decl->bases_end(), pred) + || std::any_of(decl->vbases_begin(), decl->vbases_end(), pred); +} + +bool isInjectedFunction(FunctionDecl const* decl) +{ + for (auto d = decl->redecls_begin(); d != decl->redecls_end(); ++d) + { + auto const c = d->getLexicalDeclContext(); + if (!(c->isFunctionOrMethod() || c->isRecord())) + { + return false; + } + } + return true; +} + +// Whether type1 mentions type2 (in a way relevant for argument-dependent name lookup): +bool mentions(QualType type1, QualType type2) +{ + auto t1 = type1; + for (;;) + { + if (auto const t2 = t1->getAs()) + { + t1 = t2->getPointeeType(); + } + else if (auto const t3 = t1->getAs()) + { + t1 = t3->getPointeeType(); + } + else if (auto const t4 = t1->getAsArrayTypeUnsafe()) + { + t1 = t4->getElementType(); + } + else + { + break; + } + } + if (t1.getCanonicalType().getTypePtr() == type2.getTypePtr()) + { + return true; + } + if (auto const t2 = t1->getAs()) + { + for (auto a = t2->begin(); a != t2->end(); ++a) + { + if (a->getKind() != TemplateArgument::Type) + { + continue; + } + if (mentions(a->getAsType(), type2)) + { + return true; + } + } + auto const t3 = t2->desugar(); + if (t3.getTypePtr() == t2) + { + return false; + } + return mentions(t3, type2); + } + if (auto const t2 = t1->getAs()) + { + if (mentions(t2->getReturnType(), type2)) + { + return true; + } + for (auto t3 = t2->param_type_begin(); t3 != t2->param_type_end(); ++t3) + { + if (mentions(*t3, type2)) + { + return true; + } + } + return false; + } + if (auto const t2 = t1->getAs()) + { + if (t2->getClass()->getUnqualifiedDesugaredType() == type2.getTypePtr()) + { + return true; + } + return mentions(t2->getPointeeType(), type2); + } + return false; +} + +bool hasSalDllpublicExportAttr(Decl const* decl) +{ + if (auto const attr = decl->getAttr()) + { + return attr->getVisibility() == VisibilityAttr::Default; + } + return decl->hasAttr(); +} + +class External : public loplugin::FilteringPlugin +{ +public: + explicit External(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitTagDecl(TagDecl* decl) + { + if (isa(decl)) + { + return true; + } + if (!decl->isThisDeclarationADefinition()) + { + return true; + } + if (isa(decl->getDeclContext())) + { + return true; + } + if (!compiler.getLangOpts().CPlusPlus) + { + return true; + } + if (auto const d = dyn_cast(decl)) + { + if (d->getDescribedClassTemplate() != nullptr) + { + return true; + } + if (hasSalDllpublicExportAttr(d)) + { + // If the class definition has explicit default visibility, then assume that it + // needs to be present (e.g., a backwards-compatibility stub like in + // cppuhelper/source/compat.cxx): + return true; + } + if (derivesFromTestFixture(d)) + { + // The names of CppUnit tests (that can be specified with CPPUNIT_TEST_NAME) are + // tied to the fully-qualified names of classes derived from CppUnit::TestFixture, + // so avoid unnamed namespaces in those classes' names: + return true; + } + } + return handleDeclaration(decl); + } + + bool VisitFunctionDecl(FunctionDecl* decl) + { + if (isa(decl)) + { + return true; + } + if (decl->getTemplatedKind() != FunctionDecl::TK_NonTemplate) + { + return true; + } + if (!decl->isThisDeclarationADefinition()) + { + return true; + } + if (decl->isMain() || decl->isMSVCRTEntryPoint()) + { + return true; + } + if (loplugin::hasCLanguageLinkageType(decl) + && loplugin::DeclCheck(decl).Function("_DllMainCRTStartup").GlobalNamespace()) + { + return true; + } + // If the function definition is explicit marked SAL_DLLPUBLIC_EXPORT or similar, then + // assume that it needs to be present (e.g., only called via dlopen, or a backwards- + // compatibility stub like in sal/osl/all/compat.cxx): + if (hasSalDllpublicExportAttr(decl)) + { + return true; + } + auto const canon = decl->getCanonicalDecl(); + if (loplugin::hasCLanguageLinkageType(canon) + && (canon->hasAttr() || canon->hasAttr())) + { + return true; + } + if (compiler.getDiagnostics().getDiagnosticLevel(diag::warn_unused_function, + decl->getLocation()) + < DiagnosticsEngine::Warning) + { + // Don't warn about e.g. + // + // G_DEFINE_TYPE (GLOAction, g_lo_action, G_TYPE_OBJECT); + // + // in vcl/unx/gtk/gloactiongroup.cxx (which expands to non-static g_lo_action_get_type + // function definition), which is already wrapped in + // + // #pragma GCC diagnostic ignored "-Wunused-function" + return true; + } + if (isInjectedFunction(decl)) + { + return true; + } + return handleDeclaration(decl); + } + + bool VisitVarDecl(VarDecl* decl) + { + if (decl->isStaticDataMember()) + { + return true; + } + if (isa(decl)) + { + return true; + } + if (!decl->isThisDeclarationADefinition()) + { + return true; + } + if (loplugin::DeclCheck(decl).Var("_pRawDllMain").GlobalNamespace()) + { + return true; + } + return handleDeclaration(decl); + } + + bool VisitClassTemplateDecl(ClassTemplateDecl* decl) + { + if (!decl->isThisDeclarationADefinition()) + { + return true; + } + if (isa(decl->getDeclContext())) + { + return true; + } + return handleDeclaration(decl); + } + + bool VisitFunctionTemplateDecl(FunctionTemplateDecl* decl) + { + if (!decl->isThisDeclarationADefinition()) + { + return true; + } + if (isa(decl->getDeclContext())) + { + return true; + } + if (isInjectedFunction(decl->getTemplatedDecl())) + { + return true; + } + return handleDeclaration(decl); + } + + bool VisitVarTemplateDecl(VarTemplateDecl* decl) + { + if (!decl->isThisDeclarationADefinition()) + { + return true; + } + return handleDeclaration(decl); + } + +private: + template void reportSpecializations(T specializations) + { + for (auto const d : specializations) + { + auto const k = d->getTemplateSpecializationKind(); + if (isTemplateExplicitInstantiationOrSpecialization(k)) + { + report(DiagnosticsEngine::Note, + "explicit %select{instantiation|specialization}0 is here", d->getLocation()) + << (k == TSK_ExplicitSpecialization) << d->getSourceRange(); + } + } + } + + void computeAffectedTypes(Decl const* decl, std::vector* affected) + { + assert(affected != nullptr); + if (auto const d = dyn_cast(decl)) + { + affected->push_back(compiler.getASTContext().getEnumType(d)); + } + else + { + //TODO: Derived types are also affected! + CXXRecordDecl const* rec; + if (auto const d = dyn_cast(decl)) + { + rec = d->getTemplatedDecl(); + } + else + { + rec = cast(decl); + } + affected->push_back(compiler.getASTContext().getRecordType(rec)); + for (auto d = rec->decls_begin(); d != rec->decls_end(); ++d) + { + if (*d != (*d)->getCanonicalDecl()) + { + continue; + } + if (isa(*d) || isa(*d)) + { + if (auto const d1 = dyn_cast(*d)) + { + if (d1->isInjectedClassName()) + { + continue; + } + } + computeAffectedTypes(*d, affected); + } + } + } + } + + void reportAssociatingFunctions(std::vector const& affected, Decl* decl) + { + auto c = decl->getDeclContext(); + while (isa(c) || c->isInlineNamespace()) + { + c = c->getParent(); + } + assert(c->isTranslationUnit() || c->isNamespace()); + SmallVector parts; + c->collectAllContexts(parts); + std::list ctxs; + std::copy(parts.begin(), parts.end(), + std::back_insert_iterator>(ctxs)); + if (auto const d = dyn_cast(decl)) + { + // To find friend functions declared in the class: + ctxs.push_back(d); + } + std::set fdecls; // to report every function just once + for (auto ctx = ctxs.begin(); ctx != ctxs.end(); ++ctx) + { + for (auto i = (*ctx)->decls_begin(); i != (*ctx)->decls_end(); ++i) + { + auto d = *i; + if (auto const d1 = dyn_cast(d)) + { + ctxs.push_back(d1); + continue; + } + if (auto const d1 = dyn_cast(d)) + { + if (d1->isInline()) + { + ctxs.push_back(d1); + } + continue; + } + if (auto const d1 = dyn_cast(d)) + { + d = d1->getFriendDecl(); + if (d == nullptr) // happens for 'friend struct S;' + { + continue; + } + } + FunctionDecl const* f; + if (auto const d1 = dyn_cast(d)) + { + f = d1->getTemplatedDecl(); + } + else + { + f = dyn_cast(d); + if (f == nullptr) + { + continue; + } + } + if (!fdecls.insert(f->getCanonicalDecl()).second) + { + continue; + } + if (isa(f)) + { + continue; + } + for (auto const& t : affected) + { + auto const tc = t.getCanonicalType(); + for (auto p = f->param_begin(); p != f->param_end(); ++p) + { + if (mentions((*p)->getType(), tc)) + { + report(DiagnosticsEngine::Note, + "a %select{function|function template|function template " + "specialization}0 associating %1 is declared here", + f->getLocation()) + << (f->isFunctionTemplateSpecialization() + ? 2 + : f->getDescribedFunctionTemplate() != nullptr ? 1 : 0) + << t << f->getSourceRange(); + for (auto f1 = f->redecls_begin(); f1 != f->redecls_end(); ++f1) + { + if (*f1 == f) + { + continue; + } + report(DiagnosticsEngine::Note, "another declaration is here", + f1->getLocation()) + << f1->getSourceRange(); + } + break; + } + } + } + } + } + } + + void reportAssociatingFunctions(Decl* decl) + { + std::vector affected; // enum/class/class template + recursively affected members + computeAffectedTypes(decl, &affected); + reportAssociatingFunctions(affected, decl); + } + + bool handleDeclaration(NamedDecl* decl) + { + if (ignoreLocation(decl)) + { + return true; + } + if (decl->getLinkageInternal() < ModuleLinkage) + { + return true; + } + // In some cases getLinkageInternal() arguably wrongly reports ExternalLinkage, see the + // commit message of "DR1113: anonymous namespaces formally give + // their contents internal linkage": + // + // "We still deviate from the standard in one regard here: extern "C" declarations + // in anonymous namespaces are still granted external linkage. Changing those does + // not appear to have been an intentional consequence of the standard change in + // DR1113." + // + // Do not warn about such "wrongly external" declarations here: + if (decl->isInAnonymousNamespace()) + { + return true; + } + for (Decl const* d = decl; d != nullptr; d = d->getPreviousDecl()) + { + if (!compiler.getSourceManager().isInMainFile(d->getLocation())) + { + return true; + } + } + if (compiler.getSourceManager().isMacroBodyExpansion(decl->getLocation())) + { + if (Lexer::getImmediateMacroName(decl->getLocation(), compiler.getSourceManager(), + compiler.getLangOpts()) + == "MDDS_MTV_DEFINE_ELEMENT_CALLBACKS") + { + // Even wrapping in an unnamed namespace or sneaking "static" into the macro + // wouldn't help, as then some of the functions it defines would be flagged as + // unused: + return true; + } + } + else if (compiler.getSourceManager().isMacroArgExpansion(decl->getLocation())) + { + if (Lexer::getImmediateMacroName(decl->getLocation(), compiler.getSourceManager(), + compiler.getLangOpts()) + == "DEFINE_GUID") + { + // Windows, guiddef.h: + return true; + } + } + TypedefNameDecl const* typedefed = nullptr; + if (auto const d = dyn_cast(decl)) + { + typedefed = d->getTypedefNameForAnonDecl(); + } + bool canStatic; + if (auto const d = dyn_cast(decl)) + { + canStatic = d->isUnion() && d->isAnonymousStructOrUnion(); + } + else + { + canStatic = isa(decl) || isa(decl) + || isa(decl) || isa(decl); + } + // In general, moving functions into an unnamed namespace can: break ADL like in + // + // struct S1 { int f() { return 1; } }; + // int f(S1 s) { return s.f(); } + // namespace N { + // struct S2: S1 { int f() { return 0; } }; + // int f(S2 s) { return s.f(); } // [*] + // } + // int main() { return f(N::S2()); } + // + // changing from returning 0 to returning 1 when [*] is moved into an unnamed namespace; can + // conflict with function declarations in the moved function like in + // + // int f(int) { return 0; } + // namespace { int f(int) { return 1; } } + // int g() { // [*] + // int f(int); + // return f(0); + // } + // int main() { return g(); } + // + // changing from returning 0 to returning 1 when [*] is moved into an unnamed namespace; and + // can conflict with overload resolution in general like in + // + // int f(int) { return 0; } + // namespace { int f(...) { return 1; } } + // int g() { return f(0); } // [*] + // int main() { return g(); } + // + // changing from returning 0 to returning 1 when [*] is moved into an unnamed namespace: + auto const canUnnamed = compiler.getLangOpts().CPlusPlus + && !(isa(decl) || isa(decl)); + assert(canStatic || canUnnamed); + report( + DiagnosticsEngine::Warning, + ("externally available%select{| typedef'ed}0 entity %1 is not previously declared in an" + " included file (if it is only used in this translation unit," + " %select{|make it static}2%select{| or }3%select{|put it in an unnamed namespace}4;" + " otherwise, provide a declaration of it in an included file)"), + decl->getLocation()) + << (typedefed != nullptr) << (typedefed == nullptr ? decl : typedefed) << canStatic + << (canStatic && canUnnamed) << canUnnamed << decl->getSourceRange(); + for (auto d = decl->redecls_begin(); d != decl->redecls_end(); ++d) + { + if (*d == decl) + { + continue; + } + report(DiagnosticsEngine::Note, "another declaration is here", d->getLocation()) + << d->getSourceRange(); + } + //TODO: Class template specializations can be in the enclosing namespace, so no need to + // list them here (as they won't need to be put into the unnamed namespace too, unlike for + // specializations of function and variable templates); and explicit function template + // specializations cannot have storage-class specifiers, so as we only suggest to make + // function templates static (but not to move them into an unnamed namespace), no need to + // list function template specializations here, either: + if (auto const d = dyn_cast(decl)) + { + reportSpecializations(d->specializations()); + } + if (isa(decl) || isa(decl)) + { + reportAssociatingFunctions(decl); + } + return true; + } +}; + +loplugin::Plugin::Registration external("external"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/externandnotdefined.cxx b/compilerplugins/clang/externandnotdefined.cxx new file mode 100644 index 000000000..5fd59ca4b --- /dev/null +++ b/compilerplugins/clang/externandnotdefined.cxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include + +#include "plugin.hxx" + +// Having an extern prototype for a method in a module and not actually declaring that method is dodgy. +// + +namespace { + +class ExternAndNotDefined: + public loplugin::FilteringPlugin +{ +public: + explicit ExternAndNotDefined(loplugin::InstantiationData const & data): FilteringPlugin(data) {} + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitFunctionDecl(const FunctionDecl * decl); +}; + +bool ExternAndNotDefined::VisitFunctionDecl(const FunctionDecl * functionDecl) { + if (ignoreLocation(functionDecl)) { + return true; + } + if (functionDecl->isDefined() || functionDecl->isPure() + || (functionDecl->getLinkageAndVisibility().getLinkage() + != ExternalLinkage)) { + return true; + } + //TODO, filtering out anything template for now: + if (functionDecl->isDependentContext()) { + return true; + } + CXXRecordDecl const * r = dyn_cast(functionDecl->getDeclContext()); + if (r != nullptr && r->getTemplateSpecializationKind() != TSK_Undeclared) { + return true; + } + // this is the bison/flex C API, it has to be defined this way + std::string functionName = functionDecl->getNameAsString(); + if (functionName == "yyerror" || functionName == "yyparse" || functionName == "yylex") { + return true; + } + // see vcl/unx/gtk/app/gtksys.cxx, typename conflicts prevent using the right include + if (functionName == "gdk_x11_screen_get_screen_number") { + return true; + } + if (!compiler.getSourceManager().isInMainFile(functionDecl->getLocation())) + { + return true; + } + report( + DiagnosticsEngine::Warning, + "extern prototype in main file without definition", + functionDecl->getLocation()) + << functionDecl->getSourceRange(); + return true; +} + + +loplugin::Plugin::Registration< ExternAndNotDefined > externandnotdefined("externandnotdefined"); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/faileddyncast.cxx b/compilerplugins/clang/faileddyncast.cxx new file mode 100644 index 000000000..078d5c884 --- /dev/null +++ b/compilerplugins/clang/faileddyncast.cxx @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include + +#include "clang/AST/Attr.h" +#include "clang/AST/CXXInheritance.h" + +#include "plugin.hxx" + +namespace { + +// cf. Clang's clang::AST::CXXDynamicCastExpr::isAlwaysNull +// (lib/AST/ExprCXX.cpp): +bool isAlwaysNull(CXXDynamicCastExpr const * expr) { + QualType SrcType = expr->getSubExpr()->getType(); + QualType DestType = expr->getType(); + + if (const clang::PointerType *SrcPTy = SrcType->getAs()) { + SrcType = SrcPTy->getPointeeType(); +#if 0 + DestType = DestType->castAs()->getPointeeType(); +#else + auto DstPTy = DestType->getAs(); + if (!DstPTy) + return false; + DestType = DstPTy->getPointeeType(); +#endif + } + + if (DestType->isVoidType()) + return false; + +#if 0 + const CXXRecordDecl *SrcRD = + cast(SrcType->castAs()->getDecl()); +#else + auto SrcRT = SrcType->getAs(); + if (!SrcRT) + return false; + const CXXRecordDecl *SrcRD = cast(SrcRT->getDecl()); +#endif + +#if 0 + if (!SrcRD->hasAttr()) + return false; +#endif + +#if 0 + const CXXRecordDecl *DestRD = + cast(DestType->castAs()->getDecl()); +#else + auto DestRT = DestType->getAs(); + if (!DestRT) + return false; + const CXXRecordDecl *DestRD = cast(DestRT->getDecl()); +#endif + +#if 1 + if (!(SrcRD && DestRD)) + return false; + + if (DestRD->hasAttr()) { + CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + if (DestRD->isDerivedFrom(SrcRD, Paths) && + std::all_of(Paths.begin(), Paths.end(), + [](CXXBasePath const & Path) { + return Path.Access != AS_public; })) + return true; + } + + if (!SrcRD->hasAttr()) + return false; +#endif + +#if 0 + return !DestRD->isDerivedFrom(SrcRD); +#else + return !(DestRD->isDerivedFrom(SrcRD) + || SrcRD->isDerivedFrom(DestRD) + || SrcRD == DestRD); +#endif +} + +class FailedDynCast: + public loplugin::FilteringPlugin +{ +public: + explicit FailedDynCast(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + bool shouldVisitTemplateInstantiations() const { return true; } + + bool preRun() override; + void run() override; + + bool VisitCXXDynamicCastExpr(CXXDynamicCastExpr const * expr); +}; + +bool FailedDynCast::preRun() { + return compiler.getLangOpts().CPlusPlus; +} + +void FailedDynCast::run() { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } +} + +bool FailedDynCast::VisitCXXDynamicCastExpr(CXXDynamicCastExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (isAlwaysNull(expr)) { + report( + DiagnosticsEngine::Warning, + "dynamic_cast from %0 to %1 always fails", expr->getBeginLoc()) + << expr->getSubExpr()->getType() << expr->getType() + << expr->getSourceRange(); + } + return true; +} + +loplugin::Plugin::Registration faileddyncast("faileddyncast"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/fakebool.cxx b/compilerplugins/clang/fakebool.cxx new file mode 100644 index 000000000..cc7a9434a --- /dev/null +++ b/compilerplugins/clang/fakebool.cxx @@ -0,0 +1,910 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "clang/AST/Attr.h" +#include "clang/Basic/Builtins.h" + +#include "config_clang.h" + +#include "check.hxx" +#include "functionaddress.hxx" +#include "plugin.hxx" + +namespace { + +enum FakeBoolKind { + FBK_No, + FBK_BOOL, FBK_First = FBK_BOOL, + FBK_Boolean, FBK_FT_Bool, FBK_FcBool, FBK_GLboolean, FBK_NPBool, FBK_TW_BOOL, FBK_UBool, + FBK_boolean, FBK_dbus_bool_t, FBK_gboolean, FBK_hb_boot_t, FBK_jboolean, FBK_my_bool, + FBK_sal_Bool, + FBK_End }; + // matches loplugin::TypeCheck::AnyBoolean (compilerplugins/clang/check.hxx) + +StringRef getName(FakeBoolKind k) { + static constexpr llvm::StringLiteral names[] = { + "BOOL", "Boolean", "FT_Bool", "FcBool", "GLboolean", "NPBool", "TW_BOOL", "UBool", + "boolean", "dbus_bool_t", "gboolean", "hb_boot_t", "jboolean", "my_bool", "sal_Bool"}; + assert(k >= FBK_First && k < FBK_End); + return names[k - FBK_First]; +} + +FakeBoolKind isFakeBool(QualType type) { + TypedefType const * t = type->getAs(); + if (t != nullptr) { + auto const name = t->getDecl()->getName(); + for (int i = FBK_First; i != FBK_End; ++i) { + auto const k = FakeBoolKind(i); + if (name == getName(k)) { + return k; + } + } + } + return FBK_No; +} + +FakeBoolKind isFakeBoolArray(QualType type) { + auto t = type->getAsArrayTypeUnsafe(); + if (t == nullptr) { + return FBK_No; + } + auto const k = isFakeBool(t->getElementType()); + if (k != FBK_No) { + return k; + } + return isFakeBoolArray(t->getElementType()); +} + +// It appears that, given a function declaration, there is no way to determine +// the language linkage of the function's type, only of the function's name +// (via FunctionDecl::isExternC); however, in a case like +// +// extern "C" { static void f(); } +// +// the function's name does not have C language linkage while the function's +// type does (as clarified in C++11 [decl.link]); cf. +// "Language linkage of function type": +bool hasCLanguageLinkageType(FunctionDecl const * decl) { + assert(decl != nullptr); + if (decl->isExternC()) { + return true; + } + if (decl->isInExternCContext()) { + return true; + } + return false; +} + +enum class OverrideKind { NO, YES, MAYBE }; + +OverrideKind getOverrideKind(FunctionDecl const * decl) { + CXXMethodDecl const * m = dyn_cast(decl); + if (m == nullptr) { + return OverrideKind::NO; + } + if (m->size_overridden_methods() != 0 || m->hasAttr()) { + return OverrideKind::YES; + } + if (!dyn_cast(m->getDeclContext())->hasAnyDependentBases()) { + return OverrideKind::NO; + } + return OverrideKind::MAYBE; +} + +enum class BoolOverloadKind { No, Yes, CheckNext }; + +BoolOverloadKind isBoolOverloadOf( + FunctionDecl const * f, FunctionDecl const * decl, bool mustBeDeleted) +{ + if (!mustBeDeleted || f->isDeleted()) { + unsigned n = decl->getNumParams(); + if (f->getNumParams() == n) { + bool hasFB = false; + for (unsigned i = 0; i != n; ++i) { + QualType t1 { decl->getParamDecl(i)->getType() }; + bool isFB = isFakeBool(t1) != FBK_No; + bool isFBRef = !isFB && t1->isReferenceType() + && isFakeBool(t1.getNonReferenceType()) != FBK_No; + QualType t2 { f->getParamDecl(i)->getType() }; + if (!(isFB + ? t2->isBooleanType() + : isFBRef + ? (t2->isReferenceType() + && t2.getNonReferenceType()->isBooleanType()) + : t2.getCanonicalType() == t1.getCanonicalType())) + { + return BoolOverloadKind::CheckNext; + } + hasFB |= isFB || isFBRef; + } + return hasFB ? BoolOverloadKind::Yes : BoolOverloadKind::No; + // cheaply protect against the case where decl would have no + // fake bool parameters at all and would match itself + } + } + return BoolOverloadKind::CheckNext; +} + +//TODO: current implementation is not at all general, just tests what we +// encounter in practice: +bool hasBoolOverload(FunctionDecl const * decl, bool mustBeDeleted) { + auto ctx = decl->getDeclContext(); + if (!ctx->isLookupContext()) { + return false; + } + auto res = ctx->lookup(decl->getDeclName()); + for (auto d = res.begin(); d != res.end(); ++d) { + if (auto f = dyn_cast(*d)) { + switch (isBoolOverloadOf(f, decl, mustBeDeleted)) { + case BoolOverloadKind::No: + return false; + case BoolOverloadKind::Yes: + return true; + case BoolOverloadKind::CheckNext: + break; + } + } else if (auto ftd = dyn_cast(*d)) { + for (auto f: ftd->specializations()) { + if (f->getTemplateSpecializationKind() + == TSK_ExplicitSpecialization) + { + switch (isBoolOverloadOf(f, decl, mustBeDeleted)) { + case BoolOverloadKind::No: + return false; + case BoolOverloadKind::Yes: + return true; + case BoolOverloadKind::CheckNext: + break; + } + } + } + } + } + return false; +} + +class FakeBool: + public loplugin::FunctionAddress> +{ +public: + explicit FakeBool(loplugin::InstantiationData const & data): + FunctionAddress(data) {} + + virtual void run() override; + + bool VisitUnaryOperator(UnaryOperator * op); + + bool VisitCallExpr(CallExpr * expr); + + bool VisitCStyleCastExpr(CStyleCastExpr * expr); + + bool VisitCXXStaticCastExpr(CXXStaticCastExpr * expr); + + bool VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr * expr); + + bool VisitImplicitCastExpr(ImplicitCastExpr * expr); + + bool VisitReturnStmt(ReturnStmt const * stmt); + + bool WalkUpFromParmVarDecl(ParmVarDecl const * decl); + bool VisitParmVarDecl(ParmVarDecl const * decl); + + bool WalkUpFromVarDecl(VarDecl const * decl); + bool VisitVarDecl(VarDecl const * decl); + + bool WalkUpFromFieldDecl(FieldDecl const * decl); + bool VisitFieldDecl(FieldDecl const * decl); + + bool WalkUpFromFunctionDecl(FunctionDecl const * decl); + bool VisitFunctionDecl(FunctionDecl const * decl); + + bool VisitValueDecl(ValueDecl const * decl); + + bool TraverseLinkageSpecDecl(LinkageSpecDecl * decl); + +private: + bool isFromCIncludeFile(SourceLocation spellingLocation) const; + + bool isSharedCAndCppCode(SourceLocation location) const; + + bool rewrite(SourceLocation location, FakeBoolKind kind); + + std::map varDecls_; + std::map fieldDecls_; + std::map parmVarDecls_; + std::map functionDecls_; + unsigned int externCContexts_ = 0; +}; + +void FakeBool::run() { + if (compiler.getLangOpts().CPlusPlus) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + for (auto const & dcl: varDecls_) { + auto const decl = dcl.first; auto const fbk = dcl.second; + SourceLocation loc { decl->getBeginLoc() }; + TypeSourceInfo * tsi = decl->getTypeSourceInfo(); + if (tsi != nullptr) { + SourceLocation l { + compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getBeginLoc()) }; + SourceLocation end { + compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getEndLoc()) }; + assert(l.isFileID() && end.isFileID()); + if (l == end + || compiler.getSourceManager().isBeforeInTranslationUnit( + l, end)) + { + for (;;) { + unsigned n = Lexer::MeasureTokenLength( + l, compiler.getSourceManager(), + compiler.getLangOpts()); + std::string s { + compiler.getSourceManager().getCharacterData(l), + n }; + if (s == getName(fbk)) { + loc = l; + break; + } + if (l == end) { + break; + } + l = l.getLocWithOffset(std::max(n, 1)); + } + } + } + if (!(suppressWarningAt(loc) || rewrite(loc, fbk))) { + report( + DiagnosticsEngine::Warning, + "VarDecl, use \"bool\" instead of %0", loc) + << decl->getType().getLocalUnqualifiedType() + << decl->getSourceRange(); + } + } + for (auto const & dcl: fieldDecls_) { + auto const decl = dcl.first; auto const fbk = dcl.second; + SourceLocation loc { decl->getBeginLoc() }; + TypeSourceInfo * tsi = decl->getTypeSourceInfo(); + if (tsi != nullptr) { + SourceLocation l { + compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getBeginLoc()) }; + SourceLocation end { + compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getEndLoc()) }; + assert(l.isFileID() && end.isFileID()); + if (l == end + || compiler.getSourceManager().isBeforeInTranslationUnit( + l, end)) + { + for (;;) { + unsigned n = Lexer::MeasureTokenLength( + l, compiler.getSourceManager(), + compiler.getLangOpts()); + std::string s { + compiler.getSourceManager().getCharacterData(l), + n }; + if (s == getName(fbk)) { + loc = l; + break; + } + if (l == end) { + break; + } + l = l.getLocWithOffset(std::max(n, 1)); + } + } + } + if (!(suppressWarningAt(loc) || rewrite(loc, fbk))) { + report( + DiagnosticsEngine::Warning, + "FieldDecl, use \"bool\" instead of %0", loc) + << decl->getType().getLocalUnqualifiedType() << decl->getSourceRange(); + } + } + auto const ignoredFns = getFunctionsWithAddressTaken(); + for (auto const & dcl: parmVarDecls_) { + auto const decl = dcl.first; auto const fbk = dcl.second; + FunctionDecl const * f = cast(decl->getDeclContext())->getCanonicalDecl(); + if (ignoredFns.find(f) != ignoredFns.end()) { + continue; + } + SourceLocation loc { decl->getBeginLoc() }; + TypeSourceInfo * tsi = decl->getTypeSourceInfo(); + if (tsi != nullptr) { + SourceLocation l { + compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getBeginLoc()) }; + SourceLocation end { + compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getEndLoc()) }; + assert(l.isFileID() && end.isFileID()); + if (l == end + || (compiler.getSourceManager() + .isBeforeInTranslationUnit(l, end))) + { + for (;;) { + unsigned n = Lexer::MeasureTokenLength( + l, compiler.getSourceManager(), + compiler.getLangOpts()); + std::string s { + compiler.getSourceManager().getCharacterData(l), + n }; + if (s == getName(fbk)) { + loc = l; + break; + } + if (l == end) { + break; + } + l = l.getLocWithOffset(std::max(n, 1)); + } + } + } + // Only rewrite declarations in include files if a + // definition is also seen, to avoid compilation of a + // definition (in a main file only processed later) to fail + // with a "mismatch" error before the rewriter had a chance + // to act upon the definition (but use the heuristic of + // assuming pure virtual functions do not have definitions); + // also, do not automatically rewrite functions that could + // implicitly override depend base functions (and thus stop + // doing so after the rewrite; note that this is less + // dangerous for return types than for parameter types, + // where the function would still implicitly override and + // cause a compilation error due to the incompatible return + // type): + OverrideKind k = getOverrideKind(f); + if (!((compiler.getSourceManager().isInMainFile( + compiler.getSourceManager().getSpellingLoc( + dyn_cast( + decl->getDeclContext()) + ->getNameInfo().getLoc())) + || f->isDefined() || f->isPure()) + && k != OverrideKind::MAYBE && rewrite(loc, fbk))) + { + report( + DiagnosticsEngine::Warning, + ("ParmVarDecl, use \"bool\" instead of" + " %0%1"), + loc) + << decl->getType().getNonReferenceType().getLocalUnqualifiedType() + << (k == OverrideKind::MAYBE + ? (" (unless this member function overrides a" + " dependent base member function, even" + " though it is not marked 'override')") + : "") + << decl->getSourceRange(); + } + } + for (auto const & dcl: functionDecls_) { + auto const decl = dcl.first; auto const fbk = dcl.second; + FunctionDecl const * f = decl->getCanonicalDecl(); + if (ignoredFns.find(f) != ignoredFns.end()) { + continue; + } + SourceLocation loc { decl->getBeginLoc() }; + SourceLocation l { compiler.getSourceManager().getExpansionLoc( + loc) }; + SourceLocation end { compiler.getSourceManager().getExpansionLoc( + decl->getNameInfo().getLoc()) }; + assert(l.isFileID() && end.isFileID()); + if (compiler.getSourceManager().isBeforeInTranslationUnit(l, end)) { + while (l != end) { + unsigned n = Lexer::MeasureTokenLength( + l, compiler.getSourceManager(), compiler.getLangOpts()); + std::string s { + compiler.getSourceManager().getCharacterData(l), n }; + if (s == getName(fbk)) { + loc = l; + break; + } + l = l.getLocWithOffset(std::max(n, 1)); + } + } + // Only rewrite declarations in include files if a definition is + // also seen, to avoid compilation of a definition (in a main file + // only processed later) to fail with a "mismatch" error before the + // rewriter had a chance to act upon the definition (but use the + // heuristic of assuming pure virtual functions do not have + // definitions): + if (!((compiler.getSourceManager().isInMainFile( + compiler.getSourceManager().getSpellingLoc( + decl->getNameInfo().getLoc())) + || f->isDefined() || f->isPure()) + && rewrite(loc, fbk))) + { + report( + DiagnosticsEngine::Warning, + "use \"bool\" instead of %0 as return type%1", + loc) + << decl->getReturnType().getNonReferenceType().getLocalUnqualifiedType() + << (getOverrideKind(f) == OverrideKind::MAYBE + ? (" (unless this member function overrides a dependent" + " base member function, even though it is not marked" + " 'override')") + : "") + << decl->getSourceRange(); + } + } + } +} + +bool FakeBool::VisitUnaryOperator(UnaryOperator * op) { + if (op->getOpcode() != UO_AddrOf) { + return FunctionAddress::VisitUnaryOperator(op); + } + FunctionAddress::VisitUnaryOperator(op); + Expr const * e1 = op->getSubExpr()->IgnoreParenCasts(); + if (isFakeBool(e1->getType()) != FBK_No) { + if (DeclRefExpr const * e2 = dyn_cast(e1)) { + if (auto const d = dyn_cast(e2->getDecl())) { + varDecls_.erase(d); + } else if (auto const d = dyn_cast(e2->getDecl())) { + fieldDecls_.erase(d); + } + } else if (auto const e3 = dyn_cast(e1)) { + if (auto const d = dyn_cast(e3->getMemberDecl())) { + fieldDecls_.erase(d); + } + } + } + return true; +} + +bool FakeBool::VisitCallExpr(CallExpr * expr) { + Decl const * d = expr->getCalleeDecl(); + FunctionProtoType const * ft = nullptr; + if (d != nullptr) { + FunctionDecl const * fd = dyn_cast(d); + if (fd != nullptr) { + if (!hasBoolOverload(fd, false)) { + clang::PointerType const * pt = fd->getType() + ->getAs(); + QualType t2( + pt == nullptr ? fd->getType() : pt->getPointeeType()); + ft = t2->getAs(); + assert( + ft != nullptr || !compiler.getLangOpts().CPlusPlus + || (fd->getBuiltinID() != Builtin::NotBuiltin + && isa(t2))); + // __builtin_*s have no proto type? + } + } else { + VarDecl const * vd = dyn_cast(d); + if (vd != nullptr) { + clang::PointerType const * pt = vd->getType() + ->getAs(); + ft = (pt == nullptr ? vd->getType() : pt->getPointeeType()) + ->getAs(); + } + } + } + if (ft != nullptr) { + for (unsigned i = 0; i != ft->getNumParams(); ++i) { + QualType t(ft->getParamType(i)); + bool b = false; + if (t->isLValueReferenceType()) { + t = t.getNonReferenceType(); + b = !t.isConstQualified() && isFakeBool(t) != FBK_No; + } else if (t->isPointerType()) { + for (;;) { + auto t2 = t->getAs(); + if (t2 == nullptr) { + break; + } + t = t2->getPointeeType(); + } + b = isFakeBool(t) != FBK_No; + } + if (b && i < expr->getNumArgs()) { + auto const e1 = expr->getArg(i)->IgnoreParenImpCasts(); + if (DeclRefExpr * ref = dyn_cast(e1)) { + VarDecl const * d = dyn_cast(ref->getDecl()); + if (d != nullptr) { + varDecls_.erase(d); + } + } else if (auto const e2 = dyn_cast(e1)) { + if (auto const d = dyn_cast(e2->getMemberDecl())) { + fieldDecls_.erase(d); + } + } + } + } + } + return true; +} + +bool FakeBool::VisitCStyleCastExpr(CStyleCastExpr * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto const k = isFakeBool(expr->getType()); + if (k != FBK_No) { + SourceLocation loc { expr->getBeginLoc() }; + while (compiler.getSourceManager().isMacroArgExpansion(loc)) { + loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc); + } + if (compiler.getSourceManager().isMacroBodyExpansion(loc)) { + StringRef name { Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()) }; + if (k == FBK_sal_Bool && (name == "sal_False" || name == "sal_True")) { + auto callLoc = compiler.getSourceManager() + .getImmediateMacroCallerLoc(loc); + if (!isSharedCAndCppCode(callLoc)) { + SourceLocation argLoc; + if (compiler.getSourceManager().isMacroArgExpansion( + expr->getBeginLoc(), &argLoc) + //TODO: check it's the complete (first) arg to the macro + && (Lexer::getImmediateMacroName( + argLoc, compiler.getSourceManager(), + compiler.getLangOpts()) + == "CPPUNIT_ASSERT_EQUAL")) + { + // Ignore sal_False/True that are directly used as + // arguments to CPPUNIT_ASSERT_EQUAL: + return true; + } + if (suppressWarningAt(callLoc)) { + return true; + } + bool b = k == FBK_sal_Bool && name == "sal_True"; + if (rewriter != nullptr) { + auto callSpellLoc = compiler.getSourceManager() + .getSpellingLoc(callLoc); + unsigned n = Lexer::MeasureTokenLength( + callSpellLoc, compiler.getSourceManager(), + compiler.getLangOpts()); + if (StringRef( + compiler.getSourceManager().getCharacterData( + callSpellLoc), + n) + == name) + { + return replaceText( + callSpellLoc, n, b ? "true" : "false"); + } + } + report( + DiagnosticsEngine::Warning, + "use '%select{false|true}0' instead of '%1'", callLoc) + << b << name << expr->getSourceRange(); + } + return true; + } + if (isSharedCAndCppCode(loc)) { + return true; + } + } + report( + DiagnosticsEngine::Warning, + "CStyleCastExpr, suspicious cast from %0 to %1", + expr->getBeginLoc()) + << expr->getSubExpr()->IgnoreParenImpCasts()->getType() + << expr->getType() << expr->getSourceRange(); + } + return true; +} + +bool FakeBool::VisitCXXStaticCastExpr(CXXStaticCastExpr * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (isFakeBool(expr->getType()) == FBK_No) { + return true; + } + if (suppressWarningAt(expr->getBeginLoc())) { + return true; + } + report( + DiagnosticsEngine::Warning, + "CXXStaticCastExpr, suspicious cast from %0 to %1", + expr->getBeginLoc()) + << expr->getSubExpr()->IgnoreParenImpCasts()->getType() + << expr->getType() << expr->getSourceRange(); + return true; +} + +bool FakeBool::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (isFakeBool(expr->getType()) != FBK_No) { + report( + DiagnosticsEngine::Warning, + "CXXFunctionalCastExpr, suspicious cast from %0 to %1", + expr->getBeginLoc()) + << expr->getSubExpr()->IgnoreParenImpCasts()->getType() + << expr->getType() << expr->getSourceRange(); + } + return true; +} + +bool FakeBool::VisitImplicitCastExpr(ImplicitCastExpr * expr) { + FunctionAddress::VisitImplicitCastExpr(expr); + if (ignoreLocation(expr)) { + return true; + } + if (isFakeBool(expr->getType()) == FBK_No) { + return true; + } + auto l = expr->getBeginLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(l)) { + l = compiler.getSourceManager().getImmediateMacroCallerLoc(l); + } + if (compiler.getSourceManager().isMacroBodyExpansion(l) && isSharedCAndCppCode(l)) { + return true; + } + auto e1 = expr->getSubExprAsWritten(); + auto t = e1->getType(); + if (!t->isFundamentalType() || loplugin::TypeCheck(t).AnyBoolean()) { + return true; + } + auto e2 = dyn_cast(e1); + if (e2 != nullptr) { + auto ic1 = dyn_cast( + e2->getTrueExpr()->IgnoreParens()); + auto ic2 = dyn_cast( + e2->getFalseExpr()->IgnoreParens()); + if (ic1 != nullptr && ic2 != nullptr + && ic1->getType()->isSpecificBuiltinType(BuiltinType::Int) + && (loplugin::TypeCheck(ic1->getSubExprAsWritten()->getType()) + .AnyBoolean()) + && ic2->getType()->isSpecificBuiltinType(BuiltinType::Int) + && (loplugin::TypeCheck(ic2->getSubExprAsWritten()->getType()) + .AnyBoolean())) + { + return true; + } + } + report( + DiagnosticsEngine::Warning, "conversion from %0 to %1", + expr->getBeginLoc()) + << t << expr->getType() << expr->getSourceRange(); + return true; +} + +bool FakeBool::VisitReturnStmt(ReturnStmt const * stmt) { + // Just enough to avoid warnings in rtl_getUriCharClass (sal/rtl/uri.cxx), + // which has + // + // static sal_Bool const aCharClass[][nCharClassSize] = ...; + // + // and + // + // return aCharClass[eCharClass]; + // + if (ignoreLocation(stmt)) { + return true; + } + auto e = stmt->getRetValue(); + if (e == nullptr) { + return true; + } + auto t = e->getType(); + if (!t->isPointerType()) { + return true; + } + for (;;) { + auto t2 = t->getAs(); + if (t2 == nullptr) { + break; + } + t = t2->getPointeeType(); + } + if (isFakeBool(t) != FBK_sal_Bool) { + return true; + } + auto e2 = dyn_cast(e->IgnoreParenImpCasts()); + if (e2 == nullptr) { + return true; + } + auto e3 = dyn_cast(e2->getBase()->IgnoreParenImpCasts()); + if (e3 == nullptr) { + return true; + } + auto d = dyn_cast(e3->getDecl()); + if (d == nullptr) { + return true; + } + varDecls_.erase(d); + return true; +} + +bool FakeBool::WalkUpFromParmVarDecl(ParmVarDecl const * decl) { + return VisitParmVarDecl(decl); +} + +bool FakeBool::VisitParmVarDecl(ParmVarDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + auto const fbk = isFakeBool(decl->getType().getNonReferenceType()); + if (fbk != FBK_No) { + FunctionDecl const * f = dyn_cast(decl->getDeclContext()); + if (f != nullptr) { // e.g.: typedef sal_Bool (* FuncPtr )( sal_Bool ); + f = f->getCanonicalDecl(); + if (handler.isAllRelevantCodeDefined(f) + && !(hasCLanguageLinkageType(f) + || (fbk == FBK_sal_Bool && isInUnoIncludeFile(f) + && (!f->isInlined() || f->hasAttr() + || decl->getType()->isReferenceType() + || hasBoolOverload(f, false))) + || f->isDeleted() || hasBoolOverload(f, true))) + { + OverrideKind k = getOverrideKind(f); + if (k != OverrideKind::YES) { + parmVarDecls_.insert({decl, fbk}); + } + } + } + } + return true; +} + +bool FakeBool::WalkUpFromVarDecl(VarDecl const * decl) { + return VisitVarDecl(decl); +} + +bool FakeBool::VisitVarDecl(VarDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + if (decl->isExternC()) { + return true; + } + auto k = isFakeBool(decl->getType()); + if (k == FBK_No) { + k = isFakeBoolArray(decl->getType()); + } + if (k == FBK_No) { + return true; + } + auto l = decl->getBeginLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(l)) { + l = compiler.getSourceManager().getImmediateMacroCallerLoc(l); + } + if (compiler.getSourceManager().isMacroBodyExpansion(l) + && isSharedCAndCppCode(l)) + { + return true; + } + varDecls_.insert({decl, k}); + return true; +} + +bool FakeBool::WalkUpFromFieldDecl(FieldDecl const * decl) { + return VisitFieldDecl(decl); +} + +bool FakeBool::VisitFieldDecl(FieldDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + auto k = isFakeBool(decl->getType()); + if (k == FBK_No) { + k = isFakeBoolArray(decl->getType()); + } + if (k == FBK_No) { + return true; + } + if (!handler.isAllRelevantCodeDefined(decl)) { + return true; + } + TagDecl const * td = dyn_cast(decl->getDeclContext()); + if (td == nullptr) { + //TODO: ObjCInterface + return true; + } + if (!(((td->isStruct() || td->isUnion()) && td->isExternCContext()) + || isInUnoIncludeFile( + compiler.getSourceManager().getSpellingLoc( + decl->getLocation())))) + { + fieldDecls_.insert({decl, k}); + } + return true; +} + +bool FakeBool::WalkUpFromFunctionDecl(FunctionDecl const * decl) { + return VisitFunctionDecl(decl); +} + +bool FakeBool::VisitFunctionDecl(FunctionDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + auto const fbk = isFakeBool(decl->getReturnType().getNonReferenceType()); + if (fbk != FBK_No + && !(decl->isDeletedAsWritten() && isa(decl)) + && handler.isAllRelevantCodeDefined(decl)) + { + FunctionDecl const * f = decl->getCanonicalDecl(); + OverrideKind k = getOverrideKind(f); + if (k != OverrideKind::YES + && !(hasCLanguageLinkageType(f) + || (isInUnoIncludeFile(f) + && (!f->isInlined() || f->hasAttr())))) + { + functionDecls_.insert({decl, fbk}); + } + } + return true; +} + +bool FakeBool::VisitValueDecl(ValueDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + auto const k = isFakeBool(decl->getType()); + if (k != FBK_No && !rewrite(decl->getBeginLoc(), k)) { + report( + DiagnosticsEngine::Warning, + "ValueDecl, use \"bool\" instead of %0", + decl->getBeginLoc()) + << decl->getType() << decl->getSourceRange(); + } + return true; +} + +bool FakeBool::TraverseLinkageSpecDecl(LinkageSpecDecl * decl) { + assert(externCContexts_ != std::numeric_limits::max()); //TODO + ++externCContexts_; + bool ret = RecursiveASTVisitor::TraverseLinkageSpecDecl(decl); + assert(externCContexts_ != 0); + --externCContexts_; + return ret; +} + +bool FakeBool::isFromCIncludeFile(SourceLocation spellingLocation) const { + return !compiler.getSourceManager().isInMainFile(spellingLocation) + && (StringRef( + compiler.getSourceManager().getPresumedLoc(spellingLocation) + .getFilename()) + .endswith(".h")); +} + +bool FakeBool::isSharedCAndCppCode(SourceLocation location) const { + // Assume that code is intended to be shared between C and C++ if it comes + // from an include file ending in .h, and is either in an extern "C" context + // or the body of a macro definition: + return + isFromCIncludeFile(compiler.getSourceManager().getSpellingLoc(location)) + && (externCContexts_ != 0 + || compiler.getSourceManager().isMacroBodyExpansion(location)); +} + +bool FakeBool::rewrite(SourceLocation location, FakeBoolKind kind) { + if (rewriter != nullptr) { + //TODO: "::sal_Bool" -> "bool", not "::bool" + SourceLocation loc { compiler.getSourceManager().getExpansionLoc( + location) }; + unsigned n = Lexer::MeasureTokenLength( + loc, compiler.getSourceManager(), compiler.getLangOpts()); + if (std::string(compiler.getSourceManager().getCharacterData(loc), n) + == getName(kind)) + { + return replaceText(loc, n, "bool"); + } + } + return false; +} + +loplugin::Plugin::Registration X("fakebool", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/finalclasses.cxx b/compilerplugins/clang/finalclasses.cxx new file mode 100644 index 000000000..e061bb7c5 --- /dev/null +++ b/compilerplugins/clang/finalclasses.cxx @@ -0,0 +1,162 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" +#include + +/** +Look for classes that are final i.e. nothing extends them, and have either +(a) protected fields or members. +or +(b) virtual members + +In the case of (a), those members/fields can be made private. +In the case of (b), making the class final means the compiler can devirtualise +some method calls + +The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='finalclasses' check + $ ./compilerplugins/clang/finalclasses.py + +*/ + +namespace { + +// try to limit the voluminous output a little +static std::set inheritedFromSet; +static std::map definitionMap; // className -> filename + +class FinalClasses: + public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit FinalClasses(loplugin::InstantiationData const & data): + Plugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + std::string output; + for (const std::string & s : inheritedFromSet) + output += "inherited-from:\t" + s + "\n"; + for (const auto & s : definitionMap) + output += "definition:\t" + s.first + "\t" + s.second + "\n"; + std::ofstream myfile; + myfile.open( WORKDIR "/loplugin.finalclasses.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + + bool shouldVisitTemplateInstantiations () const { return true; } + + bool shouldVisitImplicitCode() const { return true; } + + bool VisitCXXRecordDecl( const CXXRecordDecl* decl); +private: + void checkBase(QualType qt); +}; + +bool ignoreClass(StringRef s) +{ + // ignore stuff in the standard library, and UNO stuff we can't touch. + if (s.startswith("rtl::") || s.startswith("sal::") || s.startswith("com::sun::") + || s.startswith("std::") || s.startswith("boost::") + || s == "OString" || s == "OUString" || s == "bad_alloc") + { + return true; + } + return false; +} + +bool FinalClasses::VisitCXXRecordDecl(const CXXRecordDecl* decl) +{ + if (ignoreLocation(decl)) + return true; + if (!decl->hasDefinition()) + return true; + + for (auto it = decl->bases_begin(); it != decl->bases_end(); ++it) + { + const CXXBaseSpecifier spec = *it; + checkBase(spec.getType()); + } + for (auto it = decl->vbases_begin(); it != decl->vbases_end(); ++it) + { + const CXXBaseSpecifier spec = *it; + checkBase(spec.getType()); + } + + if (decl->hasAttr()) + return true; + bool bFoundVirtual = false; + bool bFoundProtected = false; + for (auto it = decl->method_begin(); it != decl->method_end(); ++it) { + auto i = *it; + // ignore methods that are overriding base-class methods, making them private + // isn't useful + if ( !i->hasAttr() && i->getAccess() == AS_protected ) + bFoundProtected = true; + if ( i->isVirtual() ) + bFoundVirtual = true; + } + + if (!bFoundProtected) + { + for (auto it = decl->field_begin(); it != decl->field_end(); ++it) { + auto i = *it; + if ( i->getAccess() == AS_protected ) { + bFoundProtected = true; + break; + } + } + } + if (!bFoundProtected && !bFoundVirtual) + return true; + + std::string s = decl->getQualifiedNameAsString(); + if (ignoreClass(s)) + return true; + + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(decl->getBeginLoc()); + auto const filename = getFilenameOfLocation(spellingLocation); + auto sourceLocation = filename.substr(strlen(SRCDIR)).str() + ":" + + std::to_string(compiler.getSourceManager().getSpellingLineNumber(spellingLocation)); + definitionMap.insert( std::pair(s, sourceLocation) ); + return true; +} + +void FinalClasses::checkBase(QualType baseType) +{ + // need to look through typedefs, hence the getUnqualifiedDesugaredType + baseType = baseType.getDesugaredType(compiler.getASTContext()); + std::string x; + // so that we get just the template name, excluding the template parameters + if (baseType->isRecordType()) + x = baseType->getAsCXXRecordDecl()->getQualifiedNameAsString(); + else if (auto templateType = baseType->getAs()) + x = templateType->getTemplateName().getAsTemplateDecl()->getQualifiedNameAsString(); + else + x = baseType.getAsString(); + inheritedFromSet.insert( x ); +} + +loplugin::Plugin::Registration< FinalClasses > X("finalclasses", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/finalclasses.py b/compilerplugins/clang/finalclasses.py new file mode 100755 index 000000000..05a1d0c43 --- /dev/null +++ b/compilerplugins/clang/finalclasses.py @@ -0,0 +1,81 @@ +#!/usr/bin/python3 + +import re +import sys + +definitionSet = set() +inheritFromSet = set() +definitionToFileDict = {} + +with open("workdir/loplugin.finalclasses.log") as txt: + for line in txt: + tokens = line.strip().split("\t") + + if len(tokens) == 1: + pass + + elif tokens[0] == "definition:": + clazzName = tokens[1] + # the 1.. is so we skip the leading / + fileName = tokens[2][1:] + definitionSet.add(clazzName) + definitionToFileDict[clazzName] = fileName + + elif tokens[0] == "inherited-from:": + parent = tokens[1] + if (parent.startswith("class ")): + parent = parent[6:] + elif (parent.startswith("struct ")): + parent = parent[7:] + inheritFromSet.add(parent); + + else: + print( "unknown line: " + line) + +match_module_inc1 = re.compile(r'^\w+/inc/') +match_module_inc2 = re.compile(r'^\w+/.*/inc/') +tmpset = set() +for clazz in sorted(definitionSet - inheritFromSet): + file = definitionToFileDict[clazz] + # ignore classes defined inside compilation units, the compiler knows they are final already + if (".cxx" in file): continue + # ignore test and external code + if ("/qa/" in file): continue + if (file.startswith("workdir/")): continue + # We are only really interested in classes that are shared between linkage units, where the compiler + # is not able to figure out for itself that classes are final. + if not(file.startswith("include/") or match_module_inc1.match(file) or match_module_inc2.match(file)): continue + #if not(file.endswith(".hxx")): continue + # Exclude URE + if file.startswith("include/com/"): continue + if file.startswith("include/cppu/"): continue + if file.startswith("include/cppuhelper/"): continue + if file.startswith("include/osl/"): continue + if file.startswith("include/rtl/"): continue + if file.startswith("include/sal/"): continue + if file.startswith("include/salhelper/"): continue + if file.startswith("include/typelib/"): continue + if file.startswith("include/uno/"): continue + # some kind of template noise + if file.startswith("include/unotest/"): continue + # no point optimising test code + if file.startswith("include/test/"): continue + tmpset.add((clazz, file)) + +# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[1]) + [v[0]] +def sort_set_by_natural_key(s): + return sorted(s, key=lambda v: v_sort_key(v)) + +# print output, sorted by name and line number +with open("compilerplugins/clang/finalclasses.results", "wt") as f: + for t in sort_set_by_natural_key(tmpset): + f.write(t[1] + "\n") + f.write(" " + t[0] + "\n") + diff --git a/compilerplugins/clang/flatten.cxx b/compilerplugins/clang/flatten.cxx new file mode 100644 index 000000000..8d7eac9d9 --- /dev/null +++ b/compilerplugins/clang/flatten.cxx @@ -0,0 +1,687 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "plugin.hxx" +#include +#include +#include +#include +#include +#include + +/** + Look for places where we can flatten the control flow in a method by returning early. + */ +namespace { + +class Flatten: + public loplugin::FilteringRewritePlugin +{ +public: + explicit Flatten(loplugin::InstantiationData const & data): + FilteringRewritePlugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool TraverseIfStmt(IfStmt *); + bool TraverseCXXCatchStmt(CXXCatchStmt * ); + bool TraverseCompoundStmt(CompoundStmt *); + bool TraverseFunctionDecl(FunctionDecl *); + bool TraverseCXXMethodDecl(CXXMethodDecl *); + bool TraverseCXXConstructorDecl(CXXConstructorDecl *); + bool TraverseCXXConversionDecl(CXXConversionDecl *); + bool TraverseCXXDestructorDecl(CXXDestructorDecl *); + bool VisitIfStmt(IfStmt const * ); +private: + bool rewrite1(IfStmt const * ); + bool rewrite2(IfStmt const * ); + bool rewriteLargeIf(IfStmt const * ); + SourceRange ignoreMacroExpansions(SourceRange range); + SourceRange extendOverComments(SourceRange range); + std::string getSourceAsString(SourceRange range); + llvm::Optional invertCondition(Expr const * condExpr, SourceRange conditionRange); + bool isLargeCompoundStmt(Stmt const *); + + Stmt const * lastStmtInCompoundStmt = nullptr; + FunctionDecl const * functionDecl = nullptr; + CompoundStmt const * functionDeclBody = nullptr; + Stmt const * mElseBranch = nullptr; +}; + +static Stmt const * containsSingleThrowExpr(Stmt const * stmt) +{ + if (auto compoundStmt = dyn_cast(stmt)) { + if (compoundStmt->size() != 1) + return nullptr; + stmt = *compoundStmt->body_begin(); + } + if (auto exprWithCleanups = dyn_cast(stmt)) { + stmt = exprWithCleanups->getSubExpr(); + } + return dyn_cast(stmt); +} + +static bool containsVarDecl(Stmt const * stmt) +{ + if (auto compoundStmt = dyn_cast(stmt)) { + for (auto i = compoundStmt->body_begin(); i != compoundStmt->body_end(); ++i) { + auto declStmt = dyn_cast(*i); + if (declStmt && isa(*declStmt->decl_begin())) + return true; + } + return false; + } + auto declStmt = dyn_cast(stmt); + return declStmt && isa(*declStmt->decl_begin()); +} + +bool Flatten::TraverseCXXCatchStmt(CXXCatchStmt* ) +{ + // ignore stuff inside catch statements, where doing a "if...else..throw" is more natural + return true; +} + +bool Flatten::TraverseIfStmt(IfStmt * ifStmt) +{ + if (!WalkUpFromIfStmt(ifStmt)) { + return false; + } + auto const saved = mElseBranch; + mElseBranch = ifStmt->getElse(); + auto ret = true; + for (auto const sub: ifStmt->children()) { + if (!TraverseStmt(sub)) { + ret = false; + break; + } + } + mElseBranch = saved; + return ret; +} + +bool Flatten::TraverseCompoundStmt(CompoundStmt * compoundStmt) +{ + auto copy = lastStmtInCompoundStmt; + if (compoundStmt->size() > 0) + lastStmtInCompoundStmt = compoundStmt->body_back(); + else + lastStmtInCompoundStmt = nullptr; + + bool rv = RecursiveASTVisitor::TraverseCompoundStmt(compoundStmt); + + lastStmtInCompoundStmt = copy; + return rv; +} + +bool Flatten::TraverseFunctionDecl(FunctionDecl * fd) +{ + auto copy1 = functionDeclBody; + auto copy2 = fd; + functionDeclBody = dyn_cast_or_null(fd->getBody()); + functionDecl = fd; + bool rv = RecursiveASTVisitor::TraverseFunctionDecl(fd); + functionDeclBody = copy1; + functionDecl = copy2; + return rv; +} + +bool Flatten::TraverseCXXMethodDecl(CXXMethodDecl * fd) +{ + auto copy1 = functionDeclBody; + auto copy2 = fd; + functionDeclBody = dyn_cast_or_null(fd->getBody()); + functionDecl = fd; + bool rv = RecursiveASTVisitor::TraverseCXXMethodDecl(fd); + functionDeclBody = copy1; + functionDecl = copy2; + return rv; +} + +bool Flatten::TraverseCXXConstructorDecl(CXXConstructorDecl * fd) +{ + auto copy1 = functionDeclBody; + auto copy2 = fd; + functionDeclBody = dyn_cast_or_null(fd->getBody()); + functionDecl = fd; + bool rv = RecursiveASTVisitor::TraverseCXXConstructorDecl(fd); + functionDeclBody = copy1; + functionDecl = copy2; + return rv; +} + +bool Flatten::TraverseCXXConversionDecl(CXXConversionDecl * fd) +{ + auto copy1 = functionDeclBody; + auto copy2 = fd; + functionDeclBody = dyn_cast_or_null(fd->getBody()); + functionDecl = fd; + bool rv = RecursiveASTVisitor::TraverseCXXConversionDecl(fd); + functionDeclBody = copy1; + functionDecl = copy2; + return rv; +} + +bool Flatten::TraverseCXXDestructorDecl(CXXDestructorDecl * fd) +{ + auto copy1 = functionDeclBody; + auto copy2 = fd; + functionDeclBody = dyn_cast_or_null(fd->getBody()); + functionDecl = fd; + bool rv = RecursiveASTVisitor::TraverseCXXDestructorDecl(fd); + functionDeclBody = copy1; + functionDecl = copy2; + return rv; +} + + +bool Flatten::VisitIfStmt(IfStmt const * ifStmt) +{ + if (ignoreLocation(ifStmt)) + return true; + + // ignore if we are part of an if/then/else/if chain + if (ifStmt == mElseBranch || (ifStmt->getElse() && isa(ifStmt->getElse()))) + return true; + + // look for a large if(){} block at the end of a function + if (!ifStmt->getElse() + && (functionDecl->getReturnType().isNull() || functionDecl->getReturnType()->isVoidType()) + && functionDeclBody && functionDeclBody->size() + && functionDeclBody->body_back() == ifStmt + && isLargeCompoundStmt(ifStmt->getThen())) + { + if (!rewriteLargeIf(ifStmt)) + { + report( + DiagnosticsEngine::Warning, + "large if statement at end of function, rather invert the condition and exit early, and flatten the function", + ifStmt->getBeginLoc()) + << ifStmt->getSourceRange(); + } + return true; + } + + if (!ifStmt->getElse()) + return true; + + auto const thenThrowExpr = containsSingleThrowExpr(ifStmt->getThen()); + auto const elseThrowExpr = containsSingleThrowExpr(ifStmt->getElse()); + // If neither contains a throw, nothing to do; if both contain throws, no + // improvement: + if ((thenThrowExpr == nullptr) == (elseThrowExpr == nullptr)) { + return true; + } + + if (containsPreprocessingConditionalInclusion(ifStmt->getSourceRange())) { + return true; + } + + if (elseThrowExpr) + { + // if the "if" statement is not the last statement in its block, and it contains + // var decls in its then block, we cannot de-indent the then block without + // extending the lifetime of some variables, which may be problematic + if (ifStmt != lastStmtInCompoundStmt && containsVarDecl(ifStmt->getThen())) + return true; + + if (!rewrite1(ifStmt)) + { + report( + DiagnosticsEngine::Warning, + "unconditional throw in else branch, rather invert the condition, throw early, and flatten the normal case", + elseThrowExpr->getBeginLoc()) + << elseThrowExpr->getSourceRange(); + report( + DiagnosticsEngine::Note, + "if condition here", + ifStmt->getBeginLoc()) + << ifStmt->getSourceRange(); + } + } + if (thenThrowExpr) + { + // if the "if" statement is not the last statement in its block, and it contains + // var decls in its else block, we cannot de-indent the else block without + // extending the lifetime of some variables, which may be problematic + if (ifStmt != lastStmtInCompoundStmt && containsVarDecl(ifStmt->getElse())) + return true; + + if (!rewrite2(ifStmt)) + { + report( + DiagnosticsEngine::Warning, + "unconditional throw in then branch, just flatten the else", + thenThrowExpr->getBeginLoc()) + << thenThrowExpr->getSourceRange(); + } + } + return true; +} + +static std::string stripOpenAndCloseBrace(std::string s); +static std::string stripTrailingEmptyLines(std::string s); +static std::string deindent(std::string const & s); +static std::vector split(std::string s); +static bool startswith(std::string const & rStr, char const * pSubStr); +static int countLeadingSpaces(std::string const &); +static std::string padSpace(int iNoSpaces); +static bool replace(std::string & s, std::string const & from, std::string const & to); + +bool Flatten::rewrite1(IfStmt const * ifStmt) +{ + if (!rewriter) + return false; + + auto conditionRange = ignoreMacroExpansions(ifStmt->getCond()->getSourceRange()); + if (!conditionRange.isValid()) { + return false; + } + auto thenRange = ignoreMacroExpansions(ifStmt->getThen()->getSourceRange()); + if (!thenRange.isValid()) { + return false; + } + auto elseRange = ignoreMacroExpansions(ifStmt->getElse()->getSourceRange()); + if (!elseRange.isValid()) { + return false; + } + SourceRange elseKeywordRange = ifStmt->getElseLoc(); + + thenRange = extendOverComments(thenRange); + elseRange = extendOverComments(elseRange); + elseKeywordRange = extendOverComments(elseKeywordRange); + + // in adjusting the formatting I assume that "{" starts on a new line + + llvm::Optional conditionString = invertCondition(ifStmt->getCond(), conditionRange); + if (!conditionString) + return false; + + std::string thenString = getSourceAsString(thenRange); + if (auto compoundStmt = dyn_cast(ifStmt->getThen())) { + if (compoundStmt->getLBracLoc().isValid()) { + thenString = stripOpenAndCloseBrace(thenString); + } + } + thenString = deindent(thenString); + + std::string elseString = getSourceAsString(elseRange); + + if (!replaceText(elseRange, thenString)) { + return false; + } + if (!removeText(elseKeywordRange)) { + return false; + } + if (!replaceText(thenRange, elseString)) { + return false; + } + if (!replaceText(conditionRange, *conditionString)) { + return false; + } + + return true; +} + +bool Flatten::rewrite2(IfStmt const * ifStmt) +{ + if (!rewriter) + return false; + + auto conditionRange = ignoreMacroExpansions(ifStmt->getCond()->getSourceRange()); + if (!conditionRange.isValid()) { + return false; + } + auto thenRange = ignoreMacroExpansions(ifStmt->getThen()->getSourceRange()); + if (!thenRange.isValid()) { + return false; + } + auto elseRange = ignoreMacroExpansions(ifStmt->getElse()->getSourceRange()); + if (!elseRange.isValid()) { + return false; + } + SourceRange elseKeywordRange = ifStmt->getElseLoc(); + + elseRange = extendOverComments(elseRange); + elseKeywordRange = extendOverComments(elseKeywordRange); + + // in adjusting the formatting I assume that "{" starts on a new line + + std::string elseString = getSourceAsString(elseRange); + if (auto compoundStmt = dyn_cast(ifStmt->getElse())) { + if (compoundStmt->getLBracLoc().isValid()) { + elseString = stripOpenAndCloseBrace(elseString); + } + } + elseString = deindent(elseString); + + if (!replaceText(elseRange, elseString)) { + return false; + } + if (!removeText(elseKeywordRange)) { + return false; + } + + return true; +} + +bool Flatten::rewriteLargeIf(IfStmt const * ifStmt) +{ + if (!rewriter) + return false; + + auto conditionRange = ignoreMacroExpansions(ifStmt->getCond()->getSourceRange()); + if (!conditionRange.isValid()) { + return false; + } + auto thenRange = ignoreMacroExpansions(ifStmt->getThen()->getSourceRange()); + if (!thenRange.isValid()) { + return false; + } + + thenRange = extendOverComments(thenRange); + + // in adjusting the formatting I assume that "{" starts on a new line + + llvm::Optional conditionString = invertCondition(ifStmt->getCond(), conditionRange); + if (!conditionString) + return false; + + std::string thenString = getSourceAsString(thenRange); + if (auto compoundStmt = dyn_cast(ifStmt->getThen())) { + if (compoundStmt->getLBracLoc().isValid()) { + thenString = stripOpenAndCloseBrace(thenString); + } + } + int iNoSpaces = countLeadingSpaces(thenString); + thenString = padSpace(iNoSpaces) + "return;\n\n" + deindent(thenString); + thenString = stripTrailingEmptyLines(thenString); + + if (!replaceText(thenRange, thenString)) { + return false; + } + if (!replaceText(conditionRange, *conditionString)) { + return false; + } + + return true; +} + +llvm::Optional Flatten::invertCondition(Expr const * condExpr, SourceRange conditionRange) +{ + std::string s = getSourceAsString(conditionRange); + + condExpr = condExpr->IgnoreImpCasts(); + + if (auto exprWithCleanups = dyn_cast(condExpr)) + condExpr = exprWithCleanups->getSubExpr()->IgnoreImpCasts(); + + // an if statement will automatically invoke a bool-conversion method + if (auto memberCallExpr = dyn_cast(condExpr)) + { + if (memberCallExpr->getMethodDecl() && isa(memberCallExpr->getMethodDecl())) + condExpr = memberCallExpr->getImplicitObjectArgument()->IgnoreImpCasts(); + } + + if (auto unaryOp = dyn_cast(condExpr)) + { + if (unaryOp->getOpcode() != UO_LNot) + return "!(" + s + ")"; + auto i = s.find("!"); + assert (i != std::string::npos); + s = s.substr(i+1); + } + else if (auto binaryOp = dyn_cast(condExpr)) + { + bool ok = true; + switch (binaryOp->getOpcode()) + { + case BO_LT: ok = replace(s, "<", ">="); break; + case BO_GT: ok = replace(s, ">", "<="); break; + case BO_LE: ok = replace(s, "<=", ">"); break; + case BO_GE: ok = replace(s, ">=", "<"); break; + case BO_EQ: ok = replace(s, "==", "!="); break; + case BO_NE: ok = replace(s, "!=", "=="); break; + default: + s = "!(" + s + ")"; + } + if (!ok) + return llvm::Optional(); + } + else if (auto opCallExpr = dyn_cast(condExpr)) + { + bool ok = true; + switch (opCallExpr->getOperator()) + { + case OO_Less: ok = replace(s, "<", ">="); break; + case OO_Greater: ok = replace(s, ">", "<="); break; + case OO_LessEqual: ok = replace(s, "<=", ">"); break; + case OO_GreaterEqual: ok = replace(s, ">=", "<"); break; + case OO_EqualEqual: ok = replace(s, "==", "!="); break; + case OO_ExclaimEqual: ok = replace(s, "!=", "=="); break; + default: + s = "!(" + s + ")"; + } + if (!ok) + return llvm::Optional(); + } + else if (isa(condExpr) || isa(condExpr) || isa(condExpr)) + s = "!" + s; + else + s = "!(" + s + ")"; + return s; +} + +std::string stripOpenAndCloseBrace(std::string s) +{ + size_t i = s.find("{"); + if (i == std::string::npos) + { + assert( !"did not find {" ); + abort(); + } + + ++i; + // strip to line end + while (s[i] == ' ') + ++i; + if (s[i] == '\n') + ++i; + s = s.substr(i); + + i = s.rfind("}"); + if (i == std::string::npos) + { + assert( !"did not find }" ); + abort(); + } + --i; + while (s[i] == ' ') + --i; + s = s.substr(0,i); + return s; +} + +std::string deindent(std::string const & s) +{ + std::vector lines = split(s); + std::string rv; + for (auto s : lines) { + if (startswith(s, " ")) + rv += s.substr(4); + else + rv += s; + rv += "\n"; + } + return rv; +} + +std::vector split(std::string s) +{ + if (s.back() == '\n') + s = s.substr(0, s.size()-1); + size_t next = -1; + std::vector rv; + do + { + size_t current = next + 1; + next = s.find_first_of( "\n", current ); + rv.push_back(s.substr( current, next - current )); + } + while (next != std::string::npos); + return rv; +} + +bool startswith(std::string const & rStr, char const * pSubStr) +{ + return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; +} + +int countLeadingSpaces(std::string const & s) +{ + int i = 0; + while (i < (int)s.length() && s[i] == ' ') + i++; + return i; +} + +std::string padSpace(int iNoSpaces) +{ + std::string s; + for (int i = 0; i < iNoSpaces; ++i) + s += " "; + return s; +} + +std::string stripTrailingEmptyLines(std::string s) +{ + while (s.back() == '\n') + s.resize(s.length() - 1); + return s; +} + +bool replace(std::string & s, std::string const & from, std::string const & to) +{ + auto i = s.find(from); + assert (i != std::string::npos); + s.replace(i, from.length(), to); + // just in case we have something really weird, like the operator token is also present in the rest of the condition somehow + return s.find(from) == std::string::npos; +} + +SourceRange Flatten::ignoreMacroExpansions(SourceRange range) { + while (compiler.getSourceManager().isMacroArgExpansion(range.getBegin())) { + range.setBegin( + compiler.getSourceManager().getImmediateMacroCallerLoc( + range.getBegin())); + } + if (range.getBegin().isMacroID()) { + SourceLocation loc; + if (Lexer::isAtStartOfMacroExpansion( + range.getBegin(), compiler.getSourceManager(), + compiler.getLangOpts(), &loc)) + { + range.setBegin(loc); + } + } + while (compiler.getSourceManager().isMacroArgExpansion(range.getEnd())) { + range.setEnd( + compiler.getSourceManager().getImmediateMacroCallerLoc( + range.getEnd())); + } + if (range.getEnd().isMacroID()) { + SourceLocation loc; + if (Lexer::isAtEndOfMacroExpansion( + range.getEnd(), compiler.getSourceManager(), + compiler.getLangOpts(), &loc)) + { + range.setEnd(loc); + } + } + return range.getBegin().isMacroID() || range.getEnd().isMacroID() + ? SourceRange() : range; +} + +/** + * Extend the SourceRange to include any leading and trailing whitespace, and any comments. + */ +SourceRange Flatten::extendOverComments(SourceRange range) +{ + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = range.getBegin(); + SourceLocation endLoc = range.getEnd(); + char const *p1 = SM.getCharacterData( startLoc ); + char const *p2 = SM.getCharacterData( endLoc ); + + // scan backwards from the beginning to include any spaces on that line + while (*(p1-1) == ' ') + --p1; + startLoc = startLoc.getLocWithOffset(p1 - SM.getCharacterData( startLoc )); + + // look for trailing ";" + while (*(p2+1) == ';') + ++p2; + // look for trailing " " + while (*(p2+1) == ' ') + ++p2; + // look for single line comments attached to the end of the statement + if (*(p2+1) == '/' && *(p2+2) == '/') + { + p2 += 2; + while (*(p2+1) && *(p2+1) != '\n') + ++p2; + if (*(p2+1) == '\n') + ++p2; + } + else + { + // make the source code we extract include any trailing "\n" + if (*(p2+1) == '\n') + ++p2; + } + endLoc = endLoc.getLocWithOffset(p2 - SM.getCharacterData( endLoc )); + + return SourceRange(startLoc, endLoc); +} + +std::string Flatten::getSourceAsString(SourceRange range) +{ + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = range.getBegin(); + SourceLocation endLoc = range.getEnd(); + char const *p1 = SM.getCharacterData( startLoc ); + char const *p2 = SM.getCharacterData( endLoc ); + p2 += Lexer::MeasureTokenLength( endLoc, SM, compiler.getLangOpts()); + if (p2 < p1) { + // workaround clang weirdness, but don't return empty string + // in case it happens during code replacement + return "clang returned bad pointers"; + } + if (p2 - p1 > 64 * 1024) { + // workaround clang weirdness, but don't return empty string + // in case it happens during code replacement + return "clang returned overlay large source range"; + } + return std::string( p1, p2 - p1); +} + +bool Flatten::isLargeCompoundStmt(Stmt const * stmt) +{ + auto stmtRange = stmt->getSourceRange(); + std::string s = getSourceAsString(stmtRange); + return std::count(s.begin(), s.end(), '\n') > 10; +} + +loplugin::Plugin::Registration< Flatten > X("flatten", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/fragiledestructor.cxx b/compilerplugins/clang/fragiledestructor.cxx new file mode 100644 index 000000000..f8ec76a56 --- /dev/null +++ b/compilerplugins/clang/fragiledestructor.cxx @@ -0,0 +1,147 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include + +#include "plugin.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" + + +// Check for calls to virtual methods from destructors. These are dangerous because intention might be to call +// a method on a subclass, while in actual fact, it only calls the method on the current or super class. +// + +namespace { + +class FragileDestructor: + public loplugin::FilteringPlugin +{ +public: + explicit FragileDestructor(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual bool preRun() override + { + StringRef fn(handler.getMainFileName()); + + // TODO, these all need fixing + + if (loplugin::isSamePathname(fn, SRCDIR "/comphelper/source/misc/proxyaggregation.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/svdraw/svdpntv.cxx")) // ~SdrPaintView calling ClearPageView + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/svdraw/svdobj.cxx")) // ~SdrObject calling GetLastBoundRect + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/svdraw/svdedxv.cxx")) // ~SdrObjEditView calling SdrEndTextEdit + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/connectivity/source/drivers/file/FStatement.cxx")) // ~OStatement_Base calling disposing + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/core/CustomAnimationEffect.cxx")) // ~EffectSequenceHelper calling reset + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/view/sdview.cxx")) // ~View calling DeleteWindowFromPaintView + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/layout/ssfrm.cxx")) // ~SwFrame calling IsDeleteForbidden + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/chart2/source/model/template/CandleStickChartType.cxx")) // to ignore "[10/11/12 Regression] using declaration causing virtual call with wrongly adjusted this pointer" workaround + return false; + + return true; + } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool PreTraverseCXXDestructorDecl(CXXDestructorDecl*); + bool PostTraverseCXXDestructorDecl(CXXDestructorDecl*, bool); + bool TraverseCXXDestructorDecl(CXXDestructorDecl*); + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *); + +private: + std::vector m_vDestructors; +}; + +bool FragileDestructor::PreTraverseCXXDestructorDecl(CXXDestructorDecl* cxxDestructorDecl) +{ + if (ignoreLocation(cxxDestructorDecl)) + return true; + if (!cxxDestructorDecl->isThisDeclarationADefinition()) + return true; + if (cxxDestructorDecl->getParent()->hasAttr()) + return true; + m_vDestructors.push_back(cxxDestructorDecl); + return true; +} + +bool FragileDestructor::PostTraverseCXXDestructorDecl(CXXDestructorDecl* cxxDestructorDecl, bool) +{ + if (!m_vDestructors.empty() && m_vDestructors.back() == cxxDestructorDecl) + m_vDestructors.pop_back(); + return true; +} + +bool FragileDestructor::TraverseCXXDestructorDecl(CXXDestructorDecl* cxxDestructorDecl) +{ + PreTraverseCXXDestructorDecl(cxxDestructorDecl); + auto ret = FilteringPlugin::TraverseCXXDestructorDecl(cxxDestructorDecl); + PostTraverseCXXDestructorDecl(cxxDestructorDecl, ret); + return ret; +} + +bool FragileDestructor::VisitCXXMemberCallExpr(const CXXMemberCallExpr* callExpr) +{ + if (m_vDestructors.empty() || ignoreLocation(callExpr)) + return true; + const CXXMethodDecl* methodDecl = callExpr->getMethodDecl(); + if (!methodDecl->isVirtual() || methodDecl->hasAttr()) + return true; + const CXXRecordDecl* parentRecordDecl = methodDecl->getParent(); + if (parentRecordDecl->hasAttr()) + return true; + if (!callExpr->getImplicitObjectArgument()->IgnoreImpCasts()->isImplicitCXXThis()) + return true; + + // if we see an explicit call to its own method, that's OK + auto s1 = compiler.getSourceManager().getCharacterData(callExpr->getBeginLoc()); + auto s2 = compiler.getSourceManager().getCharacterData(callExpr->getEndLoc()); + std::string tok(s1, s2-s1); + if (tok.find("::") != std::string::npos) + return true; + + // Very common pattern that we call acquire/dispose in destructors of UNO objects + // to make sure they are cleaned up. + if (methodDecl->getName() == "acquire" || methodDecl->getName() == "dispose") + return true; + + report( + DiagnosticsEngine::Warning, + "calling virtual method from destructor, either make the virtual method final, or make this class final", + callExpr->getBeginLoc()) + << callExpr->getSourceRange(); + report( + DiagnosticsEngine::Note, + "callee method here", + methodDecl->getBeginLoc()) + << methodDecl->getSourceRange(); + return true; +} + + +loplugin::Plugin::Registration fragiledestructor("fragiledestructor"); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/functionaddress.hxx b/compilerplugins/clang/functionaddress.hxx new file mode 100644 index 000000000..d2bf19e14 --- /dev/null +++ b/compilerplugins/clang/functionaddress.hxx @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include "plugin.hxx" + +/** + * Common code for checking if the address of a function was taken. + */ +namespace loplugin { + +template +class FunctionAddress : public Base +{ +public: + explicit FunctionAddress( const InstantiationData& data ) : Base(data) {} + + bool TraverseCallExpr(CallExpr * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = Base::TraverseCallExpr(expr); + callee_ = saved; + return ret; + } + + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = Base::TraverseCXXOperatorCallExpr(expr); + callee_ = saved; + return ret; + } + + bool TraverseCXXMemberCallExpr(CXXMemberCallExpr * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = Base::TraverseCXXMemberCallExpr(expr); + callee_ = saved; + return ret; + } + + bool TraverseCUDAKernelCallExpr(CUDAKernelCallExpr * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = Base::TraverseCUDAKernelCallExpr(expr); + callee_ = saved; + return ret; + } + + bool TraverseUserDefinedLiteral(UserDefinedLiteral * expr) { + auto const saved = callee_; + callee_ = expr->getCallee(); + auto const ret = Base::TraverseUserDefinedLiteral(expr); + callee_ = saved; + return ret; + } + + bool VisitImplicitCastExpr(ImplicitCastExpr const * expr) { + if (expr == callee_) { + return true; + } + if (this->ignoreLocation(expr)) { + return true; + } + if (expr->getCastKind() != CK_FunctionToPointerDecay) { + return true; + } + auto const dre = dyn_cast( + expr->getSubExpr()->IgnoreParens()); + if (dre == nullptr) { + return true; + } + auto const fd = dyn_cast(dre->getDecl()); + if (fd == nullptr) { + return true; + } + ignoredFunctions_.insert(fd->getCanonicalDecl()); + return true; + } + + bool VisitUnaryOperator(UnaryOperator * expr) { + if (expr->getOpcode() != UO_AddrOf) { + return Base::VisitUnaryOperator(expr); + } + if (this->ignoreLocation(expr)) { + return true; + } + auto const dre = dyn_cast( + expr->getSubExpr()->IgnoreParenImpCasts()); + if (dre == nullptr) { + return true; + } + auto const fd = dyn_cast(dre->getDecl()); + if (fd == nullptr) { + return true; + } + ignoredFunctions_.insert(fd->getCanonicalDecl()); + return true; + } + +protected: + std::unordered_set const & getFunctionsWithAddressTaken() { return ignoredFunctions_; } + +private: + std::unordered_set ignoredFunctions_; + Expr const * callee_ = nullptr; +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/getimplementationname.cxx b/compilerplugins/clang/getimplementationname.cxx new file mode 100644 index 000000000..acc45acb7 --- /dev/null +++ b/compilerplugins/clang/getimplementationname.cxx @@ -0,0 +1,313 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// only compile this on unixy system +// as we don't want to bother with x-platform system()/mkdir() +#if defined(__unix__) +// only compile this on clang 3.7 or higher, which is known to work +// there were problems on clang 3.5 at least +#include "config_clang.h" +#include +#include +#include +#include +#include +#include +#include "check.hxx" +#include "plugin.hxx" +#include "clang/Frontend/CompilerInstance.h" + +namespace { + +clang::Expr const * ignoreParenImplicitComma(clang::Expr const * expr) { + for (;;) { + auto const e1 = expr->IgnoreParens()->IgnoreImplicit(); + if (e1 != expr) { + expr = e1; + continue; + } + // auto const e1 = dyn_cast(expr); + // if (e1 != nullptr) { + // expr = e1->getSubExpr(); + // continue; + // } + auto const e2 = dyn_cast(expr); + if (e2 != nullptr && e2->getOpcode() == clang::BO_Comma) { + expr = e2->getRHS(); + continue; + } + return expr; + } +} + +bool overridesXServiceInfo(clang::CXXMethodDecl const * decl) { + for (auto i = decl->begin_overridden_methods(); + i != decl->end_overridden_methods(); ++i) + { + if (((*i)->getParent()->getQualifiedNameAsString() + == "com::sun::star::lang::XServiceInfo") + || overridesXServiceInfo(*i)) + { + return true; + } + } + return false; +} + +std::string replace_all(std::string subject, const std::string& search, const std::string& replace) +{ + size_t pos = 0; + + while ((pos = subject.find(search, pos)) != std::string::npos) + { + subject.replace(pos, search.length(), replace); + pos += replace.length(); + } + + return subject; +} + +class GetImplementationName: + public loplugin::FilteringPlugin +{ +public: + explicit GetImplementationName(loplugin::InstantiationData const & data) + : FilteringPlugin(data) + , m_Outdir(initOutdir()) + , m_OutdirCreated(false) + , m_Srcdir(initSrcdir()) + {} + void run() override; + + bool VisitCXXMethodDecl(clang::CXXMethodDecl const * decl); + +private: + bool isStringConstant(Expr const * expr, clang::StringRef * string); + + bool returnsStringConstant( + FunctionDecl const * decl, clang::StringRef * string); + + void ensureOutdirCreated() + { + if(m_OutdirCreated) + return; + std::string cmd("mkdir -p "); + cmd += "\"" + m_Outdir + "\""; + if(system(cmd.c_str()) != 0) { + report( + clang::DiagnosticsEngine::Error, + "Error creating ServiceImplementations output dir \"%0\".") + << m_Outdir; + } + m_OutdirCreated = true; + } + + void generateOutput(FunctionDecl const * decl, const std::string unoimpl, const std::string cppclass); + std::string initOutdir(); + std::string initSrcdir(); + const std::string m_Outdir; + bool m_OutdirCreated; + const std::string m_Srcdir; +}; + +void GetImplementationName::run() { + if (compiler.getLangOpts().CPlusPlus) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } +} + +bool GetImplementationName::VisitCXXMethodDecl( + clang::CXXMethodDecl const * decl) +{ + if (ignoreLocation(decl) || !decl->doesThisDeclarationHaveABody() + || !decl->isVirtual()) + { + return true; + } + auto const id = decl->getIdentifier(); + if (id == nullptr || id->getName() != "getImplementationName" + || !overridesXServiceInfo(decl)) + { + return true; + } + clang::StringRef unoimpl; + if (!returnsStringConstant(decl, &unoimpl)) { + report( + clang::DiagnosticsEngine::Warning, + "cannot determine returned string", decl->getLocation()) + << decl->getSourceRange(); + return true; + } + generateOutput(decl, unoimpl.str(), decl->getParent()->getQualifiedNameAsString()); + return true; +} + +bool GetImplementationName::isStringConstant( + Expr const * expr, clang::StringRef * string) +{ + QualType t = expr->getType(); + if (!(t->isConstantArrayType() && t.isConstQualified() + && (loplugin::TypeCheck(t->getAsArrayTypeUnsafe()->getElementType()) + .Char()))) + { + return false; + } + DeclRefExpr const * dre = dyn_cast(expr); + if (dre != nullptr) { + VarDecl const * var = dyn_cast(dre->getDecl()); + if (var != nullptr) { + Expr const * init = var->getAnyInitializer(); + if (init != nullptr) { + expr = ignoreParenImplicitComma(init); + } + } + } + clang::StringLiteral const * lit = dyn_cast(expr); + if (lit != nullptr) { + if (!lit->isAscii()) { + return false; + } + *string = lit->getString(); + return true; + } + APValue v; + if (!expr->isCXX11ConstantExpr(compiler.getASTContext(), &v)) { + return false; + } + switch (v.getKind()) { + case APValue::LValue: + return false; //TODO + case APValue::Array: + { + if (v.hasArrayFiller()) { //TODO: handle final NUL filler? + return false; + } + unsigned n = v.getArraySize(); + assert(n != 0); + for (unsigned i = 0; i != n; ++i) { + APValue e(v.getArrayInitializedElt(i)); + if (!e.isInt()) { //TODO: assert? + return false; + } + APSInt iv = e.getInt(); + if (iv == 0) { + if (i == n -1) { + continue; + } + return false; + } else if (iv.uge(0x80)) { + return false; + } + //TODO + } + return false;//TODO + } + default: + abort(); //TODO??? + } +} + +bool GetImplementationName::returnsStringConstant( + FunctionDecl const * decl, clang::StringRef * string) +{ + auto s1 = decl->getBody(); + if (s1 == nullptr) { + return false; + } + for (;;) { + auto s2 = dyn_cast(s1); + if (s2 == nullptr) { + auto const s3 = dyn_cast(s1); + if (s3 == nullptr) { + break; + } + s2 = s3->getTryBlock(); + } + if (s2->size() != 1) { + break; + } + s1 = s2->body_front(); + } + auto const s4 = dyn_cast(s1); + if (s4 == nullptr) { + return false; + } + for (auto e1 = ignoreParenImplicitComma(s4->getRetValue());;) { + auto const e2 = dyn_cast(e1); + if (e2 != nullptr) { + auto const d = e2->getDirectCallee(); + return d != nullptr && returnsStringConstant(d, string); + } + auto const e3 = dyn_cast(e1); + if (e3 != nullptr) { + e1 = ignoreParenImplicitComma(e3->getSubExpr()); + continue; + } + auto const e4 = dyn_cast(e1); + if (e4 != nullptr) { + if (e4->getNumArgs() < 1) { + return false; + } + e1 = ignoreParenImplicitComma(e4->getArg(0)); + continue; + } + return isStringConstant(e1, string); + } +} + +void GetImplementationName::generateOutput(FunctionDecl const * decl, const std::string unoimpl, const std::string cppclass) { + ensureOutdirCreated(); + clang::SourceManager& sm(compiler.getSourceManager()); + const std::string absfilename(sm.getFilename(decl->getSourceRange().getBegin()).str()); + if(absfilename.length() <= m_Srcdir.length()) + return; + const std::string filename(absfilename.substr(m_Srcdir.length()+1)); + const std::regex moduleregex("^\\w+"); + std::smatch modulematch; + std::regex_search(filename, modulematch, moduleregex); + if(modulematch.empty()) + return; + const std::string module(modulematch[0]); + const std::string doublecolonregex("::"); + const std::string cppclassweb(replace_all(cppclass, doublecolonregex, "_1_1")); + std::ofstream redirectfile(m_Outdir + "/" + unoimpl + ".html"); + redirectfile << "\n"; + redirectfile.close(); +} + +std::string GetImplementationName::initOutdir() { +{ + char* pWorkdir = getenv("WORKDIR"); + if(pWorkdir) { + std::string result(pWorkdir); + result += "/ServiceImplementations"; + return result; + } + report( + clang::DiagnosticsEngine::Error, "WORKDIR unset, don't know where to write service implementation info."); + return std::string(); + } +} + +std::string GetImplementationName::initSrcdir() { +{ + char* pSrcdir = getenv("SRCDIR"); + if(!pSrcdir) { + report( + clang::DiagnosticsEngine::Error, "SRCDIR unset, don't know where the source base is."); + } + return std::string(pSrcdir); + } +} +loplugin::Plugin::Registration X( + "getimplementationname", false); +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/getstr.cxx b/compilerplugins/clang/getstr.cxx new file mode 100644 index 000000000..671699e73 --- /dev/null +++ b/compilerplugins/clang/getstr.cxx @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include + +#include "check.hxx" +#include "plugin.hxx" + +// Find matches of +// +// ... << s.getStr() +// +// (for the rtl string classes) that can be written as just +// +// ... << s + +namespace +{ +class GetStr final : public loplugin::FilteringPlugin +{ +public: + explicit GetStr(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool PreTraverseFunctionDecl(FunctionDecl* decl) + { + functions_.push(decl); + return true; + } + + bool PostTraverseFunctionDecl(FunctionDecl*, bool) + { + assert(!functions_.empty()); + functions_.pop(); + return true; + } + + bool TraverseFunctionDecl(FunctionDecl* decl) + { + bool ret = true; + if (PreTraverseFunctionDecl(decl)) + { + ret = FilteringPlugin::TraverseFunctionDecl(decl); + PostTraverseFunctionDecl(decl, ret); + } + return ret; + } + + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + if (expr->getOperator() != OO_LessLess) + { + return true; + } + assert(expr->getNumArgs() == 2); + if (!loplugin::TypeCheck(expr->getArg(0)->getType()) + .ClassOrStruct("basic_ostream") + .StdNamespace()) //TODO: check template args + { + return true; + } + auto const arg1 = expr->getArg(1); + auto const e = dyn_cast(arg1->IgnoreParenImpCasts()); + if (e == nullptr) + { + return true; + } + bool castToVoid = false; + if (auto const ic = dyn_cast(arg1)) + { + if (loplugin::TypeCheck(arg1->getType()).Pointer().Void()) + { + castToVoid = true; + } + } + auto const t = e->getObjectType(); + auto const tc = loplugin::TypeCheck(t); + if (!(tc.Class("OString").Namespace("rtl").GlobalNamespace() + || tc.Class("OUString").Namespace("rtl").GlobalNamespace() + || (castToVoid + && (tc.Class("OStringBuffer").Namespace("rtl").GlobalNamespace() + || tc.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace())))) + { + return true; + } + if (!loplugin::DeclCheck(e->getMethodDecl()).Function("getStr")) + { + return true; + } + if (castToVoid) + { + report(DiagnosticsEngine::Warning, + ("suspicious use of 'getStr' on an object of type %0; the result is implicitly" + " cast to a void pointer in a call of 'operator <<'"), + e->getExprLoc()) + << t.getLocalUnqualifiedType() << expr->getSourceRange(); + return true; + } + if (!functions_.empty()) + { + // Filter out occurrences of `s << t.getStr()` in the implementation of + // `operator <<(std::basic_ostream<...> & s, T const & t)`: + auto const fd = functions_.top(); + if (fd->getOverloadedOperator() == OO_LessLess) + { + assert(fd->getNumParams() == 2); + if (loplugin::TypeCheck(fd->getParamDecl(0)->getType()) + .LvalueReference() + .NonConstVolatile() + .TemplateSpecializationClass() + .ClassOrStruct("basic_ostream") + .StdNamespace()) //TODO: check template args + { + if (auto const t2 + = fd->getParamDecl(1)->getType()->getAs()) + { + auto const t3 = t2->getPointeeType(); + if (t3.isConstQualified() && !t3.isVolatileQualified() + && (t3.getCanonicalType().getTypePtr() + == t.getCanonicalType().getTypePtr())) + { + return true; + } + } + } + } + } + report(DiagnosticsEngine::Warning, + ("directly use object of type %0 in a call of 'operator <<', instead of calling" + " 'getStr' first"), + e->getExprLoc()) + << t.getLocalUnqualifiedType() << expr->getSourceRange(); + return true; + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + +private: + std::stack functions_; + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } +}; + +loplugin::Plugin::Registration getstr("getstr"); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/implicitboolconversion.cxx b/compilerplugins/clang/implicitboolconversion.cxx new file mode 100644 index 000000000..29b82d8ea --- /dev/null +++ b/compilerplugins/clang/implicitboolconversion.cxx @@ -0,0 +1,896 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "clang/Basic/Builtins.h" + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" + +namespace { + +Expr const * ignoreParenAndTemporaryMaterialization(Expr const * expr) { + for (;;) { + expr = expr->IgnoreParens(); + auto e = dyn_cast(expr); + if (e == nullptr) { + return expr; + } + expr = e->getSubExpr(); + } +} + +Expr const * ignoreParenImpCastAndComma(Expr const * expr) { + for (;;) { + expr = expr->IgnoreParenImpCasts(); + BinaryOperator const * op = dyn_cast(expr); + if (op == nullptr || op->getOpcode() != BO_Comma) { + return expr; + } + expr = op->getRHS(); + } +} + +SubstTemplateTypeParmType const * getAsSubstTemplateTypeParmType(QualType type) +{ + //TODO: unwrap all kinds of (non-SubstTemplateTypeParmType) sugar, not only + // TypedefType sugar: + for (;;) { + TypedefType const * t = type->getAs(); + if (t == nullptr) { + return dyn_cast(type); + } + type = t->desugar(); + } +} + +QualType reconstructTemplateArgumentType( + TemplateDecl const * decl, TemplateSpecializationType const * specializationType, + SubstTemplateTypeParmType const * parmType) +{ + TemplateParameterList const * ps = decl->getTemplateParameters(); + auto i = std::find(ps->begin(), ps->end(), parmType->getReplacedParameter()->getDecl()); + if (i == ps->end()) { + return {}; + } + if (ps->size() != specializationType->getNumArgs()) { //TODO + return {}; + } + TemplateArgument const & arg = specializationType->getArg(i - ps->begin()); + if (arg.getKind() != TemplateArgument::Type) { + return {}; + } + return arg.getAsType(); +} + +bool areSameTypedef(QualType type1, QualType type2) { + // type1.getTypePtr() == typ2.getTypePtr() fails for e.g. ::sal_Bool vs. + // sal_Bool: + auto t1 = type1->getAs(); + auto t2 = type2->getAs(); + return t1 != nullptr && t2 != nullptr && t1->getDecl() == t2->getDecl(); +} + +bool isBool(Expr const * expr, bool allowTypedefs = true) { + auto t = expr->getType(); + return allowTypedefs + ? bool(loplugin::TypeCheck(t).AnyBoolean()) : t->isBooleanType(); +} + +bool isMatchingBool(Expr const * expr, Expr const * comparisonExpr) { + return isBool(expr, false) + || areSameTypedef(expr->getType(), comparisonExpr->getType()); +} + +bool isSalBool(QualType type) { + auto t = type->getAs(); + return t != nullptr && t->getDecl()->getName() == "sal_Bool"; +} + +bool isBoolExpr(Expr const * expr) { + if (isBool(expr)) { + return true; + } + expr = ignoreParenImpCastAndComma(expr); + ConditionalOperator const * co = dyn_cast(expr); + if (co != nullptr) { + ImplicitCastExpr const * ic1 = dyn_cast( + co->getTrueExpr()->IgnoreParens()); + ImplicitCastExpr const * ic2 = dyn_cast( + co->getFalseExpr()->IgnoreParens()); + if (ic1 != nullptr && ic2 != nullptr + && ic1->getType()->isSpecificBuiltinType(BuiltinType::Int) + && isBoolExpr(ic1->getSubExpr()->IgnoreParens()) + && ic2->getType()->isSpecificBuiltinType(BuiltinType::Int) + && isBoolExpr(ic2->getSubExpr()->IgnoreParens())) + { + return true; + } + } + std::stack stack; + Expr const * e = expr; + for (;;) { + e = ignoreParenImpCastAndComma(e); + MemberExpr const * me = dyn_cast(e); + if (me == nullptr) { + break; + } + stack.push(e); + e = me->getBase(); + } + for (;;) { + e = ignoreParenImpCastAndComma(e); + CXXOperatorCallExpr const * op = dyn_cast(e); + if (op == nullptr || op->getOperator() != OO_Subscript) { + break; + } + stack.push(e); + e = op->getArg(0); + } + if (!stack.empty()) { + TemplateSpecializationType const * t + = e->getType()->getAs(); + for (;;) { + if (t == nullptr) { + break; + } + QualType ty; + MemberExpr const * me = dyn_cast(stack.top()); + if (me != nullptr) { + TemplateDecl const * td + = t->getTemplateName().getAsTemplateDecl(); + if (td == nullptr) { + break; + } + SubstTemplateTypeParmType const * t2 + = getAsSubstTemplateTypeParmType( + me->getMemberDecl()->getType()); + if (t2 == nullptr) { + break; + } + ty = reconstructTemplateArgumentType(td, t, t2); + if (ty.isNull()) { + auto const canon = cast(td->getCanonicalDecl()); + if (canon != td) { + ty = reconstructTemplateArgumentType(canon, t, t2); + } + } + if (ty.isNull()) { + break; + } + } else { + CXXOperatorCallExpr const * op + = dyn_cast(stack.top()); + assert(op != nullptr); + (void)op; + TemplateDecl const * d + = t->getTemplateName().getAsTemplateDecl(); + if (d == nullptr) { + break; + } + auto const dc = loplugin::DeclCheck(d->getTemplatedDecl()); + if (dc.ClassOrStruct("array").StdNamespace() && t->getNumArgs() >= 2 + && t->getArg(0).getKind() == TemplateArgument::Type) + { + ty = t->getArg(0).getAsType(); + } else if (dc.Class("Sequence").Namespace("uno").Namespace("star").Namespace("sun") + .Namespace("com").GlobalNamespace() + && t->getNumArgs() == 1 + && t->getArg(0).getKind() == TemplateArgument::Type) + { + ty = t->getArg(0).getAsType(); + } else { + break; + } + } + stack.pop(); + if (stack.empty()) { + if (loplugin::TypeCheck(ty).AnyBoolean()) { + return true; + } + break; + } + t = ty->getAs(); + } + } + return false; +} + +// It appears that, given a function declaration, there is no way to determine +// the language linkage of the function's type, only of the function's name +// (via FunctionDecl::isExternC); however, in a case like +// +// extern "C" { static void f(); } +// +// the function's name does not have C language linkage while the function's +// type does (as clarified in C++11 [decl.link]); cf. +// "Language linkage of function type": +bool hasCLanguageLinkageType(FunctionDecl const * decl) { + assert(decl != nullptr); + if (decl->isExternC()) { + return true; + } + if (decl->isInExternCContext()) { + return true; + } + return false; +} + +class ImplicitBoolConversion: + public loplugin::FilteringPlugin +{ +public: + explicit ImplicitBoolConversion(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool TraverseCallExpr(CallExpr * expr); + + bool TraverseCXXMemberCallExpr(CXXMemberCallExpr * expr); + + bool TraverseCXXConstructExpr(CXXConstructExpr * expr); + + bool TraverseCXXTemporaryObjectExpr(CXXTemporaryObjectExpr * expr); + + bool TraverseCStyleCastExpr(CStyleCastExpr * expr); + + bool TraverseCXXStaticCastExpr(CXXStaticCastExpr * expr); + + bool TraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr * expr); + + bool TraverseConditionalOperator(ConditionalOperator * expr); + + bool TraverseBinaryOperator(BinaryOperator * expr); + + bool TraverseCompoundAssignOperator(CompoundAssignOperator * expr); + + bool TraverseInitListExpr(InitListExpr * expr); + + bool TraverseReturnStmt(ReturnStmt * stmt); + + bool TraverseFunctionDecl(FunctionDecl * decl); + + bool VisitImplicitCastExpr(ImplicitCastExpr const * expr); + + bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr const * expr); + +private: + bool isExternCFunctionCall( + CallExpr const * expr, FunctionProtoType const ** functionType); + + bool isExternCFunctionCallReturningInt(Expr const * expr); + + void checkCXXConstructExpr(CXXConstructExpr const * expr); + + void reportWarning(ImplicitCastExpr const * expr); + + std::stack> nested; + std::stack calls; + bool bExternCIntFunctionDefinition = false; +}; + +bool ImplicitBoolConversion::TraverseCallExpr(CallExpr * expr) { + nested.push(std::vector()); + calls.push(expr); + bool bRet = RecursiveASTVisitor::TraverseCallExpr(expr); + FunctionProtoType const * t; + bool bExt = isExternCFunctionCall(expr, &t); + assert(!nested.empty()); + for (auto i: nested.top()) { + auto j = std::find_if( + expr->arg_begin(), expr->arg_end(), + [&i](Expr * e) { + return i == ignoreParenAndTemporaryMaterialization(e); + }); + if (j == expr->arg_end()) { + reportWarning(i); + } else { + std::ptrdiff_t n = j - expr->arg_begin(); + assert(n >= 0); + if (t != nullptr + && static_cast(n) >= t->getNumParams()) + { + assert(t->isVariadic()); + // ignore bool to int promotions of variadic arguments + } else if (bExt) { + if (t != nullptr) { + assert( + static_cast(n) < t->getNumParams()); + if (!(t->getParamType(n)->isSpecificBuiltinType( + BuiltinType::Int) + || t->getParamType(n)->isSpecificBuiltinType( + BuiltinType::UInt) + || t->getParamType(n)->isSpecificBuiltinType( + BuiltinType::Long))) + { + reportWarning(i); + } + } else { + reportWarning(i); + } + } else { + // Filter out + // + // template void f(T); + // f(true); + // + DeclRefExpr const * dr = dyn_cast( + expr->getCallee()->IgnoreParenImpCasts()); + if (dr != nullptr && dr->hasExplicitTemplateArgs()) { + FunctionDecl const * fd + = dyn_cast(dr->getDecl()); + if (fd != nullptr + && static_cast(n) < fd->getNumParams()) + { + SubstTemplateTypeParmType const * t2 + = getAsSubstTemplateTypeParmType( + fd->getParamDecl(n)->getType() + .getNonReferenceType()); + if (t2 != nullptr) { + //TODO: fix this superficial nonsense check: + if (dr->getNumTemplateArgs() == 1) { + auto const ta = dr->getTemplateArgs(); + if ((ta[0].getArgument().getKind() + == TemplateArgument::Type) + && (loplugin::TypeCheck( + ta[0].getTypeSourceInfo() + ->getType()) + .AnyBoolean())) + { + continue; + } + } + } + } + } + reportWarning(i); + } + } + } + calls.pop(); + nested.pop(); + return bRet; +} + +bool ImplicitBoolConversion::TraverseCXXMemberCallExpr(CXXMemberCallExpr * expr) +{ + nested.push(std::vector()); + bool bRet = RecursiveASTVisitor::TraverseCXXMemberCallExpr(expr); + assert(!nested.empty()); + for (auto i: nested.top()) { + auto j = std::find_if( + expr->arg_begin(), expr->arg_end(), + [&i](Expr * e) { + return i == ignoreParenAndTemporaryMaterialization(e); + }); + if (j != expr->arg_end()) { + // Filter out + // + // template struct S { void f(T); }; + // S s; + // s.f(true); + // + std::ptrdiff_t n = j - expr->arg_begin(); + assert(n >= 0); + CXXMethodDecl const * d = expr->getMethodDecl(); + if (static_cast(n) >= d->getNumParams()) { + // Ignore bool to int promotions of variadic arguments: + assert(d->isVariadic()); + continue; + } + QualType ty + = ignoreParenImpCastAndComma(expr->getImplicitObjectArgument()) + ->getType(); + if (dyn_cast(expr->getCallee())->isArrow()) { + ty = ty->getAs()->getPointeeType(); + } + TemplateSpecializationType const * ct + = ty->getAs(); + if (ct != nullptr) { + SubstTemplateTypeParmType const * pt + = getAsSubstTemplateTypeParmType( + d->getParamDecl(n)->getType().getNonReferenceType()); + if (pt != nullptr) { + TemplateDecl const * td + = ct->getTemplateName().getAsTemplateDecl(); + if (td != nullptr) { + //TODO: fix this superficial nonsense check: + if (ct->getNumArgs() >= 1 + && ct->getArg(0).getKind() == TemplateArgument::Type + && (loplugin::TypeCheck(ct->getArg(0).getAsType()) + .AnyBoolean())) + { + continue; + } + } + } + } + } + reportWarning(i); + } + nested.pop(); + return bRet; +} + +bool ImplicitBoolConversion::TraverseCXXConstructExpr(CXXConstructExpr * expr) { + nested.push(std::vector()); + bool bRet = RecursiveASTVisitor::TraverseCXXConstructExpr(expr); + checkCXXConstructExpr(expr); + nested.pop(); + return bRet; +} + +bool ImplicitBoolConversion::TraverseCXXTemporaryObjectExpr( + CXXTemporaryObjectExpr * expr) +{ + nested.push(std::vector()); + bool bRet = RecursiveASTVisitor::TraverseCXXTemporaryObjectExpr(expr); + checkCXXConstructExpr(expr); + nested.pop(); + return bRet; +} + +bool ImplicitBoolConversion::TraverseCStyleCastExpr(CStyleCastExpr * expr) { + nested.push(std::vector()); + bool bRet = RecursiveASTVisitor::TraverseCStyleCastExpr(expr); + assert(!nested.empty()); + for (auto i: nested.top()) { + if (i != expr->getSubExpr()->IgnoreParens()) { + reportWarning(i); + } + } + nested.pop(); + return bRet; +} + +bool ImplicitBoolConversion::TraverseCXXStaticCastExpr(CXXStaticCastExpr * expr) +{ + nested.push(std::vector()); + bool bRet = RecursiveASTVisitor::TraverseCXXStaticCastExpr(expr); + assert(!nested.empty()); + for (auto i: nested.top()) { + if (i != expr->getSubExpr()->IgnoreParens()) { + reportWarning(i); + } + } + nested.pop(); + return bRet; +} + +bool ImplicitBoolConversion::TraverseCXXFunctionalCastExpr( + CXXFunctionalCastExpr * expr) +{ + nested.push(std::vector()); + bool bRet = RecursiveASTVisitor::TraverseCXXFunctionalCastExpr(expr); + assert(!nested.empty()); + for (auto i: nested.top()) { + if (i != expr->getSubExpr()->IgnoreParens()) { + reportWarning(i); + } + } + nested.pop(); + return bRet; +} + +bool ImplicitBoolConversion::TraverseConditionalOperator( + ConditionalOperator * expr) +{ + nested.push(std::vector()); + bool bRet = RecursiveASTVisitor::TraverseConditionalOperator(expr); + assert(!nested.empty()); + for (auto i: nested.top()) { + if (!((i == expr->getTrueExpr()->IgnoreParens() + && (isBoolExpr(expr->getFalseExpr()->IgnoreParenImpCasts()) + || isExternCFunctionCallReturningInt(expr->getFalseExpr()))) + || (i == expr->getFalseExpr()->IgnoreParens() + && (isBoolExpr(expr->getTrueExpr()->IgnoreParenImpCasts()) + || isExternCFunctionCallReturningInt( + expr->getTrueExpr()))) + || (!compiler.getLangOpts().CPlusPlus + && i == expr->getCond()->IgnoreParens()))) + { + reportWarning(i); + } + } + nested.pop(); + return bRet; +} + +bool ImplicitBoolConversion::TraverseBinaryOperator(BinaryOperator * expr) { + switch (expr->getOpcode()) { + case BO_LT: + case BO_LE: + case BO_GT: + case BO_GE: + case BO_EQ: + case BO_NE: + { + nested.push(std::vector()); + bool bRet = RecursiveASTVisitor::TraverseBinaryOperator(expr); + assert(!nested.empty()); + for (auto i: nested.top()) { + if (!((i == expr->getLHS()->IgnoreParens() + && isMatchingBool( + expr->getRHS()->IgnoreImpCasts(), i->getSubExprAsWritten())) + || (i == expr->getRHS()->IgnoreParens() + && isMatchingBool( + expr->getLHS()->IgnoreImpCasts(), + i->getSubExprAsWritten())))) + { + reportWarning(i); + } + } + nested.pop(); + return bRet; + } + case BO_Assign: + { + nested.push(std::vector()); + bool bRet = RecursiveASTVisitor::TraverseBinaryOperator(expr); + // gtk-2.0/gtk/gtktogglebutton.h: struct _GtkToggleButton: + // guint GSEAL (active) : 1; + // even though : + // "active" gboolean : Read / Write + // qt5/QtGui/qaccessible.h: struct State: + // quint64 disabled : 1; + bool bExt = false; + MemberExpr const * me = dyn_cast(expr->getLHS()); + if (me != nullptr) { + FieldDecl const * fd = dyn_cast(me->getMemberDecl()); + if (fd != nullptr && fd->isBitField() + && fd->getBitWidthValue(compiler.getASTContext()) == 1) + { + auto const check = loplugin::TypeCheck(fd->getType()); + bExt = check.Typedef("guint").GlobalNamespace() + || check.Typedef("quint64").GlobalNamespace(); + } + } + assert(!nested.empty()); + for (auto i: nested.top()) { + if (i != expr->getRHS()->IgnoreParens() + || !(bExt || isBoolExpr(expr->getLHS()))) + { + reportWarning(i); + } + } + nested.pop(); + return bRet; + } + default: + return RecursiveASTVisitor::TraverseBinaryOperator(expr); + } +} + +bool ImplicitBoolConversion::TraverseCompoundAssignOperator(CompoundAssignOperator * expr) { + switch (expr->getOpcode()) { + case BO_AndAssign: + case BO_OrAssign: + case BO_XorAssign: + { + nested.push(std::vector()); + bool bRet = RecursiveASTVisitor::TraverseCompoundAssignOperator(expr); + assert(!nested.empty()); + for (auto i: nested.top()) { + if (i != expr->getRHS()->IgnoreParens() + || !isBool(expr->getLHS()->IgnoreParens(), false)) + { + reportWarning(i); + } + } + nested.pop(); + if (!ignoreLocation(expr) && isBool(expr->getLHS(), false) + && !isBool(expr->getRHS()->IgnoreParenImpCasts(), false)) + { + report( + DiagnosticsEngine::Warning, "mix of %0 and %1 in operator %2", + expr->getRHS()->getBeginLoc()) + << expr->getLHS()->getType() + << expr->getRHS()->IgnoreParenImpCasts()->getType() + << expr->getOpcodeStr() + << expr->getSourceRange(); + } + return bRet; + } + default: + return RecursiveASTVisitor::TraverseCompoundAssignOperator(expr); + } +} + +bool ImplicitBoolConversion::TraverseInitListExpr(InitListExpr * expr) { + nested.push(std::vector()); + auto const e = expr->isSemanticForm() ? expr : expr->getSemanticForm(); + auto const ret = TraverseSynOrSemInitListExpr(e, nullptr); + assert(!nested.empty()); + for (auto i: nested.top()) { + if (std::find(e->begin(), e->end(), i) == e->end() + || !i->getType()->isSpecificBuiltinType(clang::BuiltinType::UChar)) + { + reportWarning(i); + } + } + nested.pop(); + return ret; +} + +bool ImplicitBoolConversion::TraverseReturnStmt(ReturnStmt * stmt) { + nested.push(std::vector()); + bool bRet = RecursiveASTVisitor::TraverseReturnStmt(stmt); + Expr const * expr = stmt->getRetValue(); + if (expr != nullptr) { + ExprWithCleanups const * ec = dyn_cast(expr); + if (ec != nullptr) { + expr = ec->getSubExpr(); + } + expr = expr->IgnoreParens(); + } + assert(!nested.empty()); + for (auto i: nested.top()) { + if (i != expr || !bExternCIntFunctionDefinition) { + reportWarning(i); + } + } + nested.pop(); + return bRet; +} + +bool ImplicitBoolConversion::TraverseFunctionDecl(FunctionDecl * decl) { + bool bExt = false; + if (hasCLanguageLinkageType(decl) && decl->isThisDeclarationADefinition()) { + QualType t { decl->getReturnType() }; + if (t->isSpecificBuiltinType(BuiltinType::Int) + || t->isSpecificBuiltinType(BuiltinType::UInt)) + { + bExt = true; + } else { + TypedefType const * t2 = t->getAs(); + // cf. rtl_locale_equals (and sal_Int32 can be long): + if (t2 != nullptr + && t2->getDecl()->getNameAsString() == "sal_Int32") + { + bExt = true; + } + } + } + if (bExt) { + assert(!bExternCIntFunctionDefinition); + bExternCIntFunctionDefinition = true; + } + bool bRet = RecursiveASTVisitor::TraverseFunctionDecl(decl); + if (bExt) { + bExternCIntFunctionDefinition = false; + } + return bRet; +} + +bool ImplicitBoolConversion::VisitImplicitCastExpr( + ImplicitCastExpr const * expr) +{ + if (ignoreLocation(expr)) { + return true; + } + if (isBool(compat::getSubExprAsWritten(expr)) && !isBool(expr)) { + // Ignore NoOp from 'sal_Bool' (aka 'unsigned char') to 'const unsigned + // char' in makeAny(b) with b of type sal_Bool: + if (expr->getCastKind() != CK_NoOp) { + if (nested.empty()) { + reportWarning(expr); + } else { + nested.top().push_back(expr); + } + } + return true; + } + if (auto const sub = dyn_cast( + compat::getSubExprAsWritten(expr))) + { + auto const subsub = compat::getSubExprAsWritten(sub); + if (subsub->getType().IgnoreParens() == expr->getType().IgnoreParens() + && isBool(subsub)) + { + // Ignore "normalizing cast" bool(b) from sal_Bool b to bool, then + // implicitly cast back again to sal_Bool: + if (dyn_cast(sub) != nullptr + && sub->getType()->isBooleanType() && isSalBool(expr->getType()) + && isSalBool(subsub->getType())) + { + return true; + } + report( + DiagnosticsEngine::Warning, + ("explicit conversion (%0) from %1 to %2 implicitly cast back" + " to %3"), + expr->getBeginLoc()) + << sub->getCastKindName() << subsub->getType() << sub->getType() + << expr->getType() << expr->getSourceRange(); + return true; + } + } + if (expr->getType()->isBooleanType() && !isBoolExpr(expr->getSubExpr()) + && !calls.empty()) + { + CallExpr const * call = calls.top(); + if (std::any_of( + call->arg_begin(), call->arg_end(), + [expr](Expr const * e) { return expr == e->IgnoreParens(); })) + { + report( + DiagnosticsEngine::Warning, + "implicit conversion (%0) of call argument from %1 to %2", + expr->getBeginLoc()) + << expr->getCastKindName() << expr->getSubExpr()->getType() + << expr->getType() << expr->getSourceRange(); + return true; + } + } + return true; +} + +bool ImplicitBoolConversion::VisitMaterializeTemporaryExpr( + MaterializeTemporaryExpr const * expr) +{ + if (ignoreLocation(expr)) { + return true; + } + if (auto const sub = dyn_cast(expr->getSubExpr())) { + auto const subsub = compat::getSubExprAsWritten(sub); + if (subsub->getType().IgnoreParens() == expr->getType().IgnoreParens() + && isBool(subsub)) + { + report( + DiagnosticsEngine::Warning, + ("explicit conversion (%0) from %1 to %2 implicitly converted" + " back to %3"), + expr->getBeginLoc()) + << sub->getCastKindName() << subsub->getType() << sub->getType() + << expr->getType() << expr->getSourceRange(); + return true; + } + } + return true; +} + +bool ImplicitBoolConversion::isExternCFunctionCall( + CallExpr const * expr, FunctionProtoType const ** functionType) +{ + assert(functionType != nullptr); + *functionType = nullptr; + Decl const * d = expr->getCalleeDecl(); + if (d != nullptr) { + FunctionDecl const * fd = dyn_cast(d); + if (fd != nullptr) { + clang::PointerType const * pt = fd->getType() + ->getAs(); + QualType t2(pt == nullptr ? fd->getType() : pt->getPointeeType()); + *functionType = t2->getAs(); + assert( + *functionType != nullptr || !compiler.getLangOpts().CPlusPlus + || (fd->getBuiltinID() != Builtin::NotBuiltin + && isa(t2))); + // __builtin_*s have no proto type? + return fd->isExternC() + || compiler.getSourceManager().isInExternCSystemHeader( + fd->getLocation()); + } + VarDecl const * vd = dyn_cast(d); + if (vd != nullptr) { + clang::PointerType const * pt = vd->getType() + ->getAs(); + *functionType + = ((pt == nullptr ? vd->getType() : pt->getPointeeType()) + ->getAs()); + return vd->isExternC(); + } + } + return false; +} + +bool ImplicitBoolConversion::isExternCFunctionCallReturningInt( + Expr const * expr) +{ + CallExpr const * e = dyn_cast(expr->IgnoreParenImpCasts()); + FunctionProtoType const * t; + return e != nullptr && e->getType()->isSpecificBuiltinType(BuiltinType::Int) + && isExternCFunctionCall(e, &t); +} + +void ImplicitBoolConversion::checkCXXConstructExpr( + CXXConstructExpr const * expr) +{ + assert(!nested.empty()); + for (auto i: nested.top()) { + auto j = std::find_if( + expr->arg_begin(), expr->arg_end(), + [&i](Expr const * e) { + return i == ignoreParenAndTemporaryMaterialization(e); + }); + if (j != expr->arg_end()) { + TemplateSpecializationType const * t1 = expr->getType()-> + getAs(); + if (t1 == nullptr) { + //TODO: + if (i->getType()->isSpecificBuiltinType(clang::BuiltinType::UChar)) { + continue; + } + } else { + SubstTemplateTypeParmType const * t2 = nullptr; + CXXConstructorDecl const * d = expr->getConstructor(); + if (d->getNumParams() == expr->getNumArgs()) { //TODO: better check + t2 = getAsSubstTemplateTypeParmType( + d->getParamDecl(j - expr->arg_begin())->getType() + .getNonReferenceType()); + } + if (t2 != nullptr) { + TemplateDecl const * td + = t1->getTemplateName().getAsTemplateDecl(); + if (td != nullptr) { + TemplateParameterList const * ps + = td->getTemplateParameters(); + auto k = std::find( + ps->begin(), ps->end(), + t2->getReplacedParameter()->getDecl()); + if (k != ps->end()) { + if (ps->size() == t1->getNumArgs()) { //TODO + TemplateArgument const & arg = t1->getArg( + k - ps->begin()); + if (arg.getKind() == TemplateArgument::Type + && (loplugin::TypeCheck(arg.getAsType()) + .AnyBoolean())) + { + continue; + } + } + } + } + } + } + } + reportWarning(i); + } +} + +void ImplicitBoolConversion::reportWarning(ImplicitCastExpr const * expr) { + if (compiler.getLangOpts().CPlusPlus) { + if (expr->getCastKind() == CK_ConstructorConversion) { + auto const t1 = expr->getType(); + if (auto const t2 = t1->getAs()) { + assert(t2->getNumArgs() >= 1); + auto const a = t2->getArg(0); + if (a.getKind() == TemplateArgument::Type && a.getAsType()->isBooleanType() + && (loplugin::TypeCheck(t1).TemplateSpecializationClass() + .ClassOrStruct("atomic").StdNamespace())) + { + return; + } + } + } + report( + DiagnosticsEngine::Warning, + "implicit conversion (%0) from %1 to %2", expr->getBeginLoc()) + << expr->getCastKindName() << expr->getSubExprAsWritten()->getType() + << expr->getType() << expr->getSourceRange(); + } +} + +loplugin::Plugin::Registration X( + "implicitboolconversion"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/includeform.cxx b/compilerplugins/clang/includeform.cxx new file mode 100644 index 000000000..7b2c0feb0 --- /dev/null +++ b/compilerplugins/clang/includeform.cxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include "config_clang.h" + +#include "plugin.hxx" + +// Enforces the "Rules for #include directives (C/C++)" described in README.md. + +namespace { + +class IncludeForm final: public PPCallbacks, public loplugin::RewritePlugin { +public: + explicit IncludeForm(loplugin::InstantiationData const & data): + RewritePlugin(data) + { compiler.getPreprocessor().addPPCallbacks(std::unique_ptr(this)); } + +private: + void run() override {} + + void InclusionDirective( + SourceLocation HashLoc, Token const & IncludeTok, StringRef, + bool IsAngled, CharSourceRange FilenameRange, +#if CLANG_VERSION >= 150000 + Optional File, +#else + FileEntry const * File, +#endif + StringRef SearchPath, StringRef, clang::Module const *, SrcMgr::CharacteristicKind) override + { + if (ignoreLocation(HashLoc)) { + return; + } + if (!File) { // in case of "fatal error: '...' file not found" + return; + } + if (IncludeTok.getIdentifierInfo()->getPPKeywordID() != tok::pp_include) + { + return; + } + auto const uno = isInUnoIncludeFile(HashLoc) + && !compiler.getSourceManager().isInMainFile(HashLoc); + // exclude the various compat.cxx that are included in + // isInUnoIncludeFile + //TODO: 'uno' should be false if HashLoc is inside an + // '#ifdef LIBO_INTERNAL_ONLY' block + bool shouldUseAngles; + if (uno) { + shouldUseAngles + = (!(loplugin::hasPathnamePrefix(SearchPath, SRCDIR "/") + || loplugin::hasPathnamePrefix(SearchPath, BUILDDIR "/")) + || loplugin::hasPathnamePrefix( + SearchPath, WORKDIR "/UnpackedTarball/")); + } else { + auto dir1 = std::string(SearchPath); + loplugin::normalizeDotDotInFilePath(dir1); + auto const file = StringRef( + compiler.getSourceManager().getPresumedLoc(HashLoc) + .getFilename()); + auto pos = file.rfind('/'); +#if defined _WIN32 + auto const pos2 = file.rfind('\\'); + if (pos2 != StringRef::npos + && (pos == StringRef::npos || pos2 > pos)) + { + pos = pos2; + } +#endif + auto dir2 = std::string(file.take_front(pos)); + loplugin::normalizeDotDotInFilePath(dir2); + shouldUseAngles = !loplugin::isSamePathname(dir1, dir2); + } + if (shouldUseAngles == IsAngled) { + return; + } + if (rewriter != nullptr) { + auto last = FilenameRange.getEnd().getLocWithOffset(-1); + if ((compiler.getSourceManager().getCharacterData( + FilenameRange.getBegin())[0] + == (IsAngled ? '<' : '"')) + && (compiler.getSourceManager().getCharacterData(last)[0] + == (IsAngled ? '>' : '"')) + && replaceText( + FilenameRange.getBegin(), 1, shouldUseAngles ? "<" : "\"") + && replaceText(last, 1, shouldUseAngles ? ">" : "\"")) + { + //TODO: atomically only replace both or neither + return; + } + } + report( + DiagnosticsEngine::Warning, + ("%select{|in UNO API include file, }0replace" + " %select{\"...\"|<...>}1 include form with" + " %select{\"...\"|<...>}2 for inclusion of %select{%select{a" + " source file next to the current source file|a source file not" + " next to the current source file, or a header}2|%select{a source" + " file|a header}2}0, %3"), + FilenameRange.getBegin()) + << uno << IsAngled << shouldUseAngles << File->getName() + << FilenameRange; + } +}; + +static loplugin::Plugin::Registration reg("includeform", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/indentation.cxx b/compilerplugins/clang/indentation.cxx new file mode 100644 index 000000000..cf2512d1d --- /dev/null +++ b/compilerplugins/clang/indentation.cxx @@ -0,0 +1,460 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" + +/* +Check for child statements inside a compound statement that do not share the same indentation. + +TODO if an open-brace starts on a new line by itself, check that it lines up with it's closing-brace +TODO else should line up with if +*/ + +namespace +{ +class Indentation : public loplugin::FilteringPlugin +{ +public: + explicit Indentation(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual bool preRun() override + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + // include another file to build a table + if (fn == SRCDIR "/sc/source/core/tool/cellkeytranslator.cxx") + return false; + // weird structure + if (fn == SRCDIR "/sc/source/core/tool/compiler.cxx") + return false; + // looks like lex/yacc output + if (fn == SRCDIR "/hwpfilter/source/grammar.cxx") + return false; + // the QEMIT macros + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/qt5/") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/qt6/") + || loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/gtk3_kde5/kde5_filepicker_ipc.cxx")) + return false; + return true; + } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCompoundStmt(CompoundStmt const*); + bool PreTraverseSwitchStmt(SwitchStmt*); + bool PostTraverseSwitchStmt(SwitchStmt*, bool); + bool TraverseSwitchStmt(SwitchStmt*); + bool VisitSwitchStmt(SwitchStmt const*); + bool VisitIfStmt(IfStmt const*); + bool VisitForStmt(ForStmt const*); + bool VisitWhileStmt(WhileStmt const*); + bool VisitDoStmt(DoStmt const*); + bool VisitCXXForRangeStmt(CXXForRangeStmt const*); + +private: + void checkCompoundStmtBraces(const Stmt* parentStmt, const CompoundStmt*); + + std::vector switchStmtBodies; + std::unordered_set chainedSet; +}; + +bool Indentation::PreTraverseSwitchStmt(SwitchStmt* switchStmt) +{ + switchStmtBodies.push_back(switchStmt->getBody()); + return true; +} + +bool Indentation::PostTraverseSwitchStmt(SwitchStmt*, bool) +{ + switchStmtBodies.pop_back(); + return true; +} + +bool Indentation::TraverseSwitchStmt(SwitchStmt* switchStmt) +{ + PreTraverseSwitchStmt(switchStmt); + auto ret = FilteringPlugin::TraverseSwitchStmt(switchStmt); + PostTraverseSwitchStmt(switchStmt, ret); + return ret; +} + +bool Indentation::VisitCompoundStmt(CompoundStmt const* compoundStmt) +{ + if (ignoreLocation(compoundStmt)) + return true; + // these are kind of free form + if (!switchStmtBodies.empty() && switchStmtBodies.back() == compoundStmt) + return true; + + constexpr unsigned MAX = std::numeric_limits::max(); + unsigned column = MAX; + Stmt const* firstStmt = nullptr; + unsigned curLine = MAX; + unsigned prevLine = MAX; + SourceLocation prevEnd; + auto& SM = compiler.getSourceManager(); + for (auto i = compoundStmt->body_begin(); i != compoundStmt->body_end(); ++i) + { + auto stmt = *i; + auto const actualPrevEnd = prevEnd; + prevEnd = stmt->getEndLoc(); // compute early, before below `continue`s + + // these show up in macro expansions, not interesting + if (isa(stmt)) + continue; + // these are always weirdly indented + if (isa(stmt)) + continue; + + auto stmtLoc = stmt->getBeginLoc(); + + StringRef macroName; + bool partOfMacro = false; + if (SM.isMacroArgExpansion(stmtLoc) || SM.isMacroBodyExpansion(stmtLoc)) + { + partOfMacro = true; + macroName = Lexer::getImmediateMacroNameForDiagnostics( + stmtLoc, compiler.getSourceManager(), compiler.getLangOpts()); + // CPPUNIT_TEST_SUITE/CPPUNIT_TEST/CPPUNIT_TEST_SUITE_END work together, so the one is indented inside the other + if (macroName == "CPPUNIT_TEST_SUITE") + continue; + // similar thing in dbaccess/ + if (macroName == "DECL_PROP_IMPL") + continue; + // similar thing in forms/ + if (macroName == "DECL_IFACE_PROP_IMPL" || macroName == "DECL_BOOL_PROP_IMPL") + continue; + stmtLoc = SM.getExpansionRange(stmtLoc).getBegin(); + } + + // check for comment to the left of the statement + { + const char* p1 = SM.getCharacterData(stmtLoc); + --p1; + bool foundComment = false; + while (*p1 && *p1 != '\n') + { + if (*p1 == '/') + { + foundComment = true; + break; + } + --p1; + } + if (foundComment) + continue; + } + + bool invalid1 = false; + bool invalid2 = false; + unsigned tmpColumn = SM.getPresumedColumnNumber(stmtLoc, &invalid1); + unsigned tmpLine = SM.getPresumedLineNumber(stmtLoc, &invalid2); + if (invalid1 || invalid2) + continue; + prevLine = curLine; + curLine = tmpLine; + if (column == MAX) + { + column = tmpColumn; + firstStmt = stmt; + } + else if (curLine == prevLine) + { + // ignore multiple statements on same line + } + else if (column != tmpColumn) + { + if (containsPreprocessingConditionalInclusion(SourceRange( + locationAfterToken(compiler.getSourceManager().getExpansionLoc(actualPrevEnd)), + compiler.getSourceManager().getExpansionLoc(stmt->getBeginLoc())))) + continue; + report(DiagnosticsEngine::Warning, "statement mis-aligned compared to neighbours %0", + stmtLoc) + << macroName; + report(DiagnosticsEngine::Note, "measured against this one", firstStmt->getBeginLoc()); + //getParentStmt(compoundStmt)->dump(); + //stmt->dump(); + } + + if (!partOfMacro) + if (auto ifStmt = dyn_cast(stmt)) + { + auto bodyStmt = ifStmt->getThen(); + if (bodyStmt && !isa(bodyStmt)) + { + stmtLoc = bodyStmt->getBeginLoc(); + invalid1 = false; + invalid2 = false; + unsigned bodyColumn = SM.getPresumedColumnNumber(stmtLoc, &invalid1); + unsigned bodyLine = SM.getPresumedLineNumber(stmtLoc, &invalid2); + if (invalid1 || invalid2) + return true; + + if (bodyLine != tmpLine && bodyColumn <= tmpColumn) + report(DiagnosticsEngine::Warning, "if body should be indented", stmtLoc); + } + + auto elseStmt = ifStmt->getElse(); + if (elseStmt && !isa(elseStmt) && !isa(elseStmt)) + { + stmtLoc = elseStmt->getBeginLoc(); + invalid1 = false; + invalid2 = false; + unsigned elseColumn = SM.getPresumedColumnNumber(stmtLoc, &invalid1); + unsigned elseLine = SM.getPresumedLineNumber(stmtLoc, &invalid2); + if (invalid1 || invalid2) + return true; + if (elseLine != tmpLine && elseColumn <= tmpColumn) + report(DiagnosticsEngine::Warning, "else body should be indented", stmtLoc); + } + if (elseStmt && !isa(bodyStmt)) + { + stmtLoc = ifStmt->getElseLoc(); + invalid1 = false; + invalid2 = false; + unsigned elseColumn = SM.getPresumedColumnNumber(stmtLoc, &invalid1); + unsigned elseLine = SM.getPresumedLineNumber(stmtLoc, &invalid2); + if (invalid1 || invalid2) + return true; + if (elseLine != tmpLine && elseColumn != tmpColumn) + report(DiagnosticsEngine::Warning, "if and else not aligned", stmtLoc); + } + } + } + + return true; +} + +bool Indentation::VisitIfStmt(IfStmt const* ifStmt) +{ + if (ignoreLocation(ifStmt)) + return true; + + // TODO - ignore chained if statements for now + if (auto chained = ifStmt->getElse()) + chainedSet.insert(chained); + if (chainedSet.find(ifStmt) != chainedSet.end()) + return true; + + if (auto compoundStmt = dyn_cast_or_null(ifStmt->getThen())) + checkCompoundStmtBraces(ifStmt, compoundStmt); + // TODO - needs to be checked against the line that contains the else keyword, but not against the parent + // if (auto compoundStmt = dyn_cast_or_null(ifStmt->getElse())) + // checkCompoundStmtBraces(ifStmt, compoundStmt); + return true; +} + +bool Indentation::VisitForStmt(ForStmt const* forStmt) +{ + if (ignoreLocation(forStmt)) + return true; + if (chainedSet.find(forStmt) != chainedSet.end()) + return true; + if (auto compoundStmt = dyn_cast_or_null(forStmt->getBody())) + checkCompoundStmtBraces(forStmt, compoundStmt); + return true; +} + +bool Indentation::VisitWhileStmt(WhileStmt const* whileStmt) +{ + if (ignoreLocation(whileStmt)) + return true; + if (chainedSet.find(whileStmt) != chainedSet.end()) + return true; + if (auto compoundStmt = dyn_cast_or_null(whileStmt->getBody())) + checkCompoundStmtBraces(whileStmt, compoundStmt); + return true; +} + +bool Indentation::VisitDoStmt(DoStmt const* doStmt) +{ + if (ignoreLocation(doStmt)) + return true; + if (chainedSet.find(doStmt) != chainedSet.end()) + return true; + if (auto compoundStmt = dyn_cast_or_null(doStmt->getBody())) + checkCompoundStmtBraces(doStmt, compoundStmt); + return true; +} + +bool Indentation::VisitCXXForRangeStmt(CXXForRangeStmt const* cxxForRangeStmt) +{ + if (ignoreLocation(cxxForRangeStmt)) + return true; + if (chainedSet.find(cxxForRangeStmt) != chainedSet.end()) + return true; + if (auto compoundStmt = dyn_cast_or_null(cxxForRangeStmt->getBody())) + checkCompoundStmtBraces(cxxForRangeStmt, compoundStmt); + return true; +} + +void Indentation::checkCompoundStmtBraces(const Stmt* parentStmt, const CompoundStmt* compoundStmt) +{ + auto& SM = compiler.getSourceManager(); + bool invalid1 = false; + bool invalid2 = false; + + auto parentBeginLoc = parentStmt->getBeginLoc(); + unsigned parentColumn = SM.getPresumedColumnNumber(parentBeginLoc, &invalid1); + if (invalid1) + return; + + auto startBraceLoc = compoundStmt->getLBracLoc(); + auto endBraceLoc = compoundStmt->getRBracLoc(); + unsigned beginColumn = SM.getPresumedColumnNumber(startBraceLoc, &invalid1); + unsigned beginLine = SM.getPresumedLineNumber(startBraceLoc, &invalid2); + if (invalid1 || invalid2) + return; + unsigned endColumn = SM.getPresumedColumnNumber(endBraceLoc, &invalid1); + unsigned endLine = SM.getPresumedLineNumber(endBraceLoc, &invalid2); + if (invalid1 || invalid2) + return; + if (beginLine == endLine) + return; + + // check for code to the left of the starting brace + bool foundCodeToLeft = false; + { + const char* p1 = SM.getCharacterData(startBraceLoc); + --p1; + while (*p1 && *p1 != '\n') + { + if (*p1 != ' ') + { + foundCodeToLeft = true; + break; + } + --p1; + } + } + + // if we found code to the left of the start brace, that means the end-brace needs + // to line up with the start of the parent statement + if (foundCodeToLeft) + { + if (parentColumn != endColumn) + { + report(DiagnosticsEngine::Warning, "end brace not aligned with beginning of statement", + endBraceLoc); + report(DiagnosticsEngine::Note, "statement beginning here", parentBeginLoc); + } + return; + } + + if (parentColumn != beginColumn) + { + report(DiagnosticsEngine::Warning, + "start brace not aligned with beginning of parent statement", startBraceLoc); + report(DiagnosticsEngine::Note, "statement beginning here", parentBeginLoc); + } + else if (beginColumn != endColumn) + { + report(DiagnosticsEngine::Warning, "start and end brace not aligned", endBraceLoc); + report(DiagnosticsEngine::Note, "start brace here", startBraceLoc); + } + + /** now check that lines inside the compoundstmt are indented */ + if (!compoundStmt->size()) + return; + auto firstStmt = compoundStmt->body_front(); + if (isa(firstStmt)) + return; + auto firstStmtLoc = firstStmt->getBeginLoc(); + unsigned firstStmtBeginColumn = SM.getPresumedColumnNumber(firstStmtLoc, &invalid1); + if (invalid1) + return; + if (firstStmtBeginColumn > beginColumn) + return; + StringRef fn = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(firstStmtLoc)); + // this is doing code generation, so the weird layout is deliberate + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/core/opencl/")) + return; + report(DiagnosticsEngine::Warning, "body inside brace not indented", firstStmtLoc); +} + +bool Indentation::VisitSwitchStmt(SwitchStmt const* switchStmt) +{ + if (ignoreLocation(switchStmt)) + return true; + + constexpr unsigned MAX = std::numeric_limits::max(); + unsigned column = MAX; + Stmt const* firstStmt = nullptr; + unsigned curLine = MAX; + unsigned prevLine = MAX; + auto& SM = compiler.getSourceManager(); + auto compoundStmt = dyn_cast(switchStmt->getBody()); + if (!compoundStmt) + return true; + for (auto i = compoundStmt->body_begin(); i != compoundStmt->body_end(); ++i) + { + Stmt const* caseStmt = dyn_cast(*i); + if (!caseStmt) + caseStmt = dyn_cast(*i); + if (!caseStmt) + continue; + + auto stmtLoc = caseStmt->getBeginLoc(); + + bool invalid1 = false; + bool invalid2 = false; + unsigned tmpColumn = SM.getPresumedColumnNumber(stmtLoc, &invalid1); + unsigned tmpLine = SM.getPresumedLineNumber(stmtLoc, &invalid2); + if (invalid1 || invalid2) + continue; + prevLine = curLine; + curLine = tmpLine; + if (column == MAX) + { + column = tmpColumn; + firstStmt = caseStmt; + } + else if (curLine == prevLine) + { + // ignore multiple statements on same line + } + else if (column != tmpColumn) + { + // disable this for now, ends up touching some very large switch statements in sw/ and sc/ + (void)firstStmt; + // report(DiagnosticsEngine::Warning, "statement mis-aligned compared to neighbours", + // stmtLoc); + // report(DiagnosticsEngine::Note, "measured against this one", + // firstStmt->getBeginLoc()); + //getParentStmt(compoundStmt)->dump(); + //stmt->dump(); + } + } + return true; +} + +loplugin::Plugin::Registration indentation("indentation"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/inlinefields.cxx b/compilerplugins/clang/inlinefields.cxx new file mode 100644 index 000000000..1573e8d52 --- /dev/null +++ b/compilerplugins/clang/inlinefields.cxx @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include "plugin.hxx" +#include "compat.hxx" + +/** +if a field is +- a pointer +- only assigned to in the constructor via a new expression +- unconditionally deleted in the destructor +then it can probably just be allocated inline in the parent object + +TODO check for cases where the pointer is passed by non-const reference + +Be warned that it produces around 5G of log file. + +The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='inlinefields' check + $ ./compilerplugins/clang/inlinefields.py + +and then + $ for dir in *; do make FORCE_COMPILE=all UPDATE_FILES=$dir COMPILER_PLUGIN_TOOL='inlinefieldsremove' $dir; done +to auto-remove the method declarations + +Note that the actual process may involve a fair amount of undoing, hand editing, and general messing around +to get it to work :-) + +*/ + +namespace { + +struct MyFieldInfo +{ + std::string parentClass; + std::string fieldName; + std::string sourceLocation; +}; +bool operator < (const MyFieldInfo &lhs, const MyFieldInfo &rhs) +{ + return std::tie(lhs.parentClass, lhs.fieldName) + < std::tie(rhs.parentClass, rhs.fieldName); +} + + +// try to limit the voluminous output a little +static std::set excludedSet; +static std::set definitionSet; +static std::set deletedInDestructorSet; +static std::set newedInConstructorSet; + +class InlineFields: + public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit InlineFields(loplugin::InstantiationData const & data): + Plugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + std::string output; + for (const MyFieldInfo & s : definitionSet) + output += "definition:\t" + s.parentClass + "\t" + s.fieldName + "\t" + s.sourceLocation + "\n"; + for (const MyFieldInfo & s : excludedSet) + output += "excluded:\t" + s.parentClass + "\t" + s.fieldName + "\n"; + for (const MyFieldInfo & s : deletedInDestructorSet) + output += "deletedInDestructor:\t" + s.parentClass + "\t" + s.fieldName + "\n"; + for (const MyFieldInfo & s : newedInConstructorSet) + output += "newedInConstructor:\t" + s.parentClass + "\t" + s.fieldName + "\n"; + std::ofstream myfile; + myfile.open( WORKDIR "/loplugin.inlinefields.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + + bool shouldVisitTemplateInstantiations () const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitFieldDecl( const FieldDecl* ); + bool VisitCXXConstructorDecl( const CXXConstructorDecl* ); + bool VisitCXXDeleteExpr( const CXXDeleteExpr* ); + bool VisitBinaryOperator( const BinaryOperator* ); +private: + MyFieldInfo niceName(const FieldDecl*); + void checkTouched(const FieldDecl* fieldDecl, const Expr* memberExpr); +}; + +MyFieldInfo InlineFields::niceName(const FieldDecl* fieldDecl) +{ + MyFieldInfo aInfo; + + const RecordDecl* recordDecl = fieldDecl->getParent(); + + if (const CXXRecordDecl* cxxRecordDecl = dyn_cast(recordDecl)) + { + if (cxxRecordDecl->getTemplateInstantiationPattern()) + cxxRecordDecl = cxxRecordDecl->getTemplateInstantiationPattern(); + aInfo.parentClass = cxxRecordDecl->getQualifiedNameAsString(); + } + else + aInfo.parentClass = recordDecl->getQualifiedNameAsString(); + + aInfo.fieldName = fieldDecl->getNameAsString(); + + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( fieldDecl->getLocation() ); + StringRef name = getFilenameOfLocation(expansionLoc); + aInfo.sourceLocation = std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(aInfo.sourceLocation); + + return aInfo; +} + +bool InlineFields::VisitFieldDecl( const FieldDecl* fieldDecl ) +{ + fieldDecl = fieldDecl->getCanonicalDecl(); + if (ignoreLocation( fieldDecl )) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocation()))) { + return true; + } + QualType type = fieldDecl->getType(); + if (!type->isPointerType()) + return true; + definitionSet.insert(niceName(fieldDecl)); + return true; +} + +bool InlineFields::VisitCXXConstructorDecl( const CXXConstructorDecl* decl ) +{ + if( ignoreLocation( decl ) ) + return true; + if (decl->isCopyOrMoveConstructor()) + return true; + for(auto it = decl->init_begin(); it != decl->init_end(); ++it) + { + const CXXCtorInitializer* init = *it; + const FieldDecl* fieldDecl = init->getMember(); + if( !fieldDecl || !fieldDecl->getType()->isPointerType() ) + continue; + auto e = init->getInit(); + if (auto parentListExpr = dyn_cast(e)) + e = parentListExpr->getExpr(0); + e = e->IgnoreParenImpCasts(); + if( isa(e) ) + newedInConstructorSet.insert(niceName(fieldDecl)); + else if( isa(e) || isa(e)) + ; // ignore + else + excludedSet.insert(niceName(fieldDecl)); + } + return true; +} + +static bool isSameParent(const CXXMethodDecl* cxxMethodDecl, const FieldDecl* fieldDecl) +{ + return cxxMethodDecl->getParent() == dyn_cast(fieldDecl->getParent()); +} + +bool InlineFields::VisitBinaryOperator(const BinaryOperator * binaryOp) +{ + if (binaryOp->getOpcode() != BO_Assign) { + return true; + } + if( ignoreLocation( binaryOp ) ) + return true; + auto memberExpr = dyn_cast(binaryOp->getLHS()); + if (!memberExpr) + return true; + auto fieldDecl = dyn_cast(memberExpr->getMemberDecl()); + if (!fieldDecl || !fieldDecl->getType()->isPointerType()) { + return true; + } + const FunctionDecl* parentFunction = getParentFunctionDecl(binaryOp); + if (!parentFunction) { + return true; + } + // if the field is being assigned from outside its own constructor or destructor, exclude + auto constructorDecl = dyn_cast(parentFunction); + if (constructorDecl && isSameParent(constructorDecl, fieldDecl)) { + if( isa(binaryOp->getRHS()) ) + newedInConstructorSet.insert(niceName(fieldDecl)); + else { + excludedSet.insert(niceName(fieldDecl)); + std::cout << "assign in constructor:" << std::endl; + binaryOp->getRHS()->dump(); + } + return true; + } + auto destructorDecl = dyn_cast(parentFunction); + if (destructorDecl && isSameParent(destructorDecl, fieldDecl)) { + auto e = binaryOp->getRHS()->IgnoreParenImpCasts(); + if( !isa(e) && !isa(e)) { + excludedSet.insert(niceName(fieldDecl)); + std::cout << "assign in destructor:" << std::endl; + e->dump(); + } + return true; + } + excludedSet.insert(niceName(fieldDecl)); + return true; +} + +bool InlineFields::VisitCXXDeleteExpr(const CXXDeleteExpr * deleteExpr) +{ + if( ignoreLocation( deleteExpr ) ) + return true; + auto memberExpr = dyn_cast(deleteExpr->getArgument()->IgnoreParenImpCasts()); + if (!memberExpr) + return true; + auto fieldDecl = dyn_cast(memberExpr->getMemberDecl()); + if (!fieldDecl || !fieldDecl->getType()->isPointerType()) { + return true; + } + // TODO for some reason, this part is not working properly, it doesn't find the parent + // function for delete statements properly + const FunctionDecl* parentFunction = getParentFunctionDecl(deleteExpr); + if (!parentFunction) { + return true; + } + auto destructorDecl = dyn_cast(parentFunction); + if (destructorDecl && isSameParent(destructorDecl, fieldDecl)) { + deletedInDestructorSet.insert(niceName(fieldDecl)); + return true; + } + excludedSet.insert(niceName(fieldDecl)); + return true; +} + +loplugin::Plugin::Registration< InlineFields > X("inlinefields", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/inlinefields.py b/compilerplugins/clang/inlinefields.py new file mode 100755 index 000000000..1a0dbda34 --- /dev/null +++ b/compilerplugins/clang/inlinefields.py @@ -0,0 +1,73 @@ +#!/usr/bin/python + +import sys +import re +import io + +definitionToSourceLocationMap = dict() # dict of tuple(parentClass, fieldName) to sourceLocation +definitionSet = set() +excludedSet = set() +deletedInDestructorSet = set() +newedInConstructorSet = set(); + +# clang does not always use exactly the same numbers in the type-parameter vars it generates +# so I need to substitute them to ensure we can match correctly. +normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") +def normalizeTypeParams( line ): + return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) + +# reading as binary (since we known it is pure ascii) is much faster than reading as unicode +with io.open("workdir/loplugin.inlinefields.log", "rb", buffering=1024*1024) as txt: + for line in txt: + tokens = line.strip().split("\t") + if tokens[0] == "definition:": + parentClass = normalizeTypeParams(tokens[1]) + fieldName = normalizeTypeParams(tokens[2]) + sourceLocation = tokens[3] + fieldInfo = (parentClass, fieldName) + definitionSet.add(fieldInfo) + definitionToSourceLocationMap[fieldInfo] = sourceLocation + elif tokens[0] == "excluded:": + parentClass = normalizeTypeParams(tokens[1]) + fieldName = normalizeTypeParams(tokens[2]) + fieldInfo = (parentClass, fieldName) + excludedSet.add(fieldInfo) + elif tokens[0] == "deletedInDestructor:": + parentClass = normalizeTypeParams(tokens[1]) + fieldName = normalizeTypeParams(tokens[2]) + fieldInfo = (parentClass, fieldName) + deletedInDestructorSet.add(fieldInfo) + elif tokens[0] == "newedInConstructor:": + parentClass = normalizeTypeParams(tokens[1]) + fieldName = normalizeTypeParams(tokens[2]) + fieldInfo = (parentClass, fieldName) + newedInConstructorSet.add(fieldInfo) + else: + print( "unknown line: " + line) + +tmp1list = list() +for d in definitionSet: +# TODO see comment in InlineFields::VisitCXXDeleteExpr +# if d in excludedSet or d not in deletedInDestructorSet or d not in newedInConstructorSet: + if d in excludedSet or d not in newedInConstructorSet: + continue + srcLoc = definitionToSourceLocationMap[d]; + tmp1list.append((d[0] + " " + d[1], srcLoc)) + +# sort results by filename:lineno +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[1]) + [v[0]] +tmp1list.sort(key=lambda v: v_sort_key(v)) + +# print out the results +with open("loplugin.inlinefields.report", "wt") as f: + for v in tmp1list: + f.write(v[1] + "\n") + f.write(" " + v[0] + "\n") + + diff --git a/compilerplugins/clang/inlinesimplememberfunctions.cxx b/compilerplugins/clang/inlinesimplememberfunctions.cxx new file mode 100644 index 000000000..760094b5a --- /dev/null +++ b/compilerplugins/clang/inlinesimplememberfunctions.cxx @@ -0,0 +1,294 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include "plugin.hxx" + +// Methods that purely return a local field should be declared in the header and be declared inline. +// So that the compiler can elide the function call and turn it into a simple fixed-offset-load instruction. + +namespace { + +class InlineSimpleMemberFunctions: + public loplugin::FilteringRewritePlugin +{ +public: + explicit InlineSimpleMemberFunctions(loplugin::InstantiationData const & data): FilteringRewritePlugin(data) {} + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXMethodDecl(const CXXMethodDecl * decl); +private: + bool rewrite(const CXXMethodDecl * functionDecl); +}; + +static bool oneAndOnlyOne(clang::Stmt::const_child_range range) { + if (range.begin() == range.end()) { + return false; + } + if (++range.begin() != range.end()) { + return false; + } + return true; +} + + +bool InlineSimpleMemberFunctions::VisitCXXMethodDecl(const CXXMethodDecl * functionDecl) { + if (ignoreLocation(functionDecl)) { + return true; + } + // no point in doing virtual methods, the compiler always has to generate a vtable entry and a method + if (functionDecl->isVirtual()) { + return true; + } + if (functionDecl->getTemplatedKind() != FunctionDecl::TK_NonTemplate) { + return true; + } + if (!functionDecl->isInstance()) { + return true; + } + if (!functionDecl->isOutOfLine()) { + return true; + } + if( !functionDecl->hasBody()) { + return true; + } + if( functionDecl->isInlineSpecified()) { + return true; + } + if( functionDecl->getCanonicalDecl()->isInlineSpecified()) { + return true; + } + if( functionDecl->getNameAsString().find("Impl") != std::string::npos) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) { + return true; + } + // ignore stuff like: + // template E * Sequence::begin() { return getArray(); } + if( functionDecl->getParent()->getDescribedClassTemplate() != nullptr ) { + return true; + } + + /* + The chain here looks like + CompoundStmt + ReturnStmt + other stuff + CXXThisExpr + */ + + const CompoundStmt* compoundStmt = dyn_cast< CompoundStmt >( functionDecl->getBody() ); + if (compoundStmt == nullptr) { + return true; + } + if (compoundStmt->body_begin() == compoundStmt->body_end()) { + return true; + } + + + const Stmt* childStmt = *compoundStmt->child_begin(); + + if (dyn_cast( childStmt ) == nullptr) { + return true; + } + if (!oneAndOnlyOne(childStmt->children())) { + return true; + } + + + /* Don't warn if we see a method definition like + X X::a() { + return *this; + } + which translates to: + CompoundStmt + ReturnStmt + ImplicitCastExpr + UnaryOperator + CXXThisExpr + or: + CompoundStmt + ReturnStmt + UnaryOperator + CXXThisExpr + */ + childStmt = *childStmt->child_begin(); + if (dyn_cast( childStmt ) != nullptr + && oneAndOnlyOne( childStmt->children() )) + { + const Stmt* childStmt2 = *childStmt->child_begin(); + if (dyn_cast( childStmt2 ) != nullptr + && oneAndOnlyOne(childStmt2->children())) + { + childStmt2 = *childStmt2->child_begin(); + if (dyn_cast( childStmt2 ) != nullptr + && childStmt2->children().begin() == childStmt2->children().end()) + { + return true; + } + } + } + if (dyn_cast( childStmt ) != nullptr + && oneAndOnlyOne( childStmt->children() )) + { + const Stmt* childStmt2 = *childStmt->child_begin(); + if (dyn_cast( childStmt2 ) != nullptr + && childStmt2->children().begin() == childStmt2->children().end()) + { + return true; + } + } + + /* look for a chains like: + CompoundStmt + ReturnStmt + stuff + CXXThisExpr + */ + childStmt = *(*compoundStmt->child_begin())->child_begin(); + while (1) { + if (dyn_cast( childStmt ) != nullptr) + return true; + if (dyn_cast( childStmt ) != nullptr) + return true; + if (dyn_cast( childStmt ) != nullptr) + return true; + if (dyn_cast( childStmt ) != nullptr) + return true; + if (dyn_cast( childStmt ) != nullptr) + return true; + // exclude methods that return fields on incomplete types .e.g the pImpl pattern + const MemberExpr* memberExpr = dyn_cast( childStmt ); + if (memberExpr != nullptr && memberExpr->getMemberDecl()) { + const FieldDecl* fieldDecl = dyn_cast(memberExpr->getMemberDecl()); + if (fieldDecl != nullptr) + { + // yes, a little bit of a hack. However, it is quite hard to determine if the method + // in question is accessing a field via a pImpl pattern. + if (fieldDecl->getType()->isIncompleteType()) + return true; + if (fieldDecl->getNameAsString().find("Impl") != std::string::npos) + return true; + if (fieldDecl->getNameAsString().find("pImp") != std::string::npos) + return true; + // somewhere in VCL + if (fieldDecl->getNameAsString().find("mpGlobalSyncData") != std::string::npos) + return true; + std::string s = fieldDecl->getType().getAsString(); + if (s.find("Impl") != std::string::npos || s.find("pImp") != std::string::npos || s.find("Internal") != std::string::npos) + return true; + } + } + if (dyn_cast( childStmt ) != nullptr) { + if (!rewrite(functionDecl)) + { + report( + DiagnosticsEngine::Warning, + "inlinesimpleaccessmethods", + functionDecl->getSourceRange().getBegin()) + << functionDecl->getSourceRange(); + // display the location of the class member declaration so I don't have to search for it by hand + report( + DiagnosticsEngine::Note, + "inlinesimpleaccessmethods", + functionDecl->getCanonicalDecl()->getSourceRange().getBegin()) + << functionDecl->getCanonicalDecl()->getSourceRange(); + } + return true; + } + if ( childStmt->children().begin() == childStmt->children().end() ) + return true; + childStmt = *childStmt->child_begin(); + } + return true; +} + +static std::string ReplaceString(std::string subject, const std::string& search, + const std::string& replace) { + size_t pos = 0; + while ((pos = subject.find(search, pos)) != std::string::npos) { + subject.replace(pos, search.length(), replace); + pos += replace.length(); + } + return subject; +} + +bool InlineSimpleMemberFunctions::rewrite(const CXXMethodDecl * functionDecl) { + if (rewriter == nullptr) { + return false; + } + // Only rewrite declarations in include files if a + // definition is also seen, to avoid compilation of a + // definition (in a main file only processed later) to fail + // with a "mismatch" error before the rewriter had a chance + // to act upon the definition. + if (!compiler.getSourceManager().isInMainFile( + compiler.getSourceManager().getSpellingLoc( + functionDecl->getNameInfo().getLoc()))) + { + return false; + } + + const char *p1, *p2; + + // get the function body contents + p1 = compiler.getSourceManager().getCharacterData( functionDecl->getBody()->getBeginLoc() ); + p2 = compiler.getSourceManager().getCharacterData( functionDecl->getBody()->getEndLoc() ); + std::string s1( p1, p2 - p1 + 1); + + /* we can't safely move around stuff containing comments, we mess up the resulting code */ + if ( s1.find("/*") != std::string::npos || s1.find("//") != std::string::npos ) { + return false; + } + + // strip linefeeds and any double-spaces, so we have a max of one space between tokens + s1 = ReplaceString(s1, "\r", ""); + s1 = ReplaceString(s1, "\n", ""); + s1 = ReplaceString(s1, "\t", " "); + s1 = ReplaceString(s1, " ", " "); + s1 = ReplaceString(s1, " ", " "); + s1 = ReplaceString(s1, " ", " "); + s1 = " " + s1; + + // scan from the end of the function's body through the trailing whitespace, so we can do a nice clean remove +// commented out because for some reason it will sometimes chomp an extra token +// SourceLocation endOfRemoveLoc = functionDecl->getBody()->getLocEnd(); +// for (;;) { +// endOfRemoveLoc = endOfRemoveLoc.getLocWithOffset(1); +// p1 = compiler.getSourceManager().getCharacterData( endOfRemoveLoc ); +// if (*p1 != ' ' && *p1 != '\r' && *p1 != '\n' && *p1 != '\t') +// break; +// } + + // remove the function's out of line body and declaration + RewriteOptions opts; + opts.RemoveLineIfEmpty = true; + if (!removeText(SourceRange(functionDecl->getBeginLoc(), functionDecl->getBody()->getEndLoc()), opts)) { + return false; + } + + // scan forward until we find the semicolon + const FunctionDecl * canonicalDecl = functionDecl->getCanonicalDecl(); + p1 = compiler.getSourceManager().getCharacterData( canonicalDecl->getEndLoc() ); + p2 = ++p1; + while (*p2 != 0 && *p2 != ';') p2++; + + // insert the function body into the inline function definition (i.e. the one inside the class definition) + return replaceText(canonicalDecl->getEndLoc().getLocWithOffset(p2 - p1 + 1), 1, s1); +} + +loplugin::Plugin::Registration< InlineSimpleMemberFunctions > X("inlinesimplememberfunctions"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/inlinevisible.cxx b/compilerplugins/clang/inlinevisible.cxx new file mode 100644 index 000000000..eb3e249f5 --- /dev/null +++ b/compilerplugins/clang/inlinevisible.cxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include + +#include "clang/AST/Attr.h" +#include "clang/Sema/SemaInternal.h" // warn_unused_function + +#include "plugin.hxx" + +namespace { + +class InlineVisible: + public loplugin::FilteringPlugin +{ +public: + explicit InlineVisible(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitFunctionDecl(FunctionDecl const * decl); +}; + +bool InlineVisible::VisitFunctionDecl(FunctionDecl const * decl) { + if (!ignoreLocation(decl) && decl->isInlineSpecified()) { + VisibilityAttr * attr = decl->getAttr(); + if (attr != nullptr && attr->getVisibility() == VisibilityAttr::Default) + { + report( + DiagnosticsEngine::Warning, + ("Function explicitly declared both inline and " + " visibility=default"), + decl->getLocation()) + << decl->getSourceRange(); + } + } + return true; +} + +loplugin::Plugin::Registration inlinevisible("inlinevisible"); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/intvsfloat.cxx b/compilerplugins/clang/intvsfloat.cxx new file mode 100644 index 000000000..771e2bca0 --- /dev/null +++ b/compilerplugins/clang/intvsfloat.cxx @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" +#include "check.hxx" +#include + +/** + +TODO multiplying/otherop on a combination of a float and int, and then truncating to int. like this: + float getRotation() {} + int moRotation = -F_PI180 * 90 * getRotation(); +*/ +namespace +{ +class IntVsFloat : public loplugin::FilteringPlugin +{ +public: + explicit IntVsFloat(loplugin::InstantiationData const& data) + : loplugin::FilteringPlugin(data) + { + } + + void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitVarDecl(VarDecl const*); + bool VisitBinaryOperator(BinaryOperator const*); + +private: + llvm::Optional getExprValue(Expr const* expr); +}; + +bool IntVsFloat::VisitVarDecl(VarDecl const* varDecl) +{ + if (ignoreLocation(varDecl->getLocation())) + return true; + auto init = varDecl->getInit(); + if (!init) + return true; + init = init->IgnoreImpCasts(); + if (varDecl->getType()->isFloatingType()) + return true; + // init->dump(); + llvm::Optional d = getExprValue(init); + if (!d) + return true; + if (static_cast(*d) == *d) + return true; + report(DiagnosticsEngine::Warning, "assigning constant float value to int truncates data", + init->getBeginLoc()) + << init->getSourceRange(); + + return true; +} + +bool IntVsFloat::VisitBinaryOperator(BinaryOperator const* op) +{ + if (op->getOpcode() != BO_EQ) + { + return true; + } + if (ignoreLocation(op->getBeginLoc())) + return true; + auto lhs = op->getLHS()->IgnoreImpCasts(); + auto rhs = op->getRHS()->IgnoreImpCasts(); + if (!lhs->getType()->isFloatingType()) + std::swap(lhs, rhs); + if (!lhs->getType()->isFloatingType()) + return true; + if (rhs->getType()->isFloatingType()) + return true; + llvm::Optional d = getExprValue(lhs); + if (!d) + return true; + if (static_cast(*d) == *d) + return true; + report(DiagnosticsEngine::Warning, "comparing integer to float constant, can never be true", + op->getBeginLoc()) + << op->getSourceRange(); + return true; +} + +llvm::Optional IntVsFloat::getExprValue(Expr const* expr) +{ + // Of the available clang Evaluate* APIs, this is the __only__ one that produces useful output + // (as of 17 Aug 2018 checkout of clang, ie. towards clang 7) + + if (expr->isValueDependent()) + return llvm::Optional(); + Expr::EvalResult evalResult; + if (!expr->EvaluateAsRValue(evalResult, compiler.getASTContext())) + return llvm::Optional(); + if (!evalResult.Val.isFloat()) + return llvm::Optional(); + llvm::APFloat floatResult = evalResult.Val.getFloat(); + bool losesInfo; + floatResult.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &losesInfo); + + double d = floatResult.convertToDouble(); + return d; +} + +loplugin::Plugin::Registration intvsfloat("intvsfloat"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/literaltoboolconversion.cxx b/compilerplugins/clang/literaltoboolconversion.cxx new file mode 100644 index 000000000..9894daec5 --- /dev/null +++ b/compilerplugins/clang/literaltoboolconversion.cxx @@ -0,0 +1,232 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include + +#include "clang/Lex/Lexer.h" + +#include "compat.hxx" +#include "plugin.hxx" + +namespace { + +class LiteralToBoolConversion: + public loplugin::FilteringRewritePlugin +{ +public: + explicit LiteralToBoolConversion(loplugin::InstantiationData const & data): + FilteringRewritePlugin(data) {} + + virtual void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitImplicitCastExpr(ImplicitCastExpr const * expr); + + bool PreTraverseLinkageSpecDecl(LinkageSpecDecl * decl); + bool PostTraverseLinkageSpecDecl(LinkageSpecDecl * decl, bool); + bool TraverseLinkageSpecDecl(LinkageSpecDecl * decl); + +private: + bool isFromCIncludeFile(SourceLocation spellingLocation) const; + + bool isSharedCAndCppCode(SourceLocation location) const; + + void handleImplicitCastSubExpr( + ImplicitCastExpr const * castExpr, Expr const * subExpr); + + unsigned int externCContexts_ = 0; +}; + +bool LiteralToBoolConversion::VisitImplicitCastExpr( + ImplicitCastExpr const * expr) +{ + if (ignoreLocation(expr)) { + return true; + } + if (!expr->getType()->isBooleanType()) { + return true; + } + handleImplicitCastSubExpr(expr, expr->getSubExpr()); + return true; +} + +bool LiteralToBoolConversion::PreTraverseLinkageSpecDecl(LinkageSpecDecl *) { + assert(externCContexts_ != std::numeric_limits::max()); //TODO + ++externCContexts_; + return true; +} + +bool LiteralToBoolConversion::PostTraverseLinkageSpecDecl(LinkageSpecDecl *, bool) { + assert(externCContexts_ != 0); + --externCContexts_; + return true; +} + +bool LiteralToBoolConversion::TraverseLinkageSpecDecl(LinkageSpecDecl * decl) { + PreTraverseLinkageSpecDecl(decl); + bool ret = RecursiveASTVisitor::TraverseLinkageSpecDecl(decl); + PostTraverseLinkageSpecDecl(decl, ret); + return ret; +} + +bool LiteralToBoolConversion::isFromCIncludeFile( + SourceLocation spellingLocation) const +{ + return !compiler.getSourceManager().isInMainFile(spellingLocation) + && (StringRef( + compiler.getSourceManager().getPresumedLoc(spellingLocation) + .getFilename()) + .endswith(".h")); +} + +bool LiteralToBoolConversion::isSharedCAndCppCode(SourceLocation location) const +{ + // Assume that code is intended to be shared between C and C++ if it comes + // from an include file ending in .h, and is either in an extern "C" context + // or the body of a macro definition: + return + isFromCIncludeFile(compiler.getSourceManager().getSpellingLoc(location)) + && (externCContexts_ != 0 + || compiler.getSourceManager().isMacroBodyExpansion(location)); +} + +void LiteralToBoolConversion::handleImplicitCastSubExpr( + ImplicitCastExpr const * castExpr, Expr const * subExpr) +{ + Expr const * expr2 = subExpr; + // track sub-expr with potential parens, to e.g. rewrite all of expanded + // + // #define sal_False ((sal_Bool)0) + // + // including the parens + subExpr = expr2->IgnoreParenCasts(); + for (;;) { + BinaryOperator const * op = dyn_cast(subExpr); + if (op == nullptr || op->getOpcode() != BO_Comma) { + break; + } + expr2 = op->getRHS(); + subExpr = expr2->IgnoreParenCasts(); + } + if (subExpr->getType()->isBooleanType()) { + return; + } + ConditionalOperator const * op = dyn_cast(subExpr); + if (op != nullptr) { + handleImplicitCastSubExpr(castExpr, op->getTrueExpr()); + handleImplicitCastSubExpr(castExpr, op->getFalseExpr()); + return; + } + if (!subExpr->isValueDependent()) { + if (auto const res = subExpr->getIntegerConstantExpr(compiler.getASTContext())) { + if (res->getLimitedValue() <= 1) + { + SourceLocation loc { subExpr->getBeginLoc() }; + while (compiler.getSourceManager().isMacroArgExpansion(loc)) { + loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc); + } + if (compiler.getSourceManager().isMacroBodyExpansion(loc)) { + StringRef name { Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()) }; + if (name == "sal_False" || name == "sal_True") { + loc = compat::getImmediateExpansionRange(compiler.getSourceManager(), loc) + .first; + } + if (isSharedCAndCppCode(loc)) { + return; + } + } + } + } + } + if (isa(subExpr)) { + SourceLocation loc { subExpr->getBeginLoc() }; + if (compiler.getSourceManager().isMacroArgExpansion(loc) + && (Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()) + == "assert")) + { + return; + } + } + if (isa(subExpr) || isa(subExpr) + || isa(subExpr) || isa(subExpr) + || isa(subExpr)) + { + bool bRewritten = false; + if (rewriter != nullptr) { + SourceLocation loc { compiler.getSourceManager().getExpansionLoc( + expr2->getBeginLoc()) }; + if (compiler.getSourceManager().getExpansionLoc(expr2->getEndLoc()) + == loc) + { + char const * s = compiler.getSourceManager().getCharacterData( + loc); + unsigned n = Lexer::MeasureTokenLength( + expr2->getEndLoc(), compiler.getSourceManager(), + compiler.getLangOpts()); + std::string tok { s, n }; + if (tok == "sal_False" || tok == "0") { + bRewritten = replaceText( + compiler.getSourceManager().getExpansionLoc( + expr2->getBeginLoc()), + n, "false"); + } else if (tok == "sal_True" || tok == "1") { + bRewritten = replaceText( + compiler.getSourceManager().getExpansionLoc( + expr2->getBeginLoc()), + n, "true"); + } + } + } + if (!bRewritten) { + report( + DiagnosticsEngine::Warning, + "implicit conversion (%0) of literal of type %1 to %2", + expr2->getBeginLoc()) + << castExpr->getCastKindName() << subExpr->getType() + << castExpr->getType() << expr2->getSourceRange(); + } + } else if (subExpr->isNullPointerConstant( + compiler.getASTContext(), Expr::NPC_ValueDependentIsNull) + > Expr::NPCK_ZeroExpression) + { + // The test above originally checked for != Expr::NPCK_NotNull, but in non-C++11 + // mode we can get also Expr::NPCK_ZeroExpression inside templates, even though + // the expression is actually not a null pointer. Clang bug or C++98 misfeature? + // See Clang's NPCK_ZeroExpression declaration and beginning of isNullPointerConstant(). + static_assert( Expr::NPCK_NotNull == 0 && Expr::NPCK_ZeroExpression == 1, "Clang API change" ); + report( + DiagnosticsEngine::Warning, + ("implicit conversion (%0) of null pointer constant of type %1 to" + " %2"), + expr2->getBeginLoc()) + << castExpr->getCastKindName() << subExpr->getType() + << castExpr->getType() << expr2->getSourceRange(); + } else if (!subExpr->isValueDependent()) { + if (auto const res = subExpr->getIntegerConstantExpr(compiler.getASTContext())) { + report( + DiagnosticsEngine::Warning, + ("implicit conversion (%0) of integer constant expression of type" + " %1 with value %2 to %3"), + expr2->getBeginLoc()) + << castExpr->getCastKindName() << subExpr->getType() + << compat::toString(*res, 10) << castExpr->getType() + << expr2->getSourceRange(); + } + } +} + +loplugin::Plugin::Registration literaltoboolconversion("literaltoboolconversion"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS diff --git a/compilerplugins/clang/logexceptionnicely.cxx b/compilerplugins/clang/logexceptionnicely.cxx new file mode 100644 index 000000000..6cc66fdf0 --- /dev/null +++ b/compilerplugins/clang/logexceptionnicely.cxx @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include +#include + +namespace loplugin +{ +/* +Check that we are using exceptionToString when printing exceptions inside SAL_WARN, so that we +get nicely formatted exception details in our logs. +*/ + +class LogExceptionNicely : public loplugin::FilteringPlugin +{ + std::unordered_set m_visited; + +public: + LogExceptionNicely(const InstantiationData& data) + : FilteringPlugin(data) + { + } + + bool preRun() + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + // these are below tools in the module hierarchy, so we can't use the pretty printing + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/cppuhelper/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/ucbhelper/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/binaryurp/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/comphelper/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/io/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/javaunohelper/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/stoc/")) + return false; + // can't do that here, don't have an Any + if (loplugin::hasPathnamePrefix(fn, SRCDIR + "/connectivity/source/drivers/hsqldb/HStorageMap.cxx")) + return false; + return true; + } + + void run() + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + static bool BaseCheckNotExceptionSubclass(const CXXRecordDecl* BaseDefinition) + { + if (!BaseDefinition) + return true; + auto tc = loplugin::TypeCheck(BaseDefinition); + if (tc.Class("Exception") + .Namespace("uno") + .Namespace("star") + .Namespace("sun") + .Namespace("com") + .GlobalNamespace()) + return false; + return true; + } + + bool isDerivedFromException(const CXXRecordDecl* decl) + { + if (!decl || !decl->hasDefinition()) + return false; + auto tc = loplugin::TypeCheck(decl); + if (tc.Class("Exception") + .Namespace("uno") + .Namespace("star") + .Namespace("sun") + .Namespace("com") + .GlobalNamespace()) + return true; + if ( // not sure what hasAnyDependentBases() does, + // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1 + !decl->hasAnyDependentBases() && !decl->forallBases(BaseCheckNotExceptionSubclass)) + { + return true; + } + return false; + } + + bool VisitCXXOperatorCallExpr(const CXXOperatorCallExpr* operatorCallExpr) + { + if (ignoreLocation(operatorCallExpr)) + return true; + + StringRef fn = getFilenameOfLocation( + compiler.getSourceManager().getExpansionLoc(operatorCallExpr->getBeginLoc())); + // these are below tools in the module hierarchy, so we can't use the pretty printing + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/include/comphelper/")) + return true; + + if (operatorCallExpr->getOperator() != OO_LessLess) + return true; + auto expr = operatorCallExpr->getArg(1)->IgnoreImplicit(); + if (auto declRefExpr = dyn_cast(expr)) + if (auto varDecl = dyn_cast(declRefExpr->getDecl())) + { + const clang::Type* type = varDecl->getType()->getUnqualifiedDesugaredType(); + const CXXRecordDecl* cxxRecordDecl = type->getAsCXXRecordDecl(); + if (!cxxRecordDecl) + cxxRecordDecl = type->getPointeeCXXRecordDecl(); + if (!cxxRecordDecl) + return true; + if (!isDerivedFromException(cxxRecordDecl)) + return true; + auto loc = operatorCallExpr->getBeginLoc(); + // for some reason, I'm warning multiple times? so just check if I've warned already + if (!m_visited.insert(compiler.getSourceManager().getExpansionLoc(loc)).second) + return true; + report(DiagnosticsEngine::Warning, + "use TOOLS_WARN_EXCEPTION/TOOLS_INFO_EXCEPTION/exceptionToString to print " + "exception nicely", + loc) + << operatorCallExpr->getSourceRange(); + return true; + } + return true; + } +}; + +static Plugin::Registration logexceptionnicely("logexceptionnicely"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/loopvartoosmall.cxx b/compilerplugins/clang/loopvartoosmall.cxx new file mode 100644 index 000000000..bc03e94ca --- /dev/null +++ b/compilerplugins/clang/loopvartoosmall.cxx @@ -0,0 +1,246 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * +*/ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include + +#include "compat.hxx" +#include "plugin.hxx" +//#include "clang/AST/CXXInheritance.h" + +// Idea from bubli. Check that the index variable in a for loop is able to cover the range +// revealed by the terminating condition. +// If not, we might end up in an endless loop, or just not process certain parts. + +namespace +{ + +class LoopVarTooSmall: + public loplugin::FilteringPlugin +{ +public: + explicit LoopVarTooSmall(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitForStmt( const ForStmt* stmt ) { + checkExpr(stmt->getCond()); + return true; + } + + bool VisitWhileStmt(WhileStmt const * stmt) { + checkExpr(stmt->getCond()); + return true; + } + + bool VisitDoStmt(DoStmt const * stmt) { + checkExpr(stmt->getCond()); + return true; + } + +private: + unsigned getIntValueWidth(QualType type) const; + + void checkSubExpr(Expr const * expr, bool positive); + + void checkExpr(Expr const * expr); + + struct Comparison { + BinaryOperator const * op; + unsigned rhsWidth; + }; + + struct Comparisons { + std::list comparisons; + unsigned lhsWidth; + }; + + std::map comparisons_; +}; + +unsigned LoopVarTooSmall::getIntValueWidth(QualType type) const { + if (auto const et = type->getAs()) { + auto const ed = et->getDecl(); + if (!ed->isFixed()) { + unsigned pos = ed->getNumPositiveBits(); + unsigned neg = ed->getNumNegativeBits(); + return neg == 0 ? std::max(pos, 1U) : std::max(pos + 1, neg); + } + } + return compiler.getASTContext().getIntWidth(type); +} + +void LoopVarTooSmall::checkSubExpr(Expr const * expr, bool positive) { + auto const e = expr->IgnoreImplicit()->IgnoreParenImpCasts(); + if (auto const uo = dyn_cast(e)) { + if (uo->getOpcode() == UO_LNot) { + checkSubExpr(uo->getSubExpr(), !positive); + } + return; + } + const BinaryOperator* binOp = dyn_cast(e); + if (!binOp) + return; + bool less; + if (positive) { + switch (binOp->getOpcode()) { + case BO_LAnd: + checkSubExpr(binOp->getLHS(), true); + checkSubExpr(binOp->getRHS(), true); + return; + case BO_LT: + case BO_NE: + less = true; + break; + case BO_LE: + less = false; + break; + default: + return; + } + } else { + switch (binOp->getOpcode()) { + case BO_LOr: + checkSubExpr(binOp->getLHS(), false); + checkSubExpr(binOp->getRHS(), false); + return; + case BO_GE: + case BO_EQ: + less = true; + break; + case BO_GT: + less = false; + break; + default: + return; + } + } + auto lhs = dyn_cast(binOp->getLHS()->IgnoreParenImpCasts()); + if (!lhs) + return; + QualType qt = lhs->getType(); + if (!qt->isIntegralOrEnumerationType()) + return; + unsigned qt1BitWidth = getIntValueWidth(qt); + auto lhsDecl = lhs->getDecl(); + if (!isa(lhsDecl)) { + if (auto fd = dyn_cast(lhsDecl)) { + if (fd->isBitField()) { + qt1BitWidth = std::max( + qt1BitWidth, + fd->getBitWidthValue(compiler.getASTContext())); + } + } else { + return; + } + } + const Expr* binOpRHS = binOp->getRHS()->IgnoreParenImpCasts(); + QualType qt2 = binOpRHS->getType(); + if (!qt2->isIntegralType(compiler.getASTContext())) + return; + unsigned qt2BitWidth; + llvm::APSInt aIntResult; + // Work around missing Clang 3.9 fix + // "Sema: do not attempt to sizeof a dependent type", causing Clang 3.8 to + // crash during EvaluateAsInt() on expressions of the form + // + // sizeof (T) + // + // with dependent type T: + if (!binOpRHS->isValueDependent() + && compat::EvaluateAsInt(binOpRHS, aIntResult, compiler.getASTContext())) + { + if (less && aIntResult.isStrictlyPositive()) { + --aIntResult; + } + qt2BitWidth = aIntResult.isUnsigned() || !aIntResult.isNegative() + ? std::max(aIntResult.getActiveBits(), 1U) + : aIntResult.getBitWidth() - aIntResult.countLeadingOnes() + 1; + } else { + // Ignore complex expressions for now, promotion rules on conditions + // like "i < (size()+1)" make it hard to guess at a correct type: + if (isa(binOpRHS) || isa(binOpRHS)) + { + return; + } + qt2BitWidth = getIntValueWidth(qt2); + if (auto dre = dyn_cast(binOpRHS)) { + if (auto fd = dyn_cast(dre->getDecl())) { + if (fd->isBitField()) { + qt2BitWidth = std::max( + qt2BitWidth, + fd->getBitWidthValue(compiler.getASTContext())); + } + } + } + } + + auto i = comparisons_.find(lhsDecl); + if (i == comparisons_.end()) { + i = (comparisons_.insert( + decltype(comparisons_)::value_type(lhsDecl, {{}, qt1BitWidth})) + .first); + } else { + assert(i->second.lhsWidth == qt1BitWidth); + } + bool ins = true; + for (auto j = i->second.comparisons.begin(); + j != i->second.comparisons.end();) + { + if (qt2BitWidth > j->rhsWidth) { + ins = false; + break; + } else if (qt2BitWidth < j->rhsWidth) { + j = i->second.comparisons.erase(j); + } else { + ++j; + } + } + if (ins) { + i->second.comparisons.push_back({binOp, qt2BitWidth}); + } +} + +void LoopVarTooSmall::checkExpr(Expr const * expr) { + if (expr != nullptr && !ignoreLocation(expr)) { + assert(comparisons_.empty()); + checkSubExpr(expr, true); + for (auto const & i: comparisons_) { + for (auto const & j: i.second.comparisons) { + if (i.second.lhsWidth < j.rhsWidth) { + report( + DiagnosticsEngine::Warning, + "loop index type %0 is narrower than length type %1", + j.op->getExprLoc()) + << j.op->getLHS()->IgnoreImpCasts()->getType() + << j.op->getRHS()->IgnoreImpCasts()->getType() + << j.op->getSourceRange(); + } + } + } + comparisons_.clear(); + } +} + +loplugin::Plugin::Registration< LoopVarTooSmall > loopvartoosmall("loopvartoosmall"); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/makeshared.cxx b/compilerplugins/clang/makeshared.cxx new file mode 100644 index 000000000..902d200ff --- /dev/null +++ b/compilerplugins/clang/makeshared.cxx @@ -0,0 +1,252 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include + +#include "config_clang.h" + +#include "check.hxx" +#include "plugin.hxx" + +/** + * look for places we can use std::make_shared + */ + +namespace +{ +class MakeShared : public loplugin::FilteringPlugin +{ +public: + explicit MakeShared(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual bool preRun() override + { + StringRef fn(handler.getMainFileName()); + // TODO something weird with protected base classes going on here + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/excel/xeextlst.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/excel/xecontent.cxx")) + return false; + // no idea what is going on here + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/sidebar/nbdtmg.cxx")) + return false; + + // legitimate use of moving std::unique_ptr to std::shared_ptr + if (loplugin::isSamePathname(fn, SRCDIR "/comphelper/source/container/enumerablemap.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/svl/source/items/style.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/app/weldutils.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sfx2/source/appl/appopen.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/table/tablertfimporter.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/docshell/externalrefmgr.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/attr/swatrset.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/condformat/condformatdlg.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/layout/frmtool.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/excel/xihelper.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/excel/xeformula.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/excel/xichart.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/html/htmlpars.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/view/cellsh1.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/html/htmltab.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/ww8/docxattributeoutput.cxx")) + return false; + return true; + } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool shouldVisitTemplateInstantiations() const { return true; } + + bool VisitCXXConstructExpr(CXXConstructExpr const*); + bool VisitCXXMemberCallExpr(CXXMemberCallExpr const*); + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const*); + bool VisitVarDecl(VarDecl const*); +}; + +bool MakeShared::VisitCXXConstructExpr(CXXConstructExpr const* constructExpr) +{ + if (ignoreLocation(constructExpr)) + return true; + if (!loplugin::TypeCheck(constructExpr->getType()).ClassOrStruct("shared_ptr").StdNamespace()) + return true; + if (!(constructExpr->getNumArgs() == 1 + || (constructExpr->getNumArgs() > 1 && isa(constructExpr->getArg(1))))) + return true; + auto arg0 = constructExpr->getArg(0)->IgnoreParenImpCasts(); + auto cxxNewExpr = dyn_cast(arg0); + if (cxxNewExpr) + { + auto construct2 = cxxNewExpr->getConstructExpr(); + if (construct2) + { + if (construct2->getConstructor()->getAccess() != AS_public) + return true; + if (construct2->getNumArgs() == 1 + && isa(construct2->getArg(0))) + return true; + } + } + else if (loplugin::TypeCheck(arg0->getType()).ClassOrStruct("shared_ptr").StdNamespace()) + return true; + else if (loplugin::TypeCheck(arg0->getType()).ClassOrStruct("weak_ptr").StdNamespace()) + return true; + else if (arg0->getType()->isDependentType()) + return true; + else if (isa(arg0)) + return true; + else if (auto const call = dyn_cast(arg0)) + { + if (auto const decl = call->getDirectCallee()) + { + // Don't warn about cases where e.g. the Bitmap* result of calling Windows' + // Bitmap::FromBITMAPINFO is wrapped in a shared_ptr: + if (decl->getReturnType()->isPointerType() + && compiler.getSourceManager().isInSystemHeader(decl->getLocation())) + { + return true; + } + } + } + + StringRef fn = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(constructExpr->getBeginLoc())); + if (loplugin::isSamePathname(fn, SRCDIR "/include/o3tl/make_shared.hxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/svl/source/items/stylepool.cxx")) + return true; + + report(DiagnosticsEngine::Warning, "rather use make_shared than constructing from %0", + constructExpr->getBeginLoc()) + << arg0->getType() << constructExpr->getSourceRange(); + return true; +} + +bool MakeShared::VisitCXXMemberCallExpr(CXXMemberCallExpr const* cxxMemberCallExpr) +{ + if (ignoreLocation(cxxMemberCallExpr)) + return true; + + if (cxxMemberCallExpr->getNumArgs() != 1) + return true; + + // cannot find a way to use the loplugin::DeclCheck stuff here + auto templateDecl + = dyn_cast(cxxMemberCallExpr->getRecordDecl()); + if (!templateDecl) + return true; + auto cxxRecordDecl = templateDecl->getSpecializedTemplate()->getTemplatedDecl(); + if (!cxxRecordDecl->getName().contains("shared_ptr")) + return true; + + if (auto const id = cxxMemberCallExpr->getMethodDecl()->getIdentifier()) + { + if (id->getName() != "reset") + return true; + } + auto cxxNewExpr = dyn_cast(cxxMemberCallExpr->getArg(0)->IgnoreParenImpCasts()); + if (!cxxNewExpr) + return true; + if (cxxNewExpr->getConstructExpr() + && cxxNewExpr->getConstructExpr()->getConstructor()->getAccess() != AS_public) + return true; + + StringRef fn = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(cxxMemberCallExpr->getBeginLoc())); + if (loplugin::isSamePathname(fn, SRCDIR "/include/o3tl/make_shared.hxx")) + return true; + + report(DiagnosticsEngine::Warning, "rather use make_shared", cxxNewExpr->getBeginLoc()) + << cxxNewExpr->getSourceRange(); + + return true; +} + +bool MakeShared::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* operCallExpr) +{ + if (ignoreLocation(operCallExpr)) + return true; + if (!operCallExpr->isAssignmentOp()) + return true; + + if (!loplugin::TypeCheck(operCallExpr->getType()).ClassOrStruct("shared_ptr").StdNamespace()) + return true; + + if (loplugin::TypeCheck(operCallExpr->getArg(1)->getType()) + .ClassOrStruct("shared_ptr") + .StdNamespace()) + return true; + + report(DiagnosticsEngine::Warning, "rather use make_shared than constructing from %0", + operCallExpr->getBeginLoc()) + << operCallExpr->getArg(1)->getType() << operCallExpr->getSourceRange(); + + return true; +} + +bool MakeShared::VisitVarDecl(VarDecl const* varDecl) +{ + if (ignoreLocation(varDecl)) + return true; + if (!varDecl->hasInit()) + return true; + + if (!loplugin::TypeCheck(varDecl->getType()).ClassOrStruct("shared_ptr").StdNamespace()) + return true; + + if (varDecl->getInit()->getType().isNull()) + return true; + if (varDecl->getInit()->getType()->isDependentType()) + return true; + if (loplugin::TypeCheck(varDecl->getInit()->IgnoreParenImpCasts()->getType()) + .ClassOrStruct("shared_ptr") + .StdNamespace()) + return true; + + report(DiagnosticsEngine::Warning, "rather use make_shared than constructing from %0", + varDecl->getBeginLoc()) + << varDecl->getInit()->getType() << varDecl->getSourceRange(); + + return true; +} + +loplugin::Plugin::Registration makeshared("makeshared", false); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/mapindex.cxx b/compilerplugins/clang/mapindex.cxx new file mode 100644 index 000000000..50b1c6592 --- /dev/null +++ b/compilerplugins/clang/mapindex.cxx @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include +#include + +#include "check.hxx" +#include "plugin.hxx" + +/** + Look for places we are using map[idx] in a bool context, which allocates an entry in the map, which is sometimes a side-effect we don't want. +*/ + +namespace +{ +class MapIndex : public loplugin::FilteringPlugin +{ +public: + explicit MapIndex(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitImplicitCastExpr(const ImplicitCastExpr*); + bool VisitMemberExpr(const MemberExpr*); +}; + +bool MapIndex::VisitMemberExpr(const MemberExpr* memberExpr) +{ + if (ignoreLocation(memberExpr)) + return true; + // operator bool conversion + auto conversionDecl = dyn_cast(memberExpr->getMemberDecl()); + if (!conversionDecl || !conversionDecl->getConversionType()->isBooleanType()) + return true; + auto operatorCall = dyn_cast(memberExpr->getBase()->IgnoreCasts()); + if (!operatorCall) + return true; + if (operatorCall->getOperator() != OverloadedOperatorKind::OO_Subscript) + return true; + auto tc = loplugin::TypeCheck(operatorCall->getArg(0)->getType()); + if (!tc.Class("map") && !tc.Class("unordered_map")) + return true; + report(DiagnosticsEngine::Warning, + "will create an empty entry in the map, you sure about that, rather use count()1", + operatorCall->getExprLoc()); + return true; +} + +bool MapIndex::VisitImplicitCastExpr(const ImplicitCastExpr* implicitCastExpr) +{ + if (ignoreLocation(implicitCastExpr)) + { + return true; + } + + // first cast is some kind of "ToBoolean" cast + auto ck = implicitCastExpr->getCastKind(); + if (ck != CK_MemberPointerToBoolean && ck != CK_PointerToBoolean && ck != CK_IntegralToBoolean + && ck != CK_FloatingToBoolean && ck != CK_FloatingComplexToBoolean + && ck != CK_IntegralComplexToBoolean) + return true; + + // second cast is LValueToRValue + implicitCastExpr = dyn_cast(implicitCastExpr->getSubExpr()); + if (!implicitCastExpr) + return true; + + if (implicitCastExpr->getCastKind() != CK_LValueToRValue) + return true; + auto operatorCall = dyn_cast(implicitCastExpr->getSubExpr()); + if (!operatorCall) + return true; + if (operatorCall->getOperator() != OverloadedOperatorKind::OO_Subscript) + return true; + auto tc = loplugin::TypeCheck(operatorCall->getArg(0)->getType()); + if (!tc.Class("map") && !tc.Class("unordered_map")) + return true; + report(DiagnosticsEngine::Warning, + "will create an empty entry in the map, you sure about that, rather use count()2", + implicitCastExpr->getExprLoc()); + return true; +} + +loplugin::Plugin::Registration mapindex("mapindex"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/memoryvar.cxx b/compilerplugins/clang/memoryvar.cxx new file mode 100644 index 000000000..14c328ba4 --- /dev/null +++ b/compilerplugins/clang/memoryvar.cxx @@ -0,0 +1,238 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "config_clang.h" +#include "plugin.hxx" +#include "clang/AST/CXXInheritance.h" + +// Check for local variables that we are calling delete on + +namespace +{ + +class MemoryVar: + public loplugin::FilteringPlugin +{ +public: + explicit MemoryVar(loplugin::InstantiationData const & data): FilteringPlugin(data), mbChecking(false) {} + + virtual void run() override { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool TraverseFunctionDecl(FunctionDecl*); + bool VisitCXXDeleteExpr(const CXXDeleteExpr*); + bool VisitCXXNewExpr(const CXXNewExpr* ); + bool VisitBinaryOperator(const BinaryOperator*); + bool VisitReturnStmt(const ReturnStmt*); + +private: + bool mbChecking; + std::set maVarUsesSet; + std::set maVarNewSet; + std::set maVarIgnoreSet; + std::map maVarDeclSourceRangeMap; + std::map maVarDeleteSourceRangeMap; + StringRef getFilename(SourceLocation loc); +}; + +StringRef MemoryVar::getFilename(SourceLocation loc) +{ + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(loc); + StringRef name { getFilenameOfLocation(spellingLocation) }; + return name; +} + +bool MemoryVar::TraverseFunctionDecl(FunctionDecl * decl) +{ + if (ignoreLocation(decl)) { + return true; + } + if (!decl->hasBody() || !decl->isThisDeclarationADefinition()) { + return true; + } + + maVarUsesSet.clear(); + maVarNewSet.clear(); + maVarIgnoreSet.clear(); + maVarDeclSourceRangeMap.clear(); + maVarDeleteSourceRangeMap.clear(); + + assert(!mbChecking); + mbChecking = true; + TraverseStmt(decl->getBody()); + mbChecking = false; + + for (const auto& varLoc : maVarUsesSet) + { + // checking the location of the var instead of the function because for some reason + // I'm not getting accurate results from clang right now + StringRef aFileName = getFilename(varLoc); + // TODO these files are doing some weird stuff I don't know how to ignore yet + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/vcl/source/filter/")) { + return true; + } + if (loplugin::isSamePathname(aFileName, SRCDIR "/sw/source/core/layout/frmtool.cxx")) { + return true; + } + + + if (maVarNewSet.find(varLoc) == maVarNewSet.end()) + continue; + if (maVarIgnoreSet.find(varLoc) != maVarIgnoreSet.end()) + continue; + + report(DiagnosticsEngine::Warning, + "calling new and delete on a local var, rather use std::unique_ptr", + varLoc) + << maVarDeclSourceRangeMap[varLoc]; + report(DiagnosticsEngine::Note, + "delete called here", + maVarDeleteSourceRangeMap[varLoc].getBegin()) + << maVarDeleteSourceRangeMap[varLoc]; + } + return true; +} + +bool MemoryVar::VisitCXXDeleteExpr(const CXXDeleteExpr *deleteExpr) +{ + if (!mbChecking) + return true; + if (ignoreLocation(deleteExpr)) { + return true; + } + const Expr* argumentExpr = deleteExpr->getArgument(); + if (isa(argumentExpr)) { + argumentExpr = dyn_cast(argumentExpr)->getSubExpr(); + } + const DeclRefExpr* declRefExpr = dyn_cast(argumentExpr); + if (!declRefExpr) + return true; + const Decl* decl = declRefExpr->getDecl(); + if (!isa(decl) || isa(decl)) { + return true; + } + const VarDecl * varDecl = dyn_cast(decl)->getCanonicalDecl(); + if (varDecl->hasGlobalStorage()) { + return true; + } + + SourceLocation loc = varDecl->getLocation(); + + if (maVarUsesSet.insert(loc).second) { + maVarDeclSourceRangeMap[loc] = varDecl->getSourceRange(); + maVarDeleteSourceRangeMap[loc] = declRefExpr->getSourceRange(); + } + return true; +} + +bool MemoryVar::VisitCXXNewExpr(const CXXNewExpr *newExpr) +{ + if (!mbChecking) + return true; + if (ignoreLocation(newExpr)) { + return true; + } + const Stmt* stmt = getParentStmt(newExpr); + + const DeclStmt* declStmt = dyn_cast(stmt); + if (declStmt) { + const VarDecl* varDecl = dyn_cast(declStmt->getSingleDecl()); + if (varDecl) { + varDecl = varDecl->getCanonicalDecl(); + SourceLocation loc = varDecl->getLocation(); + maVarNewSet.insert(loc); + } + return true; + } + + const BinaryOperator* binaryOp = dyn_cast(stmt); + if (binaryOp && binaryOp->getOpcode() == BO_Assign) { + const DeclRefExpr* declRefExpr = dyn_cast(binaryOp->getLHS()); + if (declRefExpr) { + const VarDecl* varDecl = dyn_cast(declRefExpr->getDecl()); + if (varDecl) { + varDecl = varDecl->getCanonicalDecl(); + SourceLocation loc = varDecl->getLocation(); + maVarNewSet.insert(loc); + } + } + } + return true; +} + +// Ignore cases where the variable in question is assigned to another variable +bool MemoryVar::VisitBinaryOperator(const BinaryOperator *binaryOp) +{ + if (!mbChecking) + return true; + if (ignoreLocation(binaryOp)) { + return true; + } + if (binaryOp->getOpcode() != BO_Assign) { + return true; + } + const Expr* expr = binaryOp->getRHS(); + // unwrap casts + while (isa(expr)) { + expr = dyn_cast(expr)->getSubExpr(); + } + const DeclRefExpr* declRefExpr = dyn_cast(expr); + if (!declRefExpr) { + return true; + } + const VarDecl* varDecl = dyn_cast(declRefExpr->getDecl()); + if (!varDecl) { + return true; + } + varDecl = varDecl->getCanonicalDecl(); + maVarIgnoreSet.insert(varDecl->getLocation()); + return true; +} + +// Ignore cases where the variable in question is returned from a function +bool MemoryVar::VisitReturnStmt(const ReturnStmt *returnStmt) +{ + if (!mbChecking) + return true; + if (ignoreLocation(returnStmt)) { + return true; + } + const Expr* expr = returnStmt->getRetValue(); + if (!expr) { + return true; + } + // unwrap casts + while (isa(expr)) { + expr = dyn_cast(expr)->getSubExpr(); + } + const DeclRefExpr* declRefExpr = dyn_cast(expr); + if (!declRefExpr) { + return true; + } + const VarDecl* varDecl = dyn_cast(declRefExpr->getDecl()); + if (!varDecl) { + return true; + } + varDecl = varDecl->getCanonicalDecl(); + maVarIgnoreSet.insert(varDecl->getLocation()); + return true; +} + +loplugin::Plugin::Registration< MemoryVar > X("memoryvar", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/mergeclasses.cxx b/compilerplugins/clang/mergeclasses.cxx new file mode 100644 index 000000000..a644677ca --- /dev/null +++ b/compilerplugins/clang/mergeclasses.cxx @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" +#include + +/** + +Idea from Norbert (shm_get) - look for classes that are +(a) not instantiated +(b) have zero or one subclasses +and warn about them - would allow us to remove a bunch of abstract classes +that can be merged into one class and simplified. + +Dump a list of +- unique classes that exist (A) +- unique classes that are instantiated (B) +- unique class-subclass relationships (C) +Then + let D = A minus B + for each class in D, look in C and count the entries, then dump it if no-entries == 1 + +The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='mergeclasses' check + $ ./compilerplugins/clang/mergeclasses.py + +FIXME exclude 'static-only' classes, which some people may use/have used instead of a namespace to tie together a bunch of functions + +*/ + +namespace { + +// try to limit the voluminous output a little +static std::set instantiatedSet; +static std::set > childToParentClassSet; // childClassName -> parentClassName +static std::map definitionMap; // className -> filename + +class MergeClasses: + public loplugin::FilteringPlugin +{ +public: + explicit MergeClasses(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + std::string output; + for (const std::string & s : instantiatedSet) + output += "instantiated:\t" + s + "\n"; + for (const std::pair & s : childToParentClassSet) + output += "has-subclass:\t" + s.first + "\t" + s.second + "\n"; + for (const auto & s : definitionMap) + output += "definition:\t" + s.first + "\t" + s.second + "\n"; + std::ofstream myfile; + myfile.open( WORKDIR "/loplugin.mergeclasses.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + + bool shouldVisitTemplateInstantiations () const { return true; } + + bool VisitVarDecl(const VarDecl *); + bool VisitFieldDecl(const FieldDecl *); + bool VisitCXXConstructExpr( const CXXConstructExpr* var ); + bool VisitCXXRecordDecl( const CXXRecordDecl* decl); +}; + +bool ignoreClass(StringRef s) +{ + // ignore stuff in the standard library, and UNO stuff we can't touch. + if (s.startswith("rtl::") || s.startswith("sal::") || s.startswith("com::sun::") + || s.startswith("std::") || s.startswith("boost::") + || s == "OString" || s == "OUString" || s == "bad_alloc") + { + return true; + } + // ignore instantiations of pointers and arrays + if (s.endswith("*") || s.endswith("]")) { + return true; + } + return false; +} + +// check for implicit construction +bool MergeClasses::VisitVarDecl( const VarDecl* pVarDecl ) +{ + if (ignoreLocation(pVarDecl)) { + return true; + } + std::string s = pVarDecl->getType().getAsString(); + if (!ignoreClass(s)) + instantiatedSet.insert(s); + return true; +} + +// check for implicit construction +bool MergeClasses::VisitFieldDecl( const FieldDecl* pFieldDecl ) +{ + if (ignoreLocation(pFieldDecl)) { + return true; + } + std::string s = pFieldDecl->getType().getAsString(); + if (!ignoreClass(s)) + instantiatedSet.insert(s); + return true; +} + +bool MergeClasses::VisitCXXConstructExpr( const CXXConstructExpr* pCXXConstructExpr ) +{ + if (ignoreLocation(pCXXConstructExpr)) { + return true; + } + // ignore calls when a sub-class is constructing its superclass + if (pCXXConstructExpr->getConstructionKind() != CXXConstructExpr::ConstructionKind::CK_Complete) { + return true; + } + const CXXConstructorDecl* pCXXConstructorDecl = pCXXConstructExpr->getConstructor(); + const CXXRecordDecl* pParentCXXRecordDecl = pCXXConstructorDecl->getParent(); + std::string s = pParentCXXRecordDecl->getQualifiedNameAsString(); + if (!ignoreClass(s)) + instantiatedSet.insert(s); + return true; +} + +bool MergeClasses::VisitCXXRecordDecl(const CXXRecordDecl* decl) +{ + if (ignoreLocation(decl)) { + return true; + } + if (decl->isThisDeclarationADefinition()) + { + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(decl->getBeginLoc()); + auto filename = getFilenameOfLocation(spellingLocation); + filename = filename.substr(strlen(SRCDIR)); + std::string s = decl->getQualifiedNameAsString(); + if (ignoreClass(s)) + return true; + definitionMap.insert( std::pair(s, filename.str()) ); + for (auto it = decl->bases_begin(); it != decl->bases_end(); ++it) + { + const CXXBaseSpecifier spec = *it; + // need to look through typedefs, hence the getUnqualifiedDesugaredType + QualType baseType = spec.getType().getDesugaredType(compiler.getASTContext()); + childToParentClassSet.insert( std::pair(s, baseType.getAsString()) ); + } + } + return true; +} + +loplugin::Plugin::Registration< MergeClasses > X("mergeclasses", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/mergeclasses.py b/compilerplugins/clang/mergeclasses.py new file mode 100755 index 000000000..bc6d129ee --- /dev/null +++ b/compilerplugins/clang/mergeclasses.py @@ -0,0 +1,78 @@ +#!/usr/bin/python3 + +import sys + +instantiatedSet = set() +definitionSet = set() +parentChildDict = {} +definitionToFileDict = {} + +with open("workdir/loplugin.mergeclasses.log") as txt: + for line in txt: + tokens = line.strip().split("\t") + + if len(tokens) == 1: + pass + + elif tokens[0] == "instantiated:": + clazzName = tokens[1] + if (clazzName.startswith("const ")): + clazzName = clazzName[6:] + if (clazzName.startswith("class ")): + clazzName = clazzName[6:] + if (clazzName.startswith("::")): + clazzName = clazzName[2:] + instantiatedSet.add(clazzName) + + elif tokens[0] == "definition:": + clazzName = tokens[1] + # the 1.. is so we skip the leading / + fileName = tokens[2][1:] + definitionSet.add(clazzName) + definitionToFileDict[clazzName] = fileName + + elif tokens[0] == "has-subclass:": + child = tokens[1] + parent = tokens[2] + if (parent.startswith("class ")): + parent = parent[6:] + elif (parent.startswith("struct ")): + parent = parent[7:] + if (child.startswith("class ")): + child = child[6:] + elif (child.startswith("struct ")): + child = child[7:] + if (parent not in parentChildDict): + parentChildDict[parent] = set() + parentChildDict[parent].add(child) + +def extractModuleName(clazz): + filename = definitionToFileDict[clazz] + if filename.startswith("include/"): + filename = filename[8:] + idx = filename.find("/") + return filename[:idx] + +with open("compilerplugins/clang/mergeclasses.results", "wt") as f: + # loop over defined, but not instantiated classes + for clazz in sorted(definitionSet - instantiatedSet): + if clazz == "svl::IUndoManager": print(parentChildDict[clazz]) + # ignore classes without any children, and classes with more than one child + if (clazz not in parentChildDict) or (len(parentChildDict[clazz]) != 1): + continue + # exclude some common false positives + a = ['Dialog', 'Dlg', 'com::sun'] + if any(x in clazz for x in a): + continue + # ignore base class that contain the word "mutex", they are normally there to + # help with the WeakComponentImpl template magic + if ("mutex" in clazz) or ("Mutex" in clazz): + continue + otherclazz = next(iter(parentChildDict[clazz])) + if clazz == "svl::IUndoManager": print(extractModuleName(clazz)) + if otherclazz == "svl::IUndoManager": print(extractModuleName(otherclazz)) + # exclude combinations that span modules because we often use those to make cross-module dependencies more manageable. + if extractModuleName(clazz) != extractModuleName(otherclazz): + continue + f.write( "merge " + clazz + " with " + otherclazz + "\n" ) + diff --git a/compilerplugins/clang/mergeclasses.results b/compilerplugins/clang/mergeclasses.results new file mode 100644 index 000000000..096b0722f --- /dev/null +++ b/compilerplugins/clang/mergeclasses.results @@ -0,0 +1,506 @@ +merge (anonymous namespace)::Base2 with (anonymous namespace)::Derived +merge (anonymous namespace)::Base3 with (anonymous namespace)::Derived +merge (anonymous namespace)::BasePixelPtr with (anonymous namespace)::TrueColorPixelPtr +merge (anonymous namespace)::BuiltinPropertyGetSetHelper with (anonymous namespace)::CustomPropertyGetSetHelper +merge (anonymous namespace)::C2 with (anonymous namespace)::C3 +merge (anonymous namespace)::C3 with (anonymous namespace)::C4 +merge (anonymous namespace)::C4 with (anonymous namespace)::C5 +merge (anonymous namespace)::CffGlobal with (anonymous namespace)::CffSubsetterContext +merge (anonymous namespace)::Char1 with (anonymous namespace)::Char2 +merge (anonymous namespace)::Char2 with (anonymous namespace)::Char3 +merge (anonymous namespace)::DIBInfoHeader with (anonymous namespace)::DIBV5Header +merge (anonymous namespace)::DomVisitor with (anonymous namespace)::DomExport +merge (anonymous namespace)::GtkInstanceCheckButton with (anonymous namespace)::GtkInstanceRadioButton +merge (anonymous namespace)::N with (anonymous namespace)::P +merge (anonymous namespace)::O with (anonymous namespace)::O2 +merge (anonymous namespace)::ParserData with (anonymous namespace)::Entity +merge (anonymous namespace)::PopupMenuToolbarController with (anonymous namespace)::GenericPopupToolbarController +merge (anonymous namespace)::PublishableDescription with cppu::ImplInheritanceHelper +merge (anonymous namespace)::RecursiveTest with (anonymous namespace)::SimpleRecursiveTest +merge (anonymous namespace)::ReflectionTransition with (anonymous namespace)::RochadeTransition +merge (anonymous namespace)::RunInitGuard with (anonymous namespace)::RunGuard +merge (anonymous namespace)::ScVbaControlContainer with (anonymous namespace)::ScVbaButtonContainer +merge (anonymous namespace)::SimpleTransition with (anonymous namespace)::DiamondTransition +merge (anonymous namespace)::StrEntries with (anonymous namespace)::RemoveEditAttribsHandler +merge (anonymous namespace)::VariableTextField with (anonymous namespace)::VariableDateTimeField +merge (anonymous namespace)::empty with (anonymous namespace)::second +merge AbstractMailMergeWizard with AbstractMailMergeWizard_Impl +merge AbstractSmParser with SmParser5 +merge AbstractSwInsertDBColAutoPilot with AbstractSwInsertDBColAutoPilot_Impl +merge AbstractTabController_Impl with AbstractApplyTabController_Impl +merge AddressWalker with AddressWalkerWriter +merge AutoIdle with (anonymous namespace)::TestAutoIdleRR +merge B3dTransformationSet with B3dViewport +merge B3dViewport with B3dCamera +merge BaseJSWidget with JSWidget +merge BitmapConvolutionMatrixFilter with BitmapSharpenFilter +merge BrowseBox with svt::EditBrowseBox +merge BrowserHeader with svt::EditBrowserHeader +merge CSS1Parser with SvxCSS1Parser +merge DateField with CalendarField +merge DbGridControl with FmGridControl +merge DdeItem with DdeGetPutItem +merge DdeLink with DdeHotLink +merge E3DObjGeoData with E3DSceneGeoData +merge E3dUndoAction with E3dRotateUndoAction +merge EditTextObject with EditTextObjectImpl +merge ErrorInfo with DynamicErrorInfo +merge EscherPersistTable with EscherEx +merge ExcBoolRecord with Exc1904 +merge ExcelConverterBase with ExcelToSc +merge ExportTyp with ExportBiff5 +merge FmGridListener with FmXGridPeer::GridListenerDelegator +merge FmRecordCountListener_Base with FmRecordCountListener +merge FmXDisposeListener with DisposeListenerGridBridge +merge FmXFormShell_Base_Disambiguation with FmXFormShell +merge GLWindow with GLX11Window +merge GalleryFileStorage with GalleryBinaryEngine +merge GalleryFileStorageEntry with GalleryBinaryEngineEntry +merge GalleryStorageLocations with GalleryBinaryStorageLocations +merge GroupTable with PPTWriterBase +merge HostDetailsContainer with DavDetailsContainer +merge IDocumentChartDataProviderAccess with sw::DocumentChartDataProviderManager +merge IDocumentContentOperations with sw::DocumentContentOperationsManager +merge IDocumentDeviceAccess with sw::DocumentDeviceManager +merge IDocumentDrawModelAccess with sw::DocumentDrawModelManager +merge IDocumentExternalData with sw::DocumentExternalDataManager +merge IDocumentFieldsAccess with sw::DocumentFieldsManager +merge IDocumentLayoutAccess with sw::DocumentLayoutManager +merge IDocumentLinksAdministration with sw::DocumentLinksAdministrationManager +merge IDocumentListItems with sw::DocumentListItemsManager +merge IDocumentListsAccess with sw::DocumentListsManager +merge IDocumentMarkAccess with sw::mark::MarkManager +merge IDocumentMarkAccess::ILazyDeleter with sw::mark::(anonymous namespace)::LazyFieldmarkDeleter +merge IDocumentOutlineNodes with sw::DocumentOutlineNodesManager +merge IDocumentRedlineAccess with sw::DocumentRedlineManager +merge IDocumentSettingAccess with sw::DocumentSettingManager +merge IDocumentState with sw::DocumentStateManager +merge IDocumentStatistics with sw::DocumentStatisticsManager +merge IDocumentStylePoolAccess with sw::DocumentStylePoolManager +merge IDocumentTimerAccess with sw::DocumentTimerManager +merge IDocumentUndoRedo with sw::UndoManager +merge IFinishedThreadListener with ThreadListener +merge IGrammarContact with (anonymous namespace)::SwGrammarContact +merge IStyleAccess with (anonymous namespace)::SwStyleManager +merge IStylePoolIteratorAccess with (anonymous namespace)::Iterator +merge IXFAttrList with XFSaxAttrList +merge IXFStream with XFSaxStream +merge IXFStyle with XFStyle +merge IconChoicePage with SvxHyperlinkTabPageBase +merge ImplGlyphFallbackFontSubstitution with (anonymous namespace)::FcGlyphFallbackSubstitution +merge ImplPreMatchFontSubstitution with (anonymous namespace)::FcPreMatchSubstitution +merge ListView with TemplateDlgLocalView +merge LongCurrencyFormatter with LongCurrencyBox +merge LotusConverterBase with LotusToSc +merge LwpDLVListHead with LwpPropList +merge LwpMarker with LwpStoryMarker +merge ObservableThread with SwAsyncRetrieveInputStreamThread +merge OldBasicPassword with basic::SfxScriptLibraryContainer +merge PPTExBulletProvider with PPTWriter +merge PriorityHBox with PriorityMergedHBox +merge PropertyAccessorBase with GenericPropertyAccessor +merge PropertyWrapperBase with PropertyWrapper +merge SOParagraph with ParagraphObj +merge SalData with GenericUnixSalData +merge SalDisplay with SalX11Display +merge SalInfoPrinter with PspSalInfoPrinter +merge SalInstance with SalGenericInstance +merge SalInstanceBox with JSWidget +merge SalInstanceCheckButton with JSWidget +merge SalInstanceComboBoxWithEdit with JSWidget +merge SalInstanceComboBoxWithoutEdit with JSWidget +merge SalInstanceDrawingArea with JSWidget +merge SalInstanceExpander with JSWidget +merge SalInstanceIconView with JSWidget +merge SalInstanceLabel with JSWidget +merge SalInstanceNotebook with JSWidget +merge SalInstanceRadioButton with JSWidget +merge SalInstanceSpinButton with JSWidget +merge SalInstanceTextView with JSWidget +merge SalInstanceToolbar with JSWidget +merge SalInstanceTreeView with JSWidget +merge SalPrinter with PspSalPrinter +merge SalSession with (anonymous namespace)::IceSalSession +merge SalSystem with SalGenericSystem +merge ScAccessibleTableBase with ScAccessibleSpreadsheet +merge ScAsyncTabController with ScAsyncTabController_Impl +merge ScDBDataContainerBase with ScDBCollection::NamedDBs +merge ScDBFunc with ScTabViewShell +merge ScDPCache::DBConnector with (anonymous namespace)::DBConnector +merge ScDocFunc with ScDocFuncDirect +merge ScEEAbsImport with ScEEImport +merge ScEEParseEntry with ScHTMLEntry +merge ScEnginePoolHelper with ScEditEngineDefaulter +merge ScFormatFilterPlugin with ScFormatFilterPluginImpl +merge ScMultiBlockUndo with ScUndoPaste +merge ScOrcusFilters with ScOrcusFiltersImpl +merge ScOrcusXMLContext with ScOrcusXMLContextImpl +merge ScRefHandler with ScRefHdlrControllerImpl +merge ScRefHandlerCaller with ScTPValidationValue +merge ScRefHandlerHelper with ScValidationDlg +merge ScSimpleEditSourceHelper with ScEditEngineTextObj +merge ScTabView with ScViewFunc +merge ScVbaGraphicObjectsBase with ScVbaButtons +merge ScVbaObjectContainer with (anonymous namespace)::ScVbaControlContainer +merge ScViewFunc with ScDBFunc +merge SceneObject with (anonymous namespace)::Iris +merge SdNavigatorWin with sd::sidebar::NavigatorWrapper +merge SdOptionsContents with SdOptions +merge SdOptionsGrid with SdOptions +merge SdOptionsZoom with SdOptions +merge SdTransferable::UserData with sd::slidesorter::controller::TransferableData +merge SdUnoSearchReplaceShape with SdGenericDrawPage +merge SdrCreateView with SdrView +merge SdrDragView with SdrCreateView +merge SdrEditView with SdrPolyEditView +merge SdrEscherImport with SdrPowerPointImport +merge SdrExchangeView with SdrDragView +merge SdrGlueEditView with SdrObjEditView +merge SdrGrafModeItem_Base with SdrGrafModeItem +merge SdrMarkView with SdrEditView +merge SdrObjEditView with SdrExchangeView +merge SdrPaintView with SdrSnapView +merge SdrPolyEditView with SdrGlueEditView +merge SdrSnapView with SdrMarkView +merge SdrUndoInsertObj with SdrUndoNewObj +merge SdrUndoNewObj with SdrUndoCopyObj +merge SdrUndoNewPage with SdrUndoCopyPage +merge SdwTextBoxRecord with SdwTextArt +merge SfxExtItemPropertySetInfo_Base with SfxExtItemPropertySetInfo +merge SfxItemPropertySetInfo_Base with SfxItemPropertySetInfo +merge SfxModelSubComponent with sfx2::DocumentUndoManager +merge SkiaSalGraphicsImpl with X11SkiaSalGraphicsImpl +merge SmElement with SmElementSeparator +merge SmFontPickList with SmFontPickListBox +merge StarSymbolToMSMultiFont with (anonymous namespace)::StarSymbolToMSMultiFontImpl +merge StgAvlIterator with StgIterator +merge StgAvlNode with StgDirEntry +merge StgCache with StgIo +merge StylesPreviewWindow_Base with StylesPreviewWindow_Impl +merge SvHeaderTabListBox with LclHeaderTabListBox +merge SvIdlDataBase with SvIdlWorkingBase +merge SvListView with SvTreeListBox +merge SvXMLExportItemMapper with (anonymous namespace)::SwXMLTableItemMapper_Impl +merge SvXMLImportItemMapper with (anonymous namespace)::SwXMLImportTableItemMapper_Impl +merge SvxAreaTabPage with SvxBkgTabPage +merge SvxCSS1Parser with SwCSS1Parser +merge SvxLanguageItem_Base with SvxLanguageItem +merge SvxRTFItemStackType with MakeUniqueEnabler +merge SvxRTFParser with EditRTFParser +merge SvxVertCTLTextTbxCtrl_Base with SvxVertCTLTextTbxCtrl +merge SwAccessibleFrame with SwAccessibleContext +merge SwCursorShell with SwEditShell +merge SwDashedLine with (anonymous namespace)::SwBreakDashedLine +merge SwDrawModeGrf_Base with SwDrawModeGrf +merge SwEditShell with SwFEShell +merge SwEndNoteOptionPage with SwFootNoteOptionPage +merge SwFEShell with SwWrtShell +merge SwFrameAreaDefinition with SwFrame +merge SwImpBlocks with SwXMLTextBlocks +merge SwInterHyphInfo with (anonymous namespace)::SwHyphArgs +merge SwNumberTreeNode with SwNodeNum +merge SwSelPaintRects with SwShellCursor +merge SwSidebarItem with SwAnnotationItem +merge SwTextAdjuster with SwTextCursor +merge SwUndoTextFormatCollCreate with SwUndoCondTextFormatCollCreate +merge SwUnoCursor with SwUnoTableCursor +merge SwXParaFrameEnumeration with (anonymous namespace)::SwXParaFrameEnumerationImpl +merge SwXParagraphEnumeration with (anonymous namespace)::SwXParagraphEnumerationImpl +merge SwXTextRanges with (anonymous namespace)::SwXTextRangesImpl +merge Task with Timer +merge TestShape with (anonymous namespace)::ImplTestShape +merge TestView with (anonymous namespace)::ImplTestView +merge TextObj with TextObjBinary +merge TextRenderImpl with FreeTypeTextRenderImpl +merge TxtEncExportHiddenTest with testBulletsHidden +merge TxtEncExportNotHiddenTest with testBulletsNotHidden +merge ValueGetter with (anonymous namespace)::CellValueGetter +merge ValueSetter with (anonymous namespace)::CellValueSetter +merge VclVButtonBox with (anonymous namespace)::LeakTestClass +merge Viewport3D with Camera3D +merge WW8PLCFx_Fc_FKP with WW8PLCFx_Cp_FKP +merge WW8Style with WW8RStyle +merge XFDate with XFDateStart +merge XFDateTimePart with XFTimePart +merge XMLNode with XMLChildNode +merge XMLTransformer with XMLTransformerBase +merge XclDebugObjCounter with XclRootData +merge XclExpChFutureRecordBase with XclExpChFrLabelProps +merge XclExpFutureRecord with XclExpChFutureRecordBase +merge XclExpObjectManager with XclExpEmbeddedObjectManager +merge XclExpSubStream with XclExpChart +merge XclImpCachedValue with (anonymous namespace)::XclImpCrn +merge XclImpCheckBoxObj with XclImpOptionButtonObj +merge XclNumFmtBuffer with XclImpNumFmtBuffer +merge accessibility::GridControlAccessibleElement with accessibility::AccessibleGridControlTableBase +merge accessibility::IComboListBoxHelper with VCLListBoxHelper +merge animcore::(anonymous namespace)::AnimationNodeBase with animcore::(anonymous namespace)::AnimationNode +merge basctl::Entry with basctl::DocumentEntry +merge basctl::docs::IDocumentDescriptorFilter with basctl::(anonymous namespace)::FilterDocuments +merge basegfx::InterpolatorProvider3D with basegfx::RasterConverter3D +merge basegfx::trapezoidhelper::(anonymous namespace)::TrDeSimpleEdge with basegfx::trapezoidhelper::(anonymous namespace)::TrDeEdgeEntry +merge bib::OComponentAdapterBase with bib::OLoadListenerAdapter +merge bib::OComponentListener with bib::OLoadListener +merge bib::OLoadListener with bib::FormControlContainer +merge cairocanvas::CanvasBaseSurfaceProvider_Base with canvas::CanvasBase +merge cairocanvas::CanvasBitmapSpriteSurface_Base with canvas::CanvasBase +merge cairocanvas::CanvasCustomSpriteSpriteBase_Base with canvas::CanvasBase +merge cairocanvas::Sprite with cairocanvas::CanvasCustomSpriteSpriteBase_Base +merge cairocanvas::SpriteCanvasBaseSpriteSurface_Base with canvas::CanvasBase +merge canvas::ISurfaceProxy with canvas::SurfaceProxy +merge canvas::ISurfaceProxyManager with canvas::(anonymous namespace)::SurfaceProxyManager +merge chart::CategoryPositionHelper with chart::BarPositionHelper +merge chart::ExplicitValueProvider with chart::ChartView +merge chart::LegendEntryProvider with chart::VSeriesPlotter +merge chart::MarkHandleProvider with chart::SelectionHelper +merge chart::wrapper::ChartDocumentWrapper_Base with chart::wrapper::ChartDocumentWrapper +merge comphelper::ChainablePropertySetInfo_Base with comphelper::ChainablePropertySetInfo +merge comphelper::ConfigurationListenerPropertyBase with comphelper::ConfigurationListenerProperty +merge comphelper::ConfigurationListener_Base with comphelper::ConfigurationListener +merge comphelper::MasterPropertySetInfo_Base with comphelper::MasterPropertySetInfo +merge comphelper::OAccessibleComponentHelper_Base with comphelper::OAccessibleComponentHelper +merge comphelper::OAccessibleContextHelper with comphelper::OCommonAccessibleComponent +merge comphelper::OAccessibleWrapper_Base with comphelper::OAccessibleWrapper +merge comphelper::OAnyEnumeration_BASE with comphelper::OAnyEnumeration +merge comphelper::OComponentProxyAggregation with comphelper::OAccessibleWrapper +merge comphelper::OContainerListenerAdapter_Base with comphelper::OContainerListenerAdapter +merge comphelper::OPropertyChangeMultiplexer_Base with comphelper::OPropertyChangeMultiplexer +merge comphelper::OProxyAggregation with comphelper::OComponentProxyAggregationHelper +merge comphelper::OSeekableInputWrapper_BASE with comphelper::OSeekableInputWrapper +merge comphelper::OSequenceOutputStream_Base with comphelper::OSequenceOutputStream +merge comphelper::OWeakListenerAdapterBase with comphelper::OWeakListenerAdapter +merge comphelper::PropertySetInfo_BASE with comphelper::PropertySetInfo +merge comphelper::TraceEvent with comphelper::NamedEvent +merge connectivity::OKeySet_Base with connectivity::OKeySet +merge connectivity::evoab::(anonymous namespace)::OEvoabVersion36Helper with connectivity::evoab::(anonymous namespace)::OEvoabVersion38Helper +merge connectivity::file::OStatement_Base with connectivity::file::OStatement_BASE2 +merge connectivity::hsqldb::IMethodGuardAccess with connectivity::hsqldb::OHsqlConnection +merge connectivity::java_lang_Exception with connectivity::java_sql_SQLException_BASE +merge connectivity::java_sql_Statement_Base with connectivity::OStatement_BASE2 +merge connectivity::odbc::ODBCDriver with connectivity::odbc::(anonymous namespace)::ORealOdbcDriver +merge connectivity::odbc::OStatement_Base with connectivity::odbc::OStatement_BASE2 +merge connectivity::sdbcx::IObjectCollection with (anonymous namespace)::OHardRefMap +merge connectivity::sdbcx::OKey with connectivity::OTableKeyHelper +merge cppcanvas::Bitmap with cppcanvas::internal::ImplBitmap +merge cppcanvas::BitmapCanvas with cppcanvas::internal::ImplBitmapCanvas +merge cppcanvas::CustomSprite with cppcanvas::internal::ImplCustomSprite +merge cppcanvas::PolyPolygon with cppcanvas::internal::ImplPolyPolygon +merge cppcanvas::Renderer with cppcanvas::internal::ImplRenderer +merge cppcanvas::SpriteCanvas with cppcanvas::internal::ImplSpriteCanvas +merge cppcanvas::internal::ImplSprite with cppcanvas::internal::ImplCustomSprite +merge cppu::(anonymous namespace)::OSingleFactoryHelper with cppu::(anonymous namespace)::OFactoryComponentHelper +merge cppu::PropertySetMixinImpl with cppu::PropertySetMixin +merge dbaccess::IPropertyContainer with dbaccess::OColumn +merge dbaccess::IRefreshListener with dbaccess::OConnection +merge dbaccess::OColumnWrapper with dbaccess::OTableColumnDescriptorWrapper +merge dbaccess::OComponentDefinition_Impl with dbaccess::OCommandDefinition_Impl +merge dbahsql::AlterStmtParser with dbahsql::FbAlterStmtParser +merge dbahsql::CreateStmtParser with dbahsql::FbCreateStmtParser +merge dbaui::IController with dbaui::OGenericUnoController +merge dbaui::IEntryFilter with dbaui::(anonymous namespace)::FilterByEntryDataId +merge dbaui::IUpdateHelper with dbaui::OParameterUpdateHelper +merge dbaui::OGenericUnoController with dbaui::OApplicationController +merge dbaui::OSQLNameEntry with dbaui::OPropColumnEditCtrl +merge dbaui::OTableRowView with dbaui::OTableEditorCtrl +merge dbaui::OTableWindowData with dbaui::OQueryTableWindowData +merge dbaui::SbaGridListener with dbaui::SbaXDataBrowserController +merge dbp::OGridPage with dbp::OGridFieldsSelection +merge dbtools::ISQLStatementHelper with connectivity::mysql::OTables +merge detail::ScVbaHlinkContainerMember with ScVbaHyperlinks +merge drawinglayer::primitive2d::ObjectAndViewTransformationDependentPrimitive2D with drawinglayer::primitive2d::DiscreteBitmapPrimitive2D +merge drawinglayer::primitive2d::ViewTransformationDependentPrimitive2D with drawinglayer::primitive2d::WallpaperBitmapPrimitive2D +merge drawinglayer::processor3d::DefaultProcessor3D with drawinglayer::processor3d::ZBufferProcessor3D +merge drawinglayer::texture::GeoTexSvxBitmapEx with drawinglayer::texture::GeoTexSvxBitmapExTiled +merge fileaccess::Notifier with fileaccess::BaseContent +merge framework::OReadStatusBarDocumentHandler_Base with framework::OReadStatusBarDocumentHandler +merge framework::OReadToolBoxDocumentHandler_Base with framework::OReadToolBoxDocumentHandler +merge framework::SaxNamespaceFilter_Base with framework::SaxNamespaceFilter +merge frm::IEngineStatusListener with frm::RichTextControlImpl +merge frm::IEngineTextChangeListener with frm::ORichTextModel +merge frm::IFeatureDispatcher with frm::OFormNavigationHelper +merge frm::IMultiAttributeDispatcher with frm::RichTextControl +merge frm::ITextAttributeListener with frm::OAttributeDispatcher +merge frm::ITextSelectionListener with frm::ORichTextPeer +merge frm::OFormComponents with frm::ODatabaseForm +merge ftp::CurlInput with (anonymous namespace)::InsertData +merge ftp::ResultSetBase with ftp::ResultSetI +merge gfx::DrawCommand with gfx::DrawBase +merge gfx::GradientInfo with gfx::LinearGradientInfo +merge gio::Seekable with gio::OutputStream +merge oglcanvas::IBufferContext with oglcanvas::(anonymous namespace)::BufferContextImpl +merge old_SdrDownCompat with SdIOCompat +merge oox::SequenceSeekableStream with oox::SequenceInputStream +merge oox::core::FilterBase with oox::core::XmlFilterBase +merge oox::drawingml::LayoutAtomVisitor with oox::drawingml::LayoutAtomVisitorBase +merge oox::drawingml::TextRun with oox::drawingml::TextField +merge oox::dump::ConstList with oox::dump::MultiList +merge oox::dump::FlagsList with oox::dump::CombiList +merge oox::dump::ItemFormat with oox::dump::CombiList::ExtItemFormat +merge oox::dump::OleStreamObject with oox::dump::OleCompObjObject +merge oox::dump::OutputObjectBase with oox::dump::InputObjectBase +merge oox::dump::RecordObjectBase with oox::dump::SequenceRecordObjectBase +merge oox::formulaimport::XmlStream with oox::formulaimport::XmlStreamBuilder +merge oox::ole::AxListBoxModel with oox::ole::HtmlSelectModel +merge oox::ole::AxTextBoxModel with oox::ole::HtmlTextBoxModel +merge oox::ole::VbaFilterConfig with oox::ole::VbaProject +merge oox::vml::CustomShape with oox::vml::ComplexShape +merge oox::vml::ShapeType with oox::vml::ShapeBase +merge oox::xls::FormulaParserImpl with oox::xls::(anonymous namespace)::OoxFormulaParserImpl +merge oox::xls::FormulaProcessorBase with oox::xls::FormulaParser +merge oox::xls::FunctionProvider with oox::xls::OpCodeProvider +merge oox::xls::IWorksheetProgress with oox::xls::WorksheetGlobals +merge pcr::(anonymous namespace)::BroadcastHelperBase with pcr::(anonymous namespace)::ShapeGeometryChangeNotifier +merge pcr::(anonymous namespace)::ISQLCommandPropertyUI with pcr::(anonymous namespace)::SQLCommandPropertyUI +merge pcr::CommonBehaviourControlHelper with pcr::CommonBehaviourControl +merge pcr::IButtonClickListener with pcr::OBrowserListBox +merge pcr::IPropertyControlObserver with pcr::OPropertyBrowserController +merge pcr::IPropertyInfoService with pcr::OPropertyInfoService +merge pcr::IPropertyLineListener with pcr::OPropertyBrowserController +merge pcr::ISQLCommandAdapter with pcr::(anonymous namespace)::ISQLCommandPropertyUI +merge pcr::PropertyHandler with pcr::PropertyHandlerComponent +merge psp::(anonymous namespace)::Ascii85Encoder with psp::(anonymous namespace)::LZWEncoder +merge psp::PrinterBmp with (anonymous namespace)::SalPrinterBmp +merge registry::tools::Options with (anonymous namespace)::Options_Impl +merge reportdesign::ITraverseReport with rptui::(anonymous namespace)::NavigatorTree +merge rptui::AnyConverter with rptui::(anonymous namespace)::ParaAdjust +merge rptui::IConditionalFormatAction with rptui::ConditionalFormattingDialog +merge sax_fastparser::FastSaxSerializer::ForMerge with sax_fastparser::FastSaxSerializer::ForSort +merge sax_fastparser::ForMergeBase with sax_fastparser::FastSaxSerializer::ForMerge +merge sc::CompiledFormula with sc::opencl::(anonymous namespace)::DynamicKernel +merge sc::FormulaGroupInterpreter with sc::opencl::FormulaGroupInterpreterOpenCL +merge sc::opencl::(anonymous namespace)::SumOfProduct with sc::opencl::(anonymous namespace)::OpSumProduct +merge sc::opencl::Cumipmt with sc::opencl::OpCumipmt +merge sc::opencl::Fvschedule with sc::opencl::OpFvschedule +merge sc::opencl::IRR with sc::opencl::OpIRR +merge sc::opencl::MIRR with sc::opencl::OpMIRR +merge sc::opencl::OpBase with sc::opencl::SlidingFunctionBase +merge sc::opencl::PriceMat with sc::opencl::OpPriceMat +merge sc::opencl::RATE with sc::opencl::OpIntrate +merge sc::opencl::RRI with sc::opencl::OpRRI +merge sc::opencl::XNPV with sc::opencl::OpXNPV +merge sc_apitest::(anonymous namespace)::TempFileBase with sc_apitest::ScDDELinkObj +merge sd::BroadcastHelperOwner with sd::DrawController +merge sd::ClientInfo with sd::ClientInfoInternal +merge sd::IBluetoothSocket with sd::BufferedStreamSocket +merge sd::ICustomAnimationListController with sd::CustomAnimationPane +merge sd::ZeroconfService with sd::AvahiNetworkService +merge sd::sidebar::MasterPageContainerFiller::ContainerAdapter with sd::sidebar::MasterPageContainer::Implementation +merge sd::sidebar::MasterPageContainerQueue::ContainerAdapter with sd::sidebar::MasterPageContainer::Implementation +merge sd::slidesorter::view::(anonymous namespace)::AnimatorAccess with sd::slidesorter::view::InsertAnimator::Implementation +merge sd::slidesorter::view::ILayerInvalidator with sd::slidesorter::view::(anonymous namespace)::LayerInvalidator +merge sdext::presenter::IPresentationTime with sdext::presenter::(anonymous namespace)::PresentationTimeLabel +merge sdext::presenter::PresenterClockTimer::Listener with sdext::presenter::(anonymous namespace)::TimeLabel::Listener +merge sdext::presenter::PresenterScrollBar with sdext::presenter::PresenterVerticalScrollBar +merge sdext::presenter::PresenterSlidePreview with sdext::presenter::(anonymous namespace)::NextSlidePreview +merge sdr::SelectionController with sdr::table::SvxTableController +merge sdr::contact::ObjectContactOfPagePainter with sdr::contact::PagePrimitiveExtractor +merge sdr::table::TableDesignUser with sdr::table::SdrTableObjImpl +merge sfx2::IXmlIdRegistry with sfx2::XmlIdRegistry +merge sfx2::ThreadHelpBase2 with sfx2::PreventDuplicateInteraction +merge slideshow::internal::(anonymous namespace)::EventContainer with slideshow::internal::ClickEventHandler +merge slideshow::internal::AnimationFunction with slideshow::internal::ExpressionNode +merge slideshow::internal::AnimationNode with slideshow::internal::BaseNode +merge slideshow::internal::AttributableShape with slideshow::internal::DrawShape +merge slideshow::internal::BoolAnimation with slideshow::internal::(anonymous namespace)::GenericAnimation +merge slideshow::internal::ClickEventHandler with slideshow::internal::SkipEffectEventHandler +merge slideshow::internal::ColorAnimation with slideshow::internal::(anonymous namespace)::GenericAnimation +merge slideshow::internal::ContinuousKeyTimeActivityBase with slideshow::internal::(anonymous namespace)::ValuesActivity +merge slideshow::internal::DocTreeNodeSupplier with slideshow::internal::DrawShape +merge slideshow::internal::EnumAnimation with slideshow::internal::(anonymous namespace)::GenericAnimation +merge slideshow::internal::HSLColorAnimation with slideshow::internal::(anonymous namespace)::HSLWrapper +merge slideshow::internal::HyperlinkArea with slideshow::internal::DrawShape +merge slideshow::internal::HyperlinkHandler with (anonymous namespace)::SlideShowImpl::SeparateListenerImpl +merge slideshow::internal::IExternalMediaShapeBase with slideshow::internal::ExternalShapeBase +merge slideshow::internal::MediaFileManager with (anonymous namespace)::SlideShowImpl +merge slideshow::internal::PairAnimation with slideshow::internal::(anonymous namespace)::TupleAnimation +merge slideshow::internal::PauseEventHandler with slideshow::internal::SoundPlayer +merge slideshow::internal::ScreenUpdater::UpdateLock with (anonymous namespace)::UpdateLock +merge slideshow::internal::ShapeListenerEventHandler with slideshow::internal::ShapeManagerImpl +merge slideshow::internal::ShapeManager with slideshow::internal::SubsettableShapeManager +merge slideshow::internal::Slide with slideshow::internal::(anonymous namespace)::SlideImpl +merge slideshow::internal::SnakeWipe with slideshow::internal::ParallelSnakesWipe +merge slideshow::internal::SpiralWipe with slideshow::internal::BoxSnakesWipe +merge slideshow::internal::StringAnimation with slideshow::internal::(anonymous namespace)::GenericAnimation +merge slideshow::internal::SubsettableShapeManager with slideshow::internal::ShapeManagerImpl +merge slideshow::internal::UserPaintEventHandler with slideshow::internal::PaintOverlayHandler +merge slideshow::internal::View with slideshow::internal::UnoView +merge slideshow::internal::ViewRepaintHandler with (anonymous namespace)::SlideShowImpl::SeparateListenerImpl +merge slideshow::internal::ViewUpdate with slideshow::internal::ShapeManagerImpl +merge slideshow::internal::ZigZagWipe with slideshow::internal::BarnZigZagWipe +merge store::OStorePageBIOS with store::OStorePageManager +merge svgio::svgreader::Visitor with svgio::svgreader::SvgDrawVisitor +merge svl::StyleSheetCallback with (anonymous namespace)::AddStyleSheetCallback +merge svl::StyleSheetDisposer with (anonymous namespace)::StyleSheetDisposerFunctor +merge svt::FrameStatusListener with (anonymous namespace)::ToolbarPopupStatusListener +merge svt::IEnumerationResultHandler with SvtFileView_Impl +merge svt::IFilePickerController with SvtFileDialog_Base +merge svt::IFilePickerListener with SvtFilePicker +merge svt::PopupWindowController_Base with svt::PopupWindowController +merge svt::table::IColumnModel with svt::table::UnoGridColumnFacade +merge svt::table::ITableControl with svt::table::TableControl_Impl +merge svt::table::ITableDataSort with svt::table::UnoControlTableModel +merge svt::table::ITableInputHandler with svt::table::DefaultInputHandler +merge svt::table::ITableModelListener with svt::table::TableControl_Impl +merge svt::table::ITableRenderer with svt::table::GridTableRenderer +merge svx::IContextRequestObserver with svx::FmTextControlShell +merge svx::IControllerFeatureInvalidation with FmXFormShell +merge svx::IFocusObserver with svx::FmTextControlShell +merge svx::IPropertyValueProvider with svx::PropertyValueProvider +merge svx::RegistrationItemSetHolder with svx::DatabaseRegistrationDialog +merge svx::sidebar::SvxShapeCommandsMap with svx::sidebar::DefaultShapesPanel +merge svxform::DispatchInterceptor with svxform::FormController +merge sw::ClientIteratorBase with SwIterator +merge sw::ICoreFrameStyle with (anonymous namespace)::SwXFrameStyle +merge sw::IShellCursorSupplier with SwCursorShell +merge sw::Meta with sw::MetaField +merge sw::ModelTraverseHandler with sw::(anonymous namespace)::IndexingNodeHandler +merge sw::WriterListener with SwClient +merge sw::mark::Bookmark with sw::mark::CrossRefBookmark +merge sw::mark::ContentIdxStore with (anonymous namespace)::ContentIdxStoreImpl +merge sw::mark::DdeBookmark with sw::mark::Bookmark +merge sw::mark::IBookmark with sw::mark::Bookmark +merge sw::mark::ICheckboxFieldmark with sw::mark::CheckboxFieldmark +merge sw::mark::IDateFieldmark with sw::mark::DateFieldmark +merge sw::util::WrtRedlineAuthor with WW8_WrtRedlineAuthor +merge testHFBase with testHFLinkToPrev +merge ucbhelper::ActiveDataSink_Base with ucbhelper::ActiveDataSink +merge ucbhelper::CommandEnvironment_Base with ucbhelper::CommandEnvironment +merge ucbhelper::InterceptedInteraction_Base with ucbhelper::InterceptedInteraction +merge utl::OInputStreamWrapper_Base with utl::OInputStreamWrapper +merge vcl::DeletionNotifier with SalFrame +merge vcl::ExtOutDevData with vcl::PDFExtOutDevData +merge vcl::SolarThreadExecutor with vcl::solarthread::detail::GenericSolarThreadExecutor +merge vcl::SwapFile with ImpSwapFile +merge vcl::pdf::PDFium with vcl::pdf::(anonymous namespace)::PDFiumImpl +merge vcl::pdf::PDFiumAnnotation with vcl::pdf::(anonymous namespace)::PDFiumAnnotationImpl +merge vcl::pdf::PDFiumBitmap with vcl::pdf::(anonymous namespace)::PDFiumBitmapImpl +merge vcl::pdf::PDFiumDocument with vcl::pdf::(anonymous namespace)::PDFiumDocumentImpl +merge vcl::pdf::PDFiumPage with vcl::pdf::(anonymous namespace)::PDFiumPageImpl +merge vcl::pdf::PDFiumPageObject with vcl::pdf::(anonymous namespace)::PDFiumPageObjectImpl +merge vcl::pdf::PDFiumPathSegment with vcl::pdf::(anonymous namespace)::PDFiumPathSegmentImpl +merge vcl::pdf::PDFiumSearchHandle with vcl::pdf::(anonymous namespace)::PDFiumSearchHandleImpl +merge vcl::pdf::PDFiumSignature with vcl::pdf::(anonymous namespace)::PDFiumSignatureImpl +merge vcl::pdf::PDFiumTextPage with vcl::pdf::(anonymous namespace)::PDFiumTextPageImpl +merge vclcanvas::CanvasCustomSpriteSpriteBase_Base with canvas::CanvasBase +merge vclcanvas::Sprite with vclcanvas::CanvasCustomSpriteSpriteBase_Base +merge vclcanvas::SpriteCanvasBaseSpriteSurface_Base with canvas::CanvasBase +merge webdav_ucp::DAVAuthListener with webdav_ucp::DAVAuthListener_Impl +merge webdav_ucp::DAVSession with webdav_ucp::NeonSession +merge weld::AssistantController with vcl::WizardMachine +merge weld::WidgetStatusListener_Base with weld::WidgetStatusListener +merge writerfilter::Stream with writerfilter::LoggedStream +merge writerfilter::Table with writerfilter::LoggedTable +merge writerfilter::dmapper::TableManager with writerfilter::dmapper::DomainMapperTableManager +merge writerfilter::ooxml::OOXMLDocument with writerfilter::ooxml::OOXMLDocumentImpl +merge writerfilter::ooxml::OOXMLFastContextHandlerLinear with writerfilter::ooxml::OOXMLFastContextHandlerMath +merge writerfilter::ooxml::OOXMLStream with writerfilter::ooxml::OOXMLStreamImpl +merge writerfilter::ooxml::OOXMLUniversalMeasureValue with writerfilter::ooxml::OOXMLNthPtMeasureValue +merge writerfilter::rtftok::RTFDocument with writerfilter::rtftok::RTFDocumentImpl +merge ww8::WW8Struct with ww8::WW8Sttb +merge xforms::OValueLimitedType_Base with xforms::OValueLimitedType +merge xmloff::IEventAttacher with xmloff::OElementImport +merge xmloff::IEventAttacherManager with xmloff::ODefaultEventAttacherManager +merge xmloff::IFormsExportContext with xmloff::OFormLayerXMLExport_Impl +merge xmloff::OPropertyExport with xmloff::OElementExport +merge xmloff::OPropertyImport with xmloff::OElementImport +merge xmloff::OURLReferenceImport with xmloff::OButtonImport diff --git a/compilerplugins/clang/methodcycles.cxx b/compilerplugins/clang/methodcycles.cxx new file mode 100644 index 000000000..7b58a4bb5 --- /dev/null +++ b/compilerplugins/clang/methodcycles.cxx @@ -0,0 +1,378 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "clang/AST/Attr.h" + +#include "config_clang.h" + +#include "plugin.hxx" + +/** +What we are looking for here are methods that are not reachable from any of the program +entry points. +"Entry points" includes main, and various binary API + +Mostly that means we end up finding cycles of methods i.e. methods that refer to each +other, but are not reachable. + +It does so, by dumping various call/definition info to a log file. +Be warned that it produces around 20G of log file. + +Then we will post-process the log file with a python script, which takes about +15min to run on a fast machine. + +The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='methodcycles' check + $ ./compilerplugins/clang/methodcycles.py + +Note that the actual process may involve a fair amount of undoing, hand editing, and general messing around +to get it to work :-) + +*/ + +namespace +{ +struct MyFuncInfo +{ + std::string returnType; + std::string nameAndParams; + std::string sourceLocation; +}; +bool operator<(const MyFuncInfo& lhs, const MyFuncInfo& rhs) +{ + return std::tie(lhs.returnType, lhs.nameAndParams) + < std::tie(rhs.returnType, rhs.nameAndParams); +} + +// try to limit the voluminous output a little +static std::multimap callMap; +static std::set definitionSet; + +class MethodCycles : public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit MethodCycles(loplugin::InstantiationData const& data) + : Plugin(data) + { + } + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + + std::string output; + for (const MyFuncInfo& s : definitionSet) + output += "definition:\t" + s.returnType + "\t" + s.nameAndParams + "\t" + + s.sourceLocation + "\n"; + for (const auto& pair : callMap) + { + if (!isLocationMine(pair.first->getLocation()) + || !isLocationMine(pair.second->getLocation())) + continue; + auto niceNameFrom = niceName(pair.first); + auto niceNameTo = niceName(pair.second); + output += "call:\t" + niceNameFrom.returnType + "\t" + niceNameFrom.nameAndParams + "\t" + + niceNameTo.returnType + "\t" + niceNameTo.nameAndParams + "\n"; + } + std::ofstream myfile; + myfile.open(WORKDIR "/loplugin.methodcycles.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitCallExpr(CallExpr*); + bool VisitFunctionDecl(const FunctionDecl* decl); + bool VisitDeclRefExpr(const DeclRefExpr*); + bool VisitCXXConstructExpr(const CXXConstructExpr*); + + bool TraverseFunctionDecl(FunctionDecl*); + bool TraverseCXXMethodDecl(CXXMethodDecl*); + bool TraverseCXXConstructorDecl(CXXConstructorDecl*); + bool TraverseCXXConversionDecl(CXXConversionDecl*); + bool TraverseCXXDestructorDecl(CXXDestructorDecl*); + bool TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl*); + +private: + void logCallToRootMethods(const FunctionDecl* functionDeclFrom, + const FunctionDecl* functionDeclTo); + void findRoots(const FunctionDecl* functionDecl, + std::unordered_set& roots); + MyFuncInfo niceName(const FunctionDecl* functionDecl); + bool isLocationMine(SourceLocation loc); + std::string toString(SourceLocation loc); + FunctionDecl const* currentFunctionDecl = nullptr; +}; + +MyFuncInfo MethodCycles::niceName(const FunctionDecl* functionDecl) +{ + if (functionDecl->getInstantiatedFromMemberFunction()) + functionDecl = functionDecl->getInstantiatedFromMemberFunction(); + else if (functionDecl->getTemplateInstantiationPattern()) + functionDecl = functionDecl->getTemplateInstantiationPattern(); + + MyFuncInfo aInfo; + if (!isa(functionDecl)) + { + aInfo.returnType = functionDecl->getReturnType().getCanonicalType().getAsString(); + } + else + { + aInfo.returnType = ""; + } + + if (auto methodDecl = dyn_cast(functionDecl)) + { + const CXXRecordDecl* recordDecl = methodDecl->getParent(); + aInfo.nameAndParams + = recordDecl->getQualifiedNameAsString() + "::" + functionDecl->getNameAsString() + "("; + } + else + { + aInfo.nameAndParams = functionDecl->getQualifiedNameAsString() + "("; + } + bool bFirst = true; + for (const ParmVarDecl* pParmVarDecl : functionDecl->parameters()) + { + if (bFirst) + bFirst = false; + else + aInfo.nameAndParams += ","; + aInfo.nameAndParams += pParmVarDecl->getType().getCanonicalType().getAsString(); + } + aInfo.nameAndParams += ")"; + if (isa(functionDecl) && dyn_cast(functionDecl)->isConst()) + { + aInfo.nameAndParams += " const"; + } + + aInfo.sourceLocation = toString(functionDecl->getLocation()); + + return aInfo; +} + +std::string MethodCycles::toString(SourceLocation loc) +{ + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc(loc); + StringRef name = getFilenameOfLocation(expansionLoc); + std::string sourceLocation + = std::string(name.substr(strlen(SRCDIR) + 1)) + ":" + + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(sourceLocation); + return sourceLocation; +} + +bool MethodCycles::isLocationMine(SourceLocation loc) +{ + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc(loc); + if (compiler.getSourceManager().isInSystemHeader(expansionLoc)) + return false; + const char* bufferName = compiler.getSourceManager().getPresumedLoc(expansionLoc).getFilename(); + if (bufferName == NULL) + return false; + if (loplugin::hasPathnamePrefix(bufferName, WORKDIR "/") + || loplugin::hasPathnamePrefix(bufferName, BUILDDIR "/") + || loplugin::hasPathnamePrefix(bufferName, SRCDIR "/")) + return true; // ok + return false; +} + +void MethodCycles::logCallToRootMethods(const FunctionDecl* functionDeclFrom, + const FunctionDecl* functionDeclTo) +{ + if (!functionDeclFrom) + { + // template magic mostly, but also things called from initialisers + return; + } + functionDeclFrom = functionDeclFrom->getCanonicalDecl(); + functionDeclTo = functionDeclTo->getCanonicalDecl(); + + std::unordered_set fromRoots; + findRoots(functionDeclFrom, fromRoots); + std::unordered_set toRoots; + findRoots(functionDeclTo, toRoots); + + for (auto const& from : fromRoots) + for (auto const& to : toRoots) + callMap.insert({ from, to }); +} + +void MethodCycles::findRoots(const FunctionDecl* functionDecl, + std::unordered_set& roots) +{ + bool bCalledSuperMethod = false; + if (auto methodDecl = dyn_cast(functionDecl)) + { + // For virtual/overriding methods, we need to pretend we called from/to root method(s), + // so that they get marked as used. + for (auto it = methodDecl->begin_overridden_methods(); + it != methodDecl->end_overridden_methods(); ++it) + { + findRoots(*it, roots); + bCalledSuperMethod = true; + } + } + if (!bCalledSuperMethod) + { + while (functionDecl->getTemplateInstantiationPattern()) + functionDecl = functionDecl->getTemplateInstantiationPattern(); + if (functionDecl->getLocation().isValid()) + roots.insert(functionDecl); + } +} + +bool MethodCycles::VisitCallExpr(CallExpr* expr) +{ + // Note that I don't ignore ANYTHING here, because I want to get calls to my code that result + // from template instantiation deep inside the STL and other external code + + FunctionDecl* calleeFunctionDecl = expr->getDirectCallee(); + if (calleeFunctionDecl == nullptr) + { + Expr* callee = expr->getCallee()->IgnoreParenImpCasts(); + DeclRefExpr* dr = dyn_cast(callee); + if (dr) + { + calleeFunctionDecl = dyn_cast(dr->getDecl()); + if (calleeFunctionDecl) + goto gotfunc; + } + return true; + } + +gotfunc: + + if (currentFunctionDecl != calleeFunctionDecl) + // ignore recursive calls + logCallToRootMethods(currentFunctionDecl, calleeFunctionDecl); + + return true; +} + +bool MethodCycles::VisitCXXConstructExpr(const CXXConstructExpr* constructExpr) +{ + // Note that I don't ignore ANYTHING here, because I want to get calls to my code that result + // from template instantiation deep inside the STL and other external code + + const CXXConstructorDecl* constructorDecl = constructExpr->getConstructor(); + constructorDecl = constructorDecl->getCanonicalDecl(); + + if (!constructorDecl->getLocation().isValid()) + { + return true; + } + + logCallToRootMethods(currentFunctionDecl, constructorDecl); + + return true; +} + +bool MethodCycles::VisitFunctionDecl(const FunctionDecl* functionDecl) +{ + const FunctionDecl* canonicalFunctionDecl = functionDecl->getCanonicalDecl(); + if (functionDecl->isDeleted()) + return true; + // don't care about compiler-generated functions + if (functionDecl->isImplicit()) + return true; + if (!canonicalFunctionDecl->getLocation().isValid()) + return true; + // ignore method overrides, since the call will show up as being directed to the root method + const CXXMethodDecl* methodDecl = dyn_cast(functionDecl); + if (methodDecl + && (methodDecl->size_overridden_methods() != 0 || methodDecl->hasAttr())) + return true; + if (!isLocationMine(canonicalFunctionDecl->getLocation())) + return true; + + MyFuncInfo funcInfo = niceName(canonicalFunctionDecl); + definitionSet.insert(funcInfo); + return true; +} + +bool MethodCycles::VisitDeclRefExpr(const DeclRefExpr* declRefExpr) +{ + const FunctionDecl* functionDecl = dyn_cast(declRefExpr->getDecl()); + if (!functionDecl) + { + return true; + } + logCallToRootMethods(currentFunctionDecl, functionDecl->getCanonicalDecl()); + + return true; +} + +bool MethodCycles::TraverseFunctionDecl(FunctionDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseFunctionDecl(f); + currentFunctionDecl = copy; + return ret; +} +bool MethodCycles::TraverseCXXMethodDecl(CXXMethodDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(f); + currentFunctionDecl = copy; + return ret; +} +bool MethodCycles::TraverseCXXConversionDecl(CXXConversionDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseCXXConversionDecl(f); + currentFunctionDecl = copy; + return ret; +} +bool MethodCycles::TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseCXXDeductionGuideDecl(f); + currentFunctionDecl = copy; + return ret; +} +bool MethodCycles::TraverseCXXConstructorDecl(CXXConstructorDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseCXXConstructorDecl(f); + currentFunctionDecl = copy; + return ret; +} +bool MethodCycles::TraverseCXXDestructorDecl(CXXDestructorDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseCXXDestructorDecl(f); + currentFunctionDecl = copy; + return ret; +} + +loplugin::Plugin::Registration X("methodcycles", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/methodcycles.partition.results b/compilerplugins/clang/methodcycles.partition.results new file mode 100644 index 000000000..9c31146da --- /dev/null +++ b/compilerplugins/clang/methodcycles.partition.results @@ -0,0 +1,8 @@ +callDict size 2 + + +void sax_fastparser::FastSaxSerializer::ForMerge::print() +sax/source/tools/fastserializer.hxx:185 + +std::__cxx11::basic_string, std::allocator > writerfilter::ooxml::OOXMLFastContextHandler::getType() const +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:85 diff --git a/compilerplugins/clang/methodcycles.py b/compilerplugins/clang/methodcycles.py new file mode 100755 index 000000000..52b950b86 --- /dev/null +++ b/compilerplugins/clang/methodcycles.py @@ -0,0 +1,266 @@ +#!/usr/bin/python3 + +from collections import defaultdict +import io +import re +import subprocess +import sys + +# -------------------------------------------------------------------------------------------- +# globals +# -------------------------------------------------------------------------------------------- + +definitionSet = set() # set of method_name +definitionToSourceLocationMap = dict() + +# for the "unused methods" analysis +callDict = defaultdict(set) # map of from_method_name -> set(method_name) + +# clang does not always use exactly the same numbers in the type-parameter vars it generates +# so I need to substitute them to ensure we can match correctly. +normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") +def normalizeTypeParams( line ): + line = normalizeTypeParamsRegex.sub("type-parameter-?-?", line) + # make some of the types a little prettier + line = line.replace("std::__debug", "std::") + line = line.replace("class ", "") + line = line.replace("struct ", "") + line = line.replace("_Bool", "bool") + return line + +# -------------------------------------------------------------------------------------------- +# primary input loop +# -------------------------------------------------------------------------------------------- + +cnt = 0 +with io.open("workdir/loplugin.methodcycles.log", "r", buffering=1024*1024) as txt: + for line in txt: + tokens = line.strip().split("\t") + if tokens[0] == "definition:": + returnType = tokens[1] + nameAndParams = tokens[2] + sourceLocation = tokens[3] + funcInfo = (normalizeTypeParams(returnType) + " " + normalizeTypeParams(nameAndParams)).strip() + definitionSet.add(funcInfo) + definitionToSourceLocationMap[funcInfo] = sourceLocation + elif tokens[0] == "call:": + returnTypeFrom = tokens[1] + nameAndParamsFrom = tokens[2] + returnTypeTo = tokens[3] + nameAndParamsTo = tokens[4] + caller = (normalizeTypeParams(returnTypeFrom) + " " + normalizeTypeParams(nameAndParamsFrom)).strip() + callee = (normalizeTypeParams(returnTypeTo) + " " + normalizeTypeParams(nameAndParamsTo)).strip() + callDict[caller].add(callee) + else: + print( "unknown line: " + line) + cnt = cnt + 1 + #if cnt > 100000: break + +# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[1]) + [v[0]] +def sort_set_by_natural_key(s): + return sorted(s, key=lambda v: v_sort_key(v)) + + +# -------------------------------------------------------------------------------------------- +# analysis +# -------------------------------------------------------------------------------------------- + +# follow caller-callee chains, removing all methods reachable from a root method +def remove_reachable(callDict, startCaller): + worklist = list() + worklist.append(startCaller) + while len(worklist) > 0: + caller = worklist.pop() + if not caller in callDict: + continue + calleeSet = callDict[caller] + del callDict[caller] + if caller in definitionSet: + definitionSet.remove(caller) + for c in calleeSet: + worklist.append(c) + +# look for all the external entry points and remove code called from there +to_be_removed = set() +to_be_removed.add("int main(int,char **)") +# random dynload entrypoints that we don't otherwise find +to_be_removed.add("bool TestImportOLE2(SvStream &)") +to_be_removed.add("void SbiRuntime::StepREDIMP()") +to_be_removed.add("_object * (anonymous namespace)::createUnoStructHelper(_object *,_object *,_object *)"); +for caller in definitionSet: + if not caller in definitionToSourceLocationMap: + to_be_removed.append(caller) + continue + location = definitionToSourceLocationMap[caller] + if "include/com/" in location \ + or "include/cppu/" in location \ + or "include/cppuhelper/" in location \ + or "include/osl/" in location \ + or "include/rtl/" in location \ + or "include/sal/" in location \ + or "include/salhelper/" in location \ + or "include/typelib/" in location \ + or "include/uno/" in location \ + or "workdir/UnpackedTarball/" in location \ + or "workdir/UnoApiHeadersTarget/" in location \ + or "workdir/CustomTarget/officecfg/" in location \ + or "workdir/LexTarget/" in location \ + or "workdir/CustomTarget/i18npool/localedata/" in location \ + or "workdir/SdiTarget/" in location \ + or "/qa/" in location \ + or "include/test/" in location: + to_be_removed.add(caller) + # TODO calls to destructors are not mentioned in the AST, so we'll just have to assume they get called, + # which is not ideal + if "::~" in caller: + to_be_removed.add(caller) + # dyload entry points for VCL builder + if "(VclPtr & rRet, const VclPtr & pParent, VclBuilder::stringmap & rMap)" in caller: + to_be_removed.add(caller) + if "(VclPtr &,const VclPtr &,std::::map, std::allocator > > &)" in caller: + to_be_removed.add(caller) +# find all the UNO load-by-symbol-name entrypoints +uno_constructor_entrypoints = set() +git_grep_process = subprocess.Popen("git grep -h 'constructor=' -- *.component", stdout=subprocess.PIPE, shell=True) +with git_grep_process.stdout as txt: + for line in txt: + idx1 = line.find(b"\"") + idx2 = line.find(b"\"", idx1 + 1) + func = line[idx1+1 : idx2] + uno_constructor_entrypoints.add(func.decode('utf-8')) +for caller in callDict: + if "(com::sun::star::uno::XComponentContext *,const com::sun::star::uno::Sequence &)" in caller: + for func in uno_constructor_entrypoints: + if func in caller: + to_be_removed.add(caller) +# remove everything reachable from the found entry points +for caller in to_be_removed: + remove_reachable(callDict, caller) +for caller in callDict: + callDict[caller] -= to_be_removed + +# create a reverse call graph +inverseCallDict = defaultdict(set) # map of from_method_name -> set(method_name) +for caller in callDict: + for callee in callDict[caller]: + inverseCallDict[callee].add(caller) + +print_tree_recurse_set = set() # protect against cycles +def print_tree(f, callDict, caller, depth): + if depth == 0: + f.write("\n") # add an empty line before each tree + print_tree_recurse_set.clear() + # protect against cycles + if caller in print_tree_recurse_set: + return + # when printing out trees, things that are not in the map are things that are reachable, + # so we're not interested in them + if not caller in callDict: + return + print_tree_recurse_set.add(caller) + f.write(" " * depth + caller + "\n") + f.write(" " * depth + definitionToSourceLocationMap[caller] + "\n") + calleeSet = callDict[caller] + for c in calleeSet: + print_tree(f, callDict, c, depth+1) + +# find possible roots (ie. entrypoints) by looking for methods that are not called +def dump_possible_roots(): + possibleRootList = list() + for caller in callDict: + if not caller in inverseCallDict and caller in definitionToSourceLocationMap: + possibleRootList.append(caller) + possibleRootList.sort() + + # print out first 100 trees of caller->callees + count = 0 + with open("compilerplugins/clang/methodcycles.roots", "wt") as f: + f.write("callDict size " + str(len(callDict)) + "\n") + f.write("possibleRootList size " + str(len(possibleRootList)) + "\n") + f.write("\n") + for caller in possibleRootList: + f.write(caller + "\n") + f.write(" " + definitionToSourceLocationMap[caller] + "\n") + #print_tree(f, caller, 0) + count = count + 1 + #if count>1000: break + +# Look for cycles in a directed graph +# Adapted from: +# https://codereview.stackexchange.com/questions/86021/check-if-a-directed-graph-contains-a-cycle +def print_cycles(): + with open("compilerplugins/clang/methodcycles.results", "wt") as f: + path = set() + visited = set() + + def printPath(path): + if len(path) < 2: + return + # we may have found a cycle, but if the cycle is called from outside the cycle + # the code is still in use. + for p in path: + for caller in inverseCallDict[p]: + if not caller in path: + return + f.write("found cycle\n") + for p in path: + f.write(" " + p + "\n") + f.write(" " + definitionToSourceLocationMap[p] + "\n") + f.write("\n") + + def checkCyclic(vertex): + if vertex in visited: + return + visited.add(vertex) + path.add(vertex) + if vertex in callDict: + for neighbour in callDict[vertex]: + if neighbour in path: + printPath(path) + break + else: + checkCyclic(neighbour) + path.remove(vertex) + + for caller in callDict: + checkCyclic(caller) + +print_cycles() + +# print partitioned sub-graphs +def print_partitions(): + callDict2 = callDict + # Remove anything with no callees, and that is itself not called. + # After this stage, we should only be left with closed sub-graphs ie. partitions + while True: + to_be_removed.clear() + for caller in callDict2: + if len(callDict2[caller]) == 0 \ + or not caller in inverseCallDict[caller]: + to_be_removed.add(caller) + if len(to_be_removed) == 0: + break + for caller in to_be_removed: + remove_reachable(callDict2, caller) + for caller in callDict2: + callDict2[caller] -= to_be_removed + + count = 0 + with open("compilerplugins/clang/methodcycles.partition.results", "wt") as f: + f.write("callDict size " + str(len(callDict2)) + "\n") + f.write("\n") + while len(callDict2) > 0: + print_tree(f, callDict2, next(iter(callDict2)), 0) + for c in print_tree_recurse_set: + callDict2.pop(c, None) + count = count + 1 + if count>1000: break + +print_partitions() diff --git a/compilerplugins/clang/methodcycles.results b/compilerplugins/clang/methodcycles.results new file mode 100644 index 000000000..60786eee9 --- /dev/null +++ b/compilerplugins/clang/methodcycles.results @@ -0,0 +1,157 @@ +found cycle + void LogProbe(bool,void *,void *,_typelib_TypeDescriptionReference *,_typelib_MethodParameter *,int,const _typelib_TypeDescription *,void *,void **,_uno_Any **) + cppu/source/LogBridge/LogBridge.cxx:188 + + void uno_ext_getMapping(_uno_Mapping **,_uno_Environment *,_uno_Environment *) + bridges/source/jni_uno/jni_bridge.cxx:514 + + void (anonymous namespace)::traceValue(_typelib_TypeDescriptionReference *,void *) + cppu/source/LogBridge/LogBridge.cxx:128 + +found cycle + void svl::Items_t::fill(typename array, sizeof...(WIDs) / 2>::iterator) + include/svl/whichranges.hxx:52 + + array, sizeof...(WIDs) / 2> svl::Items_t::make() + include/svl/whichranges.hxx:59 + +found cycle + void weld::IconView::select_all() + include/vcl/weld.hxx:1385 + + void weld::IconView::unselect(int) + include/vcl/weld.hxx:1370 + +found cycle + SvTreeListEntry * SvTreeListBox::InsertEntry(const rtl::OUString &,const Image &,const Image &,SvTreeListEntry *,bool,unsigned int,void *) + include/vcl/toolkit/treelistbox.hxx:559 + + SvTreeListEntry * SvTabListBox::InsertEntryToColumn(const rtl::OUString &,const Image &,const Image &,SvTreeListEntry *,unsigned int,unsigned short,void *) + include/vcl/toolkit/svtabbx.hxx:79 + +found cycle + void CGM::ImplDefaultReplacement() + filter/source/graphicfilter/icgm/cgm.hxx:115 + + void CGM::ImplDoClass() + filter/source/graphicfilter/icgm/cgm.hxx:116 + + void CGM::ImplDoClass0() + filter/source/graphicfilter/icgm/cgm.hxx:117 + + unsigned int ImportCGM(SvStream &,const com::sun::star::uno::Reference &,const com::sun::star::uno::Reference &) + filter/source/graphicfilter/icgm/cgm.cxx:686 + + bool CGM::Write(SvStream &) + filter/source/graphicfilter/icgm/cgm.hxx:137 + +found cycle + bool ::operator()(weld::TreeIter &) const + reportdesign/source/ui/dlg/Navigator.cxx:234 + + void basctl::(anonymous namespace)::implCollapseModifiedObjectEntry(weld::TreeIter &,weld::TreeView &) + basctl/source/basicide/baside2b.cxx:2286 + +found cycle + bool ::operator()(weld::TreeIter &) const + reportdesign/source/ui/dlg/Navigator.cxx:234 + + bool FmEntryData::IsEqualWithoutChildren(FmEntryData *) + svx/source/inc/fmexpl.hxx:159 + +found cycle + void sdext::presenter::PresenterToolBar::ProcessEntry(const com::sun::star::uno::Reference &,const sdext::presenter::PresenterToolBar::Context &) + sdext/source/presenter/PresenterToolBar.hxx:183 + + void ::operator()(const rtl::OUString &,const com::sun::star::uno::Reference &) const + sdext/source/presenter/PresenterToolBar.cxx:611 + + void sdext::presenter::(anonymous namespace)::Element::SetModes(const std::shared_ptr &,const std::shared_ptr &,const std::shared_ptr &,const std::shared_ptr &,const std::shared_ptr &) + sdext/source/presenter/PresenterToolBar.cxx:129 + +found cycle + void cppcanvas::internal::ImplRenderer::createActions(GDIMetaFile &,const cppcanvas::internal::ActionFactoryParameters &,bool) + cppcanvas/source/inc/implrenderer.hxx:170 + + cppcanvas::internal::ImplRenderer::ImplRenderer(const std::shared_ptr &,const GDIMetaFile &,const cppcanvas::Renderer::Parameters &) + cppcanvas/source/inc/implrenderer.hxx:122 + + void cppcanvas::internal::ImplRenderer::createGradientAction(const tools::PolyPolygon &,const Gradient &,const cppcanvas::internal::ActionFactoryParameters &,bool,bool) + cppcanvas/source/inc/implrenderer.hxx:185 + +found cycle + void SbxObject::Dump(SvStream &,bool) + include/basic/sbxobj.hxx:80 + + void SbRtl_DumpAllObjects(StarBASIC *,SbxArray &,bool) + basic/source/inc/rtlproto.hxx:290 + + void SbxVariable::Dump(SvStream &,bool) + include/basic/sbxvar.hxx:268 + +found cycle + unsigned long com::sun::star::uno::hash_value(const Reference &) + slideshow/source/inc/tools.hxx:86 + + unsigned long slideshow::internal::hash::operator()(const type-parameter-?-? &) const + slideshow/source/inc/tools.hxx:76 + +found cycle + std::unique_ptr > SdrUndoFactory::CreateUndoPageRemoveMasterPage(SdrPage &) + include/svx/svdundo.hxx:736 + + SdrUndoDelPage::SdrUndoDelPage(SdrPage &) + include/svx/svdundo.hxx:562 + +found cycle + void oox::PropertyMap::dumpCode(const com::sun::star::uno::Reference &) + include/oox/helper/propertymap.hxx:113 + + const char * oox::lclDumpAnyValueCode(const com::sun::star::uno::Any &,int) + oox/source/helper/propertymap.cxx:548 + +found cycle + void ScDPResultMember::DumpState(const ScDPResultMember *,ScDocument *,ScAddress &) const + sc/inc/dptabres.hxx:404 + + void ScDPResultDimension::DumpState(const ScDPResultMember *,ScDocument *,ScAddress &) const + sc/inc/dptabres.hxx:572 + +found cycle + void ScXMLSourceDlg::LoadSourceFileStructure(const rtl::OUString &) + sc/source/ui/inc/xmlsourcedlg.hxx:77 + + void ScXMLSourceDlg::LinkStubBtnPressedHdl(void *,weld::Button &) + sc/source/ui/inc/xmlsourcedlg.hxx:101 + + void (anonymous namespace)::populateTree(weld::TreeView &,orcus::xml_structure_tree::walker &,const orcus::xml_structure_tree::entity_name &,bool,const weld::TreeIter *,ScOrcusXMLTreeParam &) + sc/source/filter/orcus/xmlcontext.cxx:70 + + void ScXMLSourceDlg::SelectSourceFile() + sc/source/ui/inc/xmlsourcedlg.hxx:76 + + void ScXMLSourceDlg::BtnPressedHdl(weld::Button &) + sc/source/ui/inc/xmlsourcedlg.hxx:101 + + ScXMLSourceDlg::ScXMLSourceDlg(SfxBindings *,SfxChildWindow *,weld::Window *,ScDocument *) + sc/source/ui/inc/xmlsourcedlg.hxx:66 + + void ScOrcusXMLContext::loadXMLStructure(weld::TreeView &,ScOrcusXMLTreeParam &) + sc/inc/orcusfilters.hxx:63 + +found cycle + void (anonymous namespace)::getFieldLinks(ScOrcusImportXMLParam::RangeLink &,std::::vector > &,const weld::TreeView &,const weld::TreeIter &) + sc/source/ui/xmlsource/xmlsourcedlg.cxx:448 + + void ScXMLSourceDlg::LinkStubBtnPressedHdl(void *,weld::Button &) + sc/source/ui/inc/xmlsourcedlg.hxx:101 + + void ScXMLSourceDlg::BtnPressedHdl(weld::Button &) + sc/source/ui/inc/xmlsourcedlg.hxx:101 + + ScXMLSourceDlg::ScXMLSourceDlg(SfxBindings *,SfxChildWindow *,weld::Window *,ScDocument *) + sc/source/ui/inc/xmlsourcedlg.hxx:66 + + void ScXMLSourceDlg::OkPressed() + sc/source/ui/inc/xmlsourcedlg.hxx:97 + diff --git a/compilerplugins/clang/moveit.cxx b/compilerplugins/clang/moveit.cxx new file mode 100644 index 000000000..353359e28 --- /dev/null +++ b/compilerplugins/clang/moveit.cxx @@ -0,0 +1,250 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" +#include "check.hxx" + +/* +Look for local variables that can be std::move'd into parameters. + +TODO +(*) Ideally we would use a proper data-flow analysis, to detect that the var is dead after this point, + like the one in clang at include/clang/Analysis/CFG.h +(*) we could expand the set of approved/interesting types +*/ + +namespace +{ +class MoveIt : public loplugin::FilteringPlugin +{ +public: + explicit MoveIt(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual bool preRun() override + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + // false + + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/basic/source/classes/sbunoobj.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/svx/source/svdraw/textchainflow.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/svx/source/unodraw/unoshtxt.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, + SRCDIR "/connectivity/source/drivers/dbase/dindexnode.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/basctl/source/basicide/moduldlg.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/core/SwNumberTree/SwNumberTree.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/core/tool/scmatrix.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/core/bastyp/calc.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/core/edit/edattr.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/core/fields/expfld.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/uibase/docvw/edtwin.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/uibase/uiview/viewling.cxx")) + return false; + if (loplugin::hasPathnamePrefix( + fn, SRCDIR "/writerfilter/source/dmapper/DomainMapperTableHandler.cxx")) + return false; + return true; + } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr*); + bool VisitCXXConstructExpr(const CXXConstructExpr*); + +private: + bool isInterestingType(QualType); +}; + +bool MoveIt::VisitCXXMemberCallExpr(const CXXMemberCallExpr* topExpr) +{ + if (ignoreLocation(topExpr)) + return true; + const CXXMethodDecl* methodDecl = topExpr->getMethodDecl(); + if (!methodDecl) + return true; + + unsigned len = std::min(topExpr->getNumArgs(), methodDecl->getNumParams()); + for (unsigned i = 0; i < len; ++i) + { + // check if the parameter is a moveable type + const ParmVarDecl* parmVarDecl = methodDecl->getParamDecl(i); + if (!parmVarDecl->getType()->isRecordType()) + continue; + const CXXRecordDecl* recordDecl + = dyn_cast(parmVarDecl->getType()->getAsRecordDecl()); + if (!recordDecl || !recordDecl->hasMoveConstructor() || recordDecl->isTriviallyCopyable()) + continue; + if (!isInterestingType(parmVarDecl->getType())) + continue; + + // check if (a) we're making a copy to pass to the param and (b) we're making a copy of a local var + const Expr* argExpr = topExpr->getArg(i); + if (!argExpr) + continue; + const CXXConstructExpr* argSubExpr = dyn_cast(argExpr->IgnoreImplicit()); + if (!argSubExpr || argSubExpr->getNumArgs() == 0) + continue; + const DeclRefExpr* dre = dyn_cast(argSubExpr->getArg(0)->IgnoreImplicit()); + if (!dre) + continue; + const VarDecl* localVarDecl = dyn_cast(dre->getDecl()); + if (!localVarDecl || localVarDecl->getType()->isReferenceType() + || localVarDecl->getType()->isPointerType() || !localVarDecl->hasLocalStorage()) + continue; + // because sometimes the parameter type is some obscured STL thing + if (!isInterestingType(localVarDecl->getType())) + continue; + + report(DiagnosticsEngine::Warning, "can std::move this var into this param", + argExpr->getBeginLoc()); + report(DiagnosticsEngine::Note, "passing to this param", parmVarDecl->getBeginLoc()); + report(DiagnosticsEngine::Note, "local var declared here", localVarDecl->getBeginLoc()); + report(DiagnosticsEngine::Note, "type declared here", recordDecl->getBeginLoc()); + // parmVarDecl->getType()->dump(); + } + + // StringRef aFileName = getFilenameOfLocation( + // compiler.getSourceManager().getSpellingLoc(parmVarDecl->getBeginLoc())); + // if (loplugin::hasPathnamePrefix(aFileName, + // SRCDIR "/svx/source/sidebar/line/LineWidthValueSet.cxx")) + // return true; + + return true; +} + +bool MoveIt::VisitCXXConstructExpr(const CXXConstructExpr* topExpr) +{ + if (ignoreLocation(topExpr)) + return true; + if (isa(topExpr)) + return true; + const CXXConstructorDecl* methodDecl = topExpr->getConstructor(); + if (!methodDecl) + return true; + + unsigned len = std::min(topExpr->getNumArgs(), methodDecl->getNumParams()); + for (unsigned i = 0; i < len; ++i) + { + // check if the parameter is a moveable type + const ParmVarDecl* parmVarDecl = methodDecl->getParamDecl(i); + if (!parmVarDecl->getType()->isRecordType()) + continue; + const CXXRecordDecl* recordDecl + = dyn_cast(parmVarDecl->getType()->getAsRecordDecl()); + if (!recordDecl || !recordDecl->hasMoveConstructor() || recordDecl->isTriviallyCopyable()) + continue; + if (!isInterestingType(parmVarDecl->getType())) + continue; + + // check if (a) we're making a copy to pass to the param and (b) we're making a copy of a local var + const Expr* argExpr = topExpr->getArg(i); + if (!argExpr) + continue; + const CXXConstructExpr* argSubExpr = dyn_cast(argExpr->IgnoreImplicit()); + if (!argSubExpr || argSubExpr->getNumArgs() == 0) + continue; + const DeclRefExpr* dre = dyn_cast(argSubExpr->getArg(0)->IgnoreImplicit()); + if (!dre) + continue; + const VarDecl* localVarDecl = dyn_cast(dre->getDecl()); + if (!localVarDecl || localVarDecl->getType()->isReferenceType() + || localVarDecl->getType()->isPointerType() || !localVarDecl->hasLocalStorage()) + continue; + // because sometimes the parameter type is some obscured STL thing + if (!isInterestingType(localVarDecl->getType())) + continue; + + report(DiagnosticsEngine::Warning, "can std::move this var into this param", + argExpr->getBeginLoc()); + report(DiagnosticsEngine::Note, "passing to this param", parmVarDecl->getBeginLoc()); + report(DiagnosticsEngine::Note, "local var declared here", localVarDecl->getBeginLoc()); + report(DiagnosticsEngine::Note, "type declared here", recordDecl->getBeginLoc()); + // parmVarDecl->getType()->dump(); + } + + // StringRef aFileName = getFilenameOfLocation( + // compiler.getSourceManager().getSpellingLoc(parmVarDecl->getBeginLoc())); + // if (loplugin::hasPathnamePrefix(aFileName, + // SRCDIR "/svx/source/sidebar/line/LineWidthValueSet.cxx")) + // return true; + + return true; +} + +/// Exclude boring types, so that we don't generate too many low-value conversions. +/// e.g. for now I ignore ref-counted types like Sequence and OUString and css::uno::Reference, +/// because that generates too many changes +bool MoveIt::isInterestingType(QualType qt) +{ + if (qt->isEnumeralType()) + return false; + if (!qt->isRecordType()) + return false; + + auto tc = loplugin::TypeCheck(qt); + + // clang-format off + return !tc.ClassOrStruct("iterator") + && !tc.ClassOrStruct("const_iterator") + && !tc.Typedef("iterator") + && !tc.Typedef("const_iterator") + && !tc.Class("_Safe_iterator") + && !tc.Typedef("string") + && !tc.ClassOrStruct("shared_ptr").StdNamespace() + && !tc.ClassOrStruct("shared_ptr").Namespace("boost") + && !tc.Class("B2DHomMatrix").Namespace("basegfx").GlobalNamespace() + && !tc.Class("Pipe").Namespace("osl") + && !tc.Class("Any").Namespace("uno") + && !tc.Class("TypeDescription").Namespace("uno") + && !tc.Class("UnoInterfaceReference").Namespace("uno") + && !tc.Class("ByteSequence").Namespace("rtl").GlobalNamespace() + && !tc.Class("OUString").Namespace("rtl").GlobalNamespace() + && !tc.Class("OString").Namespace("rtl").GlobalNamespace() + && !tc.Class("BinaryAny") + && !tc.Class("Reference") + && !tc.Class("SvRef").Namespace("tools").GlobalNamespace() + && !tc.ClassOrStruct("sk_sp") // skia shared pointer + && !tc.ClassOrStruct("VclPtr") + && !tc.Typedef("IterString") // SalInstanceTreeView::IterString + && !tc.Typedef("svtree_render_args") + && !tc.Typedef("render_args") // weld::ComboBox::render_args + ; + // clang-format on +} + +/// off by default because each warning needs to be hand checked to ensure it is not a false+ +loplugin::Plugin::Registration moveit("moveit", false); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/moveparam.cxx b/compilerplugins/clang/moveparam.cxx new file mode 100644 index 000000000..dc7a84b4d --- /dev/null +++ b/compilerplugins/clang/moveparam.cxx @@ -0,0 +1,191 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include +#include +#include +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" +#include "check.hxx" + +/* +Look for places where we can pass by move && param and so avoid +unnecessary copies. +Empirically, when we are passing a container type to a function, 80% of the time, +we are passing a local temporary that can be moved instead of being copied. + +TODO this could be a lot smarter, with ignoring false+ e.g. when copying a param +in a loop +*/ + +namespace +{ +class MoveParam : public loplugin::FilteringPlugin +{ +public: + explicit MoveParam(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual bool preRun() override + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/filter/source/msfilter/escherex.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/ui/docshell/docfunc.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/ui/view/viewfunc.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/basegfx/source/polygon/b2dpolygontools.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/basegfx/source/polygon/b3dpolygontools.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/connectivity/source/commontools/dbtools.cxx")) + return false; + return true; + } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXOperatorCallExpr(const CXXOperatorCallExpr*); + bool VisitCXXConstructExpr(const CXXConstructExpr*); + + bool isContainerType(QualType qt); +}; + +bool MoveParam::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr* callExpr) +{ + if (ignoreLocation(callExpr)) + return true; + if (!callExpr->isAssignmentOp()) + return true; + auto qt = callExpr->getType(); + if (!isContainerType(qt)) + return true; + auto declRef = dyn_cast(callExpr->getArg(1)->IgnoreParenImpCasts()); + if (!declRef) + return true; + + auto parmVarDecl = dyn_cast_or_null(declRef->getDecl()); + if (!parmVarDecl) + return true; + + if (!loplugin::TypeCheck(parmVarDecl->getType()).LvalueReference().Const()) + return true; + + StringRef aFileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(parmVarDecl->getBeginLoc())); + if (loplugin::hasPathnamePrefix(aFileName, + SRCDIR "/svx/source/sidebar/line/LineWidthValueSet.cxx")) + return true; + + report(DiagnosticsEngine::Warning, "rather use move && param1", callExpr->getBeginLoc()); + + return true; +} + +bool MoveParam::VisitCXXConstructExpr(const CXXConstructExpr* constructExpr) +{ + if (ignoreLocation(constructExpr->getBeginLoc())) + return true; + if (isInUnoIncludeFile(constructExpr->getBeginLoc())) + return true; + + auto qt = constructExpr->getType(); + if (!isContainerType(qt)) + return true; + + if (constructExpr->getNumArgs() != 1) + return true; + + auto declRef = dyn_cast(constructExpr->getArg(0)->IgnoreParenImpCasts()); + if (!declRef) + return true; + + auto parmVarDecl = dyn_cast_or_null(declRef->getDecl()); + if (!parmVarDecl) + return true; + + if (!loplugin::TypeCheck(parmVarDecl->getType()).LvalueReference().Const()) + return true; + + StringRef aFileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(parmVarDecl->getBeginLoc())); + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR + "/include/drawinglayer/primitive2d/Primitive2DContainer.hxx")) + return true; + if (loplugin::hasPathnamePrefix(aFileName, + SRCDIR "/include/drawinglayer/primitive3d/baseprimitive3d.hxx")) + return true; + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/svx/source/svdraw/svdmrkv.cxx")) + return true; + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/editeng/swafopt.hxx")) + return true; + if (loplugin::hasPathnamePrefix( + aFileName, SRCDIR "/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx")) + return true; + if (loplugin::hasPathnamePrefix(aFileName, + SRCDIR "/chart2/source/tools/InternalDataProvider.cxx")) + return true; + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/sc/source/core/data/attrib.cxx")) + return true; + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/sw/source/core/doc/docfmt.cxx")) + return true; + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/configmgr/source/modifications.cxx")) + return true; + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/svx/source/dialog/srchdlg.cxx")) + return true; + if (loplugin::hasPathnamePrefix(aFileName, + SRCDIR "/stoc/source/servicemanager/servicemanager.cxx")) + return true; + + report(DiagnosticsEngine::Warning, "rather use move && param3", constructExpr->getBeginLoc()); + + return true; +} + +bool MoveParam::isContainerType(QualType qt) +{ + auto tc = loplugin::TypeCheck(qt); + return tc.Class("Primitive2DContainer") + .Namespace("primitive2d") + .Namespace("drawinglayer") + .GlobalNamespace() + || tc.ClassOrStruct("sorted_vector").Namespace("o3tl").GlobalNamespace() + || tc.ClassOrStruct("array").StdNamespace() || tc.ClassOrStruct("vector").StdNamespace() + || tc.ClassOrStruct("deque").StdNamespace() + || tc.ClassOrStruct("forward_list").StdNamespace() + || tc.ClassOrStruct("list").StdNamespace() || tc.ClassOrStruct("set").StdNamespace() + || tc.ClassOrStruct("map").StdNamespace() || tc.ClassOrStruct("multiset").StdNamespace() + || tc.ClassOrStruct("multimap").StdNamespace() + || tc.ClassOrStruct("unordered_set").StdNamespace() + || tc.ClassOrStruct("unordered_map").StdNamespace() + || tc.ClassOrStruct("unordered_multiset").StdNamespace() + || tc.ClassOrStruct("unordered_multimap").StdNamespace() + || tc.ClassOrStruct("stack").StdNamespace() || tc.ClassOrStruct("queue").StdNamespace() + || tc.ClassOrStruct("priority_queue").StdNamespace(); +} + +/** off by default because it needs some hand-holding */ +loplugin::Plugin::Registration moveparam("moveparam", false); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/namespaceindentation.cxx b/compilerplugins/clang/namespaceindentation.cxx new file mode 100644 index 000000000..1398efc86 --- /dev/null +++ b/compilerplugins/clang/namespaceindentation.cxx @@ -0,0 +1,220 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include +#include +#include "plugin.hxx" + +/* +*/ + +namespace +{ +class NamespaceIndentation : public loplugin::FilteringPlugin +{ +public: + explicit NamespaceIndentation(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual bool preRun() override { return true; } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitNamespaceDecl(NamespaceDecl const*); + +private: + std::string GetFullNamespace(const NamespaceDecl* nsDecl); +}; + +void trim(std::string& str) +{ + // right trim + auto it1 = std::find_if(str.rbegin(), str.rend(), [](char ch) { + return !std::isspace(ch, std::locale::classic()); + }); + str.erase(it1.base(), str.end()); + // left trim + auto it2 = std::find_if(str.begin(), str.end(), [](char ch) { + return !std::isspace(ch, std::locale::classic()); + }); + str.erase(str.begin(), it2); +} + +bool NamespaceIndentation::VisitNamespaceDecl(NamespaceDecl const* nsDecl) +{ + if (ignoreLocation(nsDecl)) + return true; + if (nsDecl->isAnonymousNamespace()) + return true; + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(nsDecl->getLocation()))) + return true; + + // right now, just fixing up the fallout from clang-tidy-modernize-namespaces, which + // does not touch header files + if (!compiler.getSourceManager().isInMainFile(nsDecl->getLocation())) + return true; + + auto& SM = compiler.getSourceManager(); + + // if we have a combined ns (.e.g namespace aaa::bbb), this appears in the AST + // as two nested namespace sharing the same source locations, so ignore the outer decls + if (!nsDecl->decls_empty()) + { + auto child = dyn_cast_or_null(*nsDecl->decls_begin()); + if (child) + { + bool invalid1 = false; + bool invalid2 = false; + unsigned line1 = SM.getPresumedLineNumber(nsDecl->getBeginLoc(), &invalid1); + unsigned line2 = SM.getPresumedLineNumber(child->getBeginLoc(), &invalid2); + if (line1 == line2) + return true; + } + } + + // Truly hacky way to find the actual beginning of an xxx::yyy namespace declaration + // if we are inside the yyy NameSpaceDecl of + // namespace xxx::yyy + // the beginLoc is just between the "xxx" and the "::" + auto nsDeclBeginLoc = nsDecl->getBeginLoc(); + bool foundMultiple = false; + { + constexpr int BACKSCAN = 32; + auto beginLoc = nsDecl->getBeginLoc().getLocWithOffset(-BACKSCAN); + auto endLoc = nsDecl->getBeginLoc().getLocWithOffset(3); + const char* p1 = SM.getCharacterData(beginLoc); + const char* p2 = SM.getCharacterData(endLoc); + unsigned n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts()); + if (p2 < p1 || n > 128 || (p2 - p1 + n) > 2048) + return true; + auto s = std::string(p1, p2 - p1); + auto idx1 = s.rfind(" "); // find the space preceding the namespace token + if (idx1 != std::string::npos) + { + auto namespaceToken = s.substr(idx1); + if (namespaceToken.find("::") != std::string::npos) + { + auto idx = s.rfind("\n"); + nsDeclBeginLoc = nsDecl->getBeginLoc().getLocWithOffset(idx - BACKSCAN + 1); + foundMultiple = true; + } + } + } + + // for now, I am only interested in fixing the fallout from clang-tidy-modernize-namespace, not + // anything else + if (!foundMultiple) + return true; + + bool invalid1 = false; + bool invalid2 = false; + unsigned col1 = SM.getPresumedColumnNumber(nsDeclBeginLoc, &invalid1); + unsigned col2 = SM.getPresumedColumnNumber(nsDecl->getRBraceLoc(), &invalid2); + unsigned line1 = SM.getPresumedLineNumber(nsDeclBeginLoc, &invalid1); + unsigned line2 = SM.getPresumedLineNumber(nsDecl->getRBraceLoc(), &invalid2); + if (invalid1 || invalid2) + return true; + if (line1 == line2) // single line declaration + return true; + if (col1 != col2) + report(DiagnosticsEngine::Warning, "statement right brace mis-aligned", + nsDecl->getRBraceLoc()); + + // no easy way to get the position of the left brace + auto endLoc = nsDecl->getBeginLoc().getLocWithOffset(256); + const char* p1 = SM.getCharacterData(SM.getExpansionLoc(nsDecl->getBeginLoc())); + const char* p2 = SM.getCharacterData(SM.getExpansionLoc(endLoc)); + unsigned n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts()); + if (p2 < p1 || n > 128 || (p2 - p1 + n) > 2048) + return true; + auto s = std::string(p1, p2 - p1 + n); + auto idx1 = s.find("\n"); + auto idx2 = s.find("{"); + if (idx1 != std::string::npos && idx2 != std::string::npos) + if (idx1 < idx2) + { + auto col3 = idx2 - idx1; + if (col1 != col3) + report(DiagnosticsEngine::Warning, "statement left brace mis-aligned", + nsDecl->getBeginLoc()); + } + + // extract the comment following the end brace + auto beginLoc = nsDecl->getRBraceLoc(); + endLoc = beginLoc.getLocWithOffset(128); + p1 = SM.getCharacterData(SM.getExpansionLoc(beginLoc)); + p2 = SM.getCharacterData(SM.getExpansionLoc(endLoc)); + n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts()); + if (p2 < p1 || n > 128 || (p2 - p1 + n) > 2048) + return true; + s = std::string(p1, p2 - p1 + n); + idx1 = s.find("//"); + idx2 = s.find("\n"); + if (idx1 != std::string::npos && idx2 != std::string::npos && idx1 < idx2) + { + idx1 += 2; + s = s.substr(idx1, idx2 - idx1); + trim(s); + std::string fullNamespace = GetFullNamespace(nsDecl); + if (!(s == fullNamespace || s == (fullNamespace + " namespace") || s == "namespace" + || s == ("namespace " + fullNamespace) || s == ("namespace ::" + fullNamespace) + || s == ("end " + fullNamespace) || s == "end namespace" + || s == ("end namespace " + fullNamespace) + || s == ("end " + fullNamespace + " namespace") || s == "end of namespace" + || s == ("end of namespace " + fullNamespace) + || s == ("end of namespace ::" + fullNamespace) + || s == ("eof of namespace " + fullNamespace))) + { + report(DiagnosticsEngine::Warning, "incorrect comment at end of namespace %0", + nsDecl->getRBraceLoc()) + << fullNamespace; + } + } + + return true; +} + +std::string NamespaceIndentation::GetFullNamespace(const NamespaceDecl* nsDecl) +{ + std::vector names; + auto ns = nsDecl; + while (ns) + { + names.push_back(ns->getName()); + ns = dyn_cast(ns->getParent()); + } + std::string fullNamespace; + for (auto it = names.rbegin(); it != names.rend(); ++it) + fullNamespace += "::" + it->str(); + fullNamespace = fullNamespace.substr(2); + return fullNamespace; +} + +// leave this off by default, so as not to annoy people +loplugin::Plugin::Registration namespaceindentation("namespaceindentation", + false); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/nestedunnamed.cxx b/compilerplugins/clang/nestedunnamed.cxx new file mode 100644 index 000000000..adc4f81a8 --- /dev/null +++ b/compilerplugins/clang/nestedunnamed.cxx @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include + +#include "plugin.hxx" + +// Warn about unnamed namespaces nested (directly) within unnamed namespaces. (It can be hard to +// keep track whether a certain spot in a source file is already in an unnamed namespace, so it +// happens that additions to the source add redundant, nested unnamed namespaces.) + +namespace +{ +class NestedUnnamed : public loplugin::FilteringPlugin +{ +public: + explicit NestedUnnamed(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitNamespaceDecl(NamespaceDecl const* decl) + { + if (ignoreLocation(decl)) + { + return true; + } + if (!decl->isAnonymousNamespace()) + { + return true; + } + NamespaceDecl const* outer; + for (auto p = decl->getLexicalParent();; p = p->getLexicalParent()) + { + outer = dyn_cast(p); + if (outer != nullptr) + { + break; + } + if (isa(p)) + { + return true; + } + } + if (!outer->isAnonymousNamespace()) + { + return true; + } + report(DiagnosticsEngine::Warning, "unnamed namespace directly nested in unnamed namespace", + decl->getLocation()) + << decl->getSourceRange(); + report(DiagnosticsEngine::Note, "outer namespace declared here", outer->getLocation()) + << outer->getSourceRange(); + return true; + } +}; + +loplugin::Plugin::Registration nestedunnamed("nestedunnamed"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/noexcept.cxx b/compilerplugins/clang/noexcept.cxx new file mode 100644 index 000000000..de956839e --- /dev/null +++ b/compilerplugins/clang/noexcept.cxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "plugin.hxx" + +namespace +{ +class Noexcept : public loplugin::FilteringRewritePlugin +{ +public: + explicit Noexcept(loplugin::InstantiationData const& data) + : FilteringRewritePlugin(data) + { + } + + void run() override + { + // Don't execute for < C++11, so we don't accidentally rewrite the legacy definitions of + // SAL_THROW_EXTERN_C and SAL_NOEXCEPT in include/sal/types.h e.g. when building + // CppunitTest_odk_checkapi which explicitly uses gb_CXX03FLAGS: + if (compiler.getLangOpts().CPlusPlus11) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc tloc) + { + if (ignoreLocation(tloc)) + { + return true; + } + if (tloc.getTypePtr()->getExceptionSpecType() != EST_DynamicNone) + { + return true; + } + auto const r = tloc.getExceptionSpecRange(); + auto r2 = r; + auto l1 = r.getBegin(); + while (compiler.getSourceManager().isMacroArgExpansion(l1)) + { + l1 = compiler.getSourceManager().getImmediateMacroCallerLoc(l1); + } + if (compiler.getSourceManager().isMacroBodyExpansion(l1)) + { + auto l2 = r.getEnd(); + while (compiler.getSourceManager().isMacroArgExpansion(l2)) + { + l2 = compiler.getSourceManager().getImmediateMacroCallerLoc(l2); + } + if (compiler.getSourceManager().isMacroBodyExpansion(l2)) + { + //TODO: check l1, l2 are in same macro body expansion + auto const spl = compiler.getSourceManager().getSpellingLoc(l1); + if (ignoreLocation(spl)) + { + return true; + } + r2 = { spl, compiler.getSourceManager().getSpellingLoc(l2) }; + } + } + auto const repl = isInUnoIncludeFile(r.getBegin()) ? "SAL_NOEXCEPT" : "noexcept"; + if (rewriter != nullptr && replaceText(r2, repl)) + { + return true; + } + report(DiagnosticsEngine::Warning, + "Replace legacy dynamic 'throw ()' exception specification with '%0'", r.getBegin()) + << repl << r; + return true; + } +}; + +loplugin::Plugin::Registration X("noexcept", true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/noexceptmove.cxx b/compilerplugins/clang/noexceptmove.cxx new file mode 100644 index 000000000..4f242848a --- /dev/null +++ b/compilerplugins/clang/noexceptmove.cxx @@ -0,0 +1,331 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// versions before 9.0 didn't have getExceptionSpecType + +#include "check.hxx" +#include "plugin.hxx" + +#include "config_clang.h" + +#include +#include + +/** + Look for move constructors that can be noexcept. +*/ + +namespace +{ +/// Look for the stuff that can be marked noexcept, but only if we also mark some of the callees noexcept. +/// Off by default so as not too annoy people. +constexpr bool bLookForStuffWeCanFix = false; + +class NoExceptMove : public loplugin::FilteringPlugin +{ +public: + explicit NoExceptMove(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + StringRef fn(handler.getMainFileName()); + // ONDXPagePtr::operator= calls ONDXPage::ReleaseRef which cannot be noexcept + if (loplugin::isSamePathname(fn, + SRCDIR "/connectivity/source/drivers/dbase/dindexnode.cxx")) + return; + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool shouldVisitImplicitCode() const { return true; } + + bool TraverseCXXConstructorDecl(CXXConstructorDecl*); + bool TraverseCXXMethodDecl(CXXMethodDecl*); + bool VisitCallExpr(const CallExpr*); + bool VisitCXXConstructExpr(const CXXConstructExpr*); + bool VisitVarDecl(const VarDecl*); + +private: + llvm::Optional IsCallThrows(const CallExpr* callExpr); + std::vector m_ConstructorThrows; + std::vector> m_Exclusions; + std::vector m_CannotFix; +}; + +bool NoExceptMove::TraverseCXXConstructorDecl(CXXConstructorDecl* constructorDecl) +{ + const bool isMove = constructorDecl->isMoveConstructor() + && constructorDecl->getExceptionSpecType() == EST_None + && !constructorDecl->isDefaulted() && !constructorDecl->isDeleted() + && !ignoreLocation(constructorDecl) + && constructorDecl->isThisDeclarationADefinition() + && constructorDecl->getBody() != nullptr; + if (isMove) + { + m_ConstructorThrows.push_back(false); + m_Exclusions.emplace_back(); + m_CannotFix.push_back(false); + } + bool rv = RecursiveASTVisitor::TraverseCXXConstructorDecl(constructorDecl); + if (isMove) + { + if (!m_ConstructorThrows.back()) + { + report(DiagnosticsEngine::Warning, "move constructor can be noexcept", + constructorDecl->getSourceRange().getBegin()) + << constructorDecl->getSourceRange(); + auto canonicalDecl = constructorDecl->getCanonicalDecl(); + if (canonicalDecl != constructorDecl) + report(DiagnosticsEngine::Note, "declaration here", + canonicalDecl->getSourceRange().getBegin()) + << canonicalDecl->getSourceRange(); + } + else if (bLookForStuffWeCanFix && !m_CannotFix.back()) + { + report(DiagnosticsEngine::Warning, "move constructor can be noexcept", + constructorDecl->getSourceRange().getBegin()) + << constructorDecl->getSourceRange(); + auto canonicalDecl = constructorDecl->getCanonicalDecl(); + if (canonicalDecl != constructorDecl) + report(DiagnosticsEngine::Note, "declaration here", + canonicalDecl->getSourceRange().getBegin()) + << canonicalDecl->getSourceRange(); + for (const Decl* callDecl : m_Exclusions.back()) + report(DiagnosticsEngine::Warning, "but need to fix this to be noexcept", + callDecl->getSourceRange().getBegin()) + << callDecl->getSourceRange(); + } + m_ConstructorThrows.pop_back(); + m_Exclusions.pop_back(); + m_CannotFix.pop_back(); + } + return rv; +} + +bool NoExceptMove::TraverseCXXMethodDecl(CXXMethodDecl* methodDecl) +{ + bool isMove = methodDecl->isMoveAssignmentOperator() + && methodDecl->getExceptionSpecType() == EST_None && !methodDecl->isDefaulted() + && !methodDecl->isDeleted() && !ignoreLocation(methodDecl) + && methodDecl->isThisDeclarationADefinition() && methodDecl->getBody() != nullptr; + if (isMove) + { + StringRef fn = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(methodDecl->getBeginLoc())); + // SfxObjectShellLock::operator= calls SotObject::OwnerLock which in turn calls stuff which cannot be noexcept + if (loplugin::isSamePathname(fn, SRCDIR "/include/sfx2/objsh.hxx")) + isMove = false; + } + if (isMove) + { + m_ConstructorThrows.push_back(false); + m_Exclusions.emplace_back(); + m_CannotFix.push_back(false); + } + bool rv = RecursiveASTVisitor::TraverseCXXMethodDecl(methodDecl); + if (isMove) + { + if (!m_ConstructorThrows.back()) + { + report(DiagnosticsEngine::Warning, "move operator= can be noexcept", + methodDecl->getSourceRange().getBegin()) + << methodDecl->getSourceRange(); + auto canonicalDecl = methodDecl->getCanonicalDecl(); + if (canonicalDecl != methodDecl) + report(DiagnosticsEngine::Note, "declaration here", + canonicalDecl->getSourceRange().getBegin()) + << canonicalDecl->getSourceRange(); + } + else if (bLookForStuffWeCanFix && !m_CannotFix.back()) + { + report(DiagnosticsEngine::Warning, "move operator= can be noexcept", + methodDecl->getSourceRange().getBegin()) + << methodDecl->getSourceRange(); + auto canonicalDecl = methodDecl->getCanonicalDecl(); + if (canonicalDecl != methodDecl) + report(DiagnosticsEngine::Note, "declaration here", + canonicalDecl->getSourceRange().getBegin()) + << canonicalDecl->getSourceRange(); + for (const Decl* callDecl : m_Exclusions.back()) + report(DiagnosticsEngine::Warning, "but need to fix this to be noexcept", + callDecl->getSourceRange().getBegin()) + << callDecl->getSourceRange(); + } + m_ConstructorThrows.pop_back(); + m_Exclusions.pop_back(); + m_CannotFix.pop_back(); + } + return rv; +} + +bool NoExceptMove::VisitCallExpr(const CallExpr* callExpr) +{ + if (ignoreLocation(callExpr)) + return true; + if (m_ConstructorThrows.empty()) + return true; + llvm::Optional bCallThrows = IsCallThrows(callExpr); + if (!bCallThrows) + { + callExpr->dump(); + if (callExpr->getCalleeDecl()) + callExpr->getCalleeDecl()->dump(); + report(DiagnosticsEngine::Warning, "what's up doc?", callExpr->getSourceRange().getBegin()) + << callExpr->getSourceRange(); + m_ConstructorThrows.back() = true; + return true; + } + if (*bCallThrows) + m_ConstructorThrows.back() = true; + return true; +} + +static bool IsCallThrowsSpec(clang::ExceptionSpecificationType est) +{ + return !(est == EST_DynamicNone || est == EST_NoThrow || est == EST_BasicNoexcept + || est == EST_NoexceptTrue); +} + +bool NoExceptMove::VisitCXXConstructExpr(const CXXConstructExpr* constructExpr) +{ + if (ignoreLocation(constructExpr)) + return true; + if (m_ConstructorThrows.empty()) + return true; + auto constructorDecl = constructExpr->getConstructor(); + auto est = constructorDecl->getExceptionSpecType(); + if (constructorDecl->isDefaulted() && est == EST_None) + ; // ok, non-throwing + else if (IsCallThrowsSpec(est)) + { + if (bLookForStuffWeCanFix) + { + if (est == EST_None && !ignoreLocation(constructorDecl)) + m_Exclusions.back().push_back(constructorDecl); + else + m_CannotFix.back() = true; + } + m_ConstructorThrows.back() = true; + } + return true; +} + +bool NoExceptMove::VisitVarDecl(const VarDecl* varDecl) +{ + if (varDecl->getLocation().isValid() && ignoreLocation(varDecl)) + return true; + if (m_ConstructorThrows.empty()) + return true; + // The clang AST does not show me implicit calls to destructors at the end of a block, + // so assume any local var decls of class type will call their destructor. + if (!varDecl->getType()->isRecordType()) + return true; + auto cxxRecordDecl = varDecl->getType()->getAsCXXRecordDecl(); + if (!cxxRecordDecl) + return true; + auto destructorDecl = cxxRecordDecl->getDestructor(); + if (!destructorDecl) + return true; + auto est = destructorDecl->getExceptionSpecType(); + if (destructorDecl->isDefaulted() && est == EST_None) + ; // ok, non-throwing + else if (IsCallThrowsSpec(est)) + { + if (bLookForStuffWeCanFix) + { + if (est == EST_None && !ignoreLocation(destructorDecl)) + m_Exclusions.back().push_back(destructorDecl); + else + m_CannotFix.back() = true; + } + m_ConstructorThrows.back() = true; + } + return true; +} + +llvm::Optional NoExceptMove::IsCallThrows(const CallExpr* callExpr) +{ + const FunctionDecl* calleeFunctionDecl = callExpr->getDirectCallee(); + if (calleeFunctionDecl) + { + auto est = calleeFunctionDecl->getExceptionSpecType(); + if (bLookForStuffWeCanFix) + { + if (est == EST_None && !ignoreLocation(calleeFunctionDecl)) + m_Exclusions.back().push_back(calleeFunctionDecl); + else + m_CannotFix.back() = true; + } + // Allowlist of functions that could be noexcept, but we can't change them because of backwards-compatibility reasons + // css::uno::XInterface::acquire + // css::uno::XInterface::release + if (calleeFunctionDecl->getIdentifier()) + { + auto name = calleeFunctionDecl->getName(); + if (auto cxxMethodDecl = dyn_cast(calleeFunctionDecl)) + if (loplugin::ContextCheck(cxxMethodDecl->getParent()->getDeclContext()) + .Namespace("uno") + .Namespace("star") + .Namespace("sun") + .Namespace("com") + .GlobalNamespace() + && (name == "acquire" || name == "release")) + return false; + if (name == "osl_releasePipe" || name == "osl_destroySocketAddr") + return false; + } + return IsCallThrowsSpec(est); + } + + auto calleeExpr = callExpr->getCallee(); + if (isa(calleeExpr) || isa(calleeExpr)) + { + m_CannotFix.back() = true; + return true; + } + + // check for call via function-pointer + clang::QualType calleeType; + if (auto fieldDecl = dyn_cast_or_null(callExpr->getCalleeDecl())) + calleeType = fieldDecl->getType(); + else if (auto varDecl = dyn_cast_or_null(callExpr->getCalleeDecl())) + calleeType = varDecl->getType(); + else + { + m_CannotFix.back() = true; + return llvm::Optional(); + } + + // allowlist of functions that could be noexcept, but we can't change them because of backwards-compatibility reasons + if (auto typedefType = calleeType->getAs()) + if (typedefType->getDecl()->getName() == "uno_ReleaseMappingFunc") + return false; + + if (calleeType->isPointerType()) + calleeType = calleeType->getPointeeType(); + auto funcProto = calleeType->getAs(); + if (!funcProto) + { + m_CannotFix.back() = true; + return llvm::Optional(); + } + + auto est = funcProto->getExceptionSpecType(); + if (bLookForStuffWeCanFix) + { + m_CannotFix.back() = true; // TODO, could improve + } + return IsCallThrowsSpec(est); +} + +loplugin::Plugin::Registration noexceptmove("noexceptmove"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/nullptr.cxx b/compilerplugins/clang/nullptr.cxx new file mode 100644 index 000000000..dcacb1bd2 --- /dev/null +++ b/compilerplugins/clang/nullptr.cxx @@ -0,0 +1,431 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" + +namespace { + +char const * kindName(Expr::NullPointerConstantKind kind) { + switch (kind) { + case Expr::NPCK_ZeroExpression: + return "ZeroExpression"; + case Expr::NPCK_ZeroLiteral: + return "ZeroLiteral"; + case Expr::NPCK_CXX11_nullptr: + return "CXX11_nullptr"; + case Expr::NPCK_GNUNull: + return "GNUNull"; + case Expr::NPCK_NotNull: + break; // cannot happen + } + llvm_unreachable("unknown null pointer kind"); +} + +bool isAnyKindOfPointerType(QualType type) { + return type->isAnyPointerType() || type->isFunctionPointerType() + || type->isMemberPointerType(); +} + +bool isNullPointerCast(CastExpr const * expr) { + switch (expr->getCastKind()) { + case CK_NullToPointer: + case CK_NullToMemberPointer: + return true; + default: + return false; + } +} + +class Nullptr: + public loplugin::FilteringRewritePlugin +{ +public: + explicit Nullptr(loplugin::InstantiationData const & data): + FilteringRewritePlugin(data) {} + + void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitImplicitCastExpr(CastExpr const * expr); + + bool VisitGNUNullExpr(GNUNullExpr const * expr); + + bool VisitBinaryOperator(BinaryOperator const * expr); + + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const * expr); + + bool VisitParmVarDecl(ParmVarDecl const * decl); + + bool TraverseConstructorInitializer(CXXCtorInitializer * init); + + bool TraverseLinkageSpecDecl(LinkageSpecDecl * decl); + + bool TraverseInitListExpr(InitListExpr * expr, DataRecursionQueue * queue = nullptr); + + bool shouldVisitTemplateInstantiations() const { return true; } + +private: + bool isInLokIncludeFile(SourceLocation spellingLocation) const; + + bool isFromCIncludeFile(SourceLocation spellingLocation) const; + + bool isSharedCAndCppCode(SourceLocation location) const; + + void visitCXXCtorInitializer(CXXCtorInitializer const * init); + + void handleZero(Expr const * expr); + + void handleNull( + Expr const * expr, char const * castKind, + Expr::NullPointerConstantKind nullPointerKind); + + void rewriteOrWarn( + Expr const * expr, char const * castKind, + Expr::NullPointerConstantKind nullPointerKind, + char const * replacement); + + std::set gnuNulls_; + unsigned int externCContexts_ = 0; +}; + +bool Nullptr::VisitImplicitCastExpr(CastExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (!isNullPointerCast(expr)) { + return true; + } + Expr::NullPointerConstantKind k = expr->isNullPointerConstant( + compiler.getASTContext(), Expr::NPC_ValueDependentIsNotNull); + switch (k) { + case Expr::NPCK_NotNull: + k = expr->isNullPointerConstant( + compiler.getASTContext(), Expr::NPC_ValueDependentIsNull); + switch (k) { + case Expr::NPCK_NotNull: + break; + case Expr::NPCK_ZeroExpression: + case Expr::NPCK_ZeroLiteral: + report( + DiagnosticsEngine::Warning, + "suspicious ValueDependentIsNull %0", expr->getBeginLoc()) + << kindName(k) << expr->getSourceRange(); + break; + default: + assert(false); // cannot happen + } + break; + case Expr::NPCK_CXX11_nullptr: + break; + default: + if (loplugin::TypeCheck(expr->getType()).Typedef("locale_t") + .GlobalNamespace()) + { + break; // POSIX locale_t is left unspecified + } + handleNull(expr->getSubExpr(), expr->getCastKindName(), k); + break; + } + return true; +} + +bool Nullptr::VisitGNUNullExpr(GNUNullExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + handleNull(expr, nullptr, Expr::NPCK_GNUNull); + return true; +} + +bool Nullptr::VisitBinaryOperator(BinaryOperator const * expr) { + if (ignoreLocation(expr)) { + return true; + } + Expr const * e; + switch (expr->getOpcode()) { + case BO_EQ: + case BO_NE: + if (isAnyKindOfPointerType(expr->getRHS()->getType())) { + e = expr->getLHS(); + break; + } + // fall through + case BO_Assign: + if (isAnyKindOfPointerType(expr->getLHS()->getType())) { + e = expr->getRHS(); + break; + } + // fall through + default: + return true; + } + handleZero(e); + return true; +} + +bool Nullptr::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + Expr const * e; + switch (expr->getOperator()) { + case OO_EqualEqual: + case OO_ExclaimEqual: + if (isAnyKindOfPointerType(expr->getArg(1)->getType())) { + e = expr->getArg(0); + break; + } + // fall through + case OO_Equal: + if (isAnyKindOfPointerType(expr->getArg(0)->getType())) { + e = expr->getArg(1); + break; + } + // fall through + default: + return true; + } + handleZero(e); + return true; +} + +bool Nullptr::VisitParmVarDecl(ParmVarDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + if (!isAnyKindOfPointerType(decl->getType())) { + return true; + } + if (decl->hasUninstantiatedDefaultArg()) { + return true; //TODO + } + auto e = decl->getDefaultArg(); + if (e == nullptr) { + return true; + } + handleZero(e); + return true; +} + +bool Nullptr::TraverseConstructorInitializer(CXXCtorInitializer * init) { + visitCXXCtorInitializer(init); + return RecursiveASTVisitor::TraverseConstructorInitializer(init); +} + +bool Nullptr::TraverseLinkageSpecDecl(LinkageSpecDecl * decl) { + assert(externCContexts_ != std::numeric_limits::max()); //TODO + ++externCContexts_; + bool ret = RecursiveASTVisitor::TraverseLinkageSpecDecl(decl); + assert(externCContexts_ != 0); + --externCContexts_; + return ret; +} + +bool Nullptr::TraverseInitListExpr(InitListExpr * expr, DataRecursionQueue * queue) { + return WalkUpFromInitListExpr(expr) + && TraverseSynOrSemInitListExpr( + expr->isSemanticForm() ? expr : expr->getSemanticForm(), queue); +} + +bool Nullptr::isInLokIncludeFile(SourceLocation spellingLocation) const { + return loplugin::hasPathnamePrefix( + getFilenameOfLocation(spellingLocation), + SRCDIR "/include/LibreOfficeKit/"); +} + +bool Nullptr::isFromCIncludeFile(SourceLocation spellingLocation) const { + return !compiler.getSourceManager().isInMainFile(spellingLocation) + && (StringRef( + compiler.getSourceManager().getPresumedLoc(spellingLocation) + .getFilename()) + .endswith(".h")); +} + +bool Nullptr::isSharedCAndCppCode(SourceLocation location) const { + // Assume that code is intended to be shared between C and C++ if it comes + // from an include file ending in .h, and is either in an extern "C" context + // or the body of a macro definition: + return + isFromCIncludeFile(compiler.getSourceManager().getSpellingLoc(location)) + && (externCContexts_ != 0 + || compiler.getSourceManager().isMacroBodyExpansion(location)); +} + +void Nullptr::visitCXXCtorInitializer(CXXCtorInitializer const * init) { + if (!init->isWritten()) { + return; + } + auto e = init->getInit(); + if (ignoreLocation(e)) { + return; + } + auto d = init->getAnyMember(); + if (d == nullptr || !isAnyKindOfPointerType(d->getType())) { + return; + } + if (auto e2 = dyn_cast(e)) { + if (e2->getNumExprs() != 1) { + return; + } + e = e2->getExpr(0); + } else if (auto e2 = dyn_cast(e)) { + if (e2->getNumInits() != 1) { + return; + } + e = e2->getInit(0); + } + handleZero(e); +} + +void Nullptr::handleZero(Expr const * expr) { + //TODO: detect NPCK_ZeroExpression where appropriate + // Filter out ImplicitCastExpr that will be handled by + // VisitImplicitCastExpr: + if (auto ice = dyn_cast(expr)) { + if (isNullPointerCast(ice)) { + return; + } + } + auto const lit = dyn_cast(expr->IgnoreParenImpCasts()); + if (lit != nullptr && !lit->getValue().getBoolValue()) { + handleNull(expr, nullptr, Expr::NPCK_ZeroLiteral); + } +} + +void Nullptr::handleNull( + Expr const * expr, char const * castKind, + Expr::NullPointerConstantKind nullPointerKind) +{ + auto e = expr; + SourceLocation loc; + for (;;) { + e = e->IgnoreImpCasts(); + loc = e->getBeginLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(loc)) { + loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc); + } + if (compiler.getSourceManager().isMacroBodyExpansion(loc)) { + if (Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()) + == "NULL") + { + if (!compiler.getLangOpts().CPlusPlus) { + //TODO: if !castKind, warn if NULL is passed into fn call + // ellipsis, cast to void* + return; + } + loc = compat::getImmediateExpansionRange(compiler.getSourceManager(), loc).first; + if (ignoreLocation( + compiler.getSourceManager().getSpellingLoc(loc))) + { + return; + } + if (isInUnoIncludeFile( + compiler.getSourceManager().getSpellingLoc(loc)) + || isInLokIncludeFile( + compiler.getSourceManager().getSpellingLoc(loc)) + || isSharedCAndCppCode(loc)) + { + //TODO: if !castKind, warn if NULL is passed into fn call + // ellipsis, cast to void* + return; + } + } else if (ignoreLocation( + compiler.getSourceManager().getSpellingLoc(loc))) + { + return; + } + } + ParenExpr const * pe = dyn_cast(e); + if (pe == nullptr) { + break; + } + e = pe->getSubExpr(); + } + if (nullPointerKind == Expr::NPCK_GNUNull) { + if (castKind == nullptr) { + if (gnuNulls_.erase(expr) == 1) { + return; + } + } else { + auto const ok = gnuNulls_.insert(expr).second; + assert(ok); (void) ok; + } + } + auto const asMacro = !compiler.getLangOpts().CPlusPlus + || isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(loc)) + || isInLokIncludeFile(compiler.getSourceManager().getSpellingLoc(loc)) + || isSharedCAndCppCode(loc); + assert(!asMacro || nullPointerKind != Expr::NPCK_GNUNull); + rewriteOrWarn(e, castKind, nullPointerKind, asMacro ? "NULL" : "nullptr"); +} + +void Nullptr::rewriteOrWarn( + Expr const * expr, char const * castKind, + Expr::NullPointerConstantKind nullPointerKind, char const * replacement) +{ + if (rewriter != nullptr) { + SourceLocation locStart(expr->getBeginLoc()); + while (compiler.getSourceManager().isMacroArgExpansion(locStart)) { + locStart = compiler.getSourceManager() + .getImmediateMacroCallerLoc(locStart); + } + if (compiler.getLangOpts().CPlusPlus + && compiler.getSourceManager().isMacroBodyExpansion(locStart) + && (Lexer::getImmediateMacroName( + locStart, compiler.getSourceManager(), + compiler.getLangOpts()) + == "NULL")) + { + locStart = compat::getImmediateExpansionRange(compiler.getSourceManager(), locStart) + .first; + } + SourceLocation locEnd(expr->getEndLoc()); + while (compiler.getSourceManager().isMacroArgExpansion(locEnd)) { + locEnd = compiler.getSourceManager() + .getImmediateMacroCallerLoc(locEnd); + } + if (compiler.getLangOpts().CPlusPlus + && compiler.getSourceManager().isMacroBodyExpansion(locEnd) + && (Lexer::getImmediateMacroName( + locEnd, compiler.getSourceManager(), + compiler.getLangOpts()) + == "NULL")) + { + locEnd = compat::getImmediateExpansionRange(compiler.getSourceManager(), locEnd).first; + } + if (replaceText(SourceRange(compiler.getSourceManager().getSpellingLoc(locStart), compiler.getSourceManager().getSpellingLoc(locEnd)), replacement)) { + return; + } + } + if (castKind == nullptr) { + report(DiagnosticsEngine::Warning, "%0 -> %1", expr->getBeginLoc()) + << kindName(nullPointerKind) << replacement + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, "%0 ValueDependentIsNotNull %1 -> %2", + expr->getBeginLoc()) + << castKind << kindName(nullPointerKind) << replacement + << expr->getSourceRange(); + } +} + +loplugin::Plugin::Registration X("nullptr", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/oncevar.cxx b/compilerplugins/clang/oncevar.cxx new file mode 100644 index 000000000..44fcfa950 --- /dev/null +++ b/compilerplugins/clang/oncevar.cxx @@ -0,0 +1,414 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +// Original idea from tml. +// Look for variables that are (a) initialised from zero or one constants. (b) only used in one spot. +// In which case, we might as well inline it. + +namespace +{ + +Expr const * lookThroughInitListExpr(Expr const * expr) { + if (auto const ile = dyn_cast(expr->IgnoreParenImpCasts())) { + if (ile->getNumInits() == 1) { + return ile->getInit(0); + } + } + return expr; +} + +class ConstantValueDependentExpressionVisitor: + public ConstStmtVisitor +{ + ASTContext const & context_; + +public: + ConstantValueDependentExpressionVisitor(ASTContext const & context): + context_(context) {} + + bool Visit(Stmt const * stmt) { + assert(isa(stmt)); + auto const expr = cast(stmt); + if (!expr->isValueDependent()) { + return expr->isEvaluatable(context_); + } + return ConstStmtVisitor::Visit(stmt); + } + + bool VisitParenExpr(ParenExpr const * expr) + { return Visit(expr->getSubExpr()); } + + bool VisitCastExpr(CastExpr const * expr) { + return Visit(expr->getSubExpr()); + } + + bool VisitUnaryOperator(UnaryOperator const * expr) + { return Visit(expr->getSubExpr()); } + + bool VisitBinaryOperator(BinaryOperator const * expr) { + return Visit(expr->getLHS()) && Visit(expr->getRHS()); + } + + bool VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr const *) { + return true; + } +}; + +class OnceVar: + public loplugin::FilteringPlugin +{ +public: + explicit OnceVar(loplugin::InstantiationData const & data): FilteringPlugin(data) {} + + virtual void run() override { + // ignore some files with problematic macros + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + // platform-specific stuff + if (fn == SRCDIR "/sal/osl/unx/thread.cxx" + || fn == SRCDIR "/sot/source/base/formats.cxx" + || fn == SRCDIR "/svl/source/config/languageoptions.cxx" + || fn == SRCDIR "/sfx2/source/appl/appdde.cxx" + || fn == SRCDIR "/configmgr/source/components.cxx" + || fn == SRCDIR "/embeddedobj/source/msole/oleembed.cxx") + return; + // some of this is necessary + if (loplugin::hasPathnamePrefix( fn, SRCDIR "/sal/qa/")) + return; + if (loplugin::hasPathnamePrefix( fn, SRCDIR "/comphelper/qa/")) + return; + // TODO need to check calls via function pointer + if (fn == SRCDIR "/i18npool/source/textconversion/textconversion_zh.cxx" + || fn == SRCDIR "/i18npool/source/localedata/localedata.cxx") + return; + // debugging stuff + if (fn == SRCDIR "/sc/source/core/data/dpcache.cxx" + || fn == SRCDIR "/sw/source/core/layout/dbg_lay.cxx" + || fn == SRCDIR "/sw/source/core/layout/ftnfrm.cxx") + return; + // TODO taking local reference to variable + if (fn == SRCDIR "/sc/source/filter/excel/xechart.cxx") + return; + // macros managing to generate to a valid warning + if (fn == SRCDIR "/solenv/bin/concat-deps.c") + return; + // TODO bug in the plugin + if (fn == SRCDIR "/vcl/unx/generic/app/saldisp.cxx") + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + for (auto const & varDecl : maVarDeclSet) + { + if (maVarDeclToIgnoreSet.find(varDecl) != maVarDeclToIgnoreSet.end()) + continue; + int noUses = 0; + auto it = maVarUsesMap.find(varDecl); + if (it != maVarUsesMap.end()) + noUses = it->second; + if (noUses > 1) + continue; + report(DiagnosticsEngine::Warning, + "var used only once, should be inlined or declared const", + varDecl->getLocation()) + << varDecl->getSourceRange(); + if (it != maVarUsesMap.end()) + report(DiagnosticsEngine::Note, + "used here", + maVarUseSourceRangeMap[varDecl].getBegin()) + << maVarUseSourceRangeMap[varDecl]; + } + } + + bool VisitMemberExpr(MemberExpr const * expr) { + // ignore cases like: + // const OUString("xxx") xxx; + // rtl_something(xxx.pData); + // where we cannot inline the declaration. + if (isa(expr->getMemberDecl())) { + recordIgnore(expr); + } + return true; + } + + bool VisitUnaryOperator(UnaryOperator const * expr) { + // if we take the address of it, or we modify it, ignore it + UnaryOperator::Opcode op = expr->getOpcode(); + if (op == UO_AddrOf || op == UO_PreInc || op == UO_PostInc + || op == UO_PreDec || op == UO_PostDec) + { + recordIgnore(expr->getSubExpr()); + } + return true; + } + + bool VisitBinaryOperator(BinaryOperator const * expr) { + // if we assign it another value, or modify it, ignore it + BinaryOperator::Opcode op = expr->getOpcode(); + if (op == BO_Assign || op == BO_PtrMemD || op == BO_PtrMemI || op == BO_MulAssign + || op == BO_DivAssign || op == BO_RemAssign || op == BO_AddAssign + || op == BO_SubAssign || op == BO_ShlAssign || op == BO_ShrAssign + || op == BO_AndAssign || op == BO_XorAssign || op == BO_OrAssign) + { + recordIgnore(expr->getLHS()); + } + return true; + } + + bool VisitCallExpr(CallExpr const * expr) { + unsigned firstArg = 0; + if (auto const cmce = dyn_cast(expr)) { + if (auto const e1 = cmce->getMethodDecl()) { + if (!(e1->isConst() || e1->isStatic())) { + recordIgnore(cmce->getImplicitObjectArgument()); + } + } else if (auto const e2 = dyn_cast( + cmce->getCallee()->IgnoreParenImpCasts())) + { + switch (e2->getOpcode()) { + case BO_PtrMemD: + case BO_PtrMemI: + if (!e2->getRHS()->getType()->getAs() + ->getPointeeType()->getAs() + ->isConst()) + { + recordIgnore(e2->getLHS()); + } + break; + default: + break; + } + } + } else if (auto const coce = dyn_cast(expr)) { + if (auto const cmd = dyn_cast_or_null( + coce->getDirectCallee())) + { + if (!cmd->isStatic()) { + assert(coce->getNumArgs() != 0); + if (!cmd->isConst()) { + recordIgnore(coce->getArg(0)); + } + firstArg = 1; + } + } + } + // ignore those ones we are passing by reference + const FunctionDecl* calleeFunctionDecl = expr->getDirectCallee(); + if (calleeFunctionDecl) { + for (unsigned i = firstArg; i < expr->getNumArgs(); ++i) { + if (i < calleeFunctionDecl->getNumParams()) { + QualType qt { calleeFunctionDecl->getParamDecl(i)->getType() }; + if (loplugin::TypeCheck(qt).LvalueReference().NonConst()) { + recordIgnore(expr->getArg(i)); + } + if (loplugin::TypeCheck(qt).Pointer().NonConst()) { + recordIgnore(expr->getArg(i)); + } + } + } + } + return true; + } + + bool VisitCXXConstructExpr(CXXConstructExpr const * expr) { + // ignore those ones we are passing by reference + const CXXConstructorDecl* cxxConstructorDecl = expr->getConstructor(); + for (unsigned i = 0; i < expr->getNumArgs(); ++i) { + if (i < cxxConstructorDecl->getNumParams()) { + QualType qt { cxxConstructorDecl->getParamDecl(i)->getType() }; + if (loplugin::TypeCheck(qt).LvalueReference().NonConst()) { + recordIgnore(expr->getArg(i)); + } + if (loplugin::TypeCheck(qt).Pointer().NonConst()) { + recordIgnore(expr->getArg(i)); + } + } + } + return true; + } + + bool VisitDeclRefExpr( const DeclRefExpr* ); + bool VisitVarDecl( const VarDecl* ); + bool TraverseFunctionDecl( FunctionDecl* functionDecl ); + +private: + std::unordered_set maVarDeclSet; + std::unordered_set maVarDeclToIgnoreSet; + std::unordered_map maVarUsesMap; + std::unordered_map maVarUseSourceRangeMap; + + bool isConstantValueDependentExpression(Expr const * expr) { + return ConstantValueDependentExpressionVisitor(compiler.getASTContext()) + .Visit(expr); + } + + void recordIgnore(Expr const * expr) { + for (;;) { + expr = expr->IgnoreParenImpCasts(); + if (auto const e = dyn_cast(expr)) { + if (isa(e->getMemberDecl())) { + expr = e->getBase(); + continue; + } + } + if (auto const e = dyn_cast(expr)) { + expr = e->getBase(); + continue; + } + if (auto const e = dyn_cast(expr)) { + if (e->getOpcode() == BO_PtrMemD) { + expr = e->getLHS(); + continue; + } + } + break; + } + auto const dre = dyn_cast(expr); + if (dre == nullptr) { + return; + } + auto const var = dyn_cast(dre->getDecl()); + if (var == nullptr) { + return; + } + maVarDeclToIgnoreSet.insert(var); + } +}; + +bool OnceVar::TraverseFunctionDecl( FunctionDecl* functionDecl ) +{ + // Ignore functions that contains #ifdef-ery, can be quite tricky + // to make useful changes when this plugin fires in such functions + if (containsPreprocessingConditionalInclusion( + functionDecl->getSourceRange())) + return true; + return RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); +} + +bool OnceVar::VisitVarDecl( const VarDecl* varDecl ) +{ + if (ignoreLocation(varDecl)) { + return true; + } + if (auto const init = varDecl->getInit()) { + recordIgnore(lookThroughInitListExpr(init)); + } + if (varDecl->isExceptionVariable() || isa(varDecl)) { + return true; + } + // ignore stuff in header files (which should really not be there, but anyhow) + if (!compiler.getSourceManager().isInMainFile(varDecl->getLocation())) { + return true; + } + // Ignore macros like FD_ZERO + if (compiler.getSourceManager().isMacroBodyExpansion(varDecl->getBeginLoc())) { + return true; + } + if (varDecl->hasGlobalStorage()) { + return true; + } + auto const tc = loplugin::TypeCheck(varDecl->getType()); + if (!varDecl->getType().isCXX11PODType(compiler.getASTContext()) + && !tc.Class("OString").Namespace("rtl").GlobalNamespace() + && !tc.Class("OUString").Namespace("rtl").GlobalNamespace() + && !tc.Class("OStringBuffer").Namespace("rtl").GlobalNamespace() + && !tc.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + && !tc.Class("Color").GlobalNamespace() + && !tc.Class("Pair").GlobalNamespace() + && !tc.Class("Point").GlobalNamespace() + && !tc.Class("Size").GlobalNamespace() + && !tc.Class("Range").GlobalNamespace() + && !tc.Class("Selection").GlobalNamespace() + && !tc.Class("Rectangle").Namespace("tools").GlobalNamespace()) + { + return true; + } + if (varDecl->getType()->isPointerType()) + return true; + // if it's declared const, ignore it, it's there to make the code easier to read + if (tc.Const()) + return true; + + if (!varDecl->hasInit()) + return true; + + // check for string or scalar literals + bool foundStringLiteral = false; + const Expr * initExpr = varDecl->getInit(); + if (auto e = dyn_cast(initExpr)) { + initExpr = e->getSubExpr(); + } + if (isa(initExpr)) { + foundStringLiteral = true; + } else if (auto constructExpr = dyn_cast(initExpr)) { + if (constructExpr->getNumArgs() == 0) { + foundStringLiteral = true; // i.e., empty string + } else { + auto stringLit2 = dyn_cast(constructExpr->getArg(0)); + foundStringLiteral = stringLit2 != nullptr; + } + } + if (!foundStringLiteral) { + auto const init = varDecl->getInit(); + if (!(init->isValueDependent() + ? isConstantValueDependentExpression(init) + : init->isConstantInitializer( + compiler.getASTContext(), false/*ForRef*/))) + { + return true; + } + } + + maVarDeclSet.insert(varDecl); + + return true; +} + +bool OnceVar::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) +{ + if (ignoreLocation(declRefExpr)) { + return true; + } + const Decl* decl = declRefExpr->getDecl(); + if (!isa(decl) || isa(decl)) { + return true; + } + const VarDecl * varDecl = dyn_cast(decl)->getCanonicalDecl(); + // ignore stuff in header files (which should really not be there, but anyhow) + if (!compiler.getSourceManager().isInMainFile(varDecl->getLocation())) { + return true; + } + + if (maVarUsesMap.find(varDecl) == maVarUsesMap.end()) { + maVarUsesMap[varDecl] = 1; + maVarUseSourceRangeMap[varDecl] = declRefExpr->getSourceRange(); + } else { + maVarUsesMap[varDecl]++; + } + + return true; +} + +loplugin::Plugin::Registration< OnceVar > X("oncevar", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/oslendian.cxx b/compilerplugins/clang/oslendian.cxx new file mode 100644 index 000000000..13296330b --- /dev/null +++ b/compilerplugins/clang/oslendian.cxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +#include "plugin.hxx" + +namespace { + +class OslEndian: public loplugin::Plugin, public PPCallbacks { +public: + explicit OslEndian(loplugin::InstantiationData const & data): Plugin(data) { + compiler.getPreprocessor().addPPCallbacks(std::unique_ptr(this)); + } + + enum { isPPCallback = true }; + +private: + void run() override {} + + virtual void FileChanged(SourceLocation, FileChangeReason, SrcMgr::CharacteristicKind, FileID) override { + if(!startChecked) { + // With precompiled headers MacroDefined() would not be called, so check already at the very + // start whether the macros exist. + startChecked = true; + if(const MacroInfo* macroBig = compiler.getPreprocessor().getMacroInfo( + &compiler.getPreprocessor().getIdentifierTable().get("OSL_BIGENDIAN"))) { + definedBig_ = macroBig->getDefinitionLoc(); + } + if(const MacroInfo* macroLit = compiler.getPreprocessor().getMacroInfo( + &compiler.getPreprocessor().getIdentifierTable().get("OSL_LITENDIAN"))) { + definedLit_ = macroLit->getDefinitionLoc(); + } + } + } + + void MacroDefined(Token const & MacroNameTok, MacroDirective const *) + override + { + auto id = MacroNameTok.getIdentifierInfo()->getName(); + if (id == "OSL_BIGENDIAN") { + if (definedLit_.isValid()) { + report( + DiagnosticsEngine::Warning, + "macro %0 defined in addition to 'OSL_LITENDIAN'", + MacroNameTok.getLocation()) + << MacroNameTok.getIdentifierInfo(); + report( + DiagnosticsEngine::Note, + "conflicting macro definition is here", definedLit_); + } + definedBig_ = MacroNameTok.getLocation(); + assert(definedBig_.isValid()); + } else if (id == "OSL_LITENDIAN") { + if (definedBig_.isValid()) { + report( + DiagnosticsEngine::Warning, + "macro %0 defined in addition to 'OSL_BIGENDIAN'", + MacroNameTok.getLocation()) + << MacroNameTok.getIdentifierInfo(); + report( + DiagnosticsEngine::Note, + "conflicting macro definition is here", definedBig_); + } + definedLit_ = MacroNameTok.getLocation(); + assert(definedLit_.isValid()); + } + } + + void MacroUndefined( + Token const & MacroNameTok, MacroDefinition const &, MacroDirective const *) override + { + auto id = MacroNameTok.getIdentifierInfo()->getName(); + if (id == "OSL_BIGENDIAN" || id == "OSL_LITENDIAN") { + report( + DiagnosticsEngine::Warning, "macro %0 undefinition", + MacroNameTok.getLocation()) + << MacroNameTok.getIdentifierInfo(); + } + } + + void Defined( + Token const & MacroNameTok, MacroDefinition const &, SourceRange) + override + { + check(MacroNameTok); + } + + void Ifdef( + SourceLocation, Token const & MacroNameTok, + MacroDefinition const &) override + { + check(MacroNameTok); + } + + void Ifndef( + SourceLocation, Token const & MacroNameTok, + MacroDefinition const &) override + { + check(MacroNameTok); + } + + void check(Token const & macro) const { + auto id = macro.getIdentifierInfo()->getName(); + if ((id == "OSL_BIGENDIAN" || id == "OSL_LITENDIAN") + && definedBig_.isInvalid() && definedLit_.isInvalid()) + { + report( + DiagnosticsEngine::Warning, + "definition of macro %0 checked but 'osl/endian.h' is not" + " included", + macro.getLocation()) + << macro.getIdentifierInfo(); + } + } + + SourceLocation definedBig_; + SourceLocation definedLit_; + bool startChecked = false; +}; + +loplugin::Plugin::Registration X("oslendian"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/overrideparam.cxx b/compilerplugins/clang/overrideparam.cxx new file mode 100644 index 000000000..61efe15b1 --- /dev/null +++ b/compilerplugins/clang/overrideparam.cxx @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include + +#include "plugin.hxx" +#include "check.hxx" + +/* + Find overridden methods that : + (a) declare default params in different places to their super-method(s) + + Still TODO + (b) Find places where the values of the default parameters are different + (c) Find places where the names of the parameters differ +*/ + +namespace { + +class OverrideParam: + public loplugin::FilteringPlugin +{ +public: + explicit OverrideParam(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override; + + bool VisitCXXMethodDecl(const CXXMethodDecl *); + +private: + bool hasSameDefaultParams(const ParmVarDecl * parmVarDecl, const ParmVarDecl * superParmVarDecl); +}; + +void OverrideParam::run() +{ + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); +} + +bool OverrideParam::VisitCXXMethodDecl(const CXXMethodDecl * methodDecl) { + if (ignoreLocation(methodDecl)) { + return true; + } + if (methodDecl->isThisDeclarationADefinition() || methodDecl->size_overridden_methods() == 0) { + return true; + } + loplugin::DeclCheck dc(methodDecl); + // This class is overriding ShowCursor(bool) AND declaring a ShowCursor() method. + // Adding a default param causes 'ambiguous override'. + if (dc.Function("ShowCursor").Class("ScTabViewShell").GlobalNamespace()) { + return true; + } + + for(auto superMethodIt = methodDecl->begin_overridden_methods(); + superMethodIt != methodDecl->end_overridden_methods(); ++superMethodIt) + { + const CXXMethodDecl * superMethodDecl = *superMethodIt; + if (ignoreLocation(superMethodDecl)) { + continue; + } + int i = 0; + for (const ParmVarDecl *superParmVarDecl : superMethodDecl->parameters()) { + const ParmVarDecl *parmVarDecl = methodDecl->getParamDecl(i); + if (parmVarDecl->hasDefaultArg() && !superParmVarDecl->hasDefaultArg()) { + report( + DiagnosticsEngine::Warning, + "overridden method declaration has default arg, but super-method does not", + parmVarDecl->getSourceRange().getBegin()) + << parmVarDecl->getSourceRange(); + report( + DiagnosticsEngine::Note, + "original param here", + superParmVarDecl->getSourceRange().getBegin()) + << superParmVarDecl->getSourceRange(); + } + else if (!parmVarDecl->hasDefaultArg() && superParmVarDecl->hasDefaultArg()) { + report( + DiagnosticsEngine::Warning, + "overridden method declaration has no default arg, but super-method does", + parmVarDecl->getSourceRange().getBegin()) + << parmVarDecl->getSourceRange(); + report( + DiagnosticsEngine::Note, + "original param here", + superParmVarDecl->getSourceRange().getBegin()) + << superParmVarDecl->getSourceRange(); + } + else if (parmVarDecl->hasDefaultArg() && superParmVarDecl->hasDefaultArg() + && !hasSameDefaultParams(parmVarDecl, superParmVarDecl)) { + report( + DiagnosticsEngine::Warning, + "overridden method declaration has different default param to super-method", + parmVarDecl->getSourceRange().getBegin()) + << parmVarDecl->getSourceRange(); + report( + DiagnosticsEngine::Note, + "original param here", + superParmVarDecl->getSourceRange().getBegin()) + << superParmVarDecl->getSourceRange(); + } + /* do nothing for now, will enable this in a later commit + if (methodDecl->isThisDeclarationADefinition() && parmVarDecl->getName().empty()) { + // ignore this - means the param is unused + } + else if (superParmVarDecl->getName().empty()) { + // ignore, nothing reasonable I can do + } + else if (superParmVarDecl->getName() != parmVarDecl->getName()) { + report( + DiagnosticsEngine::Warning, + "overridden method declaration uses different name for parameter", + parmVarDecl->getSourceRange().getBegin()) + << parmVarDecl->getSourceRange(); + report( + DiagnosticsEngine::Note, + "original param here", + superParmVarDecl->getSourceRange().getBegin()) + << superParmVarDecl->getSourceRange(); + }*/ + ++i; + } + } + return true; +} + +bool OverrideParam::hasSameDefaultParams(const ParmVarDecl * parmVarDecl, const ParmVarDecl * superParmVarDecl) +{ + // don't know what this means, but it prevents a clang crash + if (parmVarDecl->hasUninstantiatedDefaultArg() || superParmVarDecl->hasUninstantiatedDefaultArg()) { + return true; + } + return + checkIdenticalDefaultArguments( + parmVarDecl->getDefaultArg(), superParmVarDecl->getDefaultArg()) + != IdenticalDefaultArgumentsResult::No; + // for one, Clang 3.8 doesn't have EvaluateAsFloat; for another, since + // + // "PR23135: Don't instantiate constexpr functions referenced in + // unevaluated operands where possible", default args are not + // necessarily evaluated, so the above calls to EvaluateAsInt etc. may + // fail (as they do e.g. for SfxViewShell::SetPrinter and derived + // classes' 'SfxPrinterChangeFlags nDiffFlags = SFX_PRINTER_ALL' arg, + // include/sfx2/viewsh.hxx; what appears would help is to call + // 'compiler.getSema().MarkDeclarationsReferencedInExpr()' on + // defaultArgExpr and superDefaultArgExpr before any of the calls to + // EvaluateAsInt etc., cf. the implementation of + // Sema::CheckCXXDefaultArgExpr in Clang's lib/Sema/SemaExpr.cpp, but + // that would probably have unwanted side-effects) +} + +loplugin::Plugin::Registration< OverrideParam > overrideparam("overrideparam"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/overridevirtual.cxx b/compilerplugins/clang/overridevirtual.cxx new file mode 100644 index 000000000..8dd29ab0e --- /dev/null +++ b/compilerplugins/clang/overridevirtual.cxx @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include "clang/AST/Attr.h" + +#include "plugin.hxx" + +namespace { + +class OverrideVirtual: + public loplugin::FilteringRewritePlugin +{ +public: + explicit OverrideVirtual(loplugin::InstantiationData const & data): + FilteringRewritePlugin(data) {} + + virtual bool preRun() override; + virtual void run() override; + + bool VisitCXXMethodDecl(CXXMethodDecl const * decl); + +private: + std::set insertions_; +}; + +bool OverrideVirtual::preRun() { + return compiler.getLangOpts().CPlusPlus + && compiler.getPreprocessor().getIdentifierInfo( + "LIBO_INTERNAL_ONLY")->hasMacroDefinition(); +} + +void OverrideVirtual::run() { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); +} +bool OverrideVirtual::VisitCXXMethodDecl(CXXMethodDecl const * decl) { + // As a heuristic, ignore declarations where the name is spelled out in an + // ignored location; that e.g. handles uses of the Q_OBJECT macro from + // external QtCore/qobjectdefs.h: + if (ignoreLocation(decl) || !decl->isFirstDecl() + || decl->begin_overridden_methods() == decl->end_overridden_methods() + || decl->hasAttr() + || ignoreLocation( + compiler.getSourceManager().getSpellingLoc( + decl->getNameInfo().getLoc()))) + { + return true; + } + std::string over( + isInUnoIncludeFile(decl->getSourceRange().getBegin()) + ? "SAL_OVERRIDE" : "override"); + if (rewriter != nullptr) { + // In void MACRO(...); getSourceRange().getEnd() would (erroneously?) + // point at "MACRO" rather than ")", so make the loop always terminate + // at the first ";" or "{" instead of getSourceRange().getEnd(): + unsigned parens = 0; + bool seenSpace = false; + //TODO: Whether to add a space after an inserted "SAL_OVERRIDE" should + // depend on the following token at the spelling location where + // "SAL_OVERRIDE" is inserted, not on the following token in the fully- + // macro-expanded view: + bool addSpace = bool(); + SourceLocation loc; + for (SourceLocation l(decl->getSourceRange().getBegin());;) { + SourceLocation sl(compiler.getSourceManager().getSpellingLoc(l)); + unsigned n = Lexer::MeasureTokenLength( + sl, compiler.getSourceManager(), compiler.getLangOpts()); + StringRef s(compiler.getSourceManager().getCharacterData(sl), n); + //TODO: Looks like a Clang bug that in some cases like + // (filter/source/svg/svgexport.cxx) + // + // | #define TEXT_FIELD_GET_CLASS_NAME_METHOD( class_name ) \ | + // | virtual OUString getClassName() const \ | + // | { \ | + // | static const char className[] = #class_name; \ | + // | return OUString( className ); \ | + // | } | + // | | + // | TEXT_FIELD_GET_CLASS_NAME_METHOD( TextField ) | + // + // where "\" is followed directly by a real token without + // intervening whitespace, tokens "\virtual" and "\{" are + // reported: + if (s.startswith("\\\n")) { + s = s.drop_front(2); + } + if (parens == 0) { + if (s == "=" || s == "{") { + if (!seenSpace) { + addSpace = true; + } + break; + } + if (s == ";") { + break; + } + } + if (s == "(") { + assert(parens < std::numeric_limits::max()); + ++parens; + } else if (s == ")") { + assert(parens != 0); + --parens; + } + if (s.empty()) { + if (!seenSpace) { + addSpace = false; + } + seenSpace = true; + } else if (s.startswith("/*") || s.startswith("//") || s == "\\") { + if (!seenSpace) { + addSpace = true; + } + seenSpace = true; + } else { + seenSpace = false; + addSpace = false; + loc = sl; + } + if (l.isMacroID() + && compiler.getSourceManager().isAtEndOfImmediateMacroExpansion( + l, &l)) + { + n = Lexer::MeasureTokenLength( + compiler.getSourceManager().getSpellingLoc(l), + compiler.getSourceManager(), compiler.getLangOpts()); + } + l = l.getLocWithOffset(std::max(n, 1)); + } + assert(loc.isValid()); + if (!insertions_.insert(loc).second + || insertTextAfterToken( + loc, + std::string(" ") + over + std::string(addSpace ? " " : ""))) + { + return true; + } + } + report( + DiagnosticsEngine::Warning, + ("overriding virtual function declaration not marked '%0'"), + decl->getLocation()) + << over << decl->getSourceRange(); + for (auto i = decl->begin_overridden_methods(); + i != decl->end_overridden_methods(); ++i) + { + report( + DiagnosticsEngine::Note, "overridden declaration is here", + (*i)->getLocation()) + << (*i)->getSourceRange(); + } + return true; +} + +loplugin::Plugin::Registration overridevirtual("overridevirtual"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/pahole-all-classes.py b/compilerplugins/clang/pahole-all-classes.py new file mode 100755 index 000000000..6037287a8 --- /dev/null +++ b/compilerplugins/clang/pahole-all-classes.py @@ -0,0 +1,156 @@ +#!/usr/bin/python3 +# +# Find holes in structures, so that we can pack them and improve our memory density. +# +# In order to make this work, you need to +# (1) Be operating in a workspace where you have a __NON-DEBUG__ build of LibreOffice, but __WITH SYMBOLS__. +# (A debug build has different sizes for some things in the standard library.) +# (2) First run the unusedfields loplugin to generate a log file +# (3) Install the pahole stuff into your gdb, I used this one: +# https://github.com/PhilArmstrong/pahole-gdb +# (4) Run the script +# ./compilerplugins/clang/pahole-all-classes.py +# + +import _thread +import io +import os +import subprocess +import time +import re + +# search for all the class names in the file produced by the unusedfields loplugin +#a = subprocess.Popen("grep 'definition:' workdir/loplugin.unusedfields.log | sort -u", stdout=subprocess.PIPE, shell=True) +a = subprocess.Popen("cat n1", stdout=subprocess.PIPE, shell=True) + +classSet = set() +classSourceLocDict = dict() +locToClassDict = dict() +with a.stdout as txt: + for line in txt: + tokens = line.decode('utf8').strip().split("\t") + className = tokens[2].strip() + srcLoc = tokens[5].strip() + # ignore things like unions + if "anonymous" in className: continue + # ignore duplicates + if className in classSet: continue + classSet.add(className) + classSourceLocDict[className] = srcLoc + locToClassDict[srcLoc] = className +a.terminate() + +# Some of the pahole commands are going to fail, and I cannot read the error stream and the input stream +# together because python has no way of (easily) doing a non-blocking read. +# So I have to write the commands out using a background thread, and then read the entire resulting +# stream out below. +def write_pahole_commands(classes): + for className in classes: + stdin.write("echo " + className + " " + classSourceLocDict[className] + "\n") + stdin.write("pahole " + className + "\n") + stdin.flush() + stdin.write("echo all-done\n") + stdin.flush() + stdin.close() # only way to make it flush the last echo command + +# Use generator because lines often end up merged together in gdb's output, and we need +# to split them up, and that creates a mess in the parsing logic. +def read_generator(gdbOutput): + while True: + line = gdbOutput.readline(); + if line == "": return # end of file + line = line.decode('utf8').strip() + print("gdb: " + line) + for split in line.split("(gdb)"): + split = split.strip() + if len(split) == 0: continue + if "all-done" in split: return + yield split + +# build list of classes sorted by source location to increase the chances of +# processing stuff stored in the same DSO together +sortedLocs = sorted(locToClassDict.keys()) +classList = list() +for src in sortedLocs: + if "/inc/" in src or "include/" in src: + classList.append(locToClassDict[src]) + +with open("compilerplugins/clang/pahole.results", "wt") as f: + # Process 400 classes at a time, otherwise gdb's memory usage blows up and kills the machine + # This number is chosen to make gdb peak at around 8G. + while len(classList) > 0: + + currClassList = classList[0:500]; + classList = classList[500:] + + gdbProc = subprocess.Popen("gdb", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) + + stdin = io.TextIOWrapper(gdbProc.stdin, 'utf-8') + + # make gdb load all the debugging info + stdin.write("set confirm off\n") + # make gdb not wrap output and mess up my parsing + stdin.write("set width unlimited\n") + for filename in sorted(os.listdir('instdir/program')): + if filename.endswith(".so"): + stdin.write("add-symbol-file instdir/program/" + filename + "\n") + stdin.flush() + + + _thread.start_new_thread( write_pahole_commands, (currClassList,) ) + + firstLineRegex = re.compile(r"/\*\s+(\d+)\s+\*/ struct") # /* 16 */ struct Foo + fieldLineRegex = re.compile(r"/\*\s+(\d+)\s+(\d+)\s+\*/ ") # /* 12 8 */ class rtl::OUString aName + holeLineRegex = re.compile(r"/\* XXX (\d+) bit hole, try to pack \*/") + # sometimes pahole can't determine the size of a sub-struct, and then it returns bad data + bogusLineRegex = re.compile(r"/\*\s+\d+\s+0\s+\*/") + structLines = list() + foundHole = False + cumulativeHoleBits = 0 + alignedStructSize = 0 + foundBogusLine = False + # pahole doesn't report space at the end of the structure, so work it out myself + sizeOfStructWithoutPadding = 0 + for line in read_generator(gdbProc.stdout): + structLines.append(line) + firstLineMatch = firstLineRegex.match(line) + if firstLineMatch: + alignedStructSize = int(firstLineMatch.group(1)) + structLines.clear() + structLines.append(line) + holeLineMatch = holeLineRegex.match(line) + if holeLineMatch: + foundHole = True + cumulativeHoleBits += int(holeLineMatch.group(1)) + fieldLineMatch = fieldLineRegex.match(line) + if fieldLineMatch: + fieldPosInBytes = int(fieldLineMatch.group(1)) + fieldSizeInBytes = int(fieldLineMatch.group(2)) + sizeOfStructWithoutPadding = fieldPosInBytes + fieldSizeInBytes + if bogusLineRegex.match(line): + foundBogusLine = True + if line == "}": + # Ignore very large structs, packing those is not going to help much, and + # re-organising them can make them much less readable. + if foundHole and len(structLines) < 16 and alignedStructSize < 100 and not foundBogusLine: + # Verify that, after packing, and compiler alignment, the new structure will be actually smaller. + # Sometimes, we can save space, but the compiler will align the structure such that we don't + # actually save any space. + # TODO improve detection of the required alignment for a structure + holeAtEnd = alignedStructSize - sizeOfStructWithoutPadding + potentialSpace = (cumulativeHoleBits / 8) + holeAtEnd + if potentialSpace >= 8: + for line in structLines: + f.write(line + "\n") + if holeAtEnd > 0: + f.write("hole at end of struct: " + str(holeAtEnd) + "\n") + f.write("\n") + # reset state + structLines.clear() + foundHole = False + cumulativeHoleBits = 0 + structSize = 0 + foundBogusLine = False + actualStructSize = 0 + + gdbProc.terminate() diff --git a/compilerplugins/clang/passparamsbyref.cxx b/compilerplugins/clang/passparamsbyref.cxx new file mode 100644 index 000000000..9a3562752 --- /dev/null +++ b/compilerplugins/clang/passparamsbyref.cxx @@ -0,0 +1,234 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" + +// Find places where parameters are passed by value +// It's not very efficient, because we generally end up copying it twice - once into the parameter and +// again into the destination. +// They should rather be passed by reference. +// +// Generally recommending lambda capture by-ref rather than by-copy is even more +// problematic than with function parameters, as a lambda instance can easily +// outlive a referenced variable. So once lambdas start to get used in more +// sophisticated ways than passing them into standard algorithms, this plugin's +// advice, at least for explicit captures, will need to be revisited. + +namespace { + +class PassParamsByRef: + public loplugin::FilteringPlugin +{ +public: + explicit PassParamsByRef(loplugin::InstantiationData const & data): FilteringPlugin(data), mbInsideFunctionDecl(false) {} + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + // When warning about function params of primitive type that could be passed + // by value instead of by reference, make sure not to warn if the parameter + // is ever bound to a reference; on the one hand, this needs scaffolding in + // all Traverse*Decl functions (indirectly) derived from FunctionDecl; and + // on the other hand, use a hack of ignoring just the DeclRefExprs nested in + // LValueToRValue ImplicitCastExprs when determining whether a param is + // bound to a reference: + bool PreTraverseFunctionDecl(FunctionDecl *); + bool PostTraverseFunctionDecl(FunctionDecl *, bool); + bool TraverseFunctionDecl(FunctionDecl *); + bool PreTraverseImplicitCastExpr(ImplicitCastExpr *); + bool TraverseImplicitCastExpr(ImplicitCastExpr *); + + bool VisitBinaryOperator(BinaryOperator const *); + bool VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *); + +private: + bool isFat(QualType type); + + bool mbInsideFunctionDecl; + std::unordered_set mParamExclusions; +}; + +bool PassParamsByRef::PreTraverseFunctionDecl(FunctionDecl* functionDecl) +{ + if (ignoreLocation(functionDecl)) + return false; + if (functionDecl->isDeleted() + || functionDecl->isFunctionTemplateSpecialization()) + { + return false; + } + // only consider base declarations, not overridden ones, or we warn on methods that + // are overriding stuff from external libraries + const CXXMethodDecl * methodDecl = dyn_cast(functionDecl); + if (methodDecl && methodDecl->size_overridden_methods() > 0) + return false; + + // Only warn on the definition of the function: + if (!functionDecl->doesThisDeclarationHaveABody()) + return false; + + mbInsideFunctionDecl = true; + mParamExclusions.clear(); + return true; +} + +bool PassParamsByRef::PostTraverseFunctionDecl(FunctionDecl* functionDecl, bool) +{ + mbInsideFunctionDecl = false; + + auto cxxConstructorDecl = dyn_cast(functionDecl); + unsigned n = functionDecl->getNumParams(); + for (unsigned i = 0; i != n; ++i) { + const ParmVarDecl * pvDecl = functionDecl->getParamDecl(i); + auto const t = pvDecl->getType(); + if (!isFat(t)) + continue; + if (mParamExclusions.find(pvDecl) != mParamExclusions.end()) + continue; + // Ignore cases where the parameter is std::move'd. + // This is a fairly simple check, might need some more complexity if the parameter is std::move'd + // somewhere else in the constructor. + bool bFoundMove = false; + if (cxxConstructorDecl) { + for (CXXCtorInitializer const * cxxCtorInitializer : cxxConstructorDecl->inits()) { + if (cxxCtorInitializer->isMemberInitializer()) + { + auto cxxConstructExpr = dyn_cast(cxxCtorInitializer->getInit()->IgnoreParenImpCasts()); + if (cxxConstructExpr && cxxConstructExpr->getNumArgs() == 1) + { + if (auto callExpr = dyn_cast(cxxConstructExpr->getArg(0)->IgnoreParenImpCasts())) { + if (loplugin::DeclCheck(callExpr->getCalleeDecl()).Function("move").StdNamespace()) { + bFoundMove = true; + break; + } + } + } + } + } + } + if (bFoundMove) + continue; + report( + DiagnosticsEngine::Warning, + ("passing %0 by value, rather pass by const lvalue reference"), + pvDecl->getLocation()) + << t << pvDecl->getSourceRange(); + auto can = functionDecl->getCanonicalDecl(); + if (can->getLocation() != functionDecl->getLocation()) { + report( + DiagnosticsEngine::Note, "function is declared here:", + can->getLocation()) + << can->getSourceRange(); + } + } + return true; +} + +bool PassParamsByRef::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + bool ret = true; + if (PreTraverseFunctionDecl(functionDecl)) + { + ret = RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); + PostTraverseFunctionDecl(functionDecl, ret); + } + return ret; +} + +bool PassParamsByRef::PreTraverseImplicitCastExpr(ImplicitCastExpr * expr) +{ + if (ignoreLocation(expr)) + return false; + if (expr->getCastKind() == CK_LValueToRValue + && isa(expr->getSubExpr()->IgnoreParenImpCasts())) + return false; + return true; +} + +bool PassParamsByRef::TraverseImplicitCastExpr(ImplicitCastExpr * expr) +{ + bool ret = true; + if (PreTraverseImplicitCastExpr(expr)) + { + ret = RecursiveASTVisitor::TraverseImplicitCastExpr(expr); + } + return ret; +} + +bool PassParamsByRef::VisitBinaryOperator(const BinaryOperator * binaryOperator) +{ + if (binaryOperator->getOpcode() != BO_Assign) { + return true; + } + if (!mbInsideFunctionDecl) + return true; + // if we are assigning to a parameter, it can be inconvenient to make the param pass-by-ref + if (auto declRefExpr = dyn_cast(binaryOperator->getLHS())) + { + if (auto parmVarDecl = dyn_cast(declRefExpr->getDecl())) + mParamExclusions.emplace(parmVarDecl); + } + return true; +} + +bool PassParamsByRef::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr * cxxOperatorCallExpr ) +{ + if (!mbInsideFunctionDecl) + return true; + // if we are assigning to a parameter, it can be inconvenient to make the param pass-by-ref + auto op = cxxOperatorCallExpr->getOperator(); + if ( op != clang::OverloadedOperatorKind::OO_Equal + && op != clang::OverloadedOperatorKind::OO_SlashEqual + && op != clang::OverloadedOperatorKind::OO_StarEqual + && op != clang::OverloadedOperatorKind::OO_MinusEqual + && op != clang::OverloadedOperatorKind::OO_PlusEqual) + return true; + auto declRefExpr = dyn_cast(cxxOperatorCallExpr->getArg(0)); + if (!declRefExpr) + return true; + if (auto parmVarDecl = dyn_cast(declRefExpr->getDecl())) + mParamExclusions.emplace(parmVarDecl); + return true; +} + +bool PassParamsByRef::isFat(QualType type) { + if (!type->isRecordType()) { + return false; + } + loplugin::TypeCheck tc(type); + if ((tc.Class("Reference").Namespace("uno").Namespace("star") + .Namespace("sun").Namespace("com").GlobalNamespace()) + || (tc.Class("Sequence").Namespace("uno").Namespace("star") + .Namespace("sun").Namespace("com").GlobalNamespace()) + || tc.Class("OString").Namespace("rtl").GlobalNamespace() + || tc.Class("OUString").Namespace("rtl").GlobalNamespace() + || tc.Class("Reference").Namespace("rtl").GlobalNamespace()) + { + return true; + } + if (type->isIncompleteType()) { + return false; + } + clang::Type const * t2 = type.getTypePtrOrNull(); + return t2 != nullptr + && compiler.getASTContext().getTypeSizeInChars(t2).getQuantity() > 64; +} + +loplugin::Plugin::Registration< PassParamsByRef > passparamsbyref("passparamsbyref"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/passstuffbyref.cxx b/compilerplugins/clang/passstuffbyref.cxx new file mode 100644 index 000000000..d6ab91fc8 --- /dev/null +++ b/compilerplugins/clang/passstuffbyref.cxx @@ -0,0 +1,502 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include "check.hxx" +#include "plugin.hxx" + +// Find places where various things are passed by value. +// It's not very efficient, because we generally end up copying it twice - once into the parameter and +// again into the destination. +// They should rather be passed by reference. +// +// Generally recommending lambda capture by-ref rather than by-copy is even more +// problematic than with function parameters, as a lambda instance can easily +// outlive a referenced variable. So once lambdas start to get used in more +// sophisticated ways than passing them into standard algorithms, this plugin's +// advice, at least for explicit captures, will need to be revisited. + +namespace { + +class PassStuffByRef: + public loplugin::FilteringPlugin +{ +public: + explicit PassStuffByRef(loplugin::InstantiationData const & data): FilteringPlugin(data), mbInsideFunctionDecl(false), mbFoundReturnValueDisqualifier(false) {} + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + // When warning about function params of primitive type that could be passed + // by value instead of by reference, make sure not to warn if the parameter + // is ever bound to a reference; on the one hand, this needs scaffolding in + // all Traverse*Decl functions (indirectly) derived from FunctionDecl; and + // on the other hand, use a hack of ignoring just the DeclRefExprs nested in + // LValueToRValue ImplicitCastExprs when determining whether a param is + // bound to a reference: + bool TraverseFunctionDecl(FunctionDecl * decl); + bool TraverseCXXMethodDecl(CXXMethodDecl * decl); + bool TraverseCXXConstructorDecl(CXXConstructorDecl * decl); + bool TraverseCXXDestructorDecl(CXXDestructorDecl * decl); + bool TraverseCXXConversionDecl(CXXConversionDecl * decl); + bool VisitFunctionDecl(const FunctionDecl * decl); + bool TraverseImplicitCastExpr(ImplicitCastExpr * expr); + bool VisitDeclRefExpr(const DeclRefExpr * expr); + + bool VisitReturnStmt(const ReturnStmt * ); + bool VisitVarDecl(const VarDecl * ); + +private: + template bool traverseAnyFunctionDecl( + T * decl, bool (RecursiveASTVisitor::* fn)(T *)); + void checkParams(const FunctionDecl * functionDecl); + void checkReturnValue(const FunctionDecl * functionDecl, const CXXMethodDecl * methodDecl); + bool isPrimitiveConstRef(QualType type); + bool isReturnExprDisqualified(const Expr* expr); + + bool mbInsideFunctionDecl; + bool mbFoundReturnValueDisqualifier; + + struct FDecl { + std::set parms; + bool check = false; + }; + std::vector functionDecls_; +}; + +bool PassStuffByRef::TraverseFunctionDecl(FunctionDecl * decl) { + return traverseAnyFunctionDecl( + decl, &RecursiveASTVisitor::TraverseFunctionDecl); +} + +bool PassStuffByRef::TraverseCXXMethodDecl(CXXMethodDecl * decl) { + return traverseAnyFunctionDecl( + decl, &RecursiveASTVisitor::TraverseCXXMethodDecl); +} + +bool PassStuffByRef::TraverseCXXConstructorDecl(CXXConstructorDecl * decl) { + return traverseAnyFunctionDecl( + decl, &RecursiveASTVisitor::TraverseCXXConstructorDecl); +} + +bool PassStuffByRef::TraverseCXXDestructorDecl(CXXDestructorDecl * decl) { + return traverseAnyFunctionDecl( + decl, &RecursiveASTVisitor::TraverseCXXDestructorDecl); +} + +bool PassStuffByRef::TraverseCXXConversionDecl(CXXConversionDecl * decl) { + return traverseAnyFunctionDecl( + decl, &RecursiveASTVisitor::TraverseCXXConversionDecl); +} + +template bool PassStuffByRef::traverseAnyFunctionDecl( + T * decl, bool (RecursiveASTVisitor::* fn)(T *)) +{ + if (ignoreLocation(decl)) { + return true; + } + if (decl->doesThisDeclarationHaveABody()) { + functionDecls_.emplace_back(); + } + bool ret = (this->*fn)(decl); + if (decl->doesThisDeclarationHaveABody()) { + assert(!functionDecls_.empty()); + if (functionDecls_.back().check) { + for (auto d: functionDecls_.back().parms) { + report( + DiagnosticsEngine::Warning, + ("passing primitive type param %0 by const &, rather pass" + " by value"), + d->getLocation()) + << d->getType() << d->getSourceRange(); + auto can = decl->getCanonicalDecl(); + if (can->getLocation() != decl->getLocation()) { + report( + DiagnosticsEngine::Note, "function is declared here:", + can->getLocation()) + << can->getSourceRange(); + } + } + } + functionDecls_.pop_back(); + } + return ret; +} + +bool PassStuffByRef::VisitFunctionDecl(const FunctionDecl * functionDecl) { + if (ignoreLocation(functionDecl)) { + return true; + } + if (functionDecl->isDeleted() + || functionDecl->isFunctionTemplateSpecialization()) + { + return true; + } + // only consider base declarations, not overridden ones, or we warn on methods that + // are overriding stuff from external libraries + const CXXMethodDecl * methodDecl = dyn_cast(functionDecl); + if (methodDecl && methodDecl->size_overridden_methods() > 0) { + return true; + } + + checkParams(functionDecl); + checkReturnValue(functionDecl, methodDecl); + return true; +} + +bool PassStuffByRef::TraverseImplicitCastExpr(ImplicitCastExpr * expr) { + if (ignoreLocation(expr)) { + return true; + } + return + (expr->getCastKind() == CK_LValueToRValue + && (dyn_cast(expr->getSubExpr()->IgnoreParenImpCasts()) + != nullptr)) + || RecursiveASTVisitor::TraverseImplicitCastExpr(expr); +} + +bool PassStuffByRef::VisitDeclRefExpr(const DeclRefExpr * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto d = dyn_cast(expr->getDecl()); + if (d == nullptr) { + return true; + } + for (auto & fd: functionDecls_) { + if (fd.parms.erase(d) == 1) { + break; + } + } + return true; +} + +void PassStuffByRef::checkParams(const FunctionDecl * functionDecl) { + // Only warn on the definition of the function: + if (!functionDecl->doesThisDeclarationHaveABody()) { + return; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) { + return; + } + // these functions are passed as parameters to another function + if (loplugin::DeclCheck(functionDecl).MemberFunction() + .Class("ShapeAttributeLayer").Namespace("internal") + .Namespace("slideshow").GlobalNamespace()) + { + return; + } + unsigned n = functionDecl->getNumParams(); + assert(!functionDecls_.empty()); + functionDecls_.back().check = true; + for (unsigned i = 0; i != n; ++i) { + const ParmVarDecl * pvDecl = functionDecl->getParamDecl(i); + auto const t = pvDecl->getType(); + if (isPrimitiveConstRef(t)) { + functionDecls_.back().parms.insert(pvDecl); + } + } +} + +static bool startswith(const std::string& rStr, const char* pSubStr) { + return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; +} + +void PassStuffByRef::checkReturnValue(const FunctionDecl * functionDecl, const CXXMethodDecl * methodDecl) { + if (methodDecl && (methodDecl->isVirtual() || methodDecl->hasAttr())) { + return; + } + if( !functionDecl->doesThisDeclarationHaveABody() + || functionDecl->isLateTemplateParsed()) + { + return; + } + + const QualType type = functionDecl->getReturnType().getDesugaredType(compiler.getASTContext()); + if (type->isReferenceType() || type->isIntegralOrEnumerationType() || type->isPointerType() + || type->isTemplateTypeParmType() || type->isDependentType() || type->isBuiltinType() + || type->isScalarType()) + { + return; + } + + // not sure if it's possible to modify these + if (isa(functionDecl)) + return; + + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) { + return; + } + + loplugin::DeclCheck dc(functionDecl); + // function is passed as parameter to another function + if (dc.Function("ImplColMonoFnc").Class("GDIMetaFile").GlobalNamespace() + || (dc.Function("darkColor").Class("SvxBorderLine").Namespace("editeng") + .GlobalNamespace()) + || (dc.MemberFunction().Class("Binding").Namespace("xforms") + .GlobalNamespace()) + || (dc.MemberFunction().Class("Model").Namespace("xforms") + .GlobalNamespace()) + || (dc.MemberFunction().Class("Submission").Namespace("xforms") + .GlobalNamespace()) + || (dc.Function("TopLeft").Class("SwRect").GlobalNamespace()) + || (dc.Function("ConvDicList_CreateInstance").GlobalNamespace()) + || (dc.Function("Create").Class("OUnoAutoPilot").Namespace("dbp").GlobalNamespace()) + || (dc.Function("Size_").Class("SwRect").GlobalNamespace())) + { + return; + } + // not sure how to exclude this yet, returns copy of one of it's params + if (dc.Function("sameDistColor").GlobalNamespace() + || dc.Function("sameColor").GlobalNamespace() + || (dc.Operator(OO_Call).Struct("StringIdentity").AnonymousNamespace() + .Namespace("pcr").GlobalNamespace()) + || (dc.Function("accumulate").Namespace("internal") + .Namespace("slideshow").GlobalNamespace()) + || (dc.Function("lerp").Namespace("internal").Namespace("slideshow") + .GlobalNamespace())) + return; + // depends on a define + if (dc.Function("GetSharedFileURL").Class("SfxObjectShell") + .GlobalNamespace()) { + return; + } + // hides a constructor + if (dc.Function("createNonOwningCopy").Class("SortedAutoCompleteStrings").Namespace("editeng") + .GlobalNamespace()) { + return; + } + // template function + if (dc.Function("convertItems").Class("ValueParser").Namespace("configmgr").GlobalNamespace() + || dc.Function("parseListValue").AnonymousNamespace().Namespace("configmgr").GlobalNamespace() + || dc.Function("parseSingleValue").AnonymousNamespace().Namespace("configmgr").GlobalNamespace() + || dc.Function("Create").Class("HandlerComponentBase").Namespace("pcr").GlobalNamespace()) { + return; + } + if (startswith(type.getAsString(), "struct o3tl::strong_int")) { + return; + } + auto tc = loplugin::TypeCheck(functionDecl->getReturnType()); + // these functions are passed by function-pointer + if (functionDecl->getIdentifier() && functionDecl->getName() == "GetRanges" + && tc.Struct("WhichRangesContainer").GlobalNamespace()) + return; + // extremely simple class, might as well pass by value + if (tc.Class("Color")) { + return; + } + // extremely simple class, might as well pass by value + if (tc.Struct("TranslateId")) { + return; + } + + // functionDecl->dump(); + + mbInsideFunctionDecl = true; + mbFoundReturnValueDisqualifier = false; + TraverseStmt(functionDecl->getBody()); + mbInsideFunctionDecl = false; + + if (mbFoundReturnValueDisqualifier) + return; + + report( DiagnosticsEngine::Warning, + "rather return %0 by const& than by value, to avoid unnecessary copying", + functionDecl->getSourceRange().getBegin()) + << type.getAsString() << functionDecl->getSourceRange(); + + // display the location of the class member declaration so I don't have to search for it by hand + auto canonicalDecl = functionDecl->getCanonicalDecl(); + if (functionDecl != canonicalDecl) + { + report( DiagnosticsEngine::Note, + "decl here", + canonicalDecl->getSourceRange().getBegin()) + << canonicalDecl->getSourceRange(); + } + + //functionDecl->dump(); +} + +bool PassStuffByRef::VisitReturnStmt(const ReturnStmt * returnStmt) +{ + if (!mbInsideFunctionDecl) + return true; + const Expr* expr = dyn_cast(*returnStmt->child_begin())->IgnoreParenCasts(); + + if (isReturnExprDisqualified(expr)) + mbFoundReturnValueDisqualifier = true; + + return true; +} + +/** + * Does a return expression disqualify this method from doing return by const & ? + */ +bool PassStuffByRef::isReturnExprDisqualified(const Expr* expr) +{ + while (true) + { + expr = expr->IgnoreParens(); + if (auto implicitCast = dyn_cast(expr)) { + expr = implicitCast->getSubExpr(); + continue; + } + if (auto exprWithCleanups = dyn_cast(expr)) { + expr = exprWithCleanups->getSubExpr(); + continue; + } + if (auto constructExpr = dyn_cast(expr)) + { + if (constructExpr->getNumArgs()==1 + && constructExpr->getConstructor()->isCopyOrMoveConstructor()) + { + expr = constructExpr->getArg(0); + continue; + } + else + return true; + } + if (isa(expr)) { + return true; + } + if (isa(expr)) { + return true; + } + if (isa(expr)) { + return true; + } + if (isa(expr)) { + return true; + } + expr = expr->IgnoreParenCasts(); + if (auto childExpr = dyn_cast(expr)) { + expr = childExpr->getLHS(); + continue; + } + if (auto memberExpr = dyn_cast(expr)) { + expr = memberExpr->getBase(); + continue; + } + if (auto declRef = dyn_cast(expr)) { + // a param might be a temporary + if (isa(declRef->getDecl())) + return true; + const VarDecl* varDecl = dyn_cast(declRef->getDecl()); + if (varDecl) { + if (varDecl->getStorageDuration() == SD_Thread + || varDecl->getStorageDuration() == SD_Static ) { + return false; + } + return true; + } + } + if (auto condOper = dyn_cast(expr)) { + return isReturnExprDisqualified(condOper->getTrueExpr()) + || isReturnExprDisqualified(condOper->getFalseExpr()); + } + if (auto unaryOp = dyn_cast(expr)) { + expr = unaryOp->getSubExpr(); + continue; + } + if (auto operatorCallExpr = dyn_cast(expr)) { + // TODO could improve this, but sometimes it means we're returning a copy of a temporary. + // Same logic as CXXOperatorCallExpr::isAssignmentOp(), which our supported clang + // doesn't have yet. + auto Opc = operatorCallExpr->getOperator(); + if (Opc == OO_Equal || Opc == OO_StarEqual || + Opc == OO_SlashEqual || Opc == OO_PercentEqual || + Opc == OO_PlusEqual || Opc == OO_MinusEqual || + Opc == OO_LessLessEqual || Opc == OO_GreaterGreaterEqual || + Opc == OO_AmpEqual || Opc == OO_CaretEqual || + Opc == OO_PipeEqual) + return true; + if (Opc == OO_Subscript) + { + if (isReturnExprDisqualified(operatorCallExpr->getArg(0))) + return true; + // otherwise fall through to the checking below + } + } + if (auto memberCallExpr = dyn_cast(expr)) { + if (isReturnExprDisqualified(memberCallExpr->getImplicitObjectArgument())) + return true; + // otherwise fall through to the checking in CallExpr + } + if (auto callExpr = dyn_cast(expr)) { + FunctionDecl const * calleeFunctionDecl = callExpr->getDirectCallee(); + if (!calleeFunctionDecl) + return true; + // TODO anything takes a non-integral param is suspect because it might return the param by ref. + // we could tighten this to only reject functions that have a param of the same type + // as the return type. Or we could check for such functions and disallow them. + // Or we could force such functions to be annotated somehow. + for (unsigned i = 0; i != calleeFunctionDecl->getNumParams(); ++i) { + if (!calleeFunctionDecl->getParamDecl(i)->getType()->isIntegralOrEnumerationType()) + return true; + } + auto tc = loplugin::TypeCheck(calleeFunctionDecl->getReturnType()); + if (!tc.LvalueReference() && !tc.Pointer()) + return true; + } + return false; + } +} + +bool PassStuffByRef::VisitVarDecl(const VarDecl * varDecl) +{ + if (!mbInsideFunctionDecl) + return true; + // things guarded by locking are probably best left alone + loplugin::TypeCheck dc(varDecl->getType()); + if (dc.Class("Guard").Namespace("osl").GlobalNamespace()) + mbFoundReturnValueDisqualifier = true; + if (dc.Class("ClearableGuard").Namespace("osl").GlobalNamespace()) + mbFoundReturnValueDisqualifier = true; + if (dc.Class("ResettableGuard").Namespace("osl").GlobalNamespace()) + mbFoundReturnValueDisqualifier = true; + else if (dc.Class("SolarMutexGuard").GlobalNamespace()) + mbFoundReturnValueDisqualifier = true; + else if (dc.Class("SfxModelGuard").GlobalNamespace()) + mbFoundReturnValueDisqualifier = true; + else if (dc.Class("ReadWriteGuard").Namespace("utl").GlobalNamespace()) + mbFoundReturnValueDisqualifier = true; + return true; +} + +bool PassStuffByRef::isPrimitiveConstRef(QualType type) { + if (type->isIncompleteType()) { + return false; + } + const clang::ReferenceType* referenceType = type->getAs(); + if (referenceType == nullptr) { + return false; + } + QualType pointeeQT = referenceType->getPointeeType(); + if (!pointeeQT.isConstQualified()) { + return false; + } + if (!pointeeQT->isFundamentalType()) { + return false; + } + // ignore double for now, some of our code seems to believe it is cheaper to pass by ref + const BuiltinType* builtinType = pointeeQT->getAs(); + return builtinType->getKind() != BuiltinType::Kind::Double; +} + + +loplugin::Plugin::Registration< PassStuffByRef > X("passstuffbyref", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx new file mode 100644 index 000000000..727eda589 --- /dev/null +++ b/compilerplugins/clang/plugin.cxx @@ -0,0 +1,1081 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "plugin.hxx" + +#include +#include +#include + +#include +#include +#include + +#include "config_clang.h" + +#include "compat.hxx" +#include "pluginhandler.hxx" +#include "check.hxx" + +/* +Base classes for plugin actions. +*/ +namespace loplugin +{ + +namespace { + +Expr const * skipImplicit(Expr const * expr) { + if (auto const e = dyn_cast(expr)) { + expr = e->getSubExpr()->IgnoreImpCasts(); + } + if (auto const e = dyn_cast(expr)) { + expr = e->getSubExpr(); + } + return expr; +} + +bool structurallyIdentical(Stmt const * stmt1, Stmt const * stmt2) { + if (stmt1->getStmtClass() != stmt2->getStmtClass()) { + return false; + } + switch (stmt1->getStmtClass()) { + case Stmt::CXXConstructExprClass: + if (cast(stmt1)->getConstructor()->getCanonicalDecl() + != cast(stmt2)->getConstructor()->getCanonicalDecl()) + { + return false; + } + break; + case Stmt::DeclRefExprClass: + if (cast(stmt1)->getDecl()->getCanonicalDecl() + != cast(stmt2)->getDecl()->getCanonicalDecl()) + { + return false; + } + break; + case Stmt::ImplicitCastExprClass: + { + auto const e1 = cast(stmt1); + auto const e2 = cast(stmt2); + if (e1->getCastKind() != e2->getCastKind() + || e1->getType().getCanonicalType() != e2->getType().getCanonicalType()) + { + return false; + } + break; + } + case Stmt::MemberExprClass: + { + auto const e1 = cast(stmt1); + auto const e2 = cast(stmt2); + if (e1->isArrow() != e2->isArrow() + || e1->getType().getCanonicalType() != e2->getType().getCanonicalType()) + { + return false; + } + break; + } + case Stmt::CXXMemberCallExprClass: + case Stmt::CXXOperatorCallExprClass: + if (cast(stmt1)->getType().getCanonicalType() + != cast(stmt2)->getType().getCanonicalType()) + { + return false; + } + break; + case Stmt::MaterializeTemporaryExprClass: + case Stmt::CXXBindTemporaryExprClass: + case Stmt::ParenExprClass: + break; + case Stmt::CXXNullPtrLiteralExprClass: + return true; + default: + // Conservatively assume non-identical for expressions that don't happen for us in practice + // when compiling the LO code base (and for which the above set of supported classes would + // need to be extended): + return false; + } + auto i1 = stmt1->child_begin(); + auto e1 = stmt1->child_end(); + auto i2 = stmt2->child_begin(); + auto e2 = stmt2->child_end(); + for (; i1 != e1; ++i1, ++i2) { + if (i2 == e2 || !structurallyIdentical(*i1, *i2)) { + return false; + } + } + return i2 == e2; +} + +} + +Plugin::Plugin( const InstantiationData& data ) + : compiler( data.compiler ), handler( data.handler ), name( data.name ) +{ +} + +DiagnosticBuilder Plugin::report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc ) const +{ + return handler.report( level, name, message, compiler, loc ); +} + +bool Plugin::suppressWarningAt(SourceLocation location) const { + auto const start = compiler.getSourceManager().getSpellingLoc(location); + auto const startInfo = compiler.getSourceManager().getDecomposedLoc(start); + auto invalid = false; + auto const buf = compiler.getSourceManager().getBufferData(startInfo.first, &invalid); + if (invalid) { + if (isDebugMode()) { + report(DiagnosticsEngine::Fatal, "failed to getBufferData", start); + } + return false; + } + auto const label = std::string("[-loplugin:").append(name).append("]"); + // Look back to the beginning of the previous line: + auto loc = start; + auto locInfo = startInfo; + auto cur = loc; + enum class State { Normal, Slash, Comment }; + auto state = State::Normal; + auto newlines = 0; + for (auto prev = cur;;) { + auto prevInfo = compiler.getSourceManager().getDecomposedLoc(prev); + if (prev == compiler.getSourceManager().getLocForStartOfFile(prevInfo.first)) { + if (state == State::Comment && isDebugMode()) { + report( + DiagnosticsEngine::Fatal, + "beginning of file while looking for beginning of comment", prev); + } + break; + } + Token tok; + if (Lexer::getRawToken( + Lexer::GetBeginningOfToken( + prev.getLocWithOffset(-1), compiler.getSourceManager(), compiler.getLangOpts()), + tok, compiler.getSourceManager(), compiler.getLangOpts(), true)) + { + if (isDebugMode()) { + report( + DiagnosticsEngine::Fatal, "failed to getRawToken", + prev.getLocWithOffset(-1)); + } + break; + } + if (tok.getLocation() == cur) { + // Keep walking back, character by character, through whitespace preceding the current + // token, which Clang treats as nominally belonging to that token (so the above + // Lexer::getRawToken/Lexer::GetBeginningOfToken will have produced just the same tok + // again): + prev = prev.getLocWithOffset(-1); + continue; + } + cur = tok.getLocation(); + prev = cur; + if (state == State::Comment) { + // Lexer::GetBeginningOfToken (at least towards Clang 15, still) only re-scans from the + // start of the current line, so if we saw the end of a multi-line /*...*/ comment, we + // saw that as individual '/' and '*' faux-tokens, at which point we must (hopefully?) + // actually be at the end of such a multi-line comment, so we keep walking back to the + // first '/*' we encounter (TODO: which still need not be the real start of the comment, + // if the comment contains embedded '/*', but we could determine that only if we + // re-scanned from the start of the file): + if (!tok.is(tok::comment)) { + continue; + } + SmallVector tmp; + bool invalid = false; + auto const spell = Lexer::getSpelling( + prev, tmp, compiler.getSourceManager(), compiler.getLangOpts(), &invalid); + if (invalid) { + if (isDebugMode()) { + report(DiagnosticsEngine::Fatal, "failed to getSpelling", prev); + } + } else if (!spell.startswith("/*")) { + continue; + } + } + prevInfo = compiler.getSourceManager().getDecomposedLoc(prev); + auto const end = prev.getLocWithOffset(tok.getLength()); + auto const endInfo = compiler.getSourceManager().getDecomposedLoc(end); + assert(prevInfo.first == endInfo .first); + assert(prevInfo.second <= endInfo.second); + assert(endInfo.first == locInfo.first); + // Whitespace between tokens is found at the end of prev, from end to loc (unless this is a + // multi-line comment, in which case the whitespace has already been inspected as the + // whitespace following the comment's final '/' faux-token): + StringRef ws; + if (state != State::Comment) { + assert(endInfo.second <= locInfo.second); + ws = buf.substr(endInfo.second, locInfo.second - endInfo.second); + } + for (std::size_t i = 0;;) { + auto const j = ws.find('\n', i); + if (j == StringRef::npos) { + break; + } + ++newlines; + if (newlines == 2) { + break; + } + i = j + 1; + } + if (newlines == 2) { + break; + } + auto str = buf.substr(prevInfo.second, endInfo.second - prevInfo.second); + if (tok.is(tok::comment) && str.contains(label)) { + return true; + } + for (std::size_t i = 0;;) { + auto const j = str.find('\n', i); + if (j == StringRef::npos) { + break; + } + ++newlines; + if (newlines == 2) { + break; + } + i = j + 1; + } + if (newlines == 2) { + break; + } + loc = prev; + locInfo = prevInfo; + switch (state) { + case State::Normal: + if (tok.is(tok::slash)) { + state = State::Slash; + } + break; + case State::Slash: + state = tok.is(tok::star) && ws.empty() ? State::Comment : State::Normal; + //TODO: check for "ws is only folding whitespace" rather than for `ws.empty()` (but + // then, we must not count newlines in that whitespace twice, first as part of the + // whitespace following the comment's semi-final '*' faux-token and then as part of + // the comment token's content) + break; + case State::Comment: + state = State::Normal; + } + } + // Look forward to the end of the current line: + loc = start; + locInfo = startInfo; + for (;;) { + Token tok; + if (Lexer::getRawToken(loc, tok, compiler.getSourceManager(), compiler.getLangOpts(), true)) + { + if (isDebugMode()) { + report(DiagnosticsEngine::Fatal, "failed to getRawToken", loc); + } + break; + } + // Whitespace between tokens is found at the beginning, from loc to beg: + auto const beg = tok.getLocation(); + auto const begInfo = compiler.getSourceManager().getDecomposedLoc(beg); + assert(begInfo.first == locInfo.first); + assert(begInfo.second >= locInfo.second); + if (buf.substr(locInfo.second, begInfo.second - locInfo.second).contains('\n')) { + break; + } + auto const next = beg.getLocWithOffset(tok.getLength()); + auto const nextInfo = compiler.getSourceManager().getDecomposedLoc(next); + assert(nextInfo.first == begInfo.first); + assert(nextInfo.second >= begInfo.second); + auto const str = buf.substr(begInfo.second, nextInfo.second - begInfo.second); + if (tok.is(tok::comment) && str.contains(label)) { + return true; + } + if (tok.is(tok::eof) || str.contains('\n')) { + break; + } + loc = next; + locInfo = nextInfo; + } + return false; +} + +void normalizeDotDotInFilePath( std::string & s ) +{ + for (std::string::size_type i = 0;;) + { + i = s.find("/.", i); + if (i == std::string::npos) { + break; + } + if (i + 2 == s.length() || s[i + 2] == '/') { + s.erase(i, 2); // [AAA]/.[/CCC] -> [AAA][/CCC] + } else if (s[i + 2] == '.' + && (i + 3 == s.length() || s[i + 3] == '/')) + { + if (i == 0) { // /..[/CCC] -> /..[/CCC] + break; + } + auto j = s.rfind('/', i - 1); + if (j == std::string::npos) + { + // BBB/..[/CCC] -> BBB/..[/CCC] (instead of BBB/../CCC -> + // CCC, to avoid wrong ../../CCC -> CCC; relative paths + // shouldn't happen anyway, and even if they did, wouldn't + // match against WORKDIR anyway, as WORKDIR should be + // absolute): + break; + } + s.erase(j, i + 3 - j); // AAA/BBB/..[/CCC] -> AAA[/CCC] + i = j; + } else { + i += 2; + } + } +} + +void Plugin::registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName, + bool isPPCallback, bool isSharedPlugin, bool byDefault ) +{ + PluginHandler::registerPlugin( create, optionName, isPPCallback, isSharedPlugin, byDefault ); +} + +bool Plugin::evaluate(const Expr* expr, APSInt& x) +{ + if (compat::EvaluateAsInt(expr, x, compiler.getASTContext())) + { + return true; + } + if (isa(expr)) { + x = 0; + return true; + } + return false; +} + +const Stmt* Plugin::getParentStmt( const Stmt* stmt ) +{ + auto parentsRange = compiler.getASTContext().getParents(*stmt); + if ( parentsRange.begin() == parentsRange.end()) + return nullptr; + return parentsRange.begin()->get(); +} + +Stmt* Plugin::getParentStmt( Stmt* stmt ) +{ + auto parentsRange = compiler.getASTContext().getParents(*stmt); + if ( parentsRange.begin() == parentsRange.end()) + return nullptr; + return const_cast(parentsRange.begin()->get()); +} + +const Decl* getFunctionDeclContext(ASTContext& context, const Stmt* stmt) +{ + auto const parents = context.getParents(*stmt); + auto it = parents.begin(); + + if (it == parents.end()) + return nullptr; + + const Decl *decl = it->get(); + if (decl) + { + if (isa(decl)) + return dyn_cast(decl->getDeclContext()); + return decl; + } + + stmt = it->get(); + if (stmt) + return getFunctionDeclContext(context, stmt); + + return nullptr; +} + +const FunctionDecl* Plugin::getParentFunctionDecl( const Stmt* stmt ) +{ + const Decl *decl = getFunctionDeclContext(compiler.getASTContext(), stmt); + if (decl) + return static_cast(decl->getNonClosureContext()); + + return nullptr; +} + +StringRef Plugin::getFilenameOfLocation(SourceLocation spellingLocation) const +{ + // prevent crashes when running the global-analysis plugins + if (!spellingLocation.isValid()) + return ""; + + static enum { NOINIT, STDIN, GOOD } s_Mode(NOINIT); + if (s_Mode == GOOD) + { + return compiler.getSourceManager().getFilename(spellingLocation); + } + else if (s_Mode == STDIN + || !compiler.getSourceManager().isInMainFile(spellingLocation)) + { + const char* bufferName = compiler.getSourceManager().getPresumedLoc(spellingLocation).getFilename(); + return bufferName; + } + else + { + char const*const pCXX = getenv("CXX"); + if (pCXX && strstr(pCXX, "sccache")) + { // heuristic; sccache passes file with -frewrite-directives by name + s_Mode = STDIN; + return getFilenameOfLocation(spellingLocation); + } + auto const fn(compiler.getSourceManager().getFilename(spellingLocation)); + if (!fn.data()) // wtf? happens in sot/source/sdstor/stg.cxx + { + return fn; + } +#if !defined _WIN32 + assert(fn.startswith("/") || fn == ""); +#endif + s_Mode = fn == "" ? STDIN : GOOD; + return getFilenameOfLocation(spellingLocation); + } +} + +bool Plugin::isInUnoIncludeFile(SourceLocation spellingLocation) const +{ + StringRef name{ getFilenameOfLocation(spellingLocation) }; + return compiler.getSourceManager().isInMainFile(spellingLocation) + ? (isSamePathname(name, SRCDIR "/cppu/source/cppu/compat.cxx") + || isSamePathname(name, SRCDIR "/cppuhelper/source/compat.cxx") + || isSamePathname(name, SRCDIR "/sal/osl/all/compat.cxx")) + : (hasPathnamePrefix(name, SRCDIR "/include/com/") + || hasPathnamePrefix(name, SRCDIR "/include/cppu/") + || hasPathnamePrefix(name, SRCDIR "/include/cppuhelper/") + || hasPathnamePrefix(name, SRCDIR "/include/osl/") + || hasPathnamePrefix(name, SRCDIR "/include/rtl/") + || hasPathnamePrefix(name, SRCDIR "/include/sal/") + || hasPathnamePrefix(name, SRCDIR "/include/salhelper/") + || hasPathnamePrefix(name, SRCDIR "/include/typelib/") + || hasPathnamePrefix(name, SRCDIR "/include/uno/") + || hasPathnamePrefix(name, SDKDIR "/include/")); +} + +bool Plugin::isInUnoIncludeFile(const FunctionDecl* functionDecl) const +{ + return isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( + functionDecl->getCanonicalDecl()->getNameInfo().getLoc())); +} + +SourceLocation Plugin::locationAfterToken( SourceLocation location ) +{ + return Lexer::getLocForEndOfToken( location, 0, compiler.getSourceManager(), compiler.getLangOpts()); +} + +bool Plugin::isUnitTestMode() +{ + return PluginHandler::isUnitTestMode(); +} + +bool Plugin::containsPreprocessingConditionalInclusion(SourceRange range) +{ + // Preprocessing directives (other than _Pragma, which is not relevant here) cannot appear in + // macro expansions, so it is safe to just consider the range of expansion locations: + auto const begin = compiler.getSourceManager().getExpansionLoc( + range.getBegin()); + auto const end = compiler.getSourceManager().getExpansionLoc( + range.getEnd()); + assert(begin.isFileID() && end.isFileID()); + if (!(begin == end + || compiler.getSourceManager().isBeforeInTranslationUnit( + begin, end))) + { + if (isDebugMode()) { + report( + DiagnosticsEngine::Fatal, + ("unexpected broken range for Plugin::containsPreprocessingConditionalInclusion," + " case 1"), + range.getBegin()) + << range; + } + // Conservatively assume "yes" if lexing fails: + return true; + } + auto hash = false; + for (auto loc = begin;;) { + Token tok; + if (Lexer::getRawToken( + loc, tok, compiler.getSourceManager(), + compiler.getLangOpts(), true)) + { + if (isDebugMode()) { + report( + DiagnosticsEngine::Fatal, + ("unexpected broken range for" + " Plugin::containsPreprocessingConditionalInclusion, case 2"), + loc) + << range; + } + // Conservatively assume "yes" if lexing fails: + return true; + } + if (hash && tok.is(tok::raw_identifier)) { + auto const id = tok.getRawIdentifier(); + if (id == "if" || id == "ifdef" || id == "ifndef" + || id == "elif" || id == "else" || id == "endif") + { + return true; + } + } + if (loc == end) { + break; + } + hash = tok.is(tok::hash) && tok.isAtStartOfLine(); + loc = loc.getLocWithOffset( + std::max( + Lexer::MeasureTokenLength( + loc, compiler.getSourceManager(), + compiler.getLangOpts()), + 1)); + } + return false; +} + +Plugin::IdenticalDefaultArgumentsResult Plugin::checkIdenticalDefaultArguments( + Expr const * argument1, Expr const * argument2) +{ + if ((argument1 == nullptr) != (argument2 == nullptr)) { + return IdenticalDefaultArgumentsResult::No; + } + if (argument1 == nullptr) { + return IdenticalDefaultArgumentsResult::Yes; + } + if (argument1->isNullPointerConstant(compiler.getASTContext(), Expr::NPC_NeverValueDependent) + && argument2->isNullPointerConstant(compiler.getASTContext(), Expr::NPC_NeverValueDependent)) + { + return IdenticalDefaultArgumentsResult::Yes; + } + APSInt x1, x2; + if (evaluate(argument1, x1) && evaluate(argument2, x2)) + { + return x1 == x2 + ? IdenticalDefaultArgumentsResult::Yes + : IdenticalDefaultArgumentsResult::No; + } + APFloat f1(0.0f), f2(0.0f); + if (argument1->EvaluateAsFloat(f1, compiler.getASTContext()) + && argument2->EvaluateAsFloat(f2, compiler.getASTContext())) + { + return f1.bitwiseIsEqual(f2) + ? IdenticalDefaultArgumentsResult::Yes + : IdenticalDefaultArgumentsResult::No; + } + auto const desugared1 = argument1->IgnoreParenImpCasts(); + auto const desugared2 = argument2->IgnoreParenImpCasts(); + if (auto const lit1 = dyn_cast(desugared1)) { + if (auto const lit2 = dyn_cast(desugared2)) { + return lit1->getBytes() == lit2->getBytes() + ? IdenticalDefaultArgumentsResult::Yes + : IdenticalDefaultArgumentsResult::No; + } + } + // catch params with defaults like "= OUString()" + for (Expr const * e1 = desugared1, * e2 = desugared2;;) { + auto const ce1 = dyn_cast(skipImplicit(e1)); + auto const ce2 = dyn_cast(skipImplicit(e2)); + if (ce1 == nullptr || ce2 == nullptr) { + break; + } + if (ce1->getConstructor()->getCanonicalDecl() != ce2->getConstructor()->getCanonicalDecl()) + { + return IdenticalDefaultArgumentsResult::No; + } + if (ce1->isElidable() && ce2->isElidable() && ce1->getNumArgs() == 1 + && ce2->getNumArgs() == 1) + { + assert(ce1->getConstructor()->isCopyOrMoveConstructor()); + e1 = ce1->getArg(0)->IgnoreImpCasts(); + e2 = ce2->getArg(0)->IgnoreImpCasts(); + continue; + } + if (ce1->getNumArgs() == 0 && ce2->getNumArgs() == 0) { + return IdenticalDefaultArgumentsResult::Yes; + } + break; + } + // If the EvaluateAsRValue derivatives above failed because the arguments use e.g. (constexpr) + // function template specializations that happen to not have been instantiated in this TU, try a + // structural comparison of the arguments: + if (structurallyIdentical(argument1, argument2)) { + return IdenticalDefaultArgumentsResult::Yes; + } + if (isDebugMode()) { + report( + DiagnosticsEngine::Fatal, "TODO: Unexpected 'IdenticalDefaultArgumentsResult::Maybe'", + argument1->getExprLoc()) + << argument1->getSourceRange(); + report( + DiagnosticsEngine::Note, "TODO: second argument is here", argument2->getExprLoc()) + << argument2->getSourceRange(); + argument1->dump(); + argument2->dump(); + } + return IdenticalDefaultArgumentsResult::Maybe; +} + +RewritePlugin::RewritePlugin( const InstantiationData& data ) + : Plugin( data ) + , rewriter( data.rewriter ) +{ +} + +bool RewritePlugin::insertText( SourceLocation Loc, StringRef Str, bool InsertAfter, bool indentNewLines ) +{ + assert( rewriter ); + if (wouldRewriteWorkdir(Loc)) + return false; + SourceRange Range(SourceRange(Loc, Loc.getLocWithOffset(Str.size()))); + if( !handler.checkOverlap( Range ) ) + { + report( DiagnosticsEngine::Warning, "double code removal, possible plugin error", Range.getBegin()); + return false; + } + if( rewriter->InsertText( Loc, Str, InsertAfter, indentNewLines )) + return reportEditFailure( Loc ); + handler.addSourceModification(Range); + return true; +} + +bool RewritePlugin::insertTextAfter( SourceLocation Loc, StringRef Str ) +{ + assert( rewriter ); + if (wouldRewriteWorkdir(Loc)) + return false; + SourceRange Range(SourceRange(Loc, Loc.getLocWithOffset(Str.size()))); + if( !handler.checkOverlap( Range ) ) + { + report( DiagnosticsEngine::Warning, "double code removal, possible plugin error", Range.getBegin()); + return false; + } + if( rewriter->InsertTextAfter( Loc, Str )) + return reportEditFailure( Loc ); + handler.addSourceModification(Range); + return true; +} + +bool RewritePlugin::insertTextAfterToken( SourceLocation Loc, StringRef Str ) +{ + assert( rewriter ); + if (wouldRewriteWorkdir(Loc)) + return false; + SourceRange Range(SourceRange(Loc, Loc.getLocWithOffset(Str.size()))); + if( !handler.checkOverlap( Range ) ) + { + report( DiagnosticsEngine::Warning, "double code removal, possible plugin error", Range.getBegin()); + return false; + } + if( rewriter->InsertTextAfterToken( Loc, Str )) + return reportEditFailure( Loc ); + handler.addSourceModification(Range); + return true; +} + +bool RewritePlugin::insertTextBefore( SourceLocation Loc, StringRef Str ) +{ + assert( rewriter ); + if (wouldRewriteWorkdir(Loc)) + return false; + SourceRange Range(SourceRange(Loc, Loc.getLocWithOffset(Str.size()))); + if( !handler.checkOverlap( Range ) ) + { + report( DiagnosticsEngine::Warning, "double code removal, possible plugin error", Range.getBegin()); + return false; + } + if( rewriter->InsertTextBefore( Loc, Str )) + return reportEditFailure( Loc ); + handler.addSourceModification(Range); + return true; +} + +bool RewritePlugin::removeText( SourceLocation Start, unsigned Length, RewriteOptions opts ) +{ + CharSourceRange range( SourceRange( Start, Start.getLocWithOffset( Length )), false ); + return removeText( range, opts ); +} + +bool RewritePlugin::removeText( SourceRange range, RewriteOptions opts ) +{ + return removeText( CharSourceRange( range, true ), opts ); +} + +bool RewritePlugin::removeText( CharSourceRange range, RewriteOptions opts ) +{ + assert( rewriter ); + if (wouldRewriteWorkdir(range.getBegin())) + return false; + if( rewriter->getRangeSize( range, opts ) == -1 ) + return reportEditFailure( range.getBegin()); + if( !handler.checkOverlap( range.getAsRange() ) ) + { + report( DiagnosticsEngine::Warning, "double code removal, possible plugin error", range.getBegin()); + return false; + } + if( opts.flags & RemoveWholeStatement || opts.flags & RemoveAllWhitespace ) + { + if( !adjustRangeForOptions( &range, opts )) + return reportEditFailure( range.getBegin()); + } + if( rewriter->RemoveText( range, opts )) + return reportEditFailure( range.getBegin()); + handler.addSourceModification(range.getAsRange()); + return true; +} + +bool RewritePlugin::adjustRangeForOptions( CharSourceRange* range, RewriteOptions opts ) +{ + assert( rewriter ); + SourceManager& SM = rewriter->getSourceMgr(); + SourceLocation fileStartLoc = SM.getLocForStartOfFile( SM.getFileID( range->getBegin())); + if( fileStartLoc.isInvalid()) + return false; + bool isInvalid = false; + const char* fileBuf = SM.getCharacterData( fileStartLoc, &isInvalid ); + if( isInvalid ) + return false; + const char* startBuf = SM.getCharacterData( range->getBegin(), &isInvalid ); + if( isInvalid ) + return false; + SourceLocation locationEnd = range->getEnd(); + if( range->isTokenRange()) + locationEnd = locationAfterToken( locationEnd ); + const char* endBuf = SM.getCharacterData( locationEnd, &isInvalid ); + if( isInvalid ) + return false; + const char* startPos = startBuf; + --startPos; + while( startPos >= fileBuf && ( *startPos == ' ' || *startPos == '\t' )) + --startPos; + if( startPos >= fileBuf && *startPos == '\n' ) + startPos = startBuf - 1; // do not remove indentation whitespace (RemoveLineIfEmpty can do that) + const char* endPos = endBuf; + while( *endPos == ' ' || *endPos == '\t' ) + ++endPos; + if( opts.flags & RemoveWholeStatement ) + { + if( *endPos == ';' ) + ++endPos; + else + return false; + } + *range = CharSourceRange( SourceRange( range->getBegin().getLocWithOffset( startPos - startBuf + 1 ), + locationEnd.getLocWithOffset( endPos - endBuf )), false ); + return true; +} + +bool RewritePlugin::replaceText( SourceLocation Start, unsigned OrigLength, StringRef NewStr ) +{ + assert( rewriter ); + if (wouldRewriteWorkdir(Start)) + return false; + SourceRange Range(Start, Start.getLocWithOffset(std::max(OrigLength, NewStr.size()))); + if( OrigLength != 0 && !handler.checkOverlap( Range ) ) + { + report( DiagnosticsEngine::Warning, "overlapping code replacement, possible plugin error", Start ); + return false; + } + if( rewriter->ReplaceText( Start, OrigLength, NewStr )) + return reportEditFailure( Start ); + handler.addSourceModification(Range); + return true; +} + +bool RewritePlugin::replaceText( SourceRange range, StringRef NewStr ) +{ + assert( rewriter ); + if (wouldRewriteWorkdir(range.getBegin())) + return false; + if( rewriter->getRangeSize( range ) == -1 ) + return reportEditFailure( range.getBegin()); + if( !handler.checkOverlap( range ) ) + { + report( DiagnosticsEngine::Warning, "overlapping code replacement, possible plugin error", range.getBegin()); + return false; + } + if( rewriter->ReplaceText( range, NewStr )) + return reportEditFailure( range.getBegin()); + handler.addSourceModification(range); + return true; +} + +bool RewritePlugin::replaceText( SourceRange range, SourceRange replacementRange ) +{ + assert( rewriter ); + if (wouldRewriteWorkdir(range.getBegin())) + return false; + if( rewriter->getRangeSize( range ) == -1 ) + return reportEditFailure( range.getBegin()); + if( !handler.checkOverlap( range ) ) + { + report( DiagnosticsEngine::Warning, "overlapping code replacement, possible plugin error", range.getBegin()); + return false; + } + if( rewriter->ReplaceText( range, replacementRange )) + return reportEditFailure( range.getBegin()); + handler.addSourceModification(range); + return true; +} + +bool RewritePlugin::wouldRewriteWorkdir(SourceLocation loc) +{ + if (loc.isInvalid() || loc.isMacroID()) { + return false; + } + return + getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(loc)) + .startswith(WORKDIR "/"); +} + +bool RewritePlugin::reportEditFailure( SourceLocation loc ) +{ + report( DiagnosticsEngine::Warning, "cannot perform source modification (macro expansion involved?)", loc ); + return false; +} + +namespace { + +template bool checkPathname( + StringRef pathname, StringRef against, Fn check) +{ + if (check(pathname, against)) { + return true; + } +#if defined _WIN32 + for (std::size_t n = 0;;) + { + std::size_t n1 = pathname.find('\\', n); + std::size_t n2 = against.find('\\', n); + if (n1 <= n2) { + if (n1 >= against.size()) { + return check(pathname.substr(n), against.substr(n)); + } + if ((against[n1] != '/' && against[n1] != '\\') + || pathname.substr(n, n1 - n) != against.substr(n, n1 - n)) + { + break; + } + n = n1 + 1; + } else { + if (n2 >= pathname.size()) { + return check(pathname.substr(n), against.substr(n)); + } + if (pathname[n2] != '/' + || pathname.substr(n, n2 - n) != against.substr(n, n2 - n)) + { + break; + } + n = n2 + 1; + } + } +#endif + return false; +} + +} + +bool hasPathnamePrefix(StringRef pathname, StringRef prefix) +{ + return checkPathname( + pathname, prefix, + [](StringRef p, StringRef a) { return p.startswith(a); }); +} + +bool isSamePathname(StringRef pathname, StringRef other) +{ + return checkPathname( + pathname, other, [](StringRef p, StringRef a) { return p == a; }); +} + +bool isSameUnoIncludePathname(StringRef fullPathname, StringRef includePathname) +{ + llvm::SmallVector buf; + if (isSamePathname(fullPathname, (SRCDIR "/include/" + includePathname).toStringRef(buf))) { + return true; + } + buf.clear(); + return isSamePathname(fullPathname, (SDKDIR "/include/" + includePathname).toStringRef(buf)); +} + +bool hasCLanguageLinkageType(FunctionDecl const * decl) { + assert(decl != nullptr); + if (decl->isExternC()) { + return true; + } + if (decl->isInExternCContext()) { + return true; + } + return false; +} + +static const CXXRecordDecl* stripTypeSugar(QualType qt) +{ + const clang::Type* t = qt.getTypePtr(); + do + { + if (auto elaboratedType = dyn_cast(t)) + t = elaboratedType->desugar().getTypePtr(); + else if (auto tsType = dyn_cast(t)) + t = tsType->desugar().getTypePtr(); + else if (auto sttpType = dyn_cast(t)) + t = sttpType->desugar().getTypePtr(); + else if (auto tdType = dyn_cast(t)) + t = tdType->desugar().getTypePtr(); + else + break; + } while(true); + auto recordType = dyn_cast(t); + if (!recordType) + return nullptr; + return dyn_cast_or_null(recordType->getDecl()); +} + +int derivedFromCount(const CXXRecordDecl* subclassRecordDecl, const CXXRecordDecl* baseclassRecordDecl) +{ + if (!subclassRecordDecl || !baseclassRecordDecl) + return 0; + int derivedCount = 0; + if (subclassRecordDecl == baseclassRecordDecl) + derivedCount++; + if (!subclassRecordDecl->hasDefinition()) + return derivedCount; + for (auto it = subclassRecordDecl->bases_begin(); it != subclassRecordDecl->bases_end(); ++it) + { + derivedCount += derivedFromCount(stripTypeSugar(it->getType()), baseclassRecordDecl); + // short-circuit, we only care about 0,1,2 + if (derivedCount > 1) + return derivedCount; + } + for (auto it = subclassRecordDecl->vbases_begin(); it != subclassRecordDecl->vbases_end(); ++it) + { + derivedCount += derivedFromCount(stripTypeSugar(it->getType()), baseclassRecordDecl); + // short-circuit, we only care about 0,1,2 + if (derivedCount > 1) + return derivedCount; + } + return derivedCount; +} + +int derivedFromCount(QualType subclassQt, QualType baseclassQt) +{ + auto baseclassRecordDecl = stripTypeSugar(baseclassQt); + if (!baseclassRecordDecl) + return 0; + auto subclassRecordDecl = stripTypeSugar(subclassQt); + if (!subclassRecordDecl) + return 0; + + return derivedFromCount(subclassRecordDecl, baseclassRecordDecl); +} + +// It looks like Clang wrongly implements DR 4 +// () and treats +// a variable declared in an 'extern "..." {...}'-style linkage-specification as +// if it contained the 'extern' specifier: +bool hasExternalLinkage(VarDecl const * decl) { + if (decl->getLinkageAndVisibility().getLinkage() != ExternalLinkage) { + return false; + } + for (auto ctx = decl->getLexicalDeclContext(); + ctx->getDeclKind() != Decl::TranslationUnit; + ctx = ctx->getLexicalParent()) + { + if (auto ls = dyn_cast(ctx)) { + if (!ls->hasBraces()) { + return true; + } + if (auto prev = decl->getPreviousDecl()) { + return hasExternalLinkage(prev); + } + return !decl->isInAnonymousNamespace(); + } + } + return true; +} + +bool isSmartPointerType(QualType qt) +{ + // First check whether the object type as written is, or is derived from, std::unique_ptr or + // std::shared_ptr, in case the get member function is declared at a base class of that std + // type: + if (loplugin::isDerivedFrom( + qt->getAsCXXRecordDecl(), + [](Decl const * decl) { + auto const dc = loplugin::DeclCheck(decl); + return dc.ClassOrStruct("unique_ptr").StdNamespace() + || dc.ClassOrStruct("shared_ptr").StdNamespace(); + })) + return true; + + // Then check the object type coerced to the type of the get member function, in + // case the type-as-written is derived from one of these types (tools::SvRef is + // final, but the rest are not): + auto const tc2 = loplugin::TypeCheck(qt); + if (tc2.ClassOrStruct("unique_ptr").StdNamespace() + || tc2.ClassOrStruct("shared_ptr").StdNamespace() + || tc2.Class("Reference").Namespace("uno").Namespace("star") + .Namespace("sun").Namespace("com").GlobalNamespace() + || tc2.Class("Reference").Namespace("rtl").GlobalNamespace() + || tc2.Class("SvRef").Namespace("tools").GlobalNamespace() + || tc2.Class("WeakReference").Namespace("tools").GlobalNamespace() + || tc2.Class("ScopedReadAccess").Namespace("Bitmap").GlobalNamespace() + || tc2.Class("ScopedVclPtrInstance").GlobalNamespace() + || tc2.Class("VclPtr").GlobalNamespace() + || tc2.Class("ScopedVclPtr").GlobalNamespace() + || tc2.Class("intrusive_ptr").Namespace("boost").GlobalNamespace()) + { + return true; + } + return false; +} + +bool isSmartPointerType(const Expr* e) +{ + // First check whether the object type as written is, or is derived from, std::unique_ptr or + // std::shared_ptr, in case the get member function is declared at a base class of that std + // type: + if (loplugin::isDerivedFrom( + e->IgnoreImpCasts()->getType()->getAsCXXRecordDecl(), + [](Decl const * decl) { + auto const dc = loplugin::DeclCheck(decl); + return dc.ClassOrStruct("unique_ptr").StdNamespace() + || dc.ClassOrStruct("shared_ptr").StdNamespace(); + })) + return true; + + // Then check the object type coerced to the type of the get member function, in + // case the type-as-written is derived from one of these types (tools::SvRef is + // final, but the rest are not): + auto const tc2 = loplugin::TypeCheck(e->getType()); + if (tc2.ClassOrStruct("unique_ptr").StdNamespace() + || tc2.ClassOrStruct("shared_ptr").StdNamespace() + || tc2.Class("Reference").Namespace("uno").Namespace("star") + .Namespace("sun").Namespace("com").GlobalNamespace() + || tc2.Class("Reference").Namespace("rtl").GlobalNamespace() + || tc2.Class("SvRef").Namespace("tools").GlobalNamespace() + || tc2.Class("WeakReference").Namespace("tools").GlobalNamespace() + || tc2.Class("ScopedReadAccess").Namespace("Bitmap").GlobalNamespace() + || tc2.Class("ScopedVclPtrInstance").GlobalNamespace() + || tc2.Class("VclPtr").GlobalNamespace() + || tc2.Class("ScopedVclPtr").GlobalNamespace() + || tc2.Class("intrusive_ptr").Namespace("boost").GlobalNamespace()) + { + return true; + } + return false; +} + + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/plugin.hxx b/compilerplugins/clang/plugin.hxx new file mode 100644 index 000000000..cd272dc52 --- /dev/null +++ b/compilerplugins/clang/plugin.hxx @@ -0,0 +1,319 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "pluginhandler.hxx" + +using namespace clang; +using namespace llvm; + +namespace loplugin +{ + +struct InstantiationData +{ + const char* name; + PluginHandler& handler; + CompilerInstance& compiler; + Rewriter* rewriter; +}; + +/** + Base class for plugins. + + If you want to create a non-rewriter action, inherit from this class. Remember to also + use Plugin::Registration. +*/ +class Plugin +{ +public: + explicit Plugin( const InstantiationData& data ); + virtual ~Plugin() {} + // The main function of the plugin. + // Note that for shared plugins, its functionality must be split into preRun() and postRun(), + // see sharedvisitor/generator.cxx . + virtual void run() = 0; + // Should be called from run() before TraverseDecl(). + // If returns false, run() should not do anything. + virtual bool preRun() { return true; } + virtual void postRun() {} + template< typename T > class Registration; + // Returns location right after the end of the token that starts at the given location. + SourceLocation locationAfterToken( SourceLocation location ); + virtual bool setSharedPlugin( Plugin* /*plugin*/, const char* /*name*/ ) { return false; } + enum { isPPCallback = false }; + enum { isSharedPlugin = false }; +protected: + DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc = SourceLocation()) const; + // Look at the line containing location and the previous line for any comments that overlap + // either of those two lines and that contain "[-loplugin:]" (with the name of this + // plugin), indicating that warnings from this plugin should be suppressed here: + bool suppressWarningAt(SourceLocation location) const; + bool ignoreLocation( SourceLocation loc ) const + { return handler.ignoreLocation(loc); } + bool ignoreLocation( const Decl* decl ) const; + bool ignoreLocation( const Stmt* stmt ) const; + bool ignoreLocation(TypeLoc tloc) const; + CompilerInstance& compiler; + PluginHandler& handler; + /** + Returns the parent of the given AST node. Clang's internal AST representation doesn't provide this information, + it can only provide children, but getting the parent is often useful for inspecting a part of the AST. + */ + const Stmt* getParentStmt( const Stmt* stmt ); + Stmt* getParentStmt( Stmt* stmt ); + const FunctionDecl* getParentFunctionDecl( const Stmt* stmt ); + + /** + Get filename of the given location. Use this instead of SourceManager::getFilename(), as that one + does not handle source with expanded #inline directives (used by Icecream for remote compilation). + */ + StringRef getFilenameOfLocation(SourceLocation spellingLocation) const; + /** + Checks if the location is inside a UNO file, more specifically, if it forms part of the URE stable interface, + which is not allowed to be changed. + */ + bool isInUnoIncludeFile(SourceLocation spellingLocation) const; + bool isInUnoIncludeFile(const FunctionDecl*) const; + + bool isDebugMode() const { return handler.isDebugMode(); } + + static bool isUnitTestMode(); + + bool containsPreprocessingConditionalInclusion(SourceRange range); + + enum class IdenticalDefaultArgumentsResult { No, Yes, Maybe }; + IdenticalDefaultArgumentsResult checkIdenticalDefaultArguments( + Expr const * argument1, Expr const * argument2); + +private: + static void registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName, + bool isPPCallback, bool isSharedPlugin, bool byDefault ); + template< typename T > static Plugin* createHelper( const InstantiationData& data ); + bool evaluate(const Expr* expr, APSInt& x); + + enum { isRewriter = false }; + const char* name; +}; + +template +class FilteringPlugin : public RecursiveASTVisitor, public Plugin +{ +public: + explicit FilteringPlugin( const InstantiationData& data ) : Plugin(data) {} + + bool TraverseNamespaceDecl(NamespaceDecl * decl) { + if (ignoreLocation(decl->getBeginLoc())) + return true; + return RecursiveASTVisitor::TraverseNamespaceDecl(decl); + } +}; + +/** + Base class for rewriter plugins. + + Remember to also use Plugin::Registration. +*/ +class RewritePlugin + : public Plugin +{ +public: + explicit RewritePlugin( const InstantiationData& data ); +protected: + enum RewriteOption + { + // This enum allows passing just 'RemoveLineIfEmpty' to functions below. + // If the resulting line would be completely empty, it'll be removed. + RemoveLineIfEmpty = 1 << 0, + // Use this to remove the declaration/statement as a whole, i.e. all whitespace before the statement + // and the trailing semicolon (is not part of the AST element range itself). + // The trailing semicolon must be present. + RemoveWholeStatement = 1 << 1, + // Removes also all whitespace preceding and following the expression (completely, so that + // the preceding and following tokens would be right next to each other, follow with insertText( " " ) + // if this is not wanted). Despite the name, indentation whitespace is not removed. + RemoveAllWhitespace = 1 << 2 + }; + struct RewriteOptions + : public Rewriter::RewriteOptions + { + RewriteOptions() : flags( 0 ) {} + explicit RewriteOptions( RewriteOption option ); + const int flags; + }; + // syntactic sugar to be able to write 'RemoveLineIfEmpty | RemoveWholeStatement' + friend RewriteOption operator|( RewriteOption option1, RewriteOption option2 ); + // These following insert/remove/replaceText functions map to functions + // in clang::Rewriter, with these differences: + // - they (more intuitively) return false on failure rather than true + // - they report a warning when the change cannot be done + // - There are more options for easier removal of surroundings of a statement/expression. + bool insertText( SourceLocation Loc, StringRef Str, + bool InsertAfter = true, bool indentNewLines = false ); + bool insertTextAfter( SourceLocation Loc, StringRef Str ); + bool insertTextAfterToken( SourceLocation Loc, StringRef Str ); + bool insertTextBefore( SourceLocation Loc, StringRef Str ); + bool removeText( SourceLocation Start, unsigned Length, RewriteOptions opts = RewriteOptions()); + bool removeText( CharSourceRange range, RewriteOptions opts = RewriteOptions()); + bool removeText( SourceRange range, RewriteOptions opts = RewriteOptions()); + bool replaceText( SourceLocation Start, unsigned OrigLength, StringRef NewStr ); + bool replaceText( SourceRange range, StringRef NewStr ); + bool replaceText( SourceRange range, SourceRange replacementRange ); + Rewriter* rewriter; +private: + template< typename T > friend class Plugin::Registration; + enum { isRewriter = true }; + bool wouldRewriteWorkdir(SourceLocation loc); + bool reportEditFailure( SourceLocation loc ); + bool adjustRangeForOptions( CharSourceRange* range, RewriteOptions options ); +}; + +/** + Plugin registration helper. + + If you create a new helper class, create also an instance of this class to automatically register it. + The passed argument is name of the plugin, used for explicitly invoking rewriter plugins + (it is ignored for non-rewriter plugins). + + @code + static Plugin::Registration< NameOfClass > X( "nameofclass" ); + @endcode +*/ +template< typename T > +class Plugin::Registration +{ +public: + Registration( const char* optionName, bool byDefault = !T::isRewriter ); +}; + +class RegistrationCreate +{ +public: + template< typename T, bool > static T* create( const InstantiationData& data ); +}; + +inline +bool Plugin::ignoreLocation( const Decl* decl ) const +{ + return ignoreLocation( decl->getLocation()); +} + +inline +bool Plugin::ignoreLocation( const Stmt* stmt ) const +{ + // Invalid location can happen at least for ImplicitCastExpr of + // ImplicitParam 'self' in Objective C method declarations: + return stmt->getBeginLoc().isValid() && ignoreLocation( stmt->getBeginLoc()); +} + +inline bool Plugin::ignoreLocation(TypeLoc tloc) const +{ + return ignoreLocation(tloc.getBeginLoc()); +} + +template< typename T > +Plugin* Plugin::createHelper( const InstantiationData& data ) + { + return new T( data ); +} + +template< typename T > +inline +Plugin::Registration< T >::Registration( const char* optionName, bool byDefault ) +{ + registerPlugin( &T::template createHelper< T >, optionName, T::isPPCallback, T::isSharedPlugin, byDefault ); +} + +inline +RewritePlugin::RewriteOptions::RewriteOptions( RewriteOption option ) + : flags( option ) +{ + // Note that 'flags' stores also RemoveLineIfEmpty, it must be kept in sync with the base class. + if( flags & RewritePlugin::RemoveLineIfEmpty ) + RemoveLineIfEmpty = true; +} + +inline +RewritePlugin::RewriteOption operator|( RewritePlugin::RewriteOption option1, RewritePlugin::RewriteOption option2 ) +{ + return static_cast< RewritePlugin::RewriteOption >( int( option1 ) | int( option2 )); +} + +template +class FilteringRewritePlugin : public RecursiveASTVisitor, public RewritePlugin +{ +public: + explicit FilteringRewritePlugin( const InstantiationData& data ) : RewritePlugin(data) {} + + bool TraverseNamespaceDecl(NamespaceDecl * decl) { + if (ignoreLocation(decl->getBeginLoc())) + return true; + return RecursiveASTVisitor::TraverseNamespaceDecl(decl); + } +}; + +void normalizeDotDotInFilePath(std::string&); + +// Same as pathname.startswith(prefix), except on Windows, where pathname and +// prefix may also contain backslashes: +bool hasPathnamePrefix(StringRef pathname, StringRef prefix); + +// Same as pathname == other, except on Windows, where pathname and other may +// also contain backslashes: +bool isSamePathname(StringRef pathname, StringRef other); + +// Check whether fullPathname is either SRCDIR/include/includePathname or +// SDKDIR/include/includePathname: +bool isSameUnoIncludePathname(StringRef fullPathname, StringRef includePathname); + +// It appears that, given a function declaration, there is no way to determine +// the language linkage of the function's type, only of the function's name +// (via FunctionDecl::isExternC); however, in a case like +// +// extern "C" { static void f(); } +// +// the function's name does not have C language linkage while the function's +// type does (as clarified in C++11 [decl.link]); cf. +// "Language linkage of function type": +bool hasCLanguageLinkageType(FunctionDecl const * decl); + +// Count the number of times the base class is present in the subclass hierarchy +// +int derivedFromCount(clang::QualType subclassType, clang::QualType baseclassType); +int derivedFromCount(const CXXRecordDecl* subtypeRecord, const CXXRecordDecl* baseRecord); + +// It looks like Clang wrongly implements DR 4 +// () and treats +// a variable declared in an 'extern "..." {...}'-style linkage-specification as +// if it contained the 'extern' specifier: +bool hasExternalLinkage(VarDecl const * decl); + +bool isSmartPointerType(const Expr*); +bool isSmartPointerType(clang::QualType); + +const Decl* getFunctionDeclContext(ASTContext& context, const Stmt* stmt); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/pluginhandler.cxx b/compilerplugins/clang/pluginhandler.cxx new file mode 100644 index 000000000..2856d5a0e --- /dev/null +++ b/compilerplugins/clang/pluginhandler.cxx @@ -0,0 +1,532 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include +#include +#include + +#include "config_clang.h" + +#include "plugin.hxx" +#include "pluginhandler.hxx" + +#include +#include +#include +#include +#include + +#if defined _WIN32 +#include +#else +#include +#include +#endif + +/** +This source file manages all plugin actions. It is not necessary to modify this +file when adding new actions. +*/ + +static bool isPrefix( const std::string& prefix, const std::string& full) +{ + return full.compare(0, prefix.size(), prefix) == 0; +} + +namespace loplugin +{ + +struct PluginData +{ + Plugin* (*create)( const InstantiationData& ); + Plugin* object; + const char* optionName; + bool isPPCallback; + bool isSharedPlugin; + bool byDefault; + bool disabledRun; +}; + +const int MAX_PLUGINS = 200; +static PluginData plugins[ MAX_PLUGINS ]; +static int pluginCount = 0; +static bool bPluginObjectsCreated = false; +static bool unitTestMode = false; + +StringRef initMainFileName(CompilerInstance& compiler) +{ + StringRef const& fn(compiler.getASTContext().getSourceManager().getFileEntryForID( + compiler.getASTContext().getSourceManager().getMainFileID())->getName()); + if (fn == "") + // stdin means icecream, so we can rely on -main-file-name containing the full path name + return compiler.getCodeGenOpts().MainFileName; + else + // this is always a full path name + return fn; +} + +PluginHandler::PluginHandler( CompilerInstance& compiler, const std::vector< std::string >& args ) + : compiler( compiler ) + , mainFileName(initMainFileName(compiler)) + , rewriter( compiler.getSourceManager(), compiler.getLangOpts()) + , scope( "mainfile" ) + , warningsAsErrors( false ) +{ + std::set< std::string > rewriters; + for( std::string const & arg : args ) + { + if( arg.size() >= 2 && arg[ 0 ] == '-' && arg[ 1 ] == '-' ) + handleOption( arg.substr( 2 )); + else + rewriters.insert( arg ); + } + createPlugins( rewriters ); + bPluginObjectsCreated = true; +} + +PluginHandler::~PluginHandler() +{ + for( int i = 0; i < pluginCount; ++i ) + if( plugins[ i ].object != NULL ) + { + // PPCallbacks is owned by preprocessor object, don't delete those + if( !plugins[ i ].isPPCallback ) + delete plugins[ i ].object; + } +} + +bool PluginHandler::isUnitTestMode() +{ + return unitTestMode; +} + +void PluginHandler::handleOption( const std::string& option ) +{ + if( option.substr( 0, 6 ) == "scope=" ) + { + scope = option.substr( 6 ); + if( scope == "mainfile" || scope == "all" ) + ; // ok + else + { +#if !defined _WIN32 //TODO, S_ISDIR + struct stat st; + if( stat(( SRCDIR "/" + scope ).c_str(), &st ) != 0 || !S_ISDIR( st.st_mode )) + report( DiagnosticsEngine::Fatal, "unknown scope %0 (no such module directory)" ) << scope; +#endif + } + } + else if( option.substr( 0, 14 ) == "warnings-only=" ) + { + warningsOnly = option.substr(14); + } + else if( option == "warnings-as-errors" ) + warningsAsErrors = true; + else if( option == "unit-test-mode" ) + unitTestMode = true; + else if (option == "debug") + debugMode = true; + else + report( DiagnosticsEngine::Fatal, "unknown option %0" ) << option; +} + +void PluginHandler::createPlugins( std::set< std::string > rewriters ) +{ + for( int i = 0; i < pluginCount; ++i ) + { + const char* name = plugins[i].optionName; + // When in unit-test mode, ignore plugins whose names don't match the filename of the test, + // so that we only generate warnings for the plugin that we want to test. + // Sharedvisitor plugins still need to remain enabled, they don't do anything on their own, + // but sharing-capable plugins need them to actually work (if compiled so) and they register + // with them in the code below. + if (unitTestMode && mainFileName.find(plugins[ i ].optionName) == StringRef::npos + && !plugins[ i ].isSharedPlugin) + continue; + if( rewriters.erase( name ) != 0 ) + plugins[ i ].object = plugins[ i ].create( InstantiationData { name, *this, compiler, &rewriter } ); + else if( plugins[ i ].byDefault ) + plugins[ i ].object = plugins[ i ].create( InstantiationData { name, *this, compiler, NULL } ); + else if( unitTestMode && strcmp(name, "unusedmethodsremove") != 0 && strcmp(name, "unusedfieldsremove") != 0) + plugins[ i ].object = plugins[ i ].create( InstantiationData { name, *this, compiler, NULL } ); + } + for( auto r: rewriters ) + report( DiagnosticsEngine::Fatal, "unknown plugin tool %0" ) << r; + // If there is a shared plugin, make it handle all plugins that it can handle. + for( int i = 0; i < pluginCount; ++i ) + { + if( plugins[ i ].isSharedPlugin && plugins[ i ].object != nullptr ) + { + Plugin* plugin = plugins[ i ].object; + for( int j = 0; j < pluginCount; ++j ) + { + if( plugins[ j ].object != nullptr + && plugin->setSharedPlugin( plugins[ j ].object, plugins[ j ].optionName )) + { + plugins[ j ].disabledRun = true; + } + } + } + } +} + +void PluginHandler::registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName, + bool isPPCallback, bool isSharedPlugin, bool byDefault ) +{ + assert( !bPluginObjectsCreated ); + assert( pluginCount < MAX_PLUGINS ); + plugins[ pluginCount ].create = create; + plugins[ pluginCount ].object = NULL; + plugins[ pluginCount ].optionName = optionName; + plugins[ pluginCount ].isPPCallback = isPPCallback; + plugins[ pluginCount ].isSharedPlugin = isSharedPlugin; + plugins[ pluginCount ].byDefault = byDefault; + plugins[ pluginCount ].disabledRun = false; + ++pluginCount; +} + +DiagnosticBuilder PluginHandler::report( DiagnosticsEngine::Level level, const char* plugin, StringRef message, CompilerInstance& compiler, + SourceLocation loc ) +{ + DiagnosticsEngine& diag = compiler.getDiagnostics(); + // Do some mappings (e.g. for -Werror) that clang does not do for custom messages for some reason. + if( level == DiagnosticsEngine::Warning && ((diag.getWarningsAsErrors() && (plugin == nullptr || plugin != warningsOnly)) || warningsAsErrors)) + level = DiagnosticsEngine::Error; + if( level == DiagnosticsEngine::Error && diag.getErrorsAsFatal()) + level = DiagnosticsEngine::Fatal; + std::string fullMessage = ( message + " [loplugin" ).str(); + if( plugin ) + { + fullMessage += ":"; + fullMessage += plugin; + } + fullMessage += "]"; + if( loc.isValid()) + return diag.Report( loc, diag.getDiagnosticIDs()->getCustomDiagID(static_cast(level), fullMessage) ); + else + return diag.Report( diag.getDiagnosticIDs()->getCustomDiagID(static_cast(level), fullMessage) ); +} + +DiagnosticBuilder PluginHandler::report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc ) +{ + return report( level, nullptr, message, compiler, loc ); +} + +bool PluginHandler::ignoreLocation(SourceLocation loc) { + auto i = ignored_.find(loc); + if (i == ignored_.end()) { + i = ignored_.emplace(loc, checkIgnoreLocation(loc)).first; + } + return i->second; +} + +bool PluginHandler::checkIgnoreLocation(SourceLocation loc) +{ + // If a location comes from a PCH, it is not necessary to check it + // in every compilation using the PCH, since with Clang we use + // -building-pch-with-obj to build a separate precompiled_foo.cxx file + // for the PCH, and so it is known that everything in the PCH will + // be checked while compiling this file. Skip the checks for all + // other files using the PCH. + if( !compiler.getSourceManager().isLocalSourceLocation( loc )) + { + if( !compiler.getLangOpts().BuildingPCHWithObjectFile ) + return true; + } + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( loc ); + if( compiler.getSourceManager().isInSystemHeader( expansionLoc )) + return true; + PresumedLoc presumedLoc = compiler.getSourceManager().getPresumedLoc( expansionLoc ); + if( presumedLoc.isInvalid()) + return true; + const char* bufferName = presumedLoc.getFilename(); + if (bufferName == NULL + || hasPathnamePrefix(bufferName, SRCDIR "/external/") + || isSamePathname(bufferName, SRCDIR "/sdext/source/pdfimport/wrapper/keyword_list") ) + // workdir/CustomTarget/sdext/pdfimport/hash.cxx is generated from + // sdext/source/pdfimport/wrapper/keyword_list by gperf, which + // inserts various #line directives denoting the latter into the + // former, but fails to add a #line directive returning back to + // hash.cxx itself before the gperf generated boilerplate, so + // compilers erroneously consider errors in the boilerplate to come + // from keyword_list instead of hash.cxx (for Clang on Linux/macOS + // this is not an issue due to the '#pragma GCC system_header' + // generated into the start of hash.cxx, #if'ed for __GNUC__, but + // for clang-cl it is an issue) + return true; + if( hasPathnamePrefix(bufferName, WORKDIR "/") ) + { + // workdir/CustomTarget/vcl/unx/kde4/tst_exclude_socket_notifiers.moc + // includes + // "../../../../../vcl/unx/kde4/tst_exclude_socket_notifiers.hxx", + // making the latter file erroneously match here; so strip any ".." + // segments: + if (strstr(bufferName, "/..") == nullptr) { + return true; + } + std::string s(bufferName); + normalizeDotDotInFilePath(s); + if (hasPathnamePrefix(s, WORKDIR "/")) + return true; + } + if( hasPathnamePrefix(bufferName, BUILDDIR "/") + || hasPathnamePrefix(bufferName, SRCDIR "/") ) + return false; // ok + return true; +} + +// If we overlap with a previous area we modified, we cannot perform this change +// without corrupting the source +bool PluginHandler::checkOverlap(SourceRange range) +{ + SourceManager& SM = compiler.getSourceManager(); + char const *p1 = SM.getCharacterData( range.getBegin() ); + char const *p2 = SM.getCharacterData( range.getEnd() ); + for (std::pair const & rPair : mvModifiedRanges) + { + if (rPair.first <= p1 && p1 <= rPair.second) + return false; + if (p1 <= rPair.second && rPair.first <= p2) + return false; + } + return true; +} + +void PluginHandler::addSourceModification(SourceRange range) +{ + SourceManager& SM = compiler.getSourceManager(); + char const *p1 = SM.getCharacterData( range.getBegin() ); + char const *p2 = SM.getCharacterData( range.getEnd() ); + mvModifiedRanges.emplace_back(p1, p2); +} + +void PluginHandler::HandleTranslationUnit( ASTContext& context ) +{ + llvm::TimeTraceScope mainTimeScope("LOPluginMain", StringRef("")); + if( context.getDiagnostics().hasErrorOccurred()) + return; + if (mainFileName.endswith(".ii")) + { + report(DiagnosticsEngine::Fatal, + "input file has suffix .ii: \"%0\"\nhighly suspicious, probably ccache generated, this will break warning suppressions; export CCACHE_CPP2=1 to prevent this") << mainFileName; + return; + } + + for( int i = 0; i < pluginCount; ++i ) + { + if( plugins[ i ].object != NULL && !plugins[ i ].disabledRun ) + { + llvm::TimeTraceScope timeScope("LOPlugin", [&]() { return plugins[i].optionName; }); + plugins[ i ].object->run(); + } + } +#if defined _WIN32 + //TODO: make the call to 'rename' work on Windows (where the renamed-to + // original file is probably still held open somehow): + rewriter.overwriteChangedFiles(); +#else + for( Rewriter::buffer_iterator it = rewriter.buffer_begin(); + it != rewriter.buffer_end(); + ++it ) + { + const FileEntry* e = context.getSourceManager().getFileEntryForID( it->first ); + if( e == NULL ) + continue; // Failed modification because of a macro expansion? + /* Check where the file actually is, and warn about cases where modification + most probably doesn't matter (generated files in workdir). + The order here is important, as INSTDIR and WORKDIR are often in SRCDIR/BUILDDIR, + and BUILDDIR is sometimes in SRCDIR. */ + std::string modifyFile; + const char* pathWarning = NULL; + bool bSkip = false; + StringRef const name = e->getName(); + if( name.startswith(WORKDIR "/") ) + pathWarning = "modified source in workdir/ : %0"; + else if( strcmp( SRCDIR, BUILDDIR ) != 0 && name.startswith(BUILDDIR "/") ) + pathWarning = "modified source in build dir : %0"; + else if( name.startswith(SRCDIR "/") ) + ; // ok + else + { + pathWarning = "modified source in unknown location, not modifying : %0"; + bSkip = true; + } + if( modifyFile.empty()) + modifyFile = name.str(); + // Check whether the modified file is in the wanted scope + if( scope == "mainfile" ) + { + if( it->first != context.getSourceManager().getMainFileID()) + continue; + } + else if( scope == "all" ) + ; // ok + else // scope is module + { + if( !( isPrefix( SRCDIR "/" + scope + "/", modifyFile ) || isPrefix( SRCDIR "/include/" + scope + "/", modifyFile ) ) ) + continue; + } + // Warn only now, so that files not in scope do not cause warnings. + if( pathWarning != NULL ) + report( DiagnosticsEngine::Warning, pathWarning ) << name; + if( bSkip ) + continue; + char* filename = new char[ modifyFile.length() + 100 ]; + sprintf( filename, "%s.new.%d", modifyFile.c_str(), getpid()); + std::string error; + bool bOk = false; + std::error_code ec; + std::unique_ptr ostream( + new raw_fd_ostream(filename, ec, sys::fs::OF_None)); + if( !ec) + { + it->second.write( *ostream ); + ostream->close(); + if( !ostream->has_error() && rename( filename, modifyFile.c_str()) == 0 ) + bOk = true; + } + else + error = "error: " + ec.message(); + ostream->clear_error(); + unlink( filename ); + if( !bOk ) + report( DiagnosticsEngine::Error, "cannot write modified source to %0 (%1)" ) << modifyFile << error; + delete[] filename; + } +#endif + } + +namespace { + +// BEGIN code copied from LLVM's clang/lib/Sema/Sema.cpp + +/// Returns true, if all methods and nested classes of the given +/// CXXRecordDecl are defined in this translation unit. +/// +/// Should only be called from ActOnEndOfTranslationUnit so that all +/// definitions are actually read. +static bool MethodsAndNestedClassesComplete(const CXXRecordDecl *RD, + RecordCompleteMap &MNCComplete) { + RecordCompleteMap::iterator Cache = MNCComplete.find(RD); + if (Cache != MNCComplete.end()) + return Cache->second; + if (!RD->isCompleteDefinition()) + return false; + bool Complete = true; + for (DeclContext::decl_iterator I = RD->decls_begin(), + E = RD->decls_end(); + I != E && Complete; ++I) { + if (const CXXMethodDecl *M = dyn_cast(*I)) + Complete = M->isDefined() || M->isDefaulted() || + (M->isPure() && !isa(M)); + else if (const FunctionTemplateDecl *F = dyn_cast(*I)) + // If the template function is marked as late template parsed at this + // point, it has not been instantiated and therefore we have not + // performed semantic analysis on it yet, so we cannot know if the type + // can be considered complete. + Complete = !F->getTemplatedDecl()->isLateTemplateParsed() && + F->getTemplatedDecl()->isDefined(); + else if (const CXXRecordDecl *R = dyn_cast(*I)) { + if (R->isInjectedClassName()) + continue; + if (R->hasDefinition()) + Complete = MethodsAndNestedClassesComplete(R->getDefinition(), + MNCComplete); + else + Complete = false; + } + } + MNCComplete[RD] = Complete; + return Complete; +} + +/// Returns true, if the given CXXRecordDecl is fully defined in this +/// translation unit, i.e. all methods are defined or pure virtual and all +/// friends, friend functions and nested classes are fully defined in this +/// translation unit. +/// +/// Should only be called from ActOnEndOfTranslationUnit so that all +/// definitions are actually read. +static bool IsRecordFullyDefined(const CXXRecordDecl *RD, + RecordCompleteMap &RecordsComplete, + RecordCompleteMap &MNCComplete) { + RecordCompleteMap::iterator Cache = RecordsComplete.find(RD); + if (Cache != RecordsComplete.end()) + return Cache->second; + bool Complete = MethodsAndNestedClassesComplete(RD, MNCComplete); + for (CXXRecordDecl::friend_iterator I = RD->friend_begin(), + E = RD->friend_end(); + I != E && Complete; ++I) { + // Check if friend classes and methods are complete. + if (TypeSourceInfo *TSI = (*I)->getFriendType()) { + // Friend classes are available as the TypeSourceInfo of the FriendDecl. + if (CXXRecordDecl *FriendD = TSI->getType()->getAsCXXRecordDecl()) + Complete = MethodsAndNestedClassesComplete(FriendD, MNCComplete); + else + Complete = false; + } else { + // Friend functions are available through the NamedDecl of FriendDecl. + if (const FunctionDecl *FD = + dyn_cast((*I)->getFriendDecl())) + Complete = FD->isDefined(); + else + // This is a template friend, give up. + Complete = false; + } + } + RecordsComplete[RD] = Complete; + return Complete; +} + +// END code copied from LLVM's clang/lib/Sema/Sema.cpp + +} + +bool PluginHandler::isAllRelevantCodeDefined(NamedDecl const * decl) { + switch (decl->getAccess()) { + case AS_protected: + if (!cast(decl->getDeclContext())->hasAttr()) { + break; + } + LLVM_FALLTHROUGH; + case AS_private: + if (IsRecordFullyDefined( + cast(decl->getDeclContext()), RecordsComplete_, MNCComplete_)) + { + return true; + } + break; + default: + break; + } + return !decl->isExternallyVisible(); +} + +std::unique_ptr LibreOfficeAction::CreateASTConsumer( CompilerInstance& Compiler, StringRef ) +{ +#if __cplusplus >= 201402L + return std::make_unique( Compiler, _args ); +#else + return llvm::make_unique( Compiler, _args ); +#endif +} + +bool LibreOfficeAction::ParseArgs( const CompilerInstance&, const std::vector< std::string >& args ) +{ + _args = args; + return true; +} + +static FrontendPluginRegistry::Add< loplugin::LibreOfficeAction > X( "loplugin", "LibreOffice compile check plugin" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/pluginhandler.hxx b/compilerplugins/clang/pluginhandler.hxx new file mode 100644 index 000000000..f7a399672 --- /dev/null +++ b/compilerplugins/clang/pluginhandler.hxx @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace clang; + +namespace std { + +template<> struct hash<::clang::SourceLocation> { + size_t operator ()(::clang::SourceLocation loc) const + { return loc.getRawEncoding(); } +}; + +} + +namespace loplugin +{ + +class Plugin; +struct InstantiationData; + +// Used internally by PluginHandler::isAllRelevantCodeDefined and its (free) helper functions: +typedef llvm::DenseMap RecordCompleteMap; + +/** + Class that manages all LO modules. +*/ +class PluginHandler + : public ASTConsumer +{ +public: + PluginHandler( CompilerInstance& compiler, const std::vector< std::string >& args ); + virtual ~PluginHandler(); + virtual void HandleTranslationUnit( ASTContext& context ) override; + static void registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName, + bool isPPCallback, bool isSharedPlugin, bool byDefault ); + DiagnosticBuilder report( DiagnosticsEngine::Level level, const char * plugin, StringRef message, + CompilerInstance& compiler, SourceLocation loc = SourceLocation()); + bool ignoreLocation(SourceLocation loc); + bool isDebugMode() const { return debugMode; } + static bool isUnitTestMode(); + // If we overlap with a previous area we modified, we cannot perform this change + // without corrupting the source + bool checkOverlap(SourceRange range); + void addSourceModification(SourceRange range); + StringRef const& getMainFileName() const { return mainFileName; } + + // Is all code that could see `decl` defined in this TU? + bool isAllRelevantCodeDefined(NamedDecl const * decl); + +private: + void handleOption( const std::string& option ); + void createPlugins( std::set< std::string > rewriters ); + DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc = SourceLocation()); + bool checkIgnoreLocation(SourceLocation loc); + CompilerInstance& compiler; + StringRef const mainFileName; + std::unordered_map ignored_; + Rewriter rewriter; + std::string scope; + std::string warningsOnly; + bool warningsAsErrors; + bool debugMode = false; + std::vector> mvModifiedRanges; + + // Used internally by isAllRelevantCodeDefined: + RecordCompleteMap RecordsComplete_; + RecordCompleteMap MNCComplete_; +}; + +/** + The Clang plugin class, just forwards to PluginHandler. +*/ +class LibreOfficeAction + : public PluginASTAction +{ +public: + virtual std::unique_ptr CreateASTConsumer( CompilerInstance& Compiler, StringRef InFile ); + + virtual bool ParseArgs( const CompilerInstance& CI, const std::vector< std::string >& args ); +private: + std::vector< std::string > _args; +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/pointerbool.cxx b/compilerplugins/clang/pointerbool.cxx new file mode 100644 index 000000000..3bc87e743 --- /dev/null +++ b/compilerplugins/clang/pointerbool.cxx @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include +#include "plugin.hxx" +#include "check.hxx" +#include "compat.hxx" + +/** + Look for calls where the param is bool but the call-site-arg is pointer. +*/ +#ifndef LO_CLANG_SHARED_PLUGINS + +namespace +{ +class PointerBool : public loplugin::FilteringPlugin +{ +public: + explicit PointerBool(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool shouldVisitTemplateInstantiations() const { return true; } + + bool PreTraverseFunctionDecl(FunctionDecl* decl); + bool PostTraverseFunctionDecl(FunctionDecl* decl, bool); + bool TraverseFunctionDecl(FunctionDecl* decl); + bool VisitCallExpr(CallExpr const*); + +private: + llvm::Optional getCallValue(const Expr* arg); + std::vector functions_; +}; + +bool PointerBool::PreTraverseFunctionDecl(FunctionDecl* decl) +{ + functions_.push_back(decl); + return true; +} + +bool PointerBool::PostTraverseFunctionDecl(FunctionDecl*, bool) +{ + assert(!functions_.empty()); + functions_.pop_back(); + return true; +} + +bool PointerBool::TraverseFunctionDecl(FunctionDecl* decl) +{ + bool ret = true; + if (PreTraverseFunctionDecl(decl)) + { + ret = FilteringPlugin::TraverseFunctionDecl(decl); + PostTraverseFunctionDecl(decl, ret); + } + return ret; +} + +bool PointerBool::VisitCallExpr(CallExpr const* callExpr) +{ + if (ignoreLocation(callExpr)) + return true; + // TODO this doesn't currently work, the args and the params don't seem to line up + if (isa(callExpr)) + return true; + const FunctionDecl* functionDecl; + if (isa(callExpr)) + { + functionDecl = dyn_cast(callExpr)->getMethodDecl(); + } + else + { + functionDecl = callExpr->getDirectCallee(); + } + if (!functionDecl) + return true; + + unsigned len = std::min(callExpr->getNumArgs(), functionDecl->getNumParams()); + for (unsigned i = 0; i < len; ++i) + { + auto param = functionDecl->getParamDecl(i); + auto paramTC = loplugin::TypeCheck(param->getType()); + if (!paramTC.AnyBoolean()) + continue; + auto arg = callExpr->getArg(i)->IgnoreImpCasts(); + auto argTC = loplugin::TypeCheck(arg->getType()); + if (argTC.AnyBoolean()) + continue; + // sal_Bool is sometimes disguised + if (isa(arg->getType())) + if (arg->getType()->getUnqualifiedDesugaredType()->isSpecificBuiltinType( + clang::BuiltinType::UChar)) + continue; + if (arg->getType()->isDependentType()) + continue; + if (arg->getType()->isIntegerType()) + { + auto ret = getCallValue(arg); + if (ret.hasValue() && (ret.getValue() == 1 || ret.getValue() == 0)) + continue; + // something like: priv->m_nLOKFeatures & LOK_FEATURE_DOCUMENT_PASSWORD + if (isa(arg->IgnoreParenImpCasts())) + continue; + // something like: pbEmbolden ? FcTrue : FcFalse + if (isa(arg->IgnoreParenImpCasts())) + continue; + } + report(DiagnosticsEngine::Warning, + "possibly unwanted implicit conversion when calling bool param", arg->getExprLoc()) + << arg->getSourceRange(); + report(DiagnosticsEngine::Note, "method here", param->getLocation()) + << param->getSourceRange(); + if (!functions_.empty()) + { + auto callerFD = functions_.back(); + if (callerFD->isTemplateInstantiation()) + report(DiagnosticsEngine::Note, "instantiated from here", + callerFD->getPointOfInstantiation()); + } + } + return true; +} + +llvm::Optional PointerBool::getCallValue(const Expr* arg) +{ + arg = arg->IgnoreParenCasts(); + if (auto defArg = dyn_cast(arg)) + { + arg = defArg->getExpr()->IgnoreParenCasts(); + } + // ignore this, it seems to trigger an infinite recursion + if (isa(arg)) + { + return llvm::Optional(); + } + APSInt x1; + if (compat::EvaluateAsInt(arg, x1, compiler.getASTContext())) + { + return x1; + } + return llvm::Optional(); +} + +loplugin::Plugin::Registration pointerbool("pointerbool"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/precompiled_clang.hxx b/compilerplugins/clang/precompiled_clang.hxx new file mode 100644 index 000000000..926580353 --- /dev/null +++ b/compilerplugins/clang/precompiled_clang.hxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +// This file is generated manually. Is it based on the output of +// cat *.cxx *.hxx | grep '#include' | grep 'clang/' | sort -u + +#if PCH_LEVEL >= 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if PCH_LEVEL >= 2 +// These are included by everything anyway. +#include "plugin.hxx" +#include "check.hxx" +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/privatebase.cxx b/compilerplugins/clang/privatebase.cxx new file mode 100644 index 000000000..210ce6376 --- /dev/null +++ b/compilerplugins/clang/privatebase.cxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" + +namespace { + +class PrivateBase: + public loplugin::FilteringPlugin +{ +public: + explicit PrivateBase(loplugin::InstantiationData const & data): FilteringPlugin(data) + {} + + void run() override; + + bool VisitCXXRecordDecl(CXXRecordDecl const * decl); +}; + +void PrivateBase::run() { + if (compiler.getLangOpts().CPlusPlus) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } +} + +bool PrivateBase::VisitCXXRecordDecl(CXXRecordDecl const * decl) { + if (ignoreLocation(decl) || !decl->isThisDeclarationADefinition() + || decl->getTagKind() != TTK_Class) + { + return true; + } + for (auto i = decl->bases_begin(); i != decl->bases_end(); ++i) { + if (i->getAccessSpecifierAsWritten() == AS_none) { + report( + DiagnosticsEngine::Warning, + "base class is private by default; explicitly give an access" + " specifier", + i->getBeginLoc()) + << i->getSourceRange(); + } + } + return true; +} + +loplugin::Plugin::Registration privatebase("privatebase"); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/ptrvector.cxx b/compilerplugins/clang/ptrvector.cxx new file mode 100644 index 000000000..758e3e90f --- /dev/null +++ b/compilerplugins/clang/ptrvector.cxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include +#include + +#include "check.hxx" +#include "plugin.hxx" + +/** + Check for calls to operator== on a std::container< std::unique_ptr >, which is not useful, + because std::container will compare the pointers so it is never true +*/ + +namespace { + +class PtrVector: + public loplugin::FilteringPlugin +{ +public: + explicit PtrVector(loplugin::InstantiationData const & data): FilteringPlugin(data) + {} + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool shouldVisitTemplateInstantiations () const { return true; } + + bool VisitCXXOperatorCallExpr(const CXXOperatorCallExpr* ); +}; + +bool PtrVector::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr* expr) +{ + if (ignoreLocation(expr)) { + return true; + } + if (expr->getOperator() != clang::OverloadedOperatorKind::OO_EqualEqual + && expr->getOperator() != clang::OverloadedOperatorKind::OO_ExclaimEqual) + { + return true; + } + if (isa(expr->getArg(1))) { + return true; + } + const Expr* argExpr = expr->getArg(0); + std::string s = argExpr->getType().getDesugaredType(compiler.getASTContext()).getAsString(); + if (s.find("iterator") != std::string::npos + || (loplugin::TypeCheck(argExpr->getType()).Class("__wrap_iter").Namespace("__1") + .StdNamespace())) + { + return true; + } + if (s.find("array") == std::string::npos && s.find("deque") == std::string::npos + && s.find("list") == std::string::npos && s.find("vector") == std::string::npos + && s.find("set") == std::string::npos && s.find("map") == std::string::npos + && s.find("stack") == std::string::npos && s.find("queue") == std::string::npos) + { + return true; + } + if (s.find("unique_ptr") != std::string::npos) { + expr->getArg(1)->dump(); + report( + DiagnosticsEngine::Warning, + "do not call operator== on a std container containing a unique_ptr " + s, + expr->getExprLoc()); + } + return true; +} + + +loplugin::Plugin::Registration< PtrVector > ptrvector("ptrvector"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/rangedforcopy.cxx b/compilerplugins/clang/rangedforcopy.cxx new file mode 100644 index 000000000..01124bb4d --- /dev/null +++ b/compilerplugins/clang/rangedforcopy.cxx @@ -0,0 +1,70 @@ + +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include + +#include "plugin.hxx" +#include "clang/AST/CXXInheritance.h" + +// Check that we're not unnecessarily copying variables in a range based for loop +// e.g. "for (OUString a: aList)" results in a copy of each string being made, +// whereas "for (const OUString& a: aList)" does not. + +namespace +{ + +class RangedForCopy: + public loplugin::FilteringPlugin +{ +public: + explicit RangedForCopy(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXForRangeStmt( const CXXForRangeStmt* stmt ); +}; + +bool RangedForCopy::VisitCXXForRangeStmt( const CXXForRangeStmt* stmt ) +{ + if (ignoreLocation( stmt )) + return true; + + const VarDecl* varDecl = stmt->getLoopVariable(); + if (!varDecl) + return true; + + const QualType type = varDecl->getType(); + if (type->isRecordType() && !type->isReferenceType() && !type->isPointerType()) + { + std::string name = type.getAsString(); + report( + DiagnosticsEngine::Warning, + "Loop variable passed by value, pass by reference instead, e.g. 'const %0&'", + varDecl->getBeginLoc()) + << name << varDecl->getSourceRange(); + } + + return true; +} + + +loplugin::Plugin::Registration< RangedForCopy > rangedforcopy("rangedforcopy"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/readability-redundant-pp.cxx b/compilerplugins/clang/readability-redundant-pp.cxx new file mode 100644 index 000000000..dcfd70247 --- /dev/null +++ b/compilerplugins/clang/readability-redundant-pp.cxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include +#include + +#include "plugin.hxx" + +#include +#include +#include +#include +#include + +/// Finds preprocessor usage which is redundant (only #ifndef for now). + +namespace +{ +struct Entry +{ + clang::SourceLocation m_aLoc; + std::string m_aMacroName; +}; + +class RedundantPreprocessor : public clang::PPCallbacks, public loplugin::Plugin +{ +public: + explicit RedundantPreprocessor(const loplugin::InstantiationData& data); + virtual void run() override; + void Ifndef(clang::SourceLocation aLoc, const clang::Token& rMacroNameTok, + const clang::MacroDefinition& rMacroDefinition) override; + void Ifdef(clang::SourceLocation aLoc, const clang::Token& rMacroNameTok, + const clang::MacroDefinition& rMacroDefinition) override; + void Endif(clang::SourceLocation aLoc, clang::SourceLocation aIfLoc) override; + enum + { + isPPCallback = true + }; + +private: + clang::Preprocessor& m_rPP; + std::vector m_aDefStack; + std::vector m_aNotDefStack; +}; + +RedundantPreprocessor::RedundantPreprocessor(const loplugin::InstantiationData& data) + : Plugin(data) + , m_rPP(compiler.getPreprocessor()) +{ + compiler.getPreprocessor().addPPCallbacks(std::unique_ptr(this)); +} + +void RedundantPreprocessor::run() +{ + // nothing, only check preprocessor usage +} + +void RedundantPreprocessor::Ifdef(clang::SourceLocation aLoc, const clang::Token& rMacroNameTok, + const clang::MacroDefinition& /*rMacroDefinition*/) +{ + if (ignoreLocation(aLoc)) + return; + + std::string aMacroName = m_rPP.getSpelling(rMacroNameTok); + if (m_rPP.getSourceManager().isInMainFile(aLoc)) + { + for (const auto& rEntry : m_aDefStack) + { + if (rEntry.m_aMacroName == aMacroName) + { + report(DiagnosticsEngine::Warning, "nested ifdef", aLoc); + report(DiagnosticsEngine::Note, "previous ifdef", rEntry.m_aLoc); + } + } + } + + Entry aEntry; + aEntry.m_aLoc = aLoc; + aEntry.m_aMacroName = aMacroName; + m_aDefStack.push_back(aEntry); +} + +void RedundantPreprocessor::Ifndef(clang::SourceLocation aLoc, const clang::Token& rMacroNameTok, + const clang::MacroDefinition& /*rMacroDefinition*/) +{ + if (ignoreLocation(aLoc)) + return; + + std::string aMacroName = m_rPP.getSpelling(rMacroNameTok); + if (m_rPP.getSourceManager().isInMainFile(aLoc)) + { + for (const auto& rEntry : m_aNotDefStack) + { + if (rEntry.m_aMacroName == aMacroName) + { + report(DiagnosticsEngine::Warning, "nested ifndef", aLoc); + report(DiagnosticsEngine::Note, "previous ifndef", rEntry.m_aLoc); + } + } + } + + Entry aEntry; + aEntry.m_aLoc = aLoc; + aEntry.m_aMacroName = aMacroName; + m_aNotDefStack.push_back(aEntry); +} + +void RedundantPreprocessor::Endif(clang::SourceLocation /*aLoc*/, clang::SourceLocation aIfLoc) +{ + if (!m_aDefStack.empty()) + { + if (aIfLoc == m_aDefStack.back().m_aLoc) + m_aDefStack.pop_back(); + } + if (!m_aNotDefStack.empty()) + { + if (aIfLoc == m_aNotDefStack.back().m_aLoc) + m_aNotDefStack.pop_back(); + } +} + +loplugin::Plugin::Registration X("redundantpreprocessor"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/reducevarscope.cxx b/compilerplugins/clang/reducevarscope.cxx new file mode 100644 index 000000000..be7254a2d --- /dev/null +++ b/compilerplugins/clang/reducevarscope.cxx @@ -0,0 +1,551 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +// Original idea from mike kaganski. +// Look for variables that can have their scoped reduced, which makes the code easier to read. + +// TODO when dealing with vars that are referenced in multiple child blocks, the check is very primitive +// and could be greatly improved. + +namespace +{ +class ReduceVarScope : public loplugin::FilteringPlugin +{ +public: + explicit ReduceVarScope(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override + { + if (!compiler.getLangOpts().CPlusPlus) + return false; + // ignore some files with problematic macros + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + // some declarations look better all together + if (fn == SRCDIR "/package/source/manifest/ManifestExport.cxx") + return false; + // storing pointer to OUString internal data + if (fn == SRCDIR "/connectivity/source/drivers/odbc/ODatabaseMetaDataResultSet.cxx" + || fn == SRCDIR "/sc/source/filter/excel/xestyle.cxx" + || fn == SRCDIR "/sw/source/filter/html/htmlflywriter.cxx" + || fn == SRCDIR "/unoxml/source/dom/element.cxx" + || fn == SRCDIR "/unoxml/source/dom/document.cxx" + || fn == SRCDIR "/sd/source/filter/eppt/pptx-animations.cxx") + return false; + if (fn == SRCDIR "/sal/qa/rtl/strings/nonconstarray.cxx") + return false; + return true; + } + + virtual void run() override + { + if (!preRun()) + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + postRun(); + } + + virtual void postRun() override + { + for (auto const& pair : maVarDeclMap) + { + auto varDecl = pair.first; + auto const& depthInfo = pair.second; + if (depthInfo.maDeclBlockPath.size() == depthInfo.maCommonBlockPath.size()) + continue; + if (maVarDeclToIgnoreSet.find(varDecl) != maVarDeclToIgnoreSet.end()) + continue; + auto it = maVarUseSourceRangeMap.find(varDecl); + if (it == maVarUseSourceRangeMap.end()) + continue; + report(DiagnosticsEngine::Warning, "can reduce scope of var", varDecl->getLocation()) + << varDecl->getSourceRange(); + for (SourceRange const& useRange : it->second) + report(DiagnosticsEngine::Note, "used here", useRange.getBegin()) << useRange; + } + } + + bool VisitUnaryOperator(UnaryOperator const* expr) + { + // if we take the address of it + UnaryOperator::Opcode op = expr->getOpcode(); + if (op == UO_AddrOf) + recordIgnore(expr->getSubExpr()); + return true; + } + + bool VisitDeclRefExpr(const DeclRefExpr*); + bool VisitVarDecl(const VarDecl*); + bool VisitLambdaExpr(const LambdaExpr*); + + bool PreTraverseFunctionDecl(FunctionDecl*); + bool PostTraverseFunctionDecl(FunctionDecl*, bool); + bool TraverseFunctionDecl(FunctionDecl*); + + bool PreTraverseCompoundStmt(CompoundStmt*); + bool PostTraverseCompoundStmt(CompoundStmt*, bool); + bool TraverseCompoundStmt(CompoundStmt*); + + bool PreTraverseWhileStmt(WhileStmt*); + bool PostTraverseWhileStmt(WhileStmt*, bool); + bool TraverseWhileStmt(WhileStmt*); + + bool PreTraverseDoStmt(DoStmt*); + bool PostTraverseDoStmt(DoStmt*, bool); + bool TraverseDoStmt(DoStmt*); + + bool PreTraverseCXXForRangeStmt(CXXForRangeStmt*); + bool PostTraverseCXXForRangeStmt(CXXForRangeStmt*, bool); + bool TraverseCXXForRangeStmt(CXXForRangeStmt*); + + bool PreTraverseForStmt(ForStmt*); + bool PostTraverseForStmt(ForStmt*, bool); + bool TraverseForStmt(ForStmt*); + + bool PreTraverseSwitchStmt(SwitchStmt*); + bool PostTraverseSwitchStmt(SwitchStmt*, bool); + bool TraverseSwitchStmt(SwitchStmt*); + +private: + struct DepthInfo + { + unsigned int mnFirstDepth = 0; + unsigned int mnFirstLoopDepth = 0; + std::vector maDeclBlockPath = {}; + std::vector maCommonBlockPath = {}; + }; + std::unordered_map maVarDeclMap; // varDecl->depth + std::unordered_set maVarDeclToIgnoreSet; + std::map> maVarUseSourceRangeMap; + std::vector maCurrentBlockPath; + unsigned int mnCurrentDepth = 0; + unsigned int mnCurrentLoopDepth = 0; + static unsigned int gnBlockId; + + bool isTypeOK(QualType qt); + bool isInitConstant(const VarDecl* varDecl); + + void recordIgnore(Expr const* expr) + { + for (;;) + { + expr = expr->IgnoreParenImpCasts(); + if (auto const e = dyn_cast(expr)) + { + if (isa(e->getMemberDecl())) + { + expr = e->getBase(); + continue; + } + } + if (auto const e = dyn_cast(expr)) + { + expr = e->getBase(); + continue; + } + if (auto const e = dyn_cast(expr)) + { + if (e->getOpcode() == BO_PtrMemD) + { + expr = e->getLHS(); + continue; + } + } + break; + } + auto const dre = dyn_cast(expr); + if (dre == nullptr) + return; + auto const var = dyn_cast(dre->getDecl()); + if (var == nullptr) + return; + maVarDeclToIgnoreSet.insert(var); + } +}; + +unsigned int ReduceVarScope::gnBlockId = 0; + +bool ReduceVarScope::PreTraverseFunctionDecl(FunctionDecl* functionDecl) +{ + // Ignore functions that contains #ifdef-ery, can be quite tricky + // to make useful changes when this plugin fires in such functions + if (containsPreprocessingConditionalInclusion(functionDecl->getSourceRange())) + return false; + return true; +} + +bool ReduceVarScope::PostTraverseFunctionDecl(FunctionDecl*, bool) { return true; } + +bool ReduceVarScope::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + bool ret = true; + if (PreTraverseFunctionDecl(functionDecl)) + { + ret = FilteringPlugin::TraverseFunctionDecl(functionDecl); + PostTraverseFunctionDecl(functionDecl, ret); + } + return ret; +} + +bool ReduceVarScope::PreTraverseCompoundStmt(CompoundStmt*) +{ + assert(mnCurrentDepth != std::numeric_limits::max()); + ++mnCurrentDepth; + ++gnBlockId; + maCurrentBlockPath.push_back(gnBlockId); + return true; +} + +bool ReduceVarScope::PostTraverseCompoundStmt(CompoundStmt*, bool) +{ + assert(mnCurrentDepth != 0); + --mnCurrentDepth; + maCurrentBlockPath.pop_back(); + return true; +} + +bool ReduceVarScope::TraverseCompoundStmt(CompoundStmt* decl) +{ + bool ret = true; + if (PreTraverseCompoundStmt(decl)) + { + ret = FilteringPlugin::TraverseCompoundStmt(decl); + PostTraverseCompoundStmt(decl, ret); + } + return ret; +} + +bool ReduceVarScope::PreTraverseWhileStmt(WhileStmt*) +{ + assert(mnCurrentLoopDepth != std::numeric_limits::max()); + ++mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::PostTraverseWhileStmt(WhileStmt*, bool) +{ + assert(mnCurrentLoopDepth != 0); + --mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::TraverseWhileStmt(WhileStmt* decl) +{ + bool ret = true; + if (PreTraverseWhileStmt(decl)) + { + ret = FilteringPlugin::TraverseWhileStmt(decl); + PostTraverseWhileStmt(decl, ret); + } + return ret; +} + +bool ReduceVarScope::PreTraverseDoStmt(DoStmt*) +{ + assert(mnCurrentLoopDepth != std::numeric_limits::max()); + ++mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::PostTraverseDoStmt(DoStmt*, bool) +{ + assert(mnCurrentLoopDepth != 0); + --mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::TraverseDoStmt(DoStmt* decl) +{ + bool ret = true; + if (PreTraverseDoStmt(decl)) + { + ret = FilteringPlugin::TraverseDoStmt(decl); + PostTraverseDoStmt(decl, ret); + } + return ret; +} + +bool ReduceVarScope::PreTraverseSwitchStmt(SwitchStmt*) +{ + assert(mnCurrentLoopDepth != std::numeric_limits::max()); + ++mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::PostTraverseSwitchStmt(SwitchStmt*, bool) +{ + assert(mnCurrentLoopDepth != 0); + --mnCurrentLoopDepth; + return true; +} + +// Consider a switch to be a loop, because weird things happen inside it +bool ReduceVarScope::TraverseSwitchStmt(SwitchStmt* decl) +{ + bool ret = true; + if (PreTraverseSwitchStmt(decl)) + { + ret = FilteringPlugin::TraverseSwitchStmt(decl); + PostTraverseSwitchStmt(decl, ret); + } + return ret; +} + +bool ReduceVarScope::PreTraverseCXXForRangeStmt(CXXForRangeStmt*) +{ + assert(mnCurrentLoopDepth != std::numeric_limits::max()); + ++mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::PostTraverseCXXForRangeStmt(CXXForRangeStmt*, bool) +{ + assert(mnCurrentLoopDepth != 0); + --mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::TraverseCXXForRangeStmt(CXXForRangeStmt* decl) +{ + bool ret = true; + if (PreTraverseCXXForRangeStmt(decl)) + { + ret = FilteringPlugin::TraverseCXXForRangeStmt(decl); + PostTraverseCXXForRangeStmt(decl, ret); + } + return ret; +} + +bool ReduceVarScope::PreTraverseForStmt(ForStmt* forStmt) +{ + assert(mnCurrentLoopDepth != std::numeric_limits::max()); + ++mnCurrentLoopDepth; + + auto declStmt = dyn_cast_or_null(forStmt->getInit()); + if (declStmt) + { + if (declStmt->isSingleDecl()) + { + if (auto varDecl = dyn_cast_or_null(declStmt->getSingleDecl())) + maVarDeclToIgnoreSet.insert(varDecl); + } + else + { + for (auto const& decl : declStmt->getDeclGroup()) + if (auto varDecl = dyn_cast_or_null(decl)) + maVarDeclToIgnoreSet.insert(varDecl); + } + } + + return true; +} + +bool ReduceVarScope::PostTraverseForStmt(ForStmt*, bool) +{ + assert(mnCurrentLoopDepth != 0); + --mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::TraverseForStmt(ForStmt* decl) +{ + bool ret = true; + if (PreTraverseForStmt(decl)) + { + ret = FilteringPlugin::TraverseForStmt(decl); + PostTraverseForStmt(decl, ret); + } + return ret; +} + +bool ReduceVarScope::VisitVarDecl(const VarDecl* varDecl) +{ + if (ignoreLocation(varDecl)) + return true; + if (varDecl->isExceptionVariable() || isa(varDecl)) + return true; + // ignore stuff in header files (which should really not be there, but anyhow) + if (!compiler.getSourceManager().isInMainFile(varDecl->getLocation())) + return true; + // Ignore macros like FD_ZERO + if (compiler.getSourceManager().isMacroBodyExpansion(varDecl->getBeginLoc())) + return true; + if (varDecl->hasGlobalStorage()) + return true; + if (varDecl->isConstexpr()) + return true; + if (varDecl->isInitCapture()) + return true; + if (varDecl->isCXXForRangeDecl()) + return true; + if (!isTypeOK(varDecl->getType())) + return true; + + if (varDecl->hasInit() && !isInitConstant(varDecl)) + return true; + + maVarDeclMap[varDecl].mnFirstDepth = mnCurrentDepth; + maVarDeclMap[varDecl].mnFirstLoopDepth = mnCurrentLoopDepth; + maVarDeclMap[varDecl].maDeclBlockPath = maCurrentBlockPath; + + return true; +} + +bool ReduceVarScope::isInitConstant(const VarDecl* varDecl) +{ + // check for string or scalar literals + const Expr* initExpr = varDecl->getInit(); + if (auto e = dyn_cast(initExpr)) + initExpr = e->getSubExpr(); + if (isa(initExpr)) + return true; + if (auto constructExpr = dyn_cast(initExpr)) + { + if (constructExpr->getNumArgs() == 0) + { + return true; // i.e., empty string + } + else + { + auto stringLit2 = dyn_cast(constructExpr->getArg(0)); + if (stringLit2) + return true; + } + } + + auto const init = varDecl->getInit(); + if (init->isValueDependent()) + return false; + return init->isConstantInitializer(compiler.getASTContext(), false /*ForRef*/); +} + +bool ReduceVarScope::isTypeOK(QualType varType) +{ + // TODO improve this - requires more analysis because it's really easy to + // take a pointer to an array + if (varType->isArrayType()) + return false; + + if (varType.isCXX11PODType(compiler.getASTContext())) + return true; + if (!varType->isRecordType()) + return false; + auto recordDecl = dyn_cast_or_null(varType->getAs()->getDecl()); + if (recordDecl && recordDecl->hasTrivialDestructor()) + return true; + auto const tc = loplugin::TypeCheck(varType); + // Safe types with destructors that don't do anything interesting + if (tc.Class("OString").Namespace("rtl").GlobalNamespace() + || tc.Class("OUString").Namespace("rtl").GlobalNamespace() + || tc.Class("OStringBuffer").Namespace("rtl").GlobalNamespace() + || tc.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + || tc.Class("Color").GlobalNamespace() || tc.Class("Pair").GlobalNamespace() + || tc.Class("Point").GlobalNamespace() || tc.Class("Size").GlobalNamespace() + || tc.Class("Range").GlobalNamespace() || tc.Class("Selection").GlobalNamespace() + || tc.Class("Rectangle").Namespace("tools").GlobalNamespace()) + return true; + return false; +} + +bool ReduceVarScope::VisitDeclRefExpr(const DeclRefExpr* declRefExpr) +{ + if (ignoreLocation(declRefExpr)) + return true; + const Decl* decl = declRefExpr->getDecl(); + if (!isa(decl) || isa(decl)) + return true; + const VarDecl* varDecl = dyn_cast(decl)->getCanonicalDecl(); + // ignore stuff in header files (which should really not be there, but anyhow) + if (!compiler.getSourceManager().isInMainFile(varDecl->getLocation())) + return true; + + auto varIt = maVarDeclMap.find(varDecl); + if (varIt == maVarDeclMap.end()) + return true; + + auto& depthInfo = varIt->second; + + // merge block paths to get common ancestor path + if (depthInfo.maCommonBlockPath.empty()) + depthInfo.maCommonBlockPath = maCurrentBlockPath; + else + { + auto len = std::min(depthInfo.maCommonBlockPath.size(), maCurrentBlockPath.size()); + unsigned int i = 0; + while (i < len && depthInfo.maCommonBlockPath[i] == maCurrentBlockPath[i]) + ++i; + depthInfo.maCommonBlockPath.resize(i); + if (depthInfo.maCommonBlockPath == depthInfo.maDeclBlockPath) + { + maVarDeclMap.erase(varIt); + maVarUseSourceRangeMap.erase(varDecl); + return true; + } + } + + // seen in a loop below initial decl + if (mnCurrentLoopDepth > depthInfo.mnFirstLoopDepth) + { + // TODO, we could additionally check if we are reading or writing to the var inside a loop + // We only need to exclude vars that are written to, or passed taken-addr-of, or have non-const method called, + // or passed as arg to non-const-ref parameter. + maVarDeclMap.erase(varIt); + maVarUseSourceRangeMap.erase(varDecl); + return true; + } + + auto it = maVarUseSourceRangeMap.find(varDecl); + if (it == maVarUseSourceRangeMap.end()) + it = maVarUseSourceRangeMap.emplace(varDecl, std::vector()).first; + it->second.push_back(declRefExpr->getSourceRange()); + + return true; +} + +bool ReduceVarScope::VisitLambdaExpr(const LambdaExpr* lambdaExpr) +{ + if (ignoreLocation(lambdaExpr)) + return true; + for (auto captureIt = lambdaExpr->capture_begin(); captureIt != lambdaExpr->capture_end(); + ++captureIt) + { + const LambdaCapture& capture = *captureIt; + if (capture.capturesVariable()) + { + auto varDecl = capture.getCapturedVar(); + maVarDeclMap.erase(varDecl); + maVarUseSourceRangeMap.erase(varDecl); + } + } + return true; +} + +loplugin::Plugin::Registration reducevarscope("reducevarscope", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/redundantcast.cxx b/compilerplugins/clang/redundantcast.cxx new file mode 100644 index 000000000..87c4d1445 --- /dev/null +++ b/compilerplugins/clang/redundantcast.cxx @@ -0,0 +1,969 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Warn about certain redundant casts: +// +// * A reinterpret_cast(...) whose result is then implicitly cast to a void +// pointer +// +// * A static_cast(e) where e is of void pointer type and whose result is +// then implicitly cast to a void pointer +// +// * Various const_casts that are either not needed (like casting away constness +// in a delete expression) or are implicitly cast back afterwards +// +// C-style casts are ignored because it makes this plugin simpler, and they +// should eventually be eliminated via loplugin:cstylecast and/or +// -Wold-style-cast. That implies that this plugin is only relevant for C++ +// code. + +#include "clang/Sema/Sema.h" + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" +#include + +namespace { + +bool isVoidPointer(QualType type) { + return type->isPointerType() + && type->getAs()->getPointeeType()->isVoidType(); +} + +bool isRedundantConstCast(CXXConstCastExpr const * expr) { + auto const sub = compat::getSubExprAsWritten(expr); + return + (expr->getType().getCanonicalType() + == sub->getType().getCanonicalType()) + && (expr->getValueKind() != VK_XValue + || sub->getValueKind() == VK_XValue); +} + +bool canConstCastFromTo(Expr const * from, Expr const * to) { + auto const k1 = from->getValueKind(); + auto const k2 = to->getValueKind(); + return (k2 == VK_LValue && k1 == VK_LValue) + || (k2 == VK_XValue + && (k1 != compat::VK_PRValue || from->getType()->isRecordType())); +} + +char const * printExprValueKind(ExprValueKind k) { + switch (k) { + case compat::VK_PRValue: + return "prvalue"; + case VK_LValue: + return "lvalue"; + case VK_XValue: + return "xvalue"; + }; + llvm_unreachable("unknown ExprValueKind"); +} + +enum class AlgebraicType { None, Integer, FloatingPoint }; + +AlgebraicType algebraicType(clang::Type const & type) { + if (type.isIntegralOrEnumerationType()) { + return AlgebraicType::Integer; + } else if (type.isRealFloatingType()) { + return AlgebraicType::FloatingPoint; + } else { + return AlgebraicType::None; + } +} + +// Do not look through FunctionToPointerDecay, but through e.g. NullToPointer: +Expr const * stopAtFunctionPointerDecay(ExplicitCastExpr const * expr) { + auto const e1 = expr->getSubExpr(); + if (auto const e2 = dyn_cast(e1)) { + if (e2->getCastKind() != CK_FunctionToPointerDecay) { + return e2->getSubExpr(); + } + } + return e1; +} + +class RedundantCast: + public loplugin::FilteringRewritePlugin +{ +public: + explicit RedundantCast(loplugin::InstantiationData const & data): + FilteringRewritePlugin(data) + {} + + virtual void run() override { + if (compiler.getLangOpts().CPlusPlus) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool TraverseInitListExpr(InitListExpr * expr, DataRecursionQueue * queue = nullptr) { + return WalkUpFromInitListExpr(expr) + && TraverseSynOrSemInitListExpr( + expr->isSemanticForm() ? expr : expr->getSemanticForm(), queue); + } + + bool TraverseReturnStmt(ReturnStmt * stmt) { + auto const saved = returnExpr_; + returnExpr_ = stmt->getRetValue(); + auto const ret = FilteringRewritePlugin::TraverseReturnStmt(stmt); + returnExpr_ = saved; + return ret; + } + + bool VisitImplicitCastExpr(ImplicitCastExpr const * expr); + + bool VisitCXXStaticCastExpr(CXXStaticCastExpr const * expr); + + bool VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr const * expr); + + bool VisitCXXConstCastExpr(CXXConstCastExpr const * expr); + + bool VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const * expr); + + bool VisitCXXDynamicCastExpr(CXXDynamicCastExpr const * expr); + + bool VisitCallExpr(CallExpr const * expr); + + bool VisitCXXDeleteExpr(CXXDeleteExpr const * expr); + + bool VisitCStyleCastExpr(CStyleCastExpr const * expr); + + bool VisitBinaryOperator(BinaryOperator const * expr) { + auto const op = expr->getOpcode(); + if (op == BO_Sub || expr->isRelationalOp() || expr->isEqualityOp()) { + return visitBinOp(expr); + } + if (op == BO_Assign) { + if (ignoreLocation(expr)) { + return true; + } + visitAssign(expr->getLHS()->getType(), expr->getRHS()); + return true; + } + return true; + } + + bool VisitVarDecl(VarDecl const * varDecl); + +private: + bool visitBinOp(BinaryOperator const * expr); + void visitAssign(QualType lhs, Expr const * rhs); + bool isOverloadedFunction(FunctionDecl const * decl); + + bool isInIgnoredMacroBody(Expr const * expr) { + auto const loc = expr->getBeginLoc(); + return compiler.getSourceManager().isMacroBodyExpansion(loc) + && ignoreLocation(compiler.getSourceManager().getSpellingLoc(loc)); + } + + Expr const * returnExpr_ = nullptr; +}; + +bool RedundantCast::VisitImplicitCastExpr(const ImplicitCastExpr * expr) { + if (ignoreLocation(expr)) { + return true; + } + switch (expr->getCastKind()) { + case CK_NoOp: + if (expr->getType()->isPointerType() + || expr->getType()->isObjectType()) + { + auto e = dyn_cast( + expr->getSubExpr()->IgnoreParenImpCasts()); + if (e != nullptr && !isRedundantConstCast(e)) { + auto t1 = e->getSubExpr()->getType().getCanonicalType(); + auto t3 = expr->getType().getCanonicalType(); + bool ObjCLifetimeConversion; + if (t1.getTypePtr() == t3.getTypePtr() + || (compiler.getSema().IsQualificationConversion( + t1, t3, false, ObjCLifetimeConversion) + && (e->getType().getCanonicalType().getTypePtr() + != t3.getTypePtr()))) + { + report( + DiagnosticsEngine::Warning, + ("redundant const_cast from %0 to %1, result is" + " implicitly cast to %2"), + e->getExprLoc()) + << e->getSubExprAsWritten()->getType() << e->getType() + << expr->getType() << expr->getSourceRange(); + } + } + } + break; + case CK_BitCast: + if (isVoidPointer(expr->getType()) + && expr->getSubExpr()->getType()->isPointerType()) + { + Expr const * e = expr->getSubExpr()->IgnoreParenImpCasts(); + while (isa(e)) { + auto cc = dyn_cast(e); + if (expr->getType()->getAs() + ->getPointeeType().isAtLeastAsQualifiedAs( + cc->getSubExpr()->getType() + ->getAs()->getPointeeType())) + { + report( + DiagnosticsEngine::Warning, + ("redundant const_cast from %0 to %1, result is" + " ultimately implicitly cast to %2"), + cc->getExprLoc()) + << cc->getSubExprAsWritten()->getType() << cc->getType() + << expr->getType() << expr->getSourceRange(); + } + e = cc->getSubExpr()->IgnoreParenImpCasts(); + } + if (isa(e)) { + report( + DiagnosticsEngine::Warning, + ("redundant reinterpret_cast, result is implicitly cast to" + " void pointer"), + e->getExprLoc()) + << e->getSourceRange(); + } else if (isa(e) + && isVoidPointer( + dyn_cast(e)->getSubExpr() + ->IgnoreParenImpCasts()->getType()) + && !compiler.getSourceManager().isMacroBodyExpansion( + e->getBeginLoc())) + { + report( + DiagnosticsEngine::Warning, + ("redundant static_cast from void pointer, result is" + " implicitly cast to void pointer"), + e->getExprLoc()) + << e->getSourceRange(); + } + } + break; + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + if (expr->getType()->isPointerType()) { + Expr const * e = expr->getSubExpr()->IgnoreParenImpCasts(); + while (isa(e)) { + auto cc = dyn_cast(e); + if (expr->getType()->getAs() + ->getPointeeType().isAtLeastAsQualifiedAs( + cc->getSubExpr()->getType() + ->getAs()->getPointeeType())) + { + report( + DiagnosticsEngine::Warning, + ("redundant const_cast from %0 to %1, result is" + " ultimately implicitly cast to %2"), + cc->getExprLoc()) + << cc->getSubExprAsWritten()->getType() << cc->getType() + << expr->getType() << expr->getSourceRange(); + } + e = cc->getSubExpr()->IgnoreParenImpCasts(); + } + } else if (expr->getType()->isReferenceType()) { + Expr const * e = expr->getSubExpr()->IgnoreParenImpCasts(); + while (isa(e)) { + auto cc = dyn_cast(e); + if (expr->getType()->getAs()->getPointeeType() + .isAtLeastAsQualifiedAs( + cc->getSubExpr()->getType() + ->getAs()->getPointeeType())) + { + report( + DiagnosticsEngine::Warning, + ("redundant const_cast from %0 to %1, result is" + " ultimately implicitly cast to %2"), + cc->getExprLoc()) + << cc->getSubExprAsWritten()->getType() << cc->getType() + << expr->getType() << expr->getSourceRange(); + } + e = cc->getSubExpr()->IgnoreParenImpCasts(); + } + } + break; + case CK_FloatingToIntegral: + case CK_IntegralToFloating: + if (auto e = dyn_cast(expr->getSubExpr()->IgnoreParenImpCasts())) { + if ((isa(e) || isa(e)) + && (algebraicType(*e->getSubExprAsWritten()->getType()) + == algebraicType(*expr->getType()))) + { + report( + DiagnosticsEngine::Warning, + ("suspicious %select{static_cast|functional cast}0 from %1 to %2, result is" + " implicitly cast to %3"), + e->getExprLoc()) + << isa(e) << e->getSubExprAsWritten()->getType() + << e->getTypeAsWritten() << expr->getType() << expr->getSourceRange(); + } + } + break; + default: + break; + } + return true; +} + +bool RedundantCast::VisitCStyleCastExpr(CStyleCastExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc()))) { + return true; + } + auto t1 = compat::getSubExprAsWritten(expr)->getType(); + auto t2 = expr->getTypeAsWritten(); + if (auto templateType = dyn_cast(t1)) { + t1 = templateType->desugar(); + } + if (t1 != t2) { + return true; + } + if (!t1->isBuiltinType() && !loplugin::TypeCheck(t1).Enum() && !loplugin::TypeCheck(t1).Typedef()) { + return true; + } + if (!loplugin::isOkToRemoveArithmeticCast(compiler.getASTContext(), t1, t2, expr->getSubExpr())) + { + return true; + } + // Ignore FD_ISSET expanding to "...(SOCKET)(fd)..." in some Microsoft + // winsock2.h (TODO: improve heuristic of determining that the whole + // expr is part of a single macro body expansion): + auto l1 = expr->getBeginLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(l1)) { + l1 = compiler.getSourceManager().getImmediateMacroCallerLoc(l1); + } + auto l2 = expr->getExprLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(l2)) { + l2 = compiler.getSourceManager().getImmediateMacroCallerLoc(l2); + } + auto l3 = expr->getEndLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(l3)) { + l3 = compiler.getSourceManager().getImmediateMacroCallerLoc(l3); + } + if (compiler.getSourceManager().isMacroBodyExpansion(l1) + && compiler.getSourceManager().isMacroBodyExpansion(l2) + && compiler.getSourceManager().isMacroBodyExpansion(l3) + && ignoreLocation(compiler.getSourceManager().getSpellingLoc(l2))) + { + return true; + } + report( + DiagnosticsEngine::Warning, + "redundant cstyle cast from %0 to %1", expr->getExprLoc()) + << t1 << t2 << expr->getSourceRange(); + return true; +} + +bool RedundantCast::VisitVarDecl(VarDecl const * varDecl) { + if (ignoreLocation(varDecl)) { + return true; + } + if (!varDecl->getInit()) + return true; + visitAssign(varDecl->getType(), varDecl->getInit()); + return true; +} + +void RedundantCast::visitAssign(QualType t1, Expr const * rhs) +{ + auto staticCastExpr = dyn_cast(rhs->IgnoreImplicit()); + if (!staticCastExpr) + return; + + auto const t2 = staticCastExpr->getSubExpr()->IgnoreImplicit()->getType(); + + // if there is more than one copy of the LHS, this cast is resolving ambiguity + bool foundOne = false; + if (t1->isRecordType()) + { + foundOne = loplugin::derivedFromCount(t2, t1) == 1; + } + else + { + auto pointee1 = t1->getPointeeCXXRecordDecl(); + auto pointee2 = t2->getPointeeCXXRecordDecl(); + if (pointee1 && pointee2) + foundOne = loplugin::derivedFromCount(pointee2, pointee1) == 1; + } + + if (foundOne) + { + report( + DiagnosticsEngine::Warning, "redundant static_cast from %0 to %1", + staticCastExpr->getExprLoc()) + << t2 << t1 << staticCastExpr->getSourceRange(); + } +} + +bool RedundantCast::VisitCXXStaticCastExpr(CXXStaticCastExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto const t2 = expr->getTypeAsWritten(); + bool const fnptr = t2->isFunctionPointerType() || t2->isMemberFunctionPointerType(); + auto const sub = fnptr ? stopAtFunctionPointerDecay(expr) : compat::getSubExprAsWritten(expr); + auto const t1 = sub->getType(); + auto const nonClassObjectType = t2->isObjectType() + && !(t2->isRecordType() || t2->isArrayType()); + if (nonClassObjectType && t2.hasLocalQualifiers()) { + report( + DiagnosticsEngine::Warning, + ("in static_cast from %0 %1 to %2 %3, remove redundant top-level" + " %select{const qualifier|volatile qualifier|const volatile" + " qualifiers}4"), + expr->getExprLoc()) + << t1 << printExprValueKind(sub->getValueKind()) + << t2 << printExprValueKind(expr->getValueKind()) + << ((t2.isLocalConstQualified() ? 1 : 0) + + (t2.isLocalVolatileQualified() ? 2 : 0) - 1) + << expr->getSourceRange(); + return true; + } + if (auto const impl = dyn_cast(expr->getSubExpr())) { + if (impl->getCastKind() == CK_ArrayToPointerDecay && impl->getType() == t2) + //TODO: instead of exact QualType match, allow some variation? + { + auto const fn = handler.getMainFileName(); + if (!(loplugin::isSamePathname( + fn, SRCDIR "/sal/qa/rtl/strings/test_ostring_concat.cxx") + || loplugin::isSamePathname( + fn, SRCDIR "/sal/qa/rtl/strings/test_ostring_stringliterals.cxx") + || loplugin::isSamePathname( + fn, SRCDIR "/sal/qa/rtl/strings/test_oustring_concat.cxx") + || loplugin::isSamePathname( + fn, SRCDIR "/sal/qa/rtl/strings/test_oustring_stringliterals.cxx") + || isInIgnoredMacroBody(expr))) + { + report( + DiagnosticsEngine::Warning, "redundant static_cast from %0 to %1", + expr->getExprLoc()) + << expr->getSubExprAsWritten()->getType() << t2 << expr->getSourceRange(); + } + return true; + } + } + auto const t3 = expr->getType(); + auto const c1 = t1.getCanonicalType(); + auto const c3 = t3.getCanonicalType(); + if (nonClassObjectType || !canConstCastFromTo(sub, expr) + ? c1.getTypePtr() != c3.getTypePtr() : c1 != c3) + { + bool ObjCLifetimeConversion; + if (nonClassObjectType + || (c1.getTypePtr() != c3.getTypePtr() + && !compiler.getSema().IsQualificationConversion( + c1, c3, false, ObjCLifetimeConversion))) + { + return true; + } + report( + DiagnosticsEngine::Warning, + "static_cast from %0 %1 to %2 %3 should be written as const_cast", + expr->getExprLoc()) + << t1 << printExprValueKind(sub->getValueKind()) + << t2 << printExprValueKind(expr->getValueKind()) + << expr->getSourceRange(); + return true; + } + if (!loplugin::isOkToRemoveArithmeticCast(compiler.getASTContext(), t1, t2, expr->getSubExpr())) + { + return true; + } + // Don't warn if the types are 'void *' and at least one involves a typedef + // (and if both involve typedefs, they're different) (this covers cases like + // 'oslModule', or 'CURL *', or casts between 'LPVOID' and 'HANDLE' in + // Windows-only code): + if (loplugin::TypeCheck(t1).Pointer().NonConstVolatile().Void()) { + if (auto const td1 = t1->getAs()) { + auto const td2 = t2->getAs(); + if (td2 == nullptr || td2 != td1) { + return true; + } + } else if (auto const td2 = t2->getAs()) { + auto const td1 = t1->getAs(); + if (td1 == nullptr || td1 != td2) { + return true; + } + } else { + auto const pt1 = t1->getAs()->getPointeeType(); + auto const pt2 = t2->getAs()->getPointeeType(); + if (auto const ptd1 = pt1->getAs()) { + auto const ptd2 = pt2->getAs(); + if (ptd2 == nullptr || ptd2 != ptd1) { + return true; + } + } else if (auto const ptd2 = pt2->getAs()) { + auto const ptd1 = pt1->getAs(); + if (ptd1 == nullptr || ptd1 != ptd2) { + return true; + } + } + } + } + auto const k1 = sub->getValueKind(); + auto const k3 = expr->getValueKind(); + if ((k3 == VK_XValue && k1 != VK_XValue) + || (k3 == VK_LValue && k1 == VK_XValue)) + { + return true; + } + // For "P2266R1: Simpler + // implicit move" (as implemented with "[clang] Implement P2266 Simpler implicit move" + // towards Clang 13), don't warn about a static_cast in a return statement like + // + // return static_cast(x); + // + // that needs an lvalue but where in a return statement like + // + // return x; + // + // the expression would now be an xvalue: + if (k3 == VK_LValue && k1 == VK_LValue && returnExpr_ != nullptr + && expr == returnExpr_->IgnoreParens()) + { + return true; + } + // Don't warn if a static_cast on a pointer to function or member function is used to + // disambiguate an overloaded function: + if (fnptr) { + auto e = sub->IgnoreParenImpCasts(); + if (auto const e1 = dyn_cast(e)) { + if (e1->getOpcode() == UO_AddrOf) { + e = e1->getSubExpr()->IgnoreParenImpCasts(); + } + } + if (auto const e1 = dyn_cast(e)) { + if (auto const fdecl = dyn_cast(e1->getDecl())) { + if (isOverloadedFunction(fdecl)) { + return true; + } + } + } + } + // Suppress warnings from static_cast in C++ definition of assert in + // "assert: Support types + // without operator== (int) [BZ #21972]": + if (t1->isBooleanType() && t2->isBooleanType()) { + auto loc = expr->getBeginLoc(); + if (compiler.getSourceManager().isMacroBodyExpansion(loc) + && (Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()) + == "assert")) + { + return true; + } + } + report( + DiagnosticsEngine::Warning, + ("static_cast from %0 %1 to %2 %3 is redundant%select{| or should be" + " written as an explicit construction of a temporary}4"), + expr->getExprLoc()) + << t1 << printExprValueKind(k1) << t2 << printExprValueKind(k3) + << (k3 == compat::VK_PRValue && (k1 != compat::VK_PRValue || t1->isRecordType())) + << expr->getSourceRange(); + return true; +} + +bool RedundantCast::VisitCXXReinterpretCastExpr( + CXXReinterpretCastExpr const * expr) +{ + if (ignoreLocation(expr)) { + return true; + } + if (expr->getTypeAsWritten() == expr->getSubExprAsWritten()->getType()) + //TODO: instead of exact QualType match, allow some variation? + { + report( + DiagnosticsEngine::Warning, "redundant reinterpret_cast from %0 to %1", + expr->getExprLoc()) + << expr->getSubExprAsWritten()->getType() << expr->getTypeAsWritten() + << expr->getSourceRange(); + return true; + } + if (auto const sub = dyn_cast(expr->getSubExpr())) { + if (sub->getCastKind() == CK_ArrayToPointerDecay && sub->getType() == expr->getType()) + //TODO: instead of exact QualType match, allow some variation? + { + if (loplugin::TypeCheck(sub->getType()).Pointer().Const().Char()) { + if (auto const lit = dyn_cast(expr->getSubExprAsWritten())) { + if (lit->getKind() == clang::StringLiteral::UTF8) { + // Don't warn about + // + // redundant_cast(u8"...") + // + // in pre-C++2a code: + return true; + } + } + } + report( + DiagnosticsEngine::Warning, "redundant reinterpret_cast from %0 to %1", + expr->getExprLoc()) + << expr->getSubExprAsWritten()->getType() << expr->getTypeAsWritten() + << expr->getSourceRange(); + return true; + } + } + if (expr->getSubExpr()->getType()->isVoidPointerType()) { + auto t = expr->getType()->getAs(); + if (t == nullptr || !t->getPointeeType()->isObjectType()) { + return true; + } + if (rewriter != nullptr) { + auto loc = expr->getBeginLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(loc)) { + loc = compiler.getSourceManager().getImmediateMacroCallerLoc( + loc); + } + if (compiler.getSourceManager().isMacroBodyExpansion(loc)) { + auto loc2 = expr->getEndLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(loc2)) { + loc2 = compiler.getSourceManager() + .getImmediateMacroCallerLoc(loc2); + } + if (compiler.getSourceManager().isMacroBodyExpansion(loc2)) { + //TODO: check loc, loc2 are in same macro body expansion + loc = compiler.getSourceManager().getSpellingLoc(loc); + } + } + auto s = compiler.getSourceManager().getCharacterData(loc); + auto n = Lexer::MeasureTokenLength( + loc, compiler.getSourceManager(), compiler.getLangOpts()); + std::string tok(s, n); + if (tok == "reinterpret_cast" && replaceText(loc, n, "static_cast")) + { + return true; + } + } + report( + DiagnosticsEngine::Warning, + "reinterpret_cast from %0 to %1 can be simplified to static_cast", + expr->getExprLoc()) + << expr->getSubExprAsWritten()->getType() << expr->getType() + << expr->getSourceRange(); + } else if (expr->getType()->isVoidPointerType()) { + auto t = expr->getSubExpr()->getType()->getAs(); + if (t == nullptr || !t->getPointeeType()->isObjectType()) { + return true; + } + report( + DiagnosticsEngine::Warning, + ("reinterpret_cast from %0 to %1 can be simplified to static_cast" + " or an implicit conversion"), + expr->getExprLoc()) + << expr->getSubExprAsWritten()->getType() << expr->getType() + << expr->getSourceRange(); + } else if (expr->getType()->isFundamentalType()) { + if (auto const sub = dyn_cast( + expr->getSubExpr()->IgnoreParens())) + { + report( + DiagnosticsEngine::Warning, + ("redundant const_cast from %0 to %1 within reinterpret_cast to" + " fundamental type %2"), + expr->getExprLoc()) + << sub->getSubExprAsWritten()->getType() + << sub->getTypeAsWritten() << expr->getTypeAsWritten() + << expr->getSourceRange(); + return true; + } + } + return true; +} + +bool RedundantCast::VisitCXXConstCastExpr(CXXConstCastExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto const sub = compat::getSubExprAsWritten(expr); + if (isRedundantConstCast(expr)) { + report( + DiagnosticsEngine::Warning, + "redundant const_cast from %0 %1 to %2 %3", expr->getExprLoc()) + << sub->getType() << printExprValueKind(sub->getValueKind()) + << expr->getTypeAsWritten() + << printExprValueKind(expr->getValueKind()) + << expr->getSourceRange(); + return true; + } + if (auto const dce = dyn_cast( + sub->IgnoreParenImpCasts())) + { + auto const sub2 = compat::getSubExprAsWritten(dce); + auto t1 = sub2->getType().getCanonicalType(); + auto isNullptr = t1->isNullPtrType(); + auto t2 = dce->getType().getCanonicalType(); + auto t3 = expr->getType().getCanonicalType(); + auto redundant = false; + for (;;) { + if ((t2.isConstQualified() + && (isNullptr || !t1.isConstQualified()) + && !t3.isConstQualified()) + || (t2.isVolatileQualified() + && (isNullptr || !t1.isVolatileQualified()) + && !t3.isVolatileQualified())) + { + redundant = true; + break; + } + if (!isNullptr) { + auto const p1 = t1->getAs(); + if (p1 == nullptr) { + break; + } + t1 = p1->getPointeeType(); + isNullptr = t1->isNullPtrType(); + } + auto const p2 = t2->getAs(); + if (p2 == nullptr) { + break; + } + t2 = p2->getPointeeType(); + auto const p3 = t3->getAs(); + if (p3 == nullptr) { + break; + } + t3 = p3->getPointeeType(); + } + if (redundant) { + report( + DiagnosticsEngine::Warning, + ("redundant static_cast/const_cast combination from %0 via %1" + " to %2"), + expr->getExprLoc()) + << sub2->getType() << dce->getTypeAsWritten() + << expr->getTypeAsWritten() << expr->getSourceRange(); + } + } + return true; +} + +bool RedundantCast::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + // Restrict this to "real" casts (compared to uses of braced-init-list, like + // + // Foo{bar, baz} + // + // or + // + // std::initializer_list{bar, baz} + // + // ), and only to cases where the sub-expression already is a prvalue of + // non-class type (and thus the cast is unlikely to be meant to create a + // temporary): + auto const t1 = expr->getTypeAsWritten(); + bool const fnptr = t1->isFunctionPointerType() || t1->isMemberFunctionPointerType(); + auto const sub = fnptr ? stopAtFunctionPointerDecay(expr) : compat::getSubExprAsWritten(expr); + if ((sub->getValueKind() != compat::VK_PRValue && !fnptr) || expr->getType()->isRecordType() + || isa(sub) || isa(sub)) + { + return true; + } + + // See "There might even be good reasons(?) not to warn inside explicit + // casts" block in compilerplugins/clang/test/cppunitassertequals.cxx: + auto const eloc = expr->getExprLoc(); + if (compiler.getSourceManager().isMacroArgExpansion(eloc)) { + auto const name = Lexer::getImmediateMacroName( + eloc, compiler.getSourceManager(), compiler.getLangOpts()); + if (name == "CPPUNIT_ASSERT" || name == "CPPUNIT_ASSERT_MESSAGE") { + return true; + } + } + + // Don't warn if a functional cast on a pointer to function or member function is used to + // disambiguate an overloaded function: + if (fnptr) { + auto e = sub->IgnoreParenImpCasts(); + if (auto const e1 = dyn_cast(e)) { + if (e1->getOpcode() == UO_AddrOf) { + e = e1->getSubExpr()->IgnoreParenImpCasts(); + } + } + if (auto const e1 = dyn_cast(e)) { + if (auto const fdecl = dyn_cast(e1->getDecl())) { + if (isOverloadedFunction(fdecl)) { + return true; + } + } + } + } + + // See the commit message of d0e7d020fa405ab94f19916ec96fbd4611da0031 + // "socket.c -> socket.cxx" for the reason to have + // + // bool(FD_ISSET(...)) + // + // in sal/osl/unx/socket.cxx: + //TODO: Better check that sub is exactly an expansion of FD_ISSET: + if (sub->getEndLoc().isMacroID()) { + for (auto loc = sub->getBeginLoc(); + loc.isMacroID() + && (compiler.getSourceManager() + .isAtStartOfImmediateMacroExpansion(loc)); + loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc)) + { + if (Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()) + == "FD_ISSET") + { + return true; + } + } + } + + auto const t2 = sub->getType(); + if (t1.getCanonicalType() != t2.getCanonicalType()) + return true; + if (!loplugin::isOkToRemoveArithmeticCast(compiler.getASTContext(), t1, t2, expr->getSubExpr())) + return true; + report( + DiagnosticsEngine::Warning, + "redundant functional cast from %0 to %1", expr->getExprLoc()) + << t2 << t1 << expr->getSourceRange(); + return true; +} + +bool RedundantCast::VisitCXXDynamicCastExpr(CXXDynamicCastExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto const sub = compat::getSubExprAsWritten(expr); + auto const t1 = expr->getTypeAsWritten(); + auto const t2 = sub->getType(); + QualType qt1 = t1.getCanonicalType(); + QualType qt2 = t2.getCanonicalType(); + if (qt1 == qt2) + { + report( + DiagnosticsEngine::Warning, + "redundant dynamic cast from %0 to %1", expr->getExprLoc()) + << t2 << t1 << expr->getSourceRange(); + return true; + } + if (qt1->isPointerType() && qt2->isPointerType()) + { + // casting from 'T*' to 'const T*' is redundant, so compare without the qualifiers + qt1 = qt1->getPointeeType().getUnqualifiedType(); + qt2 = qt2->getPointeeType().getUnqualifiedType(); + if (qt1 == qt2) + { + report( + DiagnosticsEngine::Warning, + "redundant dynamic cast from %0 to %1", expr->getExprLoc()) + << t2 << t1 << expr->getSourceRange(); + return true; + } + if (qt1->getAsCXXRecordDecl() && qt2->getAsCXXRecordDecl()->isDerivedFrom(qt1->getAsCXXRecordDecl())) + { + report( + DiagnosticsEngine::Warning, + "redundant dynamic upcast from %0 to %1", expr->getExprLoc()) + << t2 << t1 << expr->getSourceRange(); + return true; + } + } + return true; +} + +bool RedundantCast::VisitCallExpr(CallExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto f = expr->getDirectCallee(); + if (f == nullptr || !f->isVariadic() + || expr->getNumArgs() <= f->getNumParams()) + { + return true; + } + for (auto i = f->getNumParams(); i != expr->getNumArgs(); ++i) { + auto a = expr->getArg(i); + if (a->getType()->isPointerType()) { + auto e = dyn_cast(a->IgnoreParenImpCasts()); + if (e != nullptr) { + report( + DiagnosticsEngine::Warning, + "redundant const_cast of variadic function argument", + e->getExprLoc()) + << expr->getSourceRange(); + } + } + } + return true; +} + +bool RedundantCast::VisitCXXDeleteExpr(CXXDeleteExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto e = dyn_cast( + expr->getArgument()->IgnoreParenImpCasts()); + if (e != nullptr) { + report( + DiagnosticsEngine::Warning, + "redundant const_cast in delete expression", e->getExprLoc()) + << expr->getSourceRange(); + } + return true; +} + +bool RedundantCast::visitBinOp(BinaryOperator const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (expr->getLHS()->getType()->isPointerType() + && expr->getRHS()->getType()->isPointerType()) + { + auto e = dyn_cast( + expr->getLHS()->IgnoreParenImpCasts()); + if (e != nullptr) { + report( + DiagnosticsEngine::Warning, + "redundant const_cast on lhs of pointer %select{comparison|subtraction}0 expression", + e->getExprLoc()) + << (expr->getOpcode() == BO_Sub) << expr->getSourceRange(); + } + e = dyn_cast( + expr->getRHS()->IgnoreParenImpCasts()); + if (e != nullptr) { + report( + DiagnosticsEngine::Warning, + "redundant const_cast on rhs of pointer %select{comparison|subtraction}0 expression", + e->getExprLoc()) + << (expr->getOpcode() == BO_Sub) << expr->getSourceRange(); + } + } + return true; +} + +bool RedundantCast::isOverloadedFunction(FunctionDecl const * decl) { + auto const ctx = decl->getDeclContext(); + if (!ctx->isLookupContext()) { + return false; + } + auto const canon = decl->getCanonicalDecl(); + auto const res = ctx->lookup(decl->getDeclName()); + for (auto d = res.begin(); d != res.end(); ++d) { + if (auto const f = dyn_cast(*d)) { + if (f->getCanonicalDecl() != canon) { + return true; + } + } + } + return false; +} + +loplugin::Plugin::Registration X("redundantcast", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/redundantfcast.cxx b/compilerplugins/clang/redundantfcast.cxx new file mode 100644 index 000000000..38a7daf9f --- /dev/null +++ b/compilerplugins/clang/redundantfcast.cxx @@ -0,0 +1,357 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" +#include +#include +#include +#include + +namespace +{ +class RedundantFCast final : public loplugin::FilteringPlugin +{ +public: + explicit RedundantFCast(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool VisitReturnStmt(ReturnStmt const* returnStmt) + { + if (ignoreLocation(returnStmt)) + return true; + Expr const* expr = returnStmt->getRetValue(); + if (!expr) + return true; + if (auto exprWithCleanups = dyn_cast(expr)) + expr = exprWithCleanups->getSubExpr(); + if (auto cxxConstructExpr = dyn_cast(expr)) + { + if (cxxConstructExpr->getNumArgs() != 1) + return true; + expr = cxxConstructExpr->getArg(0); + } + if (auto materializeTemporaryExpr = dyn_cast(expr)) + expr = materializeTemporaryExpr->getSubExpr(); + auto cxxFunctionalCastExpr = dyn_cast(expr); + if (!cxxFunctionalCastExpr) + return true; + auto const t1 = cxxFunctionalCastExpr->getTypeAsWritten(); + auto const t2 = compat::getSubExprAsWritten(cxxFunctionalCastExpr)->getType(); + if (t1.getCanonicalType().getTypePtr() != t2.getCanonicalType().getTypePtr()) + return true; + if (!loplugin::isOkToRemoveArithmeticCast(compiler.getASTContext(), t1, t2, + cxxFunctionalCastExpr->getSubExpr())) + { + return true; + } + if (m_Seen.insert(cxxFunctionalCastExpr->getExprLoc()).second) + { + if (suppressWarningAt(cxxFunctionalCastExpr->getBeginLoc())) + { + return true; + } + report(DiagnosticsEngine::Warning, "redundant functional cast from %0 to %1", + cxxFunctionalCastExpr->getExprLoc()) + << t2 << t1 << cxxFunctionalCastExpr->getSourceRange(); + } + return true; + } + + /* Check for the creation of unnecessary temporaries when calling a method that takes a param by const & */ + bool VisitCallExpr(CallExpr const* callExpr) + { + if (ignoreLocation(callExpr)) + return true; + const FunctionDecl* functionDecl; + if (isa(callExpr)) + functionDecl = dyn_cast(callExpr)->getMethodDecl(); + else + functionDecl = callExpr->getDirectCallee(); + if (!functionDecl) + return true; + + unsigned len = std::min(callExpr->getNumArgs(), functionDecl->getNumParams()); + for (unsigned i = 0; i < len; ++i) + { + // check if param is const& + auto param = functionDecl->getParamDecl(i); + auto lvalueType = param->getType()->getAs(); + if (!lvalueType) + continue; + if (!lvalueType->getPointeeType().isConstQualified()) + continue; + auto paramClassOrStructType = lvalueType->getPointeeType()->getAs(); + if (!paramClassOrStructType) + continue; + // check for temporary and functional cast in argument expression + auto arg = callExpr->getArg(i)->IgnoreImpCasts(); + auto materializeTemporaryExpr = dyn_cast(arg); + if (!materializeTemporaryExpr) + continue; + auto functionalCast = dyn_cast( + materializeTemporaryExpr->getSubExpr()->IgnoreImpCasts()); + if (!functionalCast) + continue; + auto const t1 = functionalCast->getTypeAsWritten(); + auto const t2 = compat::getSubExprAsWritten(functionalCast)->getType(); + if (t1.getCanonicalType().getTypePtr() != t2.getCanonicalType().getTypePtr()) + continue; + // Check that the underlying expression is of the same class/struct type as the param i.e. that we are not instantiating + // something useful + if (t1.getCanonicalType().getTypePtr() != paramClassOrStructType) + continue; + // Don't warn about (necessary) cast from braced-init-list in non-deduced contexts: + if (lvalueType->getPointeeType()->getAs() != nullptr + && loplugin::TypeCheck(t1).ClassOrStruct("initializer_list").StdNamespace() + && isa(compat::getSubExprAsWritten(functionalCast))) + { + continue; + } + + if (m_Seen.insert(arg->getExprLoc()).second) + { + report(DiagnosticsEngine::Warning, "redundant functional cast from %0 to %1", + arg->getExprLoc()) + << t2 << t1 << arg->getSourceRange(); + report(DiagnosticsEngine::Note, "in call to method here", param->getLocation()) + << param->getSourceRange(); + } + } + return true; + } + + /* Check for the creation of unnecessary temporaries when calling a constructor that takes a param by const & */ + bool VisitCXXConstructExpr(CXXConstructExpr const* callExpr) + { + if (ignoreLocation(callExpr)) + return true; + const CXXConstructorDecl* functionDecl = callExpr->getConstructor(); + + unsigned len = std::min(callExpr->getNumArgs(), functionDecl->getNumParams()); + for (unsigned i = 0; i < len; ++i) + { + // check if param is const& + auto param = functionDecl->getParamDecl(i); + auto rvalueType = param->getType()->getAs(); + if (!rvalueType) + { + auto lvalueType = param->getType()->getAs(); + if (!lvalueType) + continue; + if (!lvalueType->getPointeeType().isConstQualified()) + continue; + } + auto valueType = param->getType()->getAs(); + auto paramClassOrStructType = valueType->getPointeeType()->getAs(); + if (!paramClassOrStructType) + continue; + // check for temporary and functional cast in argument expression + auto arg = compat::IgnoreParenImplicit(callExpr->getArg(i)); + auto functionalCast = dyn_cast(arg); + if (!functionalCast) + continue; + auto const t1 = functionalCast->getTypeAsWritten(); + auto const t2 = compat::getSubExprAsWritten(functionalCast)->getType(); + if (t1.getCanonicalType().getTypePtr() != t2.getCanonicalType().getTypePtr()) + continue; + // Check that the underlying expression is of the same class/struct type as the param i.e. that we are not instantiating + // something useful + if (t1.getCanonicalType().getTypePtr() != paramClassOrStructType) + continue; + if (rvalueType) + { + // constructing a temporary to pass to a && argument is fine. But we will see that in the VisitFunctionalCast + // method below and generate a warning. And we don't have enough context there to determine that we're + // doing the wrong thing. So add the expression to the m_Seen list here to prevent that warning. + m_Seen.insert(functionalCast->getExprLoc()); + continue; + } + + if (m_Seen.insert(arg->getExprLoc()).second) + { + if (suppressWarningAt(arg->getBeginLoc())) + { + continue; + } + report(DiagnosticsEngine::Warning, + "redundant functional cast from %0 to %1 in construct expression", + arg->getExprLoc()) + << t2 << t1 << arg->getSourceRange(); + report(DiagnosticsEngine::Note, "in call to method here", param->getLocation()) + << param->getSourceRange(); + } + } + return true; + } + + // Find redundant cast to std::function, where clang reports + // two different types for the inner and outer + bool isRedundantStdFunctionCast(CXXFunctionalCastExpr const* expr) + { + bool deduced = false; + QualType target; + auto const written = expr->getTypeAsWritten(); + if (auto const t1 = written->getAs()) + { + auto const decl = t1->getTemplateName().getAsTemplateDecl(); + if (!decl) + { + return false; + } + if (!loplugin::DeclCheck(decl->getTemplatedDecl()) + .ClassOrStruct("function") + .StdNamespace()) + { + return false; + } + deduced = true; + } + else if (auto const t2 = written->getAs()) + { + auto const decl = t2->getTemplateName().getAsTemplateDecl(); + if (!decl) + { + return false; + } + if (!loplugin::DeclCheck(decl->getTemplatedDecl()) + .ClassOrStruct("function") + .StdNamespace()) + { + return false; + } + if (t2->getNumArgs() != 1) + { + if (isDebugMode()) + { + report(DiagnosticsEngine::Fatal, + "TODO: unexpected std::function with %0 template arguments", + expr->getExprLoc()) + << t2->getNumArgs() << expr->getSourceRange(); + } + return false; + } + if (t2->getArg(0).getKind() != TemplateArgument::Type) + { + if (isDebugMode()) + { + report(DiagnosticsEngine::Fatal, + "TODO: unexpected std::function with non-type template argument", + expr->getExprLoc()) + << expr->getSourceRange(); + } + return false; + } + target = t2->getArg(0).getAsType(); + } + else + { + return false; + } + auto cxxConstruct + = dyn_cast(compat::IgnoreParenImplicit(expr->getSubExpr())); + if (!cxxConstruct) + return false; + auto const lambda + = dyn_cast(compat::IgnoreParenImplicit(cxxConstruct->getArg(0))); + if (!lambda) + return false; + if (deduced) + // std::function([...](Args)->Ret{...}) should always be redundant: + return true; + auto const decl = lambda->getCallOperator(); + std::vector args; + for (unsigned i = 0; i != decl->getNumParams(); ++i) + { + args.push_back(decl->getParamDecl(i)->getType()); + } + auto const source + = compiler.getASTContext().getFunctionType(decl->getReturnType(), args, {}); + // std::function([...](Args2)->Ret2{...}) is redundant if target Ret1(Args1) + // matches source Ret2(Args2): + return target.getCanonicalType() == source.getCanonicalType(); + } + + bool VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const* expr) + { + if (ignoreLocation(expr)) + return true; + // specifying the name for an init-list is necessary sometimes + if (isa(compat::IgnoreParenImplicit(expr->getSubExpr()))) + return true; + if (isa(compat::IgnoreParenImplicit(expr->getSubExpr()))) + return true; + auto const t1 = expr->getTypeAsWritten(); + auto const t2 = compat::getSubExprAsWritten(expr)->getType(); + if (!(t1.getCanonicalType().getTypePtr() == t2.getCanonicalType().getTypePtr() + || isRedundantStdFunctionCast(expr))) + { + return true; + } + // (a) we do a lot of int/sal_Int32 kind of casts which might be platform necessary? + // (b) we do bool/bool casts in unit tests to avoid one of the other plugins + // so just ignore this kind of thing for now + if (const auto* BT = dyn_cast(t1->getUnqualifiedDesugaredType())) + { + auto k = BT->getKind(); + if (k == BuiltinType::Double || k == BuiltinType::Float + || (k >= BuiltinType::Bool && k <= BuiltinType::Int128)) + return true; + } + if (const auto* BT = dyn_cast(t2->getUnqualifiedDesugaredType())) + { + auto k = BT->getKind(); + if (k == BuiltinType::Double || k == BuiltinType::Float + || (k >= BuiltinType::Bool && k <= BuiltinType::Int128)) + return true; + } + auto tc = loplugin::TypeCheck(t1); + if (tc.Typedef("sal_Int32").GlobalNamespace()) + return true; + + if (m_Seen.insert(expr->getExprLoc()).second) + { + if (suppressWarningAt(expr->getBeginLoc())) + { + return true; + } + report(DiagnosticsEngine::Warning, "redundant functional cast from %0 to %1", + expr->getExprLoc()) + << t2 << t1 << expr->getSourceRange(); + } + return true; + } + + bool preRun() override + { + if (!compiler.getLangOpts().CPlusPlus) + return false; + return true; + } + + void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + std::unordered_set m_Seen; +}; + +static loplugin::Plugin::Registration redundantfcast("redundantfcast"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/redundantinline.cxx b/compilerplugins/clang/redundantinline.cxx new file mode 100644 index 000000000..1172dfec3 --- /dev/null +++ b/compilerplugins/clang/redundantinline.cxx @@ -0,0 +1,177 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include + +#include "plugin.hxx" + +namespace { + +class RedundantInline: + public loplugin::FilteringRewritePlugin +{ +public: + explicit RedundantInline(loplugin::InstantiationData const & data): + FilteringRewritePlugin(data) {} + + void run() override { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitFunctionDecl(FunctionDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + if (!decl->isInlineSpecified()) { + return true; + } + handleImplicitInline(decl) || handleNonExternalLinkage(decl); + return true; + } + +private: + bool removeInline(FunctionDecl const * decl, SourceLocation * inlineLoc) { + assert(inlineLoc != nullptr); + assert(inlineLoc->isInvalid()); + unsigned n = {}; // avoid -Werror=maybe-uninitialized + auto end = Lexer::getLocForEndOfToken( + compiler.getSourceManager().getExpansionLoc(decl->getEndLoc()), 0, + compiler.getSourceManager(), compiler.getLangOpts()); + assert(end.isValid()); + for (auto loc = compiler.getSourceManager().getExpansionLoc( + decl->getBeginLoc()); + loc != end; loc = loc.getLocWithOffset(std::max(n, 1))) + { + n = Lexer::MeasureTokenLength( + loc, compiler.getSourceManager(), compiler.getLangOpts()); + StringRef s(compiler.getSourceManager().getCharacterData(loc), n); + //TODO: see compilerplugins/clang/override.cxx: + if (s.startswith("\\\n")) { + s = s.drop_front(2); + } + if (s == "inline") { + if (!compiler.getSourceManager().isMacroArgExpansion(loc)) { + *inlineLoc = loc; + } + break; + } else if (s == "#") { + // Hard to pick the right 'inline' in code like + // + // #if 1 + // static + // #else + // inline + // #endif + // inline void f() {} + // + // so just give up once a preprocessing directive is seen: + break; + } + } + if (rewriter != nullptr && inlineLoc->isValid()) { + for (auto loc = inlineLoc->getLocWithOffset( + std::max(n, 1));;) + { + assert(loc != end); + unsigned n2 = Lexer::MeasureTokenLength( + loc, compiler.getSourceManager(), compiler.getLangOpts()); + StringRef s( + compiler.getSourceManager().getCharacterData(loc), n2); + //TODO: see compilerplugins/clang/override.cxx: + if (s.startswith("\\\n")) { + s = s.drop_front(2); + } + if (!s.empty()) { + break; + } + n2 = std::max(n2, 1); + n += n2; + loc = loc.getLocWithOffset(n2); + } + if (removeText(*inlineLoc, n, RewriteOptions(RemoveLineIfEmpty))) { + return true; + } + } + return false; + } + + SourceLocation unwindTo(SourceLocation const & loc, StringRef name) { + if (!loc.isMacroID()) { + return SourceLocation(); + } + auto l = compiler.getSourceManager().getImmediateMacroCallerLoc(loc); + return + (Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()) + == name) + ? l : unwindTo(l, name); + } + + bool isInMacroExpansion(FunctionDecl const * decl, StringRef name) { + auto loc = unwindTo(decl->getBeginLoc(), name); + return loc.isValid() && loc == unwindTo(decl->getEndLoc(), name); + } + + bool handleImplicitInline(FunctionDecl const * decl) { + if (!(decl->doesThisDeclarationHaveABody() || decl->isExplicitlyDefaulted()) + || !(decl->getLexicalDeclContext()->isRecord() || decl->isConstexpr())) + { + return false; + } + if (isInMacroExpansion(decl, "Q_OBJECT")) { + return true; + } + SourceLocation inlineLoc; + if (!removeInline(decl, &inlineLoc)) { + report( + DiagnosticsEngine::Warning, + "function definition redundantly declared 'inline'", + inlineLoc.isValid() ? inlineLoc : decl->getBeginLoc()) + << decl->getSourceRange(); + } + return true; + } + + bool handleNonExternalLinkage(FunctionDecl const * decl) { + if (decl->getLinkageInternal() >= ModuleLinkage) { + return false; + } + if (!compiler.getSourceManager().isInMainFile(decl->getLocation())) { + // There *may* be benefit to "static inline" in include files (esp. in C code, where an + // inline function with external linkage still requires an external definition), so + // just ignore those for now: + return true; + } + if (isInMacroExpansion(decl, "G_DEFINE_TYPE") + || isInMacroExpansion(decl, "G_DEFINE_TYPE_WITH_CODE") + || isInMacroExpansion(decl, "G_DEFINE_TYPE_WITH_PRIVATE")) + { + return true; + } + SourceLocation inlineLoc; + if (!removeInline(decl, &inlineLoc)) { + report( + DiagnosticsEngine::Warning, + "function has no external linkage but is explicitly declared 'inline'", + inlineLoc.isValid() ? inlineLoc : decl->getBeginLoc()) + << decl->getSourceRange(); + } + return true; + } +}; + +loplugin::Plugin::Registration redundantinline("redundantinline"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/redundantpointerops.cxx b/compilerplugins/clang/redundantpointerops.cxx new file mode 100644 index 000000000..caf6d4741 --- /dev/null +++ b/compilerplugins/clang/redundantpointerops.cxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include + +#include "check.hxx" +#include "plugin.hxx" + +/** + * Look for: + * (&x)->y + * which can be transformed to: + * x.y + * And + * &*x + * which can be: + * x + * + * @TODO + * (*x).y + * which can be: + * x->y + */ + +namespace { + +class RedundantPointerOps: + public loplugin::FilteringPlugin +{ +public: + explicit RedundantPointerOps(loplugin::InstantiationData const & data): FilteringPlugin(data) {} + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitFunctionDecl(FunctionDecl const *); + bool VisitMemberExpr(MemberExpr const *); + bool VisitUnaryOperator(UnaryOperator const *); +}; + +bool RedundantPointerOps::VisitFunctionDecl(FunctionDecl const * functionDecl) +{ + if (ignoreLocation(functionDecl)) + return true; +// if (functionDecl->getIdentifier() && functionDecl->getName() == "function6b") +// functionDecl->dump(); + return true; +} + +bool RedundantPointerOps::VisitMemberExpr(MemberExpr const * memberExpr) +{ + if (ignoreLocation(memberExpr)) + return true; + if (memberExpr->getBeginLoc().isMacroID()) + return true; + auto base = memberExpr->getBase()->IgnoreParenImpCasts(); + //parentStmt(parentStmt(memberExpr))->dump(); + if (memberExpr->isArrow()) + { + if (auto unaryOp = dyn_cast(base)) + { + if (unaryOp->getOpcode() == UO_AddrOf) + report( + DiagnosticsEngine::Warning, + "'&' followed by '->' operating on %0, rather use '.'", + memberExpr->getBeginLoc()) + << memberExpr->getBase()->getType()->getPointeeType() + << memberExpr->getSourceRange(); + + } + else if (auto operatorCallExpr = dyn_cast(base)) + { + if (operatorCallExpr->getOperator() == OO_Amp) + report( + DiagnosticsEngine::Warning, + "'&' followed by '->' operating on %0, rather use '.'", + memberExpr->getBeginLoc()) + << memberExpr->getBase()->getType()->getPointeeType() + << memberExpr->getSourceRange(); + + } + else if (auto cxxMemberCallExpr = dyn_cast(base)) + { + auto methodDecl = cxxMemberCallExpr->getMethodDecl(); + if (methodDecl->getIdentifier() && methodDecl->getName() == "get") + { + auto const e = cxxMemberCallExpr->getImplicitObjectArgument(); + if (loplugin::isSmartPointerType(e)) + report( + DiagnosticsEngine::Warning, + "'get()' followed by '->' operating on %0, just use '->'", + memberExpr->getBeginLoc()) + << e->IgnoreImpCasts()->getType().getLocalUnqualifiedType() + << memberExpr->getSourceRange(); + } + } + } +// else +// { +// if (auto unaryOp = dyn_cast(base)) +// { +// if (unaryOp->getOpcode() == UO_Deref) +// report( +// DiagnosticsEngine::Warning, "'*' followed by '.', rather use '->'", +// memberExpr->getLocStart()) +// << memberExpr->getSourceRange(); +// +// } +// } + return true; +} + +bool RedundantPointerOps::VisitUnaryOperator(UnaryOperator const * unaryOperator) +{ + if (ignoreLocation(unaryOperator)) + return true; + if (unaryOperator->getBeginLoc().isMacroID()) + return true; + if (unaryOperator->getOpcode() != UO_Deref) + return true; + auto subExpr = unaryOperator->getSubExpr()->IgnoreParenImpCasts(); + auto innerOp = dyn_cast(subExpr); + if (innerOp && innerOp->getOpcode() == UO_AddrOf) + report( + DiagnosticsEngine::Warning, "'&' followed by '*' operating on %0, rather use '.'", + unaryOperator->getBeginLoc()) + << innerOp->getSubExpr()->getType() << unaryOperator->getSourceRange(); + if (auto cxxMemberCallExpr = dyn_cast(subExpr)) + { + auto methodDecl = cxxMemberCallExpr->getMethodDecl(); + if (methodDecl->getIdentifier() && methodDecl->getName() == "get") + { + auto const e = cxxMemberCallExpr->getImplicitObjectArgument(); + if (loplugin::isSmartPointerType(e)) + report( + DiagnosticsEngine::Warning, + "'*' followed by '.get()' operating on %0, just use '*'", + unaryOperator->getBeginLoc()) + << e->IgnoreImpCasts()->getType().getLocalUnqualifiedType() + << unaryOperator->getSourceRange(); + } + } + return true; +} + +loplugin::Plugin::Registration< RedundantPointerOps > redundantpointerops("redundantpointerops"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/redundantstatic.cxx b/compilerplugins/clang/redundantstatic.cxx new file mode 100644 index 000000000..40f6ab45f --- /dev/null +++ b/compilerplugins/clang/redundantstatic.cxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "plugin.hxx" + +/* +This is a compile check. + +Warns about functions with static keyword in an unnamed namespace. +*/ + +namespace loplugin +{ + +class RedundantStatic + : public loplugin::FilteringPlugin + { + public: + explicit RedundantStatic( const InstantiationData& data ); + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + + virtual void run() override; + bool VisitFunctionDecl( const FunctionDecl* func ); + + bool VisitVarDecl(VarDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + if (!decl->isFileVarDecl() || decl->isStaticDataMember()) { + return true; + } + if (decl->getStorageClass() != SC_Static) { + return true; + } + if (decl->isInAnonymousNamespace()) { + auto loc = decl->getBeginLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(loc)) { + loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc); + } + if (compiler.getSourceManager().isMacroBodyExpansion(loc)) { + auto const name = Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()); + if (name == "CPPUNIT_TEST_SUITE_REGISTRATION" + || name == "CPPUNIT_TEST_SUITE_NAMED_REGISTRATION") + { + // Those macros contain a `static`, but are often used in an unnamed + // namespace, so filter them out: + return true; + } + } + report( + DiagnosticsEngine::Warning, "redundant 'static' keyword in unnamed namespace", + decl->getLocation()) + << decl->getSourceRange(); + return true; + } + if (decl->isInline()) { + return true; + } + if (!loplugin::TypeCheck(decl->getType()).ConstNonVolatile()) { + return true; + } + report( + DiagnosticsEngine::Warning, + "non-inline variable of non-volatile const-qualified type is redundantly marked as" + " 'static'", + decl->getLocation()) + << decl->getSourceRange(); + return true; + } + }; + +RedundantStatic::RedundantStatic( const InstantiationData& data ) + : FilteringPlugin( data ) + { + } + +void RedundantStatic::run() + { + if (preRun()) { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + } + + +bool RedundantStatic::VisitFunctionDecl( const FunctionDecl* func ) + + { + if( ignoreLocation( func ) ) + return true; + if( func -> isInAnonymousNamespace () ) + { + if ( !isa(func) && !func->isInExternCContext() ) + { + if(func-> getStorageClass() == SC_Static) + { + report( DiagnosticsEngine::Warning, + "redundant 'static' keyword in unnamed namespace", + func->getBeginLoc()); + } + } + } + + return true; + } + +// Register the plugin action with the LO plugin handling. +static Plugin::Registration< RedundantStatic > redundantstatic("redundantstatic"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/refcounting.cxx b/compilerplugins/clang/refcounting.cxx new file mode 100644 index 000000000..61204b67a --- /dev/null +++ b/compilerplugins/clang/refcounting.cxx @@ -0,0 +1,812 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +#include "check.hxx" +#include "plugin.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" + +/** + +If you have: + + class Foo : public css::foo::XBaa { + }; + +Then XBaa has acquire and release methods inherited from XInterface. +These are hard lifecycle controls. + +If you see another class: + + class Baz { + Foo aFooMember; + }; + +this is a bug =) since aFooMember assumes heap allocated lifecycle and +not delete on last 'release'. + +*/ + +namespace { + +class RefCounting: + public loplugin::FilteringPlugin +{ +public: + explicit RefCounting(loplugin::InstantiationData const & data): FilteringPlugin(data) + {} + + virtual bool preRun() override { return true; } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitFieldDecl(const FieldDecl *); + bool VisitVarDecl(const VarDecl *); + bool VisitFunctionDecl(const FunctionDecl *); + bool VisitTypeLoc(clang::TypeLoc typeLoc); + bool VisitCXXDeleteExpr(const CXXDeleteExpr *); + bool VisitBinaryOperator(const BinaryOperator *); + bool VisitReturnStmt(const ReturnStmt *); + + // Creation of temporaries with one argument are represented by + // CXXFunctionalCastExpr, while any other number of arguments are + // represented by CXXTemporaryObjectExpr: + bool VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr const * expr) + { return visitTemporaryObjectExpr(expr); } + bool VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const * expr) + { return visitTemporaryObjectExpr(expr); } + +private: + void checkUnoReference(QualType qt, const Decl* decl, + const RecordDecl* parent, const std::string& rDeclName); + + bool visitTemporaryObjectExpr(Expr const * expr); + bool isCastingReference(const Expr* expr); +}; + +bool containsXInterfaceSubclass(const clang::Type* pType0); + +bool containsXInterfaceSubclass(const QualType& qType) { + return containsXInterfaceSubclass(qType.getTypePtr()); +} + +bool containsXInterfaceSubclass(const clang::Type* pType0) { + if (!pType0) + return false; + const clang::Type* pType = pType0->getUnqualifiedDesugaredType(); + if (!pType) + return false; + const CXXRecordDecl* pRecordDecl = pType->getAsCXXRecordDecl(); + if (pRecordDecl) { + pRecordDecl = pRecordDecl->getCanonicalDecl(); + // these classes override acquire/release and forwards to its parent + if (loplugin::isDerivedFrom(pRecordDecl, [](Decl const * decl) -> bool { return bool(loplugin::DeclCheck(decl).Class("ListenerMultiplexerBase").GlobalNamespace()); })) { // module UnoTools + return false; + } + if (loplugin::isDerivedFrom(pRecordDecl, [](Decl const * decl) -> bool { return bool(loplugin::DeclCheck(decl).Class("GridEventForwarder").Namespace("toolkit").GlobalNamespace()); })) { // module toolkit + return false; + } + if (loplugin::isDerivedFrom(pRecordDecl, [](Decl const * decl) -> bool { return bool(loplugin::DeclCheck(decl).Class("OWeakSubObject").GlobalNamespace()); })) { // module svx + return false; + } + if (loplugin::isDerivedFrom(pRecordDecl, [](Decl const * decl) -> bool { return bool(loplugin::DeclCheck(decl).Class("OSbaWeakSubObject").Namespace("dbaui").GlobalNamespace()); })) { // module dbaccess + return false; + } + // FIXME This class has private operator new, and I cannot figure out how it can be dynamically instantiated + if (loplugin::isDerivedFrom(pRecordDecl, [](Decl const * decl) -> bool { return bool(loplugin::DeclCheck(decl).Class("XPropertyList").GlobalNamespace()); })) { // module svx + return false; + } + // tdf#114596 + if (loplugin::isDerivedFrom(pRecordDecl, [](Decl const * decl) -> bool { return bool(loplugin::DeclCheck(decl).Class("OBookmarkContainer").Namespace("dbaccess").GlobalNamespace()); })) { // module dbaccess + return false; + } + + // tdf#114596 + if (loplugin::isDerivedFrom(pRecordDecl, [](Decl const * decl) -> bool { return bool(loplugin::DeclCheck(decl).Class("OCollection").Namespace("dbaccess").GlobalNamespace()); })) { // module dbaccess + return false; + } + } + if (pRecordDecl) { + const ClassTemplateSpecializationDecl* pTemplate = dyn_cast(pRecordDecl); + if (pTemplate) { + // Probably good templates: + loplugin::DeclCheck dc(pTemplate); + if ((dc.Struct("FindUnoInstanceHint").AnonymousNamespace() + .GlobalNamespace()) + || (dc.Class("OMultiInstanceAutoRegistration").Namespace("abp") + .GlobalNamespace()) + || (dc.Class("Reference").Namespace("uno").Namespace("star") + .Namespace("sun").Namespace("com").GlobalNamespace()) + || (dc.Class("WeakReference").Namespace("uno").Namespace("star") + .Namespace("sun").Namespace("com").GlobalNamespace()) + || (dc.Class("Sequence").Namespace("uno").Namespace("star") + .Namespace("sun").Namespace("com").GlobalNamespace()) + || (dc.Class("WeakCppRef").Namespace("accessibility") + .GlobalNamespace()) + || (dc.Class("OAutoRegistration").Namespace("dba") + .GlobalNamespace()) + || (dc.Class("OMultiInstanceAutoRegistration").Namespace("dbp") + .GlobalNamespace()) + || (dc.Class("OMultiInstanceAutoRegistration") + .Namespace("dbaui").GlobalNamespace()) + || (dc.Class("OMultiInstanceAutoRegistration") + .Namespace("dbaxml").GlobalNamespace()) + || (dc.Struct("ReferenceEqual").Namespace("io_acceptor") + .GlobalNamespace()) + || (dc.Struct("ReferenceHash").Namespace("io_acceptor") + .GlobalNamespace()) + || (dc.Class("OAutoRegistration").Namespace("comphelper") + .GlobalNamespace()) + || dc.Class("WeakBag").Namespace("comphelper").GlobalNamespace() + || (dc.Struct("class_").Namespace("service_decl") + .Namespace("comphelper").GlobalNamespace()) + || (dc.Struct("vba_service_class_").Namespace("service_decl") + .Namespace("comphelper").GlobalNamespace()) + || (dc.Struct("inheritingClass_").Namespace("service_decl") + .Namespace("comphelper").GlobalNamespace()) + || (dc.Class("OAutoRegistration").Namespace("module") + .Namespace("comphelper").GlobalNamespace()) + || (dc.Class("mem_fun1_t").Namespace("comphelper") + .GlobalNamespace()) + || (dc.Class("OSimpleListenerContainer").Namespace("comphelper") + .GlobalNamespace()) + || (dc.Class("OAutoRegistration").Namespace("dbmm") + .GlobalNamespace()) + || (dc.Class("OAutoRegistration").Namespace("pcr") + .GlobalNamespace()) + || (dc.Class("ComponentMethodGuard").Namespace("logging") + .GlobalNamespace()) + || (dc.Class("OAutoRegistration").Namespace("logging") + .GlobalNamespace()) + || dc.Class("Reference").Namespace("rtl").GlobalNamespace() + || (dc.Class("OAutoRegistration").Namespace("sdbtools") + .GlobalNamespace()) + || (dc.Struct("ReferenceEqual").Namespace("stoc_connector") + .GlobalNamespace()) + || (dc.Struct("ReferenceHash").Namespace("stoc_connector") + .GlobalNamespace()) + || dc.Class("mem_fun_t").StdNamespace() + || dc.Class("mem_fun1_t").StdNamespace() + || dc.Class("SwIterator").GlobalNamespace() + || (dc.Class("SharedUNOComponent").Namespace("utl") + .GlobalNamespace()) + || (dc.Class("OAutoRegistration").Namespace("utl") + .GlobalNamespace()) + || (dc.Class("DeleteUnoReferenceOnDeinit").Namespace("vcl") + .GlobalNamespace()) + || (dc.Struct("OInterfaceCompare").Namespace("xmloff") + .GlobalNamespace())) + { + return false; + } + } + } + if (pType->isPointerType()) { + // ignore + return false; + } else if (pType->isArrayType()) { + const clang::ArrayType* pArrayType = dyn_cast(pType); + QualType elementType = pArrayType->getElementType(); + return containsXInterfaceSubclass(elementType); + } else { + return loplugin::isDerivedFrom(pRecordDecl, [](Decl const * decl) -> bool { return bool(loplugin::DeclCheck(decl).Class("XInterface").Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()); }); + } +} + +bool containsOWeakObjectSubclass(const clang::Type* pType0); + +bool containsOWeakObjectSubclass(const QualType& qType) { + return containsOWeakObjectSubclass(qType.getTypePtr()); +} + +bool containsOWeakObjectSubclass(const clang::Type* pType0) { + if (!pType0) + return false; + if (pType0->isDependentType()) { + return false; + } + const clang::Type* pType = pType0->getUnqualifiedDesugaredType(); + if (!pType) + return false; + const CXXRecordDecl* pRecordDecl = pType->getAsCXXRecordDecl(); + if (pRecordDecl) { + // because dbaccess just has to be special... + loplugin::DeclCheck dc(pRecordDecl); + if (dc.Class("DocumentEvents").Namespace("dbaccess") + .GlobalNamespace() || + dc.Class("OBookmarkContainer").Namespace("dbaccess") + .GlobalNamespace()) + return false; + // TODO not sure about these ones, just avoiding dbaccess in general for now + if (dc.Class("SbaXPropertiesChangeMultiplexer").Namespace("dbaui").GlobalNamespace() || + dc.Class("SbaXSubmitMultiplexer").Namespace("dbaui").GlobalNamespace() || + dc.Class("SbaXResetMultiplexer").Namespace("dbaui").GlobalNamespace() || + dc.Class("SbaXPropertyChangeMultiplexer").Namespace("dbaui").GlobalNamespace() || + dc.Class("SbaXSQLErrorMultiplexer").Namespace("dbaui").GlobalNamespace() || + dc.Class("SbaXParameterMultiplexer").Namespace("dbaui").GlobalNamespace() || + dc.Class("SbaXRowSetApproveMultiplexer").Namespace("dbaui").GlobalNamespace() || + dc.Class("SbaXRowSetMultiplexer").Namespace("dbaui").GlobalNamespace() || + dc.Class("SbaXLoadMultiplexer").Namespace("dbaui").GlobalNamespace() || + dc.Class("SbaXVetoableChangeMultiplexer").Namespace("dbaui").GlobalNamespace()) + return false; + // slideshow playing games here + if (dc.Class("SlideView").AnonymousNamespace().Namespace("internal").Namespace("slideshow").GlobalNamespace()) + return false; + // svx playing acquire/release games here in OWeakSubObject + if (dc.Class("FmXUpdateMultiplexer").GlobalNamespace() || + dc.Class("FmXContainerMultiplexer").GlobalNamespace() || + dc.Class("FmXSelectionMultiplexer").GlobalNamespace() || + dc.Class("FmXGridControlMultiplexer").GlobalNamespace() || + dc.Class("FmXModifyMultiplexer").GlobalNamespace()) + return false; + } + if (pType->isPointerType()) { + // ignore + return false; + } else if (pType->isArrayType()) { + const clang::ArrayType* pArrayType = dyn_cast(pType); + QualType elementType = pArrayType->getElementType(); + return containsOWeakObjectSubclass(elementType); + } else { + return loplugin::isDerivedFrom(pRecordDecl, [](Decl const * decl) -> bool { return bool(loplugin::DeclCheck(decl).Class("OWeakObject").Namespace("cppu").GlobalNamespace()); }); + } +} + +bool containsSvRefBaseSubclass(const clang::Type* pType0) { + if (!pType0) + return false; + const clang::Type* pType = pType0->getUnqualifiedDesugaredType(); + if (!pType) + return false; + const CXXRecordDecl* pRecordDecl = pType->getAsCXXRecordDecl(); + if (pRecordDecl) { + pRecordDecl = pRecordDecl->getCanonicalDecl(); + } + if (pRecordDecl) { + const ClassTemplateSpecializationDecl* pTemplate = dyn_cast(pRecordDecl); + if (pTemplate) { + if (loplugin::DeclCheck(pTemplate).Class("SvRef") + .Namespace("tools").GlobalNamespace()) + { + return false; + } + for(unsigned i=0; igetTemplateArgs().size(); ++i) { + const TemplateArgument& rArg = pTemplate->getTemplateArgs()[i]; + if (rArg.getKind() == TemplateArgument::ArgKind::Type && + containsSvRefBaseSubclass(rArg.getAsType().getTypePtr())) + { + return true; + } + } + } + } + if (pType->isPointerType()) { + // ignore + return false; + } else if (pType->isArrayType()) { + const clang::ArrayType* pArrayType = dyn_cast(pType); + QualType elementType = pArrayType->getElementType(); + return containsSvRefBaseSubclass(elementType.getTypePtr()); + } else { + return loplugin::isDerivedFrom(pRecordDecl, [](Decl const * decl) -> bool { return bool(loplugin::DeclCheck(decl).Class("SvRefBase").Namespace("tools").GlobalNamespace()); }); + } +} + +bool containsSalhelperReferenceObjectSubclass(const clang::Type* pType0) { + if (!pType0) + return false; + const clang::Type* pType = pType0->getUnqualifiedDesugaredType(); + if (!pType) + return false; + const CXXRecordDecl* pRecordDecl = pType->getAsCXXRecordDecl(); + if (pRecordDecl) { + pRecordDecl = pRecordDecl->getCanonicalDecl(); + } + if (pRecordDecl) { + // for performance reasons we sometimes allocate temporaries on the stack + if (loplugin::DeclCheck(pRecordDecl).Struct("ScSheetLimits").GlobalNamespace()) + return false; + + // the calc excel filter likes storing lots of classes either by reference or by value + if (loplugin::isDerivedFrom(pRecordDecl, + [](Decl const * decl) -> bool + { + return + bool(loplugin::DeclCheck(decl).Class("XclExpRecordBase").GlobalNamespace()) + || bool(loplugin::DeclCheck(decl).Class("XclImpChLineFormat").GlobalNamespace()); + })) + return false; + + const ClassTemplateSpecializationDecl* pTemplate = dyn_cast(pRecordDecl); + if (pTemplate) { + auto const dc = loplugin::DeclCheck(pTemplate); + if (dc.Class("Reference").Namespace("rtl").GlobalNamespace() + || (dc.Class("OStoreHandle").AnonymousNamespace().Namespace("store") + .GlobalNamespace())) + { + return false; + } + for(unsigned i=0; igetTemplateArgs().size(); ++i) { + const TemplateArgument& rArg = pTemplate->getTemplateArgs()[i]; + if (rArg.getKind() == TemplateArgument::ArgKind::Type && + containsSalhelperReferenceObjectSubclass(rArg.getAsType().getTypePtr())) + { + return true; + } + } + } + } + if (pType->isPointerType()) { + // ignore + return false; + } else if (pType->isArrayType()) { + const clang::ArrayType* pArrayType = dyn_cast(pType); + QualType elementType = pArrayType->getElementType(); + return containsSalhelperReferenceObjectSubclass(elementType.getTypePtr()); + } else { + return loplugin::isDerivedFrom(pRecordDecl, [](Decl const * decl) -> bool { return bool(loplugin::DeclCheck(decl).Class("SimpleReferenceObject").Namespace("salhelper").GlobalNamespace()); }); + } +} + +static bool containsStaticTypeMethod(const CXXRecordDecl* x) +{ + for (auto it = x->method_begin(); it != x->method_end(); ++it) { + auto i = *it; + if ( !i->isStatic() ) + continue; + auto ident = i->getIdentifier(); + if ( ident && ident->isStr("static_type") ) { + return true; + } + } + return false; +} + +void RefCounting::checkUnoReference(QualType qt, const Decl* decl, const RecordDecl* parent, const std::string& rDeclName) +{ + if (loplugin::TypeCheck(qt).Class("Reference").Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()) { + const CXXRecordDecl* pRecordDecl = qt->getAsCXXRecordDecl(); + const ClassTemplateSpecializationDecl* pTemplate = dyn_cast(pRecordDecl); + const TemplateArgument& rArg = pTemplate->getTemplateArgs()[0]; + const CXXRecordDecl* templateParam = rArg.getAsType()->getAsCXXRecordDecl()->getDefinition(); + if (templateParam && !containsStaticTypeMethod(templateParam)) { + report( + DiagnosticsEngine::Warning, + ("uno::Reference %0 with template parameter that does not" + " contain ::static_type() %1%select{|, parent is %3,}2 should" + " probably be using rtl::Reference instead"), + decl->getLocation()) + << rDeclName << qt << (parent != nullptr) + << (parent != nullptr + ? parent->getQualifiedNameAsString() : std::string()) + << decl->getSourceRange(); + } + } +} + +bool RefCounting::visitTemporaryObjectExpr(Expr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto t = expr->getType(); + if (containsSvRefBaseSubclass(t.getTypePtr())) { + report( + DiagnosticsEngine::Warning, + ("Temporary object of SvRefBase subclass %0 being directly stack" + " managed, should be managed via tools::SvRef"), + expr->getBeginLoc()) + << t.getUnqualifiedType() << expr->getSourceRange(); + } else if (containsSalhelperReferenceObjectSubclass(t.getTypePtr())) { + report( + DiagnosticsEngine::Warning, + ("Temporary object of salhelper::SimpleReferenceObject subclass %0" + " being directly stack managed, should be managed via" + " rtl::Reference"), + expr->getBeginLoc()) + << t.getUnqualifiedType() << expr->getSourceRange(); + } else if (containsXInterfaceSubclass(t)) { + report( + DiagnosticsEngine::Warning, + ("Temporary object of css::uno::XInterface subclass %0 being" + " directly stack managed, should be managed via" + " css::uno::Reference"), + expr->getBeginLoc()) + << t.getUnqualifiedType() << expr->getSourceRange(); + } else if (containsOWeakObjectSubclass(t)) { + report( + DiagnosticsEngine::Warning, + ("Temporary object of cppu::OWeakObject subclass %0 being" + " directly stack managed, should be managed via" + " css::uno::Reference"), + expr->getBeginLoc()) + << t.getUnqualifiedType() << expr->getSourceRange(); + } + return true; +} + +// check for dodgy code managing ref-counted stuff with shared_ptr or unique_ptr or similar stuff +bool RefCounting::VisitTypeLoc(clang::TypeLoc typeLoc) +{ + QualType firstTemplateParamType; + if (auto recordType = typeLoc.getType()->getUnqualifiedDesugaredType()->getAs()) { + auto const tc = loplugin::TypeCheck(recordType); + if (tc.ClassOrStruct("unique_ptr").StdNamespace() + || tc.ClassOrStruct("weak_ptr").StdNamespace() + || tc.ClassOrStruct("shared_ptr").StdNamespace() + || tc.ClassOrStruct("intrusive_ptr").Namespace("boost").GlobalNamespace()) + { + auto templateDecl = dyn_cast(recordType->getDecl()); + if (templateDecl && templateDecl->getTemplateArgs().size() > 0) + firstTemplateParamType = templateDecl->getTemplateArgs()[0].getAsType(); + } + } + if (firstTemplateParamType.isNull()) + return true; + if (containsSvRefBaseSubclass(firstTemplateParamType.getTypePtr())) + { + report( + DiagnosticsEngine::Warning, + "SvRefBase subclass %0 being managed via smart pointer, should be managed via tools::SvRef", + typeLoc.getBeginLoc()) + << firstTemplateParamType + << typeLoc.getSourceRange(); + } + if (containsSalhelperReferenceObjectSubclass(firstTemplateParamType.getTypePtr())) + { + report( + DiagnosticsEngine::Warning, + "salhelper::SimpleReferenceObject subclass %0 being managed via smart pointer, should be managed via rtl::Reference", + typeLoc.getBeginLoc()) + << firstTemplateParamType + << typeLoc.getSourceRange(); + } +// Not in general (dbaccess::DocumentEvents, dbaccess/source/core/dataaccess/databasedocument.hxx): +#if 0 + if (containsXInterfaceSubclass(firstTemplateParamType)) + { + report( + DiagnosticsEngine::Warning, + "XInterface subclass %0 being managed via smart pointer, should be managed via uno::Reference", + typeLoc.getBeginLoc()) + << firstTemplateParamType + << typeLoc.getSourceRange(); + } +#endif + if (containsOWeakObjectSubclass(firstTemplateParamType.getTypePtr())) + { + report( + DiagnosticsEngine::Warning, + "cppu::OWeakObject subclass %0 being managed via smart pointer, should be managed via rtl::Reference", + typeLoc.getBeginLoc()) + << firstTemplateParamType + << typeLoc.getSourceRange(); + } + return true; +} + +bool RefCounting::VisitCXXDeleteExpr(const CXXDeleteExpr * cxxDeleteExpr) +{ + if (ignoreLocation(cxxDeleteExpr)) + return true; + StringRef aFileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(cxxDeleteExpr->getBeginLoc())); + if (loplugin::isSamePathname(aFileName, SRCDIR "/cppuhelper/source/weak.cxx")) + return true; + + if (!cxxDeleteExpr->getArgument()) + return true; + auto argType = cxxDeleteExpr->getArgument()->getType(); + if (argType.isNull() || !argType->isPointerType()) + return true; + auto pointeeType = argType->getPointeeType(); + if (containsOWeakObjectSubclass(pointeeType)) + { + report( + DiagnosticsEngine::Warning, + "cppu::OWeakObject subclass %0 being deleted via delete, should be managed via rtl::Reference", + cxxDeleteExpr->getBeginLoc()) + << pointeeType + << cxxDeleteExpr->getSourceRange(); + } + return true; +} + +bool RefCounting::VisitFieldDecl(const FieldDecl * fieldDecl) { + if (ignoreLocation(fieldDecl)) { + return true; + } + if (fieldDecl->isBitField()) { + return true; + } + + // We can't call FieldDecl::getParent, which triggers an assertion at least with + // current trunk towards Clang 3.7 when the FieldDecl is actually an + // ObjCIvarDecl. + if (isa(fieldDecl)) { + return true; + } + + if (containsSvRefBaseSubclass(fieldDecl->getType().getTypePtr())) { + report( + DiagnosticsEngine::Warning, + "SvRefBase subclass %0 being directly heap managed, should be managed via tools::SvRef, " + ", parent is %1", + fieldDecl->getLocation()) + << fieldDecl->getType() + << fieldDecl->getParent() + << fieldDecl->getSourceRange(); + } + + if (containsSalhelperReferenceObjectSubclass(fieldDecl->getType().getTypePtr())) { + report( + DiagnosticsEngine::Warning, + "salhelper::SimpleReferenceObject subclass %0 being directly heap managed, should be managed via rtl::Reference, " + "parent is %1", + fieldDecl->getLocation()) + << fieldDecl->getType() + << fieldDecl->getParent() + << fieldDecl->getSourceRange(); + } + + auto const dc = loplugin::DeclCheck(fieldDecl->getParent()); + if ( (dc.Class("BaseReference").Namespace("uno").Namespace("star") + .Namespace("sun").Namespace("com").GlobalNamespace()) + || (dc.Class("Reference").Namespace("rtl").GlobalNamespace()) + || (dc.Union("element_alias").Namespace("detail").Namespace("cppu") + .GlobalNamespace()) + // this is playing some kind of game to avoid circular references + || (dc.Class("ResultSetDataSupplier").Namespace("ucbhelper") + .GlobalNamespace())) + { + return true; + } + + if (containsXInterfaceSubclass(fieldDecl->getType())) { + report( + DiagnosticsEngine::Warning, + "XInterface subclass %0 being directly heap managed, should be managed via uno::Reference, " + "parent is %1", + fieldDecl->getLocation()) + << fieldDecl->getType() + << fieldDecl->getParent() + << fieldDecl->getSourceRange(); + } + + if (containsOWeakObjectSubclass(fieldDecl->getType())) { + report( + DiagnosticsEngine::Warning, + "cppu::OWeakObject subclass %0 being directly heap managed, should be managed via rtl::Reference, " + "parent is %1", + fieldDecl->getLocation()) + << fieldDecl->getType() + << fieldDecl->getParent() + << fieldDecl->getSourceRange(); + } + + checkUnoReference( + fieldDecl->getType(), fieldDecl, + fieldDecl->getParent(), "field"); + + return true; +} + +bool RefCounting::VisitReturnStmt(const ReturnStmt * returnStmt) { + if (ignoreLocation(returnStmt)) { + return true; + } + + if (!returnStmt->getRetValue()) + return true; + auto cxxNewExpr = dyn_cast(returnStmt->getRetValue()->IgnoreImplicit()); + if (!cxxNewExpr) + return true; + + auto qt = returnStmt->getRetValue()->getType(); + if (!qt->isPointerType()) + return false; + qt = qt->getPointeeType(); + + if (containsOWeakObjectSubclass(qt)) { + report( + DiagnosticsEngine::Warning, + "new object of cppu::OWeakObject subclass %0 being returned via raw pointer, should be returned by via rtl::Reference", + returnStmt->getBeginLoc()) + << qt + << returnStmt->getSourceRange(); + } + + return true; +} + +bool RefCounting::VisitVarDecl(const VarDecl * varDecl) { + if (ignoreLocation(varDecl)) + return true; + + checkUnoReference(varDecl->getType(), varDecl, nullptr, "var"); + + if (isa(varDecl)) + return true; + + if (containsSvRefBaseSubclass(varDecl->getType().getTypePtr())) { + report( + DiagnosticsEngine::Warning, + "SvRefBase subclass being directly stack managed, should be managed via tools::SvRef, " + + varDecl->getType().getAsString(), + varDecl->getLocation()) + << varDecl->getSourceRange(); + } + if (containsSalhelperReferenceObjectSubclass(varDecl->getType().getTypePtr())) { + StringRef name { getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(varDecl->getLocation())) }; + // this is playing games that it believes is safe + if (loplugin::isSamePathname(name, SRCDIR "/stoc/source/security/permissions.cxx")) + return true; + report( + DiagnosticsEngine::Warning, + "salhelper::SimpleReferenceObject subclass being directly stack managed, should be managed via rtl::Reference, " + + varDecl->getType().getAsString(), + varDecl->getLocation()) + << varDecl->getSourceRange(); + } + if (containsXInterfaceSubclass(varDecl->getType())) { + report( + DiagnosticsEngine::Warning, + "XInterface subclass being directly stack managed, should be managed via uno::Reference, " + + varDecl->getType().getAsString(), + varDecl->getLocation()) + << varDecl->getSourceRange(); + } + if (containsOWeakObjectSubclass(varDecl->getType())) { + report( + DiagnosticsEngine::Warning, + "cppu::OWeakObject subclass being directly stack managed, should be managed via uno::Reference, " + + varDecl->getType().getAsString(), + varDecl->getLocation()) + << varDecl->getSourceRange(); + } + + if (varDecl->getType()->isPointerType() && varDecl->getInit()) + { + auto newExpr = dyn_cast(varDecl->getInit()->IgnoreImplicit()); + if (newExpr) + { + StringRef fileName = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(varDecl->getBeginLoc())); + if (loplugin::isSamePathname(fileName, SRCDIR "/cppuhelper/source/component_context.cxx")) + return true; + auto pointeeType = varDecl->getType()->getPointeeType(); + if (containsOWeakObjectSubclass(pointeeType)) + report( + DiagnosticsEngine::Warning, + "cppu::OWeakObject subclass %0 being managed via raw pointer, should be managed via rtl::Reference", + varDecl->getLocation()) + << pointeeType + << varDecl->getSourceRange(); + } + if (isCastingReference(varDecl->getInit())) + { + // TODO false+ code + StringRef fileName = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(varDecl->getBeginLoc())); + if (loplugin::isSamePathname(fileName, SRCDIR "/sw/source/core/unocore/unotbl.cxx")) + return true; + auto pointeeType = varDecl->getType()->getPointeeType(); + if (containsOWeakObjectSubclass(pointeeType)) + report( + DiagnosticsEngine::Warning, + "cppu::OWeakObject subclass %0 being managed via raw pointer, should be managed via rtl::Reference", + varDecl->getLocation()) + << pointeeType + << varDecl->getSourceRange(); + } + } + return true; +} + +/** + Look for code like + static_cast(makeFoo().get()); + where makeFoo() returns a Reference +*/ +bool RefCounting::isCastingReference(const Expr* expr) +{ + expr = expr->IgnoreImplicit(); + auto castExpr = dyn_cast(expr); + if (!castExpr) + return false; + auto memberCallExpr = dyn_cast(castExpr->getSubExpr()); + if (!memberCallExpr) + return false; + if (!memberCallExpr->getMethodDecl()->getIdentifier() || memberCallExpr->getMethodDecl()->getName() != "get") + return false; + QualType objectType = memberCallExpr->getImplicitObjectArgument()->getType(); + if (!loplugin::TypeCheck(objectType).Class("Reference")) + return false; + // ignore "x.get()" where x is a var + auto obj = memberCallExpr->getImplicitObjectArgument()->IgnoreImplicit(); + if (isa(obj) || isa(obj)) + return false; + // if the foo in foo().get() returns "rtl::Reference&" then the variable + // we are assigning to does not __have__ to be Reference, since the method called + // must already be holding a reference. + if (auto callExpr = dyn_cast(obj)) + { + if (auto callMethod = callExpr->getDirectCallee()) + if (callMethod->getReturnType()->isReferenceType()) + return false; + } + return true; +} + +bool RefCounting::VisitBinaryOperator(const BinaryOperator * binaryOperator) +{ + if (ignoreLocation(binaryOperator)) + return true; + if (binaryOperator->getOpcode() != BO_Assign) + return true; + if (!binaryOperator->getLHS()->getType()->isPointerType()) + return true; + + auto newExpr = dyn_cast(binaryOperator->getRHS()->IgnoreImplicit()); + if (newExpr) + { + // deliberately does not want to keep track at the allocation site + StringRef fileName = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(binaryOperator->getBeginLoc())); + if (loplugin::isSamePathname(fileName, SRCDIR "/vcl/unx/generic/dtrans/X11_selection.cxx")) + return true; + + auto pointeeType = binaryOperator->getLHS()->getType()->getPointeeType(); + if (containsOWeakObjectSubclass(pointeeType)) + { + report( + DiagnosticsEngine::Warning, + "cppu::OWeakObject subclass %0 being managed via raw pointer, should be managed via rtl::Reference", + binaryOperator->getBeginLoc()) + << pointeeType + << binaryOperator->getSourceRange(); + } + } + if (isCastingReference(binaryOperator->getRHS())) + { + auto pointeeType = binaryOperator->getLHS()->getType()->getPointeeType(); + if (containsOWeakObjectSubclass(pointeeType)) + report( + DiagnosticsEngine::Warning, + "cppu::OWeakObject subclass %0 being managed via raw pointer, should be managed via rtl::Reference", + binaryOperator->getBeginLoc()) + << pointeeType + << binaryOperator->getSourceRange(); + } + return true; +} + +bool RefCounting::VisitFunctionDecl(const FunctionDecl * functionDecl) { + if (ignoreLocation(functionDecl)) { + return true; + } + // only consider base declarations, not overridden ones, or we warn on methods that + // are overriding stuff from external libraries + const CXXMethodDecl * methodDecl = dyn_cast(functionDecl); + if (methodDecl && methodDecl->size_overridden_methods() > 0) { + return true; + } + checkUnoReference(functionDecl->getReturnType(), functionDecl, nullptr, "return"); + return true; +} + +loplugin::Plugin::Registration< RefCounting > refcounting("refcounting"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/referencecasting.cxx b/compilerplugins/clang/referencecasting.cxx new file mode 100644 index 000000000..08895f723 --- /dev/null +++ b/compilerplugins/clang/referencecasting.cxx @@ -0,0 +1,538 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include + +/* +This is a compile-time checker. + +Check for cases where we have + - two IDL interfaces A and B, + - B extends A + - we are converting a Reference to a Reference using UNO_QUERY + +This makes the code simpler and cheaper, because UNO_QUERY can be surprisingly expensive if used a lot. + +*/ + +namespace +{ +class ReferenceCasting : public loplugin::FilteringPlugin +{ +public: + explicit ReferenceCasting(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + // macros + if (fn == SRCDIR "/dbaccess/source/ui/browser/formadapter.cxx") + return false; + // UNO aggregation + if (fn == SRCDIR "/toolkit/source/controls/stdtabcontroller.cxx") + return false; + return true; + } + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitCXXConstructExpr(const CXXConstructExpr* cce); + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr* mce); + bool VisitCallExpr(const CallExpr*); + bool VisitInitListExpr(const InitListExpr*); + +private: + bool CheckForUnnecessaryGet(const Expr*, bool includeRtlReference); +}; + +static const RecordType* extractTemplateType(QualType); +static bool isDerivedFrom(const CXXRecordDecl* subtypeRecord, const CXXRecordDecl* baseRecord); + +bool ReferenceCasting::VisitInitListExpr(const InitListExpr* ile) +{ + if (ignoreLocation(ile)) + return true; + for (const Expr* expr : ile->inits()) + { + if (CheckForUnnecessaryGet(expr, /*includeRtlReference*/ true)) + { + report(DiagnosticsEngine::Warning, "unnecessary get() call", expr->getBeginLoc()) + << expr->getSourceRange(); + return true; + } + } + return true; +} +bool ReferenceCasting::VisitCXXConstructExpr(const CXXConstructExpr* cce) +{ + if (ignoreLocation(cce)) + return true; + // don't bother processing anything in the Reference.h file. Makes my life easier when debugging this. + StringRef aFileName + = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(cce->getBeginLoc())); + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/com/sun/star/uno/Reference.h")) + return true; + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/com/sun/star/uno/Reference.hxx")) + return true; + + if (cce->getNumArgs() == 0) + return true; + + // look for calls to the Reference(x, UNO_something) constructor + auto constructorClass = cce->getConstructor()->getParent(); + auto dc = loplugin::DeclCheck(constructorClass); + bool isUnoReference(dc.Class("Reference").Namespace("uno")); + bool isRtlReference(dc.Class("Reference").Namespace("rtl").GlobalNamespace()); + if (!isUnoReference && !isRtlReference) + return true; + + if (isUnoReference) + if (CheckForUnnecessaryGet(cce->getArg(0), /*includeRtlReference*/ cce->getNumArgs() == 1)) + { + report(DiagnosticsEngine::Warning, "unnecessary get() call", + cce->getArg(0)->getBeginLoc()) + << cce->getArg(0)->getSourceRange(); + return true; + } + if (isRtlReference && cce->getNumArgs() == 1) + if (CheckForUnnecessaryGet(cce->getArg(0), /*includeRtlReference*/ true)) + { + report(DiagnosticsEngine::Warning, "unnecessary get() call", + cce->getArg(0)->getBeginLoc()) + << cce->getArg(0)->getSourceRange(); + return true; + } + + if (isRtlReference) + return true; + if (isUnoReference && cce->getNumArgs() != 2) + return true; + + // ignore the up-casting constructor, which has a std::enable_if second parameter + if (isUnoReference && cce->getNumArgs() == 2 + && !isa(cce->getConstructor()->getParamDecl(1)->getType())) + return true; + + // extract the type parameter passed to the template + const RecordType* templateParamType = extractTemplateType(cce->getType()); + if (!templateParamType) + return true; + + // extract the type of the first parameter passed to the constructor + const Expr* constructorArg0 = cce->getArg(0); + if (!constructorArg0) + return true; + + // drill down the expression tree till we hit the bottom, because at the top, the type is BaseReference + QualType argType; + for (;;) + { + if (auto castExpr = dyn_cast(constructorArg0)) + { + constructorArg0 = castExpr->getSubExpr(); + continue; + } + if (auto matTempExpr = dyn_cast(constructorArg0)) + { + constructorArg0 = matTempExpr->getSubExpr(); + continue; + } + if (auto bindTempExpr = dyn_cast(constructorArg0)) + { + constructorArg0 = bindTempExpr->getSubExpr(); + continue; + } + if (auto tempObjExpr = dyn_cast(constructorArg0)) + { + constructorArg0 = tempObjExpr->getArg(0); + continue; + } + if (auto parenExpr = dyn_cast(constructorArg0)) + { + constructorArg0 = parenExpr->getSubExpr(); + continue; + } + argType = constructorArg0->getType(); + break; + } + + const RecordType* argTemplateType = extractTemplateType(argType); + if (!argTemplateType) + return true; + + CXXRecordDecl* templateParamRD = dyn_cast(templateParamType->getDecl()); + CXXRecordDecl* constructorArgRD = dyn_cast(argTemplateType->getDecl()); + + // querying for XInterface (instead of doing an upcast) has special semantics, + // to check for UNO object equivalence. + if (templateParamRD->getName() == "XInterface") + return true; + + // XShape is used in UNO aggregates in very "entertaining" ways, which means an UNO_QUERY + // can return a completely different object, e.g. see SwXShape::queryInterface + if (templateParamRD->getName() == "XShape") + return true; + + if (cce->getNumArgs() == 2) + if (auto declRefExpr = dyn_cast(cce->getArg(1))) + { + // no warning expected, used to reject null references + if (auto enumConstantDecl = dyn_cast(declRefExpr->getDecl())) + { + if (enumConstantDecl->getName() == "UNO_SET_THROW") + return true; + if (enumConstantDecl->getName() == "UNO_QUERY_THROW") + return true; + if (enumConstantDecl->getName() == "SAL_NO_ACQUIRE") + return true; + } + } + + if (constructorArgRD->Equals(templateParamRD) + || isDerivedFrom(constructorArgRD, templateParamRD)) + { + report(DiagnosticsEngine::Warning, + "the source reference is already a subtype of the destination reference, just use =", + cce->getBeginLoc()) + << cce->getSourceRange(); + } + return true; +} + +bool ReferenceCasting::VisitCXXMemberCallExpr(const CXXMemberCallExpr* mce) +{ + if (ignoreLocation(mce)) + return true; + // don't bother processing anything in the Reference.h file. Makes my life easier when debugging this. + StringRef aFileName + = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(mce->getBeginLoc())); + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/com/sun/star/uno/Reference.h")) + return true; + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/com/sun/star/uno/Reference.hxx")) + return true; + + if (mce->getNumArgs() == 0) + return true; + + // look for calls to the Reference.set(x, UNO_QUERY) constructor + auto method = mce->getMethodDecl(); + if (!method || !method->getIdentifier() || method->getName() != "set") + return true; + + auto methodRecordDecl = dyn_cast(mce->getRecordDecl()); + if (!methodRecordDecl || !methodRecordDecl->getIdentifier() + || methodRecordDecl->getName() != "Reference") + return true; + + if (CheckForUnnecessaryGet(mce->getArg(0), /*includeRtlReference*/ mce->getNumArgs() == 1)) + { + report(DiagnosticsEngine::Warning, "unnecessary get() call", mce->getArg(0)->getBeginLoc()) + << mce->getArg(0)->getSourceRange(); + return true; + } + + if (mce->getNumArgs() != 2) + return true; + + // extract the type parameter passed to the template + const RecordType* templateParamType + = dyn_cast(methodRecordDecl->getTemplateArgs()[0].getAsType()); + if (!templateParamType) + return true; + + // extract the type of the first parameter passed to the method + const Expr* arg0 = mce->getArg(0); + if (!arg0) + return true; + + // drill down the expression tree till we hit the bottom, because at the top, the type is BaseReference + QualType argType; + for (;;) + { + if (auto castExpr = dyn_cast(arg0)) + { + arg0 = castExpr->getSubExpr(); + continue; + } + if (auto matTempExpr = dyn_cast(arg0)) + { + arg0 = matTempExpr->getSubExpr(); + continue; + } + if (auto bindTempExpr = dyn_cast(arg0)) + { + arg0 = bindTempExpr->getSubExpr(); + continue; + } + if (auto tempObjExpr = dyn_cast(arg0)) + { + arg0 = tempObjExpr->getArg(0); + continue; + } + if (auto parenExpr = dyn_cast(arg0)) + { + arg0 = parenExpr->getSubExpr(); + continue; + } + argType = arg0->getType(); + break; + } + + const RecordType* argTemplateType = extractTemplateType(argType); + if (!argTemplateType) + return true; + + CXXRecordDecl* templateParamRD = dyn_cast(templateParamType->getDecl()); + CXXRecordDecl* methodArgRD = dyn_cast(argTemplateType->getDecl()); + + // querying for XInterface (instead of doing an upcast) has special semantics, + // to check for UNO object equivalence. + if (templateParamRD->getName() == "XInterface") + return true; + + // XShape is used in UNO aggregates in very "entertaining" ways, which means an UNO_QUERY + // can return a completely different object, e.g. see SwXShape::queryInterface + if (templateParamRD->getName() == "XShape") + return true; + + if (mce->getNumArgs() == 2) + if (auto declRefExpr = dyn_cast(mce->getArg(1))) + { + // no warning expected, used to reject null references + if (auto enumConstantDecl = dyn_cast(declRefExpr->getDecl())) + { + if (enumConstantDecl->getName() == "UNO_SET_THROW") + return true; + if (enumConstantDecl->getName() == "UNO_QUERY_THROW") + return true; + if (enumConstantDecl->getName() == "SAL_NO_ACQUIRE") + return true; + } + } + + if (methodArgRD->Equals(templateParamRD) || isDerivedFrom(methodArgRD, templateParamRD)) + { + report(DiagnosticsEngine::Warning, + "the source reference is already a subtype of the destination reference, just use =", + mce->getBeginLoc()) + << mce->getSourceRange(); + } + return true; +} + +bool ReferenceCasting::VisitCallExpr(const CallExpr* ce) +{ + if (ignoreLocation(ce)) + return true; + // don't bother processing anything in the Reference.h file. Makes my life easier when debugging this. + StringRef aFileName + = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(ce->getBeginLoc())); + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/com/sun/star/uno/Reference.h")) + return true; + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/com/sun/star/uno/Reference.hxx")) + return true; + + // look for calls to Reference::query(x) + auto method = dyn_cast_or_null(ce->getDirectCallee()); + if (!method || !method->getIdentifier() || method->getName() != "query") + return true; + if (ce->getNumArgs() != 1) + return true; + + auto methodRecordDecl = dyn_cast(method->getParent()); + if (!methodRecordDecl || !methodRecordDecl->getIdentifier() + || methodRecordDecl->getName() != "Reference") + return true; + + if (CheckForUnnecessaryGet(ce->getArg(0), /*includeRtlReference*/ true)) + report(DiagnosticsEngine::Warning, "unnecessary get() call", ce->getArg(0)->getBeginLoc()) + << ce->getArg(0)->getSourceRange(); + + // extract the type parameter passed to the template + const RecordType* templateParamType + = dyn_cast(methodRecordDecl->getTemplateArgs()[0].getAsType()); + if (!templateParamType) + return true; + + // extract the type of the first parameter passed to the method + const Expr* arg0 = ce->getArg(0); + if (!arg0) + return true; + + // drill down the expression tree till we hit the bottom, because at the top, the type is BaseReference + QualType argType; + for (;;) + { + if (auto castExpr = dyn_cast(arg0)) + { + arg0 = castExpr->getSubExpr(); + continue; + } + if (auto matTempExpr = dyn_cast(arg0)) + { + arg0 = matTempExpr->getSubExpr(); + continue; + } + if (auto bindTempExpr = dyn_cast(arg0)) + { + arg0 = bindTempExpr->getSubExpr(); + continue; + } + if (auto tempObjExpr = dyn_cast(arg0)) + { + arg0 = tempObjExpr->getArg(0); + continue; + } + if (auto parenExpr = dyn_cast(arg0)) + { + arg0 = parenExpr->getSubExpr(); + continue; + } + argType = arg0->getType(); + break; + } + + const RecordType* argTemplateType = extractTemplateType(argType); + if (!argTemplateType) + return true; + + CXXRecordDecl* templateParamRD = dyn_cast(templateParamType->getDecl()); + CXXRecordDecl* methodArgRD = dyn_cast(argTemplateType->getDecl()); + + // querying for XInterface (instead of doing an upcast) has special semantics, + // to check for UNO object equivalence. + if (templateParamRD->getName() == "XInterface") + return true; + + // XShape is used in UNO aggregates in very "entertaining" ways, which means an UNO_QUERY + // can return a completely different object, e.g. see SwXShape::queryInterface + if (templateParamRD->getName() == "XShape") + return true; + + if (methodArgRD->Equals(templateParamRD) || isDerivedFrom(methodArgRD, templateParamRD)) + { + report(DiagnosticsEngine::Warning, + "the source reference is already a subtype of the destination reference, just use =", + ce->getBeginLoc()) + << ce->getSourceRange(); + } + return true; +} + +/** + Check for + Reference(x.get(), UNO_QUERY) + because sometimes simplifying that means the main purpose of this plugin can kick in. + */ +bool ReferenceCasting::CheckForUnnecessaryGet(const Expr* expr, bool includeRtlReference) +{ + expr = expr->IgnoreImplicit(); + auto cxxMemberCallExpr = dyn_cast(expr); + if (!cxxMemberCallExpr) + return false; + auto methodDecl = cxxMemberCallExpr->getMethodDecl(); + if (!methodDecl) + return false; + if (!methodDecl->getIdentifier() || methodDecl->getName() != "get") + return false; + + if (!loplugin::TypeCheck(expr->getType()).Pointer()) + return false; + auto dc = loplugin::DeclCheck(methodDecl->getParent()); + if (dc.Class("Reference").Namespace("uno")) + ; // ok + else if (includeRtlReference && dc.Class("Reference").Namespace("rtl")) + ; // ok + else + return false; + + StringRef aFileName + = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc())); + if (loplugin::isSamePathname(aFileName, SRCDIR "/cppu/qa/test_reference.cxx")) + return false; + + return true; +} + +static const RecordType* extractTemplateType(QualType cceType) +{ + // check for passing raw pointer to interface case + if (cceType->isPointerType()) + { + auto pointeeType = cceType->getPointeeType(); + if (auto elaboratedType = dyn_cast(pointeeType)) + pointeeType = elaboratedType->desugar(); + if (auto substTemplateTypeParmType = dyn_cast(pointeeType)) + pointeeType = substTemplateTypeParmType->desugar(); + if (auto recordType = dyn_cast(pointeeType)) + return recordType; + } + + // extract Foo from Reference + if (auto subst = dyn_cast(cceType)) + { + if (auto recType = dyn_cast(subst->desugar())) + { + if (auto ctsd = dyn_cast(recType->getDecl())) + { + auto const& args = ctsd->getTemplateArgs(); + if (args.size() > 0 && args[0].getKind() == TemplateArgument::ArgKind::Type) + return dyn_cast_or_null(args[0].getAsType().getTypePtr()); + } + } + } + + if (auto elaboratedType = dyn_cast(cceType)) + cceType = elaboratedType->desugar(); + auto cceTST = dyn_cast(cceType); + if (!cceTST) + return NULL; + if (cceTST->getNumArgs() != 1) + return NULL; + const TemplateArgument& cceTA = cceTST->getArg(0); + QualType templateParamType = cceTA.getAsType(); + if (auto elaboratedType = dyn_cast(templateParamType)) + templateParamType = elaboratedType->desugar(); + return dyn_cast(templateParamType); +} + +/** + Implement my own isDerived because we can't always see all the definitions of the classes involved. + which will cause an assert with the normal clang isDerivedFrom code. +*/ +static bool isDerivedFrom(const CXXRecordDecl* subtypeRecord, const CXXRecordDecl* baseRecord) +{ + // if there is more than one case, then we have an ambiguous conversion, and we can't change the code + // to use the upcasting constructor. + return loplugin::derivedFromCount(subtypeRecord, baseRecord) == 1; +} + +loplugin::Plugin::Registration referencecasting("referencecasting"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/rendercontext.cxx b/compilerplugins/clang/rendercontext.cxx new file mode 100644 index 000000000..2508b449e --- /dev/null +++ b/compilerplugins/clang/rendercontext.cxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "clang/AST/CXXInheritance.h" + +// Check for calls to OutputDevice methods that are not passing through RenderContext + +namespace +{ + +class RenderContext: + public loplugin::FilteringPlugin +{ +public: + explicit RenderContext(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool TraverseFunctionDecl(const FunctionDecl * decl); + + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *); + +private: + bool mbChecking = false; +}; + +// We use Traverse to set a flag so we can easily ignore certain method calls +bool RenderContext::TraverseFunctionDecl(const FunctionDecl * pFunctionDecl) +{ + if (ignoreLocation(pFunctionDecl)) { + return true; + } + if (!pFunctionDecl->hasBody()) { + return true; + } + if ( pFunctionDecl != pFunctionDecl->getCanonicalDecl() ) { + return true; + } + // Ignore methods inside the OutputDevice class + const CXXMethodDecl *pCXXMethodDecl = dyn_cast(pFunctionDecl); + if (pCXXMethodDecl) { + if (loplugin::TypeCheck(pCXXMethodDecl->getParent()).Class("OutputDevice").GlobalNamespace()) + return true; + } + // we are only currently interested in methods where the first parameter is RenderContext + if (pFunctionDecl->getNumParams() == 0) + return true; + if ( loplugin::TypeCheck(pFunctionDecl->getParamDecl( 0 )->getType()).Class("RenderContext").GlobalNamespace() ) { + return true; + } + mbChecking = true; + TraverseStmt(pFunctionDecl->getBody()); + mbChecking = false; + return true; +} + +bool RenderContext::VisitCXXMemberCallExpr(const CXXMemberCallExpr* pCXXMemberCallExpr) +{ + if (!mbChecking) + return true; + if (ignoreLocation(pCXXMemberCallExpr)) { + return true; + } + const CXXRecordDecl *pCXXRecordDecl = pCXXMemberCallExpr->getRecordDecl(); + if (!loplugin::TypeCheck(pCXXRecordDecl).Class("OutputDevice").GlobalNamespace()) { + return true; + } + // ignore a handful of methods. They will most probably still be present in Window for use during processing outside of the Paint() + // method lifecycle + const CXXMethodDecl *pCXXMethodDecl = pCXXMemberCallExpr->getMethodDecl(); + if (pCXXMethodDecl->isInstance()) { + StringRef name = pCXXMethodDecl->getName(); + if (name == "LogicToPixel" || name == "GetMapMode" || name == "GetFontMetric" || name == "LogicToLogic" + || name == "PixelToLogic" || name == "SetDigitLanguage") + { + return true; + } + } + // for calling through a pointer + const ImplicitCastExpr *pImplicitCastExpr = dyn_cast(pCXXMemberCallExpr->getImplicitObjectArgument()); + if (pImplicitCastExpr) { + QualType aType = pImplicitCastExpr->getSubExpr()->getType(); + if (aType->isPointerType()) + aType = aType->getPointeeType(); + std::string t2 = aType.getAsString(); + if (t2 == "vcl::RenderContext" || t2 == "const vcl::RenderContext") + return true; + } + // for calling through a reference + const DeclRefExpr *pDeclRefExpr = dyn_cast(pCXXMemberCallExpr->getImplicitObjectArgument()); + if (pDeclRefExpr) { + QualType aType = pDeclRefExpr->getType(); + std::string t2 = aType.getAsString(); + if (t2 == "vcl::RenderContext" || t2 == "const vcl::RenderContext") + return true; + } + // for calling through a chain of methods + const CXXMemberCallExpr *pMemberExpr = dyn_cast(pCXXMemberCallExpr->getImplicitObjectArgument()); + if (pMemberExpr) { + QualType aType = pMemberExpr->getType(); + if (aType->isPointerType()) + aType = aType->getPointeeType(); + std::string t2 = aType.getAsString(); + if (t2 == "vcl::RenderContext" || t2 == "const vcl::RenderContext") + return true; + } + report( + DiagnosticsEngine::Warning, + "Should be calling OutputDevice method through RenderContext.", + pCXXMemberCallExpr->getBeginLoc()) + << pCXXMemberCallExpr->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration< RenderContext > X("rendercontext", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/reservedid.cxx b/compilerplugins/clang/reservedid.cxx new file mode 100644 index 000000000..be0a2f209 --- /dev/null +++ b/compilerplugins/clang/reservedid.cxx @@ -0,0 +1,328 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include "clang/AST/Attr.h" + +#include "config_clang.h" + +#include "plugin.hxx" + +namespace { + +bool isJniFunction(NamedDecl const * decl) { + auto const fdecl = dyn_cast(decl); + if (fdecl == nullptr + || !(decl->getDeclContext()->getDeclKind() == Decl::LinkageSpec + && decl->getDeclContext()->getParent()->isTranslationUnit()) + || !fdecl->isExternC()) + { + return false; + } + auto const id = decl->getIdentifier(); + return id != nullptr && id->getName().startswith("Java_"); +} + +class ReservedId: + public loplugin::FilteringPlugin +{ +public: + explicit ReservedId(loplugin::InstantiationData const & data): FilteringPlugin(data) + {} + + void run() override; + void postRun() override; + + bool VisitNamedDecl(NamedDecl const * decl); + +private: + enum class Kind { + Ok, DoubleUnderscore, UnderscoreUppercase, UnderscoreLowercase }; + + Kind determineKind(llvm::StringRef const & id); + + bool isInLokIncludeFile(SourceLocation spellingLocation) const; + + bool isApi(NamedDecl const * decl); +}; + +void ReservedId::run() { + //TODO: Rules for C? + if (TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) + postRun(); +} + +void ReservedId::postRun() { + if( compiler.hasPreprocessor()) + { + auto & prep = compiler.getPreprocessor(); + for (auto const & m: prep.macros(false)) { + auto id = m.first->getName(); + if (determineKind(id) != Kind::Ok + && id != "_ATL_APARTMENT_THREADED" + // extensions/source/activex/StdAfx2.h + && id != "_ATL_STATIC_REGISTRY" + // extensions/source/activex/StdAfx2.h + && id != "_CRT_RAND_S" // sal/osl/w32/random.cxx + && id != "_GLIBCXX_CDTOR_CALLABI" + && id != "_HAS_AUTO_PTR_ETC" // unotools/source/i18n/resmgr.cxx + && id != "_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR" // unotools/source/i18n/resmgr.cxx + && id != "_MAX_PATH" // Windows + && id != "_POSIX_SOURCE" + && id != "_USE_MATH_DEFINES" // include/sal/config.h, Windows + && id != "_WIN32_DCOM" // embedserv/source/embed/esdll.cxx + && id != "_WTL_NO_CSTRING" + // fpicker/source/win32/filepicker/platform_vista.h (TODO: + // needed?) + && id != "__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES" + && id != "__Column_FWD_DEFINED__" + // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK + // adoctint.h + && id != "__Group_FWD_DEFINED__" + // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK + // adoctint.h + && id != "__Index_FWD_DEFINED__" + // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK + // adoctint.h + && id != "__Key_FWD_DEFINED__" + // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK + // adoctint.h + && id != "__ORCUS_STATIC_LIB" + && id != "__Table_FWD_DEFINED__" + // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK + // adoctint.h + && id != "__USE_GNU" + && id != "__User_FWD_DEFINED__") + // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK + // adoctint.h + { + auto d = prep.getLocalMacroDirectiveHistory(m.first); + for (;;) { + if (d->getKind() == MacroDirective::MD_Define) { + auto loc = d->getLocation(); + if (loc.isValid() && !ignoreLocation(loc)) { + auto file = getFilenameOfLocation(loc); + if (!loplugin::isSameUnoIncludePathname( + file, + "cppuhelper/implbase_ex_post.hxx") + && !loplugin::isSameUnoIncludePathname( + file, + "cppuhelper/implbase_ex_pre.hxx")) + { + report( + DiagnosticsEngine::Warning, + "reserved macro identifier", loc); + } + } + } + d = d->getPrevious(); + if (d == nullptr) { + break; + } + } + } + } + } +} + +bool ReservedId::VisitNamedDecl(NamedDecl const * decl) { + auto spelLoc = compiler.getSourceManager().getSpellingLoc( + decl->getLocation()); + if (ignoreLocation(spelLoc)) { + return true; + } + auto filename = getFilenameOfLocation(spelLoc); + if (loplugin::hasPathnamePrefix(filename, SRCDIR "/bridges/source/cpp_uno/") + && (filename.endswith("abi.hxx") || filename.endswith("share.hxx"))) + { + return true; + } + auto const id = decl->getIdentifier(); + if (id == nullptr) { + return true; + } + auto const s = id->getName(); + switch (determineKind(s)) { + case Kind::Ok: + break; + case Kind::DoubleUnderscore: +/*TODO*/if(s=="BIFF__5"||s=="XML__COLON"||s=="XML__EMPTY"||s=="XML__UNKNOWN_")break; + if (!(isApi(decl) || isJniFunction(decl)) + && s != "__CERT_DecodeDERCertificate" + // xmlsecurity/source/xmlsec/nss/nssrenam.h + && s != "__CERT_NewTempCertificate" + // xmlsecurity/source/xmlsec/nss/nssrenam.h + && s != "__CTFont" + // vcl/source/window/cairo_cairo.cxx -> include/vcl/sysdata.hxx + && s != "__CxxDetectRethrow" + // bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx + && s != "__PK11_GetKeyData" + // xmlsecurity/source/xmlsec/nss/nssrenam.h + && s != "__current_exception" // bridges/inc/except.hxx, Windows + && s != "__data_start") // sal/osl/unx/system.cxx + { + report( + DiagnosticsEngine::Warning, + "identifier %select{beginning with|containing}0 a double" + " underscore is reserved", + decl->getLocation()) + << compiler.getLangOpts().CPlusPlus << decl->getSourceRange(); + } + break; + case Kind::UnderscoreUppercase: + if (!isApi(decl) + && s != "_ADOColumn" + // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h + && s != "_ADOGroup" + // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h + && s != "_ADOIndex" + // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h + && s != "_ADOKey" + // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h + && s != "_ADOTable" + // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h + && s != "_ADOUser" + // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h + && s != "_CustomCellRenderer" // vcl/unx/gtk3/customcellrenderer.hxx + && s != "_CustomCellRendererClass" // vcl/unx/gtk3/customcellrenderer.cxx + && s != "_FcPattern" // vcl/inc/unx/fc_fontoptions.hxx + && s != "_GdkDisplay" + // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c + && s != "_GdkEvent" // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c + && s != "_GdkScreen" // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c + && s != "_GdkWindow" + // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c + && s != "_GstVideoOverlay" + // avmedia/source/gstreamer/gstplayer.hxx + && s != "_GtkMediaStream" + // avmedia/source/gtk/gtkplayer.hxx + && s != "_GtkWidget" + // avmedia/source/gtk/gtkplayer.hxx + && s != "_Module" // extensions/source/activex/StdAfx2.h, CComModule + && s != "_NotifyingLayout" // vcl/unx/gtk4/notifyinglayout.cxx + && s != "_SurfacePaintable" // vcl/unx/gtk3/gtkinst.cxx + && s != "_SurfacePaintableClass" // vcl/unx/gtk3/gtkinst.cxx + && s != "_SurfaceCellRenderer" // vcl/unx/gtk4/surfacecellrenderer.cxx + && s != "_SurfaceCellRendererClass" // vcl/unx/gtk4/surfacecellrenderer.cxx + && s != "_TransferableContent" // vcl/unx/gtk4/transferableprovider.cxx + && s != "_TransferableContentClass" // vcl/unx/gtk4/transferableprovider.cxx + && s != "_XRegion" // vcl/unx/generic/gdi/x11cairotextrender.cxx + && s != "_XTrap") // vcl/unx/generic/gdi/xrender_peer.hxx + { + report( + DiagnosticsEngine::Warning, + "identifier beginning with an underscore followed by an" + " uppercase letter is reserved", + decl->getLocation()) + << decl->getSourceRange(); + } + break; + case Kind::UnderscoreLowercase: + if (decl->getDeclContext()->isTranslationUnit() + && !isa(decl) && !isApi(decl) + && s != "_cairo" && s != "_cairo_surface" + // tools/source/ref/errinf.cxx -> include/vcl/window.hxx -> + // include/vcl/outdev.hxx -> include/vcl/cairo.hxx + && s != "_cairo_font_options" + // vcl/source/window/accessibility.cxx -> vcl/inc/salinst.hxx + && s != "_cairo_user_data_key" + // vcl/headless/svpbmp.cxx -> vcl/inc/headless/svpgdi.hxx + && s != "_end" // sal/osl/unx/system.cxx + && s != "_rtl_Locale" + // i18nlangtag/source/isolang/mslangid.cxx -> + // include/i18nlangtag/languagetag.hxx + && s != "_uno_ExtEnvironment" + // cppu/source/threadpool/threadident.cxx -> + // threadpool/current.hxx + && s != "_xmlTextWriter") // include/svl/poolitem.hxx + { + report( + DiagnosticsEngine::Warning, + "identifier beginning with an underscore followed by a" + " lowercase letter is reserved in the global namespace", + decl->getLocation()) + << decl->getSourceRange(); + } + break; + } + return true; +} + +ReservedId::Kind ReservedId::determineKind(llvm::StringRef const & id) { + if (compiler.getLangOpts().CPlusPlus + && id.find("__") != llvm::StringRef::npos) + { + return Kind::DoubleUnderscore; + } + if (id.size() >= 2 && id[0] == '_') { + auto c = id[1]; + if (c == '_') { + return Kind::DoubleUnderscore; + } + if (c >= 'A' && c <= 'Z') { + return Kind::UnderscoreUppercase; + } + if (c >= 'a' && c <= 'z') { + return Kind::UnderscoreLowercase; + } + } + return Kind::Ok; +} + +bool ReservedId::isInLokIncludeFile(SourceLocation spellingLocation) const { + return loplugin::hasPathnamePrefix( + getFilenameOfLocation(spellingLocation), + SRCDIR "/include/LibreOfficeKit/"); +} + +bool ReservedId::isApi(NamedDecl const * decl) { + auto const fdecl = dyn_cast(decl); + if (fdecl != nullptr) { + decl = fdecl->getCanonicalDecl(); + } else { + auto const tdecl = dyn_cast(decl); + if (tdecl != nullptr) { + decl = tdecl->getCanonicalDecl(); + } + } + auto const loc = compiler.getSourceManager().getSpellingLoc( + decl->getLocation()); + if (!(isInUnoIncludeFile(loc) || isInLokIncludeFile(loc)) + || isa(decl)) + { + return false; + } + auto const ctx = decl->getDeclContext(); + if (ctx->isTranslationUnit() + || (ctx->getDeclKind() == Decl::LinkageSpec + && ctx->getParent()->isTranslationUnit())) + { + return true; + } + if (ctx->isNamespace()) { + auto const id = dyn_cast(ctx)->getIdentifier(); + return !(id == nullptr || id->getName() == "detail"); + } + return false; +} + +loplugin::Plugin::Registration reservedid("reservedid"); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/returnconstant.cxx b/compilerplugins/clang/returnconstant.cxx new file mode 100644 index 000000000..530044c96 --- /dev/null +++ b/compilerplugins/clang/returnconstant.cxx @@ -0,0 +1,226 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "plugin.hxx" +#include "check.hxx" +#include "compat.hxx" +#include "functionaddress.hxx" +#include +#include +#include + +/* + Look for member functions that merely return a compile-time constant, or they are empty, and can thus + be either removed, or converted into a constant. + + This mostly tends to happen as a side-effect of other cleanups. +*/ +namespace +{ +class ReturnConstant : public loplugin::FunctionAddress> +{ +public: + explicit ReturnConstant(loplugin::InstantiationData const& data) + : FunctionAddress(data) + { + } + + void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + for (auto& pair : problemFunctions) + { + auto functionDecl = pair.first; + auto canonicalDecl = functionDecl->getCanonicalDecl(); + if (getFunctionsWithAddressTaken().find(canonicalDecl) + != getFunctionsWithAddressTaken().end()) + continue; + report(DiagnosticsEngine::Warning, + "Method only returns a single constant value %0, does it make sense?", + functionDecl->getBeginLoc()) + << pair.second << functionDecl->getSourceRange(); + if (functionDecl != functionDecl->getCanonicalDecl()) + report(DiagnosticsEngine::Note, "decl here", + functionDecl->getCanonicalDecl()->getBeginLoc()) + << functionDecl->getCanonicalDecl()->getSourceRange(); + } + } + + bool TraverseCXXMethodDecl(CXXMethodDecl*); + bool VisitReturnStmt(ReturnStmt const*); + +private: + std::string getExprValue(Expr const* arg); + + struct Context + { + bool ignore = false; + std::set values; + }; + std::vector m_functionStack; + std::vector> problemFunctions; +}; + +bool ReturnConstant::TraverseCXXMethodDecl(CXXMethodDecl* functionDecl) +{ + if (ignoreLocation(functionDecl)) + return true; + if (isInUnoIncludeFile(functionDecl)) + return true; + + if (!functionDecl->hasBody()) + return true; + if (!functionDecl->isThisDeclarationADefinition()) + return true; + if (functionDecl->isConstexpr()) + return true; + if (functionDecl->getReturnType()->isVoidType()) + return true; + if (functionDecl->isVirtual()) + return true; + // static with inline body will be optimised at compile-time to a constant anyway + if (functionDecl->isStatic() + && (functionDecl->hasInlineBody() || functionDecl->isInlineSpecified())) + return true; + // this catches some stuff in templates + if (functionDecl->hasAttr()) + return true; + + // include/unotools/localedatawrapper.hxx + if (functionDecl->getIdentifier() && functionDecl->getName() == "getCurrZeroChar") + return true; + // sc/inc/stlalgorithm.hxx + if (loplugin::DeclCheck(functionDecl->getParent()) + .Class("AlignedAllocator") + .Namespace("sc") + .GlobalNamespace()) + return true; + + switch (functionDecl->getOverloadedOperator()) + { + case OO_Delete: + case OO_EqualEqual: + case OO_Call: + return true; + default: + break; + } + + // gtk signals and slots stuff + if (loplugin::TypeCheck(functionDecl->getReturnType()).Typedef("gboolean")) + return true; + + // ignore LINK macro stuff + if (compiler.getSourceManager().isMacroBodyExpansion(functionDecl->getBeginLoc()) + || compiler.getSourceManager().isMacroArgExpansion(functionDecl->getBeginLoc())) + { + StringRef name{ Lexer::getImmediateMacroName( + functionDecl->getBeginLoc(), compiler.getSourceManager(), compiler.getLangOpts()) }; + if (name.find("IMPL_LINK") != StringRef::npos + || name.find("IMPL_STATIC_LINK") != StringRef::npos + || name.find("DECL_LINK") != StringRef::npos + || name.find("SFX_IMPL_POS_CHILDWINDOW_WITHID") != StringRef::npos) + return true; + } + + m_functionStack.emplace_back(); + bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(functionDecl); + Context& rContext = m_functionStack.back(); + if (!rContext.ignore && rContext.values.size() == 1 + && rContext.values.find("unknown") == rContext.values.end()) + { + problemFunctions.push_back({ functionDecl, *rContext.values.begin() }); + } + m_functionStack.pop_back(); + return ret; +} + +bool ReturnConstant::VisitReturnStmt(ReturnStmt const* returnStmt) +{ + if (ignoreLocation(returnStmt)) + return true; + if (m_functionStack.empty()) + return true; + Context& rContext = m_functionStack.back(); + + if (!returnStmt->getRetValue()) + return true; + if (returnStmt->getRetValue()->isTypeDependent()) + { + rContext.ignore = true; + return true; + } + if (const UnaryOperator* unaryOp = dyn_cast(returnStmt->getRetValue())) + { + if (unaryOp->getOpcode() == UO_AddrOf) + { + rContext.ignore = true; + return true; + } + } + rContext.values.insert(getExprValue(returnStmt->getRetValue())); + return true; +} + +std::string ReturnConstant::getExprValue(Expr const* arg) +{ + arg = arg->IgnoreParenCasts(); + if (isa(arg)) + { + arg = dyn_cast(arg)->getExpr(); + } + arg = arg->IgnoreParenCasts(); + // ignore this, it seems to trigger an infinite recursion + if (isa(arg)) + { + return "unknown"; + } + APSInt x1; + if (compat::EvaluateAsInt(arg, x1, compiler.getASTContext())) + { + return compat::toString(x1, 10); + } + if (isa(arg)) + { + return "0"; + } + if (isa(arg)) + { + const CXXBindTemporaryExpr* strippedArg + = dyn_cast_or_null(arg->IgnoreParenCasts()); + if (strippedArg && strippedArg->getSubExpr()) + { + auto temp = dyn_cast(strippedArg->getSubExpr()); + if (temp->getNumArgs() == 0) + { + if (loplugin::TypeCheck(temp->getType()) + .Class("OUString") + .Namespace("rtl") + .GlobalNamespace()) + { + return "\"\""; + } + if (loplugin::TypeCheck(temp->getType()) + .Class("OString") + .Namespace("rtl") + .GlobalNamespace()) + { + return "\"\""; + } + } + } + } + return "unknown"; +} + +loplugin::Plugin::Registration X("returnconstant", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/returnconstval.cxx b/compilerplugins/clang/returnconstval.cxx new file mode 100644 index 000000000..4f8b0ac34 --- /dev/null +++ b/compilerplugins/clang/returnconstval.cxx @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include + +#include "plugin.hxx" + +/** + Find code where we are return a const value type from a function. + Which makes no sense. + Either we should return by non-const value, or by const ref. + e.g. + struct S2 { + OUString mv1; + const OUString get13() { return mv1; } + } + + Specifically, this code pattern will prevent copy/move optimisations. +*/ + +namespace +{ +class ReturnConstVal : public loplugin::FilteringPlugin +{ +public: + explicit ReturnConstVal(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitFunctionDecl(const FunctionDecl* decl); +}; + +bool ReturnConstVal::VisitFunctionDecl(const FunctionDecl* functionDecl) +{ + if (ignoreLocation(functionDecl)) + return true; + if (!functionDecl->hasBody()) + return true; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) + return true; + QualType t1{ functionDecl->getReturnType() }; + if (!t1.isConstQualified()) + return true; + if (t1->isReferenceType()) + return true; + report(DiagnosticsEngine::Warning, "either return non-const, or by const ref", + functionDecl->getSourceRange().getBegin()) + << functionDecl->getSourceRange(); + + // display the location of the class member declaration so I don't have to search for it by hand + auto canonicalDecl = functionDecl->getCanonicalDecl(); + if (canonicalDecl != functionDecl) + { + report(DiagnosticsEngine::Note, "either return non-const, or by const ref", + canonicalDecl->getSourceRange().getBegin()) + << canonicalDecl->getSourceRange(); + } + + return true; +} + +loplugin::Plugin::Registration returnconstval("returnconstval"); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/salcall.cxx b/compilerplugins/clang/salcall.cxx new file mode 100644 index 000000000..d2b4fc2bf --- /dev/null +++ b/compilerplugins/clang/salcall.cxx @@ -0,0 +1,615 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "plugin.hxx" +#include "check.hxx" +#include "compat.hxx" +#include "functionaddress.hxx" + +#include +#include +#include +#include +#include + +// The SAL_CALL function annotation is only necessary on our outward +// facing C++ ABI, anywhere else it is just cargo-cult. +// + +//TODO: To find inconsistencies like +// +// template struct S { void f(); }; // #1 +// template void S::f() {} // #2 +// template void SAL_CALL S::f(); +// +// VisitFunctionDecl would need to also visit explicit instantiations, by letting +// shouldVisitTemplateInstantiations return true and returning from VisitFunctionDecl early iff +// decl->getTemplateSpecializationKind() == TSK_ImplicitInstantiation. However, an instantiated +// FunctionDecl is created in TemplateDeclInstantiator::VisitCXXMethodDecl by copying information +// (including source locations) from the declaration at #1, and later modified in +// Sema::InstantiateFunctionDefinition with some source location information from the definition at +// #2. That means that the source scanning in isSalCallFunction below would be thoroughly confused +// and break. (This happens for both explicit and implicit template instantiations, which is the +// reason why calls to isSalCallFunction make sure to not call it with any FunctionDecls +// representing such template instantiations.) + +namespace +{ +//static bool startswith(const std::string& rStr, const char* pSubStr) +//{ +// return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; +//} + +CXXMethodDecl const* getTemplateInstantiationPattern(CXXMethodDecl const* decl) +{ + auto const p = decl->getTemplateInstantiationPattern(); + return p == nullptr ? decl : cast(p); +} + +class SalCall final : public loplugin::FunctionAddress> +{ +public: + explicit SalCall(loplugin::InstantiationData const& data) + : FunctionAddress(data) + { + } + + virtual void run() override + { + if (TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) + { + auto const& addressOfSet = getFunctionsWithAddressTaken(); + for (auto const decl : m_decls) + { + if (addressOfSet.find(decl->getCanonicalDecl()) == addressOfSet.end()) + { + handleFunctionDecl(decl); + } + } + } + } + + bool VisitFunctionDecl(FunctionDecl const*); + +private: + void handleFunctionDecl(FunctionDecl const* decl); + bool rewrite(SourceLocation); + bool isSalCallFunction(FunctionDecl const* functionDecl, SourceLocation* pLoc = nullptr); + + std::set m_decls; +}; + +bool SalCall::VisitFunctionDecl(FunctionDecl const* decl) +{ + if (ignoreLocation(decl)) + return true; + + // ignore template stuff + if (decl->getTemplatedKind() != clang::FunctionDecl::TK_NonTemplate) + return true; + auto recordDecl = dyn_cast(decl->getDeclContext()); + if (recordDecl + && (recordDecl->getTemplateSpecializationKind() != TSK_Undeclared + || recordDecl->isDependentContext())) + { + return true; + } + + auto canonicalDecl = decl->getCanonicalDecl(); + + // ignore UNO implementations + if (isInUnoIncludeFile( + compiler.getSourceManager().getSpellingLoc(canonicalDecl->getLocation()))) + return true; + + SourceLocation rewriteLoc; + SourceLocation rewriteCanonicalLoc; + bool bDeclIsSalCall = isSalCallFunction(decl, &rewriteLoc); + bool bCanonicalDeclIsSalCall = isSalCallFunction(canonicalDecl, &rewriteCanonicalLoc); + + // first, check for consistency, so we don't trip ourselves up on Linux, where we normally run the plugin + if (canonicalDecl != decl) + { + if (bCanonicalDeclIsSalCall) + ; // this is fine, the actual definition have or not have SAL_CALL, and MSVC is fine with it + else if (bDeclIsSalCall) + { + // not fine + report(DiagnosticsEngine::Warning, "SAL_CALL inconsistency", decl->getLocation()) + << decl->getSourceRange(); + report(DiagnosticsEngine::Note, "SAL_CALL inconsistency", canonicalDecl->getLocation()) + << canonicalDecl->getSourceRange(); + return true; + } + } + auto methodDecl = dyn_cast(canonicalDecl); + if (methodDecl) + { + for (auto iter = methodDecl->begin_overridden_methods(); + iter != methodDecl->end_overridden_methods(); ++iter) + { + const CXXMethodDecl* overriddenMethod + = getTemplateInstantiationPattern(*iter)->getCanonicalDecl(); + if (bCanonicalDeclIsSalCall != isSalCallFunction(overriddenMethod)) + { + report(DiagnosticsEngine::Warning, "SAL_CALL inconsistency", + methodDecl->getLocation()) + << methodDecl->getSourceRange(); + report(DiagnosticsEngine::Note, "SAL_CALL inconsistency", + overriddenMethod->getLocation()) + << overriddenMethod->getSourceRange(); + return true; + } + } + } + + if (!bCanonicalDeclIsSalCall) + return true; + + if (!decl->isThisDeclarationADefinition() && !(methodDecl && methodDecl->isPure())) + return true; + + m_decls.insert(decl); + return true; +} + +void SalCall::handleFunctionDecl(FunctionDecl const* decl) +{ + // some base classes are overridden by sub-classes which override both the base-class and a UNO class + if (auto recordDecl = dyn_cast(decl->getDeclContext())) + { + auto dc = loplugin::DeclCheck(recordDecl); + if (dc.Class("OProxyAggregation").Namespace("comphelper").GlobalNamespace() + || dc.Class("OComponentProxyAggregationHelper") + .Namespace("comphelper") + .GlobalNamespace() + || dc.Class("SvxShapeMaster").GlobalNamespace() + || dc.Class("ListBoxAccessibleBase").Namespace("accessibility").GlobalNamespace() + || dc.Class("AsyncEventNotifierBase").Namespace("comphelper").GlobalNamespace() + || dc.Class("ODescriptor") + .Namespace("sdbcx") + .Namespace("connectivity") + .GlobalNamespace() + || dc.Class("IController").Namespace("dbaui").GlobalNamespace() + || dc.Class("ORowSetBase").Namespace("dbaccess").GlobalNamespace() + || dc.Class("OComponentAdapterBase").Namespace("bib").GlobalNamespace() + || dc.Class("IEventProcessor").Namespace("comphelper").GlobalNamespace() + || dc.Class("SvxUnoTextBase").GlobalNamespace() + || dc.Class("OInterfaceContainer").Namespace("frm").GlobalNamespace() + || dc.Class("AccessibleComponentBase").Namespace("accessibility").GlobalNamespace() + || dc.Class("ContextHandler2Helper") + .Namespace("core") + .Namespace("oox") + .GlobalNamespace() + || dc.Class("AccessibleStaticTextBase").Namespace("accessibility").GlobalNamespace() + || dc.Class("OCommonPicker").Namespace("svt").GlobalNamespace() + || dc.Class("VbaDocumentBase").GlobalNamespace() + || dc.Class("VbaPageSetupBase").GlobalNamespace() + || dc.Class("ScVbaControl").GlobalNamespace() + + ) + return; + } + + auto canonicalDecl = decl->getCanonicalDecl(); + + // if any of the overridden methods are SAL_CALL, we should be too + if (auto methodDecl = dyn_cast(canonicalDecl)) + { + for (auto iter = methodDecl->begin_overridden_methods(); + iter != methodDecl->end_overridden_methods(); ++iter) + { + const CXXMethodDecl* overriddenMethod + = getTemplateInstantiationPattern(*iter)->getCanonicalDecl(); + if (isSalCallFunction(overriddenMethod)) + return; + } + } + + SourceLocation rewriteLoc; + SourceLocation rewriteCanonicalLoc; + bool bDeclIsSalCall = isSalCallFunction(decl, &rewriteLoc); + isSalCallFunction(canonicalDecl, &rewriteCanonicalLoc); + + bool bOK = rewrite(rewriteLoc); + if (bOK && canonicalDecl != decl) + { + bOK = rewrite(rewriteCanonicalLoc); + } + if (bOK) + return; + + if (bDeclIsSalCall) + { + report(DiagnosticsEngine::Warning, "SAL_CALL unnecessary here", + rewriteLoc.isValid() ? rewriteLoc : decl->getLocation()) + << decl->getSourceRange(); + } + if (canonicalDecl != decl) + { + report(DiagnosticsEngine::Warning, "SAL_CALL unnecessary here", rewriteCanonicalLoc) + << canonicalDecl->getSourceRange(); + if (!bDeclIsSalCall) + { + report(DiagnosticsEngine::Note, "defined here (without SAL_CALL decoration)", + decl->getLocation()) + << decl->getSourceRange(); + } + } +} + +//TODO: This doesn't handle all possible cases of macro usage (and possibly never will be able to), +// just what is encountered in practice: +bool SalCall::isSalCallFunction(FunctionDecl const* functionDecl, SourceLocation* pLoc) +{ + assert(!functionDecl->isTemplateInstantiation()); + + //TODO: It appears that FunctionDecls representing explicit template specializations have the + // same issue as those representing (implicit or explicit) instantiations, namely that their + // data (including relevant source locations) is an incoherent combination of data from the + // original template declaration and the later specialization definition. For example, for the + // OValueLimitedType::registerProperties specialization at + // forms/source/xforms/datatyperepository.cxx:241, the FunctionDecl (which is even considered + // canonic) representing the base-class function overridden by ODecimalType::registerProperties + // (forms/source/xforms/datatypes.hxx:299) is dumped as + // + // CXXMethodDecl + // forms/source/xforms/datatyperepository.cxx:242:37 registerProperties 'void (void)' virtual + // + // mixing the source range ("datatypes.hxx:217:9, col:54") from the original declaration with + // the name location ("datatyperepository.cxx:242:37") from the explicit specialization. Just + // give up for now and assume no "SAL_CALL" is present: + if (functionDecl->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + { + return false; + } + + SourceManager& SM = compiler.getSourceManager(); + std::vector ranges; + + SourceLocation startLoc; + SourceLocation endLoc; + bool noReturnType = isa(functionDecl) + || isa(functionDecl) + || isa(functionDecl); + bool startAfterReturnType = !noReturnType; + if (startAfterReturnType) + { + // For functions that do have a return type, start searching for "SAL_CALL" after the return + // type (which for SAL_CALL functions on Windows will be an AttributedTypeLoc, which the + // implementation of FunctionDecl::getReturnTypeSourceRange does not take into account, so + // do that here explicitly): + auto const TSI = functionDecl->getTypeSourceInfo(); + if (TSI == nullptr) + { + if (isDebugMode()) + { + report(DiagnosticsEngine::Fatal, "TODO: unexpected failure #1, needs investigation", + functionDecl->getLocation()) + << functionDecl->getSourceRange(); + } + return false; + } + auto TL = TSI->getTypeLoc().IgnoreParens(); + if (auto ATL = TL.getAs()) + { + TL = ATL.getModifiedLoc(); + } + auto const FTL = TL.getAs(); + if (!FTL) + { + // Happens when a function declaration uses a typedef for the function type, as in + // + // SAL_JNI_EXPORT javaunohelper::detail::Func_bootstrap + // Java_com_sun_star_comp_helper_Bootstrap_cppuhelper_1bootstrap; + // + // in javaunohelper/source/juhx-export-functions.hxx. + //TODO: check the typedef for mention of "SAL_CALL" (and also check for usage of such + // typedefs in the !startAfterReturnType case below) + return false; + } + startLoc = FTL.getReturnLoc().getEndLoc(); + while (SM.isMacroArgExpansion(startLoc, &startLoc)) + { + } + + // Stop searching for "SAL_CALL" at the start of the function declaration's name (for + // qualified names this will point after the qualifiers, but needlessly including those in + // the search should be harmless---modulo issues with using "SAL_CALL" as the name of a + // function-like macro parameter as discussed below): + endLoc = functionDecl->getNameInfo().getBeginLoc(); + while (SM.isMacroArgExpansion(endLoc, &endLoc)) + { + } + while (endLoc.isMacroID() && SM.isAtStartOfImmediateMacroExpansion(endLoc, &endLoc)) + { + } + endLoc = SM.getSpellingLoc(endLoc); + + auto const slEnd = Lexer::getLocForEndOfToken(startLoc, 0, SM, compiler.getLangOpts()); + if (slEnd.isValid()) + { + // startLoc is either non-macro, or at end of macro; one source range from startLoc to + // endLoc: + startLoc = slEnd; + while (startLoc.isMacroID() && SM.isAtEndOfImmediateMacroExpansion(startLoc, &startLoc)) + { + } + startLoc = SM.getSpellingLoc(startLoc); + + if (startLoc.isValid() && endLoc.isValid() && startLoc != endLoc + && !SM.isBeforeInTranslationUnit(startLoc, endLoc)) + { + // Happens for uses of trailing return type (in which case starting instead at the + // start of the function declaration should be fine), but also for cases like + // + // void (*f())(); + // + // where the function name is within the function type (TODO: in which case starting + // at the start can erroneously pick up the "SAL_CALL" from the returned pointer-to- + // function type in cases like + // + // void SAL_CALL (*f())(); + // + // that are hopefully rare): + startAfterReturnType = false; + } + } + else + { + // startLoc is within a macro body; two source ranges, first is the remainder of the + // corresponding macro definition's replacement text, second is from after the macro + // invocation to endLoc, unless endLoc is already in the first range: + //TODO: If the macro is a function-like macro with a parameter named "SAL_CALL", uses of + // that parameter in the remainder of the replacement text will be false positives. + assert(SM.isMacroBodyExpansion(startLoc)); + auto const startLoc2 = compat::getImmediateExpansionRange(SM, startLoc).second; + auto name = Lexer::getImmediateMacroName(startLoc, SM, compiler.getLangOpts()); + while (name.startswith("\\\n")) + { + name = name.drop_front(2); + while (!name.empty() + && (name.front() == ' ' || name.front() == '\t' || name.front() == '\n' + || name.front() == '\v' || name.front() == '\f')) + { + name = name.drop_front(1); + } + } + auto const MI = compiler.getPreprocessor() + .getMacroDefinitionAtLoc(&compiler.getASTContext().Idents.get(name), + SM.getSpellingLoc(startLoc)) + .getMacroInfo(); + assert(MI != nullptr); + auto endLoc1 = MI->getDefinitionEndLoc(); + assert(endLoc1.isFileID()); + endLoc1 = Lexer::getLocForEndOfToken(endLoc1, 0, SM, compiler.getLangOpts()); + startLoc = Lexer::getLocForEndOfToken(SM.getSpellingLoc(startLoc), 0, SM, + compiler.getLangOpts()); + if (!SM.isPointWithin(endLoc, startLoc, endLoc1)) + { + ranges.emplace_back(startLoc, endLoc1); + startLoc = Lexer::getLocForEndOfToken(SM.getSpellingLoc(startLoc2), 0, SM, + compiler.getLangOpts()); + } + } + } + if (!startAfterReturnType) + { + // Stop searching for "SAL_CALL" at the start of the function declaration's name (for + // qualified names this will point after the qualifiers, but needlessly including those in + // the search should be harmless): + endLoc = functionDecl->getNameInfo().getBeginLoc(); + while (endLoc.isMacroID() && SM.isAtStartOfImmediateMacroExpansion(endLoc, &endLoc)) + { + } + + SourceRange macroRange; + if (SM.isMacroBodyExpansion(endLoc)) + { + auto name = Lexer::getImmediateMacroName(endLoc, SM, compiler.getLangOpts()); + while (name.startswith("\\\n")) + { + name = name.drop_front(2); + while (!name.empty() + && (name.front() == ' ' || name.front() == '\t' || name.front() == '\n' + || name.front() == '\v' || name.front() == '\f')) + { + name = name.drop_front(1); + } + } + auto const MI = compiler.getPreprocessor() + .getMacroDefinitionAtLoc(&compiler.getASTContext().Idents.get(name), + SM.getSpellingLoc(endLoc)) + .getMacroInfo(); + assert(MI != nullptr); + macroRange = SourceRange(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); + if (isDebugMode() && macroRange.isInvalid()) + { + report(DiagnosticsEngine::Fatal, "TODO: unexpected failure #4, needs investigation", + functionDecl->getLocation()) + << functionDecl->getSourceRange(); + } + } + +#if defined _WIN32 + auto const macroExpansion = SM.getExpansionLoc(endLoc); +#endif + endLoc = SM.getSpellingLoc(endLoc); + + // Ctors/dtors/conversion functions don't have a return type, start searching for "SAL_CALL" + // at the start of the function declaration: + startLoc = functionDecl->getSourceRange().getBegin(); + while (startLoc.isMacroID() + && !(macroRange.isValid() + && SM.isPointWithin(SM.getSpellingLoc(startLoc), macroRange.getBegin(), + macroRange.getEnd())) + && SM.isAtStartOfImmediateMacroExpansion(startLoc, &startLoc)) + { + } +#if !defined _WIN32 + auto const macroStartLoc = startLoc; +#endif + startLoc = SM.getSpellingLoc(startLoc); + +#if defined _WIN32 + if (macroRange.isValid() + && !SM.isPointWithin(startLoc, macroRange.getBegin(), macroRange.getEnd())) + { + // endLoc is within a macro body but startLoc is not; two source ranges, first is from + // startLoc to the macro invocation, second is the leading part of the corresponding + // macro definition's replacement text: + ranges.emplace_back(startLoc, macroExpansion); + startLoc = macroRange.getBegin(); + } +#else + // When the SAL_CALL macro expands to nothing, it may even precede the function + // declaration's source range, so go back one token (unless the declaration is known to + // start with a token that must precede a possible "SAL_CALL", like "virtual" or + // "explicit"): + //TODO: this will produce false positives if the declaration is immediately preceded by a + // macro definition whose replacement text ends in "SAL_CALL" + if (noReturnType + && !(functionDecl->isVirtualAsWritten() + || (isa(functionDecl) + && cast(functionDecl)->getExplicitSpecifier().isExplicit()) + || (isa(functionDecl) + && cast(functionDecl) + ->getExplicitSpecifier() + .isExplicit()))) + { + SourceLocation endLoc1; + if (macroStartLoc.isMacroID() + && SM.isAtStartOfImmediateMacroExpansion(macroStartLoc, &endLoc1)) + { + // startLoc is at the start of a macro body; two source ranges, first one is looking + // backwards one token from the call site of the macro: + auto startLoc1 = endLoc1; + for (;;) + { + startLoc1 = Lexer::GetBeginningOfToken(startLoc1.getLocWithOffset(-1), SM, + compiler.getLangOpts()); + auto const s = StringRef( + SM.getCharacterData(startLoc1), + Lexer::MeasureTokenLength(startLoc1, SM, compiler.getLangOpts())); + // When looking backward at least through a function-like macro replacement like + // + // | foo\ | + // | barbaz##X | + // + // starting at "barbaz" in the second line, the next token reported will start at "\" + // in the first line and include the intervening spaces and (part of? looks like an + // error in Clang) "barbaz", so just skip any tokens starting with backslash-newline + // when looking backwards here, without even trying to look at their content: + if (!(s.empty() || s.startswith("/*") || s.startswith("//") + || s.startswith("\\\n"))) + { + break; + } + } + ranges.emplace_back(startLoc1, endLoc1); + } + else + { + for (;;) + { + startLoc = Lexer::GetBeginningOfToken(startLoc.getLocWithOffset(-1), SM, + compiler.getLangOpts()); + auto const s = StringRef( + SM.getCharacterData(startLoc), + Lexer::MeasureTokenLength(startLoc, SM, compiler.getLangOpts())); + // When looking backward at least through a function-like macro replacement like + // + // | foo\ | + // | barbaz##X | + // + // starting at "barbaz" in the second line, the next token reported will start at "\" + // in the first line and include the intervening spaces and (part of? looks like an + // error in Clang) "barbaz", so just skip any tokens starting with backslash-newline + // when looking backwards here, without even trying to look at their content: + if (!(s.empty() || s.startswith("/*") || s.startswith("//") + || s.startswith("\\\n"))) + { + break; + } + } + } + } +#endif + } + ranges.emplace_back(startLoc, endLoc); + + for (auto const& range : ranges) + { + if (range.isInvalid()) + { + if (isDebugMode()) + { + report(DiagnosticsEngine::Fatal, "TODO: unexpected failure #2, needs investigation", + functionDecl->getLocation()) + << functionDecl->getSourceRange(); + } + return false; + } + if (isDebugMode() && range.getBegin() != range.getEnd() + && !SM.isBeforeInTranslationUnit(range.getBegin(), range.getEnd())) + { + report(DiagnosticsEngine::Fatal, "TODO: unexpected failure #3, needs investigation", + functionDecl->getLocation()) + << functionDecl->getSourceRange(); + } + + for (auto loc = range.getBegin(); SM.isBeforeInTranslationUnit(loc, range.getEnd());) + { + unsigned n = Lexer::MeasureTokenLength(loc, SM, compiler.getLangOpts()); + auto s = StringRef(compiler.getSourceManager().getCharacterData(loc), n); + while (s.startswith("\\\n")) + { + s = s.drop_front(2); + while (!s.empty() + && (s.front() == ' ' || s.front() == '\t' || s.front() == '\n' + || s.front() == '\v' || s.front() == '\f')) + { + s = s.drop_front(1); + } + } + if (s == "SAL_CALL") + { + if (pLoc) + *pLoc = loc; + return true; + } + loc = loc.getLocWithOffset(std::max(n, 1)); + } + } + return false; +} + +bool SalCall::rewrite(SourceLocation locBegin) +{ + if (!rewriter) + return false; + if (!locBegin.isValid()) + return false; + + auto locEnd = locBegin.getLocWithOffset(8); + if (!locEnd.isValid()) + return false; + + SourceRange range(locBegin, locEnd); + + if (!replaceText(locBegin, 9, "")) + return false; + + return true; +} + +static loplugin::Plugin::Registration reg("salcall", true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/sallogareas.cxx b/compilerplugins/clang/sallogareas.cxx new file mode 100644 index 000000000..bd71128aa --- /dev/null +++ b/compilerplugins/clang/sallogareas.cxx @@ -0,0 +1,284 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" +#include "check.hxx" +#include "compat.hxx" + +#include + +#include +#include + +namespace +{ + +class SalLogAreas + : public loplugin::FilteringPlugin< SalLogAreas > + { + public: + explicit SalLogAreas( const loplugin::InstantiationData& data ) + : FilteringPlugin(data), inFunction(nullptr) {} + + bool preRun() override { + return true; + } + + void run() override { + if (preRun()) + { + lastSalDetailLogStreamMacro = SourceLocation(); + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitFunctionDecl( const FunctionDecl* function ); + bool VisitCallExpr( const CallExpr* call ); + private: + void checkArea( StringRef area, SourceLocation location ); + void checkAreaSyntax(StringRef area, SourceLocation location); + void readLogAreas(); + const FunctionDecl* inFunction; + SourceLocation lastSalDetailLogStreamMacro; + std::set< std::string > logAreas; +#if 0 + std::string firstSeenLogArea; + SourceLocation firstSeenLocation; +#endif + }; + +/* +This is a compile check. + +Check area used in SAL_INFO/SAL_WARN macros against the list in include/sal/log-areas.dox and +report if the area is not listed there. The fix is either use a proper area or add it to the list +if appropriate. +*/ + +bool SalLogAreas::VisitFunctionDecl( const FunctionDecl* function ) + { + inFunction = function; + return true; + } + +bool SalLogAreas::VisitCallExpr( const CallExpr* call ) + { + if( ignoreLocation( call )) + return true; + const FunctionDecl* func = call->getDirectCallee(); + if( !func || !func->getIdentifier()) + return true; + + auto name = func->getName(); + if( !( name == "sal_detail_log" || name == "log" || name == "DbgUnhandledException" || name == "XMLOFF_WARN_UNKNOWN") ) + return true; + + auto tc = loplugin::DeclCheck(func); + enum class LogCallKind { Sal, DbgUnhandledException}; + LogCallKind kind; + int areaArgIndex; + if( tc.Function("XMLOFF_WARN_UNKNOWN") ) + { + kind = LogCallKind::Sal; // fine + areaArgIndex = 0; + } + else if( tc.Function("sal_detail_log") || tc.Function("log").Namespace("detail").Namespace("sal").GlobalNamespace() ) + { + kind = LogCallKind::Sal; // fine + areaArgIndex = 1; + } + else if( tc.Function("DbgUnhandledException").GlobalNamespace() ) + { + kind = LogCallKind::DbgUnhandledException; // ok + areaArgIndex = 3; + } + else + return true; + + // The SAL_DETAIL_LOG_STREAM macro expands to two calls to sal::detail::log(), + // so do not warn repeatedly about the same macro (the area->getLocStart() of all the calls + // from the same macro should be the same). + if( kind == LogCallKind::Sal ) + { + SourceLocation expansionLocation = compiler.getSourceManager().getExpansionLoc( call->getBeginLoc()); + if( expansionLocation == lastSalDetailLogStreamMacro ) + return true; + lastSalDetailLogStreamMacro = expansionLocation; + }; + if( const clang::StringLiteral* area = dyn_cast< clang::StringLiteral >( call->getArg( areaArgIndex )->IgnoreParenImpCasts())) + { + if( area->getKind() == clang::StringLiteral::Ascii ) + checkArea( area->getBytes(), area->getExprLoc()); + else + report( DiagnosticsEngine::Warning, "unsupported string literal kind (plugin needs fixing?)", + area->getBeginLoc()); + return true; + } + if( loplugin::DeclCheck(inFunction).Function("log").Namespace("detail").Namespace("sal").GlobalNamespace() + || loplugin::DeclCheck(inFunction).Function("sal_detail_logFormat").GlobalNamespace() ) + return true; // These functions only forward to sal_detail_log, so ok. + if( loplugin::DeclCheck(inFunction).Function("XMLOFF_WARN_UNKNOWN").GlobalNamespace()) + return true; + if( call->getArg( areaArgIndex )->isNullPointerConstant( compiler.getASTContext(), + Expr::NPC_ValueDependentIsNotNull ) != Expr::NPCK_NotNull ) + { // If the area argument is a null pointer, that is allowed only for SAL_DEBUG. + const SourceManager& source = compiler.getSourceManager(); + for( SourceLocation loc = call->getBeginLoc(); + loc.isMacroID(); + loc = compat::getImmediateExpansionRange(source, loc ).first ) + { + StringRef inMacro = Lexer::getImmediateMacroName( loc, source, compiler.getLangOpts()); + if( inMacro == "SAL_DEBUG" || inMacro == "SAL_DEBUG_BACKTRACE" ) + return true; // ok + } + report( DiagnosticsEngine::Warning, "missing log area", + call->getArg( 1 )->IgnoreParenImpCasts()->getBeginLoc()); + return true; + } + report( DiagnosticsEngine::Warning, "cannot analyse log area argument (plugin needs fixing?)", + call->getBeginLoc()); + return true; + } + +void SalLogAreas::checkArea( StringRef area, SourceLocation location ) + { + if( logAreas.empty()) + readLogAreas(); + if( !logAreas.count( area.str() )) + { + report( DiagnosticsEngine::Warning, "unknown log area '%0' (check or extend include/sal/log-areas.dox)", + location ) << area; + checkAreaSyntax(area, location); + return; + } +// don't leave this alive by default, generates too many false+ +#if 0 + if (compiler.getSourceManager().isInMainFile(location)) + { + auto matchpair = [this,area](StringRef p1, StringRef p2) { + return (area == p1 && firstSeenLogArea == p2) || (area == p2 && firstSeenLogArea == p1); + }; + // these are "cross-module" log areas + if (area == "i18n" || area == "lok" || area == "lok.tiledrendering") + ; + // these appear to be cross-file log areas + else if ( area == "chart2" + || area == "oox.cscode" || area == "oox.csdata" + || area == "slideshow.verbose" + || area == "sc.opencl" + || area == "sc.core.formulagroup" + || area == "sw.pageframe" || area == "sw.idle" || area == "sw.level2" + || area == "sw.docappend" || area == "sw.mailmerge" + || area == "sw.uno" + || area == "vcl.layout" || area == "vcl.a11y" + || area == "vcl.gdi.fontmetric" || area == "vcl.opengl" + || area == "vcl.harfbuzz" || area == "vcl.eventtesting" + || area == "vcl.schedule" || area == "vcl.unity" + || area == "xmlsecurity.comp" + ) + ; + else if (firstSeenLogArea == "") + { + firstSeenLogArea = area; + firstSeenLocation = location; + } + // some modules do this deliberately + else if (firstSeenLogArea.compare(0, 3, "jfw") == 0 + || firstSeenLogArea.compare(0, 6, "opencl") == 0) + ; + // mixing these in the same file seems legitimate + else if ( + matchpair("chart2.pie.label.bestfit", "chart2.pie.label.bestfit.inside") + || matchpair("editeng", "editeng.chaining") + || matchpair("oox.drawingml", "oox.cscode") + || matchpair("oox.drawingml", "oox.drawingml.gradient") + || matchpair("sc.core", "sc.core.grouparealistener") + || matchpair("sc.orcus", "sc.orcus.condformat") + || matchpair("sc.orcus", "sc.orcus.style") + || matchpair("sc.orcus", "sc.orcus.autofilter") + || matchpair("svx", "svx.chaining") + || matchpair("sw.ww8", "sw.ww8.level2") + || matchpair("writerfilter", "writerfilter.profile") + ) + ; + else if (firstSeenLogArea != area) + { + report( DiagnosticsEngine::Warning, "two different log areas '%0' and '%1' in the same file?", + location ) << firstSeenLogArea << area; + report( DiagnosticsEngine::Note, "first area was seen here", + firstSeenLocation ); + } + } +#endif + } + +void SalLogAreas::checkAreaSyntax(StringRef area, SourceLocation location) { + for (std::size_t i = 0;;) { + std::size_t j = area.find('.', i); + if (j == StringRef::npos) { + j = area.size(); + } + if (j == i) { + goto bad; + } + for (; i != j; ++i) { + auto c = area[i]; + if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z'))) { + goto bad; + } + } + if (j == area.size()) { + return; + } + i = j + 1; + } +bad: + report( + DiagnosticsEngine::Warning, + "invalid log area syntax '%0'%1 (see include/sal/log.hxx for details)", + location) + << area << (location.isValid() ? "" : " in include/sal/log-areas.dox"); +} + +void SalLogAreas::readLogAreas() + { + std::ifstream is( SRCDIR "/include/sal/log-areas.dox" ); + while( is.good()) + { + std::string line; + getline( is, line ); + size_t pos = line.find( "@li @c " ); + if( pos != std::string::npos ) + { + pos += strlen( "@li @c " ); + size_t end = line.find( ' ', pos ); + std::string area; + if( end == std::string::npos ) + area = line.substr( pos ); + else if( pos != end ) + area = line.substr( pos, end - pos ); + checkAreaSyntax(area, SourceLocation()); + logAreas.insert(area); + } + } + // If you get this error message, you possibly have too old icecream (ICECC_EXTRAFILES is needed). + if( logAreas.empty()) + report( DiagnosticsEngine::Warning, "error reading log areas" ); + } + +static loplugin::Plugin::Registration< SalLogAreas > sallogareas( "sallogareas" ); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/salunicodeliteral.cxx b/compilerplugins/clang/salunicodeliteral.cxx new file mode 100644 index 000000000..aa0a3950c --- /dev/null +++ b/compilerplugins/clang/salunicodeliteral.cxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "plugin.hxx" + +namespace { + +bool isAsciiCharacterLiteral(Expr const * expr) { + if (auto const e = dyn_cast(expr)) { + return e->getKind() == CharacterLiteral::Ascii; + } + return false; +} + +class SalUnicodeLiteral final: + public loplugin::FilteringPlugin +{ +public: + explicit SalUnicodeLiteral(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + bool VisitCXXStaticCastExpr(CXXStaticCastExpr const * expr) { + check(expr); + return true; + } + + bool VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const * expr) { + check(expr); + return true; + } + + bool VisitCStyleCastExpr(CStyleCastExpr const * expr) { + check(expr); + return true; + } + + bool preRun() override { + return compiler.getLangOpts().CPlusPlus + && compiler.getPreprocessor().getIdentifierInfo( + "LIBO_INTERNAL_ONLY")->hasMacroDefinition(); + } + + void run() override { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + +private: + void check(ExplicitCastExpr const * expr) { + if (ignoreLocation(expr) + || isInUnoIncludeFile(expr->getExprLoc())) + //TODO: '#ifdef LIBO_INTERNAL_ONLY' within UNO include files + { + return; + } + for (auto t = expr->getTypeAsWritten();;) { + auto const tt = t->getAs(); + if (tt == nullptr) { + return; + } + if (loplugin::TypeCheck(t).Typedef("sal_Unicode") + .GlobalNamespace()) + { + break; + } + t = tt->desugar(); + } + auto const e1 = expr->getSubExprAsWritten(); + auto const loc = e1->getBeginLoc(); + if (loc.isMacroID() + && compiler.getSourceManager().isAtStartOfImmediateMacroExpansion( + loc)) + { + return; + } + auto const e2 = e1->IgnoreParenImpCasts(); + if (isAsciiCharacterLiteral(e2) || isa(e2)) { + report( + DiagnosticsEngine::Warning, + ("in LIBO_INTERNAL_ONLY code, replace literal cast to %0 with a" + " u'...' char16_t character literal"), + e2->getExprLoc()) + << expr->getTypeAsWritten() << expr->getSourceRange(); + } + } +}; + +static loplugin::Plugin::Registration salunicodeliteral("salunicodeliteral"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/selfinit.cxx b/compilerplugins/clang/selfinit.cxx new file mode 100644 index 000000000..3891a5fc7 --- /dev/null +++ b/compilerplugins/clang/selfinit.cxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include + +#include "plugin.hxx" + +// Warn when a variable is referenced from its own initializer. This is not invalid in general (see +// C++17 [basic.life]), but is at least suspicious. + +namespace +{ +class SelfInit : public loplugin::FilteringPlugin +{ +public: + explicit SelfInit(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool PreTraverseVarDecl(VarDecl* decl) + { + decls_.push_back({ decl, decl->getCanonicalDecl() }); + return true; + } + bool PostTraverseVarDecl(VarDecl*, bool) + { + decls_.pop_back(); + return true; + } + bool TraverseVarDecl(VarDecl* decl) + { + PreTraverseVarDecl(decl); + auto const ret = FilteringPlugin::TraverseVarDecl(decl); + PostTraverseVarDecl(decl, ret); + return ret; + } + + bool PreTraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr* expr) + { + if (expr->getKind() == UETT_SizeOf) + return false; + return true; + } + bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr* expr) + { + if (PreTraverseUnaryExprOrTypeTraitExpr(expr)) + return FilteringPlugin::TraverseUnaryExprOrTypeTraitExpr(expr); + return true; + } + + bool TraverseCXXTypeidExpr(CXXTypeidExpr*) { return true; } + bool PreTraverseCXXTypeidExpr(CXXTypeidExpr*) { return false; } + + bool TraverseCXXNoexceptExpr(CXXNoexceptExpr*) { return true; } + bool PreTraverseCXXNoexceptExpr(CXXNoexceptExpr*) { return false; } + + bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) { return true; } + bool PreTraverseDecltypeTypeLoc(DecltypeTypeLoc) { return false; } + + bool VisitDeclRefExpr(DeclRefExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + for (auto const& i : decls_) + { + if (expr->getDecl()->getCanonicalDecl() == i.canonical) + { + report( + DiagnosticsEngine::Warning, + ("referencing a variable during its own initialization is error-prone and thus" + " suspicious"), + expr->getLocation()) + << expr->getSourceRange(); + report(DiagnosticsEngine::Note, "variable declared here", i.current->getLocation()) + << i.current->getSourceRange(); + } + } + return true; + } + +private: + void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + struct Decl + { + VarDecl const* current; + VarDecl const* canonical; + }; + + std::vector decls_; +}; + +loplugin::Plugin::Registration selfinit("selfinit"); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/sequentialassign.cxx b/compilerplugins/clang/sequentialassign.cxx new file mode 100644 index 000000000..01172df17 --- /dev/null +++ b/compilerplugins/clang/sequentialassign.cxx @@ -0,0 +1,327 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +/** + This is a kind of simplified dead-store analysis. + + We are looking for patterns like: + Foo x = a; + x = b; + which can be simplified to + x = b + + or + Foo x = a; + x = f(x) + which can be simplified to + Foo x = f(a) + + TODO Improve this plugin to make it safer. We should really be checking the following + conditions inside the RHS of the second statement: + If the variable is having it's address taken, or a non-const method called on it, + on passed by non-const-ref. +*/ + +namespace +{ +//static bool startswith(const std::string& rStr, const char* pSubStr) { +// return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; +//} +class SequentialAssign : public loplugin::FilteringPlugin +{ +public: + explicit SequentialAssign(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + // places where the existing code style just looks better + // TODO lots of these would be unnecessary if I taught the plugin + // to ignore vars which are assigned to repeatedly + if (fn == SRCDIR "/vcl/source/helper/commandinfoprovider.cxx" + || fn == SRCDIR "/basegfx/source/polygon/b2dpolygonclipper.cxx" + || fn == SRCDIR "/i18nlangtag/source/isolang/insys.cxx" + || fn == SRCDIR "/vcl/unx/generic/fontmanager/fontconfig.cxx" + || fn == SRCDIR "/svtools/source/filter/exportdialog.cxx" + || fn == SRCDIR "/svtools/source/control/ruler.cxx" + || fn == SRCDIR "/basic/qa/cppunit/test_scanner.cxx" + || fn == SRCDIR "/basic/source/uno/namecont.cxx" + || fn == SRCDIR "/test/source/sheet/xnamedrange.cxx" + || fn == SRCDIR "/i18npool/qa/cppunit/test_breakiterator.cxx" + || fn == SRCDIR "/i18npool/source/localedata/LocaleNode.cxx" + || fn == SRCDIR "/i18npool/source/transliteration/transliteration_Ignore.cxx" + || fn == SRCDIR "/i18npool/qa/cppunit/test_textsearch.cxx" + || fn == SRCDIR "/framework/source/jobs/jobdata.cxx" + || fn == SRCDIR "/framework/source/services/pathsettings.cxx" + || fn == SRCDIR "/xmloff/source/chart/SchXMLTools.cxx" + || fn == SRCDIR "/svx/source/tbxctrls/Palette.cxx" + || fn == SRCDIR "/svx/source/sdr/contact/objectcontactofpageview.cxx" + || fn == SRCDIR "/svx/source/form/fmservs.cxx" + || fn == SRCDIR "/svx/source/svdraw/svdograf.cxx" + || fn == SRCDIR "/svx/source/accessibility/AccessibleShape.cxx" + || fn == SRCDIR "/svx/source/fmcomp/fmgridcl.cxx" + || fn == SRCDIR "/chart2/source/tools/CharacterProperties.cxx" + || fn == SRCDIR "/svx/source/dialog/dialcontrol.cxx" + || fn == SRCDIR "/connectivity/source/commontools/TTableHelper.cxx" + || fn == SRCDIR "/svx/source/dialog/_bmpmask.cxx" + || fn == SRCDIR "/media/noel/disk2/libo4/cui/source/dialogs/SignSignatureLineDialog.cxx" + || fn == SRCDIR "/filter/source/msfilter/msdffimp.cxx" + || fn == SRCDIR "/cui/source/dialogs/SignSignatureLineDialog.cxx" + || fn == SRCDIR "/cui/source/dialogs/screenshotannotationdlg.cxx" + || fn == SRCDIR "/cui/source/options/optupdt.cxx" + || fn == SRCDIR "/dbaccess/source/ui/querydesign/querycontroller.cxx" + || fn == SRCDIR "/dbaccess/source/ui/dlg/DbAdminImpl.cxx" + || fn == SRCDIR "/dbaccess/source/ui/querydesign/JoinController.cxx" + || fn == SRCDIR "/dbaccess/source/ui/misc/TokenWriter.cxx" + || fn == SRCDIR "/dbaccess/source/ui/misc/TokenWriter.cxx" + || fn == SRCDIR "/dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx" + || fn == SRCDIR "/dbaccess/source/core/api/querycomposer.cxx" + || fn == SRCDIR "/desktop/source/lib/init.cxx" + || fn == SRCDIR "/lotuswordpro/source/filter/lwpfribmark.cxx" + || fn == SRCDIR "/tools/qa/cppunit/test_color.cxx" + || fn == SRCDIR "/sc/qa/unit/ucalc.cxx" + || fn == SRCDIR "/sc/source/ui/view/printfun.cxx" + || fn == SRCDIR "/sc/source/ui/view/preview.cxx" + || fn == SRCDIR "/sw/source/core/doc/tblafmt.cxx" + || fn == SRCDIR "/sw/source/core/draw/dflyobj.cxx" + || fn == SRCDIR "/sw/source/core/doc/DocumentDrawModelManager.cxx" + || fn == SRCDIR "/sw/source/core/edit/edfcol.cxx" + || fn == SRCDIR "/sw/source/filter/ww8/ww8toolbar.cxx" + || fn == SRCDIR "/sw/source/ui/fldui/fldvar.cxx" + || fn == SRCDIR "/sw/source/filter/ww8/ww8atr.cxx" + || fn == SRCDIR "/sd/source/ui/accessibility/AccessiblePageShape.cxx" + || fn == SRCDIR "/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx" + || fn == SRCDIR "/sd/source/ui/slidesorter/cache/SlsRequestFactory.cxx" + || fn == SRCDIR "/sd/source/ui/framework/configuration/ResourceId.cxx" + || fn == SRCDIR "/sd/source/filter/html/htmlex.cxx" + || fn == SRCDIR "/starmath/source/cfgitem.cxx" + || fn == SRCDIR "/ucb/source/ucp/ftp/ftpurl.cxx" + || fn == SRCDIR "/starmath/source/node.cxx" + || fn == SRCDIR "/starmath/source/starmathdatabase.cxx" + || fn == SRCDIR "/ucb/source/ucp/cmis/certvalidation_handler.cxx" + || fn == SRCDIR "/reportdesign/source/ui/inspection/GeometryHandler.cxx" + || fn == SRCDIR "/reportdesign/source/core/api/ReportDefinition.cxx" + || fn == SRCDIR "/test/source/table/tablerow.cxx" + || fn == SRCDIR "/basegfx/test/B2DHomMatrixTest.cxx" + || fn == SRCDIR "/comphelper/qa/unit/base64_test.cxx" + || fn == SRCDIR "/testtools/source/bridgetest/bridgetest.cxx" + || fn == SRCDIR "/comphelper/qa/string/test_string.cxx" + || fn == SRCDIR "/cppu/qa/test_unotype.cxx" + || fn == SRCDIR "/cppu/qa/cppumaker/test_cppumaker.cxx" + || fn == SRCDIR "/o3tl/qa/test-lru_map.cxx" || fn == SRCDIR "/svl/qa/unit/svl.cxx" + || fn == SRCDIR "/chart2/qa/extras/PivotChartTest.cxx" + || fn == SRCDIR "/chart2/qa/extras/chart2export.cxx" + || fn == SRCDIR "/writerfilter/qa/cppunittests/misc/misc.cxx" + || fn == SRCDIR "/sw/qa/extras/ww8export/ww8export.cxx" + || fn == SRCDIR "/sw/qa/extras/uiwriter/uiwriter.cxx") + return; + // inside ifdef + if (fn == SRCDIR "/vcl/source/filter/png/pngread.cxx" + || fn == SRCDIR "/vcl/source/window/syschild.cxx" + || fn == SRCDIR "/sal/osl/unx/security.cxx" + || fn == SRCDIR "/vcl/source/filter/png/pngwrite.cxx" + || fn == SRCDIR "/svtools/source/control/inettbc.cxx" + || fn == SRCDIR "/canvas/source/cairo/cairo_textlayout.cxx" + || fn == SRCDIR "/sal/qa/osl/file/osl_File.cxx") + return; + // taking address of variable + if (fn == SRCDIR "/vcl/unx/generic/dtrans/X11_selection.cxx") + return; + // other + if (fn == SRCDIR "/sc/source/core/tool/scmatrix.cxx" + || fn == SRCDIR "/sal/qa/rtl/oustringbuffer/test_oustringbuffer_assign.cxx") + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCompoundStmt(CompoundStmt const*); + +private: + const VarDecl* findSimpleAssign(Stmt const*); + bool isSimpleRHS(Expr const*); + Expr const* ignore(Expr const*); + void checkForSecondAssign(Stmt const* stmt, VarDecl const* varDecl); +}; + +bool SequentialAssign::VisitCompoundStmt(CompoundStmt const* compoundStmt) +{ + if (ignoreLocation(compoundStmt)) + return true; + + auto it = compoundStmt->body_begin(); + while (true) + { + if (it == compoundStmt->body_end()) + break; + auto firstStmt = *it; + const VarDecl* foundVars = findSimpleAssign(firstStmt); + // reference types have slightly weird behaviour + if (!foundVars || foundVars->getType()->isReferenceType()) + { + ++it; + continue; + } + ++it; + if (it == compoundStmt->body_end()) + break; + checkForSecondAssign(*it, foundVars); + } + + return true; +} + +void SequentialAssign::checkForSecondAssign(Stmt const* stmt, VarDecl const* varDecl) +{ + if (auto exprCleanup = dyn_cast(stmt)) + stmt = exprCleanup->getSubExpr(); + + if (auto operatorCall = dyn_cast(stmt)) + { + if (operatorCall->getOperator() == OO_Equal) + { + if (auto declRefExprLHS = dyn_cast(ignore(operatorCall->getArg(0)))) + if (declRefExprLHS->getDecl() == varDecl) + { + report(DiagnosticsEngine::Warning, + "simplify by merging with the preceding assignment", stmt->getBeginLoc()) + << stmt->getSourceRange(); + } + } + return; + } + + if (auto binaryOp = dyn_cast(stmt)) + { + if (binaryOp->getOpcode() == BO_Assign) + { + if (auto declRefExpr = dyn_cast(ignore(binaryOp->getLHS()))) + if (declRefExpr->getDecl() == varDecl) + { + report(DiagnosticsEngine::Warning, + "simplify by merging with the preceding assignment", stmt->getBeginLoc()) + << stmt->getSourceRange(); + } + } + } +} + +const VarDecl* SequentialAssign::findSimpleAssign(Stmt const* stmt) +{ + if (auto declStmt = dyn_cast(stmt)) + if (declStmt->isSingleDecl()) + if (auto varDeclLHS = dyn_cast_or_null(declStmt->getSingleDecl())) + { + if (varDeclLHS->getStorageDuration() == SD_Static) + return nullptr; + // if it's call-style init (e.g. OUString s("xxx")), we only treat + // it as simple if it only contains a variable in the call + // (e.g. OUString s(x)) + if (varDeclLHS->getInitStyle() == VarDecl::InitializationStyle::CallInit) + { + auto cxxConstructExpr + = dyn_cast(ignore(varDeclLHS->getInit())); + if (cxxConstructExpr) + { + if (cxxConstructExpr->getNumArgs() == 0) + return varDeclLHS; + if (cxxConstructExpr->getNumArgs() > 1) + return nullptr; + if (!isa(ignore(cxxConstructExpr->getArg(0)))) + return nullptr; + } + } + if (auto init = varDeclLHS->getInit()) + if (isSimpleRHS(init)) + return varDeclLHS; + } + if (auto operatorCall = dyn_cast(stmt)) + if (operatorCall->getOperator() == OO_Equal) + if (auto declRefExprLHS = dyn_cast(ignore(operatorCall->getArg(0)))) + if (auto varDeclLHS = dyn_cast(declRefExprLHS->getDecl())) + if (isSimpleRHS(operatorCall->getArg(1))) + return varDeclLHS; + if (auto binaryOp = dyn_cast(stmt)) + if (binaryOp->getOpcode() == BO_Assign) + if (auto declRefExprLHS = dyn_cast(ignore(binaryOp->getLHS()))) + if (auto varDeclLHS = dyn_cast(declRefExprLHS->getDecl())) + if (isSimpleRHS(binaryOp->getRHS())) + return varDeclLHS; + return nullptr; +} + +/** + Does the first statement have a relatively simply RHS we can inline into the second statement? +*/ +bool SequentialAssign::isSimpleRHS(Expr const* expr) +{ + expr = ignore(expr); + + // code like + // Point aCurPos = rGlyphs + // always has a CXXConstructExpr wrapping the RHS + if (auto cxxConstructExpr = dyn_cast(expr)) + if (cxxConstructExpr->getNumArgs() == 1) + expr = ignore(cxxConstructExpr->getArg(0)); + + if (!expr->isValueDependent() + && expr->isConstantInitializer(compiler.getASTContext(), false /*ForRef*/)) + return true; + if (isa(expr)) + return false; + if (isa(expr)) + return false; + if (isa(expr)) + return true; + if (isa(expr)) + return false; + if (isa(expr)) + return false; + if (isa(expr)) + return false; + if (isa(expr)) + return false; + if (isa(expr)) + return false; + if (isa(expr)) + return false; + if (isa(expr)) + return false; + if (auto memberExpr = dyn_cast(expr)) + return isSimpleRHS(memberExpr->getBase()); + + return true; +} + +Expr const* SequentialAssign::ignore(Expr const* expr) +{ + return expr->IgnoreImplicit()->IgnoreParens()->IgnoreImplicit(); +} + +// Off by default because of safety concerns, see TODO at top +loplugin::Plugin::Registration X("sequentialassign", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/sfxpoolitem.cxx b/compilerplugins/clang/sfxpoolitem.cxx new file mode 100644 index 000000000..801689f0f --- /dev/null +++ b/compilerplugins/clang/sfxpoolitem.cxx @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "clang/AST/CXXInheritance.h" + +/* +what might be more interesting is a warning about subclasses that add +members but do not override virtual operator==() - that is easily +forgotten and hard to notice. +*/ +namespace { + +class SfxPoolItem: + public loplugin::FilteringPlugin +{ +public: + explicit SfxPoolItem(loplugin::InstantiationData const & data): FilteringPlugin(data) + {} + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXRecordDecl( const CXXRecordDecl* ); +}; + +bool BaseCheckNotSfxPoolItemSubclass(const CXXRecordDecl *BaseDefinition) { + if (BaseDefinition && loplugin::TypeCheck(BaseDefinition).Class("SfxPoolItem").GlobalNamespace()) { + return false; + } + return true; +} + +bool isDerivedFromSfxPoolItem(const CXXRecordDecl *decl) { + if (!decl) + return false; + if (loplugin::TypeCheck(decl).Class("SfxPoolItem").GlobalNamespace()) + return true; + if (!decl->hasDefinition()) { + return false; + } + if (// not sure what hasAnyDependentBases() does, + // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1 + !decl->hasAnyDependentBases() && + !decl->forallBases(BaseCheckNotSfxPoolItemSubclass)) { + return true; + } + return false; +} + + +bool BaseCheckNotSwMsgPoolItemSubclass(const CXXRecordDecl *BaseDefinition) { + if (BaseDefinition && loplugin::TypeCheck(BaseDefinition).Class("SwMsgPoolItem")) { + return false; + } + return true; +} + +bool isDerivedFromSwMsgPoolItem(const CXXRecordDecl *decl) { + if (!decl) + return false; + if (loplugin::TypeCheck(decl).Class("SwMsgPoolItem").GlobalNamespace()) + return true; + if (!decl->hasDefinition()) { + return false; + } + if (// not sure what hasAnyDependentBases() does, + // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1 + !decl->hasAnyDependentBases() && + !decl->forallBases(BaseCheckNotSwMsgPoolItemSubclass)) { + return true; + } + return false; +} + +bool endsWith(const std::string& a, const std::string& b) { + if (b.size() > a.size()) return false; + return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin()); +} + +bool SfxPoolItem::VisitCXXRecordDecl(const CXXRecordDecl* decl) +{ + if (ignoreLocation(decl)) { + return true; + } + if (!decl->hasDefinition()) { + return true; + } + // check if this class is derived from Window + if (!isDerivedFromSfxPoolItem(decl)) { + return true; + } + // the SwMsgPoolItem are some sort of hack to transport down-castable objects to SwClient::Modify(), they're not "real" items + if (isDerivedFromSwMsgPoolItem(decl)) { + return true; + } + if (decl->field_begin() == decl->field_end()) { + return true; + } + // the enum types do some weird stuff involving SfxEnumItemInterface + auto tc = loplugin::TypeCheck(decl); + if (tc.Class("SfxEnumItem").GlobalNamespace() || tc.Class("SfxAllEnumItem").GlobalNamespace()) + return true; + + for (auto it = decl->method_begin(); it != decl->method_end(); ++it) { + if ( endsWith((*it)->getQualifiedNameAsString(), "::operator==") ) + return true; + } + report( + DiagnosticsEngine::Warning, + "SfxPoolItem subclass %0 declares new fields, but does not override operator==", + decl->getBeginLoc()) + << decl->getQualifiedNameAsString() << decl->getSourceRange(); + return true; +} + + +loplugin::Plugin::Registration< SfxPoolItem > sfxpoolitem("sfxpoolitem"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/sharedvisitor/README b/compilerplugins/clang/sharedvisitor/README new file mode 100644 index 000000000..7b4a8b3c7 --- /dev/null +++ b/compilerplugins/clang/sharedvisitor/README @@ -0,0 +1,45 @@ +These tools generate another "plugin" which in fact only dispatches Visit* and Traverse* +calls to all other plugins registered with it. This means that there is just one +RecursiveASTVisitor pass for all those plugins instead of one per each, which +with the current number of plugins actually makes a performance difference. + +If you work on a plugin, comment out LO_CLANG_SHARED_PLUGINS in Makefile-clang.mk in order +to disable the feature (re-generating takes time). + +There are two tools: +- analyzer, which analyses one .cxx file (one plugins) and writes info about it to a .plugininfo + file, this allows parallelising this part, since it can take some time +- generator, which reads all the .plugininfo files and generates sharedvisitor.cxx + +Requirements for plugins: +- Can use Visit* and Traverse* functions, but not WalkUp*. +- Visit* functions can generally remain unmodified. +- run() function must be split into preRun() and postRun() if there's any additional functionality + besides calling TraverseDecl(). The shared visitor will call the preRun() and postRun() functions + as necessary while calling its own run(). The run() function of the plugin must stay + (in case of a non-shared build) but should generally look like this: + if( preRun()) + if( TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) + postRun(); +- Traverse* functions must be split into PreTraverse* and PostTraverse*, similarly to how run() + is handled, the Traverse* function should generally look like this: + bool ret = true; + if( PreTraverse*(decl)) + { + ret = RecursiveASTVisitor::Traverse*(decl); + PostTraverse*(decl, ret); + } + return ret; + + +TODO: +- Create macros for the standardized layout of run(), Traverse*, etc.? +- Possibly check plugin sources more thoroughly (e.g. that run() doesn't actually do more). +- Have one tool that extracts info from plugin .cxx files into some .txt file and another tool + that generates sharedvisitor.cxx based on those files? That would generally make the generation + faster when doing incremental changes. The .txt file could also contain some checksum of the .cxx + to avoid the analysing pass completely if just the timestamp has changed. +- Do not re-compile sharedvisitor.cxx if its contents have not actually changed. +- Is it possible to make the clang code analyze just the .cxx without also parsing all the headers? +- Instead of having to comment out LO_CLANG_SHARED_PLUGINS, implement --enable-compiler-plugins=debug . +- Try make analyzer use a precompiled header of Clang headers, for better performance. diff --git a/compilerplugins/clang/sharedvisitor/analyzer.cxx b/compilerplugins/clang/sharedvisitor/analyzer.cxx new file mode 100644 index 000000000..a000bd249 --- /dev/null +++ b/compilerplugins/clang/sharedvisitor/analyzer.cxx @@ -0,0 +1,299 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/StringExtras.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "config_clang.h" +#include "../check.hxx" +#include "../check.cxx" + +using namespace clang; +using namespace llvm; + +using namespace loplugin; + +// Info about a Traverse* function in a plugin. +struct TraverseFunctionInfo +{ + std::string name; + std::string argument; + bool hasPre = false; + bool hasPost = false; +}; + +struct TraverseFunctionInfoLess +{ + bool operator()( const TraverseFunctionInfo& l, const TraverseFunctionInfo& r ) const + { + return l.name < r.name; + } +}; + +static std::set< TraverseFunctionInfo, TraverseFunctionInfoLess > traverseFunctions; + +class CheckFileVisitor + : public RecursiveASTVisitor< CheckFileVisitor > +{ +public: + void setContext(ASTContext const& context) { context_ = &context; } + + bool VisitCXXRecordDecl(CXXRecordDecl *Declaration); + + bool TraverseNamespaceDecl(NamespaceDecl * decl) + { + // Skip non-LO namespaces the same way FilteringPlugin does. + if( !ContextCheck( decl ).Namespace( "loplugin" ).GlobalNamespace() + && !ContextCheck( decl ).AnonymousNamespace()) + { + return true; + } + return RecursiveASTVisitor::TraverseNamespaceDecl(decl); + } + +private: + ASTContext const* context_ = nullptr; + + QualType unqualifyPointeeType(QualType type) + { + assert(context_ != nullptr); + if (auto const t = type->getAs()) + { + return context_->getQualifiedType( + context_->getPointerType(t->getPointeeType().getUnqualifiedType()), + type.getQualifiers()); + } + return type; + } +}; + +static bool inheritsPluginClassCheck( const Decl* decl ) +{ + return bool( DeclCheck( decl ).Class( "FilteringPlugin" ).Namespace( "loplugin" ).GlobalNamespace()) + || bool( DeclCheck( decl ).Class( "FilteringRewritePlugin" ).Namespace( "loplugin" ).GlobalNamespace()); +} + +static TraverseFunctionInfo findOrCreateTraverseFunctionInfo( StringRef name ) +{ + TraverseFunctionInfo info; + info.name = name.str(); + auto foundInfo = traverseFunctions.find( info ); + if( foundInfo != traverseFunctions.end()) + { + info = std::move( *foundInfo ); + traverseFunctions.erase( foundInfo ); + } + return info; +} + +static bool foundSomething; + +bool CheckFileVisitor::VisitCXXRecordDecl( CXXRecordDecl* decl ) +{ + if( !isDerivedFrom( decl, inheritsPluginClassCheck )) + return true; + + if( decl->getName() == "FilteringPlugin" || decl->getName() == "FilteringRewritePlugin" ) + return true; + + std::cout << "# This file is autogenerated. Do not modify." << std::endl; + std::cout << "# Generated by compilerplugins/clang/sharedvisitor/analyzer.cxx ." << std::endl; + std::cout << "InfoVersion:1" << std::endl; + std::cout << "ClassName:" << decl->getName().str() << std::endl; + traverseFunctions.clear(); + for( const CXXMethodDecl* method : decl->methods()) + { + if( !method->getDeclName().isIdentifier()) + continue; + if( method->isStatic() || method->getAccess() != AS_public ) + continue; + if( method->getName().startswith( "Visit" )) + { + if( method->getNumParams() == 1 ) + { + std::cout << "VisitFunctionStart" << std::endl; + std::cout << "VisitFunctionName:" << method->getName().str() << std::endl; + std::cout << "VisitFunctionArgument:" + << unqualifyPointeeType( + method->getParamDecl( 0 )->getTypeSourceInfo()->getType()).getAsString() + << std::endl; + std::cout << "VisitFunctionEnd" << std::endl; + } + else + { + std::cerr << "Unhandled Visit* function: " << decl->getName().str() + << "::" << method->getName().str() << std::endl; + abort(); + } + } + else if( method->getName().startswith( "Traverse" )) + { + if( method->getNumParams() == 1 ) + { + TraverseFunctionInfo traverseInfo = findOrCreateTraverseFunctionInfo( method->getName()); + traverseInfo.argument = method->getParamDecl( 0 )->getTypeSourceInfo()->getType().getAsString(); + traverseFunctions.insert( std::move( traverseInfo )); + } + else + { + std::cerr << "Unhandled Traverse* function: " << decl->getName().str() + << "::" << method->getName().str() << std::endl; + abort(); + } + } + else if( method->getName().startswith( "PreTraverse" )) + { + TraverseFunctionInfo traverseInfo = findOrCreateTraverseFunctionInfo( method->getName().substr( 3 )); + traverseInfo.hasPre = true; + traverseFunctions.insert( std::move( traverseInfo )); + } + else if( method->getName().startswith( "PostTraverse" )) + { + TraverseFunctionInfo traverseInfo = findOrCreateTraverseFunctionInfo( method->getName().substr( 4 )); + traverseInfo.hasPost = true; + traverseFunctions.insert( std::move( traverseInfo )); + } + else if( method->getName() == "shouldVisitTemplateInstantiations" ) + std::cout << "ShouldVisitTemplateInstantiations:1" << std::endl; + else if (method->getName() == "shouldVisitImplicitCode") + std::cout << "ShouldVisitImplicitCode:1" << std::endl; + else if( method->getName().startswith( "WalkUp" )) + { + std::cerr << "WalkUp function not supported for shared visitor: " << decl->getName().str() + << "::" << method->getName().str() << std::endl; + abort(); + } + } + + for( const auto& traverseFunction : traverseFunctions ) + { + std::cout << "TraverseFunctionStart" << std::endl; + std::cout << "TraverseFunctionName:" << traverseFunction.name << std::endl; + std::cout << "TraverseFunctionArgument:" << traverseFunction.argument << std::endl; + std::cout << "TraverseFunctionHasPre:" << traverseFunction.hasPre << std::endl; + std::cout << "TraverseFunctionHasPost:" << traverseFunction.hasPost << std::endl; + std::cout << "TraverseFunctionEnd" << std::endl; + } + + std::cout << "InfoEnd" << std::endl; + foundSomething = true; + return true; +} + +class FindNamedClassConsumer + : public ASTConsumer +{ +public: + void Initialize(ASTContext& context) override + { + visitor.setContext(context); + } + virtual void HandleTranslationUnit(ASTContext& context) override + { + visitor.TraverseDecl( context.getTranslationUnitDecl()); + } +private: + CheckFileVisitor visitor; +}; + +class FindNamedClassAction + : public ASTFrontendAction + { +public: + virtual std::unique_ptr CreateASTConsumer( CompilerInstance&, StringRef ) override + { + return std::unique_ptr( new FindNamedClassConsumer ); + } +}; + + +std::string readSourceFile( const char* filename ) +{ + std::string contents; + std::ifstream stream( filename ); + if( !stream ) + { + std::cerr << "Failed to open: " << filename << std::endl; + exit( 1 ); + } + std::string line; + bool hasIfdef = false; + while( getline( stream, line )) + { + // TODO add checks that it's e.g. not "#ifdef" ? + if( line.find( "#ifndef LO_CLANG_SHARED_PLUGINS" ) == 0 ) + hasIfdef = true; + contents += line; + contents += '\n'; + } + if( stream.eof() && hasIfdef ) + return contents; + return ""; +} + +int main(int argc, char** argv) +{ + std::vector< std::string > args; + int i = 1; + for( ; i < argc; ++ i ) + { + constexpr std::size_t prefixlen = 5; // strlen("-arg="); + if (std::strncmp(argv[i], "-arg=", prefixlen) != 0) + { + break; + } + args.push_back(argv[i] + prefixlen); + } + SmallVector< StringRef, 20 > clangflags; + SplitString( CLANGFLAGS, clangflags ); + for (auto const & i: clangflags) { + args.push_back(i.str()); + } + args.insert( + args.end(), + { // These must match LO_CLANG_ANALYZER_PCH_CXXFLAGS in Makefile-clang.mk . + "-I" BUILDDIR "/config_host" // plugin sources use e.g. config_global.h +#if LO_CLANG_USE_ANALYZER_PCH + , + "-include-pch", // use PCH with Clang headers to speed up parsing/analysing + BUILDDIR "/compilerplugins/clang/sharedvisitor/clang.pch" +#endif + }); + for( ; i < argc; ++ i ) + { + std::string contents = readSourceFile(argv[i]); + if( contents.empty()) + continue; + foundSomething = false; + if( !tooling::runToolOnCodeWithArgs( std::unique_ptr(new FindNamedClassAction), contents, args, argv[ i ] )) + { + std::cerr << "Failed to analyze: " << argv[ i ] << std::endl; + return 2; + } + if( !foundSomething ) + { + // there's #ifndef LO_CLANG_SHARED_PLUGINS in the source, but no class matched + std::cerr << "Failed to find code: " << argv[ i ] << std::endl; + return 2; + } + } + return 0; +} diff --git a/compilerplugins/clang/sharedvisitor/dummyplugin.hxx b/compilerplugins/clang/sharedvisitor/dummyplugin.hxx new file mode 100644 index 000000000..1ef87416a --- /dev/null +++ b/compilerplugins/clang/sharedvisitor/dummyplugin.hxx @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include "config_clang.h" + +#include "../plugin.hxx" + +using namespace clang; +using namespace llvm; + +namespace loplugin +{ + +// These classes are used as base classes when building with LO_CLANG_SHARED_PLUGINS. +// Since plugin classes in that case should use just one shared RecursiveASTVisitor, +// sharedvisitor/generator.cxx will make these to be the base classes used, so that +// compiling the code doesn't spend a several minutes optimizing instances +// of RecursiveASTVisitor that will never get used. + +template +class DummyRecursiveASTVisitor +{ +public: + // These need to be reimplemented, because plugins contain calls to them, + // but they should actually never get called in the shared-visitor mode. + // This could be autogenerated too, but it's probably simpler to just extend + // manually as needed. + bool TraverseDecl( Decl* ) { return complain(); } + bool TraverseLinkageSpecDecl( LinkageSpecDecl* ) { return complain(); } + bool TraverseStmt( Stmt* ) { return complain(); } + bool TraverseIfStmt( IfStmt* ) { return complain(); } + bool TraverseWhileStmt( WhileStmt* ) { return complain(); } + bool TraverseDoStmt( DoStmt* ) { return complain(); } + bool TraverseForStmt( ForStmt* ) { return complain(); } + bool TraverseCompoundStmt( CompoundStmt* ) { return complain(); } + bool TraverseCXXForRangeStmt( CXXForRangeStmt* ) { return complain(); } + bool TraverseConditionalOperator( ConditionalOperator* ) { return complain(); } + bool TraverseCXXCatchStmt( CXXCatchStmt* ) { return complain(); } + bool TraverseCXXDestructorDecl( CXXDestructorDecl* ) { return complain(); } + bool TraverseFunctionDecl( FunctionDecl* ) { return complain(); } + bool TraverseSwitchStmt( SwitchStmt* ) { return complain(); } + bool TraverseImplicitCastExpr( ImplicitCastExpr* ) { return complain(); } + bool TraverseCStyleCastExpr( CStyleCastExpr* ) { return complain(); } + bool TraverseCXXStaticCastExpr( CXXStaticCastExpr* ) { return complain(); } + bool TraverseCXXFunctionalCastExpr( CXXFunctionalCastExpr* ) { return complain(); } + bool TraverseFriendDecl( FriendDecl* ) { return complain(); } + bool TraverseTypeLoc( TypeLoc ) { return complain(); } + bool TraverseAlignedAttr( AlignedAttr* ) { return complain(); } + bool TraverseVarDecl( VarDecl* ) { return complain(); } + bool TraverseUnaryExprOrTypeTraitExpr( UnaryExprOrTypeTraitExpr* ) { return complain(); } +private: + bool complain() { assert(false && "should not be calling this in sharedplugin mode"); abort(); return false; } +}; + +template +class DummyFilteringPlugin : public DummyRecursiveASTVisitor, public Plugin +{ +public: + explicit DummyFilteringPlugin( const InstantiationData& data ) : Plugin(data) {} +}; + +template +class DummyFilteringRewritePlugin : public DummyRecursiveASTVisitor, public RewritePlugin +{ +public: + explicit DummyFilteringRewritePlugin( const InstantiationData& data ) : RewritePlugin(data) {} +}; + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/sharedvisitor/generator.cxx b/compilerplugins/clang/sharedvisitor/generator.cxx new file mode 100644 index 000000000..ca5d2743c --- /dev/null +++ b/compilerplugins/clang/sharedvisitor/generator.cxx @@ -0,0 +1,480 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Info about a Visit* function in a plugin. +struct VisitFunctionInfo +{ + std::string name; + std::string argument; +}; + + +// Info about a Traverse* function in a plugin. +struct TraverseFunctionInfo +{ + std::string name; + std::string argument; + bool hasPre = false; + bool hasPost = false; +}; + +struct VisitFunctionInfoLess +{ + bool operator()( const VisitFunctionInfo& l, const VisitFunctionInfo& r ) const + { + return l.name < r.name; + } +}; + +struct TraverseFunctionInfoLess +{ + bool operator()( const TraverseFunctionInfo& l, const TraverseFunctionInfo& r ) const + { + return l.name < r.name; + } +}; + + +// Information about each LO plugin. +struct PluginInfo +{ + std::string className; // e.g. "BadStatics" + std::string variableName; // e.g. "badStatics" + std::string lowercaseName; + bool shouldVisitTemplateInstantiations; + bool shouldVisitImplicitCode; + std::set< VisitFunctionInfo, VisitFunctionInfoLess > visitFunctions; + std::set< TraverseFunctionInfo, TraverseFunctionInfoLess > traverseFunctions; +}; + +// We need separate visitors for shouldVisitTemplateInstantiations and shouldVisitImplicitCode, +// so split plugins into groups by what they should visit. +// It seems that trying to handle the shouldVisit* functionality with just one visitor +// is tricky. +enum PluginType +{ + PluginBasic, + PluginVisitTemplates, + PluginVisitImplicit, + PluginVisitTemplatesImplicit, +}; + +const int Plugin_Begin = PluginBasic; +const int Plugin_End = PluginVisitTemplatesImplicit + 1; +static const char* const pluginTypeNames[ Plugin_End ] + = { "Basic", "VisitTemplates", "VisitImplicit", "VisitTemplatesImplicit" }; + +static std::vector< PluginInfo > plugins[ Plugin_End ]; + + +void generateVisitor( PluginType type ); + +void generate() +{ + std::ostream& output = std::cout; + output << +"// This file is autogenerated. Do not modify.\n" +"// Generated by compilerplugins/clang/sharedvisitor/generator.cxx .\n" +"\n" +"#ifdef LO_CLANG_SHARED_PLUGINS\n" +"\n" +"#include \n" +"\n" +"#include \n" +"#include \n" +"\n" +"#include \"plugin.hxx\"\n" +"#include \"sharedvisitor/dummyplugin.hxx\"\n" +"\n"; + + output << "#undef LO_CLANG_SHARED_PLUGINS // to get sources of individual plugins\n"; + output << "// make use of the dummy base classes\n"; + output << "#define RecursiveASTVisitor DummyRecursiveASTVisitor\n"; + output << "#define FilteringPlugin DummyFilteringPlugin\n"; + output << "#define FilteringRewritePlugin DummyFilteringRewritePlugin\n"; + output << "\n"; + for( const auto& pluginGroup : plugins ) + for( const PluginInfo& plugin : pluginGroup ) + output << "#include \"" << plugin.lowercaseName << ".cxx\"" << std::endl; + output << "\n"; + output << "#undef RecursiveASTVisitor\n"; + output << "#undef FilteringPlugin\n"; + output << "#undef FilteringRewritePlugin\n"; + + output << +"\n" +"using namespace clang;\n" +"using namespace llvm;\n" +"\n" +"namespace loplugin\n" +"{\n"; + + for( int type = Plugin_Begin; type < Plugin_End; ++type ) + generateVisitor( static_cast< PluginType >( type )); + + output << +"} // namespace loplugin\n" +"\n" +"#endif // LO_CLANG_SHARED_PLUGINS\n"; +} + +void generateVisitor( PluginType type ) +{ + if( plugins[ type ].empty()) + return; + std::ostream& output = std::cout; + output << +"\n" +"class SharedRecursiveASTVisitor" << pluginTypeNames[ type ] << "\n" +" : public FilteringPlugin< SharedRecursiveASTVisitor" << pluginTypeNames[ type ] << ">\n" +"{\n" +"public:\n" +" explicit SharedRecursiveASTVisitor" << pluginTypeNames[ type ] << "(const InstantiationData& rData)\n" +" : FilteringPlugin(rData)\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + output << " , " << plugin.variableName << "( nullptr )\n"; + output << " , activeRefCount( 0 )\n"; + output << " {}\n"; + + output << +" ~SharedRecursiveASTVisitor" << pluginTypeNames[ type ] << "()\n" +" {\n" +" if( activeRefCount != 0 )\n" +" abort();\n" +" }\n"; + + output << +" virtual bool preRun() override\n" +" {\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + { + output << " if( " << plugin.variableName << " && !" << plugin.variableName << "->preRun())\n"; + // This will disable the plugin for the rest of the run. + output << " " << plugin.variableName << " = nullptr;\n"; + } + output << +" return anyPluginActive();\n" +" }\n"; + + output << +" virtual void postRun() override\n" +" {\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + { + output << " if( " << plugin.variableName << " )\n"; + output << " " << plugin.variableName << "->postRun();\n"; + } + output << +" }\n"; + + output << +" virtual void run() override {\n" +" if (preRun()) {\n" +" TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());\n" +" postRun();\n" +" }\n" +" }\n" +" enum { isSharedPlugin = true };\n"; + + output << +" virtual bool setSharedPlugin( Plugin* plugin, const char* name ) override\n" +" {\n"; + bool first = true; + for( const PluginInfo& plugin : plugins[ type ] ) + { + output << " "; + if( !first ) + output << "else "; + first = false; + output << "if( strcmp( name, \"" << plugin.lowercaseName << "\" ) == 0 )\n"; + output << " " << plugin.variableName << " = static_cast< " << plugin.className << "* >( plugin );\n"; + } + output << +" else\n" +" return false;\n" +" return true;\n" +" }\n"; + + if( type == PluginVisitTemplates || type == PluginVisitTemplatesImplicit ) + output << "bool shouldVisitTemplateInstantiations() const { return true; }\n"; + if( type == PluginVisitImplicit || type == PluginVisitTemplatesImplicit ) + output << "bool shouldVisitImplicitCode() const { return true; }\n"; + + std::set< VisitFunctionInfo, VisitFunctionInfoLess > visitFunctions; + for( const PluginInfo& plugin : plugins[ type ] ) + for( const VisitFunctionInfo& visit : plugin.visitFunctions ) + visitFunctions.insert( visit ); + for( const VisitFunctionInfo& visit : visitFunctions ) + { + output << " bool " << visit.name << "(" << visit.argument << " arg)\n"; + output << +" {\n" +" if( ignoreLocation( arg ))\n" +" return true;\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + { + if( plugin.visitFunctions.find( visit ) == plugin.visitFunctions.end()) + continue; + output << " if( " << plugin.variableName << " != nullptr "; + output << ")\n"; + output << " {\n"; + output << " if( !" << plugin.variableName << "->" << visit.name << "( arg ))\n"; + // This will disable the plugin for the rest of the run (as would returning false + // from Visit* normally do in the non-shared case). + output << " " << plugin.variableName << " = nullptr;\n"; + output << " }\n"; + } + output << +" return anyPluginActive();\n" +" }\n"; + } + + std::set< TraverseFunctionInfo, TraverseFunctionInfoLess > traverseFunctions; + for( const PluginInfo& plugin : plugins[ type ] ) + for( const TraverseFunctionInfo& traverse : plugin.traverseFunctions ) + traverseFunctions.insert( traverse ); + for( const TraverseFunctionInfo& traverse : traverseFunctions ) + { + output << " bool " << traverse.name << "(" << traverse.argument << " arg)\n"; + output << " {\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + { + auto pluginTraverse = plugin.traverseFunctions.find( traverse ); + if( pluginTraverse == plugin.traverseFunctions.end()) + continue; + output << " " << plugin.className << "* save" << plugin.className << " = " << plugin.variableName << ";\n"; + if( pluginTraverse->hasPre ) + { + output << " if( " << plugin.variableName << " != nullptr "; + output << ")\n"; + output << " {\n"; + output << " if( !" << plugin.variableName << "->Pre" << traverse.name << "( arg ))\n"; + // This will disable the plugin for the time of the traverse, until restored later, + // just like directly returning from Traverse* would skip that part. + output << " {\n"; + output << " " << plugin.variableName << " = nullptr;\n"; + output << " ++activeRefCount;\n"; + output << " }\n"; + output << " }\n"; + } + } + output << " bool ret = RecursiveASTVisitor::" << traverse.name << "( arg );\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + { + auto pluginTraverse = plugin.traverseFunctions.find( traverse ); + if( pluginTraverse == plugin.traverseFunctions.end()) + continue; + if( pluginTraverse->hasPost ) + { + output << " if( " << plugin.variableName << " != nullptr "; + output << ")\n"; + output << " {\n"; + output << " if( !" << plugin.variableName << "->Post" << traverse.name << "( arg, ret ))\n"; + // This will disable the plugin for the rest of the run. + output << " save" << plugin.className << " = nullptr;\n"; + output << " }\n"; + } + output << " if( " << plugin.variableName << " == nullptr && save" << plugin.className << " != nullptr )\n"; + output << " --activeRefCount;\n"; + output << " " << plugin.variableName << " = save" << plugin.className << ";\n"; + } + output << " if( false ) // silence -Wunused-function warnings\n"; + output << " {\n"; + for( const PluginInfo& plugin : plugins[ type ] ) + { + auto pluginTraverse = plugin.traverseFunctions.find( traverse ); + if( pluginTraverse == plugin.traverseFunctions.end()) + continue; + output << " " << plugin.variableName << "->" << pluginTraverse->name << "( arg );\n"; + } + output << " }\n"; + output << " return ret;\n"; + output << " }\n"; + } + + output << +"private:\n"; + + output << +" bool anyPluginActive() const\n" +" {\n" +" return activeRefCount > 0"; + for( const PluginInfo& plugin : plugins[ type ] ) + output << "\n || " << plugin.variableName << " != nullptr"; + output << ";\n"; + output << " }\n"; + + for( const PluginInfo& plugin : plugins[ type ] ) + output << " " << plugin.className << "* " << plugin.variableName << ";\n"; + output << " int activeRefCount;\n"; + + output << +"};\n" +"\n" +"loplugin::Plugin::Registration< SharedRecursiveASTVisitor" << pluginTypeNames[ type ] + << " > registration" << pluginTypeNames[ type ] << "(\"sharedvisitor" << pluginTypeNames[ type ] << "\");\n" +"\n"; +} + +static std::string getValue( const std::string& line, const char* tag ) +{ + size_t taglen = strlen( tag ); + if( line.size() < taglen + 2 ) + return std::string(); + if( line.compare( 0, taglen, tag ) != 0 ) + return std::string(); + if( line[ taglen ] != ':' ) + return std::string(); + return line.substr( taglen + 1 ); +} + +static bool readFile( const std::string& fileName ) +{ + std::ifstream file( fileName ); + if( !file ) + { + std::cerr << "Cannot open file " << fileName << std::endl; + return false; + } + PluginInfo pluginInfo; + std::string line; + do + { + getline( file, line ); + } while( !line.empty() && line[ 0 ] == '#' ); + std::string version = getValue( line, "InfoVersion" ); + if( version != "1" ) + { + std::cerr << "Incorrect version '" << version << "' in " << fileName << std::endl; + return false; + } + getline( file, line ); + pluginInfo.className = getValue( line, "ClassName" ); + pluginInfo.variableName = pluginInfo.className; + assert( pluginInfo.variableName.size() > 0 ); + pluginInfo.variableName[ 0 ] = tolower( pluginInfo.variableName[ 0 ] ); + pluginInfo.lowercaseName = pluginInfo.className; + for( char& c : pluginInfo.lowercaseName ) + c = tolower( c ); + pluginInfo.shouldVisitTemplateInstantiations = false; + pluginInfo.shouldVisitImplicitCode = false; + bool endOk = false; + for(;;) + { + std::string line; + getline( file, line ); + if( file.eof() || !file ) + { + std::cerr << "Unexpected end of file" << std::endl; + return false; + } + if( line.empty()) + continue; + if( line == "InfoEnd" ) + { + endOk = true; + break; + } + else if( line == "VisitFunctionStart" ) + { + VisitFunctionInfo visitInfo; + getline( file, line ); + visitInfo.name = getValue( line, "VisitFunctionName" ); + getline( file, line ); + visitInfo.argument = getValue( line, "VisitFunctionArgument" ); + getline( file, line ); + if( line != "VisitFunctionEnd" ) + { + std::cerr << "Missing VisitFunctionEnd" << std::endl; + return false; + } + pluginInfo.visitFunctions.insert( std::move( visitInfo )); + } + else if( line == "TraverseFunctionStart" ) + { + TraverseFunctionInfo traverseInfo; + getline( file, line ); + traverseInfo.name = getValue( line, "TraverseFunctionName" ); + getline( file, line ); + traverseInfo.argument = getValue( line, "TraverseFunctionArgument" ); + getline( file, line ); + traverseInfo.hasPre = getValue( line, "TraverseFunctionHasPre" ) == "1"; + getline( file, line ); + traverseInfo.hasPost = getValue( line, "TraverseFunctionHasPost" ) == "1"; + getline( file, line ); + if( line != "TraverseFunctionEnd" ) + { + std::cerr << "Missing TraverseFunctionEnd" << std::endl; + return false; + } + pluginInfo.traverseFunctions.insert( std::move( traverseInfo )); + } + else + { + std::string value; + value = getValue( line, "ShouldVisitTemplateInstantiations" ); + if( value == "1" ) + pluginInfo.shouldVisitTemplateInstantiations = true; + else + { + value = getValue( line, "ShouldVisitImplicitCode" ); + if( value == "1" ) + pluginInfo.shouldVisitImplicitCode = true; + else + { + std::cerr << "Unknown line " << line << std::endl; + return false; + } + } + } + } + + assert( endOk ); + (void)endOk; + + if( pluginInfo.shouldVisitTemplateInstantiations && pluginInfo.shouldVisitImplicitCode ) + plugins[ PluginVisitTemplatesImplicit ].push_back( std::move( pluginInfo )); + else if( pluginInfo.shouldVisitTemplateInstantiations ) + plugins[ PluginVisitTemplates ].push_back( std::move( pluginInfo )); + else if( pluginInfo.shouldVisitImplicitCode ) + plugins[ PluginVisitImplicit ].push_back( std::move( pluginInfo )); + else + plugins[ PluginBasic ].push_back( std::move( pluginInfo )); + + return true; +} + +int main(int argc, char** argv) +{ + for( int i = 1 ; i < argc; ++i ) + { + if( !readFile( argv[ i ] )) + { + std::cerr << "Error reading " << argv[ i ] << std::endl; + return 1; + } + } + for( int type = Plugin_Begin; type < Plugin_End; ++type ) + { + sort( plugins[ static_cast< PluginType >( type ) ].begin(), plugins[ static_cast< PluginType >( type ) ].end(), + []( const PluginInfo& l, const PluginInfo& r ) { return l.className < r.className; } ); + } + generate(); + return 0; +} diff --git a/compilerplugins/clang/sharedvisitor/precompiled_clang.hxx b/compilerplugins/clang/sharedvisitor/precompiled_clang.hxx new file mode 100644 index 000000000..3baf4b04f --- /dev/null +++ b/compilerplugins/clang/sharedvisitor/precompiled_clang.hxx @@ -0,0 +1,12 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Used by the analyzer to speed up processing plugin sources. + +#include "../plugin.hxx" diff --git a/compilerplugins/clang/shouldreturnbool.cxx b/compilerplugins/clang/shouldreturnbool.cxx new file mode 100644 index 000000000..bc232b472 --- /dev/null +++ b/compilerplugins/clang/shouldreturnbool.cxx @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include "config_clang.h" + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" +#include "functionaddress.hxx" + +/* + Look for functions that only return 1 and/or 0, which sometimes indicates that the + function should be returning bool. + + Note that is partly a question of taste and code style, which is why this plugin is off by default. +*/ + +namespace +{ +class ShouldReturnBool + : public loplugin::FunctionAddress> +{ +public: + explicit ShouldReturnBool(loplugin::InstantiationData const& data) + : FunctionAddress(data) + { + } + + virtual void run() override + { + if (!compiler.getLangOpts().CPlusPlus) + return; + StringRef fn(handler.getMainFileName()); + // functions used as function pointers + if (loplugin::isSamePathname(fn, SRCDIR "/sal/rtl/alloc_cache.cxx")) + return; + // false +, slightly odd usage, but not wrong + if (loplugin::isSamePathname(fn, SRCDIR "/libreofficekit/qa/tilebench/tilebench.cxx")) + return; + // uses the Unix convention of "non-zero return indicates error" + if (loplugin::isSamePathname(fn, SRCDIR "/idlc/source/idlcproduce.cxx")) + return; + // template magic + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/gdi/bmpfast.cxx")) + return; + // fine + if (loplugin::isSamePathname(fn, SRCDIR "/svl/unx/source/svdde/ddedummy.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/opengl/OpenGLHelper.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/misc/imap2.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/dialog/docrecovery.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/hwpfilter/source/lexer.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/hwpfilter/source/grammar.cxx")) + return; + if (loplugin::isSamePathname( + fn, SRCDIR "/connectivity/source/drivers/odbc/ODatabaseMetaDataResultSet.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/ui/browser/dsEntriesNoExp.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/explode.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/filter/source/graphicfilter/ipict/ipict.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/core/data/dptabsrc.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/docshell/docsh3.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/dlg/masterlayoutdlg.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/filter/ppt/pptinanimations.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/generic/app/i18n_im.cxx")) + return; + + // callback + if (loplugin::isSamePathname(fn, SRCDIR "/sax/source/expatwrap/sax_expat.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/xmlsecurity/source/xmlsec/xmlstreamio.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/ww8/ww8par.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/ww8/ww8par2.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/ww8/ww8par5.cxx")) + return; + // SaxWriterHelper::writeSequence a little weird + if (loplugin::isSamePathname(fn, SRCDIR "/sax/source/expatwrap/saxwriter.cxx")) + return; + // main function + if (loplugin::isSamePathname(fn, SRCDIR "/xmlsecurity/workben/pdfverify.cxx")) + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + for (auto functionDecl : problemFunctions) + { + auto canonicalDecl = functionDecl->getCanonicalDecl(); + if (getFunctionsWithAddressTaken().find(canonicalDecl) + != getFunctionsWithAddressTaken().end()) + continue; + report(DiagnosticsEngine::Warning, + "only returning one or zero is an indication you want to return bool", + functionDecl->getBeginLoc()) + << functionDecl->getSourceRange(); + if (canonicalDecl->getLocation() != functionDecl->getLocation()) + { + report(DiagnosticsEngine::Note, "canonical function declaration here", + canonicalDecl->getBeginLoc()) + << canonicalDecl->getSourceRange(); + } + } + } + + bool TraverseFunctionDecl(FunctionDecl*); + bool TraverseCXXMethodDecl(CXXMethodDecl*); + bool VisitReturnStmt(ReturnStmt const*); + +private: + bool mbInsideFunction = false; + bool mbFunctionOnlyReturningOneOrZero = false; + std::unordered_set problemFunctions; + + bool IsInteresting(FunctionDecl const*); + void Report(FunctionDecl const*) const; + bool isExprOneOrZero(Expr const*) const; +}; + +bool ShouldReturnBool::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + bool ret; + if (IsInteresting(functionDecl)) + { + mbInsideFunction = true; + mbFunctionOnlyReturningOneOrZero = true; + ret = FunctionAddress::TraverseFunctionDecl(functionDecl); + mbInsideFunction = false; + if (mbFunctionOnlyReturningOneOrZero) + problemFunctions.insert(functionDecl); + } + else + ret = FunctionAddress::TraverseFunctionDecl(functionDecl); + return ret; +} + +bool ShouldReturnBool::TraverseCXXMethodDecl(CXXMethodDecl* methodDecl) +{ + bool ret; + if (IsInteresting(methodDecl)) + { + mbInsideFunction = true; + mbFunctionOnlyReturningOneOrZero = true; + ret = FunctionAddress::TraverseCXXMethodDecl(methodDecl); + mbInsideFunction = false; + if (mbFunctionOnlyReturningOneOrZero) + problemFunctions.insert(methodDecl); + } + else + ret = FunctionAddress::TraverseCXXMethodDecl(methodDecl); + return ret; +} + +bool ShouldReturnBool::IsInteresting(FunctionDecl const* functionDecl) +{ + if (ignoreLocation(functionDecl)) + return false; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) + return false; + if (functionDecl->getTemplatedKind() != FunctionDecl::TK_NonTemplate) + return false; + if (!functionDecl->isThisDeclarationADefinition()) + return false; + if (functionDecl->isMain()) + return false; + if (functionDecl->isExternC() || functionDecl->isInExternCContext()) + return false; + auto methodDecl = dyn_cast(functionDecl); + if (methodDecl && methodDecl->isVirtual()) + return false; + auto tc = loplugin::TypeCheck(functionDecl->getReturnType()); + if (tc.AnyBoolean() || tc.Void()) + return false; + auto returnType = functionDecl->getReturnType(); + if (returnType->isEnumeralType() || !returnType->getUnqualifiedDesugaredType()->isIntegerType()) + return false; + // Ignore functions that contains #ifdef-ery + if (containsPreprocessingConditionalInclusion(functionDecl->getSourceRange())) + return false; + + // not sure what basegfx is doing here + StringRef fileName{ getFilenameOfLocation(functionDecl->getLocation()) }; + if (loplugin::isSamePathname(fileName, SRCDIR "/include/basegfx/range/basicrange.hxx")) + return false; + // false + + if (loplugin::isSamePathname(fileName, SRCDIR "/include/svl/macitem.hxx")) + return false; + if (loplugin::isSamePathname(fileName, SRCDIR "/lotuswordpro/source/filter/lwpcharsetmgr.hxx")) + return false; + if (loplugin::isSamePathname(fileName, SRCDIR "/sc/inc/dptabsrc.hxx")) + return false; + + return true; +} + +bool ShouldReturnBool::VisitReturnStmt(const ReturnStmt* returnStmt) +{ + if (!mbInsideFunction) + return true; + if (!returnStmt->getRetValue()) + return true; + if (loplugin::TypeCheck(returnStmt->getRetValue()->getType()).AnyBoolean()) + return true; + if (!isExprOneOrZero(returnStmt->getRetValue())) + mbFunctionOnlyReturningOneOrZero = false; + return true; +} + +bool ShouldReturnBool::isExprOneOrZero(const Expr* arg) const +{ + arg = arg->IgnoreParenCasts(); + // ignore this, it seems to trigger an infinite recursion + if (isa(arg)) + { + return false; + } + APSInt x1; + if (compat::EvaluateAsInt(arg, x1, compiler.getASTContext())) + { + return x1 == 1 || x1 == 0; + } + return false; +} + +loplugin::Plugin::Registration X("shouldreturnbool", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/simplifyconstruct.cxx b/compilerplugins/clang/simplifyconstruct.cxx new file mode 100644 index 000000000..d9eff0b3a --- /dev/null +++ b/compilerplugins/clang/simplifyconstruct.cxx @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include +#include +#include "plugin.hxx" +#include "check.hxx" + +namespace +{ +class SimplifyConstruct : public loplugin::FilteringPlugin +{ +public: + explicit SimplifyConstruct(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXConstructExpr(CXXConstructExpr const*); + bool VisitVarDecl(VarDecl const*); + + // ignore some contexts within which nullptr is fine + bool TraverseReturnStmt(ReturnStmt*) { return true; } + bool TraverseInitListExpr(InitListExpr*) { return true; } + bool TraverseCXXBindTemporaryExpr(CXXBindTemporaryExpr*) { return true; } + // ignore them for the shared visitor too + bool PreTraverseReturnStmt(ReturnStmt*) { return false; } + bool PreTraverseInitListExpr(InitListExpr*) { return false; } + bool PreTraverseCXXBindTemporaryExpr(CXXBindTemporaryExpr*) { return false; } +}; + +bool SimplifyConstruct::VisitCXXConstructExpr(CXXConstructExpr const* constructExpr) +{ + if (ignoreLocation(constructExpr)) + return true; + auto tc = loplugin::TypeCheck(constructExpr->getType()); + if (!tc.Class("unique_ptr").StdNamespace() && !tc.Class("shared_ptr").StdNamespace() + && !tc.Class("SvRef").Namespace("tools").GlobalNamespace() + && !tc.Class("Reference").Namespace("rtl").GlobalNamespace() + && !tc.Class("Reference") + .Namespace("uno") + .Namespace("star") + .Namespace("sun") + .Namespace("com") + .GlobalNamespace()) + return true; + if (constructExpr->getNumArgs() == 1 + && isa(constructExpr->getArg(0)->IgnoreParenImpCasts())) + { + report(DiagnosticsEngine::Warning, + "no need to explicitly init an instance of %0 with nullptr, just use default " + "constructor", + constructExpr->getSourceRange().getBegin()) + << constructExpr->getType() << constructExpr->getSourceRange(); + } + return true; +} + +bool SimplifyConstruct::VisitVarDecl(VarDecl const* varDecl) +{ + if (ignoreLocation(varDecl)) + return true; + // cannot use OUString s("xxx") style syntax in a parameter + if (isa(varDecl)) + return true; + varDecl = varDecl->getCanonicalDecl(); + if (!varDecl->getInit()) + return true; + if (varDecl->getInitStyle() != VarDecl::InitializationStyle::CInit) + return true; + if (!varDecl->getType()->isRecordType()) + return true; + if (isa(varDecl->getType())) + return true; + + auto init = varDecl->getInit(); + auto const e1 = init->IgnoreImplicit(); + if (!isa(e1) && !isa(e1)) + return true; + + // e.g. the LANGUAGE_DONTKNOW defines + if (compiler.getSourceManager().isMacroBodyExpansion(init->getBeginLoc())) + return true; + + report(DiagnosticsEngine::Warning, "simplify", varDecl->getLocation()) + << varDecl->getSourceRange(); + + return true; +} + +loplugin::Plugin::Registration simplifyconstruct("simplifyconstruct", true); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/simplifydynamiccast.cxx b/compilerplugins/clang/simplifydynamiccast.cxx new file mode 100644 index 000000000..ffb81658d --- /dev/null +++ b/compilerplugins/clang/simplifydynamiccast.cxx @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include +#include "plugin.hxx" + +namespace +{ +class SimplifyDynamicCast : public loplugin::FilteringPlugin +{ +public: + explicit SimplifyDynamicCast(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + // StringRef fn(handler.getMainFileName()); + // if (loplugin::isSamePathname(fn, WORKDIR "/YaccTarget/unoidl/source/sourceprovider-parser.cxx")) + // return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool TraverseIfStmt(IfStmt*); + bool VisitCXXStaticCastExpr(CXXStaticCastExpr const*); + +private: + std::vector dynamicCastVec; + std::vector dynamicCastSubExprVec; + std::vector ifVec; +}; + +bool SimplifyDynamicCast::TraverseIfStmt(IfStmt* ifStmt) +{ + auto condExpr = ifStmt->getCond()->IgnoreParenImpCasts(); + auto dynamicCastExpr = dyn_cast(condExpr); + if (!dynamicCastExpr) + { + if (auto binaryOp = dyn_cast(condExpr)) + { + if (binaryOp->getOpcode() == BO_NE) + dynamicCastExpr + = dyn_cast(binaryOp->getLHS()->IgnoreParenImpCasts()); + } + } + Decl const* subExprDecl = nullptr; + if (dynamicCastExpr) + { + auto subExprDeclRefExpr + = dyn_cast(dynamicCastExpr->getSubExpr()->IgnoreParenImpCasts()); + if (!subExprDeclRefExpr) + dynamicCastExpr = nullptr; + else + subExprDecl = subExprDeclRefExpr->getDecl(); + } + if (dynamicCastExpr) + { + auto qt = dynamicCastExpr->getTypeAsWritten(); + dynamicCastVec.push_back(qt); + dynamicCastSubExprVec.push_back(subExprDecl); + ifVec.push_back(ifStmt); + } + bool ret = RecursiveASTVisitor::TraverseIfStmt(ifStmt); + if (dynamicCastExpr) + { + dynamicCastVec.pop_back(); + dynamicCastSubExprVec.pop_back(); + ifVec.pop_back(); + } + return ret; +} + +bool SimplifyDynamicCast::VisitCXXStaticCastExpr(CXXStaticCastExpr const* staticCastExpr) +{ + if (ignoreLocation(staticCastExpr)) + return true; + if (dynamicCastVec.empty()) + return true; + + auto qt = staticCastExpr->getTypeAsWritten(); + auto it = std::find(dynamicCastVec.begin(), dynamicCastVec.end(), qt); + if (it == dynamicCastVec.end()) + return true; + int idx = it - dynamicCastVec.begin(); + auto subExprDecl = dyn_cast(staticCastExpr->getSubExpr()->IgnoreParenImpCasts()); + if (!subExprDecl) + return true; + if (dynamicCastSubExprVec[idx] != subExprDecl->getDecl()) + return true; + report(DiagnosticsEngine::Warning, "simplify, use var in if", staticCastExpr->getBeginLoc()) + << staticCastExpr->getSourceRange(); + auto ifStmt = ifVec[idx]; + report(DiagnosticsEngine::Note, "if here", ifStmt->getBeginLoc()) << ifStmt->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration X("simplifydynamiccast", true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/simplifypointertobool.cxx b/compilerplugins/clang/simplifypointertobool.cxx new file mode 100644 index 000000000..097a78e16 --- /dev/null +++ b/compilerplugins/clang/simplifypointertobool.cxx @@ -0,0 +1,444 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "plugin.hxx" +#include "check.hxx" + +/** + Simplify boolean expressions involving smart pointers e.g. + if (x.get()) + can be + if (x) +*/ +//TODO: Make this a shared plugin for Clang 12 (and possibly even for older Clang) again. + +namespace +{ +class SimplifyPointerToBool : public loplugin::FilteringRewritePlugin +{ +public: + explicit SimplifyPointerToBool(loplugin::InstantiationData const& data) + : FilteringRewritePlugin(data) + { + } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitImplicitCastExpr(ImplicitCastExpr const*); + bool VisitBinaryOperator(BinaryOperator const*); + + bool PreTraverseUnaryOperator(UnaryOperator* expr) + { + if (expr->getOpcode() == UO_LNot) + { + contextuallyConvertedExprs_.push_back(expr->getSubExpr()->IgnoreParenImpCasts()); + } + return true; + } + + bool PostTraverseUnaryOperator(UnaryOperator* expr, bool) + { + if (expr->getOpcode() == UO_LNot) + { + assert(!contextuallyConvertedExprs_.empty()); + contextuallyConvertedExprs_.pop_back(); + } + return true; + } + + bool TraverseUnaryOperator(UnaryOperator* expr) + { + auto res = PreTraverseUnaryOperator(expr); + assert(res); + res = FilteringRewritePlugin::TraverseUnaryOperator(expr); + PostTraverseUnaryOperator(expr, res); + return res; + } + + bool PreTraverseBinaryOperator(BinaryOperator* expr) + { + auto const op = expr->getOpcode(); + if (op == BO_LAnd || op == BO_LOr) + { + contextuallyConvertedExprs_.push_back(expr->getLHS()->IgnoreParenImpCasts()); + contextuallyConvertedExprs_.push_back(expr->getRHS()->IgnoreParenImpCasts()); + } + return true; + } + + bool PostTraverseBinaryOperator(BinaryOperator* expr, bool) + { + auto const op = expr->getOpcode(); + if (op == BO_LAnd || op == BO_LOr) + { + assert(contextuallyConvertedExprs_.size() >= 2); + contextuallyConvertedExprs_.pop_back(); + contextuallyConvertedExprs_.pop_back(); + } + return true; + } + + bool TraverseBinaryOperator(BinaryOperator* expr) + { + auto res = PreTraverseBinaryOperator(expr); + assert(res); + res = FilteringRewritePlugin::TraverseBinaryOperator(expr); + PostTraverseBinaryOperator(expr, res); + return res; + } + + bool PreTraverseConditionalOperator(ConditionalOperator* expr) + { + contextuallyConvertedExprs_.push_back(expr->getCond()->IgnoreParenImpCasts()); + return true; + } + + bool PostTraverseConditionalOperator(ConditionalOperator*, bool) + { + assert(!contextuallyConvertedExprs_.empty()); + contextuallyConvertedExprs_.pop_back(); + return true; + } + + bool TraverseConditionalOperator(ConditionalOperator* expr) + { + auto res = PreTraverseConditionalOperator(expr); + assert(res); + res = FilteringRewritePlugin::TraverseConditionalOperator(expr); + PostTraverseConditionalOperator(expr, res); + return res; + } + + bool PreTraverseIfStmt(IfStmt* stmt) + { + contextuallyConvertedExprs_.push_back(stmt->getCond()->IgnoreParenImpCasts()); + return true; + } + + bool PostTraverseIfStmt(IfStmt*, bool) + { + assert(!contextuallyConvertedExprs_.empty()); + contextuallyConvertedExprs_.pop_back(); + return true; + } + + bool TraverseIfStmt(IfStmt* stmt) + { + auto res = PreTraverseIfStmt(stmt); + assert(res); + res = FilteringRewritePlugin::TraverseIfStmt(stmt); + PostTraverseIfStmt(stmt, res); + return res; + } + + bool PreTraverseWhileStmt(WhileStmt* stmt) + { + contextuallyConvertedExprs_.push_back(stmt->getCond()->IgnoreParenImpCasts()); + return true; + } + + bool PostTraverseWhileStmt(WhileStmt*, bool) + { + assert(!contextuallyConvertedExprs_.empty()); + contextuallyConvertedExprs_.pop_back(); + return true; + } + + bool TraverseWhileStmt(WhileStmt* stmt) + { + auto res = PreTraverseWhileStmt(stmt); + assert(res); + res = FilteringRewritePlugin::TraverseWhileStmt(stmt); + PostTraverseWhileStmt(stmt, res); + return res; + } + + bool PreTraverseDoStmt(DoStmt* stmt) + { + contextuallyConvertedExprs_.push_back(stmt->getCond()->IgnoreParenImpCasts()); + return true; + } + + bool PostTraverseDoStmt(DoStmt*, bool) + { + assert(!contextuallyConvertedExprs_.empty()); + contextuallyConvertedExprs_.pop_back(); + return true; + } + + bool TraverseDoStmt(DoStmt* stmt) + { + auto res = PreTraverseDoStmt(stmt); + assert(res); + res = FilteringRewritePlugin::TraverseDoStmt(stmt); + PostTraverseDoStmt(stmt, res); + return res; + } + + bool PreTraverseForStmt(ForStmt* stmt) + { + auto const e = stmt->getCond(); + if (e != nullptr) + { + contextuallyConvertedExprs_.push_back(e->IgnoreParenImpCasts()); + } + return true; + } + + bool PostTraverseForStmt(ForStmt* stmt, bool) + { + if (stmt->getCond() != nullptr) + { + assert(!contextuallyConvertedExprs_.empty()); + contextuallyConvertedExprs_.pop_back(); + } + return true; + } + + bool TraverseForStmt(ForStmt* stmt) + { + auto res = PreTraverseForStmt(stmt); + assert(res); + res = FilteringRewritePlugin::TraverseForStmt(stmt); + PostTraverseForStmt(stmt, res); + return res; + } + +private: + bool isContextuallyConverted(Expr const* expr) const + { + return std::find(contextuallyConvertedExprs_.begin(), contextuallyConvertedExprs_.end(), + expr) + != contextuallyConvertedExprs_.end(); + } + + // Get the source range starting at the "."or "->" (plus any preceding non-comment white space): + SourceRange getCallSourceRange(CXXMemberCallExpr const* expr) const + { + if (expr->getImplicitObjectArgument() == nullptr) + { + //TODO: Arguably, such a call of a `get` member function from within some member + // function (so that syntactically no caller is mentioned) should already be handled + // differently when reporting it (just "drop the get()" does not make sense), instead of + // being filtered here: + return {}; + } + // CXXMemberCallExpr::getExprLoc happens to return the location following the "." or "->": + auto start = compiler.getSourceManager().getSpellingLoc(expr->getExprLoc()); + if (!start.isValid()) + { + return {}; + } + for (;;) + { + start = Lexer::GetBeginningOfToken(start.getLocWithOffset(-1), + compiler.getSourceManager(), compiler.getLangOpts()); + auto const s = StringRef(compiler.getSourceManager().getCharacterData(start), + Lexer::MeasureTokenLength(start, compiler.getSourceManager(), + compiler.getLangOpts())); + if (s.empty() || s.startswith("\\\n")) + { + continue; + } + if (s != "." && s != "->") + { + return {}; + } + break; + } + for (;;) + { + auto start1 = Lexer::GetBeginningOfToken( + start.getLocWithOffset(-1), compiler.getSourceManager(), compiler.getLangOpts()); + auto const s = StringRef(compiler.getSourceManager().getCharacterData(start1), + Lexer::MeasureTokenLength(start1, compiler.getSourceManager(), + compiler.getLangOpts())); + if (!(s.empty() || s.startswith("\\\n"))) + { + break; + } + start = start1; + } + return SourceRange(start, compiler.getSourceManager().getSpellingLoc(expr->getEndLoc())); + } + + //TODO: There are some more places where an expression is contextually converted to bool, but + // those are probably not relevant for our needs here. + std::deque contextuallyConvertedExprs_; +}; + +bool SimplifyPointerToBool::VisitImplicitCastExpr(ImplicitCastExpr const* castExpr) +{ + if (ignoreLocation(castExpr)) + return true; + if (castExpr->getCastKind() != CK_PointerToBoolean) + return true; + auto memberCallExpr + = dyn_cast(castExpr->getSubExpr()->IgnoreParenImpCasts()); + if (!memberCallExpr) + return true; + auto methodDecl = memberCallExpr->getMethodDecl(); + if (!methodDecl || !methodDecl->getIdentifier() || methodDecl->getName() != "get") + return true; + // castExpr->dump(); + // methodDecl->getParent()->getTypeForDecl()->dump(); + if (!loplugin::isSmartPointerType(memberCallExpr->getImplicitObjectArgument())) + return true; + // if (isa(callExpr)) + // return true; + // const FunctionDecl* functionDecl; + // if (isa(callExpr)) + // { + // functionDecl = dyn_cast(callExpr)->getMethodDecl(); + // } + // else + // { + // functionDecl = callExpr->getDirectCallee(); + // } + // if (!functionDecl) + // return true; + // + // unsigned len = std::min(callExpr->getNumArgs(), functionDecl->getNumParams()); + // for (unsigned i = 0; i < len; ++i) + // { + // auto param = functionDecl->getParamDecl(i); + // auto paramTC = loplugin::TypeCheck(param->getType()); + // if (!paramTC.AnyBoolean()) + // continue; + // auto arg = callExpr->getArg(i)->IgnoreImpCasts(); + // auto argTC = loplugin::TypeCheck(arg->getType()); + // if (argTC.AnyBoolean()) + // continue; + // // sal_Bool is sometimes disguised + // if (isa(arg->getType())) + // if (arg->getType()->getUnqualifiedDesugaredType()->isSpecificBuiltinType( + // clang::BuiltinType::UChar)) + // continue; + // if (arg->getType()->isDependentType()) + // continue; + // if (arg->getType()->isIntegerType()) + // { + // auto ret = getCallValue(arg); + // if (ret.hasValue() && (ret.getValue() == 1 || ret.getValue() == 0)) + // continue; + // // something like: priv->m_nLOKFeatures & LOK_FEATURE_DOCUMENT_PASSWORD + // if (isa(arg->IgnoreParenImpCasts())) + // continue; + // // something like: pbEmbolden ? FcTrue : FcFalse + // if (isa(arg->IgnoreParenImpCasts())) + // continue; + // } + if (isContextuallyConverted(memberCallExpr)) + { + if (rewriter) + { + auto const range = getCallSourceRange(memberCallExpr); + if (range.isValid() && removeText(range)) + { + return true; + } + } + report(DiagnosticsEngine::Warning, "simplify, drop the get()", memberCallExpr->getExprLoc()) + << memberCallExpr->getSourceRange(); + } + else if (isa(castExpr->getSubExpr())) + { + if (rewriter) + { + auto const loc + = compiler.getSourceManager().getSpellingLoc(memberCallExpr->getBeginLoc()); + auto const range = getCallSourceRange(memberCallExpr); + if (loc.isValid() && range.isValid() && insertText(loc, "bool") && removeText(range)) + { + //TODO: atomically only change both or neither + return true; + } + } + report(DiagnosticsEngine::Warning, + "simplify, drop the get() and turn the surrounding parentheses into a functional " + "cast to bool", + memberCallExpr->getExprLoc()) + << memberCallExpr->getSourceRange(); + report(DiagnosticsEngine::Note, "surrounding parentheses here", + castExpr->getSubExpr()->getExprLoc()) + << castExpr->getSubExpr()->getSourceRange(); + } + else + { + if (rewriter) + { + auto const loc + = compiler.getSourceManager().getSpellingLoc(memberCallExpr->getBeginLoc()); + auto const range = getCallSourceRange(memberCallExpr); + if (loc.isValid() && range.isValid() && insertText(loc, "bool(") + && replaceText(range, ")")) + { + //TODO: atomically only change both or neither + return true; + } + } + report(DiagnosticsEngine::Warning, + "simplify, drop the get() and wrap the expression in a functional cast to bool", + memberCallExpr->getExprLoc()) + << memberCallExpr->getSourceRange(); + } + // report(DiagnosticsEngine::Note, "method here", param->getLocation()) + // << param->getSourceRange(); + return true; +} + +bool SimplifyPointerToBool::VisitBinaryOperator(BinaryOperator const* binOp) +{ + if (ignoreLocation(binOp)) + return true; + auto opCode = binOp->getOpcode(); + if (opCode != BO_EQ && opCode != BO_NE) + return true; + const Expr* possibleMemberCall = nullptr; + if (isa(binOp->getLHS()->IgnoreParenImpCasts())) + possibleMemberCall = binOp->getRHS(); + else if (isa(binOp->getRHS()->IgnoreParenImpCasts())) + possibleMemberCall = binOp->getLHS(); + else + return true; + auto memberCallExpr = dyn_cast(possibleMemberCall); + if (!memberCallExpr) + return true; + auto methodDecl = memberCallExpr->getMethodDecl(); + if (!methodDecl || !methodDecl->getIdentifier() || methodDecl->getName() != "get") + return true; + if (!loplugin::isSmartPointerType(memberCallExpr->getImplicitObjectArgument())) + return true; + report(DiagnosticsEngine::Warning, + std::string("simplify, convert to ") + (opCode == BO_EQ ? "'!x'" : "'x'"), + binOp->getExprLoc()) + << binOp->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration simplifypointertobool("simplifypointertobool", + true); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/singlevalfields.could-be-bool.results b/compilerplugins/clang/singlevalfields.could-be-bool.results new file mode 100644 index 000000000..9e2d1e01b --- /dev/null +++ b/compilerplugins/clang/singlevalfields.could-be-bool.results @@ -0,0 +1,117 @@ +connectivity/source/inc/dbase/dindexnode.hxx:119 + connectivity::dbase::ONDXPage bNoDelete + unsigned int +cui/source/inc/cfg.hxx:234 + SvxConfigEntry nId + sal_uInt16 +desktop/source/app/main.c:29 + /home/noel/libo2/desktop/source/app/main.c g_Exiting + int +editeng/source/misc/hangulhanja.cxx:78 + editeng::HangulHanjaConversion_Impl m_eConvType + class HangulHanjaConversion::ConversionType +editeng/source/misc/svxacorr.cxx:233 + GetIgnoreTranslWrapper bIsInit + int +include/opencl/openclwrapper.hxx:46 + openclwrapper::GPUEnv mnIsUserCreated + int +include/svtools/ruler.hxx:621 + Ruler mnBorderWidth + tools::Long +include/tools/ref.hxx:126 + SvRefBase bNoDelete + unsigned int +include/vbahelper/vbapagesetupbase.hxx:50 + VbaPageSetupBase mnOrientPortrait + sal_Int32 +include/vcl/headbar.hxx:208 + HeaderBar mnBorderOff1 + tools::Long +include/vcl/headbar.hxx:209 + HeaderBar mnBorderOff2 + tools::Long +include/vcl/toolkit/dialog.hxx:54 + Dialog mnMousePositioned + tools::Long +jvmfwk/plugins/sunmajor/pluginlib/sunjavaplugin.cxx:199 + (anonymous) g_bInGetJavaVM + sig_atomic_t +libreofficekit/source/gtk/tilebuffer.hxx:232 + LOEvent m_nSetGraphicSelectionType + int +sal/rtl/cipher.cxx:113 + (anonymous namespace)::Cipher_Impl m_algorithm + rtlCipherAlgorithm +sc/source/filter/inc/stylesbuffer.hxx:288 + oox::xls::ApiAlignmentData mnHorJustifyMethod + sal_Int32 +sc/source/filter/inc/stylesbuffer.hxx:290 + oox::xls::ApiAlignmentData mnVerJustifyMethod + sal_Int32 +sc/source/ui/Accessibility/AccessibleDocumentPagePreview.cxx:1084 + (anonymous namespace)::ScPagePreviewCountData nHeaders + tools::Long +sc/source/ui/Accessibility/AccessibleDocumentPagePreview.cxx:1085 + (anonymous namespace)::ScPagePreviewCountData nTables + tools::Long +sc/source/ui/Accessibility/AccessibleDocumentPagePreview.cxx:1087 + (anonymous namespace)::ScPagePreviewCountData nFooters + tools::Long +sc/source/ui/vba/vbahyperlink.hxx:83 + ScVbaHyperlink mnType + tools::Long +sd/qa/unit/tiledrendering/tiledrendering.cxx:854 + (anonymous namespace)::ViewCallback m_nPart + int +soltools/cpp/_tokens.c:35 + /home/noel/libo2/soltools/cpp/_tokens.c EBCDIC_ExternTokenDetected + int +soltools/cpp/_tokens.c:36 + /home/noel/libo2/soltools/cpp/_tokens.c EBCDIC_StartTokenDetected + int +soltools/cpp/cpp.h:121 + includelist always + char +svx/source/inc/cell.hxx:202 + sdr::table::Cell mnCellContentType + css::table::CellContentType +svx/source/table/tablertfimporter.cxx:57 + sdr::table::(anonymous namespace)::RTFCellDefault mnRowSpan + sal_Int32 +sw/source/filter/ww8/docxexport.hxx:98 + DocxExport m_nHeadersFootersInSection + sal_Int32 +sw/source/filter/ww8/ww8scan.hxx:57 + SprmInfo nVari + unsigned int +sw/source/uibase/inc/tautofmt.hxx:48 + SwAutoFormatDlg m_nDfltStylePos + sal_uInt8 +vcl/inc/unx/i18n_ic.hxx:32 + SalI18N_InputContext mbUseable + int +vcl/inc/unx/salframe.h:125 + X11SalFrame mbInputFocus + int +vcl/source/filter/eps/eps.cxx:141 + (anonymous namespace)::PSWriter nNextChrSetId + sal_uInt8 +vcl/unx/generic/app/saldata.cxx:449 + EmitFontpathWarning bOnce + int +vcl/unx/generic/app/saldata.cxx:502 + X11SalData::XError bOnce + int +vcl/unx/generic/app/sm.cxx:184 + /home/noel/libo2/vcl/unx/generic/app/sm.cxx nSmDel + int +vcl/workben/icontest.cxx:145 + (anonymous namespace)::IconTestApp nRet + int +workdir/LexTarget/l10ntools/source/cfglex.cxx:2293 + /home/noel/libo2/workdir/LexTarget/l10ntools/source/cfglex.cxx bText + int +writerfilter/source/dmapper/PageBordersHandler.hxx:47 + writerfilter::dmapper::PageBordersHandler m_eOffsetFrom + class SectionPropertyMap::BorderOffsetFrom diff --git a/compilerplugins/clang/singlevalfields.cxx b/compilerplugins/clang/singlevalfields.cxx new file mode 100644 index 000000000..df5abcc00 --- /dev/null +++ b/compilerplugins/clang/singlevalfields.cxx @@ -0,0 +1,577 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "config_clang.h" + +#include "compat.hxx" +#include "plugin.hxx" + +#include "clang/AST/ParentMapContext.h" + +/** +Look for fields that are only ever assigned a single constant value. + +We dmp a list of values assigned to fields, and a list of field definitions. +Then we will post-process the 2 lists and find the set of interesting fields. + +Be warned that it produces around 5G of log file. + +The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='singlevalfields' check + $ ./compilerplugins/clang/singlevalfields.py + +Note that the actual process may involve a fair amount of undoing, hand editing, and general messing around +to get it to work :-) + +@TODO we don't spot fields that have been zero-initialised via calloc or rtl_allocateZeroMemory or memset +@TODO calls to lambdas where a reference to the field is taken + +*/ + +namespace { + +struct MyFieldInfo +{ + FieldDecl const * fieldDecl; + std::string parentClass; + std::string fieldName; + std::string fieldType; + std::string sourceLocation; +}; +bool operator < (const MyFieldInfo &lhs, const MyFieldInfo &rhs) +{ + return std::tie(lhs.parentClass, lhs.fieldName) + < std::tie(rhs.parentClass, rhs.fieldName); +} + +struct MyFieldAssignmentInfo : public MyFieldInfo +{ + std::string value; +}; + +bool operator < (const MyFieldAssignmentInfo &lhs, const MyFieldAssignmentInfo &rhs) +{ + return std::tie(lhs.parentClass, lhs.fieldName, lhs.value) + < std::tie(rhs.parentClass, rhs.fieldName, rhs.value); +} + + +// try to limit the voluminous output a little +static std::set assignedSet; +static std::set definitionSet; + +/** escape the value string to make it easier to parse the output file in python */ +std::string escape(std::string s) +{ + std::string out; + for (size_t i=0; i= 32) + out += s[i]; + else + out += "\\" + std::to_string((int)s[i]); + return out; +} + +class SingleValFields: + public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit SingleValFields(loplugin::InstantiationData const & data): + Plugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + if (!isUnitTestMode()) + { + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + std::string output; + for (const MyFieldAssignmentInfo & s : assignedSet) + output += "asgn:\t" + s.parentClass + "\t" + s.fieldName + "\t" + escape(s.value) + "\n"; + for (const MyFieldInfo & s : definitionSet) + output += "defn:\t" + s.parentClass + "\t" + s.fieldName + "\t" + s.fieldType + "\t" + s.sourceLocation + "\n"; + std::ofstream myfile; + myfile.open( WORKDIR "/loplugin.singlevalfields.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + else + { + for (const MyFieldAssignmentInfo & s : assignedSet) + if (s.fieldDecl && compiler.getSourceManager().isInMainFile(s.fieldDecl->getBeginLoc())) + report( + DiagnosticsEngine::Warning, + "assign %0", + s.fieldDecl->getBeginLoc()) + << s.value; + } + } + + bool shouldVisitTemplateInstantiations () const { return true; } + // to catch compiler-generated constructors + bool shouldVisitImplicitCode() const { return true; } + + bool VisitFieldDecl( const FieldDecl* ); + bool VisitVarDecl( const VarDecl* ); + bool VisitMemberExpr( const MemberExpr* ); + bool VisitDeclRefExpr( const DeclRefExpr* ); + bool VisitCXXConstructorDecl( const CXXConstructorDecl* ); +// bool VisitUnaryExprOrTypeTraitExpr( const UnaryExprOrTypeTraitExpr* ); +private: + void niceName(const DeclaratorDecl*, MyFieldInfo&); + void walkPotentialAssign( const DeclaratorDecl* fieldOrVarDecl, const Stmt* stmt ); + std::string getExprValue(const Expr*); + const FunctionDecl* get_top_FunctionDecl_from_Stmt(const Stmt&); + void checkCallExpr(const Stmt* child, const CallExpr* callExpr, std::string& assignValue, bool& bPotentiallyAssignedTo); +}; + +void SingleValFields::niceName(const DeclaratorDecl* fieldOrVarDecl, MyFieldInfo& aInfo) +{ + const VarDecl* varDecl = dyn_cast(fieldOrVarDecl); + const FieldDecl* fieldDecl = dyn_cast(fieldOrVarDecl); + aInfo.fieldDecl = fieldDecl; + if (fieldDecl) + aInfo.parentClass = fieldDecl->getParent()->getQualifiedNameAsString(); + else + { + if (auto parentRecordDecl = dyn_cast(varDecl->getDeclContext())) + aInfo.parentClass = parentRecordDecl->getQualifiedNameAsString(); + else if (auto parentMethodDecl = dyn_cast(varDecl->getDeclContext())) + aInfo.parentClass = parentMethodDecl->getQualifiedNameAsString(); + else if (auto parentFunctionDecl = dyn_cast(varDecl->getDeclContext())) + aInfo.parentClass = parentFunctionDecl->getQualifiedNameAsString(); + else if (isa(varDecl->getDeclContext())) + aInfo.parentClass = handler.getMainFileName().str(); + else if (auto parentNamespaceDecl = dyn_cast(varDecl->getDeclContext())) + aInfo.parentClass = parentNamespaceDecl->getQualifiedNameAsString(); + else if (isa(varDecl->getDeclContext())) + aInfo.parentClass = "extern"; // what to do here? + else + { + std::cout << "what is this? " << varDecl->getDeclContext()->getDeclKindName() << std::endl; + exit(1); + } + } + aInfo.fieldName = fieldOrVarDecl->getNameAsString(); + aInfo.fieldType = fieldOrVarDecl->getType().getAsString(); + + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( fieldOrVarDecl->getLocation() ); + StringRef name = getFilenameOfLocation(expansionLoc); + aInfo.sourceLocation = std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(aInfo.sourceLocation); +} + +bool SingleValFields::VisitFieldDecl( const FieldDecl* fieldDecl ) +{ + auto canonicalDecl = fieldDecl->getCanonicalDecl(); + + if( isInUnoIncludeFile( compiler.getSourceManager().getSpellingLoc(canonicalDecl->getLocation())) ) + return true; + + MyFieldInfo aInfo; + niceName(canonicalDecl, aInfo); + definitionSet.insert(aInfo); + + if (fieldDecl->getInClassInitializer()) + { + MyFieldAssignmentInfo aInfo; + niceName(canonicalDecl, aInfo); + aInfo.value = getExprValue(fieldDecl->getInClassInitializer()); + assignedSet.insert(aInfo); + } + + return true; +} + +bool SingleValFields::VisitVarDecl( const VarDecl* varDecl ) +{ + if (isa(varDecl)) + return true; + if (varDecl->getType().isConstQualified()) + return true; + if (!(varDecl->isStaticLocal() || varDecl->isStaticDataMember() || varDecl->hasGlobalStorage())) + return true; + + auto canonicalDecl = varDecl->getCanonicalDecl(); + if (!canonicalDecl->getLocation().isValid()) + return true; + + if( isInUnoIncludeFile( compiler.getSourceManager().getSpellingLoc(canonicalDecl->getLocation())) ) + return true; + + MyFieldInfo aInfo; + niceName(canonicalDecl, aInfo); + definitionSet.insert(aInfo); + + if (varDecl->getInit()) + { + MyFieldAssignmentInfo aInfo; + niceName(canonicalDecl, aInfo); + aInfo.value = getExprValue(varDecl->getInit()); + assignedSet.insert(aInfo); + } + + return true; +} + +bool SingleValFields::VisitCXXConstructorDecl( const CXXConstructorDecl* decl ) +{ + // doesn't count as a write to fields because it's self->self + if (decl->isCopyOrMoveConstructor()) + return true; + + for(auto it = decl->init_begin(); it != decl->init_end(); ++it) + { + const CXXCtorInitializer* init = *it; + const FieldDecl* fieldDecl = init->getMember(); + if( !fieldDecl ) + continue; + MyFieldAssignmentInfo aInfo; + niceName(fieldDecl, aInfo); + const Expr * expr = init->getInit(); + // unwrap any single-arg constructors, this helps to find smart pointers + // that are only assigned nullptr + if (auto cxxConstructExpr = dyn_cast(expr)) + if (cxxConstructExpr->getNumArgs() == 1) + expr = cxxConstructExpr->getArg(0); + aInfo.value = getExprValue(expr); + assignedSet.insert(aInfo); + } + return true; +} + +bool SingleValFields::VisitMemberExpr( const MemberExpr* memberExpr ) +{ + const ValueDecl* decl = memberExpr->getMemberDecl(); + const FieldDecl* fieldDecl = dyn_cast(decl); + if (!fieldDecl) + return true; + walkPotentialAssign(fieldDecl, memberExpr); + return true; +} + +bool SingleValFields::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) +{ + const VarDecl* varDecl = dyn_cast_or_null(declRefExpr->getDecl()); + if (!varDecl) + return true; + if (isa(varDecl)) + return true; + if (varDecl->getType().isConstQualified()) + return true; + if (!(varDecl->isStaticLocal() || varDecl->isStaticDataMember() || varDecl->hasGlobalStorage())) + return true; + walkPotentialAssign(varDecl, declRefExpr); + return true; +} + +void SingleValFields::walkPotentialAssign( const DeclaratorDecl* fieldOrVarDecl, const Stmt* memberExpr ) +{ + const FunctionDecl* parentFunction = getParentFunctionDecl(memberExpr); + if (parentFunction) + { + auto methodDecl = dyn_cast(parentFunction); + if (methodDecl && (methodDecl->isCopyAssignmentOperator() || methodDecl->isMoveAssignmentOperator())) + return; + if (methodDecl && methodDecl->getIdentifier() + && (methodDecl->getName().startswith("Clone") || methodDecl->getName().startswith("clone"))) + return; + auto cxxConstructorDecl = dyn_cast(parentFunction); + if (cxxConstructorDecl && cxxConstructorDecl->isCopyOrMoveConstructor()) + return; + } + + // walk up the tree until we find something interesting + const Stmt* child = memberExpr; + const Stmt* parent = getParentStmt(memberExpr); + bool bPotentiallyAssignedTo = false; + bool bDump = false; + std::string assignValue = "?"; + + // check for field being returned by non-const ref eg. Foo& getFoo() { return f; } + if (parentFunction && parent && isa(parent)) { + const Stmt* parent2 = getParentStmt(parent); + if (parent2 && isa(parent2)) { + QualType qt = parentFunction->getReturnType().getDesugaredType(compiler.getASTContext()); + if (!qt.isConstQualified() && qt->isReferenceType()) { + bPotentiallyAssignedTo = true; + } + } + } + + while (!bPotentiallyAssignedTo) { + // check for field being accessed by a reference variable e.g. Foo& f = m.foo; + auto parentsList = compiler.getASTContext().getParents(*child); + auto it = parentsList.begin(); + if (it != parentsList.end()) { + const VarDecl *varDecl = it->get(); + if (varDecl) { + QualType qt = varDecl->getType().getDesugaredType(compiler.getASTContext()); + if (!qt.isConstQualified() && qt->isReferenceType()) { + bPotentiallyAssignedTo = true; + break; + } + } + } + + if (!parent) { + return; + } + if (isa(parent) || isa(parent) || isa(parent) || isa(parent) + || isa(parent)) + { + child = parent; + parent = getParentStmt(parent); + } + else if (isa(parent)) + { + const UnaryOperator* unaryOperator = dyn_cast(parent); + int x = unaryOperator->getOpcode(); + if (x == UO_AddrOf || x == UO_PostInc || x == UO_PostDec || x == UO_PreInc || x == UO_PreDec) { + assignValue = "?"; + bPotentiallyAssignedTo = true; + break; + } + // cannot be assigned to anymore + break; + } + else if (auto callExpr = dyn_cast(parent)) + { + checkCallExpr(child, callExpr, assignValue, bPotentiallyAssignedTo); + break; + } + else if (isa(parent)) + { + const CXXConstructExpr* consExpr = dyn_cast(parent); + const CXXConstructorDecl* consDecl = consExpr->getConstructor(); + for (unsigned i = 0; i < consExpr->getNumArgs(); ++i) { + if (i >= consDecl->getNumParams()) // can happen in template code + break; + if (consExpr->getArg(i) == child) { + const ParmVarDecl* parmVarDecl = consDecl->getParamDecl(i); + QualType qt = parmVarDecl->getType().getDesugaredType(compiler.getASTContext()); + if (!qt.isConstQualified() && qt->isReferenceType()) { + bPotentiallyAssignedTo = true; + } + break; + } + } + break; + } + else if (isa(parent)) + { + const BinaryOperator* binaryOp = dyn_cast(parent); + auto op = binaryOp->getOpcode(); + if ( binaryOp->getLHS() != child ) { + // if the expr is on the RHS, do nothing + } + else if ( op == BO_Assign ) { + assignValue = getExprValue(binaryOp->getRHS()); + bPotentiallyAssignedTo = true; + } else if ( op == BO_MulAssign || op == BO_DivAssign + || op == BO_RemAssign || op == BO_AddAssign + || op == BO_SubAssign || op == BO_ShlAssign + || op == BO_ShrAssign || op == BO_AndAssign + || op == BO_XorAssign || op == BO_OrAssign ) + { + bPotentiallyAssignedTo = true; + } + break; + } + else if ( isa(parent) + || isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) //??? + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + ) + { + break; + } + else if ( isa(parent) || isa(parent) || isa(parent) || isa(parent)) + { + bPotentiallyAssignedTo = true; + break; + } + else { + bPotentiallyAssignedTo = true; + bDump = true; + break; + } + } + if (bDump) + { + report( + DiagnosticsEngine::Warning, + "oh dear, what can the matter be?", + memberExpr->getBeginLoc()) + << memberExpr->getSourceRange(); + parent->dump(); + } + if (bPotentiallyAssignedTo) + { + MyFieldAssignmentInfo aInfo; + niceName(fieldOrVarDecl, aInfo); + aInfo.value = assignValue; + assignedSet.insert(aInfo); + } +} + +void SingleValFields::checkCallExpr(const Stmt* child, const CallExpr* callExpr, std::string& assignValue, bool& bPotentiallyAssignedTo) +{ + if (callExpr->getCallee() == child) { + return; + } + const FunctionDecl* functionDecl; + if (auto memberCallExpr = dyn_cast(callExpr)) { + functionDecl = memberCallExpr->getMethodDecl(); + } else { + functionDecl = callExpr->getDirectCallee(); + } + if (functionDecl) { + if (auto operatorCallExpr = dyn_cast(callExpr)) { + if (operatorCallExpr->getArg(0) == child) { + const CXXMethodDecl* calleeMethodDecl = dyn_cast_or_null(operatorCallExpr->getDirectCallee()); + if (calleeMethodDecl) { + if (operatorCallExpr->getOperator() == OO_Equal) { + assignValue = getExprValue(operatorCallExpr->getArg(1)); + bPotentiallyAssignedTo = true; + return; + } + } + } + } + for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) { + if (i >= functionDecl->getNumParams()) // can happen in template code + break; + if (callExpr->getArg(i) == child) { + const ParmVarDecl* parmVarDecl = functionDecl->getParamDecl(i); + QualType qt = parmVarDecl->getType().getDesugaredType(compiler.getASTContext()); + if (!qt.isConstQualified() && qt->isReferenceType()) { + assignValue = "?"; + bPotentiallyAssignedTo = true; + } + break; + } + } + return; + } + // check for function pointers + const FieldDecl* calleeFieldDecl = dyn_cast_or_null(callExpr->getCalleeDecl()); + if (!calleeFieldDecl) { + return; + } + QualType qt = calleeFieldDecl->getType().getDesugaredType(compiler.getASTContext()); + if (!qt->isPointerType()) { + return; + } + qt = qt->getPointeeType().getDesugaredType(compiler.getASTContext()); + const FunctionProtoType* proto = qt->getAs(); + if (!proto) { + return; + } + for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) { + if (i >= proto->getNumParams()) // can happen in template code + break; + if (callExpr->getArg(i) == child) { + QualType qt = proto->getParamType(i).getDesugaredType(compiler.getASTContext()); + if (!qt.isConstQualified() && qt->isReferenceType()) { + assignValue = "?"; + bPotentiallyAssignedTo = true; + } + break; + } + } +} + + +std::string SingleValFields::getExprValue(const Expr* arg) +{ + if (!arg) + return "?"; + arg = arg->IgnoreParenCasts(); + arg = arg->IgnoreImplicit(); + // ignore this, it seems to trigger an infinite recursion + if (isa(arg)) + return "?"; + if (arg->isValueDependent()) + return "?"; + // for stuff like: OUString foo = "xxx"; + if (auto stringLiteral = dyn_cast(arg)) + { + if (stringLiteral->getCharByteWidth() == 1) + return stringLiteral->getString().str(); + return "?"; + } + // ParenListExpr containing a CXXNullPtrLiteralExpr and has a NULL type pointer + if (auto parenListExpr = dyn_cast(arg)) + { + if (parenListExpr->getNumExprs() == 1) + return getExprValue(parenListExpr->getExpr(0)); + return "?"; + } + if (auto constructExpr = dyn_cast(arg)) + { + if (constructExpr->getNumArgs() >= 1 + && isa(constructExpr->getArg(0))) + { + auto stringLiteral = dyn_cast(constructExpr->getArg(0)); + if (stringLiteral->getCharByteWidth() == 1) + return stringLiteral->getString().str(); + return "?"; + } + } + if (arg->getType()->isFloatingType()) + { + APFloat x1(0.0f); + if (arg->EvaluateAsFloat(x1, compiler.getASTContext())) + { + std::string s; + llvm::raw_string_ostream os(s); + x1.print(os); + return os.str(); + } + } + APSInt x1; + if (compat::EvaluateAsInt(arg, x1, compiler.getASTContext())) + return compat::toString(x1, 10); + if (isa(arg)) + return "0"; + return "?"; +} + +loplugin::Plugin::Registration< SingleValFields > X("singlevalfields", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/singlevalfields.py b/compilerplugins/clang/singlevalfields.py new file mode 100755 index 000000000..0830a8cdc --- /dev/null +++ b/compilerplugins/clang/singlevalfields.py @@ -0,0 +1,111 @@ +#!/usr/bin/python3 + +import sys +import re +import io + +definitionToSourceLocationMap = dict() # dict of tuple(parentClass, fieldName) to sourceLocation +definitionToTypeMap = dict() # dict of tuple(parentClass, fieldName) to field type +fieldAssignDict = dict() # dict of tuple(parentClass, fieldName) to (set of values) + +# clang does not always use exactly the same numbers in the type-parameter vars it generates +# so I need to substitute them to ensure we can match correctly. +normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") +def normalizeTypeParams( line ): + return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) + +# reading as binary (since we known it is pure ascii) is much faster than reading as unicode +with io.open("workdir/loplugin.singlevalfields.log", "r", buffering=1024*1024) as txt: + for line in txt: + tokens = line.strip().split("\t") + if tokens[0] == "defn:": + parentClass = normalizeTypeParams(tokens[1]) + fieldName = normalizeTypeParams(tokens[2]) + fieldType = normalizeTypeParams(tokens[3]) + sourceLocation = tokens[4] + fieldInfo = (parentClass, fieldName) + definitionToSourceLocationMap[fieldInfo] = sourceLocation + definitionToTypeMap[fieldInfo] = fieldType + elif tokens[0] == "asgn:": + parentClass = normalizeTypeParams(tokens[1]) + fieldName = normalizeTypeParams(tokens[2]) + if len(tokens) > 3: + assignValue = tokens[3] + else: + assignValue = "" + fieldInfo = (parentClass, fieldName) + if not fieldInfo in fieldAssignDict: + fieldAssignDict[fieldInfo] = set() + fieldAssignDict[fieldInfo].add(assignValue) + else: + print( "unknown line: " + line) + +# look for stuff also has a single value +tmp1list = list() +# look for things which have two values - zero and one +tmp2list = list() +for fieldInfo, assignValues in fieldAssignDict.items(): + v0 = fieldInfo[0] + " " + fieldInfo[1] + v1 = (",".join(assignValues)) + v2 = "" + if fieldInfo not in definitionToSourceLocationMap: + continue + v2 = definitionToSourceLocationMap[fieldInfo] + if len(assignValues) > 2: + continue + if "?" in assignValues: + continue + #if len(assignValues - set(["0", "1", "-1", "nullptr"])) > 0: + # continue + # ignore things which are locally declared but are actually redeclarations of things from 3rd party code + containingClass = fieldInfo[0] + if containingClass == "_mwmhints": + continue + # ignore things which are representations of on-disk structures + if containingClass in ["SEPr", "WW8Dop", "BmpInfoHeader", "BmpFileHeader", "Exif::ExifIFD", + "sw::WW8FFData", "FFDataHeader", "INetURLHistory_Impl::head_entry", "ImplPPTParaPropSet", "SvxSwAutoFormatFlags", + "T602ImportFilter::T602ImportFilter::format602struct", "DataNode"]: + continue + if v2.startswith("hwpfilter/source"): + continue + # ignore things which are representations of structures from external code + if v2.startswith("desktop/unx/source/splashx.c"): + continue + # Windows-only + if containingClass in ["SfxAppData_Impl", "sfx2::ImplDdeItem", "SvFileStream", + "DdeService", "DdeTopic", "DdeItem", "DdeConnection", "connectivity::sdbcx::OUser", "connectivity::sdbcx::OGroup", "connectivity::sdbcx::OCatalog", + "cairocanvas::SpriteHelper"]: + continue + if v2.startswith("include/svl/svdde.hxx") or v2.startswith("embeddedobj/source/inc/oleembobj.hxx"): + continue + # Some of our supported compilers don't do constexpr, which means o3tl::typed_flags can't be 'static const' + if containingClass in ["WaitWindow_Impl"]: + continue + if len(assignValues) == 2: + if "0" in assignValues and "1" in assignValues: + fieldType = definitionToTypeMap[fieldInfo] + if not "_Bool" in fieldType and not "enum " in fieldType and not "boolean" in fieldType: + tmp2list.append((v0,v1,v2,fieldType)) + else: + tmp1list.append((v0,v1,v2)) + +# sort results by filename:lineno +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +tmp1list.sort(key=lambda v: natural_sort_key(v[2])) +tmp2list.sort(key=lambda v: natural_sort_key(v[2])) + +# print out the results +with open("compilerplugins/clang/singlevalfields.results", "wt") as f: + for v in tmp1list: + f.write(v[2] + "\n") + f.write(" " + v[0] + "\n") + f.write(" " + v[1] + "\n") +with open("compilerplugins/clang/singlevalfields.could-be-bool.results", "wt") as f: + for v in tmp2list: + f.write(v[2] + "\n") + f.write(" " + v[0] + "\n") + f.write(" " + v[3] + "\n") + + diff --git a/compilerplugins/clang/singlevalfields.results b/compilerplugins/clang/singlevalfields.results new file mode 100644 index 000000000..c426b4a42 --- /dev/null +++ b/compilerplugins/clang/singlevalfields.results @@ -0,0 +1,1134 @@ +avmedia/inc/mediacontrol.hxx:64 + avmedia::MediaControl maIdle + avmedia MediaControl Idle +avmedia/inc/mediacontrol.hxx:65 + avmedia::MediaControl maChangeTimeIdle + avmedia MediaControl Change Time Idle +avmedia/source/framework/soundhandler.hxx:114 + avmedia::SoundHandler m_aUpdateIdle + avmedia SoundHandler Update +basctl/source/basicide/baside2.hxx:84 + basctl::EditorWindow aHighlighter + 0 +basctl/source/inc/dlged.hxx:132 + basctl::DlgEditor aMarkIdle + basctl DlgEditor Mark +binaryurp/source/proxy.hxx:80 + binaryurp::Proxy references_ + 1 +binaryurp/source/writerstate.hxx:40 + binaryurp::WriterState typeCache + 256 +binaryurp/source/writerstate.hxx:42 + binaryurp::WriterState oidCache + 256 +binaryurp/source/writerstate.hxx:44 + binaryurp::WriterState tidCache + 256 +bridges/inc/bridge.hxx:89 + bridges::cpp_uno::shared::Bridge nRef + 1 +bridges/inc/cppinterfaceproxy.hxx:82 + bridges::cpp_uno::shared::CppInterfaceProxy nRef + 1 +bridges/inc/unointerfaceproxy.hxx:83 + bridges::cpp_uno::shared::UnoInterfaceProxy nRef + 1 +bridges/source/jni_uno/jni_bridge.h:52 + jni_uno::Bridge m_ref + 1 +bridges/source/jni_uno/jni_uno2java.cxx:391 + jni_uno::(anonymous namespace)::UNO_proxy m_ref + 1 +canvas/inc/rendering/irendermodule.hxx:35 + canvas::Vertex b + 1\10 +canvas/inc/rendering/irendermodule.hxx:35 + canvas::Vertex g + 1\10 +canvas/inc/rendering/irendermodule.hxx:35 + canvas::Vertex r + 1\10 +canvas/inc/rendering/irendermodule.hxx:37 + canvas::Vertex z + 0\10 +chart2/source/controller/dialogs/DataBrowser.cxx:201 + chart::impl::SeriesHeader m_aUpdateDataTimer + UpdateDataTimer +chart2/source/controller/inc/ChartController.hxx:377 + chart::ChartController m_aLifeTimeManager + 0 +chart2/source/controller/inc/TitleDialogData.hxx:33 + chart::TitleDialogData aPossibilityList + 7 +chart2/source/controller/inc/TitleDialogData.hxx:34 + chart::TitleDialogData aExistenceList + 7 +chart2/source/controller/inc/TitleDialogData.hxx:35 + chart::TitleDialogData aTextList + 7 +chart2/source/model/main/DataPoint.hxx:107 + chart::DataPoint m_bNoParentPropAllowed + 0 +comphelper/source/misc/threadpool.cxx:37 + comphelper gbIsWorkerThread + 1 +connectivity/source/inc/dbase/DIndexIter.hxx:33 + connectivity::dbase::OIndexIterator m_pOperator + 0 +connectivity/source/inc/dbase/DIndexIter.hxx:34 + connectivity::dbase::OIndexIterator m_pOperand + 0 +connectivity/source/inc/OColumn.hxx:40 + connectivity::OColumn m_AutoIncrement + 0 +connectivity/source/inc/OColumn.hxx:41 + connectivity::OColumn m_CaseSensitive + 0 +connectivity/source/inc/OColumn.hxx:42 + connectivity::OColumn m_Searchable + 1 +connectivity/source/inc/OColumn.hxx:43 + connectivity::OColumn m_Currency + 0 +connectivity/source/inc/OColumn.hxx:44 + connectivity::OColumn m_Signed + 0 +connectivity/source/inc/OColumn.hxx:45 + connectivity::OColumn m_ReadOnly + 1 +connectivity/source/inc/OColumn.hxx:46 + connectivity::OColumn m_Writable + 0 +connectivity/source/inc/OColumn.hxx:47 + connectivity::OColumn m_DefinitelyWritable + 0 +connectivity/source/inc/writer/WTable.hxx:43 + connectivity::writer::OWriterTable m_nStartCol + 0 +cppu/source/uno/copy.hxx:38 + cppu::(anonymous namespace)::SequencePrefix nRefCount + 1 +cui/source/inc/acccfg.hxx:100 + SfxAcceleratorConfigPage m_aUpdateDataTimer + UpdateDataTimer +cui/source/inc/AdditionsDialog.hxx:59 + AdditionsDialog m_aSearchDataTimer + SearchDataTimer +cui/source/inc/cfg.hxx:372 + SvxConfigPage m_aUpdateDataTimer + UpdateDataTimer +cui/source/inc/linkdlg.hxx:45 + SvBaseLinksDlg aUpdateIdle + cui SvBaseLinksDlg UpdateIdle +cui/source/inc/thesdlg.hxx:31 + SvxThesaurusDialog m_aModifyIdle + cui SvxThesaurusDialog LookUp Modify +cui/source/options/optgdlg.cxx:1010 + LanguageConfig_Impl aLanguageOptions + 0 +cui/source/options/optjava.hxx:59 + SvxJavaOptionsPage m_aResetIdle + cui options SvxJavaOptionsPage Reset +dbaccess/source/ui/inc/sqledit.hxx:42 + dbaui::SQLEditView m_aHighlighter + 1 +desktop/source/app/app.cxx:480 + desktop::Desktop::Init bTryHardOfficeconfigBroken + 0 +desktop/source/app/cmdlineargs.hxx:136 + desktop::CommandLineArgs m_quickstart + 0 +drawinglayer/source/primitive2d/sceneprimitive2d.cxx:373 + drawinglayer::primitive2d::ScenePrimitive2D::create2DDecomposition bMultithreadAllowed + 0 +drawinglayer/source/primitive2d/sceneprimitive2d.cxx:481 + drawinglayer::primitive2d::ScenePrimitive2D::create2DDecomposition bAddOutlineToCreated3DSceneRepresentation + 0 +drawinglayer/source/processor2d/vclhelperbufferdevice.cxx:333 + drawinglayer::impBufferDevice::paint bDoSaveForVisualControl + 0 +drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx:950 + drawinglayer::processor2d::VclMetafileProcessor2D::processGraphicPrimitive2D bSuppressPDFExtOutDevDataSupport + 0 +drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx:1298 + drawinglayer::processor2d::VclMetafileProcessor2D::processTextHierarchyParagraphPrimitive2D bSuppressPDFExtOutDevDataSupport + 0 +drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx:2057 + drawinglayer::processor2d::VclMetafileProcessor2D::processUnifiedTransparencePrimitive2D bForceToMetafile + 0 +drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx:2158 + drawinglayer::processor2d::VclMetafileProcessor2D::processTransparencePrimitive2D bForceToBigTransparentVDev + 0 +drawinglayer/source/tools/converters.cxx:91 + drawinglayer::convertToBitmapEx bDoSaveForVisualControl + 0 +editeng/source/editeng/impedit.hxx:530 + ImpEditEngine nBigTextObjectStart + 20 +emfio/qa/cppunit/wmf/wmfimporttest.cxx:34 + WmfTest maDataUrl + /emfio/qa/cppunit/wmf/data/ +emfio/source/reader/emfreader.cxx:1596 + emfio::EmfReader::ReadEnhWMF bDoSaveForVisualControl + 0 +extensions/source/bibliography/bibcont.hxx:67 + BibBookContainer aIdle + extensions BibBookContainer Split Idle +filter/source/msfilter/msdffimp.cxx:2637 + DffPropertyReader::ApplyAttributes bCheckShadow + 0 +filter/source/msfilter/viscache.hxx:29 + Impl_OlePres nFormat + 3 +framework/source/services/autorecovery.cxx:398 + (anonymous namespace)::AutoRecovery m_aTimer + Auto save timer +framework/source/uiconfiguration/imagemanagerimpl.hxx:172 + framework::ImageManagerImpl m_aResourceString + private:resource/images/moduleimages +helpcompiler/inc/BasCodeTagger.hxx:28 + BasicCodeTagger m_Highlighter + 0 +i18npool/source/localedata/localedata.cxx:50 + /home/noel/libo2/i18npool/source/localedata/localedata.cxx lcl_DATA_EN + localedata_en +i18npool/source/localedata/localedata.cxx:51 + /home/noel/libo2/i18npool/source/localedata/localedata.cxx lcl_DATA_ES + localedata_es +i18npool/source/localedata/localedata.cxx:52 + /home/noel/libo2/i18npool/source/localedata/localedata.cxx lcl_DATA_EURO + localedata_euro +i18npool/source/localedata/localedata.cxx:53 + /home/noel/libo2/i18npool/source/localedata/localedata.cxx lcl_DATA_OTHERS + localedata_others +idlc/source/idlccompile.cxx:51 + /home/noel/libo2/idlc/source/idlccompile.cxx yydebug + 0 +include/basegfx/pixel/bpixel.hxx:41 + basegfx::BPixel::(anonymous union)::(anonymous) mnValue + 0 +include/basegfx/pixel/bpixel.hxx:42 + basegfx::BPixel::(anonymous) maCombinedRGBA + 0 +include/basic/sbxvar.hxx:75 + SbxValues::(anonymous) pData + 0 +include/comphelper/parallelsort.hxx:88 + comphelper::(anonymous namespace)::ProfileZone mbDummy + 1 +include/editeng/swafopt.hxx:58 + editeng::SortedAutoCompleteStrings owning_ + 1 +include/filter/msfilter/dffpropset.hxx:33 + DffPropFlags bSet + 0 +include/filter/msfilter/dffpropset.hxx:34 + DffPropFlags bComplex + 1 +include/filter/msfilter/dffpropset.hxx:35 + DffPropFlags bBlip + 1 +include/i18nutil/casefolding.hxx:58 + i18nutil::Mapping nmap + 0 +include/o3tl/cow_wrapper.hxx:203 + o3tl::cow_wrapper::impl_t m_ref_count + 1 +include/o3tl/vector_pool.hxx:93 + o3tl::detail::struct_from_value::type nextFree + -1 +include/oox/core/contexthandler2.hxx:216 + oox::core::ContextHandler2Helper mnRootStackSize + 0 +include/oox/dump/dumperbase.hxx:1680 + oox::dump::RecordObjectBase mbBinaryOnly + 0 +include/oox/ole/axcontrol.hxx:426 + oox::ole::ComCtlModelBase mbCommonPart + 1 +include/oox/ole/axcontrol.hxx:427 + oox::ole::ComCtlModelBase mbComplexPart + 1 +include/sfx2/msg.hxx:187 + SfxSlot nGroupId + 0 +include/sfx2/msg.hxx:191 + SfxSlot nValue + 0 +include/sfx2/msg.hxx:196 + SfxSlot pType + 0 +include/sfx2/msg.hxx:200 + SfxSlot pFirstArgDef + 0 +include/sfx2/msg.hxx:201 + SfxSlot nArgDefCount + 0 +include/sfx2/templatedlg.hxx:131 + SfxTemplateManagerDlg m_aUpdateDataTimer + UpdateDataTimer +include/svtools/ctrlbox.hxx:339 + FontNameBox maUpdateIdle + FontNameBox Preview Update +include/svtools/filechangedchecker.hxx:31 + FileChangedChecker mTimer + SVTools FileChangedChecker Timer +include/svtools/svparser.hxx:55 + SvParser pImplData + 0 +include/svtools/svparser.hxx:73 + SvParser::TokenStackType nTokenValue + 0 +include/svtools/svparser.hxx:74 + SvParser::TokenStackType bTokenHasValue + 0 +include/svtools/tabbar.hxx:323 + TabBar mnOffY + 0 +include/svx/ctredlin.hxx:92 + SvxRedlinTable aDaTiFirst + 0 +include/svx/ctredlin.hxx:93 + SvxRedlinTable aDaTiLast + 0 +include/svx/deflt3d.hxx:40 + E3dDefaultAttributes bDefaultCubePosIsCenter + 0 +include/svx/deflt3d.hxx:47 + E3dDefaultAttributes bDefaultLatheSmoothed + 1 +include/svx/deflt3d.hxx:48 + E3dDefaultAttributes bDefaultLatheSmoothFrontBack + 0 +include/svx/deflt3d.hxx:50 + E3dDefaultAttributes bDefaultLatheCloseFront + 1 +include/svx/deflt3d.hxx:51 + E3dDefaultAttributes bDefaultLatheCloseBack + 1 +include/svx/deflt3d.hxx:54 + E3dDefaultAttributes bDefaultExtrudeSmoothed + 1 +include/svx/deflt3d.hxx:55 + E3dDefaultAttributes bDefaultExtrudeSmoothFrontBack + 0 +include/svx/fontwork.hxx:77 + SvxFontWorkDialog aInputIdle + SvxFontWorkDialog Input +include/svx/graphctl.hxx:53 + GraphCtrl aUpdateIdle + svx GraphCtrl Update +include/svx/numvset.hxx:92 + SvxBmpNumValueSet aFormatIdle + SvxBmpNumValueSet FormatIdle +include/svx/srchdlg.hxx:141 + SvxSearchDialog m_aPresentIdle + Bring SvxSearchDialog to Foreground +include/svx/svdcrtv.hxx:50 + SdrCreateView nAutoCloseDistPix + 5 +include/svx/svdcrtv.hxx:51 + SdrCreateView nFreeHandMinDistPix + 10 +include/svx/svdmark.hxx:144 + SdrMarkList mbPointNameOk + 0 +include/svx/svdmark.hxx:145 + SdrMarkList mbGluePointNameOk + 0 +include/vcl/settings.hxx:143 + DialogStyle content_area_border + 2 +include/vcl/settings.hxx:144 + DialogStyle button_spacing + 6 +include/vcl/settings.hxx:145 + DialogStyle action_area_border + 5 +include/vcl/toolkit/treelistbox.hxx:212 + SvTreeListBox nIndent + 20 +io/qa/textinputstream.cxx:97 + (anonymous namespace)::Input open_ + 1 +libreofficekit/source/gtk/lokdocview.cxx:85 + (anonymous namespace)::LOKDocViewPrivateImpl m_bIsLoading + 0 +lotuswordpro/source/filter/lwppara.hxx:213 + LwpPara m_AllText + +oox/source/core/contexthandler2.cxx:36 + oox::core::ElementInfo maChars + 0 +opencl/source/opencl_device.cxx:54 + (anonymous namespace)::LibreOfficeDeviceEvaluationIO inputSize + 15360 +opencl/source/opencl_device.cxx:55 + (anonymous namespace)::LibreOfficeDeviceEvaluationIO outputSize + 15360 +package/inc/ZipFile.hxx:61 + ZipFile aInflater + 1 +package/source/zipapi/XUnbufferedStream.hxx:57 + XUnbufferedStream maInflater + 1 +pyuno/source/module/pyuno_gc.cxx:30 + pyuno g_destructorsOfStaticObjectsHaveBeenCalled + 1 +pyuno/source/module/pyuno_impl.hxx:226 + pyuno::RuntimeCargo valid + 1 +reportdesign/source/ui/inc/DesignView.hxx:62 + rptui::ODesignView m_aMarkIdle + reportdesign ODesignView Mark Idle +sal/osl/unx/signal.cxx:81 + (anonymous namespace)::SignalAction Action + 1 +sal/osl/unx/sockimpl.hxx:39 + oslSocketImpl m_bIsInShutdown + 1 +sal/qa/osl/condition/osl_Condition_Const.h:41 + /home/noel/libo2/sal/qa/osl/condition/osl_Condition.cxx aTestCon + testcondition +sal/qa/osl/file/osl_File_Const.h:118 + extern aPreURL + file:/// +sal/qa/osl/file/osl_File_Const.h:131 + extern aCanURL3 + ca@#;+.,$//tmp/678nonical//name +sal/qa/osl/file/osl_File_Const.h:132 + extern aCanURL4 + canonical.name +sal/qa/osl/file/osl_File_Const.h:144 + extern aRelURL1 + relative/file1 +sal/qa/osl/file/osl_File_Const.h:145 + extern aRelURL2 + relative/./file2 +sal/qa/osl/file/osl_File_Const.h:146 + extern aRelURL3 + relative/../file3 +sal/qa/osl/file/osl_File_Const.h:168 + extern aTypeURL1 + file:///dev/ccv +sal/qa/osl/file/osl_File_Const.h:169 + extern aTypeURL2 + file:///devices/pseudo/tcp@0:tcp +sal/qa/osl/file/osl_File_Const.h:170 + extern aTypeURL3 + file:///lib +sal/qa/osl/file/osl_File_Const.h:185 + extern aVolURL2 + file:///dev/floppy/0u1440 +sal/qa/osl/file/osl_File_Const.h:187 + extern aVolURL3 + file:///proc +sal/qa/osl/file/osl_File_Const.h:188 + extern aVolURL4 + file:///staroffice +sal/qa/osl/file/osl_File_Const.h:189 + extern aVolURL5 + file:///tmp +sal/qa/osl/file/osl_File_Const.h:190 + extern aVolURL6 + file:///cdrom +sal/qa/osl/process/osl_process.cxx:151 + Test_osl_executeProcess env_param_ + -env +sal/qa/osl/process/osl_Thread.cxx:224 + (anonymous namespace)::myThread m_aFlag + 0 +sal/qa/osl/process/osl_Thread.cxx:264 + (anonymous namespace)::OCountThread m_aFlag + 0 +sal/qa/osl/process/osl_Thread.cxx:327 + (anonymous namespace)::ONoScheduleThread m_aFlag + 0 +sal/qa/osl/process/osl_Thread.cxx:368 + (anonymous namespace)::OAddThread m_aFlag + 0 +sal/qa/rtl/process/rtl_Process_Const.h:29 + extern suParam0 + -join +sal/qa/rtl/process/rtl_Process_Const.h:30 + extern suParam1 + -with +sal/qa/rtl/process/rtl_Process_Const.h:31 + extern suParam2 + -child +sal/qa/rtl/process/rtl_Process_Const.h:32 + extern suParam3 + -process +sal/qa/rtl/strings/test_ostring_stringliterals.cxx:22 + /home/noel/libo2/sal/qa/rtl/strings/test_ostring_stringliterals.cxx rtl_string_unittest_non_const_literal_function + 0 +sal/qa/rtl/strings/test_strings_replace.cxx:24 + (anonymous) s_bar + bar +sal/qa/rtl/strings/test_strings_replace.cxx:25 + (anonymous) s_bars + bars +sal/qa/rtl/strings/test_strings_replace.cxx:26 + (anonymous) s_foo + foo +sal/qa/rtl/strings/test_strings_replace.cxx:27 + (anonymous) s_other + other +sal/qa/rtl/strings/test_strings_replace.cxx:28 + (anonymous) s_xa + xa +sal/qa/rtl/strings/test_strings_replace.cxx:29 + (anonymous) s_xx + xx +sax/source/tools/fastserializer.hxx:232 + sax_fastparser::FastSaxSerializer mbXescape + 1 +sc/inc/compiler.hxx:112 + ScRawToken::(anonymous union)::(anonymous) eInForceArray + 0 +sc/inc/document.hxx:437 + ScDocument aTrackIdle + sc ScDocument Track Idle +sc/inc/drwlayer.hxx:230 + /home/noel/libo2/sc/source/core/data/drwlayer.cxx bDrawIsInUndo + 0 +sc/inc/global.hxx:910 + /home/noel/libo2/sc/source/core/data/global.cxx pScActiveViewShell + 0 +sc/inc/global.hxx:911 + /home/noel/libo2/sc/source/core/data/global.cxx nScClickMouseModifier + 0 +sc/inc/global.hxx:912 + /home/noel/libo2/sc/source/core/data/global.cxx nScFillModeMouseModifier + 0 +sc/inc/markmulti.hxx:80 + ScMultiSelIter aMarkArrayIter + 0 +sc/inc/refdata.hxx:38 + ScSingleRefData::(anonymous) mnFlagValue + 0 +sc/inc/scmod.hxx:81 + ScModule m_aIdleTimer + sc ScModule IdleTimer +sc/inc/table.hxx:180 + ScTable mpRowHeights + 0 +sc/qa/extras/check_data_pilot_field.cxx:63 + sc_apitest::CheckDataPilotField mMaxFieldIndex + 6 +sc/qa/unit/screenshots/screenshots.cxx:40 + ScScreenshotTest mCsv + some, strings, here, separated, by, commas +sc/qa/unit/ucalc.hxx:42 + Test::RangeNameDef mnIndex + 1 +sc/source/core/inc/parclass.hxx:93 + ScParameterClassification::RunData bHasForceArray + 1 +sc/source/core/tool/scmatrix.cxx:344 + /home/noel/libo2/sc/source/core/tool/scmatrix.cxx bElementsMaxFetched + 1 +sc/source/filter/inc/extlstcontext.hxx:19 + /home/noel/libo2/sc/source/filter/oox/condformatbuffer.cxx rStyleIdx + 0 +sc/source/filter/inc/orcusinterface.hxx:186 + ScOrcusConditionalFormat meEntryType + 0 +sc/source/filter/inc/xltracer.hxx:81 + XclTracer mbEnabled + 0 +sc/source/ui/inc/acredlin.hxx:50 + ScAcceptChgDlg aSelectionIdle + ScAcceptChgDlg SelectionIdle +sc/source/ui/inc/acredlin.hxx:51 + ScAcceptChgDlg aReOpenIdle + ScAcceptChgDlg ReOpenIdle +sc/source/ui/inc/autostyl.hxx:58 + ScAutoStyleList aTimer + ScAutoStyleList Timer +sc/source/ui/inc/autostyl.hxx:59 + ScAutoStyleList aInitIdle + ScAutoStyleList InitIdle +sc/source/ui/inc/conflictsdlg.hxx:119 + ScConflictsDlg maSelectionIdle + ScConflictsDlg SelectionIdle +sc/source/ui/inc/hdrcont.hxx:38 + ScHeaderControl aShowHelpTimer + sc HeaderControl Popover Timer +sc/source/ui/inc/viewdata.hxx:288 + ScViewData aLogicMode + 0 +sc/source/ui/inc/viewfunc.hxx:377 + /home/noel/libo2/sc/source/ui/view/viewfun7.cxx bPasteIsMove + 0 +sc/source/ui/view/output2.cxx:119 + ScDrawStringsVars mCachedGlyphs + 1000 +sccomp/source/solver/SwarmSolver.cxx:124 + (anonymous namespace)::SwarmSolver mfResultValue + 0\10 +sd/inc/sdpptwrp.hxx:43 + SdPPTFilter pBas + 0 +sd/source/filter/html/htmlex.hxx:116 + HtmlExport mbAutoSlide + 1 +sd/source/ui/framework/module/ShellStackGuard.hxx:83 + sd::framework::ShellStackGuard maPrinterPollingIdle + sd ShellStackGuard PrinterPollingIdle +sd/source/ui/inc/CustomAnimationPane.hxx:143 + sd::CustomAnimationPane maIdle + sd idle treeview select +sd/source/ui/inc/pubdlg.hxx:157 + SdPublishingDlg aAssistentFunc + 6 +sd/source/ui/inc/View.hxx:262 + sd::View maDropErrorIdle + sd View DropError +sd/source/ui/inc/View.hxx:263 + sd::View maDropInsertFileIdle + sd View DropInsertFile +sd/source/ui/inc/WindowUpdater.hxx:97 + sd::WindowUpdater maCTLOptions + 0 +sd/source/ui/presenter/SlideRenderer.hxx:81 + sd::presenter::SlideRenderer maPreviewRenderer + 1 +sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx:41 + sd::slidesorter::cache::BitmapFactory maRenderer + 0 +sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx:91 + sd::slidesorter::controller::Animator maIdle + sd slidesorter controller Animator +sdext/source/pdfimport/pdfparse/pdfparse.cxx:60 + (anonymous namespace)::StringEmitContext m_aBuf + 256 +sfx2/inc/autoredactdialog.hxx:97 + SfxAutoRedactDialog m_bIsValidState + 1 +sfx2/source/appl/lnkbase2.cxx:79 + sfx2::ImplBaseLinkData::tDDEType pItem + 0 +sfx2/source/appl/lnkbase2.cxx:84 + sfx2::ImplBaseLinkData::(anonymous) DDEType + 0 +sfx2/source/appl/lnkbase2.cxx:103 + sfx2::(anonymous namespace)::ImplDdeItem bIsInDTOR + 1 +sfx2/source/appl/newhelp.hxx:94 + IndexTabPage_Impl aFactoryIdle + sfx2 appl IndexTabPage_Impl Factory +sfx2/source/appl/newhelp.hxx:95 + IndexTabPage_Impl aAutoCompleteIdle + sfx2 appl IndexTabPage_Impl AutoComplete +sfx2/source/appl/newhelp.hxx:227 + SfxHelpIndexWindow_Impl aIdle + sfx2 appl SfxHelpIndexWindow_Impl +sfx2/source/appl/newhelp.hxx:347 + SfxHelpTextWindow_Impl aSelectIdle + sfx2 appl SfxHelpTextWindow_Impl Select +sfx2/source/control/itemdel.cxx:31 + SfxItemDisruptor_Impl m_Idle + sfx SfxItemDisruptor_Impl::Delete +slideshow/source/engine/slideshowimpl.cxx:473 + (anonymous namespace)::SlideShowImpl maFrameSynchronization + 0.02\10 +soltools/cpp/_cpp.c:31 + /home/noel/libo2/soltools/cpp/_cpp.c nerrs + 1 +soltools/cpp/_eval.c:742 + tokval cvlen + 20 +soltools/cpp/_macro.c:168 + doadefine onestr + 1 +soltools/cpp/cpp.h:120 + includelist deleted + 1 +soltools/mkdepend/def.h:116 + inclist i_notified + 1 +soltools/mkdepend/def.h:118 + inclist i_searched + 1 +soltools/mkdepend/def.h:185 + /home/noel/libo2/soltools/mkdepend/main.c printed + 0 +soltools/mkdepend/def.h:185 + /home/noel/libo2/soltools/mkdepend/pr.c printed + 1 +soltools/mkdepend/def.h:189 + /home/noel/libo2/soltools/mkdepend/main.c show_where_not + 0 +starmath/inc/cfgitem.hxx:105 + SmMathConfig vFontPickList + 5 +starmath/inc/edit.hxx:55 + SmEditWindow aModifyIdle + SmEditWindow ModifyIdle +stoc/source/corereflection/lrucache.hxx:52 + LRU_Cache _pBlock + 0 +stoc/source/inspect/introspection.cxx:1506 + (anonymous namespace)::Cache::Data hits + 1 +stoc/source/security/access_controller.cxx:65 + (anonymous) s_envType + gcc3 +stoc/source/security/access_controller.cxx:304 + (anonymous namespace)::AccessController m_rec + 0 +stoc/source/security/lru_cache.h:54 + stoc_sec::lru_cache m_block + 0 +svgio/source/svgreader/svgdocumenthandler.cxx:82 + (anonymous namespace)::whiteSpaceHandling bNoGapsForBaselineShift + 1 +svl/source/crypto/cryptosign.cxx:151 + (anonymous namespace)::TimeStampReq extensions + 0 +svx/inc/sdr/overlay/overlaymanagerbuffered.hxx:42 + sdr::overlay::OverlayManagerBuffered maBufferIdle + sdr overlay OverlayManagerBuffered Idle +svx/source/dialog/contimp.hxx:70 + SvxSuperContourDlg aUpdateIdle + SvxSuperContourDlg UpdateIdle +svx/source/dialog/contimp.hxx:71 + SvxSuperContourDlg aCreateIdle + SvxSuperContourDlg CreateIdle +svx/source/inc/StylesPreviewWindow.hxx:61 + StyleItemController m_eStyleFamily + 2 +svx/source/sdr/contact/viewcontactofsdrpage.cxx:104 + sdr::contact::ViewContactOfPageShadow::createViewIndependentPrimitive2DSequence bUseOldPageShadow + 0 +svx/source/sidebar/media/MediaPlaybackPanel.hxx:58 + svx::sidebar::MediaPlaybackPanel maIdle + MediaPlaybackPanel +svx/source/tbxctrls/lboxctrl.cxx:49 + SvxPopupWindowListBox m_nVisRows + 10 +svx/source/unodraw/recoveryui.cxx:63 + (anonymous namespace)::RecoveryUI m_pParentWindow + 0 +sw/inc/authfld.hxx:156 + SwAuthorityField m_nTempSequencePos + -1 +sw/inc/authfld.hxx:157 + SwAuthorityField m_nTempSequencePosRLHidden + -1 +sw/inc/checkit.hxx:38 + /home/noel/libo2/sw/source/core/bastyp/init.cxx pCheckIt + 0 +sw/inc/dbgoutsw.hxx:51 + /home/noel/libo2/sw/source/core/doc/dbgoutsw.cxx bDbgOutStdErr + 0 +sw/inc/dbgoutsw.hxx:52 + /home/noel/libo2/sw/source/core/doc/dbgoutsw.cxx bDbgOutPrintAttrSet + 0 +sw/inc/ftninfo.hxx:46 + SwEndNoteInfo m_aFormat + 4 +sw/inc/hints.hxx:272 + SwAttrSetChg m_bDelSet + 0 +sw/inc/modcfg.hxx:210 + SwModuleOptions m_aWebInsertConfig + 1 +sw/inc/modcfg.hxx:213 + SwModuleOptions m_aWebTableConfig + 1 +sw/inc/swmodule.hxx:265 + /home/noel/libo2/sw/source/core/frmedt/feshview.cxx g_bNoInterrupt + 0 +sw/inc/swmodule.hxx:265 + /home/noel/libo2/sw/source/uibase/app/swmodule.cxx g_bNoInterrupt + 0 +sw/inc/swmodule.hxx:265 + /home/noel/libo2/sw/source/uibase/docvw/edtdd.cxx g_bNoInterrupt + 0 +sw/inc/swmodule.hxx:265 + /home/noel/libo2/sw/source/uibase/ribbar/conform.cxx g_bNoInterrupt + 1 +sw/inc/view.hxx:201 + SwView m_pHScrollbar + 0 +sw/inc/view.hxx:202 + SwView m_pVScrollbar + 0 +sw/inc/view.hxx:719 + /home/noel/libo2/sw/source/uibase/uiview/view.cxx bDocSzUpdated + 1 +sw/inc/view.hxx:719 + /home/noel/libo2/sw/source/uibase/uiview/viewport.cxx bDocSzUpdated + 0 +sw/inc/viewopt.hxx:195 + SwViewOption m_bTest10 + 0 +sw/source/core/bastyp/calc.cxx:99 + CalcOp eOp + 0 +sw/source/core/doc/docredln.cxx:67 + sw_DebugRedline nWatch + 0 +sw/source/core/docnode/threadmanager.hxx:125 + ThreadManager maStartNewThreadIdle + SW ThreadManager StartNewThreadIdle +sw/source/core/inc/DocumentTimerManager.hxx:75 + sw::DocumentTimerManager m_aFireIdleJobsTimer + sw::DocumentTimerManager m_aFireIdleJobsTimer +sw/source/core/inc/fntcache.hxx:60 + /home/noel/libo2/sw/source/core/txtnode/fntcache.cxx pFntCache + 0 +sw/source/core/inc/fntcache.hxx:61 + /home/noel/libo2/sw/source/core/txtnode/fntcache.cxx pLastFont + 0 +sw/source/core/inc/frmtool.hxx:154 + /home/noel/libo2/sw/source/core/layout/frmtool.cxx bDontCreateObjects + 0 +sw/source/core/inc/frmtool.hxx:157 + /home/noel/libo2/sw/source/core/layout/frmtool.cxx bSetCompletePaintOnInvalidate + 0 +sw/source/core/inc/noteurl.hxx:28 + /home/noel/libo2/sw/source/core/text/noteurl.cxx pNoteURL + 0 +sw/source/core/inc/swfntcch.hxx:43 + /home/noel/libo2/sw/source/core/txtnode/swfntcch.cxx pSwFontCache + 0 +sw/source/core/inc/txtfly.hxx:44 + /home/noel/libo2/sw/source/core/text/txtinit.cxx pContourCache + 0 +sw/source/core/inc/UndoSort.hxx:38 + SwSortUndoElement::(anonymous union)::(anonymous) nID + 4294967295 +sw/source/core/inc/UndoSplitMove.hxx:57 + SwUndoMove m_bJoinNext + 0 +sw/source/core/layout/flylay.cxx:306 + SwFlyFreeFrame::supportsAutoContour bOverrideHandleContourToAlwaysOff + 1 +sw/source/core/ole/ndole.cxx:1089 + SwOLEObj::tryToGetChartContentAsPrimitive2DSequence bAsynchronousLoadingAllowed + 0 +sw/source/core/text/pordrop.hxx:32 + /home/noel/libo2/sw/source/core/text/txtinit.cxx pDropCapCache + 0 +sw/source/filter/inc/rtf.hxx:31 + RTFSurround::(anonymous union)::(anonymous) nJunk + 0 +sw/source/filter/ww8/ww8par3.cxx:340 + (anonymous namespace)::WW8LST bSimpleList + 1 +sw/source/filter/ww8/ww8par3.cxx:341 + (anonymous namespace)::WW8LST bRestartHdn + 1 +sw/source/filter/ww8/ww8par3.cxx:375 + (anonymous namespace)::WW8LVL bV6Prev + 1 +sw/source/filter/ww8/ww8par3.cxx:376 + (anonymous namespace)::WW8LVL bV6PrSp + 1 +sw/source/filter/ww8/ww8par3.cxx:377 + (anonymous namespace)::WW8LVL bV6 + 1 +sw/source/filter/ww8/ww8par5.cxx:1566 + SwWW8ImplReader::Read_F_DocInfo aName10 + \15 +sw/source/filter/ww8/ww8par5.cxx:1567 + SwWW8ImplReader::Read_F_DocInfo aName11 + TITEL +sw/source/filter/ww8/ww8par5.cxx:1569 + SwWW8ImplReader::Read_F_DocInfo aName12 + TITRE +sw/source/filter/ww8/ww8par5.cxx:1571 + SwWW8ImplReader::Read_F_DocInfo aName13 + TITLE +sw/source/filter/ww8/ww8par5.cxx:1573 + SwWW8ImplReader::Read_F_DocInfo aName14 + TITRO +sw/source/filter/ww8/ww8par5.cxx:1575 + SwWW8ImplReader::Read_F_DocInfo aName20 + \21 +sw/source/filter/ww8/ww8par5.cxx:1576 + SwWW8ImplReader::Read_F_DocInfo aName21 + ERSTELLDATUM +sw/source/filter/ww8/ww8par5.cxx:1578 + SwWW8ImplReader::Read_F_DocInfo aName22 + CR\-55\-55 +sw/source/filter/ww8/ww8par5.cxx:1580 + SwWW8ImplReader::Read_F_DocInfo aName23 + CREATED +sw/source/filter/ww8/ww8par5.cxx:1582 + SwWW8ImplReader::Read_F_DocInfo aName24 + CREADO +sw/source/filter/ww8/ww8par5.cxx:1584 + SwWW8ImplReader::Read_F_DocInfo aName30 + \22 +sw/source/filter/ww8/ww8par5.cxx:1585 + SwWW8ImplReader::Read_F_DocInfo aName31 + ZULETZTGESPEICHERTZEIT +sw/source/filter/ww8/ww8par5.cxx:1587 + SwWW8ImplReader::Read_F_DocInfo aName32 + DERNIERENREGISTREMENT +sw/source/filter/ww8/ww8par5.cxx:1589 + SwWW8ImplReader::Read_F_DocInfo aName33 + SAVED +sw/source/filter/ww8/ww8par5.cxx:1591 + SwWW8ImplReader::Read_F_DocInfo aName34 + MODIFICADO +sw/source/filter/ww8/ww8par5.cxx:1593 + SwWW8ImplReader::Read_F_DocInfo aName40 + \23 +sw/source/filter/ww8/ww8par5.cxx:1594 + SwWW8ImplReader::Read_F_DocInfo aName41 + ZULETZTGEDRUCKT +sw/source/filter/ww8/ww8par5.cxx:1596 + SwWW8ImplReader::Read_F_DocInfo aName42 + DERNI\-56REIMPRESSION +sw/source/filter/ww8/ww8par5.cxx:1598 + SwWW8ImplReader::Read_F_DocInfo aName43 + LASTPRINTED +sw/source/filter/ww8/ww8par5.cxx:1600 + SwWW8ImplReader::Read_F_DocInfo aName44 + HUPS PUPS +sw/source/filter/ww8/ww8par5.cxx:1602 + SwWW8ImplReader::Read_F_DocInfo aName50 + \24 +sw/source/filter/ww8/ww8par5.cxx:1603 + SwWW8ImplReader::Read_F_DocInfo aName51 + \-36BERARBEITUNGSNUMMER +sw/source/filter/ww8/ww8par5.cxx:1605 + SwWW8ImplReader::Read_F_DocInfo aName52 + NUM\-55RODEREVISION +sw/source/filter/ww8/ww8par5.cxx:1607 + SwWW8ImplReader::Read_F_DocInfo aName53 + REVISIONNUMBER +sw/source/filter/ww8/ww8par5.cxx:1609 + SwWW8ImplReader::Read_F_DocInfo aName54 + SNUBBEL BUBBEL +sw/source/filter/ww8/ww8par.hxx:669 + WW8FormulaControl mfUnknown + 0 +sw/source/filter/ww8/ww8par.hxx:676 + WW8FormulaControl mhpsCheckBox + 20 +sw/source/filter/ww8/ww8par.hxx:1035 + WW8TabBandDesc bCantSplit90 + 0 +sw/source/filter/ww8/ww8scan.hxx:1165 + WW8Fib m_fObfuscated + 0 +sw/source/filter/ww8/ww8scan.hxx:1511 + WW8Fib m_fcPlcffactoid + 0 +sw/source/filter/ww8/ww8scan.hxx:1513 + WW8Fib m_lcbPlcffactoid + 0 +sw/source/filter/ww8/ww8scan.hxx:1518 + WW8Fib m_lcbHplxsdr + 0 +sw/source/filter/ww8/ww8struc.hxx:542 + WW8_TCell fUnused + 0 +sw/source/filter/ww8/ww8struc.hxx:899 + WW8_TablePos nSp37 + 2 +sw/source/ui/envelp/labfmt.hxx:68 + SwLabFormatPage aPreviewIdle + SwLabFormatPage Preview +sw/source/uibase/inc/edtdd.hxx:15 + /home/noel/libo2/sw/source/uibase/docvw/edtwin.cxx g_bExecuteDrag + 0 +sw/source/uibase/inc/edtwin.hxx:300 + /home/noel/libo2/sw/source/uibase/docvw/edtdd.cxx g_bFrameDrag + 0 +sw/source/uibase/inc/edtwin.hxx:301 + /home/noel/libo2/sw/source/uibase/docvw/edtwin.cxx g_bDDTimerStarted + 0 +sw/source/uibase/inc/edtwin.hxx:303 + /home/noel/libo2/sw/source/uibase/dochdl/swdtflvr.cxx g_bDDINetAttr + 1 +sw/source/uibase/inc/edtwin.hxx:303 + /home/noel/libo2/sw/source/uibase/docvw/edtwin.cxx g_bDDINetAttr + 0 +sw/source/uibase/inc/instable.hxx:44 + SwInsTableDlg minTableIndexInLb + 1 +sw/source/uibase/inc/pview.hxx:178 + SwPagePreview m_pHScrollbar + 0 +sw/source/uibase/inc/pview.hxx:179 + SwPagePreview m_pVScrollbar + 0 +sw/source/uibase/inc/srcedtw.hxx:84 + SwSrcEditWindow m_aSyntaxIdle + sw uibase SwSrcEditWindow Syntax +sw/source/uibase/inc/unotools.hxx:46 + SwOneExampleFrame m_aLoadedIdle + sw uibase SwOneExampleFrame Loaded +unotools/source/config/saveopt.cxx:82 + (anonymous namespace)::SvtSaveOptions_Impl bROUserAutoSave + 0 +vcl/headless/svpgdi.cxx:598 + (anonymous) nMinimalSquareSizeToBuffer + 4096 +vcl/headless/svpgdi.cxx:1641 + SvpSalGraphics::drawPolyLine bDoDirectCairoStroke + 1 +vcl/inc/canvasbitmap.hxx:53 + vcl::unotools::VclCanvasBitmap m_nEndianness + 0 +vcl/inc/graphic/Manager.hxx:41 + vcl::graphic::Manager maSwapOutTimer + graphic::Manager maSwapOutTimer +vcl/inc/impfontcache.hxx:75 + ImplFontCache m_aBoundRectCache + 3000 +vcl/inc/printdlg.hxx:209 + vcl::PrintDialog maUpdatePreviewIdle + Print Dialog Update Preview Idle +vcl/inc/printdlg.hxx:211 + vcl::PrintDialog maUpdatePreviewNoCacheIdle + Print Dialog Update Preview (no cache) Idle +vcl/inc/qt5/Qt5Instance.hxx:67 + Qt5Instance m_aUpdateStyleTimer + vcl::qt5 m_aUpdateStyleTimer +vcl/inc/salprn.hxx:43 + SalPrinterQueueInfo mnStatus + 0 +vcl/inc/salprn.hxx:44 + SalPrinterQueueInfo mnJobs + 4294967295 +vcl/inc/salwtype.hxx:164 + SalWheelMouseEvent mbDeltaIsPixel + 0 +vcl/inc/svdata.hxx:316 + ImplSVNWFData mbMenuBarDockingAreaCommonBG + 0 +vcl/qa/cppunit/png/PngFilterTest.cxx:35 + PngFilterTest maDataUrl + /vcl/qa/cppunit/png/data/ +vcl/qa/cppunit/svm/svmtest.cxx:33 + SvmTest maDataUrl + /vcl/qa/cppunit/svm/data/ +vcl/source/bitmap/bitmap.cxx:159 + Bitmap::~Bitmap save + 0 +vcl/source/bitmap/dibtools.cxx:52 + (anonymous namespace)::CIEXYZ aXyzX + 0 +vcl/source/bitmap/dibtools.cxx:53 + (anonymous namespace)::CIEXYZ aXyzY + 0 +vcl/source/bitmap/dibtools.cxx:54 + (anonymous namespace)::CIEXYZ aXyzZ + 0 +vcl/source/bitmap/dibtools.cxx:107 + (anonymous namespace)::DIBV5Header nV5RedMask + 0 +vcl/source/bitmap/dibtools.cxx:108 + (anonymous namespace)::DIBV5Header nV5GreenMask + 0 +vcl/source/bitmap/dibtools.cxx:109 + (anonymous namespace)::DIBV5Header nV5BlueMask + 0 +vcl/source/bitmap/dibtools.cxx:110 + (anonymous namespace)::DIBV5Header nV5AlphaMask + 0 +vcl/source/bitmap/dibtools.cxx:113 + (anonymous namespace)::DIBV5Header nV5GammaRed + 0 +vcl/source/bitmap/dibtools.cxx:114 + (anonymous namespace)::DIBV5Header nV5GammaGreen + 0 +vcl/source/bitmap/dibtools.cxx:115 + (anonymous namespace)::DIBV5Header nV5GammaBlue + 0 +vcl/source/bitmap/dibtools.cxx:117 + (anonymous namespace)::DIBV5Header nV5ProfileData + 0 +vcl/source/bitmap/dibtools.cxx:118 + (anonymous namespace)::DIBV5Header nV5ProfileSize + 0 +vcl/source/bitmap/dibtools.cxx:119 + (anonymous namespace)::DIBV5Header nV5Reserved + 0 +vcl/source/control/imivctl.hxx:123 + SvxIconChoiceCtrl_Impl aAutoArrangeIdle + svtools contnr SvxIconChoiceCtrl_Impl AutoArrange +vcl/source/control/imivctl.hxx:124 + SvxIconChoiceCtrl_Impl aDocRectChangedIdle + svtools contnr SvxIconChoiceCtrl_Impl DocRectChanged +vcl/source/control/imivctl.hxx:125 + SvxIconChoiceCtrl_Impl aVisRectChangedIdle + svtools contnr SvxIconChoiceCtrl_Impl VisRectChanged +vcl/source/control/imivctl.hxx:126 + SvxIconChoiceCtrl_Impl aCallSelectHdlIdle + svtools contnr SvxIconChoiceCtrl_Impl CallSelectHdl +vcl/source/control/roadmapwizard.cxx:60 + vcl::RoadmapWizardImpl pRoadmap + 0 +vcl/source/filter/jpeg/transupp.h:128 + (anonymous) perfect + 0 +vcl/source/filter/jpeg/transupp.h:129 + (anonymous) trim + 0 +vcl/source/filter/jpeg/transupp.h:130 + (anonymous) force_grayscale + 0 +vcl/source/filter/jpeg/transupp.h:131 + (anonymous) crop + 0 +vcl/source/filter/jpeg/transupp.h:147 + (anonymous) crop_xoffset + 0 +vcl/source/filter/jpeg/transupp.h:149 + (anonymous) crop_yoffset + 0 +vcl/source/font/font.cxx:697 + (anonymous namespace)::WeightSearchEntry weight + 5 +vcl/source/fontsubset/ttcr.cxx:350 + vcl::(anonymous namespace)::tdata_post ptr + 0 +vcl/source/gdi/pdfwriter_impl.hxx:766 + vcl::PDFWriterImpl m_DocDigest + 0 +vcl/unx/gtk3/a11y/gtk3atkutil.cxx:629 + ooo_atk_util_ensure_event_listener bInited + 1 +vcl/unx/gtk3/gtk3gtkinst.cxx:16767 + (anonymous namespace)::ensure_intercept_drawing_area_accessibility bDone + 1 +vcl/unx/gtk3/gtk3gtkinst.cxx:16795 + (anonymous namespace)::ensure_disable_ctrl_page_up_down_bindings bDone + 1 +workdir/LexTarget/l10ntools/source/xrmlex.cxx:706 + /home/noel/libo2/workdir/LexTarget/l10ntools/source/xrmlex.cxx bText + 0 +writerfilter/source/dmapper/DomainMapper_Impl.hxx:159 + writerfilter::dmapper::FieldParagraph m_bRemove + 0 +writerfilter/source/dmapper/SettingsTable.cxx:271 + writerfilter::dmapper::SettingsTable_Impl m_pThemeFontLangProps + 3 +writerfilter/source/rtftok/rtfdocumentimpl.hxx:876 + writerfilter::rtftok::RTFDocumentImpl m_nNestedTRLeft + 0 +writerfilter/source/rtftok/rtfdocumentimpl.hxx:877 + writerfilter::rtftok::RTFDocumentImpl m_nTopLevelTRLeft + 0 +writerfilter/source/rtftok/rtfdocumentimpl.hxx:880 + writerfilter::rtftok::RTFDocumentImpl m_nNestedCurrentCellX + 0 +writerfilter/source/rtftok/rtftokenizer.hxx:60 + writerfilter::rtftok::RTFTokenizer s_bControlWordsInitialised + 1 +writerfilter/source/rtftok/rtftokenizer.hxx:63 + writerfilter::rtftok::RTFTokenizer s_bMathControlWordsSorted + 1 +xmloff/source/text/XMLIndexTemplateContext.hxx:56 + /home/noel/libo2/xmloff/source/text/XMLIndexTemplateContext.cxx aLevelNameTableMap + 0 diff --git a/compilerplugins/clang/staticaccess.cxx b/compilerplugins/clang/staticaccess.cxx new file mode 100644 index 000000000..46aa033f0 --- /dev/null +++ b/compilerplugins/clang/staticaccess.cxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include + +#include "plugin.hxx" + +namespace { + +bool isStatic(ValueDecl const * decl, bool * memberEnumerator) { + assert(memberEnumerator != nullptr); + // clang::MemberExpr::getMemberDecl is documented to return either a + // FieldDecl or a CXXMethodDecl, but can apparently also return a VarDecl + // (as C++ static data members are modeled by VarDecl, not FieldDecl) or an + // EnumConstantDecl (struct { enum {E}; } s; s.E;), see + // "Fix documentation of + // MemberExpr::getMemberDecl": + auto fd = dyn_cast(decl); + if (fd != nullptr) { + *memberEnumerator = false; + return false; + } + auto vd = dyn_cast(decl); + if (vd != nullptr) { + *memberEnumerator = false; + assert(vd->isStaticDataMember()); + return true; + } + auto md = dyn_cast(decl); + if (md != nullptr) { + *memberEnumerator = false; + return md->isStatic(); + } + assert(dyn_cast(decl) != nullptr); + *memberEnumerator = true; + return true; +} + +class StaticAccess: + public loplugin::FilteringPlugin +{ +public: + explicit StaticAccess(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitMemberExpr(MemberExpr const * expr); +}; + +bool StaticAccess::VisitMemberExpr(MemberExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto decl = expr->getMemberDecl(); + bool me; + if (!isStatic(decl, &me)) { + return true; + } + auto const loc = expr->getExprLoc(); + if (compiler.getSourceManager().isMacroBodyExpansion(loc)) { + auto const name = Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()); + if (name == "BEGIN_COM_MAP" || name == "DEFAULT_REFLECTION_HANDLER") { + // .../VC/Tools/MSVC/14.14.26428/atlmfc/include\atlcom.h(2226,10): note: expanded from + // macro 'BEGIN_COM_MAP' + // return this->InternalQueryInterface(this, _GetEntries(), iid, ppvObject); + // ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // .../VC/Tools/MSVC/14.14.26428/atlmfc/include\atlwin.h(2890,5): note: expanded from + // macro 'DEFAULT_REFLECTION_HANDLER' + // if(this->DefaultReflectionHandler(hWnd, uMsg, wParam, lParam, lResult)) + // ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + return true; + } + } + report( + DiagnosticsEngine::Warning, + ("accessing %select{static class member|member enumerator}0 through" + " class member access syntax, use a qualified name like '%1' instead"), + expr->getBeginLoc()) + << me << decl->getQualifiedNameAsString() << expr->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration staticaccess("staticaccess"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/staticconstfield.cxx b/compilerplugins/clang/staticconstfield.cxx new file mode 100644 index 000000000..74aad462f --- /dev/null +++ b/compilerplugins/clang/staticconstfield.cxx @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "plugin.hxx" +#include "check.hxx" +#include "compat.hxx" +#include +#include +#include +#include + +/** + Look for fields which are const, which can be made static const +*/ +namespace +{ +class StaticConstField : public loplugin::FilteringPlugin +{ +public: + explicit StaticConstField(loplugin::InstantiationData const& data) + : loplugin::FilteringPlugin(data) + { + } + + void run() override; + + bool TraverseConstructorInitializer(CXXCtorInitializer* init); + bool TraverseCXXConstructorDecl(CXXConstructorDecl* decl); + +private: + struct Data + { + std::vector inits; + std::string value; + }; + std::unordered_map m_potentials; + std::unordered_set m_excluded; + CXXConstructorDecl* m_currentConstructor = nullptr; +}; + +void StaticConstField::run() +{ + std::string fn = handler.getMainFileName().str(); + loplugin::normalizeDotDotInFilePath(fn); + + // unusual case where a user constructor sets a field to one value, and a copy constructor sets it to a different value + if (fn == SRCDIR "/sw/source/core/attr/hints.cxx") + return; + if (fn == SRCDIR "/oox/source/core/contexthandler2.cxx") + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + for (auto const& pair : m_potentials) + { + report(DiagnosticsEngine::Error, "const field can be static", pair.first->getLocation()) + << pair.first->getSourceRange(); + for (CXXCtorInitializer const* init : pair.second.inits) + if (pair.first->getLocation() != init->getSourceLocation()) + report(DiagnosticsEngine::Note, "init here", init->getSourceLocation()) + << init->getSourceRange(); + } +} + +bool StaticConstField::TraverseCXXConstructorDecl(CXXConstructorDecl* decl) +{ + auto prev = m_currentConstructor; + m_currentConstructor = decl; + bool ret = FilteringPlugin::TraverseCXXConstructorDecl(decl); + m_currentConstructor = prev; + return ret; +} + +bool StaticConstField::TraverseConstructorInitializer(CXXCtorInitializer* init) +{ + if (!init->getSourceLocation().isValid() || ignoreLocation(init->getSourceLocation())) + return true; + if (!init->getMember()) + return true; + if (!init->getInit()) + return true; + if (!m_currentConstructor || m_currentConstructor->isCopyOrMoveConstructor()) + return true; + if (!m_currentConstructor->getParent()->isCompleteDefinition()) + return true; + if (m_excluded.find(init->getMember()) != m_excluded.end()) + return true; + auto type = init->getMember()->getType(); + auto tc = loplugin::TypeCheck(type); + if (!tc.Const()) + return true; + + bool found = false; + std::string value; + auto const initexpr = init->getInit()->IgnoreImplicit(); + if (tc.Const().Class("OUString").Namespace("rtl").GlobalNamespace() + || tc.Const().Class("OString").Namespace("rtl").GlobalNamespace()) + { + if (auto constructExpr = dyn_cast(initexpr)) + { + if (constructExpr->getNumArgs() >= 1 + && isa(constructExpr->getArg(0))) + { + value = dyn_cast(constructExpr->getArg(0))->getString().str(); + found = true; + } + } + } + else if (type->isFloatingType()) + { + APFloat x1(0.0f); + if (initexpr->EvaluateAsFloat(x1, compiler.getASTContext())) + { + std::string s; + llvm::raw_string_ostream os(s); + x1.print(os); + value = os.str(); + found = true; + } + } + // ignore this, it seems to trigger an infinite recursion + else if (isa(initexpr)) + ; + // ignore this, calling EvaluateAsInt on it will crash clang + else if (initexpr->isValueDependent()) + ; + else + { + APSInt x1; + if (compat::EvaluateAsInt(initexpr, x1, compiler.getASTContext())) + { + value = compat::toString(x1, 10); + found = true; + } + } + + if (!found) + { + m_potentials.erase(init->getMember()); + m_excluded.insert(init->getMember()); + return true; + } + + auto findIt = m_potentials.find(init->getMember()); + if (findIt != m_potentials.end()) + { + if (findIt->second.value != value) + { + m_potentials.erase(findIt); + m_excluded.insert(init->getMember()); + } + else + findIt->second.inits.push_back(init); + } + else + { + Data& data = m_potentials[init->getMember()]; + data.inits.push_back(init); + data.value = value; + } + + return true; +} + +loplugin::Plugin::Registration X("staticconstfield", true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/staticdynamic.cxx b/compilerplugins/clang/staticdynamic.cxx new file mode 100644 index 000000000..6dc351546 --- /dev/null +++ b/compilerplugins/clang/staticdynamic.cxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include +#include + +#include "config_clang.h" + +#include "check.hxx" +#include "plugin.hxx" + +namespace +{ +class StaticDynamic : public loplugin::FilteringPlugin +{ +public: + explicit StaticDynamic(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + void postRun() override {} + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXDynamicCastExpr(CXXDynamicCastExpr const*); + bool VisitCXXStaticCastExpr(CXXStaticCastExpr const*); + bool PreTraverseCompoundStmt(CompoundStmt*); + bool PostTraverseCompoundStmt(CompoundStmt*, bool); + bool TraverseCompoundStmt(CompoundStmt*); + +private: + // the key is the pair of VarDecl and the type being cast to. + struct BlockState + { + std::map, SourceLocation> staticCastVars; + std::map, SourceLocation> dynamicCastVars; + }; + // only maintain state inside a single basic block, we're not trying to analyse + // cross-block interactions. + std::vector blockStack; + BlockState blockState; +}; + +bool StaticDynamic::PreTraverseCompoundStmt(CompoundStmt*) +{ + blockStack.push_back(std::move(blockState)); + return true; +} + +bool StaticDynamic::PostTraverseCompoundStmt(CompoundStmt*, bool) +{ + blockState = std::move(blockStack.back()); + blockStack.pop_back(); + return true; +} + +bool StaticDynamic::TraverseCompoundStmt(CompoundStmt* compoundStmt) +{ + bool ret = true; + if (PreTraverseCompoundStmt(compoundStmt)) + { + ret = FilteringPlugin::TraverseCompoundStmt(compoundStmt); + PostTraverseCompoundStmt(compoundStmt, ret); + } + return ret; +} + +const clang::Type* strip(QualType qt) +{ + const clang::Type* varType = qt->getUnqualifiedDesugaredType(); + if (varType->isPointerType()) + varType = varType->getPointeeType()->getUnqualifiedDesugaredType(); + if (varType->isReferenceType()) + varType = varType->getAs() + ->getPointeeType() + ->getUnqualifiedDesugaredType(); + return varType; +} + +bool StaticDynamic::VisitCXXStaticCastExpr(CXXStaticCastExpr const* staticCastExpr) +{ + if (ignoreLocation(staticCastExpr)) + return true; + auto subExprDecl = dyn_cast(staticCastExpr->getSubExpr()->IgnoreParenImpCasts()); + if (!subExprDecl) + return true; + auto varDecl = dyn_cast_or_null(subExprDecl->getDecl()); + if (!varDecl) + return true; + auto varType = strip(staticCastExpr->getType()); + auto it = blockState.dynamicCastVars.find({ varDecl, varType }); + if (it != blockState.dynamicCastVars.end()) + { + StringRef fn = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(staticCastExpr->getBeginLoc())); + // loop + if (loplugin::isSamePathname(fn, SRCDIR "/basctl/source/basicide/basobj3.cxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/doc/swserv.cxx")) + return true; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/text/txtfly.cxx")) + return true; + + report(DiagnosticsEngine::Warning, "static_cast after dynamic_cast", + staticCastExpr->getBeginLoc()) + << staticCastExpr->getSourceRange(); + report(DiagnosticsEngine::Note, "dynamic_cast here", it->second); + return true; + } + blockState.staticCastVars.insert({ { varDecl, varType }, staticCastExpr->getBeginLoc() }); + return true; +} + +bool StaticDynamic::VisitCXXDynamicCastExpr(CXXDynamicCastExpr const* dynamicCastExpr) +{ + if (ignoreLocation(dynamicCastExpr)) + return true; + + auto subExprDecl = dyn_cast(dynamicCastExpr->getSubExpr()->IgnoreParenImpCasts()); + if (!subExprDecl) + return true; + auto varDecl = dyn_cast_or_null(subExprDecl->getDecl()); + if (!varDecl) + return true; + auto varType = strip(dynamicCastExpr->getTypeAsWritten()); + auto it = blockState.staticCastVars.find({ varDecl, varType }); + if (it != blockState.staticCastVars.end()) + { + report(DiagnosticsEngine::Warning, "dynamic_cast after static_cast", + dynamicCastExpr->getBeginLoc()) + << dynamicCastExpr->getSourceRange(); + report(DiagnosticsEngine::Note, "static_cast here", it->second); + return true; + } + auto loc = dynamicCastExpr->getBeginLoc(); + if (compiler.getSourceManager().isMacroArgExpansion(loc) + && (Lexer::getImmediateMacroNameForDiagnostics(loc, compiler.getSourceManager(), + compiler.getLangOpts()) + == "assert")) + { + return true; + } + blockState.dynamicCastVars.insert({ { varDecl, varType }, dynamicCastExpr->getBeginLoc() }); + return true; +} + +loplugin::Plugin::Registration staticdynamic("staticdynamic"); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/staticmethods.cxx b/compilerplugins/clang/staticmethods.cxx new file mode 100644 index 000000000..4651a4a3d --- /dev/null +++ b/compilerplugins/clang/staticmethods.cxx @@ -0,0 +1,244 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "clang/AST/Attr.h" + +#include "config_clang.h" + +#include "check.hxx" +#include "plugin.hxx" + +/* + Look for member functions that can be static +*/ +namespace { + +class StaticMethods: + public loplugin::FilteringPlugin +{ +private: + bool bVisitedThis; +public: + explicit StaticMethods(loplugin::InstantiationData const & data): FilteringPlugin(data), bVisitedThis(false) {} + + void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool TraverseCXXMethodDecl(const CXXMethodDecl * decl); + + bool VisitCXXThisExpr(const CXXThisExpr *) { bVisitedThis = true; return true; } + // these two indicate that we hit something that makes our analysis unreliable + bool VisitUnresolvedMemberExpr(const UnresolvedMemberExpr *) { bVisitedThis = true; return true; } + bool VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *) { bVisitedThis = true; return true; } +private: + StringRef getFilename(SourceLocation loc); +}; + +bool BaseCheckNotTestFixtureSubclass(const CXXRecordDecl *BaseDefinition) { + if (loplugin::TypeCheck(BaseDefinition).Class("TestFixture").Namespace("CppUnit").GlobalNamespace()) { + return false; + } + return true; +} + +bool isDerivedFromTestFixture(const CXXRecordDecl *decl) { + if (!decl->hasDefinition()) + return false; + if (// not sure what hasAnyDependentBases() does, + // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1 + !decl->hasAnyDependentBases() && + !decl->forallBases(BaseCheckNotTestFixtureSubclass)) { + return true; + } + return false; +} + +StringRef StaticMethods::getFilename(SourceLocation loc) +{ + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(loc); + return getFilenameOfLocation(spellingLocation); +} + +bool startsWith(const std::string& rStr, const char* pSubStr) { + return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; +} + +bool StaticMethods::TraverseCXXMethodDecl(const CXXMethodDecl * pCXXMethodDecl) { + if (ignoreLocation(pCXXMethodDecl)) { + return true; + } + if (!pCXXMethodDecl->isInstance() || pCXXMethodDecl->isVirtual() || !pCXXMethodDecl->doesThisDeclarationHaveABody() || pCXXMethodDecl->isLateTemplateParsed()) { + return true; + } + if (pCXXMethodDecl->getOverloadedOperator() != OverloadedOperatorKind::OO_None || pCXXMethodDecl->hasAttr()) { + return true; + } + if (isa(pCXXMethodDecl) || isa(pCXXMethodDecl) || isa(pCXXMethodDecl)) { + return true; + } + if (isInUnoIncludeFile(pCXXMethodDecl)) { + return true; + } + if (pCXXMethodDecl->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return true; + + // the CppUnit stuff uses macros and methods that can't be changed + if (isDerivedFromTestFixture(pCXXMethodDecl->getParent())) { + return true; + } + // don't mess with the backwards compatibility stuff + if (loplugin::isSamePathname(getFilename(pCXXMethodDecl->getBeginLoc()), SRCDIR "/cppuhelper/source/compat.cxx")) { + return true; + } + // the DDE has a dummy implementation on Linux and a real one on Windows + auto aFilename = getFilename(pCXXMethodDecl->getCanonicalDecl()->getBeginLoc()); + if (loplugin::isSamePathname(aFilename, SRCDIR "/include/svl/svdde.hxx")) { + return true; + } + auto cdc = loplugin::DeclCheck(pCXXMethodDecl->getParent()); + // special case having something to do with static initialisation + // sal/osl/all/utility.cxx + if (cdc.Class("OGlobalTimer").Namespace("osl").GlobalNamespace()) { + return true; + } + // leave the TopLeft() method alone for consistency with the other "corner" methods + if (cdc.Class("BitmapInfoAccess").GlobalNamespace()) { + return true; + } + // the unotools and svl config code stuff is doing weird stuff with a reference-counted statically allocated pImpl class + if (loplugin::hasPathnamePrefix(aFilename, SRCDIR "/include/unotools/")) { + return true; + } + if (loplugin::hasPathnamePrefix(aFilename, SRCDIR "/include/svl/")) { + return true; + } + if (loplugin::hasPathnamePrefix(aFilename, SRCDIR "/include/framework/") || loplugin::hasPathnamePrefix(aFilename, SRCDIR "/framework/")) { + return true; + } + // there is some odd stuff happening here I don't fully understand, leave it for now + if (loplugin::hasPathnamePrefix(aFilename, SRCDIR "/include/canvas/") || loplugin::hasPathnamePrefix(aFilename, SRCDIR "/canvas/")) { + return true; + } + // classes that have static data and some kind of weird reference-counting trick in its constructor + if (cdc.Class("LinguOptions").GlobalNamespace() + || (cdc.Class("EditableExtendedColorConfig").Namespace("svtools") + .GlobalNamespace()) + || (cdc.Class("ExtendedColorConfig").Namespace("svtools") + .GlobalNamespace()) + || cdc.Class("SvtMiscOptions").GlobalNamespace() + || cdc.Class("SvtAccessibilityOptions").GlobalNamespace() + || cdc.Class("ColorConfig").Namespace("svtools").GlobalNamespace() + || cdc.Class("SvtOptionsDrawinglayer").GlobalNamespace() + || cdc.Class("SvtMenuOptions").GlobalNamespace() + || cdc.Class("SvtToolPanelOptions").GlobalNamespace() + || cdc.Class("SvtSlideSorterBarOptions").GlobalNamespace() + || (cdc.Class("SharedResources").Namespace("connectivity") + .GlobalNamespace()) + || (cdc.Class("OParseContextClient").Namespace("svxform") + .GlobalNamespace()) + || cdc.Class("OLimitedFormats").Namespace("frm").GlobalNamespace()) + { + return true; + } + auto fdc = loplugin::DeclCheck(pCXXMethodDecl); + // only empty on Linux, not on windows + if ((fdc.Function("GetVisualRepresentationInNativeFormat_Impl") + .Class("OleEmbeddedObject").GlobalNamespace()) + || (fdc.Function("GetRidOfComponent").Class("OleEmbeddedObject") + .GlobalNamespace()) + || cdc.Class("SbxDecimal").GlobalNamespace() + || fdc.Function("Call").Class("SbiDllMgr").GlobalNamespace() + || fdc.Function("FreeDll").Class("SbiDllMgr").GlobalNamespace() + || (fdc.Function("InitializeDde").Class("SfxApplication") + .GlobalNamespace()) + || (fdc.Function("RemoveDdeTopic").Class("SfxApplication") + .GlobalNamespace()) + || (fdc.Function("UpdateSkiaStatus").Class("OfaViewTabPage") + .GlobalNamespace()) + || (fdc.Function("ReleaseData").Class("ScannerManager") + .GlobalNamespace())) + { + return true; + } + // debugging stuff + if (fdc.Function("dump").Class("InternalData").Namespace("chart") + .GlobalNamespace()) + { + return true; + } + // used in a function-pointer-table + if ((cdc.Class("SbiRuntime").GlobalNamespace() + && startsWith(pCXXMethodDecl->getNameAsString(), "Step")) + || (cdc.Class("OoxFormulaParserImpl").AnonymousNamespace().Namespace("xls").Namespace("oox") + .GlobalNamespace()) + || cdc.Class("SwTableFormula").GlobalNamespace() + || (cdc.Class("BiffFormulaParserImpl").Namespace("xls").Namespace("oox") + .GlobalNamespace()) + || (fdc.Function("Read_F_Shape").Class("SwWW8ImplReader") + .GlobalNamespace()) + || (fdc.Function("Read_Majority").Class("SwWW8ImplReader") + .GlobalNamespace()) + || fdc.Function("Ignore").Class("SwWrtShell").GlobalNamespace()) + { + return true; + } + // have no idea why this can't be static, but 'make check' fails with it so... + if (fdc.Function("resolveRelationshipsOfTypeFromOfficeDoc").Class("Shape") + .Namespace("drawingml").Namespace("oox").GlobalNamespace()) + { + return true; + } + // template magic + if (fdc.Function("getValue").Class("ColumnBatch").GlobalNamespace() + || cdc.Class("TitleImpl").GlobalNamespace() + || (fdc.Function("getDefaultPropertyName").Class("DefaultReturnHelper") + .Namespace("vba").Namespace("ooo").GlobalNamespace())) + { + return true; + } + // depends on config options + if ((fdc.Function("autoInstallFontLangSupport").Class("PrintFontManager") + .Namespace("psp").GlobalNamespace()) + || fdc.Function("AllocateFrame").Class("GtkSalFrame").GlobalNamespace() + || (fdc.Function("TriggerPaintEvent").Class("GtkSalFrame") + .GlobalNamespace())) + { + return true; + } + + bVisitedThis = false; + TraverseStmt(pCXXMethodDecl->getBody()); + if (bVisitedThis) { + return true; + } + + if (containsPreprocessingConditionalInclusion((pCXXMethodDecl->getSourceRange()))) { + return true; + } + + report( + DiagnosticsEngine::Warning, + "this member function can be declared static", + pCXXMethodDecl->getCanonicalDecl()->getLocation()) + << pCXXMethodDecl->getCanonicalDecl()->getSourceRange(); + FunctionDecl const * def; + if (pCXXMethodDecl->isDefined(def) + && def != pCXXMethodDecl->getCanonicalDecl()) + { + report(DiagnosticsEngine::Note, "defined here:", def->getLocation()) + << def->getSourceRange(); + } + return true; +} + +loplugin::Plugin::Registration X("staticmethods"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/staticvar.cxx b/compilerplugins/clang/staticvar.cxx new file mode 100644 index 000000000..21cbd0f08 --- /dev/null +++ b/compilerplugins/clang/staticvar.cxx @@ -0,0 +1,213 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +// Look for variables that either +// (a) could be statically initialised, without runtime code, and warn +// (b) variables that are statically declared, but require runtime initialisation, and warn +// +// e.g. +// static const OUString[] XXX { "xxx" }; +// requires runtime initialisation, so should rather be declared as OUStringLiteral +// and +// static int[] XXX { 1,2 }; +// can be declared const since it does not require runtime initialisation. + +namespace +{ +class StaticVar : public loplugin::FilteringPlugin +{ +public: + explicit StaticVar(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + + if ( + // uses icu::UnicodeString + fn == SRCDIR "/l10ntools/source/xmlparse.cxx" + // contains mutable state + || fn == SRCDIR "/sal/osl/unx/signal.cxx" + || fn == SRCDIR "/sal/qa/rtl/digest/rtl_digest.cxx" + || fn == SRCDIR "/sal/qa/rtl/strings/test_oustring_endswith.cxx" + || fn == SRCDIR "/sal/qa/rtl/strings/test_oustring_convert.cxx" + || fn == SRCDIR "/svl/qa/unit/items/test_itempool.cxx" + // contains mutable state + || fn == SRCDIR "/vcl/unx/generic/dtrans/X11_selection.cxx" + || fn == SRCDIR "/sax/qa/cppunit/xmlimport.cxx" + || fn == SRCDIR "/pyuno/source/module/pyuno.cxx" + || fn == SRCDIR "/pyuno/source/module/pyuno_module.cxx" + || fn == SRCDIR "/pyuno/source/module/pyuno_struct.cxx" + // TODO for this one we need a static OUString + || fn == SRCDIR "/xmloff/source/core/xmltoken.cxx" + // mutable + || fn == SRCDIR "/basic/source/runtime/stdobj.cxx" + // TODO this needs more extensive cleanup + || fn == SRCDIR "/connectivity/source/drivers/postgresql/pq_statics.cxx" + // mutable + || fn == SRCDIR "/hwpfilter/source/hwpreader.cxx" + // mutable + || fn == SRCDIR "/sw/source/filter/basflt/fltini.cxx" + // mutable + || fn == SRCDIR "/sw/source/uibase/docvw/srcedtw.cxx" + // mutable + || fn == SRCDIR "/forms/source/misc/limitedformats.cxx" + // aHTMLOptionTab is ordered by useful grouping, so let it sort at runtime + || fn == SRCDIR "/svtools/source/svhtml/htmlkywd.cxx" + // TODO sorting some of these tables will be a lot of work... + || fn == SRCDIR "/sw/source/filter/ww8/ww8par6.cxx" + // this only triggers on older versions of clang, not sure why + // in any case, it is actually about the array in vcl/inc/units.hrc, which we can't change + || fn == SRCDIR "/vcl/source/app/svdata.cxx" + // I tried doing this, but got very weird unit test failures, apparently sorting this table + // disturbs some code elsewhere + || fn == SRCDIR "/svx/source/unodraw/unoprov.cxx" + // aRTFTokenTab is ordered by useful grouping, so let it sort at runtime + || fn == SRCDIR "/svtools/source/svrtf/rtfkeywd.cxx") + return; + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitVarDecl(VarDecl const*); +}; + +static bool containsNonLiteral(Expr const* expr) +{ + expr = expr->IgnoreImplicit(); + if (auto initList = dyn_cast(expr)) + { + for (unsigned i = 0; i < initList->getNumInits(); ++i) + if (containsNonLiteral(initList->getInit(i))) + return true; + } + else if (auto constructExpr = dyn_cast(expr)) + { + for (Expr const* arg : constructExpr->arguments()) + if (containsNonLiteral(arg)) + return true; + } + else if (isa(expr)) + return true; + else if (auto declRefExpr = dyn_cast(expr)) + { + auto varDecl = dyn_cast_or_null(declRefExpr->getDecl()); + return varDecl && varDecl->isLocalVarDeclOrParm(); + } + else if (isa(expr)) + return true; + else if (auto castExpr = dyn_cast(expr)) + return containsNonLiteral(castExpr->getSubExpr()); + else if (auto unaryOp = dyn_cast(expr)) + return containsNonLiteral(unaryOp->getSubExpr()); + + return false; +} + +bool StaticVar::VisitVarDecl(VarDecl const* varDecl) +{ + if (ignoreLocation(varDecl)) + return true; + if (!varDecl->hasInit()) + return true; + auto initList = dyn_cast_or_null(varDecl->getInit()); + if (!initList) + return true; + if (varDecl->isExceptionVariable() || isa(varDecl)) + return true; + if (!varDecl->getType()->isArrayType()) + return true; + auto elementType = varDecl->getType()->getBaseElementTypeUnsafe(); + if (!elementType->isRecordType()) + return true; + auto elementRecordDecl + = dyn_cast_or_null(elementType->getAs()->getDecl()); + if (!elementRecordDecl) + return true; + if (containsNonLiteral(initList)) + return true; + + if (elementRecordDecl->hasTrivialDestructor()) + { + if (varDecl->isLocalVarDecl()) + { + if (varDecl->getStorageDuration() == SD_Static && varDecl->getType().isConstQualified()) + return true; + } + else + { + if (varDecl->getType().isConstQualified()) + return true; + } + + // TODO cannot figure out how to make the loplugin::TypeCheck stuff match this + // std::string typeName = varDecl->getType().getAsString(); + // if (typeName == "std::va_list" || typeName == "va_list") + // return true; + + auto const tcElement = loplugin::TypeCheck(elementRecordDecl); + if (tcElement.Struct("ContextID_Index_Pair").GlobalNamespace()) + return true; + if (tcElement.Class("SfxSlot").GlobalNamespace()) + return true; + + if (varDecl->isLocalVarDecl()) + report(DiagnosticsEngine::Warning, "var should be static const, or allowlisted", + varDecl->getLocation()) + << varDecl->getSourceRange(); + else + report(DiagnosticsEngine::Warning, "var should be const, or allowlisted", + varDecl->getLocation()) + << varDecl->getSourceRange(); + } + else + { + if (varDecl->isLocalVarDecl()) + { + if (varDecl->getStorageDuration() != SD_Static + || !varDecl->getType().isConstQualified()) + return true; + } + else + { + if (!varDecl->getType().isConstQualified()) + return true; + } + + if (varDecl->isLocalVarDecl()) + report(DiagnosticsEngine::Warning, "static const var requires runtime initialization?", + varDecl->getLocation()) + << varDecl->getSourceRange(); + else + report(DiagnosticsEngine::Warning, "static var requires runtime initialization?", + varDecl->getLocation()) + << varDecl->getSourceRange(); + } + return true; +} + +loplugin::Plugin::Registration X("staticvar", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/stdfunction.cxx b/compilerplugins/clang/stdfunction.cxx new file mode 100644 index 000000000..43c61a047 --- /dev/null +++ b/compilerplugins/clang/stdfunction.cxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "plugin.hxx" + +namespace +{ +class StdFunction final : public loplugin::FilteringPlugin +{ +public: + explicit StdFunction(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool VisitFunctionDecl(FunctionDecl const* decl) + { + if (ignoreLocation(decl)) + { + return true; + } + if (!loplugin::ContextCheck(decl->getDeclContext()).StdOrNestedNamespace()) + { + return true; + } + report(DiagnosticsEngine::Warning, + ("Do not declare a %select{function|function template|member function template" + " specialization|function template specialization}0 in namespace 'std'"), + decl->getLocation()) + << decl->getTemplatedKind() << decl->getSourceRange(); + return true; + } + +private: + void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } +}; + +static loplugin::Plugin::Registration X("stdfunction"); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/store/README b/compilerplugins/clang/store/README new file mode 100644 index 000000000..b56254412 --- /dev/null +++ b/compilerplugins/clang/store/README @@ -0,0 +1,3 @@ +This plugin actions are not used. They are still kept in case they would be useful again +(they can be activated again by simply moving them back in the clang/ source directory) +or simply as a reference when writing new plugins. diff --git a/compilerplugins/clang/store/badvectorinit.cxx b/compilerplugins/clang/store/badvectorinit.cxx new file mode 100644 index 000000000..4ab086d9e --- /dev/null +++ b/compilerplugins/clang/store/badvectorinit.cxx @@ -0,0 +1,214 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include "plugin.hxx" + +/** + +Comments from Bjoern Michaelsen: + +Killing the 1-argument vector fill constructor: + + std::vector< basebmp::Color > aDevPal(2); + +in general is probably a Good Thing(tm). It can just be too misleading. +Requiring at least the explicit two-value fill constructor for the rare cases where +someone wants a filled vector isn't too much to ask and less prone to +misunderstandings: + + std::vector< basebmp::Color > aDevPal(2, basebmp::Color(0,0,0)); + +Although that _still_ might be misleading[1], so turning all those into the +somewhat longer, but more explicit: + + std::vector< basebmp::Color > aDevPal; + aDevPal.reserve(2); + aDevPal.push_back(...); + ... + +> So I suppose the check would be for a size reservation on a vector +> followed by push_back - rather than some array indexing - does that make +> sense ? or did I go crazy ;-) + +Yes, in general you want neither of the above forms. Preferably instead of +e.g.: + + std::vector< basebmp::Color > aDevPal(2); + aDevPal[0] = basebmp::Color( 0, 0, 0 ); + aDevPal[1] = basebmp::Color( 0xff, 0xff, 0xff ); + +you would -- if possible -- simply: + + std::vector< basebmp::Color > aDevPal{ + basebmp::Color( 0, 0, 0 ), + basebmp::Color( 0xff, 0xff, 0xff ) }; + +and only for complex cases, where you do not have the elements statically +available, something like: + + std::vector< foo > vFoos; + vFoos.reserve(vInput.size()); + std::transform(std::back_inserter(vFoos), + vInput.begin(), + vInput.end(), + [] (decltype(vInput)::value_type aInputValue) { return do_something(aInputValue); }); + +see also: +https://skyfromme.wordpress.com/2015/03/02/50-ways-to-fill-your-vector/ +https://skyfromme.wordpress.com/2015/03/12/following-the-white-rabbit/ +(tl;dr: Use initializer lists to fill vectors when possible). + +Best, + +Bjoern + +[1] Well, except that: + std::vector(3, 0) + is doing something different from: + std::vector{3, 0} + just to make things more interesting. But hey, that's C++ for you. + But that wart exists for the 1-arg ctor too -- yet another reason to kill that. +*/ + +namespace { + + +class BadVectorInit: + public loplugin::FilteringPlugin +{ +public: + explicit BadVectorInit(InstantiationData const & data): FilteringPlugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXConstructExpr(const CXXConstructExpr* ); + bool TraverseFunctionDecl(FunctionDecl* ); + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr* ); +private: + StringRef getFilename(SourceLocation loc); + std::set suspectSet; +}; + +bool BadVectorInit::TraverseFunctionDecl(FunctionDecl* decl) +{ + bool ret = RecursiveASTVisitor::TraverseFunctionDecl(decl); + suspectSet.clear(); + return ret; +} + +StringRef BadVectorInit::getFilename(SourceLocation loc) +{ + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(loc); + StringRef name { getFilenameOfLocation(spellingLocation) }; + return name; +} + +bool BadVectorInit::VisitCXXMemberCallExpr(const CXXMemberCallExpr* expr) +{ + if (suspectSet.empty() || ignoreLocation( expr )) + return true; + + // need to exclude some false positives + StringRef aFileName = getFilename(expr->getLocStart()); + if (aFileName == SRCDIR "/framework/source/services/autorecovery.cxx" + || aFileName == SRCDIR "/vcl/source/opengl/OpenGLHelper.cxx" + || aFileName == SRCDIR "/vcl/source/gdi/gdimtf.cxx" + ) + { + return true; + } + + const FunctionDecl* functionDecl = expr->getDirectCallee(); + if (!functionDecl) + return true; + if (functionDecl->getNameAsString().find("push_back") == string::npos) + return true; + const DeclRefExpr* declExpr = dyn_cast(expr->getImplicitObjectArgument()); + if (!declExpr) + return true; + const VarDecl* varDecl = dyn_cast(declExpr->getDecl()); + if (!varDecl) + return true; + varDecl = varDecl->getCanonicalDecl(); + if (suspectSet.find(varDecl) == suspectSet.end()) + return true; + report( + DiagnosticsEngine::Warning, + "calling push_back after using sized constructor", + expr->getLocStart()) + << expr->getSourceRange(); + report( + DiagnosticsEngine::Note, + "on this var", + varDecl->getLocStart()) + << varDecl->getSourceRange(); + + return true; +} + +bool BadVectorInit::VisitCXXConstructExpr(const CXXConstructExpr* expr) +{ + if (ignoreLocation( expr )) + return true; + + const CXXConstructorDecl *consDecl = expr->getConstructor(); + consDecl = consDecl->getCanonicalDecl(); + + // The default constructor can potentially have a parameter, e.g. + // in glibcxx-debug the default constructor is: + // explicit vector(const _Allocator& __a = _Allocator()) + if (consDecl->param_size() == 0 || consDecl->isDefaultConstructor()) + return true; + + std::string aParentName = consDecl->getParent()->getQualifiedNameAsString(); + if (aParentName.find("vector") == string::npos && aParentName.find("deque") == string::npos) + return true; + + // ignore the copy/move constructors, and those taking an initializer_list + // etc.: + if (consDecl->isCopyConstructor() || consDecl->isMoveConstructor()) + return true; + const ParmVarDecl* pParam = consDecl->getParamDecl(0); + std::string aParam1 = pParam->getOriginalType().getAsString(); + if (aParam1.find("initializer_list") != string::npos + || aParam1.find("iterator") != string::npos) + return true; + + // found a call to the 1-arg vector constructor, now look for the VarDecl it belongs to + + const Stmt* parent = expr; + do { + parent = parentStmt(parent); + if (!parent) break; + if (isa(parent)) + { + const DeclStmt* declStmt = dyn_cast(parent); + const Decl* decl = declStmt->getSingleDecl(); + if (decl && isa(decl)) + suspectSet.insert(dyn_cast(decl)->getCanonicalDecl()); + break; + } + } while (true); + + return true; +} + +loplugin::Plugin::Registration< BadVectorInit > X("badvectorinit", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/bodynotinblock.cxx b/compilerplugins/clang/store/bodynotinblock.cxx new file mode 100644 index 000000000..ca4f90499 --- /dev/null +++ b/compilerplugins/clang/store/bodynotinblock.cxx @@ -0,0 +1,147 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "bodynotinblock.hxx" + +namespace loplugin +{ + +/* +This is a compile check. + +Check for two statements that are both indented to look like a body of if/while/for +but are not inside a compound statement and thus the second one is unrelated. + +For example: + + if( a != 0 ) + b = 2; + c = 3; + +Here either both statements should be inside {} or the second statement in indented wrong. +*/ + +BodyNotInBlock::BodyNotInBlock( const InstantiationData& data ) + : Plugin( data ) + { + } + +void BodyNotInBlock::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +bool BodyNotInBlock::VisitIfStmt( const IfStmt* stmt ) + { + if( ignoreLocation( stmt )) + return true; + checkBody( stmt->getThen(), stmt->getIfLoc(), 0, stmt->getElse() != NULL ); + checkBody( stmt->getElse(), stmt->getElseLoc(), 0 ); + return true; + } + +bool BodyNotInBlock::VisitWhileStmt( const WhileStmt* stmt ) + { + if( ignoreLocation( stmt )) + return true; + checkBody( stmt->getBody(), stmt->getWhileLoc(), 1 ); + return true; + } + +bool BodyNotInBlock::VisitForStmt( const ForStmt* stmt ) + { + if( ignoreLocation( stmt )) + return true; + checkBody( stmt->getBody(), stmt->getForLoc(), 2 ); + return true; + } + +bool BodyNotInBlock::VisitCXXForRangeStmt( const CXXForRangeStmt* stmt ) + { + if( ignoreLocation( stmt )) + return true; + checkBody( stmt->getBody(), stmt->getForLoc(), 2 ); + return true; + } + +void BodyNotInBlock::checkBody( const Stmt* body, SourceLocation stmtLocation, int stmtType, bool dontGoUp ) + { + if( body == NULL ) + return; + // TODO: If the if/else/while/for comes from a macro expansion, ignore it completely for + // now. The code below could assume everything is in the same place (and thus also column) + // and give a false warning. Moreover some macros are rather loosely written and would + // result in poor formatting. To be evaluated later, maybe this could be handled + // including macro expansion. + if( stmtLocation.isMacroID()) + return; + if( dyn_cast< CompoundStmt >( body )) + return; // if body is a compound statement, then it is in {} + const Stmt* previousParent = parentStmt( body ); // Here the statement itself. + // Find the next statement (in source position) after 'body'. + for(;;) + { + const Stmt* parent = parentStmt( previousParent ); + if( parent == NULL ) + break; + for( ConstStmtIterator it = parent->child_begin(); + it != parent->child_end(); + ) + { + if( *it == previousParent ) // found grand(grand...)parent + { + // get next statement after our (grand...)parent + ++it; + while( it != parent->child_end() && *it == NULL ) + ++it; // skip empty ones (missing 'else' bodies for example) + if( it != parent->child_end()) + { + bool invalid1, invalid2; + unsigned bodyColumn = compiler.getSourceManager() + .getPresumedColumnNumber( body->getLocStart(), &invalid1 ); + unsigned nextStatementColumn = compiler.getSourceManager() + .getPresumedColumnNumber( (*it)->getLocStart(), &invalid2 ); + if( invalid1 || invalid2 ) + return; + if( bodyColumn == nextStatementColumn ) + { + report( DiagnosticsEngine::Warning, + "statement aligned as second statement in %select{if|while|for}0 body but not in a statement block", + (*it)->getLocStart()) << stmtType; + report( DiagnosticsEngine::Note, + "%select{if|while|for}0 body statement is here", + body->getLocStart()) << stmtType; + } + return; + } + // else we need to go higher to find the next statement + } + else + ++it; + } + // If going up would mean leaving a {} block, stop, because the } should + // make it visible the two statements are not in the same body. + if( dyn_cast< CompoundStmt >( parent )) + return; + // If the body to be checked is a body of an if statement that has also + // an else part, don't go up, the else is after the body and should make + // it clear the body does not continue there. + if( dontGoUp ) + return; + previousParent = parent; + } + } + +static Plugin::Registration< BodyNotInBlock > X( "bodynotinblock" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/bodynotinblock.hxx b/compilerplugins/clang/store/bodynotinblock.hxx new file mode 100644 index 000000000..d74a4fbc1 --- /dev/null +++ b/compilerplugins/clang/store/bodynotinblock.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include "plugin.hxx" + +namespace loplugin +{ + +class BodyNotInBlock + : public loplugin::FilteringPlugin + { + public: + explicit BodyNotInBlock( const InstantiationData& data ); + virtual void run() override; + bool VisitIfStmt( const IfStmt* stmt ); + bool VisitWhileStmt( const WhileStmt* stmt ); + bool VisitForStmt( const ForStmt* stmt ); + bool VisitCXXForRangeStmt( const CXXForRangeStmt* stmt ); + private: + void checkBody( const Stmt* body, SourceLocation stmtLocation, int stmtType, bool dontGoUp = false ); + }; + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/cascadingassignop.cxx b/compilerplugins/clang/store/cascadingassignop.cxx new file mode 100644 index 000000000..a1098ee06 --- /dev/null +++ b/compilerplugins/clang/store/cascadingassignop.cxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "cascadingassignop.hxx" + +/* +This is a compile check. + +It checks for complex statements with conditional operators in conditional +operators, which are error prone, e.g. + Thing foo = IsBar() ? ( IsBaz() ? b1 : b2 ) : b3; + +However, it finds 556 cases in sw/source alone, thus likely needs some more +restricting, e.g. by checking for multiline conditional operator statements or +a certain length in characters (but that needs the Context/SourceManager, which +I haven't played with yet). +*/ + +// the value is rather arbitrary, but code above this number of stmts begins to +// be smelly +static const int stmtlimit = 20; + +namespace loplugin +{ + +struct WalkCounter +{ + int stmtcount; + bool cascading; + bool conditionals; +}; + +// Ctor, nothing special, pass the argument(s). +CascadingAssignOp::CascadingAssignOp( const InstantiationData& data ) + : FilteringPlugin( data ) +{ +} + +// Perform the actual action. +void CascadingAssignOp::run() +{ + // Traverse the whole AST of the translation unit (i.e. examine the whole source file). + // The Clang AST helper class will call VisitReturnStmt for every return statement. + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); +} + +void CascadingAssignOp::Walk( const Stmt* stmt, WalkCounter& c ) +{ + for(Stmt::const_child_iterator it = stmt->child_begin(); it != stmt->child_end(); ++it) + { + ++c.stmtcount; + const BinaryOperator* binop = dyn_cast< BinaryOperator >( *it ); + if ( binop ) + { + if ( (binop->isAssignmentOp() || binop->isCompoundAssignmentOp())) + c.cascading = true; + if ( dyn_cast< AbstractConditionalOperator >( binop ) || binop->isLogicalOp()) + c.conditionals = true; + } + Walk(*it, c); + } +} + +bool CascadingAssignOp::VisitStmt( const Stmt* stmt ) +{ + const BinaryOperator* binop = dyn_cast< BinaryOperator >( stmt ); + if ( binop && (binop->isAssignmentOp() || binop->isCompoundAssignmentOp())) + { + WalkCounter c = { 0, false, false }; + Walk(binop, c); + if(c.cascading && c.conditionals && c.stmtcount >= stmtlimit) + { + std::string msg("cascading assign operator mixing in conditionals, complexity: "); + msg.append(std::to_string(c.stmtcount)); + report( DiagnosticsEngine::Warning, msg, binop->getLocStart()); + } + } + return true; +} + +// Register the plugin action with the LO plugin handling. +static Plugin::Registration< CascadingAssignOp > X( "cascadingassignop" ); + +} // namespace loplugin + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/cascadingassignop.hxx b/compilerplugins/clang/store/cascadingassignop.hxx new file mode 100644 index 000000000..147ecaad0 --- /dev/null +++ b/compilerplugins/clang/store/cascadingassignop.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include "plugin.hxx" + +namespace loplugin +{ + +struct WalkCounter; + +// The class implementing the plugin action. +class CascadingAssignOp + // Inherits from the Clang class that will allow examining the Clang AST tree (i.e. syntax tree). + : public FilteringPlugin< CascadingAssignOp > + { + public: + CascadingAssignOp( const InstantiationData& data ); + virtual void run() override; + void Walk( const Stmt* stmt, WalkCounter& c ); + bool VisitStmt( const Stmt* stmt ); + }; + +} // namespace loplugin + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/cascadingcondop.cxx b/compilerplugins/clang/store/cascadingcondop.cxx new file mode 100644 index 000000000..4671f41b4 --- /dev/null +++ b/compilerplugins/clang/store/cascadingcondop.cxx @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "cascadingcondop.hxx" + +/* +This is a compile check. + +It checks for complex statements with conditional operators in conditional +operators, which are error prone, e.g. + Thing foo = IsBar() ? ( IsBaz() ? b1 : b2 ) : b3; + +However, it finds 556 cases in sw/source alone, thus likely needs some more +restricting, e.g. by checking for multiline conditional operator statements or +a certain length in characters (but that needs the Context/SourceManager, which +I haven't played with yet). +*/ + +// the value is rather arbitrary, but code above this number of stmts begins to +// be smelly +static const int stmtlimit = 50; + +namespace loplugin +{ +struct WalkCounter +{ + int stmtcount; + bool cascading; +}; + +// Ctor, nothing special, pass the argument(s). +CascadingCondOp::CascadingCondOp(const InstantiationData& data) + : FilteringPlugin(data) +{ +} + +// Perform the actual action. +void CascadingCondOp::run() +{ + // Traverse the whole AST of the translation unit (i.e. examine the whole source file). + // The Clang AST helper class will call VisitReturnStmt for every return statement. + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); +} + +void CascadingCondOp::Walk(const Stmt* stmt, WalkCounter& c) +{ + for (Stmt::const_child_iterator it = stmt->child_begin(); it != stmt->child_end(); ++it) + { + ++c.stmtcount; + if (dyn_cast(*it)) + c.cascading = true; + Walk(*it, c); + } +} + +bool CascadingCondOp::VisitStmt(const Stmt* stmt) +{ + if (const ConditionalOperator* condop = dyn_cast(stmt)) + { + WalkCounter c = { 0, false }; + Walk(condop, c); + if (c.cascading && c.stmtcount >= stmtlimit) + { + std::string msg("cascading conditional operator, complexity: "); + msg.append(std::to_string(c.stmtcount)); + report(DiagnosticsEngine::Warning, msg, condop->getLocStart()); + } + } + return true; +} + +// Register the plugin action with the LO plugin handling. +static Plugin::Registration X("cascadingcondop"); + +} // namespace loplugin + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/cascadingcondop.hxx b/compilerplugins/clang/store/cascadingcondop.hxx new file mode 100644 index 000000000..599fafd82 --- /dev/null +++ b/compilerplugins/clang/store/cascadingcondop.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include "plugin.hxx" + +namespace loplugin +{ + +struct WalkCounter; + +// The class implementing the plugin action. +class CascadingCondOp + // Inherits from the Clang class that will allow examining the Clang AST tree (i.e. syntax tree). + : public FilteringPlugin< CascadingCondOp > + { + public: + CascadingCondOp( const InstantiationData& data ); + virtual void run() override; + void Walk( const Stmt* stmt, WalkCounter& c ); + bool VisitStmt( const Stmt* stmt ); + }; + +} // namespace loplugin + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/changefunctioncalls.cxx b/compilerplugins/clang/store/changefunctioncalls.cxx new file mode 100644 index 000000000..9f5390a21 --- /dev/null +++ b/compilerplugins/clang/store/changefunctioncalls.cxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +/* +This is a rewriter. + +Changes all calls to a specific function (after it's been renamed or its +arguments have changed). + +This specific example checks for calls to function 'void bar(unsigned int)' +and adds '+ 10' to the argument (as plain text, so if the argument is a more +complex expression, operator precedence may mean the result is actually different). + +This can be easily adjusted for different modifications to a function: +- replace CallExpr with CXXOperatorCallExpr or CXXMemberCallExpr +- check different names or arguments +- change getDirectCallee() to getCallee() +- etc. +*/ + +#include "plugin.hxx" +#include "check.hxx" + +namespace loplugin +{ + +class ChangeFunctionCalls + : public loplugin::FilteringRewritePlugin< ChangeFunctionCalls > + { + public: + explicit ChangeFunctionCalls( CompilerInstance& compiler, Rewriter& rewriter ); + virtual void run() override; + bool VisitCallExpr( const CallExpr* call ); + }; + +ChangeFunctionCalls::ChangeFunctionCalls( CompilerInstance& compiler, Rewriter& rewriter ) + : FilteringRewritePlugin( compiler, rewriter ) + { + } + +void ChangeFunctionCalls::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +bool ChangeFunctionCalls::VisitCallExpr( const CallExpr* call ) + { + if( ignoreLocation( call )) + return true; + // Using getDirectCallee() here means that we find only calls + // that call the function directly (i.e. not using a pointer, for example). + // Use getCallee() to include also those : + // if( const FunctionDecl* func = dyn_cast_or_null< FunctionDecl >( call->getCalleeDecl())) + if( const FunctionDecl* func = call->getDirectCallee()) + { + // so first check fast details like number of arguments or the (unqualified) + // name before checking the fully qualified name. + // See FunctionDecl for all the API about the function. + if( func->getNumParams() == 1 && func->getIdentifier() != NULL + && ( func->getName() == "bar" )) + { + auto qt = loplugin::DeclCheck(func); + if( qt.Function("bar").GlobalNamespace() ) + { + // Further checks about arguments. Check mainly ParmVarDecl, VarDecl, + // ValueDecl and QualType for Clang API details. + string arg0 = func->getParamDecl( 0 )->getType().getAsString(); + if( arg0 == "unsigned int" ) + { + insertTextAfterToken( call->getArg( 0 )->getLocEnd(), " + 10" ); + report( DiagnosticsEngine::Warning, "found", call->getLocStart()); + } + } + } + } + return true; + } + +static Plugin::Registration< ChangeFunctionCalls > X( "changefunctioncalls" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/constantfunction.cxx b/compilerplugins/clang/store/constantfunction.cxx new file mode 100644 index 000000000..a7b88704c --- /dev/null +++ b/compilerplugins/clang/store/constantfunction.cxx @@ -0,0 +1,506 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "plugin.hxx" +#include + +/* + Look for member functions that merely return a compile-time constant, or they are empty, and can thus + be either removed, or converted into a constant. + + This mostly tends to happen as a side-effect of other cleanups. +*/ +namespace { + +class ConstantFunction: + public loplugin::FilteringPlugin +{ + StringRef getFilename(const FunctionDecl* functionDecl); +public: + explicit ConstantFunction(InstantiationData const & data): FilteringRewritePlugin(data) {} + + void run() override + { + // these files crash clang-3.5 somewhere in the isEvaluatable/EvaluateAsXXX stuff +/* FileID mainFileID = compiler.getSourceManager().getMainFileID(); + if (strstr(compiler.getSourceManager().getFileEntryForID(mainFileID)->getName(), "bootstrapfixture.cxx") != 0) { + return; + } + if (strstr(compiler.getSourceManager().getFileEntryForID(mainFileID)->getName(), "gtkinst.cxx") != 0) { + return; + }*/ + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitFunctionDecl(const FunctionDecl *); +}; + +StringRef ConstantFunction::getFilename(const FunctionDecl* functionDecl) +{ + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(functionDecl->getCanonicalDecl()->getNameInfo().getLoc()); + StringRef name { getFilenameOfLocation(spellingLocation) }; + return name; +} + +static bool startsWith(const std::string& rStr, const char* pSubStr) { + return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; +} + +bool ConstantFunction::VisitFunctionDecl(const FunctionDecl * pFunctionDecl) { + if (ignoreLocation(pFunctionDecl)) { + return true; + } + if (!pFunctionDecl->hasBody()) { + return true; + } + if (!pFunctionDecl->isThisDeclarationADefinition()) { + return true; + } + // stuff declared extern-C is almost always used as a some kind of callback + if (pFunctionDecl->isExternC()) { + return true; + } + if (pFunctionDecl->isConstexpr()) { + return true; + } + if (pFunctionDecl->isMain()) { + return true; + } + + StringRef aFileName = getFilename(pFunctionDecl); + + // various tests in here are empty stubs under Linux + if (aFileName.startswith(SRCDIR "/sal/qa/")) { + return true; + } + // lots of empty stuff here where it looks like someone is still going to "fill in the blanks" + if (aFileName.startswith(SRCDIR "/basegfx/test/")) { + return true; + } + // bridges has some weird stuff in it... + if (aFileName.startswith(SRCDIR "/bridges/")) { + return true; + } + // dummy implementation of DDE, since it is only active on Windows + if (aFileName == SRCDIR "/svl/unx/source/svdde/ddedummy.cxx" + || aFileName == SRCDIR "/include/svl/svdde.hxx") { + return true; + } + // fancy templates at work here + if (aFileName == SRCDIR "/vcl/source/gdi/bmpfast.cxx") { + return true; + } + // bunch of stuff used as callbacks here + if (aFileName == SRCDIR "/vcl/generic/glyphs/gcach_layout.cxx") { + return true; + } + // salplug runtime-loading mechanism at work + if (aFileName == SRCDIR "/vcl/inc/salinst.hxx") { + return true; + } + // lots of callbacks here + if (aFileName == SRCDIR "/extensions/source/plugin/unx/npnapi.cxx") { + return true; + } + // vcl/unx/gtk3 re-using vcl/unx/gtk: + if (aFileName.find("/../../gtk/") != std::string::npos) { + return true; + } + // used by code generated by python + if (aFileName == SRCDIR "/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx") { + return true; + } + // this test just test the include of some headers + if (aFileName == SRCDIR "/officecfg/qa/cppheader.cxx") { + return true; + } + // just ignore this for now, people furiously hacking in there + if (startsWith(aFileName, SRCDIR "/libreofficekit")) { + return true; + } + + + const CXXMethodDecl *pCXXMethodDecl = dyn_cast(pFunctionDecl); + if (pCXXMethodDecl) { + if (pCXXMethodDecl->isVirtual()) { + return true; + } + // static with inline body will be optimised at compile-time to a constant anyway + if (pCXXMethodDecl->isStatic() && (pCXXMethodDecl->hasInlineBody() || pCXXMethodDecl->isInlineSpecified())) { + return true; + } + // this catches some stuff in templates + if (pFunctionDecl->hasAttr()) { + return true; + } + } + // a free function with an inline body will be optimised at compile-time to a constant anyway + if (!pCXXMethodDecl && pFunctionDecl->isInlineSpecified()) { + return true; + } + if (isa(pFunctionDecl) || isa(pFunctionDecl) || isa(pFunctionDecl)) { + return true; + } + if (isInUnoIncludeFile(pFunctionDecl)) { + return true; + } + + switch (pFunctionDecl->getOverloadedOperator()) { + case OO_Delete: + case OO_EqualEqual: + case OO_Call: + return true; + default: + break; + } + + std::string aFunctionName = pFunctionDecl->getQualifiedNameAsString(); + + // something to do with dynamic loading in sal/textenc/textenc.cxx + if (aFunctionName == "thisModule") { + return true; + } + // an empty stub under certain conditions, sal/osl/unx/thread.cxx + if (aFunctionName == "osl_thread_priority_init_Impl") { + return true; + } + // a pointer to this function is taken and passed to an underlying API, cppu/source/uno/lbenv.cxx + if (aFunctionName == "defenv_dispose") { + return true; + } + // a pointer to this function is taken and passed to an underlying API, cppuhelper/source/exc_thrower.cxx + if (aFunctionName == "ExceptionThrower_acquire_release_nop") { + return true; + } + // used as a callback, /vcl/source/filter/jpeg/JpegReader.cxx + if (aFunctionName == "term_source") { + return true; + } + // only valid for windows, extensions/source/update/check/updatecheck.cxx + if (aFunctionName == "(anonymous namespace)::UpdateCheckThread::hasInternetConnection") { + return true; + } + // used as callback, extensions/source/plugin/unx/npwrap.cxx + if (aFunctionName == "plugin_x_error_handler" || aFunctionName == "noClosure") { + return true; + } + // used as callback, sax/source/expatwrap/sax_expat.cxx + if (aFunctionName == "(anonymous namespace)::SaxExpatParser_Impl::callbackUnknownEncoding") { + return true; + } + // used as callback, i18npool/source/textconversion/textconversion.cxx + if (aFunctionName == "com::sun::star::i18n::nullFunc") { + return true; + } + // used as callback, xmloff/source/text/txtparae.cxx + if (aFunctionName == "(anonymous namespace)::lcl_TextContentsUnfiltered") { + return true; + } + // template magic, include/canvas/verifyinput.hxx + if (aFunctionName == "canvas::tools::verifyInput") { + return true; + } + // template magic, cppcanvas/source/mtfrenderer/implrenderer.cxx + if (aFunctionName == "cppcanvas::internal::(anonymous namespace)::AreaQuery::result") { + return true; + } + // callback, drawinglayer/source/dumper/XShapeDumper. + if (aFunctionName == "(anonymous namespace)::closeCallback") { + return true; + } + // callback, basic/source/runtime/runtime.cxx + if (aFunctionName == "SbiRuntime::StepNOP") { + return true; + } + // DLL stuff, only used on windows, basic/source/runtime/dllmgr.hxx + if (aFunctionName == "SbiDllMgr::FreeDll") { + return true; + } + // only used on Windows, basic/source/sbx/sbxdec.cxx + if (aFunctionName == "SbxDecimal::neg" || aFunctionName == "SbxDecimal::isZero") { + return true; + } + // used as a callback, include/sfx2/shell.hxx + if (aFunctionName == "SfxShell::EmptyExecStub" || aFunctionName == "SfxShell::EmptyStateStub" + || aFunctionName == "SfxShell::VerbState") { + return true; + } + // SFX_IMPL_POS_CHILDWINDOW_WITHID macro + if (aFunctionName.find("GetChildWindowId") != std::string::npos) { + return true; + } + // SFX_IMPL_SUPERCLASS_INTERFACE macro + if (aFunctionName.find("InitInterface_Impl") != std::string::npos) { + return true; + } + // callback, vcl/unx/generic/app/sm.cxx + if (aFunctionName == "IgnoreIceIOErrors" || aFunctionName == "IgnoreIceErrors") { + return true; + } + // callback, vcl/unx/gtk/a11y/atkcomponent.cxx + if (aFunctionName == "component_wrapper_get_mdi_zorder") { + return true; + } + // callback, vcl/unx/gtk/a11y/atkaction.cxx + if (aFunctionName == "action_wrapper_set_description") { + return true; + } + // callback, vcl/unx/gtk/a11y/atkutil.cxx + if (aFunctionName == "ooo_atk_util_get_toolkit_version" || aFunctionName == "ooo_atk_util_get_toolkit_name") { + return true; + } + // callback, vcl/unx/gtk/a11y/atktextattributes.cxx + if (aFunctionName == "InvalidValue") { + return true; + } + // callback, vcl/unx/gtk/a11y/atktable.cxx + if (aFunctionName == "table_wrapper_set_summary" || aFunctionName == "table_wrapper_set_row_header" + || aFunctionName == "table_wrapper_set_row_description" + || aFunctionName == "table_wrapper_set_column_header" + || aFunctionName == "table_wrapper_set_column_description" + || aFunctionName == "table_wrapper_set_caption") { + return true; + } + // callbacks, vcl/unx/gtk/window/gtksalframe.cxx + if (startsWith(aFunctionName, "GtkSalFrame::IMHandler::signal")) { + return true; + } + // callbacks, vcl/unx/gtk/window/glomenu.cxx + if (startsWith(aFunctionName, "g_lo_menu_is_mutable")) { + return true; + } + // only contains code for certain versions of GTK, /vcl/unx/gtk/window/gtksalframe.cx + if (aFunctionName == "GtkSalFrame::AllocateFrame") { + return true; + } + // only valid for Windows, embeddedobj/source/msole/olemisc.cxx + if (aFunctionName == "OleEmbeddedObject::GetRidOfComponent") { + return true; + } + // callback, svx/source/accessibility/ShapeTypeHandler.cxx + if (aFunctionName == "accessibility::CreateEmptyShapeReference") { + return true; + } + // chart2/source/view/main/AbstractShapeFactory.cxx + if (aFunctionName == "chart::(anonymous namespace)::thisModule") { + return true; + } + // chart2/source/tools/InternalData.cxx + if (aFunctionName == "chart::InternalData::dump") { + return true; + } + // hwpfilter/ + if (aFunctionName == "debug" || aFunctionName == "token_debug") { + return true; + } + // callback, sdext/source/presenter/PresenterFrameworkObserver.cxx + if (aFunctionName == "sdext::presenter::PresenterFrameworkObserver::True") { + return true; + } + // callback, sw/source/core/doc/tblrwcl.cxx + if (aFunctionName == "lcl_DelOtherBox") { + return true; + } + // callback, sw/source/filter/ww8/ww8par.cxx + if (aFunctionName == "SwWW8ImplReader::Read_Majority") { + return true; + } + // callback, sw/source/filter/ww8/ww8par5.cxx + if (aFunctionName == "SwWW8ImplReader::Read_F_Shape") { + return true; + } + // called from SDI file, I don't know what that stuff is about, sd/source/ui/slidesorter/shell/SlideSorterViewShell.cx + if (aFunctionName == "sd::slidesorter::SlideSorterViewShell::ExecStatusBar" + || aFunctionName == "sd::OutlineViewShell::ExecStatusBar") { + return true; + } + // only used in debug mode, sd/source/filter/ppt/pptinanimations.cxx + if (startsWith(aFunctionName, "ppt::AnimationImporter::dump")) { + return true; + } + // only used in ENABLE_SDREMOTE_BLUETOOTH mode, sd/source/ui/dlg/tpoption.cx + if (aFunctionName == "SdTpOptionsMisc::SetImpressMode") { + return true; + } + // template magic, sc/source/ui/docshell/datastream.cxx + if (startsWith(aFunctionName, "sc::(anonymous namespace)::CSVHandler::")) { + return true; + } + // called from SDI file, I don't know what that stuff is about, sc/source/ui/view/cellsh4.cxx + if (aFunctionName == "ScCellShell::GetStateCursor") { + return true; + } + // template magic, sc/source/filter/excel/xepivot.cxx + if (aFunctionName == "XclExpPivotCache::SaveXml") { + return true; + } + // template magic, sc/source/filter/html/htmlpars.cxx + if (startsWith(aFunctionName, "(anonymous namespace)::CSSHandler::")) { + return true; + } + // callbacks, sc/source/filter/oox/formulaparser.cxx + if (startsWith(aFunctionName, "oox::xls::BiffFormulaParserImpl::import")) { + return true; + } + // template magic, sc/qa/unit/helper/csv_handler.hxx + if (startsWith(aFunctionName, "csv_handler::") || startsWith(aFunctionName, "conditional_format_handler::")) { + return true; + } + // template magic, slideshow/source/inc/listenercontainer.hxx + if (startsWith(aFunctionName, "slideshow::internal::EmptyBase::EmptyClearableGuard::")) { + return true; + } + // callback, scripting/source/vbaevents/eventhelper.cxx + if (aFunctionName == "ApproveAll") { + return true; + } + // only on WNT, basic/qa/cppunit/test_vba.cx + if (aFunctionName == "(anonymous namespace)::VBATest::testMiscOLEStuff") { + return true; + } + // GtkSalFrame::TriggerPaintEvent() is only compiled under certain versions of GTK + if (aFunctionName == "GtkSalFrame::TriggerPaintEvent") { + return true; + } + if (aFunctionName == "SwVectorModifyBase::dumpAsXml") { + return true; + } + // vcl/unx/gtk3 re-using vcl/unx/gtk: + if (aFunctionName == "DeInitAtkBridge" + || aFunctionName == "GtkData::initNWF" + || aFunctionName == "GtkSalFrame::EnsureAppMenuWatch" + || aFunctionName == "InitAtkBridge") + { + return true; + } + if (aFunctionName == "sc::AlignedAllocator::operator!=") { + return true; + } + if (aFunctionName == "clipboard_owner_init") { + return true; + } + // returns sizeof(struct) vcl/source/gdi/dibtools.cxx + if (aFunctionName == "getDIBV5HeaderSize") { + return true; + } + // windows only + if (aFunctionName == "InitAccessBridge") { + return true; + } + // callbacks + if (aFunctionName == "disabled_initSystray" || aFunctionName == "disabled_deInitSystray") { + return true; + } + // behind a BREAKPAD option + if (aFunctionName == "desktop::(anonymous namespace)::crashReportInfoExists") { + return true; + } + // LOK stuff + if (aFunctionName == "doc_getTileMode") { + return true; + } + // apparently this will be useful at sometime in the future + if (aFunctionName == "LocaleDataWrapper::getCurrZeroChar") { + return true; + } + // marked with TODO + if (aFunctionName == "oglcanvas::TextLayout::draw") { + return true; + } + // called from the .sdi files + if (aFunctionName == "SfxObjectShell::StateView_Impl") { + return true; + } + // gtk callback + if (aFunctionName == "GtkSalFrame::signalVisibility") { + return true; + } + // platform-version-dependent code + if (aFunctionName == "(anonymous namespace)::ACTIVE_TAB") { + return true; + } + // SMIL callbacks + if (aFunctionName == "boost::sp_scalar_constructor_hook" || aFunctionName == "boost::sp_scalar_destructor_hook") { + return true; + } + + + + + std::string aImmediateMacro = ""; + if (compiler.getSourceManager().isMacroBodyExpansion(pFunctionDecl->getLocStart()) ) { + StringRef name { Lexer::getImmediateMacroName( + pFunctionDecl->getLocStart(), compiler.getSourceManager(), compiler.getLangOpts()) }; + aImmediateMacro = name; + if (name.startswith("IMPL_LINK_") ) + { + return true; + } + } + + const CompoundStmt *pCompoundStmt = dyn_cast(pFunctionDecl->getBody()); + bool bEmptyBody = false; + if (pCompoundStmt) { + if (pCompoundStmt->size() > 1) { + return true; + } + if (pCompoundStmt->size() > 0) { + const ReturnStmt *pReturnStmt = dyn_cast(*pCompoundStmt->body_begin()); + if (!pReturnStmt) { + return true; + } + if (const UnaryOperator* unaryOp = dyn_cast(pReturnStmt->getRetValue())) { + if (unaryOp->getOpcode() == UO_AddrOf) { + return true; + } + } + if (pReturnStmt->getRetValue() != nullptr) { + // && !pReturnStmt->getRetValue()->isEvaluatable(compiler.getASTContext())) { + bool aBoolResult; + llvm::APSInt aIntResult; + if (pReturnStmt->getRetValue()->isTypeDependent() + || (!pReturnStmt->getRetValue()->EvaluateAsBooleanCondition(aBoolResult, compiler.getASTContext()) + && !pReturnStmt->getRetValue()->EvaluateAsInt(aIntResult, compiler.getASTContext()))) + { + return true; + } + } + } else { + bEmptyBody = true; + } + } + + std::string aMessage = "this "; + aMessage += pCXXMethodDecl ? "method" : "function"; + if (bEmptyBody) { + aMessage += " is empty and should be removed, " + aFunctionName; + } else { + aMessage += " returns a constant value and should be converted to a constant " + "or to static inline, " + aFunctionName + ", " + aImmediateMacro; + } + report( + DiagnosticsEngine::Warning, + aMessage, + pFunctionDecl->getLocStart()) + << pFunctionDecl->getSourceRange(); + if (pFunctionDecl != pFunctionDecl->getCanonicalDecl()) + report( + DiagnosticsEngine::Note, + aMessage, + pFunctionDecl->getCanonicalDecl()->getLocStart()) + << pFunctionDecl->getCanonicalDecl()->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration X("constantfunction"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/deadclass.cxx b/compilerplugins/clang/store/deadclass.cxx new file mode 100644 index 000000000..f055d6de2 --- /dev/null +++ b/compilerplugins/clang/store/deadclass.cxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "plugin.hxx" + +namespace { + +class DeadClass: + public loplugin::FilteringPlugin +{ +public: + explicit DeadClass(InstantiationData const & data): FilteringPlugin(data) {} + + void run() override; + + bool VisitCXXRecordDecl(CXXRecordDecl const *); +}; + +void DeadClass::run() { + if (compiler.getLangOpts().CPlusPlus) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } +} + +bool DeadClass::VisitCXXRecordDecl(CXXRecordDecl const * decl) { + if (ignoreLocation(decl) || !decl->isThisDeclarationADefinition()) + return true; + if (decl->needsImplicitDefaultConstructor()) + return true; + if (decl->getDescribedClassTemplate()) + return true; + if (isa(decl)) + return true; + int otherCnt = 0; + int copyMoveCnt = 0; + for (auto i = decl->ctor_begin(); i != decl->ctor_end(); ++i) { + if (!i->isUserProvided()) + continue; + if (i->isCopyOrMoveConstructor()) + copyMoveCnt++; + else + otherCnt++; + } + if (otherCnt == 0 && copyMoveCnt > 0) + { + report( + DiagnosticsEngine::Warning, + "class has only copy/move constructors, must be dead", + decl->getLocStart()) + << decl->getSourceRange(); + for (auto i = decl->ctor_begin(); i != decl->ctor_end(); ++i) { + if (i->isDeleted()) + continue; + } + } + return true; +} + +loplugin::Plugin::Registration X("deadclass"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/defaultparams.cxx b/compilerplugins/clang/store/defaultparams.cxx new file mode 100644 index 000000000..cb533cb19 --- /dev/null +++ b/compilerplugins/clang/store/defaultparams.cxx @@ -0,0 +1,128 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +#include "plugin.hxx" + +// Find places where we call a method with values == the values specified in the parameter defaults. +// i.e. where the code might as well not specify anything. + +namespace { + +class DefaultParams: + public loplugin::FilteringPlugin +{ +public: + explicit DefaultParams(InstantiationData const & data): FilteringPlugin(data) {} + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCallExpr(CallExpr * callExpr); +private: + bool evaluate(const Expr* expr, APSInt& x); +}; + +bool DefaultParams::VisitCallExpr(CallExpr * callExpr) { + if (ignoreLocation(callExpr)) { + return true; + } + if (callExpr->getDirectCallee() == nullptr) { + return true; + } + const FunctionDecl* functionDecl = callExpr->getDirectCallee()->getCanonicalDecl(); + auto n = functionDecl->getNumParams(); + if (n == 0 || !functionDecl->getParamDecl(n - 1)->hasDefaultArg()) { + return true; + } + assert(callExpr->getNumArgs() <= n); // can be < in template code + for (unsigned i = callExpr->getNumArgs(); i != 0;) { + --i; + Expr* arg = callExpr->getArg(i); + if (arg->isDefaultArgument()) { + continue; + } + // ignore this, it seems to trigger an infinite recursion + if (isa(arg)) + break; + const ParmVarDecl* parmVarDecl = functionDecl->getParamDecl(i); + if (!parmVarDecl->hasDefaultArg() + || parmVarDecl->hasUninstantiatedDefaultArg()) + { + break; + } + const Expr* defaultArgExpr = parmVarDecl->getDefaultArg(); + if (!defaultArgExpr) { + break; + } + bool found = false; + if (defaultArgExpr->isNullPointerConstant(compiler.getASTContext(), Expr::NPC_NeverValueDependent) + && arg->isNullPointerConstant(compiler.getASTContext(), Expr::NPC_NeverValueDependent)) + { + found = true; + } + if (!found) + { + APSInt x1, x2; + if (evaluate(defaultArgExpr, x1) && evaluate(arg, x2) && x1 == x2) + { + found = true; + } + } + // catch params with defaults like "= OUString()" + if (!found + && isa(arg) + && isa(defaultArgExpr)) + { + const CXXBindTemporaryExpr* strippedArg = dyn_cast_or_null(arg->IgnoreParenCasts()); + if (strippedArg && isa(strippedArg->getSubExpr()) + && dyn_cast(strippedArg->getSubExpr())->getNumArgs() == 0) + { + found = true; + } + } + if (!found) + break; + // Ignore CPPUNIT, it's macros contain some stuff that triggers us + StringRef aFileName = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(parmVarDecl->getLocStart())); + if (aFileName.find("include/cppunit") != std::string::npos) + break; + report( + DiagnosticsEngine::Warning, + "not necessary to pass this argument, it defaults to the same value", + arg->getSourceRange().getBegin()) + << arg->getSourceRange(); + report( + DiagnosticsEngine::Note, + "default method parameter declaration here", + parmVarDecl->getSourceRange().getBegin()) + << parmVarDecl->getSourceRange(); + } + return true; +} + +bool DefaultParams::evaluate(const Expr* expr, APSInt& x) +{ + if (isa(expr)) { + x = 0; + return true; + } + if (expr->EvaluateAsInt(x, compiler.getASTContext())) + { + return true; + } + return false; +} + +loplugin::Plugin::Registration< DefaultParams > X("defaultparams"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/deletedspecial.cxx b/compilerplugins/clang/store/deletedspecial.cxx new file mode 100644 index 000000000..52e717d34 --- /dev/null +++ b/compilerplugins/clang/store/deletedspecial.cxx @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include "plugin.hxx" + +// Second-guess that certain private special member function declarations for +// which no definition can be found are left undefined to prevent them from +// being implicitly declared. Such situations are better expressed by marking +// the function as = delete (it e.g. helps compilers determine +// whether class members are unused if all of a class's member definitions are +// seen in a compilation unit). (Default constructors for classes with multiple +// constructors are exempted as they would not be implicitly declared. +// Destructors are exempted because it is likely that a destructor is defined +// private on purpose.) + +namespace { + +CXXRecordDecl const * getClass(CXXMethodDecl const * decl) { + CXXRecordDecl const * cls = dyn_cast(decl->getDeclContext()); + assert(cls != nullptr); + return cls; +} + +class DeletedSpecial: + public loplugin::FilteringPlugin +{ +public: + explicit DeletedSpecial(InstantiationData const & data): FilteringPlugin(data) {} + + virtual void run() override; + + bool VisitCXXMethodDecl(CXXMethodDecl const * decl); + +private: + bool allowlist( + CXXMethodDecl const * decl, std::string const & name, + std::string const & path); +}; + +void DeletedSpecial::run() { + if (compiler.getLangOpts().CPlusPlus + && compiler.getPreprocessor().getIdentifierInfo( + "LIBO_INTERNAL_ONLY")->hasMacroDefinition()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } +} + +bool DeletedSpecial::VisitCXXMethodDecl(CXXMethodDecl const * decl) { + if (ignoreLocation(decl) || !decl->isFirstDecl() || decl->isDefined() + || decl->isDefaulted() || decl->getAccess() != AS_private) + { + return true; + } + std::string desc; + if (decl->isCopyAssignmentOperator()) { + if (allowlist(decl, "ImpGraphic", "vcl/inc/impgraph.hxx") + || allowlist(decl, "SwSubFont", "sw/source/core/inc/swfont.hxx")) + { + return true; + } + desc = "copy assignment operator"; + } else if (decl->isMoveAssignmentOperator()) { + desc = "move assignment operator"; + } else { + CXXConstructorDecl const * ctor = dyn_cast(decl); + CXXRecordDecl const * cls = getClass(decl); + if (ctor != nullptr && ctor->isCopyConstructor()) { + if (allowlist(decl, "ImpGraphic", "vcl/inc/impgraph.hxx") + || allowlist(decl, "SbMethod", "include/basic/sbmeth.hxx") + || allowlist(decl, "ScDBCollection::NamedDBs", "sc/inc/dbdata.hxx") + || allowlist(decl, "ScDrawPage", "sc/inc/drawpage.hxx") + || allowlist(decl, "SmEditSource", "starmath/source/accessibility.hxx") + || allowlist(decl, "SwChartDataSequence", "sw/inc/unochart.hxx") + || allowlist(decl, "SwDPage", "sw/inc/dpage.hxx") + || allowlist(decl, "SwRedlineExtraData_Format", "sw/inc/redline.hxx") + || allowlist(decl, "SwRedlineExtraData_FormattingChanges", "sw/inc/redline.hxx") + || allowlist(decl, "SwTextAPIEditSource", "sw/source/core/inc/textapi.hxx") + || allowlist(decl, "XclImpBiff5Decrypter", "sc/source/filter/inc/xistream.hxx") + || allowlist(decl, "XclImpBiff8Decrypter", "sc/source/filter/inc/xistream.hxx") + || allowlist(decl, "configmgr::LocalizedPropertyNode", "configmgr/source/localizedpropertynode.hxx") + || allowlist(decl, "configmgr::LocalizedValueNode", "configmgr/source/localizedvaluenode.hxx") + || allowlist(decl, "configmgr::PropertyNode", "configmgr/source/propertynode.hxx") + || allowlist(decl, "oox::xls::BiffDecoder_RCF", "sc/source/filter/inc/biffcodec.hxx") + || allowlist(decl, "oox::xls::BiffDecoder_XOR", "sc/source/filter/inc/biffcodec.hxx") + || allowlist(decl, "rptui::OReportPage", "reportdesign/inc/RptPage.hxx")) + { + return true; + } + desc = "copy constructor"; + } else if (ctor != nullptr && ctor->isMoveConstructor()) { + desc = "move constructor"; + } else if (ctor != nullptr && ctor->isDefaultConstructor() + && std::distance(cls->ctor_begin(), cls->ctor_end()) == 1) + { + if (allowlist(decl, "AquaA11yFocusListener", "vcl/osx/a11yfocuslistener.hxx") + || allowlist(decl, "DocTemplLocaleHelper", "sfx2/source/doc/doctemplateslocal.hxx") + || allowlist(decl, "ScViewDataTable", "sc/source/filter/excel/../../ui/inc/viewdata.hxx") + || allowlist(decl, "ScViewDataTable", "sc/source/ui/inc/viewdata.hxx") + || allowlist(decl, "SwLineInfo", "sw/source/core/text/inftxt.hxx") + || allowlist(decl, "XRenderPeer", "vcl/unx/generic/gdi/xrender_peer.hxx") + || allowlist(decl, "desktop::DispatchWatcher", "desktop/source/app/dispatchwatcher.hxx") + || allowlist(decl, "desktop::RequestHandler", "desktop/source/app/officeipcthread.hxx") + || allowlist(decl, "desktop::RequestHandler", "desktop/source/lib/../app/officeipcthread.hxx") + || allowlist(decl, "sd::DiscoveryService", "sd/source/ui/remotecontrol/DiscoveryService.hxx") + || allowlist(decl, "sd::IconCache", "sd/source/ui/inc/tools/IconCache.hxx") + || allowlist(decl, "sd::RemoteServer", "sd/source/ui/inc/RemoteServer.hxx") + || allowlist(decl, "sd::slidesorter::cache::PageCacheManager", "sd/source/ui/slidesorter/inc/cache/SlsPageCacheManager.hxx") + || allowlist(decl, "framework::CommandInfoProvider", "include/framework/commandinfoprovider.hxx") + || allowlist(decl, "vcl::SettingsConfigItem", "vcl/inc/configsettings.hxx") + || allowlist(decl, "writerfilter::ooxml::OOXMLFactory", "writerfilter/source/ooxml/OOXMLFactory.hxx")) + { + return true; + } + desc = "default constructor"; + } else { + return true; + } + } + report( + DiagnosticsEngine::Warning, + ("private %0 is not defined at least in this compilation unit, maybe it" + " should be marked as deleted?"), + decl->getLocation()) + << desc << decl->getSourceRange(); + return true; +} + +bool DeletedSpecial::allowlist( + CXXMethodDecl const * decl, std::string const & name, + std::string const & path) +{ + return getClass(decl)->getQualifiedNameAsString() == name + && (getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(decl->getLocation())) + == SRCDIR "/" + path); +} + +loplugin::Plugin::Registration X("deletedspecial", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/derivedclass.cxx b/compilerplugins/clang/store/derivedclass.cxx new file mode 100644 index 000000000..a1df0c253 --- /dev/null +++ b/compilerplugins/clang/store/derivedclass.cxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "plugin.hxx" + +namespace { + +class DerivedClass: + public loplugin::FilteringPlugin +{ +public: + explicit DerivedClass(InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXRecordDecl(CXXRecordDecl const * decl); +}; + +bool BaseCheck(const CXXRecordDecl *BaseDefinition, void *BaseClassName) { + // print warning about deriving from this classes + // the name has to contain namespace, e.g. foo::bar::ClassName + const char *BaseClasses[] = { + "Dialog", + "ProgressBar", + "SfxToolBoxControl", + "StatusBar", + 0, + }; + for (int i = 0; BaseClasses[i]; i++) + if (BaseDefinition->getQualifiedNameAsString().compare(BaseClasses[i]) == 0) { + *(const char **)BaseClassName = BaseClasses[i]; + return false; + } + return true; +} + +bool DerivedClass::VisitCXXRecordDecl(CXXRecordDecl const * decl) { + const char *BaseClassName = 0; + // checking for decl->hasDefinition() avoids crash in decl->forallBases + if (decl->hasDefinition() && + // not sure what hasAnyDependentBases() does, + // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1 + !decl->hasAnyDependentBases() && + !decl->forallBases(BaseCheck, &BaseClassName)) { + string warning_msg("class %0 derives from "); + // no idea how BaseClassName can be 0 sometimes... + if (BaseClassName) + warning_msg += BaseClassName; + report( + DiagnosticsEngine::Warning, + warning_msg, + decl->getLocStart()) + << decl->getQualifiedNameAsString() << decl->getSourceRange(); + } + return true; +} + +loplugin::Plugin::Registration X("derivedclass"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 tabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/finalprotected.cxx b/compilerplugins/clang/store/finalprotected.cxx new file mode 100644 index 000000000..c7296232a --- /dev/null +++ b/compilerplugins/clang/store/finalprotected.cxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include + +#include "plugin.hxx" +#include "clang/AST/CXXInheritance.h" + +// Check for final classes that have protected members + +namespace +{ + +class FinalProtected: + public loplugin::FilteringPlugin +{ +public: + explicit FinalProtected(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXMethodDecl(CXXMethodDecl const *); + bool VisitFieldDecl(FieldDecl const *); +}; + + +bool FinalProtected::VisitCXXMethodDecl(CXXMethodDecl const * cxxMethodDecl) +{ + if (ignoreLocation(cxxMethodDecl)) { + return true; + } + if (cxxMethodDecl->getAccess() != AS_protected) { + return true; + } + if (!cxxMethodDecl->getParent()->hasAttr()) { + return true; + } + cxxMethodDecl = cxxMethodDecl->getCanonicalDecl(); + report(DiagnosticsEngine::Warning, + "final class should not have protected members - convert them to private", + cxxMethodDecl->getBeginLoc()) + << cxxMethodDecl->getSourceRange(); + return true; +} + +bool FinalProtected::VisitFieldDecl(FieldDecl const * fieldDecl) +{ + if (ignoreLocation(fieldDecl)) { + return true; + } + if (fieldDecl->getAccess() != AS_protected) { + return true; + } + if (!fieldDecl->getParent()->hasAttr()) { + return true; + } + fieldDecl = fieldDecl->getCanonicalDecl(); + report(DiagnosticsEngine::Warning, + "final class should not have protected members - convert them to private", + fieldDecl->getBeginLoc()) + << fieldDecl->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration< FinalProtected > finalprotected("finalprotected"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/findoncontainer.cxx b/compilerplugins/clang/store/findoncontainer.cxx new file mode 100644 index 000000000..09f51187a --- /dev/null +++ b/compilerplugins/clang/store/findoncontainer.cxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +#include "plugin.hxx" + +// Look for places calling std::find on a standard container where it should be using the container find method, which +// is more efficient. +// +// This lives in /store because the implementation is a hack and is highly dependent on the inwards +// of the libc++ library on the machine it runs on. +// + +namespace { + +class FindOnContainer: + public loplugin::FilteringPlugin +{ +public: + explicit FindOnContainer(InstantiationData const & data): FilteringPlugin(data) {} + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCallExpr(const CallExpr * expr); +}; + +bool FindOnContainer::VisitCallExpr(const CallExpr * expr) { + if (ignoreLocation(expr)) { + return true; + } + FunctionDecl const * fdecl = expr->getDirectCallee(); + if (fdecl == nullptr) { + return true; + } + std::string qname { fdecl->getQualifiedNameAsString() }; + if (qname == "std::find") + { + std::string tname = expr->getArg(0)->getType().getAsString(); + if (tname.find("std::_List_iterator") != std::string::npos + || tname.find("std::_List_const_iterator") != std::string::npos + || tname.find("std::vector") != std::string::npos + || tname.find("std::_Deque_iterator") != std::string::npos + || tname == "const int *" + || tname == "struct std::_Bit_const_iterator" + || tname == "const rtl::OUString *" + || tname == "class rtl::OUString *" + || tname == "const class rtl::OUString *" + || tname == "const sal_Int8 *" + || tname == "const sal_Int32 *" + || tname == "sal_Int32 *" + || tname == "sal_uInt16 *" ) + { + return true; + } + expr->dump(); + report( + DiagnosticsEngine::Warning, + ("rather use the more specific find method " + tname), + expr->getExprLoc()); + return true; + } + return true; +} + +loplugin::Plugin::Registration< FindOnContainer > X("findoncontainer"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/fpcomparison.cxx b/compilerplugins/clang/store/fpcomparison.cxx new file mode 100644 index 000000000..faaec0110 --- /dev/null +++ b/compilerplugins/clang/store/fpcomparison.cxx @@ -0,0 +1,386 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "check.hxx" +#include "plugin.hxx" + +/** +comparing floating point numbers using == or != is a bad idea. +*/ + +namespace { + +class FpComparison: + public loplugin::FilteringPlugin +{ +public: + explicit FpComparison(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override + { + vclFloatDevicePixel = compiler.getPreprocessor() + .getIdentifierInfo("VCL_FLOAT_DEVICE_PIXEL")->hasMacroDefinition(); + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitBinaryOperator(const BinaryOperator* ); + bool TraverseFunctionDecl(FunctionDecl* ); + bool TraverseCXXMethodDecl(CXXMethodDecl* ); +private: + bool ignore(FunctionDecl* ); + enum class EState { None, TraverseProcess, TraverseIgnore }; + EState meState = EState::None; + bool vclFloatDevicePixel; +}; + +bool FpComparison::TraverseFunctionDecl(FunctionDecl* function) +{ + bool bIgnore = ignore(function); + meState = bIgnore ? EState::TraverseIgnore : EState::TraverseProcess; + bool bRet = RecursiveASTVisitor::TraverseFunctionDecl(function); + meState = EState::None; + return bRet; +} + +bool FpComparison::TraverseCXXMethodDecl(CXXMethodDecl* function) +{ + bool bIgnore = ignore(function); + meState = bIgnore ? EState::TraverseIgnore : EState::TraverseProcess; + bool bRet = RecursiveASTVisitor::TraverseCXXMethodDecl(function); + meState = EState::None; + return bRet; +} + +bool FpComparison::ignore(FunctionDecl* function) +{ + if (ignoreLocation(function)) { + return true; + } + // we assume that these modules know what they are doing with FP stuff + StringRef aFileName = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(function->getLocStart())); + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/sc/")) { + return true; + } + if (!function->doesThisDeclarationHaveABody()) { + return true; + } + // Ignore operator== and operator!= + if (function->getOverloadedOperator() == OO_EqualEqual + || function->getOverloadedOperator() == OO_ExclaimEqual) { + return true; + } + // ignore known good functions + loplugin::DeclCheck dc(function); + if ((dc.Function("approxEqual").Namespace("math").Namespace("rtl") + .GlobalNamespace()) + || dc.Function("doubleToString").AnonymousNamespace().GlobalNamespace() + || dc.Function("stringToDouble").AnonymousNamespace().GlobalNamespace() + || dc.Function("rtl_math_round").GlobalNamespace() + || dc.Function("rtl_math_approxEqual").GlobalNamespace() + || dc.Function("rtl_math_approxValue").GlobalNamespace() + || dc.Function("rtl_math_asinh").GlobalNamespace() + || dc.Function("rtl_math_acosh").GlobalNamespace() + || dc.Function("_equalSequence").Namespace("cppu").GlobalNamespace() + // cppu/source/uno/eq.hxx + || dc.Function("_equalData").Namespace("cppu").GlobalNamespace() + // cppu/source/uno/eq.hxx + || dc.Function("equalFont").Namespace("xmlscript").GlobalNamespace() + // xmlscript/source/xmldlg_imexp/xmldlg_export.cxx + || (dc.Function("initialize").Class("Impl2").AnonymousNamespace() + .GlobalNamespace()) + // testtools/source/bridgetest/constructors.cxx + || (dc.Function("initialize").Class("Impl").AnonymousNamespace() + .GlobalNamespace()) + // testtools/source/bridgetest/constructors.cxx + || dc.Function("lok_approxEqual").AnonymousNamespace().GlobalNamespace() + // libreofficekit/source/gtk/lokdocview.cxx + // These might need fixing: + || (dc.Function("getSmallestDistancePointToPolygon").Namespace("utils") + .Namespace("basegfx").GlobalNamespace()) + // basegfx/source/polygon/b2dpolygontools.cxx + || (dc.Function("getSmallestDistancePointToPolyPolygon") + .Namespace("utils").Namespace("basegfx").GlobalNamespace()) + // basegfx/source/polygon/b2dpolypolygontools.cxx + || dc.Function("performTest").Namespace("bridge_test").GlobalNamespace() + // testtools/source/bridgetest/bridgetest.cxx + || dc.Function("equals").Namespace("bridge_test").GlobalNamespace() + || (dc.Function("lcl_getNANInsteadDBL_MIN").AnonymousNamespace() + .GlobalNamespace()) + // chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx + || dc.Function("compareSubstring").Class("ChapterCollator").Namespace("i18npool").GlobalNamespace() + || dc.Function("setDateTime").Class("Calendar_gregorian").Namespace("i18npool").GlobalNamespace() + || dc.Function("setLocalDateTime").Class("Calendar_gregorian").Namespace("i18npool").GlobalNamespace() + //TODO: + || dc.Function("ImpCheckCondition").Class("SvNumberformat").GlobalNamespace() + || dc.Function("GetTimeFormat").Class("SvNumberFormatter").GlobalNamespace() + || dc.Function("GuessDateTimeFormat").Class("SvNumberFormatter").GlobalNamespace() + || dc.Function("GetEditFormat").Class("SvNumberFormatter").GlobalNamespace() + || dc.Function("getSmallestDistancePointToBezierSegment").Class("B2DCubicBezier").Namespace("basegfx").GlobalNamespace() + || dc.Function("getLength").Class("B3DVector").Namespace("basegfx").GlobalNamespace() + || dc.Function("getXZLength").Class("B3DVector").Namespace("basegfx").GlobalNamespace() + || dc.Function("getYZLength").Class("B3DVector").Namespace("basegfx").GlobalNamespace() + || dc.Function("impSolve").Class("solver").AnonymousNamespace().Namespace("basegfx").GlobalNamespace() + || dc.Function("getB2DPolyPolygon").Class("solver").AnonymousNamespace().Namespace("basegfx").GlobalNamespace() + || dc.Function("getNormal").Class("CoordinateDataArray3D").GlobalNamespace() + || dc.Function("append").Class("ImplPolygon").AnonymousNamespace().Namespace("basegfx").GlobalNamespace() + || dc.Function("finish").Class("ImplPolygon").AnonymousNamespace().Namespace("basegfx").GlobalNamespace() + || dc.Function("convertMeasure").Class("Converter").Namespace("sax").GlobalNamespace() + || dc.Function("convertDouble").Class("Converter").Namespace("sax").GlobalNamespace() + || dc.Function("convertDuration").Class("Converter").Namespace("sax").GlobalNamespace() + || dc.Function("Frustum").Class("B3dTransformationSet").GlobalNamespace() + || dc.Function("Ortho").Class("B3dTransformationSet").GlobalNamespace() + || dc.Function("SetRatio").Class("B3dTransformationSet").GlobalNamespace() + || dc.Function("SetDeviceRectangle").Class("B3dTransformationSet").GlobalNamespace() + || dc.Function("HSBtoRGB").Class("Color").GlobalNamespace() + || dc.Function("Normalize").Class("Vector2D").Namespace("tools").GlobalNamespace() + || dc.Function("setAcceleration").Class("AnimationNode").Namespace("animcore").GlobalNamespace() + || dc.Function("setDecelerate").Class("AnimationNode").Namespace("animcore").GlobalNamespace() + || dc.Function("setVolume").Class("AnimationNode").Namespace("animcore").GlobalNamespace() + || dc.Function("setIterateInterval").Class("AnimationNode").Namespace("animcore").GlobalNamespace() + || dc.Function("createElement").Struct("Style").Namespace("xmlscript").GlobalNamespace() + || dc.Function("set_property").Class("Window").Namespace("vcl").GlobalNamespace() + || dc.Function("Adjust").Class("Bitmap").GlobalNamespace() + || dc.Function("ImplWriteActions").Class("SVMConverter").GlobalNamespace() + || dc.Function("Mirror").Class("GDIMetaFile").GlobalNamespace() + || dc.Function("Adjust").Class("GDIMetaFile").GlobalNamespace() + || dc.Function("Scale").Class("MetaCommentAction").GlobalNamespace() + || dc.Function("ImplGetGamma").Class("PNGReaderImpl").Namespace("vcl").GlobalNamespace() + || dc.Function("playMetafile").Class("PDFWriterImpl").Namespace("vcl").GlobalNamespace() + || dc.Function("invert").Class("Matrix3").Namespace("vcl").GlobalNamespace() + || dc.Function("emitTilings").Class("PDFWriterImpl").Namespace("vcl").GlobalNamespace() + || dc.Function("drawHorizontalGlyphs").Class("PDFWriterImpl").Namespace("vcl").GlobalNamespace() + || dc.Function("ImplWrite").Class("EMFWriter").GlobalNamespace() + || dc.Function("WriteRecords").Class("WMFWriter").GlobalNamespace() + || dc.Function("convertOneTypeEsc").Class("CffSubsetterContext").GlobalNamespace() + || dc.Function("ApplyGlyphTransform").Class("FreetypeFont").GlobalNamespace() + || dc.Function("JoinVerticalClipRectangles").Class("PrinterGfx").Namespace("psp").GlobalNamespace() + || dc.Function("PSSetLineWidth").Class("PrinterGfx").Namespace("psp").GlobalNamespace() + || dc.Function("DrawEPS").Class("PrinterGfx").Namespace("psp").GlobalNamespace() + || dc.Function("addDrawRectangle").Class("RenderList").GlobalNamespace() + || dc.Function("addDrawPolyPolygon").Class("RenderList").GlobalNamespace() + || dc.Function("addDrawPolyLine").Class("RenderList").GlobalNamespace() + || dc.Function("ApplyMatrix").Class("OpenGLProgram").GlobalNamespace() + || dc.Function("GuessWidth").Class("BorderWidthImpl").GlobalNamespace() + || dc.Function("ImplSetValue").Class("FormattedField").GlobalNamespace() + || dc.Function("IsAdjusted").Class("GraphicAttr").GlobalNamespace() + || dc.Operator(OO_Call).Struct("SpriteWeakOrder").Namespace("canvas").GlobalNamespace() + || dc.Function("setAlpha").Class("CanvasCustomSpriteHelper").Namespace("canvas").GlobalNamespace() + || dc.Function("setPriority").Class("CanvasCustomSpriteHelper").Namespace("canvas").GlobalNamespace() + || dc.Function("createFillGraphicAttribute").Class("SdrFillGraphicAttribute").Namespace("attribute").Namespace("drawinglayer").GlobalNamespace() + || dc.Function("create2DDecomposition").Class("ScenePrimitive2D").Namespace("primitive2d").Namespace("drawinglayer").GlobalNamespace() + || dc.Function("createAtom").Class("SvgLinearGradientPrimitive2D").Namespace("primitive2d").Namespace("drawinglayer").GlobalNamespace() + || dc.Function("createAtom").Class("SvgRadialGradientPrimitive2D").Namespace("primitive2d").Namespace("drawinglayer").GlobalNamespace() + || dc.Function("FoldConstantsBinaryNode").Class("SbiExprNode").GlobalNamespace() + || dc.Function("Format").Class("SbxValue").GlobalNamespace() + || dc.Function("Compare").Class("SbxValue").GlobalNamespace() + || dc.Function("SelectPlayToolBoxItem").Class("MediaControlBase").Namespace("avmedia").GlobalNamespace() + || dc.Function("convertDateTime").Class("SvXMLUnitConverter").GlobalNamespace() + || dc.Function("exportAudio").Class("AnimationsExporterImpl").Namespace("xmloff").GlobalNamespace() + || dc.Function("StartElement").Class("XMLEnhancedCustomShapeContext").GlobalNamespace() + || dc.Function("SetString").Class("SdXMLImExTransform2D").GlobalNamespace() + || dc.Function("SetString").Class("SdXMLImExTransform3D").GlobalNamespace() + || dc.Function("ExportPart_Impl").Class("SvXMLNumFmtExport").GlobalNamespace() + || dc.Function("AddNumber").Class("SvXMLNumFormatContext").GlobalNamespace() + || dc.Function("GetColorData").Class("EnhancedCustomShape2d").GlobalNamespace() + || dc.Function("AdaptObjColor").Class("EnhancedCustomShape2d").GlobalNamespace() + || dc.Function("RotateScene").Class("E3dScene").GlobalNamespace() + || dc.Function("createViewIndependentPrimitive2DSequence").Class("ViewContactOfSdrCaptionObj").Namespace("contact").Namespace("sdr").GlobalNamespace() + || dc.Function("PostItemChange").Class("E3dSceneProperties").Namespace("properties").Namespace("sdr").GlobalNamespace() + || dc.Function("NbcRotate").Class("SdrObject").GlobalNamespace() + || dc.Function("TakeObjNameSingul").Class("SdrPathObj").GlobalNamespace() + || dc.Function("NbcInsPoint").Class("SdrPathObj").GlobalNamespace() + || dc.Function("setValue").Class("Cell").Namespace("table").Namespace("sdr").GlobalNamespace() + || dc.Function("implSetDepth").Class("ExtrusionDepthWindow").Namespace("svx").GlobalNamespace() + || dc.Function("PointsToBezier").Class("XPolygon").GlobalNamespace() + || dc.Function("SetPosition").Class("Svx3DLightControl").GlobalNamespace() + || dc.Function("SetRotation").Class("Svx3DLightControl").GlobalNamespace() + || dc.Function("PlayToolBoxSelectHdl").Class("MediaPlaybackPanel").Namespace("sidebar").Namespace("svx").GlobalNamespace() + || dc.Function("CreateGraphicProperties").Class("EscherPropertyContainer").GlobalNamespace() + || dc.Function("renderSprite").Class("CanvasCustomSprite").Namespace("oglcanvas").GlobalNamespace() + || dc.Operator(OO_Call).Struct("SpriteComparator").AnonymousNamespace().Namespace("oglcanvas").GlobalNamespace() + || dc.Function("isHorizontalAxis").Class("TickFactory2D").Namespace("chart").GlobalNamespace() + || dc.Function("isVerticalAxis").Class("TickFactory2D").Namespace("chart").GlobalNamespace() + || dc.Function("getDistanceAxisTickToText").Class("TickFactory2D").Namespace("chart").GlobalNamespace() + || dc.Function("calculateExplicitIncrementAndScaleForLogarithmic").Class("ScaleAutomatism").Namespace("chart").GlobalNamespace() + || dc.Function("calculateExplicitIncrementAndScaleForLinear").Class("ScaleAutomatism").Namespace("chart").GlobalNamespace() + || dc.Function("makeTickmarkPropertiesForComplexCategories").Struct("AxisProperties").Namespace("chart").GlobalNamespace() + || dc.Function("createShapes").Class("BarChart").Namespace("chart").GlobalNamespace() + || dc.Function("transform").Class("Linear3DTransformation").Namespace("chart").GlobalNamespace() + || dc.Function("CalculateCubicSplines").Class("SplineCalculater").Namespace("chart").GlobalNamespace() + || dc.Function("setDiagramPositioning").Class("DiagramHelper").Namespace("chart").GlobalNamespace() + || dc.Function("centerGrow").Class("RelativePositionHelper").Namespace("chart").GlobalNamespace() + || dc.Function("pushToPropMap").Struct("FillProperties").Namespace("drawingml").Namespace("oox").GlobalNamespace() + || dc.Function("convertFromProperties").Class("AxFontDataModel").Namespace("ole").Namespace("oox").GlobalNamespace() + || dc.Function("isNotANumber").Class("ChartDataWrapper").Namespace("wrapper").Namespace("chart").GlobalNamespace() + || dc.Function("Reset").Class("ErrorBarResources").Namespace("chart").GlobalNamespace() + || dc.Function("ApplySpecialItem").Class("AxisItemConverter").Namespace("wrapper").Namespace("chart").GlobalNamespace() + || dc.Function("ApplySpecialItem").Class("DataPointItemConverter").Namespace("wrapper").Namespace("chart").GlobalNamespace() + || dc.Function("ApplySpecialItem").Class("TitleItemConverter").Namespace("wrapper").Namespace("chart").GlobalNamespace() + || dc.Function("ApplySpecialItem").Class("TextLabelItemConverter").Namespace("wrapper").Namespace("chart").GlobalNamespace() + || dc.Function("operate").Class("OOp_COMPARE").Namespace("file").Namespace("connectivity").GlobalNamespace() + || dc.Function("Write").Class("ORTFImportExport").Namespace("dbaui").GlobalNamespace() + || dc.Function("appendRow").Class("ORTFImportExport").Namespace("dbaui").GlobalNamespace() + || dc.Function("WriteCell").Class("OHTMLImportExport").Namespace("dbaui").GlobalNamespace() + || dc.Function("getBold").Class("VbaFontBase").GlobalNamespace() + || dc.Function("ModifyHdl").Class("SaneDlg").GlobalNamespace() + || dc.Function("EstablishNumericOption").Class("SaneDlg").GlobalNamespace() + || dc.Function("translatePropertiesToItems").Class("ControlCharacterDialog").Namespace("pcr").GlobalNamespace() + || dc.Function("writeMatrix").Class("Tag").Namespace("swf").GlobalNamespace() + || dc.Function("Impl_writeActions").Class("Writer").Namespace("swf").GlobalNamespace() + || dc.Function("Impl_quadBezierApprox").Class("Writer").Namespace("swf").GlobalNamespace() + || dc.Function("hasGradientOpacity").Struct("AnnotatingVisitor").AnonymousNamespace().Namespace("svgi").GlobalNamespace() + || dc.Function("getOdfColor").Struct("AnnotatingVisitor").AnonymousNamespace().Namespace("svgi").GlobalNamespace() + || dc.Function("writeStyle").Struct("AnnotatingVisitor").AnonymousNamespace().Namespace("svgi").GlobalNamespace() + || dc.Operator(OO_Call).Struct("ShapeWritingVisitor").AnonymousNamespace().Namespace("svgi").GlobalNamespace() + || dc.Function("SvgDashArray2Odf").Struct("OfficeStylesWritingVisitor").Namespace("svgi").GlobalNamespace() + || dc.Function("ImplWriteMask").Class("SVGActionWriter").GlobalNamespace() + || dc.Function("Factor").Class("FormulaCompiler").Namespace("formula").GlobalNamespace() + || dc.Function("setDateTime").Class("Calendar_gregorian").Namespace("i18n").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace() + || dc.Function("setLocalDateTime").Class("Calendar_gregorian").Namespace("i18n").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace() + || dc.Function("compareSubstring").Class("ChapterCollator").Namespace("i18n").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace() + || dc.Function("ToXml").Class("XFPadding").GlobalNamespace() + || dc.Function("Equal").Class("XFCellStyle").GlobalNamespace() + || dc.Function("Equal").Class("XFParaStyle").GlobalNamespace() + || dc.Function("GetAnimationEffect").Class("EffectMigration").Namespace("sd").GlobalNamespace() + || dc.Function("SetAnimationSpeed").Class("EffectMigration").Namespace("sd").GlobalNamespace() + || dc.Function("GetAnimationSpeed").Class("EffectMigration").Namespace("sd").GlobalNamespace() + || dc.Function("calculateIterateDuration").Class("CustomAnimationEffect").Namespace("sd").GlobalNamespace() + || dc.Function("setDuration").Class("CustomAnimationEffect").Namespace("sd").GlobalNamespace() + || dc.Function("replaceNode").Class("CustomAnimationEffect").Namespace("sd").GlobalNamespace() + || dc.Function("setIterateInterval").Class("CustomAnimationEffect").Namespace("sd").GlobalNamespace() + || dc.Function("append").Class("EffectSequenceHelper").Namespace("sd").GlobalNamespace() + || dc.Function("replace").Class("EffectSequenceHelper").Namespace("sd").GlobalNamespace() + || dc.Function("createTextGroupParagraphEffects").Class("EffectSequenceHelper").Namespace("sd").GlobalNamespace() + || dc.Function("setTextGrouping").Class("EffectSequenceHelper").Namespace("sd").GlobalNamespace() + || dc.Function("setTextGroupingAuto").Class("EffectSequenceHelper").Namespace("sd").GlobalNamespace() + || dc.Function("SetPresentationPenWidth").Class("SdOptionsMisc").GlobalNamespace() + || dc.Function("VarLook").Class("SwCalc").GlobalNamespace() + || dc.Function("Prim").Class("SwCalc").GlobalNamespace() + || dc.Function("keycompare").Struct("SwSortElement").GlobalNamespace() + || dc.Function("FormatValue").Class("SwDBField").GlobalNamespace() + || dc.Function("Evaluate").Class("SwDBField").GlobalNamespace() + || dc.Function("GetValue").Class("SwTableBox").GlobalNamespace() + || dc.Function("Modify").Class("SwTableBoxFormat").GlobalNamespace() + || dc.Function("isNotANumber").Class("SwXTextTable").GlobalNamespace() + || dc.Function("GetNextToken").Class("CSS1Parser").GlobalNamespace() + || dc.Function("update").Class("FontStylePropertyBox").Namespace("sd").GlobalNamespace() + || dc.Function("implMenuSelectHdl").Class("FontStylePropertyBox").Namespace("sd").GlobalNamespace() + || dc.Function("update").Class("CustomAnimationEffectTabPage").Namespace("sd").GlobalNamespace() + || dc.Function("update").Class("CustomAnimationDurationTabPage").Namespace("sd").GlobalNamespace() + || dc.Function("update").Class("CustomAnimationTextAnimTabPage").Namespace("sd").GlobalNamespace() + || dc.Function("FillCalcWithMergeData").Class("SwDBManager").GlobalNamespace() + || dc.Function("compareWith").Struct("TransitionEffect").Namespace("impl").Namespace("sd").GlobalNamespace() + || dc.Function("changeSelection").Class("CustomAnimationPane").Namespace("sd").GlobalNamespace() + || dc.Function("ContextMenuHdl").Class("SlideshowImpl").Namespace("sd").GlobalNamespace() + || dc.Function("FormatBox").Class("DocxAttributeOutput").GlobalNamespace() + || dc.Function("GetString").Class("Complex").Namespace("analysis").Namespace("sca").GlobalNamespace() + || dc.Function("getDelta").Class("AnalysisAddIn").GlobalNamespace() + || dc.Function("DataToDoc").Class("SwInsertDBColAutoPilot").GlobalNamespace() + || dc.Function("convertAnimateValue").Class("AnimationExporter").Namespace("ppt").GlobalNamespace() + || dc.Function("GetId").Class("PPTExBulletProvider").GlobalNamespace() + || dc.Function("SetThumbPosition").Class("PresenterScrollBar").Namespace("presenter").Namespace("sdext").GlobalNamespace() + || dc.Function("SetTotalSize").Class("PresenterScrollBar").Namespace("presenter").Namespace("sdext").GlobalNamespace() + || dc.Function("SetThumbSize").Class("PresenterScrollBar").Namespace("presenter").Namespace("sdext").GlobalNamespace() + || dc.Function("Layout").Class("PresenterNotesView").Namespace("presenter").Namespace("sdext").GlobalNamespace() + || dc.Function("compare").Struct("lessThanShape").Class("Shape").Namespace("internal").Namespace("slideshow").GlobalNamespace() + || dc.Operator(OO_Call).Struct("lessThanArea").Class("HyperlinkArea").Namespace("internal").Namespace("slideshow").GlobalNamespace() + || dc.Function("viewsChanged").Class("PointerSymbol").Namespace("internal").Namespace("slideshow").GlobalNamespace() + || dc.Function("RetrieveAttrs").Struct("SmXMLContext_Helper").GlobalNamespace() + || dc.Function("CompareImpl").Class("SortedResultSet").GlobalNamespace() + || dc.Function("emit").Struct("PDFNumber").Namespace("pdfparse").GlobalNamespace() + || dc.Function("visit").Class("DrawXmlOptimizer").Namespace("pdfi").GlobalNamespace() + || dc.Function("optimizeTextElements").Class("DrawXmlOptimizer").Namespace("pdfi").GlobalNamespace() + || dc.Function("init").Class("DrawXmlFinalizer").Namespace("pdfi").GlobalNamespace() + || dc.Function("visit").Class("DrawXmlFinalizer").Namespace("pdfi").GlobalNamespace() + || dc.Function("GetState").Class("OReportController").Namespace("rptui").GlobalNamespace() + || dc.Function("isFormatCommandEnabled").Class("OReportController").Namespace("rptui").GlobalNamespace() + || dc.Function("resolveUnderlines").Struct("PageElement").Namespace("pdfi").GlobalNamespace() + || dc.Function("visit").Class("WriterXmlOptimizer").Namespace("pdfi").GlobalNamespace() + || dc.Function("optimizeTextElements").Class("WriterXmlOptimizer").Namespace("pdfi").GlobalNamespace() + || dc.Function("drawGlyphs").Class("PDFIProcessor").Namespace("pdfi").GlobalNamespace() + || dc.Function("LTypeToDXFLineInfo").Class("DXF2GDIMetaFile").GlobalNamespace() + || dc.Function("DrawEntities").Class("DXF2GDIMetaFile").GlobalNamespace() + || dc.Function("ImplWriteActions").Class("PSWriter").GlobalNamespace() + || dc.Function("ImplWriteLineInfo").Class("PSWriter").GlobalNamespace() + || dc.Function("ImplInsert").Class("CGMBitmap").GlobalNamespace() + || dc.Function("GetNext").Class("CGMBitmap").GlobalNamespace() + || dc.Function("drawPolyLine").Class("X11SalGraphicsImpl").GlobalNamespace() + || dc.Function("testRefresh").Class("XDataPilotTable").Namespace("apitest").GlobalNamespace() + || dc.Function("testTitleManualLayoutXLSX").Class("Chart2ExportTest").GlobalNamespace() + || dc.Function("testPlotAreaManualLayoutXLSX").Class("Chart2ExportTest").GlobalNamespace() + || dc.Function("testLegendManualLayoutXLSX").Class("Chart2ExportTest").GlobalNamespace() + || dc.Function("SetScreenNumber").Class("AquaSalFrame").GlobalNamespace() + || (vclFloatDevicePixel + && (dc.Function("Justify").Class("GenericSalLayout").GlobalNamespace() + || dc.Function("AdjustLayout").Class("MultiSalLayout").GlobalNamespace())) + // vcl/headless/svpgdi.cxx, ba4a124b0c0c66fd275f5147d55eeec27ce78da9: + || dc.Function("drawAlphaBitmap").Class("SvpSalGraphics").GlobalNamespace() + || dc.Function("drawMask").Class("SvpSalGraphics").GlobalNamespace() + || dc.Function("renderSource").GlobalNamespace()) + { + return true; + } +// cout << "xxx " + function->getQualifiedNameAsString() << endl; + return false; +} + +bool isZeroConstant(ASTContext& context, const Expr* expr) +{ + if (!expr->getType()->isFloatingType()) { + return false; + } + // prevent clang crash + if (!context.getLangOpts().CPlusPlus) { + return false; + } + APValue result; + if (!expr->isCXX11ConstantExpr(context, &result)) { + return false; + } + assert(result.isFloat()); + return result.getFloat().isZero(); +} +bool FpComparison::VisitBinaryOperator(const BinaryOperator* binaryOp) +{ + if (meState != EState::TraverseProcess || ignoreLocation(binaryOp)) { + return true; + } + if (binaryOp->getOpcode() != BO_EQ && binaryOp->getOpcode() != BO_NE) { + return true; + } + // comparison with zero is valid + if (isZeroConstant(compiler.getASTContext(), binaryOp->getLHS()) + || isZeroConstant(compiler.getASTContext(), binaryOp->getRHS())) + { + return true; + } + QualType LHSStrippedType = binaryOp->getLHS()->IgnoreParenImpCasts()->getType(); + QualType RHSStrippedType = binaryOp->getRHS()->IgnoreParenImpCasts()->getType(); + if (LHSStrippedType->isFloatingType() && RHSStrippedType->isFloatingType()) { + report( + DiagnosticsEngine::Warning, "floating-point comparison", + binaryOp->getSourceRange().getBegin()) + << binaryOp->getSourceRange(); + } + return true; +} + + +loplugin::Plugin::Registration< FpComparison > X("fpcomparison", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/lclstaticfix.cxx b/compilerplugins/clang/store/lclstaticfix.cxx new file mode 100644 index 000000000..01e4171fc --- /dev/null +++ b/compilerplugins/clang/store/lclstaticfix.cxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "lclstaticfix.hxx" + +/* +This is a rewriter. + +Check all lcl_ functions and prepend static if needed. +*/ + +namespace loplugin +{ + +LclStaticFix::LclStaticFix( CompilerInstance& compiler, Rewriter& rewriter ) + : FilteringRewritePlugin( compiler, rewriter ) + { + } + +void LclStaticFix::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +bool LclStaticFix::VisitFunctionDecl( const FunctionDecl* declaration ) + { + if( ignoreLocation( declaration )) + return true; + if( declaration->isCXXClassMember()) + return true; + if( declaration->getStorageClass() == SC_Static ) + return true; + string name = declaration->getQualifiedNameAsString(); + if( name.find( "::" ) != string::npos ) + return true; + if( name.compare( 0, 4, "lcl_" ) != 0 ) + return true; + insertText( declaration->getLocStart(), "static " ); + return true; + } + +static Plugin::Registration< LclStaticFix > X( "lclstaticfix" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/lclstaticfix.hxx b/compilerplugins/clang/store/lclstaticfix.hxx new file mode 100644 index 000000000..16623edcb --- /dev/null +++ b/compilerplugins/clang/store/lclstaticfix.hxx @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include "plugin.hxx" + +namespace loplugin +{ + +class LclStaticFix + : public loplugin::FilteringRewritePlugin< LclStaticFix > + { + public: + explicit LclStaticFix( CompilerInstance& compiler, Rewriter& rewriter ); + virtual void run() override; + bool VisitFunctionDecl( const FunctionDecl* declaration ); + }; + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/manualrefcount.cxx b/compilerplugins/clang/store/manualrefcount.cxx new file mode 100644 index 000000000..c8085904f --- /dev/null +++ b/compilerplugins/clang/store/manualrefcount.cxx @@ -0,0 +1,323 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include +#include "compat.hxx" +#include "plugin.hxx" +#include "check.hxx" + +/** + Look for calls to the ref-counting methods acquire()/release(), which should only be called by classes like rtl::Reference. +*/ + +namespace { + +class ManualRefCount: + public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit ManualRefCount(InstantiationData const & data): Plugin(data) {} + + virtual void run() override + { + StringRef fn( compiler.getSourceManager().getFileEntryForID( + compiler.getSourceManager().getMainFileID())->getName() ); + + // old code, no point in updating + if (loplugin::isSamePathname(fn, SRCDIR "/store/source/store.cxx")) + return; + +// TODO ----------------------------- + if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/registry.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/regimpl.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/reflread.cxx")) + return; + // TODO MenuAttributes::CreateAttribute + if (loplugin::isSamePathname(fn, SRCDIR "/framework/source/fwe/xml/menuconfiguration.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/app/apphdl.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/core/dataaccess/ModelImpl.cxx")) + return; + // need a better replacement for vcl::EventPoster + if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/misc/acceleratorexecute.cxx")) + return; + // PostUserEvent stuff + if (loplugin::isSamePathname(fn, SRCDIR "/toolkit/source/awt/vclxwindow.cxx")) + return; + // playing games with pointers passed into combobox entries + if (loplugin::isSamePathname(fn, SRCDIR "/cui/source/customize/cfgutil.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/cui/source/customize/cfg.cxx")) + return; +// END TODO ----------------------------- + + // can't fix these without breaking stable ABI + if (fn.startswith(SRCDIR "/sal/")) + return; + if (fn.startswith(SRCDIR "/salhelper/")) + return; + if (fn.startswith(SRCDIR "/cppu/")) + return; + if (fn.startswith(SRCDIR "/cppuhelper/")) + return; + if (fn.startswith(SRCDIR "/bridges/")) + return; + + // lots of magic here + if (fn.startswith(SRCDIR "/stoc/")) + return; + if (fn.startswith(SRCDIR "/testtools/")) + return; + + // mutex games + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/app/scheduler.cxx")) + return; + // opengl games + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/app/svdata.cxx")) + return; + + // passing the pointer through PostUserEvent + if (loplugin::isSamePathname(fn, SRCDIR "/avmedia/source/gstreamer/gstplayer.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/form/fmscriptingenv.cxx")) + return; + + // thread games + if (loplugin::isSamePathname(fn, SRCDIR "/io/source/stm/opump.cxx")) + return; + + // ??? no idea what this code is up to + if (loplugin::isSamePathname(fn, SRCDIR "/extensions/source/scanner/scanunx.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/stoc/source/invocation_adapterfactory/iafactory.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/fpicker/source/office/asyncfilepicker.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/FormComponent.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/ucb/source/ucp/file/bc.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/ucb/source/ucp/file/filprp.cxx")) + return; + // calling release() ? + if (loplugin::isSamePathname(fn, SRCDIR "/toolkit/source/helper/accessibilityclient.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/misc/svtaccessiblefactory.cxx")) + return; + + // implementing css::uno::XInterface + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/animations/motionpathtag.cxx")) + return; + // UNO factory methods + if (fn.startswith(SRCDIR "/comphelper/")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/convdiclist.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/dlistimp.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/gciterator.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/lngsvcmgr.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/linguistic/source/lngopt.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/generic/gdi/gcach_xpeer.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/ui/dlg/dbwizsetup.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/ui/dlg/dbwizsetup.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lingucomponent/source/spellcheck/spell/sspellimp.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lingucomponent/source/thesaurus/libnth/nthesimp.cxx")) + return; + + + // some kind of complicated listener nonsense + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/framework/tools/FrameworkHelper.cxx")) + return; + // more listener nonsense + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/uno/unomailmerge.cxx")) + return; + // playing games with it's listener list + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/cellsuno.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/chart2uno.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/dapiuno.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/datauno.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/linkuno.cxx")) + return; + // PostUserEvent + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/vba/vbaeventshelper.cxx")) + return; + // thread holding itself + if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/EventThread.cxx")) + return; + + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool shouldVisitTemplateInstantiations () const { return true; } + + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *); + bool TraverseCXXRecordDecl(CXXRecordDecl *); + bool TraverseCXXMethodDecl(CXXMethodDecl *); + bool TraverseFunctionDecl(FunctionDecl *); + bool TraverseCXXConstructorDecl(CXXConstructorDecl *); + bool TraverseCXXDestructorDecl(CXXDestructorDecl *); + bool TraverseCXXConversionDecl(CXXConversionDecl *); + bool TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *); + bool TraverseLinkageSpecDecl(LinkageSpecDecl *); +private: + bool ignoreCallerClass(CXXRecordDecl*); +}; + +bool ManualRefCount::TraverseCXXMethodDecl(CXXMethodDecl* cxxMethodDecl) +{ + if (ignoreCallerClass(cxxMethodDecl->getParent())) + return true; + // disambiguating forwarding methods for XInterface subclasses + if (cxxMethodDecl->getIdentifier() && (cxxMethodDecl->getName() == "acquire" || cxxMethodDecl->getName() == "release")) + return true; + return RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl); +} + +bool ManualRefCount::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + auto tc = loplugin::DeclCheck(functionDecl); + if (tc.Function("make_shared_from_UNO").Namespace("comphelper").GlobalNamespace()) + return true; + return RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); +} + +bool ManualRefCount::TraverseCXXConstructorDecl(CXXConstructorDecl* cxxMethodDecl) +{ + if (ignoreCallerClass(cxxMethodDecl->getParent())) + return true; + return RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl); +} + +bool ManualRefCount::TraverseCXXDestructorDecl(CXXDestructorDecl*) +{ + // just ignore destructors, tons of places like to call acquire() on themselves in their destructor + // supposedly to prevent recursively calling the destructor + return true; +} +bool ManualRefCount::TraverseCXXConversionDecl(CXXConversionDecl* cxxMethodDecl) +{ + if (ignoreCallerClass(cxxMethodDecl->getParent())) + return true; + return RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl); +} +bool ManualRefCount::TraverseCXXRecordDecl(CXXRecordDecl* cxxRecordDecl) +{ + if (ignoreCallerClass(cxxRecordDecl)) + return true; + return RecursiveASTVisitor::TraverseCXXRecordDecl(cxxRecordDecl); +} + +bool ManualRefCount::TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl* templateDecl) +{ + if (ignoreCallerClass(templateDecl)) + return true; + return RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(templateDecl); +} + +bool ManualRefCount::TraverseLinkageSpecDecl(LinkageSpecDecl *) +{ + // ignore methods inside "extern ""C""" blocks, these are normally UNO constructors, which + // are required to raise the reference count before returning + return true; +} + +bool ManualRefCount::ignoreCallerClass(CXXRecordDecl* cxxRecordDecl) +{ + auto tc = loplugin::TypeCheck(cxxRecordDecl); + return + tc.Class("Reference").Namespace("rtl").GlobalNamespace() + || tc.Class("cow_wrapper").Namespace("o3tl").GlobalNamespace() + || tc.Class("Reference").Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace() + || tc.Class("ShareGuard").Namespace("framework").GlobalNamespace() + || tc.Class("ControlModelLock").Namespace("frm").GlobalNamespace() + || tc.Struct("ReleaseFunc").Namespace("detail").Namespace("comphelper").GlobalNamespace() + // TODO no idea what this is up to + || tc.Class("SfxModelSubComponent").GlobalNamespace() + || tc.Class("OSubComponent").Namespace("mysqlc").Namespace("connectivity").GlobalNamespace() + || tc.Class("OSubComponent").Namespace("connectivity").GlobalNamespace() + // TODO do we really need this? + || tc.Class("ShareableMutex").Namespace("framework").GlobalNamespace() + || tc.Class("ObservableThread").GlobalNamespace() + ; +} + +bool ManualRefCount::VisitCXXMemberCallExpr(const CXXMemberCallExpr* cxxMemberCallExpr) +{ + if (ignoreLocation(cxxMemberCallExpr)) + return true; + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(cxxMemberCallExpr->getLocStart()))) + return true; + + // first, use some heuristics to find the right kind of acquire()/release() calls + CXXMethodDecl const * calleeMethodDecl = cxxMemberCallExpr->getMethodDecl(); + if (!calleeMethodDecl || !calleeMethodDecl->getIdentifier()) + return true; + if (calleeMethodDecl->getName() != "acquire" && calleeMethodDecl->getName() != "release") + return true; + if (calleeMethodDecl->getNumParams() != 0) + return true; + // std::unique_ptr::release() and similar methods + if (calleeMethodDecl->getName() == "release" && loplugin::TypeCheck(calleeMethodDecl->getReturnType()).Pointer()) + return true; + + // these are OK + auto calleeRecordTC = loplugin::TypeCheck(calleeMethodDecl->getParent()); + if (calleeRecordTC.Struct("ResourceHolder").Namespace("store").GlobalNamespace()) + return true; + if (calleeRecordTC.Class("Module").Namespace("osl").GlobalNamespace()) + return true; + if (calleeRecordTC.Class("Mutex").Namespace("osl").GlobalNamespace()) + return true; + if (calleeRecordTC.Class("multi_type_vector").Namespace("mdds").GlobalNamespace()) + return true; + +// while (calleeMethodDecl->size_overridden_methods() > 0) +// calleeMethodDecl = *calleeMethodDecl->begin_overridden_methods(); +// auto tc2 = loplugin::TypeCheck(calleeMethodDecl->getParent()); +// if (tc2.Class("XInterface").Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()) +// return true; + +std::cout << calleeMethodDecl->getParent()->getQualifiedNameAsString() << std::endl; + report( + DiagnosticsEngine::Warning, "call to acquire/release", + cxxMemberCallExpr->getLocStart()) + << cxxMemberCallExpr->getSourceRange(); + return true; +} + + +loplugin::Plugin::Registration< ManualRefCount > X("manualrefcount", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/optmove.cxx b/compilerplugins/clang/store/optmove.cxx new file mode 100644 index 000000000..51b5a4b84 --- /dev/null +++ b/compilerplugins/clang/store/optmove.cxx @@ -0,0 +1,161 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "plugin.hxx" +#include "check.hxx" + +#include +#include + +/** + * This plugin is unfinished, abandoned because it did not find anything interesting. + * + * Look for variables that are + * (a) copied from + * (b) never used after the copy + * (c) have move operators + * + * The intention being to find places where we can move data (e.g. in containers) instead of copying. +*/ + +namespace +{ +class OptMove : public loplugin::FilteringPlugin +{ +public: + explicit OptMove(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + for (auto const& pair : m_Candidates) + { + //auto varDecl = pair.first; + auto candidate = pair.second; + if (!candidate.canUseExpr) + continue; + report(DiagnosticsEngine::Warning, "can std::move value instead of copy", + candidate.canUseExpr->getSourceRange().getBegin()) + << candidate.canUseExpr->getSourceRange(); + //varDecl->dump(); + } + } + + bool VisitVarDecl(const VarDecl*); + bool VisitCXXOperatorCallExpr(const CXXOperatorCallExpr*); + bool VisitDeclRefExpr(const DeclRefExpr*); + bool VisitFunctionDecl(const FunctionDecl* f) + { + if (f->getIdentifier() && f->getName() == "foo") + f->dump(); + return true; + } + +private: + struct Candidate + { + const DeclRefExpr* operatorArg1 = nullptr; + const Expr* canUseExpr = nullptr; + }; + std::map m_Candidates; +}; + +bool OptMove::VisitVarDecl(const VarDecl* varDecl) +{ + if (ignoreLocation(varDecl)) + return true; + if (varDecl->hasGlobalStorage()) + return true; + if (varDecl->getLinkageAndVisibility().getLinkage() == ExternalLinkage) + return true; + if (!varDecl->getType()->isRecordType()) + return true; + + auto cxxRecord = dyn_cast(varDecl->getType()->getAsRecordDecl()); + if (!cxxRecord || !cxxRecord->hasDefinition() || !cxxRecord->hasMoveAssignment()) + return true; + // ignore our simpler types for now, I'm after bigger game + auto typeName = cxxRecord->getName(); + if (typeName.contains("Reference") || typeName.contains("Color") || typeName.contains("VclPtr") + || typeName.contains("OString") || typeName.contains("OUString") + || typeName.contains("Rectangle") || typeName.contains("Size") + || typeName.contains("Selection") || typeName.contains("Point") + || typeName.contains("strong_int")) + return true; + m_Candidates.emplace(varDecl, Candidate()); + + if (!varDecl->hasInit()) + return true; + auto cons = dyn_cast(varDecl->getInit()); + if (!cons || !cons->getConstructor()->isCopyConstructor()) + return true; + auto arg1 = dyn_cast(cons->getArg(0)->IgnoreImplicit()); + if (!arg1) + return true; + auto varDecl1 = dyn_cast(arg1->getDecl()); + if (!varDecl1) + return true; + auto it = m_Candidates.find(varDecl1); + if (it == m_Candidates.end()) + return true; + it->second.operatorArg1 = arg1; + it->second.canUseExpr = cons; + return true; +} + +bool OptMove::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* cxxOperatorCallExpr) +{ + if (ignoreLocation(cxxOperatorCallExpr)) + return true; + auto op = cxxOperatorCallExpr->getOperator(); + if (op != OO_Equal) + return true; + auto arg0 = dyn_cast(cxxOperatorCallExpr->getArg(0)->IgnoreImplicit()); + auto arg1 = dyn_cast(cxxOperatorCallExpr->getArg(1)->IgnoreImplicit()); + if (!arg0 || !arg1) + return true; + auto varDecl0 = dyn_cast(arg0->getDecl()); + auto varDecl1 = dyn_cast(arg1->getDecl()); + if (!varDecl0 || !varDecl1) + return true; + auto cxxMethodDecl = dyn_cast_or_null(cxxOperatorCallExpr->getDirectCallee()); + if (!cxxMethodDecl || !cxxMethodDecl->isCopyAssignmentOperator()) + return true; + auto it = m_Candidates.find(varDecl1); + if (it == m_Candidates.end()) + return true; + it->second.operatorArg1 = arg1; + it->second.canUseExpr = cxxOperatorCallExpr; + return true; +} + +bool OptMove::VisitDeclRefExpr(const DeclRefExpr* declRefExpr) +{ + if (ignoreLocation(declRefExpr)) + return true; + auto varDecl = dyn_cast(declRefExpr->getDecl()); + if (!varDecl) + return true; + auto it = m_Candidates.find(varDecl); + if (it == m_Candidates.end()) + return true; + if (it->second.operatorArg1 == declRefExpr) + return true; + m_Candidates.erase(it); + return true; +} + +loplugin::Plugin::Registration noexceptmove("optmove"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/paintmethodconversion.cxx b/compilerplugins/clang/store/paintmethodconversion.cxx new file mode 100644 index 000000000..7a394ae25 --- /dev/null +++ b/compilerplugins/clang/store/paintmethodconversion.cxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "clang/Lex/Lexer.h" + +#include "plugin.hxx" +#include +#include + +/** + * Rewrites all Paint method on subclasses of vcl::Window to include RenderContext& as parameter. + * + * run as: make COMPILER_PLUGIN_TOOL=paintmethodconversion UPDATE_FILES=all FORCE_COMPILE=all + */ + +namespace +{ + +bool baseCheckNotWindowSubclass(const CXXRecordDecl* aBaseDefinition, void* /*pInput*/) +{ + if (aBaseDefinition && aBaseDefinition->getQualifiedNameAsString() == "vcl::Window") + { + return false; + } + return true; +} + +bool isDerivedFromWindow(const CXXRecordDecl* decl) { + if (!decl) + return false; + // skip vcl::Window + if (decl->getQualifiedNameAsString() == "vcl::Window") + return false; + if (!decl->forallBases(baseCheckNotWindowSubclass, nullptr, true)) + return true; + + return false; +} + +class PaintMethodConversion: public loplugin::FilteringRewritePlugin +{ +public: + explicit PaintMethodConversion(InstantiationData const& data): + FilteringRewritePlugin(data) + {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool TraverseCXXMethodDecl(const CXXMethodDecl* methodDeclaration) + { + if (!rewriter) + return true; + + if (methodDeclaration->getNameAsString() != "Paint") + return true; + + if (!isDerivedFromWindow(methodDeclaration->getParent())) + { + return true; + } + + unsigned int nNoOfParameters = methodDeclaration->getNumParams(); + + if (nNoOfParameters == 1) // we expect only one parameter Paint(Rect&) + { + const ParmVarDecl* parameterDecl = methodDeclaration->getParamDecl(0); + if (methodDeclaration->hasBody()) + { + rewriter->InsertText(parameterDecl->getLocStart(), "vcl::RenderContext& /*rRenderContext*/, ", true, true); + } + else + { + rewriter->InsertText(parameterDecl->getLocStart(), "vcl::RenderContext& rRenderContext, ", true, true); + } + } + return true; + } + +}; + +loplugin::Plugin::Registration X("paintmethodconversion", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/postfixincrementfix.cxx b/compilerplugins/clang/store/postfixincrementfix.cxx new file mode 100644 index 000000000..eba6f35b5 --- /dev/null +++ b/compilerplugins/clang/store/postfixincrementfix.cxx @@ -0,0 +1,132 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "postfixincrementfix.hxx" + +/* +This is a rewriter. + +Change all postfix ++ operators of non-trivial types to prefix if possible. +*/ + +namespace loplugin +{ + +PostfixIncrementFix::PostfixIncrementFix( const InstantiationData& data ) + : FilteringRewritePlugin( data ) + { + } + +void PostfixIncrementFix::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +bool PostfixIncrementFix::VisitCXXOperatorCallExpr( const CXXOperatorCallExpr* op ) + { + if( ignoreLocation( op )) + return true; + // postfix ++ has two arguments (the operand and the hidden extra int) + if( op->getOperator() == OO_PlusPlus && op->getNumArgs() == 2 ) + fixPostfixOperator( op ); + // For primitive types it would be UnaryOperatorExpr, but probably no good reason to change those. + return true; + } + +void PostfixIncrementFix::fixPostfixOperator( const CXXOperatorCallExpr* op ) + { + if( !canChangePostfixToPrefix( op, op )) + return; + if( !shouldDoChange( op->getArg( 0 ))) + return; + // Adding spaces around the moved ++ should not be necessary + // (there might a problem with e.g. a+b++ -> a+++b (i.e. a++ +b), + // but we don't change such expressions). + if( insertText( op->getLocStart(), "++" )) // insert is intentionally first, in case it fails + removeText( op->getCallee()->getSourceRange()); + } + +bool PostfixIncrementFix::canChangePostfixToPrefix( const Stmt* stmt , const CXXOperatorCallExpr* op ) + { + const Stmt* parent = parentStmt( stmt ); + if( parent == NULL ) + return true; + // check if foo++ can be safely replaced by ++foo + switch( parent->getStmtClass()) + { + case Stmt::CompoundStmtClass: + return true; + // these mean somebody is going to use it + case Stmt::ImplicitCastExprClass: + case Stmt::MaterializeTemporaryExprClass: + case Stmt::BinaryOperatorClass: + case Stmt::UnaryOperatorClass: + case Stmt::CallExprClass: + case Stmt::CXXOperatorCallExprClass: + return false; + case Stmt::CXXBindTemporaryExprClass: + // tricky, it may just mean the temporary will be cleaned up + // (by ExprWithCleanups), ignore and go up + return canChangePostfixToPrefix( parent, op ); + case Stmt::ExprWithCleanupsClass: + // cleanup of a temporary, should be harmless (if the use + // of the postfix ++ operator here relies on the fact that + // the dtor for the object will be called, that's pretty insane + // code). Ignore and go up. + return canChangePostfixToPrefix( parent, op ); + case Stmt::ParenExprClass: // parentheses, go up + return canChangePostfixToPrefix( parent, op ); + case Stmt::IfStmtClass: + // cannot be changed in condition, can be changed in statements + return cast< IfStmt >( parent )->getCond() != stmt; + case Stmt::WhileStmtClass: + return cast< WhileStmt >( parent )->getCond() != stmt; + case Stmt::DoStmtClass: + return cast< DoStmt >( parent )->getCond() != stmt; + case Stmt::ForStmtClass: + return cast< ForStmt >( parent )->getCond() != stmt; + default: + report( DiagnosticsEngine::Fatal, "cannot analyze operator++ (plugin needs fixing)", + op->getLocStart()) << parent->getSourceRange(); + parent->dump(); + return false; + } + } + +bool PostfixIncrementFix::shouldDoChange( const Expr* operand ) + { + // TODO Changing 'a->b++' to '++a->b' is technically the same, but the latter probably looks confusing, + // so either avoid that, or add parentheses. Avoid for now. + const Expr* expr = const_cast< Expr* >( operand )->IgnoreImplicit(); // does not have const version + switch( expr->getStmtClass()) + { + case Stmt::ParenExprClass: + return true; // there are already parentheses, ok to move the ++ + case Stmt::MemberExprClass: + return false; // ++a->b , avoid + case Stmt::DeclRefExprClass: + return true; + default: + { + report( DiagnosticsEngine::Fatal, "cannot analyze operator++ (plugin needs fixing)", + expr->getLocStart()) << operand->getSourceRange(); + expr->dump(); + operand->dump(); + return false; + } + } + } + +static Plugin::Registration< PostfixIncrementFix > X( "postfixincrementfix" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/postfixincrementfix.hxx b/compilerplugins/clang/store/postfixincrementfix.hxx new file mode 100644 index 000000000..7f496662b --- /dev/null +++ b/compilerplugins/clang/store/postfixincrementfix.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include "plugin.hxx" + +namespace loplugin +{ + +class PostfixIncrementFix + : public loplugin::FilteringRewritePlugin< PostfixIncrementFix > + { + public: + explicit PostfixIncrementFix( const InstantiationData& data ); + virtual void run() override; + bool VisitCXXOperatorCallExpr( const CXXOperatorCallExpr* op ); + private: + void fixPostfixOperator( const CXXOperatorCallExpr* op ); + void fixPostfixOperators( const Stmt* stmt ); + bool canChangePostfixToPrefix( const Stmt* stmt, const CXXOperatorCallExpr* op ); + bool shouldDoChange( const Expr* op ); + }; + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/putpoolitem.cxx b/compilerplugins/clang/store/putpoolitem.cxx new file mode 100644 index 000000000..808059997 --- /dev/null +++ b/compilerplugins/clang/store/putpoolitem.cxx @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "config_clang.h" + +#include "plugin.hxx" +#include "check.hxx" + +/** + +*/ + +namespace +{ +class PutPoolItem : public loplugin::FilteringPlugin +{ +public: + explicit PutPoolItem(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual bool preRun() override + { + // StringRef fn(handler.getMainFileName()); + // if (loplugin::isSamePathname(fn, WORKDIR "/YaccTarget/unoidl/source/sourceprovider-parser.cxx")) + // return false; + return true; + } + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr*); + bool VisitFunctionDecl(const FunctionDecl*) + { + // if (f->getIdentifier() && f->getName() == "foo") + // f->dump(); + return true; + } +}; + +bool PutPoolItem::VisitCXXMemberCallExpr(const CXXMemberCallExpr* cxxCallExpr) +{ + if (ignoreLocation(cxxCallExpr)) + return true; + auto tc = loplugin::TypeCheck(cxxCallExpr->getObjectType()); + if (!tc.Class("SfxItemSet")) + return true; + if (!cxxCallExpr->getMethodDecl()->getIdentifier() + || cxxCallExpr->getMethodDecl()->getName() != "Put") + return true; + auto argExpr = dyn_cast(cxxCallExpr->getArg(0)->IgnoreImplicit()); + if (!argExpr) + return true; + if (argExpr->getOperator() != OO_Star) + return true; + auto ptrExpr = argExpr->getArg(0)->IgnoreImplicit(); + auto tc2 = loplugin::TypeCheck(ptrExpr->getType()); + if (!tc2.Class("unique_ptr")) + return true; + // ignore calls when we are passing a copy of a member field + if (isa(ptrExpr)) + return true; + + StringRef fn = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(cxxCallExpr->getBeginLoc())); + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/app/inputwin.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/dbgui/csvgrid.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/shells/basesh.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/shells/textsh.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/xml/xmlimpit.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/shells/tabsh.cxx")) + return true; + + // argExpr->dump(); + + report(DiagnosticsEngine::Warning, "could use std::move?", cxxCallExpr->getBeginLoc()) + << cxxCallExpr->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration putpoolitem("putpoolitem", true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/refassign.cxx b/compilerplugins/clang/store/refassign.cxx new file mode 100644 index 000000000..6d8e28605 --- /dev/null +++ b/compilerplugins/clang/store/refassign.cxx @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include + +#include "check.hxx" +#include "plugin.hxx" + +/** + * Look for a mistake I made (a lot) at one point where we assign a reference to a reference var, which + * does not do at all what I thought. + */ + +namespace +{ +class RefAssign : public loplugin::FilteringPlugin +{ +public: + explicit RefAssign(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual bool preRun() override + { + StringRef fn(handler.getMainFileName()); + if (loplugin::isSamePathname(fn, SRCDIR "/comphelper/source/misc/syntaxhighlight.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/svl/source/numbers/zformat.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/tools/source/memtools/multisel.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/tools/source/generic/point.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/control/edit.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/control/fmtfield.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/control/field.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/control/field2.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/edit/textview.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/edit/vclmedit.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/editeng/source/editeng/editdoc.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/editeng/source/editeng/impedit2.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/dialog/svxruler.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/ribbar/inputwin.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/text/txtftn.cxx")) + return false; + + return true; + } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitBinaryOperator(BinaryOperator const*); + // causes crashes in CallExpr::getReturnType + bool TraverseFunctionTemplateDecl(FunctionTemplateDecl*) { return true; } + bool TraverseClassTemplateDecl(ClassTemplateDecl*) { return true; } + +private: + clang::QualType ExtractType(Expr const*); +}; + +bool RefAssign::VisitBinaryOperator(BinaryOperator const* binaryOp) +{ + if (ignoreLocation(binaryOp)) + return true; + if (binaryOp->getOpcode() != BO_Assign) + return true; + + // ignore assigning to/from an element of a collection + if (isa(binaryOp->getLHS()->IgnoreParenImpCasts())) + return true; + if (isa(binaryOp->getRHS()->IgnoreParenImpCasts())) + return true; + + // if we are assigning to a parameter we probably mean it + if (auto declRefExpr = dyn_cast(binaryOp->getLHS()->IgnoreParenImpCasts())) + if (declRefExpr->getDecl() && isa(declRefExpr->getDecl())) + return true; + + if (auto callExpr = dyn_cast(binaryOp->getRHS()->IgnoreParenImpCasts())) + if (auto functionDecl = dyn_cast_or_null(callExpr->getCalleeDecl())) + if (functionDecl->getIdentifier() + && (functionDecl->getName() == "min" || functionDecl->getName() == "max")) + return true; + + auto lhsType = ExtractType(binaryOp->getLHS()); + auto rhsType = ExtractType(binaryOp->getRHS()); + if (!loplugin::TypeCheck(lhsType).LvalueReference()) + return true; + if (!loplugin::TypeCheck(rhsType).LvalueReference()) + return true; + binaryOp->dump(); + report(DiagnosticsEngine::Warning, + "assigning a %0 to a var of type %1 probably does not do what you think", + binaryOp->getBeginLoc()) + << rhsType << lhsType << binaryOp->getSourceRange(); + return true; +} + +clang::QualType RefAssign::ExtractType(Expr const* expr) +{ + expr = expr->IgnoreParenImpCasts(); + if (auto declReflExpr = dyn_cast(expr)) + { + if (auto varDecl = dyn_cast(declReflExpr->getDecl())) + return varDecl->getType(); + } + else if (auto callExpr = dyn_cast(expr)) + { + if (callExpr->isTypeDependent()) + return {}; + // callExpr->dump(); + return callExpr->getCallReturnType(compiler.getASTContext()); + } + return expr->getType(); +} + +loplugin::Plugin::Registration refassign("refassign"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/removeforwardstringdecl.cxx b/compilerplugins/clang/store/removeforwardstringdecl.cxx new file mode 100644 index 000000000..e7a546a8f --- /dev/null +++ b/compilerplugins/clang/store/removeforwardstringdecl.cxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "removeforwardstringdecl.hxx" + +/* +This is a rewriter. + +Remove all forward declarations of rtl strings. I.e. 'namespace rtl { class OUString; }' etc. +*/ + +namespace loplugin +{ + +RemoveForwardStringDecl::RemoveForwardStringDecl( CompilerInstance& compiler, Rewriter& rewriter ) + : FilteringRewritePlugin( compiler, rewriter ) + { + } + +void RemoveForwardStringDecl::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +bool RemoveForwardStringDecl::VisitNamespaceDecl( const NamespaceDecl* declaration ) + { + if( ignoreLocation( declaration )) + return true; + if( declaration->getQualifiedNameAsString() != "rtl" ) + return true; + bool canRemove = true; + for( NamespaceDecl::decl_iterator it = declaration->decls_begin(); + it != declaration->decls_end(); + ++it ) + { + if( *it != NULL ) + { + if( !tryRemoveStringForwardDecl( *it )) + canRemove = false; + } + } + if( canRemove ) // contained only forward decls that we removed + removeText( declaration->getSourceRange(), RemoveLineIfEmpty ); + return true; + } + +bool RemoveForwardStringDecl::tryRemoveStringForwardDecl( const Decl* decl ) + { + const CXXRecordDecl* classdecl = dyn_cast< CXXRecordDecl >( decl ); + if( classdecl == NULL ) + return false; + if( !classdecl->isFreeStanding() || classdecl->isCompleteDefinition()) + return false; // not a simple forward declaration + if( classdecl->getName() == "OString" || classdecl->getName() == "OUString" + || classdecl->getName() == "OStringBuffer" || classdecl->getName() == "OUStringBuffer" + || classdecl->getName() == "OStringHash" || classdecl->getName() == "OUStringHash" + || classdecl->getName() == "OStringLiteral" || classdecl->getName() == "OUStringLiteral" ) + { + removeText( SourceRange( classdecl->getOuterLocStart(), classdecl->getLocEnd()), + RemoveLineIfEmpty | RemoveWholeStatement ); + return true; + } + return false; + } + +static Plugin::Registration< RemoveForwardStringDecl > X( "removeforwardstringdecl" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/removeforwardstringdecl.hxx b/compilerplugins/clang/store/removeforwardstringdecl.hxx new file mode 100644 index 000000000..bedd2c534 --- /dev/null +++ b/compilerplugins/clang/store/removeforwardstringdecl.hxx @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include "plugin.hxx" + +namespace loplugin +{ + +class RemoveForwardStringDecl + : public loplugin::FilteringRewritePlugin< RemoveForwardStringDecl > + { + public: + explicit RemoveForwardStringDecl( CompilerInstance& compiler, Rewriter& rewriter ); + virtual void run() override; + bool VisitNamespaceDecl( const NamespaceDecl* declaration ); + private: + bool tryRemoveStringForwardDecl( const Decl* decl ); + }; + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/removevirtuals.cxx b/compilerplugins/clang/store/removevirtuals.cxx new file mode 100644 index 000000000..1dc98304d --- /dev/null +++ b/compilerplugins/clang/store/removevirtuals.cxx @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include "plugin.hxx" +#include +#include +#include +#include +#include +#include +#include + +/** + This is intended to be run as the second stage of the "unnecessaryvirtuals" clang plugin. +*/ + +namespace { + +class RemoveVirtuals: + public loplugin::FilteringRewritePlugin +{ +public: + explicit RemoveVirtuals(InstantiationData const & data); + ~RemoveVirtuals(); + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXMethodDecl( const CXXMethodDecl* var ); +private: + // I use a brute-force approach - mmap the results file and do a linear search on it + // It works surprisingly well, because the file is small enough to fit into L2 cache on modern CPU's + size_t mmapFilesize; + int mmapFD; + char* mmappedData; +}; + +size_t getFilesize(const char* filename) +{ + struct stat st; + stat(filename, &st); + return st.st_size; +} + +RemoveVirtuals::RemoveVirtuals(InstantiationData const & data): FilteringRewritePlugin(data) +{ + static const char sInputFile[] = SRCDIR "/result.txt"; + mmapFilesize = getFilesize(sInputFile); + //Open file + mmapFD = open(sInputFile, O_RDONLY, 0); + assert(mmapFD != -1); + //Execute mmap + mmappedData = static_cast(mmap(NULL, mmapFilesize, PROT_READ, MAP_PRIVATE | MAP_POPULATE, mmapFD, 0)); + assert(mmappedData != NULL); +} + +RemoveVirtuals::~RemoveVirtuals() +{ + //Cleanup + int rc = munmap(mmappedData, mmapFilesize); + assert(rc == 0); + close(mmapFD); +} + +std::string niceName(const CXXMethodDecl* functionDecl) +{ + std::string s = + functionDecl->getParent()->getQualifiedNameAsString() + "::" + + functionDecl->getReturnType().getAsString() + "-" + + functionDecl->getNameAsString() + "("; + for (const ParmVarDecl *pParmVarDecl : functionDecl->params()) { + s += pParmVarDecl->getType().getAsString(); + s += ","; + } + s += ")"; + if (functionDecl->isConst()) { + s += "const"; + } + return s; +} + +bool RemoveVirtuals::VisitCXXMethodDecl( const CXXMethodDecl* functionDecl ) +{ + if (rewriter == nullptr) { + return true; + } + if (ignoreLocation(functionDecl)) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) { + return true; + } + + // don't mess with templates + if (functionDecl->getParent()->getDescribedClassTemplate() != nullptr) { + return true; + } + if (functionDecl->getTemplatedKind() != FunctionDecl::TK_NonTemplate) { + return true; + } + + if (!functionDecl->isVirtualAsWritten()) { + return true; + } + std::string aNiceName = "\n" + niceName(functionDecl) + "\n"; + const char *aNiceNameStr = aNiceName.c_str(); + char* found = std::search(mmappedData, mmappedData + mmapFilesize, aNiceNameStr, aNiceNameStr + strlen(aNiceNameStr)); + if(!(found < mmappedData + mmapFilesize)) { + return true; + } + if (functionDecl->isPure()) { + if (!removeText(functionDecl->getSourceRange())) { + report( + DiagnosticsEngine::Warning, + "Could not remove unused pure virtual method", + functionDecl->getLocStart()) + << functionDecl->getSourceRange(); + } + } else { + std::string aOrigText = rewriter->getRewrittenText(functionDecl->getSourceRange()); + size_t iVirtualTokenIndex = aOrigText.find_first_of("virtual "); + if (iVirtualTokenIndex == std::string::npos) { + return true; + } + if (!replaceText(functionDecl->getSourceRange(), aOrigText.replace(iVirtualTokenIndex, strlen("virtual "), ""))) { + report( + DiagnosticsEngine::Warning, + "Could not remove virtual qualifier from method", + functionDecl->getLocStart()) + << functionDecl->getSourceRange(); + } + } + return true; +} + + +loplugin::Plugin::Registration< RemoveVirtuals > X("removevirtuals", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/returnbyref.cxx b/compilerplugins/clang/store/returnbyref.cxx new file mode 100644 index 000000000..d4049481a --- /dev/null +++ b/compilerplugins/clang/store/returnbyref.cxx @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +#include "plugin.hxx" + +// Find places where we are returning a pointer to something, where we can be returning a reference. +// e.g. +// class A { +// struct X x; +// public: +// X* getX() { return &x; } +// } +// which can be: +// X& getX() { return x; } + +namespace { + +class ReturnByRef: + public loplugin::FilteringPlugin +{ +public: + explicit ReturnByRef(InstantiationData const & data): FilteringPlugin(data) {} + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXMethodDecl(const CXXMethodDecl * decl); +private: + std::string getFilename(SourceLocation loc); +}; + +bool ReturnByRef::VisitCXXMethodDecl(const CXXMethodDecl * functionDecl) { + if (ignoreLocation(functionDecl)) { + return true; + } + if (functionDecl->isVirtual()) { + return true; + } + if (!functionDecl->isInstance()) { + return true; + } + if (!functionDecl->hasBody()) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) { + return true; + } + QualType t1 { functionDecl->getReturnType() }; + if (!t1->isPointerType()) { + return true; + } + // Ignore stuff like: + // operator vcl::Window *(){ return &m_rWindow; } + if (dyn_cast< CXXConversionDecl >( functionDecl ) != nullptr) { + return true; + } + + std::string aFilename = getFilename(functionDecl->getCanonicalDecl()->getLocStart()); + if (aFilename == SRCDIR "/include/o3tl/cow_wrapper.hxx") + { + return true; + } + if ( functionDecl->getNameAsString() == "operator->") { + return true; + } + std::string aFunctionName = functionDecl->getQualifiedNameAsString(); + if (aFunctionName == "SbxValue::data") { + return true; + } + /* + std::string aParentName = functionDecl->getParent()->getQualifiedNameAsString(); + std::string fqn = aParentName + "::" + functionDecl->getNameAsString(); + if (aFilename == "TextCharAttribList::GetAttrib") { + return true; + }*/ + + /* + The AST here looks like: + -CompoundStmt + `-ReturnStmt + `-UnaryOperator + */ + + const CompoundStmt* compoundStmt = dyn_cast< CompoundStmt >( functionDecl->getBody() ); + if (compoundStmt == nullptr || compoundStmt->body_begin() == compoundStmt->body_end()) { + return true; + } + const ReturnStmt* returnStmt = dyn_cast(*compoundStmt->child_begin()); + if (returnStmt == nullptr) { + return true; + } + + const Stmt* nextStmt = dyn_cast(*returnStmt->child_begin())->IgnoreParens(); + const UnaryOperator* unaryOperator = dyn_cast(nextStmt); + if (unaryOperator == nullptr || unaryOperator->getOpcode() != UO_AddrOf) { + return true; + } +nextStmt->dump(); + report( + DiagnosticsEngine::Warning, + "rather return by reference ", + functionDecl->getSourceRange().getBegin()) + << functionDecl->getSourceRange(); + + // display the location of the class member declaration so I don't have to search for it by hand + auto otherLoc = functionDecl->getCanonicalDecl()->getSourceRange().getBegin(); + if (otherLoc != functionDecl->getSourceRange().getBegin()) + { + report( + DiagnosticsEngine::Note, + "rather return by reference", + functionDecl->getCanonicalDecl()->getSourceRange().getBegin()) + << functionDecl->getCanonicalDecl()->getSourceRange(); + } + + return true; +} + +std::string ReturnByRef::getFilename(SourceLocation loc) +{ + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(loc); + return getFilenameOfLocation(spellingLocation); +} + +loplugin::Plugin::Registration< ReturnByRef > X("returnbyref"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/returnunique.cxx b/compilerplugins/clang/store/returnunique.cxx new file mode 100644 index 000000000..913c043a4 --- /dev/null +++ b/compilerplugins/clang/store/returnunique.cxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Find places where a std::unique_ptr is release()'ed and returned as a raw +// pointer. Some occurrences of that might better be rewritten to return the +// unique_ptr is returned directly. (But other occurrences might be fine the +// way they are, hence place this plugin into store/). + +#include +#include "plugin.hxx" + +namespace { + +class ReturnUnique: + public loplugin::FilteringPlugin +{ +public: + explicit ReturnUnique(InstantiationData const & data): FilteringPlugin(data) {} + + void run() override { + if (compiler.getLangOpts().CPlusPlus) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitReturnStmt(ReturnStmt const * stmt); +}; + +bool ReturnUnique::VisitReturnStmt(ReturnStmt const * stmt) { + if (ignoreLocation(stmt)) { + return true; + } + auto const e1 = stmt->getRetValue(); + if (e1 == nullptr) { + return true; + } + auto const e2 = dyn_cast(e1->IgnoreParenImpCasts()); + if (e2 == nullptr) { + return true; + } + auto const d1 = e2->getMethodDecl(); + if (d1 == nullptr) { // call via ptr to member + return true; + } + auto const d2 = d1->getParent(); + assert(d2 != nullptr); + assert(d2->getParent() != nullptr); + auto const d3 = dyn_cast(d2->getParent()); + if (d3 == nullptr + /* || dyn_cast(d3->getParent()) == nullptr */) + { + return true; + } + auto const id3 = d3->getIdentifier(); + if (id3 == nullptr /* || id3->getName() != "std" */) { + return true; + } + auto const id2 = d2->getIdentifier(); + if (id2 == nullptr || id2->getName() != "unique_ptr") { + return true; + } + auto const id1 = d1->getIdentifier(); + if (id1 == nullptr || id1->getName() != "release") { + return true; + } + report( + DiagnosticsEngine::Warning, "return std::unique_ptr::release", + e2->getLocStart()) + << stmt->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration X("returnunique"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/revisibility.cxx b/compilerplugins/clang/store/revisibility.cxx new file mode 100644 index 000000000..727d7094a --- /dev/null +++ b/compilerplugins/clang/store/revisibility.cxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "plugin.hxx" + +// Find function declarations that redundantly re-specify a visibility attribute +// (via SAL_DLLPUBLIC_EXPORT etc.) that was already specified with a previous +// declaration of that function. But MSVC wants consistency of __declspec +// across friend declarations, so just ignore those for now. + +namespace { + +bool hasExplicitVisibilityAttr(Decl const * decl) { + VisibilityAttr const * attr = decl->getAttr(); + return attr != nullptr && !attr->isInherited(); +} + +bool isFriendDecl(Decl const * decl) { + return decl->getFriendObjectKind() != Decl::FOK_None; +} + +class ReVisibility: + public loplugin::FilteringPlugin +{ +public: + explicit ReVisibility(InstantiationData const & data): FilteringPlugin(data) {} + + void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitFunctionDecl(FunctionDecl const * decl); +}; + +bool ReVisibility::VisitFunctionDecl(FunctionDecl const * decl) { + if (!ignoreLocation(decl) && hasExplicitVisibilityAttr(decl) + && !isFriendDecl(decl)) + { + Decl const * first = nullptr; + for (Decl const * p = decl;;) { + p = p->getPreviousDecl(); + if (p == nullptr) { + break; + } + first = p; + if (hasExplicitVisibilityAttr(p) && !isFriendDecl(p)) { + report( + DiagnosticsEngine::Warning, + "Redundant visibility re-declaration", + decl->getAttr()->getLocation()) + << decl->getAttr()->getRange(); + report( + DiagnosticsEngine::Note, + "Previous visibility declaration is here", + p->getAttr()->getLocation()) + << p->getAttr()->getRange(); + return true; + } + } + if (decl->isThisDeclarationADefinition() && first != nullptr + && !(getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc( + decl->getLocation())) + .startswith(SRCDIR "/libreofficekit/"))) + { + report( + DiagnosticsEngine::Warning, + "Visibility declaration on definition, not first declaration", + decl->getAttr()->getLocation()) + << decl->getAttr()->getRange(); + report( + DiagnosticsEngine::Note, "First declaration is here", + first->getLocation()) + << first->getSourceRange(); + } + } + return true; +} + +loplugin::Plugin::Registration X("revisibility"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/rtlconstasciimacro.cxx b/compilerplugins/clang/store/rtlconstasciimacro.cxx new file mode 100644 index 000000000..c930fbfd1 --- /dev/null +++ b/compilerplugins/clang/store/rtlconstasciimacro.cxx @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +/* +This is a rewriter. + +Remove uses of the macro RTL_CONSTASCII_USTRINGPARAM. One run is for one +specific use (see below), modify source to remove other uses. +*/ + +#include "plugin.hxx" + +#include + +namespace loplugin +{ + +class RtlConstAsciiMacro + : public loplugin::FilteringRewritePlugin< RtlConstAsciiMacro > + , public PPCallbacks + { + public: + explicit RtlConstAsciiMacro( const InstantiationData& data ); + virtual void run() override; + bool VisitCXXConstructExpr( CXXConstructExpr* expr ); + bool VisitCXXTemporaryObjectExpr( CXXTemporaryObjectExpr* expr ); + bool VisitStringLiteral( const StringLiteral* literal ); + virtual void MacroExpands( const Token& macro, const MacroDirective* directive, + SourceRange range, const MacroArgs* args ) override; + enum { isPPCallback = true }; + private: + map< SourceLocation, SourceLocation > expansions; // start location -> end location + bool searchingForString; + bool suitableString; + }; + +RtlConstAsciiMacro::RtlConstAsciiMacro( const InstantiationData& data ) + : FilteringRewritePlugin( data ) + , searchingForString( false ) + { + compiler.getPreprocessor().addPPCallbacks( this ); + } + +void RtlConstAsciiMacro::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +void RtlConstAsciiMacro::MacroExpands( const Token& macro, const MacroDirective*, + SourceRange range, const MacroArgs* ) + { + if( macro.getIdentifierInfo()->getName() != "RTL_CONSTASCII_USTRINGPARAM" ) + return; + expansions[ range.getBegin() ] = range.getEnd(); + } + +/* Remove use with the following ctor: + OUString( const char * value, sal_Int32 length, + rtl_TextEncoding encoding, + sal_uInt32 convertFlags = OSTRING_TO_OUSTRING_CVTFLAGS ) + This means searching for CXXConstructExpr. + For removal when used with functions it should check e.g. for CallExpr. +*/ +bool RtlConstAsciiMacro::VisitCXXConstructExpr( CXXConstructExpr* expr ) + { + if( ignoreLocation( expr )) + return true; + if( expr->getNumArgs() != 4 ) + return true; + // The last argument should be the default one when the macro is used. + if( dyn_cast< CXXDefaultArgExpr >( expr->getArg( 3 )) == NULL ) + return true; + if( expr->getConstructor()->getQualifiedNameAsString() != "rtl::OUString::OUString" ) + return true; + const SourceManager& src = compiler.getSourceManager(); + SourceLocation start = src.getExpansionLoc( expr->getArg( 0 )->getLocStart()); + // Macro fills in the first 3 arguments, so they must all come from the same expansion. + if( start != src.getExpansionLoc( expr->getArg( 2 )->getLocEnd())) + return true; + if( expansions.find( start ) == expansions.end()) + return true; + SourceLocation end = expansions[ start ]; + // Remove the location, since sometimes the same code may be processed more than once + // (e.g. non-trivial default arguments). + expansions.erase( start ); + // Check if the string argument to the macro is suitable. + searchingForString = true; + suitableString = false; + TraverseStmt( expr->getArg( 0 )); + searchingForString = false; + if( !suitableString ) + return true; + // Search for '(' (don't just remove a given length to handle possible whitespace). + const char* text = compiler.getSourceManager().getCharacterData( start ); + const char* pos = text; + while( *pos != '(' ) + ++pos; + ++pos; + if( text[ -1 ] == ' ' && *pos == ' ' ) + ++pos; // do not leave two spaces + removeText( start, pos - text, RemoveLineIfEmpty ); + const char* textend = compiler.getSourceManager().getCharacterData( end ); + if( textend[ -1 ] == ' ' && textend[ 1 ] == ' ' ) + removeText( end, 2, RemoveLineIfEmpty ); // Remove ') '. + else + removeText( end, 1, RemoveLineIfEmpty ); // Remove ')'. + return true; + } + +bool RtlConstAsciiMacro::VisitCXXTemporaryObjectExpr( CXXTemporaryObjectExpr* expr ) + { + return VisitCXXConstructExpr( expr ); + } + +bool RtlConstAsciiMacro::VisitStringLiteral( const StringLiteral* literal ) + { + if( !searchingForString ) + return true; + if( suitableString ) // two string literals? + { + report( DiagnosticsEngine::Warning, "cannot analyze RTL_CONSTASCII_USTRINGPARAM (plugin needs fixing)" ) + << literal->getSourceRange(); + return true; + } + if( !literal->isAscii()) // ignore + return true; + if( !literal->containsNonAsciiOrNull()) + suitableString = true; + return true; + } + +static Plugin::Registration< RtlConstAsciiMacro > X( "rtlconstasciimacro" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/sfxitemsetrewrite.cxx b/compilerplugins/clang/store/sfxitemsetrewrite.cxx new file mode 100644 index 000000000..e1fa52209 --- /dev/null +++ b/compilerplugins/clang/store/sfxitemsetrewrite.cxx @@ -0,0 +1,419 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#include "check.hxx" +#include "plugin.hxx" + +namespace { + +bool gap(APSInt n1, APSInt n2) { return n1 < n2 && n2 - n1 > 1; } + +class Visitor final: + public loplugin::FilteringRewritePlugin +{ +public: + explicit Visitor(InstantiationData const & data): FilteringRewritePlugin(data) {} + + bool VisitCXXConstructExpr(CXXConstructExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto const ctor = expr->getConstructor(); + if (!loplugin::DeclCheck(ctor->getParent()).Class("SfxItemSet") + .GlobalNamespace()) + { + return true; + } + auto const numParams = ctor->getNumParams(); + auto const variadic = ctor->isVariadic(); + if (!(((numParams == 3 && !variadic) || (numParams == 4 && variadic)) + && (loplugin::TypeCheck(ctor->getParamDecl(0)->getType()) + .LvalueReference().Class("SfxItemPool").GlobalNamespace()))) + { + return true; + } + auto const numArgs = expr->getNumArgs(); + if (numArgs < 3) { + report( + DiagnosticsEngine::Warning, + ("unexpected SfxItemPool constructor call with less than three" + " arguments"), + expr->getExprLoc()) + << expr->getSourceRange(); + return true; + } + rewrite(expr, variadic, false, numArgs, expr->getArgs()); + return true; + } + + bool VisitCallExpr(CallExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto const dre = dyn_cast( + expr->getCallee()->IgnoreParenImpCasts()); + if (dre == nullptr + || !(loplugin::DeclCheck(dre->getDecl()).Function("make_unique") + .Namespace("o3tl").GlobalNamespace())) + { + return true; + } + auto const numTArgs = dre->getNumTemplateArgs(); + if (numTArgs == 0) { + report( + DiagnosticsEngine::Warning, + "unexpected o3tl::make_unique call without template arguments", + expr->getExprLoc()) + << expr->getSourceRange(); + return true; + } + auto const tArg0 = dre->getTemplateArgs()[0].getArgument(); + if (tArg0.getKind() != TemplateArgument::Type) { + report( + DiagnosticsEngine::Warning, + ("unexpected o3tl::make_unique call with non-type first" + " template argument"), + expr->getExprLoc()) + << expr->getSourceRange(); + return true; + } + if (!loplugin::TypeCheck(tArg0.getAsType()).Class("SfxItemSet") + .GlobalNamespace()) + { + return true; + } + auto const numArgs = expr->getNumArgs(); + if (numArgs < 3) { + return true; + } + rewrite(expr, numArgs > 3, true, numArgs, expr->getArgs()); + return true; + } + + bool VisitTemplateSpecializationTypeLoc( + TemplateSpecializationTypeLoc typeLoc) + { + auto const loc = typeLoc.getBeginLoc(); + if (loc.isInvalid() || ignoreLocation(loc)) { + return true; + } + if (!loplugin::TypeCheck(typeLoc.getType()).Struct("Items") + .Namespace("svl").GlobalNamespace()) + { + return true; + } + unsigned const numArgs = typeLoc.getNumArgs(); + if (numArgs == 0) { + report( + DiagnosticsEngine::Warning, + ("unexpected svl::Items specialization with zero template" + " arguments"), + loc) + << typeLoc.getSourceRange(); + return true; + } + if (numArgs % 2 == 1) { + report( + DiagnosticsEngine::Warning, + ("unexpected svl::Items specialization with odd number of" + " template arguments"), + loc) + << typeLoc.getSourceRange(); + return true; + } + std::vector ranges; + auto good = true; + APSInt prev; + for (unsigned i = 0; i != numArgs; ++i) { + auto const argLoc = typeLoc.getArgLoc(i); + auto const & arg = argLoc.getArgument(); + APSInt v; + switch (arg.getKind()) { + case TemplateArgument::Integral: + v = arg.getAsIntegral(); + break; + case TemplateArgument::Expression: + if (arg.getAsExpr()->EvaluateAsInt(v, compiler.getASTContext())) + { + break; + } + // [[fallthrough]]; + default: + report( + DiagnosticsEngine::Warning, + ("unexpected svl::Items specialization with non-integral" + " template argument %0"), + argLoc.getLocation()) + << (i + 1) + << typeLoc.getSourceRange(); + return true; + } + if (i % 2 == 0) { + good = good && (i == 0 || gap(prev, v)); + } else { + if (v < prev) { + report( + DiagnosticsEngine::Warning, + ("unexpected svl::Items specialization with template" + " argument %0 smaller than previous one, %1 < %2"), + argLoc.getLocation()) + << (i + 1) << v.toString(10) << prev.toString(10) + << typeLoc.getSourceRange(); + return true; + } + ranges.emplace_back(prev, v, (i / 2) + 1); + } + prev = v; + } + if (good) { + return true; + } + std::ostringstream buf1; + for (auto const i: ranges) { + buf1 << "\n "; + printBegin(buf1, typeLoc, i); + buf1 << " ... "; + printEnd(buf1, typeLoc, i); + } + std::sort(ranges.begin(), ranges.end()); + std::ostringstream buf2; + for (auto i = ranges.begin(); i != ranges.end();) { + buf2 << "\n "; + printBegin(buf2, typeLoc, *i); + buf2 << " ... "; + auto end = *i; + for (;;) { + auto j = i + 1; + if (j == ranges.end() || gap(get<1>(end), get<0>(*j))) { + printEnd(buf2, typeLoc, end); + i = j; + break; + } + if (get<1>(*j) >= get<1>(end)) { + end = *j; + } + i = j; + } + } + report( + DiagnosticsEngine::Warning, + ("reorder svl::Items specialization template arguments from:%0\nto:" + "%1"), + loc) + << buf1.str() << buf2.str() << typeLoc.getSourceRange(); + return true; + } + +private: + void run() override { + if (compiler.getLangOpts().CPlusPlus) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + SourceLocation nextToken(SourceLocation loc) { + return loc.getLocWithOffset( + Lexer::MeasureTokenLength( + loc, compiler.getSourceManager(), compiler.getLangOpts())); + } + + SourceLocation atMacroExpansionStart(SourceLocation loc) { + while (loc.isMacroID() + && (compiler.getSourceManager() + .isAtStartOfImmediateMacroExpansion(loc, &loc))) + {} + return loc; + } + + SourceLocation atMacroExpansionEnd(SourceLocation loc) { + while (compiler.getSourceManager().isMacroBodyExpansion(loc)) { + loc = compiler.getSourceManager().getImmediateExpansionRange(loc) + .second; + } + return loc; + } + + using Range = std::tuple; + + void printSource( + std::ostringstream & s, TemplateSpecializationTypeLoc typeLoc, Range r, + bool end) + { + auto const argLoc = typeLoc.getArgLoc( + 2 * (get<2>(r) - 1) + (end ? 1 : 0)); + auto const src1 = argLoc.getSourceRange(); + auto const src2 = SourceRange( + atMacroExpansionStart(src1.getBegin()), + Lexer::getLocForEndOfToken( + compiler.getSourceManager().getExpansionLoc( + atMacroExpansionEnd(src1.getEnd())), + 0, compiler.getSourceManager(), compiler.getLangOpts())); + s << " '" << Lexer::getSourceText( + Lexer::getAsCharRange( + src2, compiler.getSourceManager(), compiler.getLangOpts()), + compiler.getSourceManager(), compiler.getLangOpts()).str() + << "'"; + } + + void printBegin( + std::ostringstream & s, TemplateSpecializationTypeLoc typeLoc, Range r) + { + s << get<2>(r) << "B: " << get<0>(r).toString(10); + printSource(s, typeLoc, r, false); + } + + void printEnd( + std::ostringstream & s, TemplateSpecializationTypeLoc typeLoc, Range r) + { + s << get<2>(r) << "E: " << get<1>(r).toString(10); + printSource(s, typeLoc, r, true); + } + + void rewrite( + Expr const * expr, bool variadic, bool forward, unsigned numArgs, + Expr const * const * args) + { + bool constant = true; + unsigned firstZero = 0; + for (unsigned i = 1; i != numArgs; ++i) { + auto const arg = args[i]; + constant = constant + && arg->isCXX11ConstantExpr(compiler.getASTContext()); + APSInt v; + auto const zero + = ((arg->EvaluateAsInt(v, compiler.getASTContext()) + && v == 0) + || (variadic && i > 4 + && arg->isNullPointerConstant( + compiler.getASTContext(), + Expr::NPC_ValueDependentIsNotNull))); + if (variadic) { + if (zero) { + if (firstZero == 0) { + if (i == 1) { + report( + DiagnosticsEngine::Warning, + ("unexpected missing non-zero arguments before" + " first zero argument in SfxItemPool" + " constructor call"), + arg->getExprLoc()) + << expr->getSourceRange(); + return; + } + if (i % 2 == 0) { + report( + DiagnosticsEngine::Warning, + ("unexpected odd number of potentially non-zero" + " arguments before first definitely zero" + " argument in SfxItemPool constructor call"), + arg->getExprLoc()) + << expr->getSourceRange(); + return; + } + firstZero = i; + } + } else if (firstZero != 0) { + report( + DiagnosticsEngine::Warning, + ("unexpected potentially non-zero argument in" + " SfxItemPool constructor call, following zero" + " argument"), + arg->getExprLoc()) + << expr->getSourceRange(); + return; + } + } else if (zero) { + report( + DiagnosticsEngine::Warning, + "unexpected zero argument in SfxItemPool constructor call", + arg->getExprLoc()) + << expr->getSourceRange(); + return; + } + } + if (variadic && firstZero == 0) { + report( + DiagnosticsEngine::Warning, + ("unexpected SfxItemPool constructor call with no detectable" + " zero arguments"), + expr->getExprLoc()) + << expr->getSourceRange(); + return; + } + if (rewriter != nullptr) { + if (!insertTextBefore( + atMacroExpansionStart(args[1]->getLocStart()), + (constant + ? StringRef("svl::Items<") + : (forward + ? StringRef("std::initializer_list{{") + : StringRef("{{"))))) + { + goto failed; + } + auto const postLoc = atMacroExpansionEnd( + args[numArgs - 1]->getLocEnd()); + auto const postStr = constant ? StringRef(">{}") : StringRef("}}"); + if (variadic) { + //TODO: the replaced range can contain relevant comments: + if (!replaceText( + SourceRange( + nextToken( + atMacroExpansionEnd( + args[firstZero - 1]->getLocEnd())), + postLoc), + postStr)) + { + goto failed; + } + } else { + if (!insertTextAfterToken(postLoc, postStr)) { + goto failed; + } + } + if (!constant && variadic) { + for (unsigned i = 2; i != firstZero - 1; ++i) { + auto const arg = args[i]; + if (!(i % 2 == 0 + ? insertTextAfterToken( + atMacroExpansionEnd(arg->getLocEnd()), "}") + : insertTextBefore( + atMacroExpansionStart(arg->getLocStart()), "{"))) + { + goto failed; + } + } + } + return; + } + failed: //TODO: undo partial changes + report( + DiagnosticsEngine::Warning, + ("rewrite SfxItemPool constructor call with" + " %select{%select{|std::initializer_list}1" + "%{%{..., ...%}, ..., %{..., ...%}%}|svl::Items<...>%{%}}0 around" + " the %select{|leading }2%3 WID arguments%select{| and remove the" + " remaining %4 zero %plural{1:argument|:arguments}4}2"), + expr->getExprLoc()) + << constant << forward << variadic + << (variadic ? firstZero - 1 : numArgs - 1) << (numArgs - firstZero) + << expr->getSourceRange(); + } +}; + +static loplugin::Plugin::Registration reg("sfxitemsetrewrite",true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/store/simplifybool.cxx b/compilerplugins/clang/store/simplifybool.cxx new file mode 100644 index 000000000..973ab6a7a --- /dev/null +++ b/compilerplugins/clang/store/simplifybool.cxx @@ -0,0 +1,1333 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include "plugin.hxx" +#include "clang/AST/CXXInheritance.h" + +namespace { + +// Like clang::Stmt::IgnoreImplicit (lib/AST/Stmt.cpp), but also looking through implicit +// UserDefinedConversion's member function call: +Expr const * ignoreAllImplicit(Expr const * expr) { + if (auto const e = dyn_cast(expr)) { + expr = e->getSubExpr(); + } + if (auto const e = dyn_cast(expr)) { + expr = e->getSubExpr(); + } + if (auto const e = dyn_cast(expr)) { + expr = e->getSubExpr(); + } + while (auto const e = dyn_cast(expr)) { + expr = e->getSubExpr(); + if (e->getCastKind() == CK_UserDefinedConversion) { + auto const ce = cast(expr); + assert(ce->getNumArgs() == 0); + expr = ce->getImplicitObjectArgument(); + } + } + return expr; +} + +Expr const * ignoreParenImpCastAndComma(Expr const * expr) { + for (;;) { + expr = expr->IgnoreParenImpCasts(); + auto e = dyn_cast(expr); + if (e == nullptr || e->getOpcode() != BO_Comma) { + return expr; + } + expr = e->getRHS(); + } +} + +Expr const * getSubExprOfLogicalNegation(Expr const * expr) { + auto e = dyn_cast(ignoreParenImpCastAndComma(expr)); + return e == nullptr || e->getOpcode() != UO_LNot + ? nullptr : e->getSubExpr(); +} + +clang::Type const * stripConstRef(clang::Type const * type) { + auto lvalueType = dyn_cast(type); + if (!lvalueType) + return type; + return lvalueType->getPointeeType()->getUnqualifiedDesugaredType(); +} + +bool isCompatibleTypeForOperator(clang::Type const * paramType, CXXRecordDecl const * argRecordDecl) { + paramType = stripConstRef(paramType); + auto paramRecordType = dyn_cast(paramType); + if (!paramRecordType) + return false; + CXXRecordDecl const * paramRecordDecl = dyn_cast(paramRecordType->getDecl()); + if (!paramRecordDecl) + return false; + return argRecordDecl == paramRecordDecl || argRecordDecl->isDerivedFrom(paramRecordDecl); +} + +FunctionDecl const * findMemberOperator(CXXRecordDecl const * recordDecl, OverloadedOperatorKind ooOpcode, CXXRecordDecl const * rhs) { + for (auto it = recordDecl->method_begin(); it != recordDecl->method_end(); ++it) { + if (it->getOverloadedOperator() == ooOpcode) { + if (it->getNumParams() == 1 && isCompatibleTypeForOperator(it->getParamDecl(0)->getType().getTypePtr(), rhs)) + return *it; + } + } + return nullptr; +} + +// Magic value to indicate we assume this operator exists +static FunctionDecl const * const ASSUME_OPERATOR_EXISTS = reinterpret_cast(-1); + +// Search for an operator with matching parameter types; while this may miss some operators with +// odd parameter types that would actually be used by the compiler, it is overall better to have too +// many false negatives (i.e., miss valid loplugin:simplifybool warnings) than false positives here: +FunctionDecl const * findOperator(CompilerInstance& compiler, BinaryOperator::Opcode opcode, clang::Type const * lhsType, clang::Type const * rhsType) { + auto lhsRecordType = dyn_cast(lhsType); + if (!lhsRecordType) + return nullptr; + auto rhsRecordType = dyn_cast(rhsType); + if (!rhsRecordType) + return nullptr; + CXXRecordDecl const * lhsRecordDecl = dyn_cast(lhsRecordType->getDecl()); + if (!lhsRecordDecl) + return nullptr; + CXXRecordDecl const * rhsRecordDecl = dyn_cast(rhsRecordType->getDecl()); + if (!rhsRecordDecl) + return nullptr; + + auto ctx = lhsRecordDecl->getCanonicalDecl()->getDeclContext(); + + /* + It looks the clang Sema::LookupOverloadedOperatorName is the chunk of functionality I need, + but I have no idea how to call it from here. + Actually finding the right standard library operators requires doing conversions and other funky stuff. + For now, just assume that standard library operators are well-behaved, and have negated operators. + */ + if (ctx->isStdNamespace()) + return ASSUME_OPERATOR_EXISTS; + if (auto namespaceDecl = dyn_cast(ctx)) { + // because, of course, half the standard library is not "in the standard namespace" + if (namespaceDecl->getName() == "__gnu_debug") + return ASSUME_OPERATOR_EXISTS; + } + + // search for member overloads + // (using the hard way here because DeclContext::lookup does not work for member operators) + auto ooOpcode = BinaryOperator::getOverloadedOperator(opcode); + FunctionDecl const * foundFunction = findMemberOperator(lhsRecordDecl, ooOpcode, rhsRecordDecl); + if (foundFunction) + return foundFunction; + auto ForallBasesCallback = [&](const CXXRecordDecl *baseCXXRecordDecl) + { + if (baseCXXRecordDecl->isInvalidDecl()) + return false; + foundFunction = findMemberOperator(baseCXXRecordDecl, ooOpcode, rhsRecordDecl); + return false; + }; + + lhsRecordDecl->forallBases(ForallBasesCallback); + if (foundFunction) + return foundFunction; + + // search for free function overloads + if (ctx->getDeclKind() == Decl::LinkageSpec) { + ctx = ctx->getParent(); + } + auto operatorDeclName = compiler.getASTContext().DeclarationNames.getCXXOperatorName(ooOpcode); + auto res = ctx->lookup(operatorDeclName); + for (auto d = res.begin(); d != res.end(); ++d) { + FunctionDecl const * f = dyn_cast(*d); + if (!f || f->getNumParams() != 2) + continue; + if (!isCompatibleTypeForOperator(f->getParamDecl(0)->getType().getTypePtr(), lhsRecordDecl)) + continue; + if (!isCompatibleTypeForOperator(f->getParamDecl(1)->getType().getTypePtr(), rhsRecordDecl)) + continue; + return f; + } + return nullptr; +} + +enum class Value { Unknown, False, True }; + +Value getValue(Expr const * expr) { + expr = ignoreParenImpCastAndComma(expr); + if (expr->getType()->isBooleanType()) { + // Instead going via Expr::isCXX11ConstantExpr would turn up exactly one + // additional place in svx/source/dialog/framelinkarray.cxx + // + // const bool DIAG_DBL_CLIP_DEFAULT = false; + // ... + // ... = mxImpl.get() ? mxImpl->mbDiagDblClip : DIAG_DBL_CLIP_DEFAULT; + // + // where it is unclear whether it is not actually better to consider + // DIAG_DBL_CLIP_DEFAULT a tunable parameter (and thus not to simplify): + auto lit = dyn_cast(expr); + if (lit != nullptr) { + return lit->getValue() ? Value::True : Value::False; + } + } + return Value::Unknown; +} + +class SimplifyBool: + public loplugin::FilteringPlugin +{ +public: + explicit SimplifyBool(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + void run() override; + + bool VisitUnaryOperator(UnaryOperator const * expr); + + bool VisitBinaryOperator(BinaryOperator const * expr); + + bool VisitConditionalOperator(ConditionalOperator const * expr); + + bool TraverseFunctionDecl(FunctionDecl *); + + bool TraverseCXXMethodDecl(CXXMethodDecl *); + +private: + bool visitBinLT(BinaryOperator const * expr); + + bool visitBinGT(BinaryOperator const * expr); + + bool visitBinLE(BinaryOperator const * expr); + + bool visitBinGE(BinaryOperator const * expr); + + bool visitBinEQ(BinaryOperator const * expr); + + bool visitBinNE(BinaryOperator const * expr); + + FunctionDecl* m_insideFunctionDecl = nullptr; +}; + +void SimplifyBool::run() { + if (compiler.getLangOpts().CPlusPlus) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } +} + +bool SimplifyBool::VisitUnaryOperator(UnaryOperator const * expr) { + if (expr->getOpcode() != UO_LNot) { + return true; + } + if (ignoreLocation(expr)) { + return true; + } + auto e = getSubExprOfLogicalNegation(expr->getSubExpr()); + if (e) { + // Ignore macros, otherwise + // OSL_ENSURE(!b, ...); + // triggers. + if (e->getBeginLoc().isMacroID()) + return true; + // double logical not of an int is an idiom to convert to bool + auto const sub = ignoreAllImplicit(e); + if (!sub->getType()->isBooleanType()) + return true; + report( + DiagnosticsEngine::Warning, + ("double logical negation expression of the form '!!A' (with A of type" + " %0) can %select{logically|literally}1 be simplified as 'A'"), + expr->getBeginLoc()) + << sub->getType() + << sub->getType()->isBooleanType() + << expr->getSourceRange(); + return true; + } + auto sub = expr->getSubExpr()->IgnoreParenImpCasts(); + auto reversed = false; + if (auto const rewritten = dyn_cast(sub)) { + if (rewritten->isReversed()) { + if (rewritten->getOperator() == BO_EQ) { + auto const sem = rewritten->getSemanticForm(); + bool match; + if (auto const op1 = dyn_cast(sem)) { + match = op1->getOpcode() == BO_EQ; + } else if (auto const op2 = dyn_cast(sem)) { + match = op2->getOperator() == OO_EqualEqual; + } else { + match = false; + } + if (match) { + sub = sem; + reversed = true; + } + } + } + } + if (auto binaryOp = dyn_cast(sub)) { + // Ignore macros, otherwise + // OSL_ENSURE(!b, ...); + // triggers. + if (binaryOp->getBeginLoc().isMacroID()) + return true; + if (binaryOp->isComparisonOp()) + { + auto t = binaryOp->getLHS()->IgnoreImpCasts()->getType()->getUnqualifiedDesugaredType(); + if (t->isTemplateTypeParmType() || t->isDependentType() || t->isRecordType()) + return true; + // for floating point (with NaN) !(x=y + if (t->isFloatingType() || + binaryOp->getRHS()->IgnoreImpCasts()->getType()->getUnqualifiedDesugaredType()->isFloatingType()) + return true; + report( + DiagnosticsEngine::Warning, + ("logical negation of comparison operator, can be simplified by inverting operator"), + expr->getBeginLoc()) + << expr->getSourceRange(); + } + else if (binaryOp->isLogicalOp()) + { + // if we find a negation condition inside, it is definitely better + // to expand it out + bool foundLNot = false; + auto containsNegationOrComparison = [&](Expr const * expr) { + expr = ignoreParenImpCastAndComma(expr); + if (auto unaryOp = dyn_cast(expr)) + if (unaryOp->getOpcode() == UO_LNot) + { + foundLNot = true; + return expr; + } + if (auto binaryOp = dyn_cast(expr)) + if (binaryOp->isComparisonOp()) + return expr; + if (auto cxxOpCall = dyn_cast(expr)) + if (cxxOpCall->isComparisonOp()) + return expr; + return (Expr const*)nullptr; + }; + auto lhs = containsNegationOrComparison(binaryOp->getLHS()); + auto rhs = containsNegationOrComparison(binaryOp->getRHS()); + if (foundLNot || (lhs && rhs)) + report( + DiagnosticsEngine::Warning, + ("logical negation of logical op containing negation, can be simplified"), + binaryOp->getBeginLoc()) + << binaryOp->getSourceRange(); + } + } + if (auto binaryOp = dyn_cast(sub)) { + // Ignore macros, otherwise + // OSL_ENSURE(!b, ...); + // triggers. + if (binaryOp->getBeginLoc().isMacroID()) + return true; + auto op = binaryOp->getOperator(); + // Negating things like > and >= would probably not be wise, there is no guarantee the negation holds for operator overloaded types. + // However, == and != are normally considered ok. + if (!(op == OO_EqualEqual || op == OO_ExclaimEqual)) + return true; + BinaryOperator::Opcode negatedOpcode = BinaryOperator::negateComparisonOp(BinaryOperator::getOverloadedOpcode(op)); + auto lhs = binaryOp->getArg(reversed ? 1 : 0)->IgnoreImpCasts()->getType()->getUnqualifiedDesugaredType(); + auto rhs = binaryOp->getArg(reversed ? 0 : 1)->IgnoreImpCasts()->getType()->getUnqualifiedDesugaredType(); + auto const negOp = findOperator(compiler, negatedOpcode, lhs, rhs); + if (!negOp) + return true; + // if we are inside a similar operator, ignore, eg. operator!= is often defined by calling !operator== + if (m_insideFunctionDecl && m_insideFunctionDecl->getNumParams() >= 1) { + auto t = stripConstRef(m_insideFunctionDecl->getParamDecl(0)->getType().getTypePtr()); + if (t == lhs) + return true; + } + // QA code + StringRef fn(handler.getMainFileName()); + if (loplugin::isSamePathname(fn, SRCDIR "/testtools/source/bridgetest/bridgetest.cxx")) + return true; + report( + DiagnosticsEngine::Warning, + ("logical negation of comparison operator, can be simplified by inverting operator"), + expr->getBeginLoc()) + << expr->getSourceRange(); + if (negOp != ASSUME_OPERATOR_EXISTS) + report( + DiagnosticsEngine::Note, "the presumed corresponding negated operator for %0 and %1 is declared here", + negOp->getLocation()) + << binaryOp->getArg(reversed ? 1 : 0)->IgnoreImpCasts()->getType() + << binaryOp->getArg(reversed ? 0 : 1)->IgnoreImpCasts()->getType() + << negOp->getSourceRange(); + } + return true; +} + +bool SimplifyBool::VisitBinaryOperator(BinaryOperator const * expr) { + switch (expr->getOpcode()) { + case BO_LT: + return visitBinLT(expr); + case BO_GT: + return visitBinGT(expr); + case BO_LE: + return visitBinLE(expr); + case BO_GE: + return visitBinGE(expr); + case BO_EQ: + return visitBinEQ(expr); + case BO_NE: + return visitBinNE(expr); + default: + return true; + } +} + +bool SimplifyBool::visitBinLT(BinaryOperator const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (!(expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType() + && expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType())) + { + return true; + } + auto v1 = getValue(expr->getLHS()); + auto v2 = getValue(expr->getRHS()); + switch (v1) { + case Value::Unknown: + switch (v2) { + case Value::Unknown: + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("less-than expression of the form 'A < false' (with A of type" + " %0) can logically be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getLHS()->IgnoreImpCasts()->getType() + << expr->getSourceRange(); + break; + case Value::True: + { + auto e = getSubExprOfLogicalNegation(expr->getLHS()); + if (e == nullptr) { + report( + DiagnosticsEngine::Warning, + ("less-than expression of the form 'A < true' (with A" + " of type %0) can %select{logically|literally}1 be" + " simplified as '!A'"), + expr->getBeginLoc()) + << expr->getLHS()->IgnoreImpCasts()->getType() + << (expr->getLHS()->IgnoreImpCasts()->getType() + ->isBooleanType()) + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, + ("less-than expression of the form '!A < true' (with A" + " of type %0) can %select{logically|literally}1 be" + " simplified as 'A'"), + expr->getBeginLoc()) + << e->IgnoreImpCasts()->getType() + << e->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + } + break; + } + } + break; + case Value::False: + switch (v2) { + case Value::Unknown: + report( + DiagnosticsEngine::Warning, + ("less-than expression of the form 'false < A' (with A of type" + " %0) can %select{logically|literally}1 be simplified as 'A'"), + expr->getBeginLoc()) + << expr->getRHS()->IgnoreImpCasts()->getType() + << expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("less-than expression of the form 'false < false' can" + " literally be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("less-than expression of the form 'false < true' can" + " literally be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + } + break; + case Value::True: + switch (v2) { + case Value::Unknown: + report( + DiagnosticsEngine::Warning, + ("less-than expression of the form 'true < A' (with A of type" + " %0) can logically be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getRHS()->IgnoreImpCasts()->getType() + << expr->getSourceRange(); + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("less-than expression of the form 'true < false' can" + " literally be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("less-than expression of the form 'true < true' can" + " literally be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + } + break; + } + return true; +} + +bool SimplifyBool::visitBinGT(BinaryOperator const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (!(expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType() + && expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType())) + { + return true; + } + auto v1 = getValue(expr->getLHS()); + auto v2 = getValue(expr->getRHS()); + switch (v1) { + case Value::Unknown: + switch (v2) { + case Value::Unknown: + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("greater-than expression of the form 'A > false' (with A of" + " type %0) can %select{logically|literally}1 be simplified as" + " 'A'"), + expr->getBeginLoc()) + << expr->getLHS()->IgnoreImpCasts()->getType() + << expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("greater-than expression of the form 'A > true' (with A of" + " type %0) can logically be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getLHS()->IgnoreImpCasts()->getType() + << expr->getSourceRange(); + break; + } + break; + case Value::False: + switch (v2) { + case Value::Unknown: + report( + DiagnosticsEngine::Warning, + ("greater-than expression of the form 'false > A' (with A of" + " type %0) can logically be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getRHS()->IgnoreImpCasts()->getType() + << expr->getSourceRange(); + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("greater-than expression of the form 'false > false' can" + " literally be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("greater-than expression of the form 'false > true' can" + " literally be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + } + break; + case Value::True: + switch (v2) { + case Value::Unknown: + { + auto e = getSubExprOfLogicalNegation(expr->getRHS()); + if (e == nullptr) { + report( + DiagnosticsEngine::Warning, + ("greater-than expression of the form 'true > A' (with" + " A of type %0) can %select{logically|literally}1 be" + " simplified as '!A'"), + expr->getBeginLoc()) + << expr->getRHS()->IgnoreImpCasts()->getType() + << (expr->getRHS()->IgnoreImpCasts()->getType() + ->isBooleanType()) + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, + ("greater-than expression of the form 'true > !A' (with" + " A of type %0) can %select{logically|literally}1 be" + " simplified as 'A'"), + expr->getBeginLoc()) + << e->IgnoreImpCasts()->getType() + << e->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + } + break; + } + case Value::False: + report( + DiagnosticsEngine::Warning, + ("greater-than expression of the form 'true > false' can" + " literally be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("greater-than expression of the form 'true > true' can" + " literally be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + } + break; + } + return true; +} + +bool SimplifyBool::visitBinLE(BinaryOperator const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (!(expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType() + && expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType())) + { + return true; + } + auto v1 = getValue(expr->getLHS()); + auto v2 = getValue(expr->getRHS()); + switch (v1) { + case Value::Unknown: + switch (v2) { + case Value::Unknown: + break; + case Value::False: + { + auto e = getSubExprOfLogicalNegation(expr->getLHS()); + if (e == nullptr) { + report( + DiagnosticsEngine::Warning, + ("less-than-or-equal-to expression of the form 'A <=" + " false' (with A of type %0) can" + " %select{logically|literally}1 be simplified as" + " '!A'"), + expr->getBeginLoc()) + << expr->getLHS()->IgnoreImpCasts()->getType() + << (expr->getLHS()->IgnoreImpCasts()->getType() + ->isBooleanType()) + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, + ("less-than-or-equal-to expression of the form '!A <=" + " false' (with A of type %0) can" + " %select{logically|literally}1 be simplified as 'A'"), + expr->getBeginLoc()) + << e->IgnoreImpCasts()->getType() + << e->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + } + break; + } + case Value::True: + report( + DiagnosticsEngine::Warning, + ("less-than-or-equal-to expression of the form 'A <= true'" + " (with A of type %0) can logically be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getLHS()->IgnoreImpCasts()->getType() + << expr->getSourceRange(); + break; + } + break; + case Value::False: + switch (v2) { + case Value::Unknown: + report( + DiagnosticsEngine::Warning, + ("less-than-or-equal-to expression of the form 'false <= A'" + " (with A of type %0) can logically be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getRHS()->IgnoreImpCasts()->getType() + << expr->getSourceRange(); + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("less-than-or-equal-to expression of the form 'false <= false'" + " can literally be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("less-than-or-equal-to expression of the form 'false <= true'" + " can literally be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + } + break; + case Value::True: + switch (v2) { + case Value::Unknown: + report( + DiagnosticsEngine::Warning, + ("less-than-or-equal-to expression of the form 'true <= A'" + " (with A of type %0) can %select{logically|literally}1 be" + " simplified as 'A'"), + expr->getBeginLoc()) + << expr->getRHS()->IgnoreImpCasts()->getType() + << expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("less-than-or-equal-to expression of the form 'true <= false'" + " can literally be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("less-than-or-equal-to expression of the form 'true <= true'" + " can literally be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + } + break; + } + return true; +} + +bool SimplifyBool::visitBinGE(BinaryOperator const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (!(expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType() + && expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType())) + { + return true; + } + auto v1 = getValue(expr->getLHS()); + auto v2 = getValue(expr->getRHS()); + switch (v1) { + case Value::Unknown: + switch (v2) { + case Value::Unknown: + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("greater-than-or-equal-to expression of the form 'A >= false'" + " (with A of type %0) can logically be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getLHS()->IgnoreImpCasts()->getType() + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("greater-than-or-equal-to expression of the form 'A >= true'" + " (with A of type %0) can %select{logically|literally}1 be" + " simplified as 'A'"), + expr->getBeginLoc()) + << expr->getLHS()->IgnoreImpCasts()->getType() + << expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + break; + } + break; + case Value::False: + switch (v2) { + case Value::Unknown: + { + auto e = getSubExprOfLogicalNegation(expr->getRHS()); + if (e == nullptr) { + report( + DiagnosticsEngine::Warning, + ("greater-than-or-equal-to expression of the form" + " 'false >= A' (with A of type %0) can" + " %select{logically|literally}1 be simplified as" + " '!A'"), + expr->getBeginLoc()) + << expr->getRHS()->IgnoreImpCasts()->getType() + << (expr->getRHS()->IgnoreImpCasts()->getType() + ->isBooleanType()) + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, + ("greater-than-or-equal-to expression of the form" + " 'false >= !A' (with A of type %0) can" + " %select{logically|literally}1 be simplified as 'A'"), + expr->getBeginLoc()) + << e->IgnoreImpCasts()->getType() + << e->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + } + break; + } + case Value::False: + report( + DiagnosticsEngine::Warning, + ("greater-than-or-equal-to expression of the form 'false >=" + " false' can literally be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("greater-than-or-equal-to expression of the form 'false >=" + " true' can literally be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + } + break; + case Value::True: + switch (v2) { + case Value::Unknown: + report( + DiagnosticsEngine::Warning, + ("greater-than-or-equal-to expression of the form 'true >= A'" + " (with A of type %0) can logically be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getRHS()->IgnoreImpCasts()->getType() + << expr->getSourceRange(); + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("greater-than-or-equal-to expression of the form 'true >=" + " false' can literally be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("greater-than-or-equal-to expression of the form 'true >=" + " true' can literally be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + } + break; + } + return true; +} + +bool SimplifyBool::visitBinEQ(BinaryOperator const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (!(expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType() + && expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType())) + { + return true; + } + auto v1 = getValue(expr->getLHS()); + auto v2 = getValue(expr->getRHS()); + switch (v1) { + case Value::Unknown: + switch (v2) { + case Value::Unknown: + break; + case Value::False: + { + auto e = getSubExprOfLogicalNegation(expr->getLHS()); + if (e == nullptr) { + report( + DiagnosticsEngine::Warning, + ("equal-to expression of the form 'A == false' (with A" + " of type %0) can %select{logically|literally}1 be" + " simplified as '!A'"), + expr->getBeginLoc()) + << expr->getLHS()->IgnoreImpCasts()->getType() + << (expr->getLHS()->IgnoreImpCasts()->getType() + ->isBooleanType()) + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, + ("equal-to expression of the form '!A == false' (with A" + " of type %0) can %select{logically|literally}1 be" + " simplified as 'A'"), + expr->getBeginLoc()) + << e->IgnoreImpCasts()->getType() + << e->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + } + break; + } + case Value::True: + report( + DiagnosticsEngine::Warning, + ("equal-to expression of the form 'A == true' (with A of type" + " %0) can %select{logically|literally}1 be simplified as 'A'"), + expr->getBeginLoc()) + << expr->getLHS()->IgnoreImpCasts()->getType() + << expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + break; + } + break; + case Value::False: + switch (v2) { + case Value::Unknown: + { + auto e = getSubExprOfLogicalNegation(expr->getRHS()); + if (e == nullptr) { + report( + DiagnosticsEngine::Warning, + ("equal-to expression of the form 'false == A' (with A" + " of type %0) can %select{logically|literally}1 be" + " simplified as '!A'"), + expr->getBeginLoc()) + << expr->getRHS()->IgnoreImpCasts()->getType() + << (expr->getRHS()->IgnoreImpCasts()->getType() + ->isBooleanType()) + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, + ("equal-to expression of the form 'false == !A' (with A" + " of type %0) can %select{logically|literally}1 be" + " simplified as 'A'"), + expr->getBeginLoc()) + << e->IgnoreImpCasts()->getType() + << e->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + } + break; + } + case Value::False: + report( + DiagnosticsEngine::Warning, + ("equal-to expression of the form 'false == false' can" + " literally be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("equal-to expression of the form 'false == true' can" + " literally be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + } + break; + case Value::True: + switch (v2) { + case Value::Unknown: + report( + DiagnosticsEngine::Warning, + ("equal-to expression of the form 'true == A' (with A of type" + " %0) can %select{logically|literally}1 be simplified as 'A'"), + expr->getBeginLoc()) + << expr->getRHS()->IgnoreImpCasts()->getType() + << expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("equal-to expression of the form 'true == false' can" + " literally be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("equal-to expression of the form 'true == true' can" + " literally be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + } + break; + } + return true; +} + +bool SimplifyBool::visitBinNE(BinaryOperator const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (!(expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType() + && expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType())) + { + return true; + } + auto v1 = getValue(expr->getLHS()); + auto v2 = getValue(expr->getRHS()); + switch (v1) { + case Value::Unknown: + switch (v2) { + case Value::Unknown: + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("not-equal-to expression of the form 'A != false' (with A of" + " type %0) can %select{logically|literally}1 be simplified as" + " 'A'"), + expr->getBeginLoc()) + << expr->getLHS()->IgnoreImpCasts()->getType() + << expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + break; + case Value::True: + { + auto e = getSubExprOfLogicalNegation(expr->getLHS()); + if (e == nullptr) { + report( + DiagnosticsEngine::Warning, + ("not-equal-to expression of the form 'A != true' (with" + " A of type %0) can %select{logically|literally}1 be" + " simplified as '!A'"), + expr->getBeginLoc()) + << expr->getLHS()->IgnoreImpCasts()->getType() + << (expr->getLHS()->IgnoreImpCasts()->getType() + ->isBooleanType()) + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, + ("not-equal-to expression of the form '!A != true'" + " (with A of type %0) can" + " %select{logically|literally}1 be simplified as 'A'"), + expr->getBeginLoc()) + << e->IgnoreImpCasts()->getType() + << e->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + } + break; + } + } + break; + case Value::False: + switch (v2) { + case Value::Unknown: + report( + DiagnosticsEngine::Warning, + ("not-equal-to expression of the form 'false != A' (with A of" + " type %0) can %select{logically|literally}1 be simplified as" + " 'A'"), + expr->getBeginLoc()) + << expr->getRHS()->IgnoreImpCasts()->getType() + << expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("not-equal-to expression of the form 'false != false' can" + " literally be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("not-equal-to expression of the form 'false != true' can" + " literally be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + } + break; + case Value::True: + switch (v2) { + case Value::Unknown: + { + auto e = getSubExprOfLogicalNegation(expr->getRHS()); + if (e == nullptr) { + report( + DiagnosticsEngine::Warning, + ("not-equal-to expression of the form 'true != A' (with" + " A of type %0) can %select{logically|literally}1 be" + " simplified as '!A'"), + expr->getBeginLoc()) + << expr->getRHS()->IgnoreImpCasts()->getType() + << (expr->getRHS()->IgnoreImpCasts()->getType() + ->isBooleanType()) + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, + ("not-equal-to expression of the form 'true != !A'" + " (with A of type %0) can" + " %select{logically|literally}1 be simplified as 'A'"), + expr->getBeginLoc()) + << e->IgnoreImpCasts()->getType() + << e->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + } + break; + } + case Value::False: + report( + DiagnosticsEngine::Warning, + ("not-equal-to expression of the form 'true != false' can" + " literally be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("not-equal-to expression of the form 'true != true' can" + " literally be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getSourceRange(); + break; + } + break; + } + return true; +} + +bool SimplifyBool::VisitConditionalOperator(ConditionalOperator const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto v1 = getValue(expr->getTrueExpr()); + auto v2 = getValue(expr->getFalseExpr()); + switch (v1) { + case Value::Unknown: + switch (v2) { + case Value::Unknown: + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("conditional expression of the form 'A ? B : false' (with A of" + " type %0 and B of type %1) can %select{logically|literally}2" + " be simplified as 'A && B'"), + expr->getBeginLoc()) + << expr->getCond()->IgnoreImpCasts()->getType() + << expr->getTrueExpr()->IgnoreImpCasts()->getType() + << ((expr->getCond()->IgnoreImpCasts()->getType() + ->isBooleanType()) + && (expr->getTrueExpr()->IgnoreImpCasts()->getType() + ->isBooleanType())) + << expr->getSourceRange(); + break; + case Value::True: + { + auto e = getSubExprOfLogicalNegation(expr->getCond()); + if (e == nullptr) { + report( + DiagnosticsEngine::Warning, + ("conditional expression of the form 'A ? B : true'" + " (with A of type %0 and B of type %1) can" + " %select{logically|literally}2 be simplified as '!A" + " || B'"), + expr->getBeginLoc()) + << expr->getCond()->IgnoreImpCasts()->getType() + << expr->getTrueExpr()->IgnoreImpCasts()->getType() + << ((expr->getCond()->IgnoreImpCasts()->getType() + ->isBooleanType()) + && (expr->getTrueExpr()->IgnoreImpCasts()->getType() + ->isBooleanType())) + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, + ("conditional expression of the form '!A ? B : true'" + " (with A of type %0 and B of type %1) can" + " %select{logically|literally}2 be simplified as 'A ||" + " B'"), + expr->getBeginLoc()) + << e->IgnoreImpCasts()->getType() + << expr->getTrueExpr()->IgnoreImpCasts()->getType() + << (e->IgnoreImpCasts()->getType()->isBooleanType() + && (expr->getTrueExpr()->IgnoreImpCasts() + ->getType()->isBooleanType())) + << expr->getSourceRange(); + } + break; + } + } + break; + case Value::False: + switch (v2) { + case Value::Unknown: + { + auto e = getSubExprOfLogicalNegation(expr->getCond()); + if (e == nullptr) { + report( + DiagnosticsEngine::Warning, + ("conditional expression of the form 'A ? false : B'" + " (with A of type %0 and B of type %1) can" + " %select{logically|literally}2 be simplified as '!A" + " && B'"), + expr->getBeginLoc()) + << expr->getCond()->IgnoreImpCasts()->getType() + << expr->getFalseExpr()->IgnoreImpCasts()->getType() + << ((expr->getCond()->IgnoreImpCasts()->getType() + ->isBooleanType()) + && (expr->getFalseExpr()->IgnoreImpCasts() + ->getType()->isBooleanType())) + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, + ("conditional expression of the form '!A ? false : B'" + " (with A of type %0 and B of type %1) can" + " %select{logically|literally}2 be simplified as 'A &&" + " B'"), + expr->getBeginLoc()) + << e->IgnoreImpCasts()->getType() + << expr->getFalseExpr()->IgnoreImpCasts()->getType() + << (e->IgnoreImpCasts()->getType()->isBooleanType() + && (expr->getFalseExpr()->IgnoreImpCasts() + ->getType()->isBooleanType())) + << expr->getSourceRange(); + } + break; + } + case Value::False: + report( + DiagnosticsEngine::Warning, + ("conditional expression of the form 'A ? false : false' (with" + " A of type %0) can logically be simplified as 'false'"), + expr->getBeginLoc()) + << expr->getCond()->IgnoreImpCasts()->getType() + << expr->getSourceRange(); + break; + case Value::True: + { + auto e = getSubExprOfLogicalNegation(expr->getCond()); + if (e == nullptr) { + report( + DiagnosticsEngine::Warning, + ("conditional expression of the form 'A ? false : true'" + " (with A of type %0) can" + " %select{logically|literally}1 be simplified as" + " '!A'"), + expr->getBeginLoc()) + << expr->getCond()->IgnoreImpCasts()->getType() + << (expr->getCond()->IgnoreImpCasts()->getType() + ->isBooleanType()) + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, + ("conditional expression of the form '!A ? false :" + " true' (with A of type %0) can" + " %select{logically|literally}1 be simplified as 'A'"), + expr->getBeginLoc()) + << e->IgnoreImpCasts()->getType() + << e->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + } + break; + } + } + break; + case Value::True: + switch (v2) { + case Value::Unknown: + report( + DiagnosticsEngine::Warning, + ("conditional expression of the form 'A ? true : B' (with A of" + " type %0 and B of type %1) can %select{logically|literally}2" + " be simplified as 'A || B'"), + expr->getBeginLoc()) + << expr->getCond()->IgnoreImpCasts()->getType() + << expr->getFalseExpr()->IgnoreImpCasts()->getType() + << ((expr->getCond()->IgnoreImpCasts()->getType() + ->isBooleanType()) + && (expr->getFalseExpr()->IgnoreImpCasts()->getType() + ->isBooleanType())) + << expr->getSourceRange(); + break; + case Value::False: + report( + DiagnosticsEngine::Warning, + ("conditional expression of the form 'A ? true : false' (with A" + " of type %0) can %select{logically|literally}1 be simplified" + " as 'A'"), + expr->getBeginLoc()) + << expr->getCond()->IgnoreImpCasts()->getType() + << expr->getCond()->IgnoreImpCasts()->getType()->isBooleanType() + << expr->getSourceRange(); + break; + case Value::True: + report( + DiagnosticsEngine::Warning, + ("conditional expression of the form 'A ? true : true' (with A" + " of type %0) can logically be simplified as 'true'"), + expr->getBeginLoc()) + << expr->getCond()->IgnoreImpCasts()->getType() + << expr->getSourceRange(); + break; + } + break; + } + return true; +} + +bool SimplifyBool::TraverseFunctionDecl(FunctionDecl * functionDecl) { + auto copy = m_insideFunctionDecl; + m_insideFunctionDecl = functionDecl; + bool ret = RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); + m_insideFunctionDecl = copy; + return ret; +} + +bool SimplifyBool::TraverseCXXMethodDecl(CXXMethodDecl * functionDecl) { + auto copy = m_insideFunctionDecl; + m_insideFunctionDecl = functionDecl; + bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(functionDecl); + m_insideFunctionDecl = copy; + return ret; +} + +loplugin::Plugin::Registration X("simplifybool"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/stdexception.cxx b/compilerplugins/clang/store/stdexception.cxx new file mode 100644 index 000000000..47a7d5791 --- /dev/null +++ b/compilerplugins/clang/store/stdexception.cxx @@ -0,0 +1,188 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#include "plugin.hxx" + +namespace { + +bool isStdException(QualType type) { + //TODO: + std::string name { type.getAsString() }; + return name == "std::exception" || name == "::std::exception"; +} + +class StdException: + public loplugin::FilteringRewritePlugin +{ +public: + explicit StdException(InstantiationData const & data): FilteringRewritePlugin(data) + {} + + virtual void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXMethodDecl(CXXMethodDecl const * decl); +}; + +bool StdException::VisitCXXMethodDecl(CXXMethodDecl const * decl) { + if (ignoreLocation(decl) + || decl->begin_overridden_methods() == decl->end_overridden_methods()) + { + return true; + } + CXXMethodDecl const * over = nullptr; + for (auto i = decl->begin_overridden_methods(); + i != decl->end_overridden_methods(); ++i) + { + FunctionProtoType const * t + = (*i)->getType()->getAs(); + switch (t->getExceptionSpecType()) { + case EST_None: + continue; + case EST_DynamicNone: + case EST_BasicNoexcept: + return true; + case EST_Dynamic: + { + unsigned n = t->getNumExceptions(); + for (unsigned j = 0; j != n; ++j) { + if (isStdException(t->getExceptionType(j))) { + over = *i; + goto found; + } + } + return true; + } + case EST_ComputedNoexcept: + switch (t->getNoexceptSpec(compiler.getASTContext())) { + case FunctionProtoType::NR_NoNoexcept: + case FunctionProtoType::NR_BadNoexcept: + assert(false); + // fall through + case FunctionProtoType::NR_Dependent: + break; + case FunctionProtoType::NR_Throw: + continue; + case FunctionProtoType::NR_Nothrow: + return true; + } + case EST_MSAny: + case EST_Unevaluated: + case EST_Uninstantiated: + continue; //TODO??? + } + } + return true; +found: + FunctionProtoType const * t = decl->getType()->getAs(); + if (!t->hasDynamicExceptionSpec()) { + report( + DiagnosticsEngine::Warning, + "override does not have dynamic exception specification", + decl->getLocStart()) + << decl->getSourceRange(); + report( + DiagnosticsEngine::Note, + ("overridden declaration with dynamic exception specification" + " including std::exception is here"), + over->getLocStart()); + return true; + } + unsigned n = t->getNumExceptions(); + for (unsigned i = 0; i != n; ++i) { + if (isStdException(t->getExceptionType(i))) { + return true; + } + } + SourceRange r { decl->getSourceRange() }; + SourceLocation l { + compiler.getSourceManager().getExpansionLoc(r.getBegin()) }; + SourceLocation end { + compiler.getSourceManager().getExpansionLoc(r.getEnd()) }; + assert( + l == end + || compiler.getSourceManager().isBeforeInTranslationUnit(l, end)); + bool seenThrow = false; + unsigned parens = 0; + SourceLocation openParen; + SourceLocation loc; + for (;;) { + unsigned n = Lexer::MeasureTokenLength( + l, compiler.getSourceManager(), compiler.getLangOpts()); + std::string s { compiler.getSourceManager().getCharacterData(l), n }; + if (s == "{" || s == ";") { + break; + } + if (!seenThrow) { + if (s == "throw") { + seenThrow = true; + } + } else if (s == "(") { + assert(parens < std::numeric_limits::max()); + ++parens; + if (parens == 1) { + openParen = l; + } + loc = l; + } else if (s == ")") { + assert(parens != 0); + --parens; + if (parens == 0) { + assert(loc.isValid()); + // Only rewrite declarations in include files if a definition is + // also seen, to avoid compilation of a definition (in a main + // file only processed later) to fail with a "mismatch" error + // before the rewriter had a chance to act upon the definition + // (but use the heuristic of assuming pure virtual functions do + // not have definitions): + if (rewriter != nullptr + && (compiler.getSourceManager().isInMainFile( + compiler.getSourceManager().getSpellingLoc(loc)) + || decl->isDefined() || decl->isPure()) + && insertTextAfterToken( + loc, + (loc == openParen + ? "std::exception" : ", std::exception"))) + { + return true; + } + break; + } + loc = l; + } else if (!s.empty() && s.compare(0, 2, "/*") != 0 + && s.compare(0, 2, "//") != 0) + { + loc = l; + } + if (l == end) { + break; + } + l = l.getLocWithOffset(std::max(n, 1)); + } + report( + DiagnosticsEngine::Warning, + "override dropped std::exception from dynamic exception specification", + openParen.isValid() ? openParen : decl->getLocStart()) + << decl->getSourceRange(); + report( + DiagnosticsEngine::Note, "overridden declaration is here", + over->getLocStart()); + return true; +} + +loplugin::Plugin::Registration X("stdexception", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/stringbuffer.cxx b/compilerplugins/clang/store/stringbuffer.cxx new file mode 100644 index 000000000..899c9b6ac --- /dev/null +++ b/compilerplugins/clang/store/stringbuffer.cxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "plugin.hxx" +#include + +/** Look for appending result of adding OUString/OString to OUStringBuffer + */ +namespace +{ +class StringBuffer : public loplugin::FilteringPlugin +{ +public: + explicit StringBuffer(loplugin::InstantiationData const& rData) + : FilteringPlugin(rData) + { + } + + bool preRun() override + { + StringRef fn(handler.getMainFileName()); + return !loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/"); + } + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitCXXMemberCallExpr(CXXMemberCallExpr const*); +}; + +bool StringBuffer::VisitCXXMemberCallExpr(CXXMemberCallExpr const* memberCallExpr) +{ + if (ignoreLocation(memberCallExpr)) + return true; + if (!loplugin::DeclCheck(memberCallExpr->getRecordDecl()) + .Class("OUStringBuffer") + .Namespace("rtl") + .GlobalNamespace()) + return true; + if (!memberCallExpr->getMethodDecl()->getIdentifier()) + return true; + if (memberCallExpr->getMethodDecl()->getName() != "append") + return true; + auto matTemp = dyn_cast(memberCallExpr->getArg(0)); + if (!matTemp) + return true; + if (!isa(matTemp->getSubExpr())) + return true; + report(DiagnosticsEngine::Warning, + "appending added result of OUString to OUStringBuffer, rather do .append(x).append(y)", + memberCallExpr->getBeginLoc()) + << memberCallExpr->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration stringbuffer("stringbuffer", false); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/stylepolice.cxx b/compilerplugins/clang/store/stylepolice.cxx new file mode 100644 index 000000000..d3b2e8a44 --- /dev/null +++ b/compilerplugins/clang/store/stylepolice.cxx @@ -0,0 +1,196 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#include "plugin.hxx" + +// Check for some basic naming mismatches which make the code harder to read +// +// This plugin is deliberately fairly lax, and only targets the most egregeriously faulty code, +// since we have a broad range of styles in our code and we don't want to generate unnecessary +// churn. + +namespace { + +class StylePolice : + public loplugin::FilteringPlugin +{ +public: + explicit StylePolice(InstantiationData const & data): FilteringPlugin(data) {} + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitVarDecl(const VarDecl *); +private: + StringRef getFilename(SourceLocation loc); +}; + +StringRef StylePolice::getFilename(SourceLocation loc) +{ + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(loc); + StringRef name { getFilenameOfLocation(spellingLocation) }; + return name; +} + +bool startswith(const std::string& rStr, const char* pSubStr) { + return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; +} +bool isUpperLetter(char c) { + return c >= 'A' && c <= 'Z'; +} +bool isLowerLetter(char c) { + return c >= 'a' && c <= 'z'; +} +bool isIdentifierLetter(char c) { + return isUpperLetter(c) || isLowerLetter(c); +} +bool matchPointerVar(const std::string& s) { + return s.size() > 2 && s[0] == 'p' && isUpperLetter(s[1]); +} +bool matchRefCountedPointerVar(const std::string& s) { + return s.size() > 2 && s[0] == 'x' && isUpperLetter(s[1]); +} +bool matchMember(const std::string& s) { + return s.size() > 3 && s[0] == 'm' + && ( ( strchr("abnprsx", s[1]) && isUpperLetter(s[2]) ) + || ( s[1] == '_' && isIdentifierLetter(s[2]) ) ); +} + +bool StylePolice::VisitVarDecl(const VarDecl * varDecl) +{ + if (ignoreLocation(varDecl)) { + return true; + } + StringRef aFileName = getFilename(varDecl->getLocStart()); + std::string name = varDecl->getName(); + + if (!varDecl->isLocalVarDecl()) { + return true; + } + + if (matchMember(name)) + { + // these names appear to be taken from some scientific paper + if (aFileName == SRCDIR "/scaddins/source/analysis/bessel.cxx" ) { + } + // lots of places where we are storing a "method id" here + else if (aFileName.startswith(SRCDIR "/connectivity/source/drivers/jdbc") && name.compare(0,3,"mID") == 0) { + } + else { + report( + DiagnosticsEngine::Warning, + "this local variable follows our member field naming convention, which is confusing", + varDecl->getLocation()) + << varDecl->getType() << varDecl->getSourceRange(); + } + } + + QualType qt = varDecl->getType().getDesugaredType(compiler.getASTContext()).getCanonicalType(); + qt = qt.getNonReferenceType(); + std::string typeName = qt.getAsString(); + if (startswith(typeName, "const ")) + typeName = typeName.substr(6); + if (startswith(typeName, "class ")) + typeName = typeName.substr(6); + if (startswith(typeName, "struct ")) + typeName = typeName.substr(7); + std::string aOriginalTypeName = varDecl->getType().getAsString(); + if (startswith(aOriginalTypeName, "const ")) + aOriginalTypeName = aOriginalTypeName.substr(6); + + if (!qt->isPointerType() && !qt->isArrayType() && !qt->isFunctionPointerType() && !qt->isMemberPointerType() + && matchPointerVar(name) + && !startswith(typeName, "boost::intrusive_ptr") + && !startswith(typeName, "std::optional") + && !startswith(typeName, "boost::shared_ptr") + && !startswith(typeName, "com::sun::star::uno::Reference") + && !startswith(typeName, "cppu::OInterfaceIteratorHelper") + && !startswith(typeName, "formula::FormulaCompiler::CurrentFactor") + && aOriginalTypeName != "GLXPixmap" + && !startswith(typeName, "rtl::Reference") + && !startswith(typeName, "ScopedVclPtr") + && typeName.find("::mem_fun") == std::string::npos + && typeName.find("shared_ptr") == std::string::npos + && typeName.find("unique_ptr") == std::string::npos + && typeName.find("::weak_ptr") == std::string::npos + && !startswith(typeName, "_LOKDocViewPrivate") + && !startswith(typeName, "sw::UnoCursorPointer") + && !startswith(typeName, "tools::SvRef") + && !startswith(typeName, "VclPtr") + && !startswith(typeName, "vcl::ScopedBitmapAccess") + // lots of the code seems to regard iterator objects as being "pointer-like" + && typeName.find("iterator<") == std::string::npos + && typeName.find("iter<") == std::string::npos + // libc++ std::__1::__wrap_iter<...> + && aOriginalTypeName != "sal_IntPtr" ) + { + if (aFileName.startswith(SRCDIR "/bridges/") ) { + } else if (aFileName.startswith(SRCDIR "/vcl/source/fontsubset/sft.cxx") ) { + } else { + report( + DiagnosticsEngine::Warning, + "this local variable of type '%0' follows our pointer naming convention, but it is not a pointer, %1", + varDecl->getLocation()) + << typeName << aOriginalTypeName << varDecl->getSourceRange(); + } + } + + + if (matchRefCountedPointerVar(name) + && !startswith(typeName, "boost::intrusive_ptr") + && !startswith(typeName, "com::sun::star::uno::Reference") + && !startswith(typeName, "com::sun::star::uno::Sequence") + && !startswith(typeName, "com::sun::star::uno::WeakReference") + && !startswith(typeName, "drawinglayer::primitive2d::Primitive2DContainer") + && !startswith(typeName, "drawinglayer::primitive3d::Primitive3DContainer") + && !startswith(typeName, "jfw::CXPathObjectPtr") + && !startswith(typeName, "_LOKDocViewPrivate") + && !startswith(typeName, "oox::dump::BinaryInputStreamRef") + && !startswith(typeName, "oox::drawingml::chart::ModelRef") + && !startswith(typeName, "rtl::Reference") + && !startswith(typeName, "Reference") + && !startswith(typeName, "SfxObjectShellLock") + && !startswith(typeName, "store::PageHolderObject") + && !startswith(typeName, "store::ResourceHolder") + && !startswith(typeName, "store::OStoreHandle") + && typeName.find("unique_ptr") == std::string::npos + && typeName.find("shared_ptr") == std::string::npos + && !startswith(typeName, "ScopedVclPtr") + && !startswith(typeName, "svt::EmbeddedObjectRef") + && !startswith(typeName, "tools::SvRef") + && !startswith(typeName, "tools::WeakReference") + && !startswith(typeName, "utl::SharedUNOComponent") + && !startswith(typeName, "VclPtr") + && !startswith(typeName, "vcl::DeleteOnDeinit") + && !startswith(typeName, "vcl::DeleteUnoReferenceOnDeinit") + // there are lots of coordinate/position vars that start with "x" + && !qt->isArithmeticType() + && !startswith(typeName, "float [") + ) + { + report( + DiagnosticsEngine::Warning, + "this local variable of type '%0' follows our ref-counted-pointer naming convention, but it is not a ref-counted-pointer, %1", + varDecl->getLocation()) + << typeName << aOriginalTypeName << varDecl->getSourceRange(); + } + + + return true; +} + +loplugin::Plugin::Registration< StylePolice > X("stylepolice"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/svstreamoutputoperators.cxx b/compilerplugins/clang/store/svstreamoutputoperators.cxx new file mode 100644 index 000000000..6e0ff6168 --- /dev/null +++ b/compilerplugins/clang/store/svstreamoutputoperators.cxx @@ -0,0 +1,223 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +/* +This is a rewriter. + +It changes the SvStream operator<< calls into calls to more explicitly named +methods, which reduces the casting needed, and makes it less likely that we +will accidentally write data to a file using the wrong data-type-size. + +TODO we don't currently cope with macro expansion e.g. if the constant on the RHS is a #define + +TODO we don't currently cope with code like "(*this) << 1;" + +TODO we don't currently cope with code like "aStream << x << endl;" the "endl" parts ends up dangling. + +TODO we don't currently cope with custom overloads of operator<< in some of the use-sites. +*/ + +#include "plugin.hxx" +#include +#include + +namespace loplugin +{ + +class SvStreamOutputOperators + : public loplugin::FilteringRewritePlugin< SvStreamOutputOperators > +{ + public: + explicit SvStreamOutputOperators( InstantiationData const & data ); + virtual void run() override; + bool VisitCallExpr( const CallExpr* call ); + private: + SourceLocation after(const SourceLocation& loc); +}; + +SvStreamOutputOperators::SvStreamOutputOperators( InstantiationData const & data ) + : FilteringRewritePlugin( data ) +{ +} + +void SvStreamOutputOperators::run() +{ + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); +} + +bool SvStreamOutputOperators::VisitCallExpr( const CallExpr* callExpr ) +{ + if( ignoreLocation( callExpr )) + return true; + if( callExpr->getNumArgs() < 2 ) + return true; + const FunctionDecl* func = dyn_cast_or_null< FunctionDecl >( callExpr->getCalleeDecl() ); + if ( func == NULL ) + return true; + if( func->getNumParams() != 1 ) + return true; + string qualifiedName = func->getQualifiedNameAsString(); + bool bOutputOperator; + if( qualifiedName == "SvStream::operator<<" ) + bOutputOperator = true; + else if( qualifiedName == "SvStream::operator>>" ) + bOutputOperator = false; + else + return true; + + string arg0 = func->getParamDecl( 0 )->getType().getAsString(); + string newIOMethod; + if (bOutputOperator) + { + if( arg0 == "sal_uInt16" ) + newIOMethod = "WriteUInt16"; + else if( arg0 == "sal_uInt32" ) + newIOMethod = "WriteUInt32"; + else if( arg0 == "sal_uInt64" ) + newIOMethod = "WriteUInt64"; + else if( arg0 == "sal_Int16" ) + newIOMethod = "WriteInt16"; + else if( arg0 == "sal_Int32" ) + newIOMethod = "WriteInt32"; + else if( arg0 == "sal_Int64" ) + newIOMethod = "WriteInt64"; + else if( arg0 == "sal_uInt8" ) + newIOMethod = "WriteUInt8"; + else if( arg0 == "sal_Unicode" ) + newIOMethod = "WriteUnicode"; + else if( arg0 == "rtl::OString" ) + newIOMethod = "WriteOString"; + else if( arg0 == "bool" ) + newIOMethod = "WriteBool"; + else if( arg0 == "signed char" ) + newIOMethod = "WriteSChar"; + else if( arg0 == "char" ) + newIOMethod = "WriteChar"; + else if( arg0 == "unsigned char" ) + newIOMethod = "WriteUChar"; + else if( arg0 == "float" ) + newIOMethod = "WriteFloat"; + else if( arg0 == "double" ) + newIOMethod = "WriteDouble"; + else if( arg0 == "const double &" ) + newIOMethod = "WriteDouble"; + else if( arg0 == "const char *" ) + newIOMethod = "WriteCharPtr"; + else if( arg0 == "char *" ) + newIOMethod = "WriteCharPtr"; + else if( arg0 == "const unsigned char *" ) + newIOMethod = "WriteUCharPtr"; + else if( arg0 == "unsigned char *" ) + newIOMethod = "WriteUCharPtr"; + else if( arg0 == "class SvStream &" ) + newIOMethod = "WriteStream"; + else + { + report( DiagnosticsEngine::Warning, + "found call to operator<< that I cannot convert with type: " + arg0, + callExpr->getLocStart()); + return true; + } + } + else + { + if( arg0 == "sal_uInt16 &" ) + newIOMethod = "ReadUInt16"; + else if( arg0 == "sal_uInt32 &" ) + newIOMethod = "ReadUInt32"; + else if( arg0 == "sal_uInt64 &" ) + newIOMethod = "ReadUInt64"; + else if( arg0 == "sal_Int16 &" ) + newIOMethod = "ReadInt16"; + else if( arg0 == "sal_Int32 &" ) + newIOMethod = "ReadInt32"; + else if( arg0 == "sal_Int64 &" ) + newIOMethod = "ReadInt64"; + else if( arg0 == "sal_uInt8 &" ) + newIOMethod = "ReadUInt8"; + else if( arg0 == "signed char &" ) + newIOMethod = "ReadSChar"; + else if( arg0 == "char &" ) + newIOMethod = "ReadChar"; + else if( arg0 == "unsigned char &" ) + newIOMethod = "ReadUChar"; + else if( arg0 == "float &" ) + newIOMethod = "ReadFloat"; + else if( arg0 == "double &" ) + newIOMethod = "ReadDouble"; + else if( arg0 == "class SvStream &" ) + newIOMethod = "ReadStream"; + else + { + report( DiagnosticsEngine::Warning, + "found call to operator>> that I cannot convert with type: " + arg0, + callExpr->getLocStart()); + return true; + } + } + + // CallExpr overrides the children() method from Stmt, but not the const variant of it, so we need to cast const away. + StmtRange range = const_cast(callExpr)->children(); + const Stmt* child1 = *range; // ImplicitCastExpr + ++range; + const Stmt* child2 = *range; // ImplicitCastExpr + + if( dyn_cast_or_null< UnaryOperator >( child2 ) != NULL ) + { + // remove the "*" before the stream variable + if( !replaceText( callExpr->getLocStart(), 1, "" ) ) + return true; + if( !replaceText( child1->getLocStart().getLocWithOffset(-1), 4, "->" ) ) + return true; + } + else + { + if( !replaceText( child1->getLocStart().getLocWithOffset(-1), 4, "." ) ) + return true; + } + + if( !insertTextBefore( callExpr->getArg( 1 )->getLocStart(), newIOMethod + "( " ) ) + return true; + if( !insertTextAfter( after( callExpr->getLocEnd() ), " )" ) ) + return true; + +//TODO for some reason this is currently removing too much text + // if there was a cast e.g. "r << (sal_Int32) 1", then remove the cast +// const CStyleCastExpr* cast = dyn_cast_or_null< CStyleCastExpr >( callExpr->getArg(1) ); +// if (cast != NULL) +// { +// replaceText( SourceRange( cast->getLParenLoc(), cast->getRParenLoc() ), "" ); +// } + + // if there was already parentheses around the expression, remove them + const ParenExpr* paren = dyn_cast_or_null< ParenExpr >( callExpr->getArg(1) ); + if (paren != NULL) + { + if( !replaceText( paren->getLocStart(), 1, "" ) ) + return true; + if( !replaceText( paren->getLocEnd(), 1, "" ) ) + return true; + } + +// report( DiagnosticsEngine::Note, "found", callExpr->getLocStart()); + return true; +} + +SourceLocation SvStreamOutputOperators::after( const SourceLocation& loc ) +{ + return Lexer::getLocForEndOfToken( loc, 0, compiler.getASTContext().getSourceManager(), compiler.getASTContext().getLangOpts() ); +} + +static Plugin::Registration< SvStreamOutputOperators > X( "svstreamoutputoperators" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/test/deadclass.cxx b/compilerplugins/clang/store/test/deadclass.cxx new file mode 100644 index 000000000..ffae241d4 --- /dev/null +++ b/compilerplugins/clang/store/test/deadclass.cxx @@ -0,0 +1,15 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +struct Foo +{ // expected-error {{class has only copy/move constructors, must be dead [loplugin:deadclass]}} + Foo(Foo&); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/store/tutorial/tutorial1.cxx b/compilerplugins/clang/store/tutorial/tutorial1.cxx new file mode 100644 index 000000000..9f7c97fb7 --- /dev/null +++ b/compilerplugins/clang/store/tutorial/tutorial1.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "tutorial1.hxx" + +/* +This is a compile check. + +Checks all return statements and warns if they return literal false (i.e. 'return false'). +*/ + +namespace loplugin +{ + +// Ctor, nothing special, pass the argument(s). +Tutorial1::Tutorial1( const InstantiationData& data ) + : FilteringPlugin( data ) + { + } + +// Perform the actual action. +void Tutorial1::run() + { + // Traverse the whole AST of the translation unit (i.e. examine the whole source file). + // The Clang AST helper class will call VisitReturnStmt for every return statement. + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +// This function is called for every return statement. +// Returning true means to continue with examining the AST, false means to stop (just always return true). +bool Tutorial1::VisitReturnStmt( const ReturnStmt* returnstmt ) + { + // Helper function from the LO base plugin class, call at the very beginning to ignore sources + // that should not be processed (e.g. system headers). + if( ignoreLocation( returnstmt )) + return true; + // Get the expression in the return statement (see ReturnStmt API docs). + const Expr* expression = returnstmt->getRetValue(); + if( expression == NULL ) + return true; // plain 'return;' without expression + // Check if the expression is a bool literal (Clang uses dyn_cast<> instead of dynamic_cast<>). + if( const CXXBoolLiteralExpr* boolliteral = dyn_cast< CXXBoolLiteralExpr >( expression )) + { // It is. + if( boolliteral->getValue() == false ) // Is it 'return false;' ? (See CXXBoolLiteralExpr API docs) + { // Ok, warn, use LO plugin helper function. + report( DiagnosticsEngine::Warning, // It's just a warning. + "returning false", // the message + boolliteral->getLocStart()) // and the exact position where the message should point + << returnstmt->getSourceRange(); // and the full return statement to highlight (optional) + } + } + return true; + } + +// Register the plugin action with the LO plugin handling. +static Plugin::Registration< Tutorial1 > tutorial1( "tutorial1" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/tutorial/tutorial1.hxx b/compilerplugins/clang/store/tutorial/tutorial1.hxx new file mode 100644 index 000000000..10f73f04b --- /dev/null +++ b/compilerplugins/clang/store/tutorial/tutorial1.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include "plugin.hxx" + +namespace loplugin +{ + +// The class implementing the plugin action. +class Tutorial1 + // Inherits from the Clang class that will allow examining the Clang AST tree (i.e. syntax tree). + : public FilteringPlugin< Tutorial1 > + { + public: + // Ctor, nothing special. + Tutorial1( const InstantiationData& data ); + // The function that will be called to perform the actual action. + virtual void run() override; + // Function from Clang, it will be called for every return statement in the source. + bool VisitReturnStmt( const ReturnStmt* returnstmt ); + }; + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/tutorial/tutorial1_example.cxx b/compilerplugins/clang/store/tutorial/tutorial1_example.cxx new file mode 100644 index 000000000..1ec0e1e59 --- /dev/null +++ b/compilerplugins/clang/store/tutorial/tutorial1_example.cxx @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +// This is just an example file to see what AST looks like for return statements. +// To the AST, run : +// clang++ -fsyntax-only -Xclang -ast-dump tutorial1_example.cxx + +void f() + { + return; + } + +bool g() + { + return false; + } + +bool h() + { + return 3 > 2; + } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/tutorial/tutorial2.cxx b/compilerplugins/clang/store/tutorial/tutorial2.cxx new file mode 100644 index 000000000..49aaaa631 --- /dev/null +++ b/compilerplugins/clang/store/tutorial/tutorial2.cxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "tutorial2.hxx" + +/* +This is a compile check. + +Warns about if statements with a comparison followed by literal return false: +if( a == 1 ) + return false; +*/ + +namespace loplugin +{ + +Tutorial2::Tutorial2( const InstantiationData& data ) + : FilteringPlugin( data ) + { + } + +void Tutorial2::run() + { + // The Clang AST helper class will call VisitIfStmt for every if statement. + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +// This function is called for every if statement. +bool Tutorial2::VisitIfStmt( const IfStmt* ifstmt ) + { + if( ignoreLocation( ifstmt )) + return true; + // Check if the condition of the if statement is a binary operator. + if( const BinaryOperator* oper = dyn_cast< BinaryOperator >( ifstmt->getCond())) + { + // And if it's operator==. + if( oper->getOpcode() == BO_EQ ) + { + // Now check if the sub-statement is 'return false'. + const Stmt* warn = NULL; // The return statement (for the warning message). + // Check if the sub-statement is directly 'return false;'. + if( isReturnFalse( ifstmt->getThen())) + warn = ifstmt->getThen(); + // Check if the sub-statement is '{ return false; }' + else if( const CompoundStmt* compound = dyn_cast< CompoundStmt >( ifstmt->getThen())) + { + if( compound->size() == 1 ) // one statement + if( isReturnFalse( *compound->body_begin())) // check the one sub-statement + warn = *compound->body_begin(); + } + if( warn != NULL ) // there is a return statement to warn about. + { + report( DiagnosticsEngine::Warning, + "returning false after if with equality comparison", + cast< ReturnStmt >( warn )->getRetValue()->getLocStart()) // the 'false' in the return + << warn->getSourceRange(); + // Also add a note showing the if statement. + report( DiagnosticsEngine::Note, + "the if statement is here", + ifstmt->getLocStart()); + } + } + } + return true; + } + +bool Tutorial2::isReturnFalse( const Stmt* stmt ) + { + // Is it return statement? + if( const ReturnStmt* returnstmt = dyn_cast< ReturnStmt >( stmt )) + { + // dyn_cast_or_null<> can also be passed NULL, unlike dyn_cast<> + if( const CXXBoolLiteralExpr* boolliteral = dyn_cast_or_null< CXXBoolLiteralExpr >( returnstmt->getRetValue())) + { + if( boolliteral->getValue() == false ) + return true; + } + } + return false; + } + +// Register the plugin action with the LO plugin handling. +static Plugin::Registration< Tutorial2 > tutorial2( "tutorial2" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/tutorial/tutorial2.hxx b/compilerplugins/clang/store/tutorial/tutorial2.hxx new file mode 100644 index 000000000..9ae2de354 --- /dev/null +++ b/compilerplugins/clang/store/tutorial/tutorial2.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include "plugin.hxx" + +namespace loplugin +{ + +// The same like for Tutorial1. +class Tutorial2 + : public FilteringPlugin< Tutorial2 > + { + public: + Tutorial2( const InstantiationData& data ); + virtual void run() override; + // Will be called for every if statement. + bool VisitIfStmt( const IfStmt* ifstmt ); + private: + // Helper function to check if the statement is 'return false;'. + bool isReturnFalse( const Stmt* stmt ); + }; + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/tutorial/tutorial2_example.cxx b/compilerplugins/clang/store/tutorial/tutorial2_example.cxx new file mode 100644 index 000000000..7d72ff68d --- /dev/null +++ b/compilerplugins/clang/store/tutorial/tutorial2_example.cxx @@ -0,0 +1,18 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +// This is just an example file to see what AST looks like for return statements. +// To the AST, run : +// clang++ -fsyntax-only -Xclang -ast-dump tutorial1_example.cxx + +bool g() + { + if( 1 == 2 ) + return false; + if( 1 == 2 ) + { + return false; + } + if( true ) + return false; + } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/tutorial/tutorial3.cxx b/compilerplugins/clang/store/tutorial/tutorial3.cxx new file mode 100644 index 000000000..33a1249a3 --- /dev/null +++ b/compilerplugins/clang/store/tutorial/tutorial3.cxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "tutorial3.hxx" + +/* +This is a rewriter. + +It looks for if statements with a comparison followed by literal return false +and modifies the return statements to 'return maybereturntrue;' +*/ + +namespace loplugin +{ + +// Ctor, pass arguments. +Tutorial3::Tutorial3( const InstantiationData& data ) + : FilteringRewritePlugin( data ) + { + } + +void Tutorial3::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +bool Tutorial3::VisitIfStmt( const IfStmt* ifstmt ) + { + if( ignoreLocation( ifstmt )) + return true; + if( const BinaryOperator* oper = dyn_cast< BinaryOperator >( ifstmt->getCond())) + { + if( oper->getOpcode() == BO_EQ ) + { + // Modify the sub-statement if it is 'return false'. + modifyReturnFalse( ifstmt->getThen()); + // Modify the sub-statement if it is '{ return false; }'. + if( const CompoundStmt* compound = dyn_cast< CompoundStmt >( ifstmt->getThen())) + { + if( compound->size() == 1 ) // one statement + modifyReturnFalse( *compound->body_begin()); + } + } + } + return true; + } + +void Tutorial3::modifyReturnFalse( const Stmt* stmt ) + { + // Is it return statement? + if( const ReturnStmt* returnstmt = dyn_cast< ReturnStmt >( stmt )) + { + // dyn_cast_or_null<> can also be passed NULL, unlike dyn_cast<> + if( const CXXBoolLiteralExpr* boolliteral = dyn_cast_or_null< CXXBoolLiteralExpr >( returnstmt->getRetValue())) + { + if( boolliteral->getValue() == false ) + { // It is, modify the false to true using LO plugin helper function. + replaceText( boolliteral->getSourceRange(), "maybereturntrue" ); + } + } + } + } + +// Register the plugin action with the LO plugin handling. +static Plugin::Registration< Tutorial3 > tutorial3( "tutorial3" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/tutorial/tutorial3.hxx b/compilerplugins/clang/store/tutorial/tutorial3.hxx new file mode 100644 index 000000000..11378ef76 --- /dev/null +++ b/compilerplugins/clang/store/tutorial/tutorial3.hxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include "plugin.hxx" + +namespace loplugin +{ + +// Similar like for Tutorial2, but this time the base class is RewritePlugin. +class Tutorial3 + : public loplugin::FilteringRewritePlugin< Tutorial3 > + { + public: + // One more argument for ctor. + Tutorial3( const InstantiationData& data ); + virtual void run() override; + // Will be called for every if statement. + bool VisitIfStmt( const IfStmt* ifstmt ); + private: + // Helper function to check if the statement is 'return false;' and + // modify it if yes. + void modifyReturnFalse( const Stmt* stmt ); + }; + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/unusedcode.cxx b/compilerplugins/clang/store/unusedcode.cxx new file mode 100644 index 000000000..32fc4d3c2 --- /dev/null +++ b/compilerplugins/clang/store/unusedcode.cxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +/* +This is technically a rewriter, but it actually only generates data about code. + +This is incomplete. + +Checks for all function declarations for whether they are used or not. This information +should be output to files and in a second pass it should be checked (by another tool) +which functions are never used. +*/ + +#include "plugin.hxx" + +namespace loplugin +{ + +class UnusedCode + : public loplugin::FilteringRewritePlugin< UnusedCode > + { + public: + explicit UnusedCode( CompilerInstance& compiler, Rewriter& rewriter ); + virtual void run() override; + bool VisitFunctionDecl( const FunctionDecl* declaration ); + }; + +UnusedCode::UnusedCode( CompilerInstance& compiler, Rewriter& rewriter ) + : FilteringRewritePlugin( compiler, rewriter ) + { + } + +void UnusedCode::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +bool UnusedCode::VisitFunctionDecl( const FunctionDecl* declaration ) + { + if( ignoreLocation( declaration )) + return true; + bool isUsed = declaration->isUsed(); + if( const CXXMethodDecl* cxxmethod = dyn_cast< CXXMethodDecl >( declaration )) + { + if( !isUsed && cxxmethod->isVirtual()) + { // Virtual methods are used also if a method they override is used. + for( CXXMethodDecl::method_iterator it = cxxmethod->begin_overridden_methods(); + it != cxxmethod->end_overridden_methods(); + ++it ) + { + if( (*it)->isUsed()) + { + isUsed = true; + break; + } + } + } + } + // Fully qualified name: declaration->getQualifiedNameAsString() + // Is used: isUsed + // The main source file compiled: compiler.getSourceManager().getFileEntryForID( compiler.getSourceManager().getMainFileID())->getName() + return true; + } + +static Plugin::Registration< UnusedCode > X( "unusedcode" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/store/valueof.cxx b/compilerplugins/clang/store/valueof.cxx new file mode 100644 index 000000000..808e0c158 --- /dev/null +++ b/compilerplugins/clang/store/valueof.cxx @@ -0,0 +1,148 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +/* +This is a rewriter. + +Replaces all calls to the deprecated O(U)String::valueOf() . + +*/ + +#include "plugin.hxx" + +namespace loplugin +{ + +class ConvertValueOf + : public loplugin::FilteringRewritePlugin< ConvertValueOf > + { + public: + explicit ConvertValueOf( CompilerInstance& compiler, Rewriter& rewriter ); + virtual void run() override; + bool VisitCallExpr( const CallExpr* call ); + private: + void removeCast( const Expr* arg ); + }; + +ConvertValueOf::ConvertValueOf( CompilerInstance& compiler, Rewriter& rewriter ) + : FilteringRewritePlugin( compiler, rewriter ) + { + } + +void ConvertValueOf::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +bool ConvertValueOf::VisitCallExpr( const CallExpr* call ) + { + if( ignoreLocation( call )) + return true; + // Using getDirectCallee() here means that we find only calls + // that call the function directly (i.e. not using a pointer, for example). + // Use getCallee() to include also those : + // if( const FunctionDecl* func = dyn_cast_or_null< FunctionDecl >( call->getCalleeDecl())) + if( const FunctionDecl* func = call->getDirectCallee()) + { + // Optimize, getQualifiedNameAsString() is reportedly expensive, + // so first check fast details like number of arguments or the (unqualified) + // name before checking the fully qualified name. + // See FunctionDecl for all the API about the function. + if( func->getIdentifier() != NULL + && ( func->getName() == "valueOf" )) + { + string qualifiedName = func->getQualifiedNameAsString(); + if( qualifiedName == "rtl::OString::valueOf" ) + { + // Further checks about arguments. Check mainly ParmVarDecl, VarDecl, + // ValueDecl and QualType for Clang API details. + string arg0 = func->getParamDecl( 0 )->getType().getAsString(); + if( arg0 == "sal_Bool" ) + replaceText( call->getCallee()->getSourceRange(), "OString::boolean" ); + else + { + replaceText( call->getCallee()->getSourceRange(), "OString::number" ); + removeCast( call->getArg( 0 )); + } + } + if( qualifiedName == "rtl::OUString::valueOf" ) + { + // Further checks about arguments. Check mainly ParmVarDecl, VarDecl, + // ValueDecl and QualType for Clang API details. + string arg0 = func->getParamDecl( 0 )->getType().getAsString(); + if( arg0 == "sal_Bool" ) + replaceText( call->getCallee()->getSourceRange(), "OUString::boolean" ); + else if( arg0 == "sal_Unicode" ) + replaceText( call->getCallee()->getSourceRange(), "OUString" ); + else + { + replaceText( call->getCallee()->getSourceRange(), "OUString::number" ); + removeCast( call->getArg( 0 )); + } + } + } + } + return true; + } + +void ConvertValueOf::removeCast( const Expr* arg ) + { + arg = arg->IgnoreImpCasts(); + if( const ExplicitCastExpr* cast = dyn_cast< ExplicitCastExpr >( arg )) + { +// Explicit casts don't seem to actually always change the type (integer promotion +// takes place first?), so remove also preceding implicit casts: +// void f( int ); +// char a; +// f( int( a )); +// |-CallExpr 0x1a84f20 'void' +// | |-ImplicitCastExpr 0x1a84f08 'void (*)(int)' +// | | `-DeclRefExpr 0x1a84eb8 'void (int)' lvalue Function 0x1a58900 'f' 'void (int)' +// | `-CXXFunctionalCastExpr 0x1a84e90 'int' functional cast to int +// | `-ImplicitCastExpr 0x1a84e78 'int' +// | `-ImplicitCastExpr 0x1a84e60 'char' +// | `-DeclRefExpr 0x1a58b88 'char' lvalue Var 0x1a58ab0 'a' 'char' + const Expr* castFrom = cast->getSubExpr()->IgnoreImpCasts(); + if( cast->getType()->isIntegerType() && castFrom->getType()->isIntegerType()) + { + string fromType = castFrom->getType().getAsString(); + if( fromType != "sal_Bool" && fromType != "bool" && fromType != "sal_Unicode" ) + { + if( const CXXFunctionalCastExpr* funcCast = dyn_cast< CXXFunctionalCastExpr >( cast )) + { + removeText( CharSourceRange::getCharRange( funcCast->getLocStart(), + compiler.getSourceManager().getExpansionLoc( funcCast->getSubExpr()->getLocStart()))); + removeText( CharSourceRange::getCharRange( locationAfterToken( + compiler.getSourceManager().getExpansionLoc( funcCast->getSubExpr()->getLocEnd())), + locationAfterToken( funcCast->getLocEnd()))); + } + else if( const CXXNamedCastExpr* namedCast = dyn_cast< CXXNamedCastExpr >( cast )) + { + removeText( CharSourceRange::getCharRange( namedCast->getLocStart(), + compiler.getSourceManager().getExpansionLoc( namedCast->getSubExpr()->getLocStart()))); + removeText( CharSourceRange::getCharRange( locationAfterToken( + compiler.getSourceManager().getExpansionLoc( namedCast->getSubExpr()->getLocEnd())), + locationAfterToken( namedCast->getLocEnd()))); + } + else if( const CStyleCastExpr* cCast = dyn_cast< CStyleCastExpr >( cast )) + removeText( SourceRange( cCast->getLocStart(), cCast->getRParenLoc())); + else + abort(); + } + } + } + } + +static Plugin::Registration< ConvertValueOf > X( "convertvalueof" ); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/stringadd.cxx b/compilerplugins/clang/stringadd.cxx new file mode 100644 index 000000000..339192a78 --- /dev/null +++ b/compilerplugins/clang/stringadd.cxx @@ -0,0 +1,467 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +/** + Look for repeated addition to OUString/OString. + + Eg. + OUString x = "xxx"; + x += b; + + which can be simplified to + x = "xxx" + b + + which is more efficient, because of the OUStringConcat magic. +*/ + +namespace +{ +class StringAdd : public loplugin::FilteringPlugin +{ +public: + explicit StringAdd(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/rtl/oustring/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/rtl/oustringbuffer/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/rtl/strings/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/OStringBuffer/")) + return false; + // there is an ifdef here, but my check is not working, not sure why + if (fn == SRCDIR "/pyuno/source/module/pyuno_runtime.cxx") + return false; + // TODO the += depends on the result of the preceding assign, so can't merge + if (fn == SRCDIR "/editeng/source/misc/svxacorr.cxx") + return false; + return true; + } + + virtual void run() override + { + if (!preRun()) + return; + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCompoundStmt(CompoundStmt const*); + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const*); + bool VisitCXXMemberCallExpr(CXXMemberCallExpr const*); + +private: + enum class Summands + { + OnlyCompileTimeConstants, + OnlySideEffectFree, + SideEffect + }; + + struct VarDeclAndSummands + { + const VarDecl* varDecl; + Summands summands; + }; + + VarDeclAndSummands findAssignOrAdd(Stmt const*); + bool checkForCompoundAssign(Stmt const* stmt1, Stmt const* stmt2, VarDeclAndSummands& varDecl); + + Expr const* ignore(Expr const*); + bool isSideEffectFree(Expr const*); + bool isCompileTimeConstant(Expr const*); +}; + +bool StringAdd::VisitCompoundStmt(CompoundStmt const* compoundStmt) +{ + if (ignoreLocation(compoundStmt)) + return true; + + auto it = compoundStmt->body_begin(); + while (true) + { + if (it == compoundStmt->body_end()) + break; + VarDeclAndSummands foundVar = findAssignOrAdd(*it); + // reference types have slightly weird behaviour + if (foundVar.varDecl && !foundVar.varDecl->getType()->isReferenceType()) + { + auto stmt1 = *it; + ++it; + while (it != compoundStmt->body_end()) + { + if (!checkForCompoundAssign(stmt1, *it, foundVar)) + { + break; + } + stmt1 = *it; + ++it; + } + } + else + ++it; + } + + return true; +} + +StringAdd::VarDeclAndSummands StringAdd::findAssignOrAdd(Stmt const* stmt) +{ + if (auto exprCleanup = dyn_cast(stmt)) + stmt = exprCleanup->getSubExpr(); + if (auto switchCase = dyn_cast(stmt)) + stmt = switchCase->getSubStmt(); + + if (auto declStmt = dyn_cast(stmt)) + if (declStmt->isSingleDecl()) + if (auto varDeclLHS = dyn_cast_or_null(declStmt->getSingleDecl())) + { + auto tc = loplugin::TypeCheck(varDeclLHS->getType()); + if (!tc.Class("OUString").Namespace("rtl").GlobalNamespace() + && !tc.Class("OString").Namespace("rtl").GlobalNamespace()) + return {}; + if (varDeclLHS->getStorageDuration() == SD_Static) + return {}; + if (!varDeclLHS->hasInit()) + return {}; + return { varDeclLHS, (isCompileTimeConstant(varDeclLHS->getInit()) + ? Summands::OnlyCompileTimeConstants + : (isSideEffectFree(varDeclLHS->getInit()) + ? Summands::OnlySideEffectFree + : Summands::SideEffect)) }; + } + if (auto operatorCall = dyn_cast(stmt)) + if (operatorCall->getOperator() == OO_Equal || operatorCall->getOperator() == OO_PlusEqual) + if (auto declRefExprLHS = dyn_cast(ignore(operatorCall->getArg(0)))) + if (auto varDeclLHS = dyn_cast(declRefExprLHS->getDecl())) + { + auto tc = loplugin::TypeCheck(varDeclLHS->getType()); + if (!tc.Class("OUString").Namespace("rtl").GlobalNamespace() + && !tc.Class("OString").Namespace("rtl").GlobalNamespace()) + return {}; + auto rhs = operatorCall->getArg(1); + return { varDeclLHS, + (isCompileTimeConstant(rhs) + ? Summands::OnlyCompileTimeConstants + : (isSideEffectFree(rhs) ? Summands::OnlySideEffectFree + : Summands::SideEffect)) }; + } + return {}; +} + +bool StringAdd::checkForCompoundAssign(Stmt const* stmt1, Stmt const* stmt2, + VarDeclAndSummands& varDecl) +{ + // OString additions are frequently wrapped in these + if (auto exprCleanup = dyn_cast(stmt2)) + stmt2 = exprCleanup->getSubExpr(); + if (auto switchCase = dyn_cast(stmt2)) + stmt2 = switchCase->getSubStmt(); + auto operatorCall = dyn_cast(stmt2); + if (!operatorCall) + return false; + if (operatorCall->getOperator() != OO_PlusEqual) + return false; + auto declRefExprLHS = dyn_cast(ignore(operatorCall->getArg(0))); + if (!declRefExprLHS) + return false; + if (declRefExprLHS->getDecl() != varDecl.varDecl) + return false; + // if either side is a compile-time-constant, then we don't care about + // side-effects + auto rhs = operatorCall->getArg(1); + auto const ctcRhs = isCompileTimeConstant(rhs); + if (!ctcRhs) + { + auto const sefRhs = isSideEffectFree(rhs); + auto const oldSummands = varDecl.summands; + varDecl.summands = sefRhs ? Summands::OnlySideEffectFree : Summands::SideEffect; + if (oldSummands != Summands::OnlyCompileTimeConstants + && (oldSummands == Summands::SideEffect || !sefRhs)) + { + return true; + } + } + // if we cross a #ifdef boundary + if (containsPreprocessingConditionalInclusion( + SourceRange(stmt1->getSourceRange().getBegin(), stmt2->getSourceRange().getEnd()))) + { + varDecl.summands + = ctcRhs ? Summands::OnlyCompileTimeConstants + : isSideEffectFree(rhs) ? Summands::OnlySideEffectFree : Summands::SideEffect; + return true; + } + report(DiagnosticsEngine::Warning, "simplify by merging with the preceding assignment", + stmt2->getBeginLoc()) + << stmt2->getSourceRange(); + return true; +} + +// Check for generating temporaries when adding strings +// +bool StringAdd::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* operatorCall) +{ + if (ignoreLocation(operatorCall)) + return true; + if (operatorCall->getOperator() != OO_Plus) + return true; + auto tc = loplugin::TypeCheck(operatorCall->getType()->getUnqualifiedDesugaredType()); + if (!tc.Struct("OUStringConcat").Namespace("rtl").GlobalNamespace() + && !tc.Struct("OStringConcat").Namespace("rtl").GlobalNamespace() + && !tc.Class("OUString").Namespace("rtl").GlobalNamespace() + && !tc.Class("OString").Namespace("rtl").GlobalNamespace()) + return true; + + auto check = [operatorCall, this](unsigned arg) { + auto const e + = dyn_cast(operatorCall->getArg(arg)->IgnoreParenImpCasts()); + if (e == nullptr) + return; + auto tc3 = loplugin::TypeCheck(e->getType()); + if (!tc3.Class("OUString").Namespace("rtl").GlobalNamespace() + && !tc3.Class("OString").Namespace("rtl").GlobalNamespace() + && !tc3.Class("OUStringLiteral").Namespace("rtl").GlobalNamespace() + && !tc3.Class("OStringLiteral").Namespace("rtl").GlobalNamespace() + && !tc3.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + && !tc3.Class("OStringBuffer").Namespace("rtl").GlobalNamespace()) + return; + report(DiagnosticsEngine::Warning, + ("rather use O[U]String::Concat than constructing %0 from %1 on %select{L|R}2HS of " + "+ (where %select{R|L}2HS is of" + " type %3)"), + e->getBeginLoc()) + << e->getType().getLocalUnqualifiedType() << e->getSubExprAsWritten()->getType() << arg + << operatorCall->getArg(1 - arg)->IgnoreImpCasts()->getType() << e->getSourceRange(); + }; + + check(0); + check(1); + return true; +} + +bool StringAdd::VisitCXXMemberCallExpr(CXXMemberCallExpr const* methodCall) +{ + if (ignoreLocation(methodCall)) + return true; + + auto methodDecl = methodCall->getMethodDecl(); + if (!methodDecl || !methodDecl->getIdentifier() || methodDecl->getName() != "append" + || methodCall->getNumArgs() == 0) + return true; + auto tc1 = loplugin::TypeCheck(methodCall->getType()); + if (!tc1.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + && !tc1.Class("OStringBuffer").Namespace("rtl").GlobalNamespace()) + return true; + auto paramType = methodDecl->getParamDecl(0)->getType(); + // char is still a pain to work with, when constructing a chained + + if (paramType->isCharType() || loplugin::TypeCheck(paramType).Typedef("sal_Unicode")) + return true; + auto arg = methodCall->getArg(0); + // I don't think the OUStringAppend functionality can handle this efficiently + if (isa(ignore(arg))) + return true; + + auto methodCall2 = dyn_cast(ignore(methodCall->getImplicitObjectArgument())); + if (!methodCall2) + return true; + auto tc = loplugin::TypeCheck(methodCall2->getType()); + if (!tc.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + && !tc.Class("OStringBuffer").Namespace("rtl").GlobalNamespace()) + return true; + auto methodDecl2 = methodCall2->getMethodDecl(); + if (!methodDecl2->getIdentifier() || methodDecl2->getName() != "append" + || methodCall2->getNumArgs() == 0) + return true; + auto paramType2 = methodDecl2->getParamDecl(0)->getType(); + // char is still a pain to work with, when constructing a chained + + if (paramType2->isCharType() || loplugin::TypeCheck(paramType2).Typedef("sal_Unicode")) + return true; + arg = methodCall2->getArg(0); + // I don't think the OUStringAppend functionality can handle this efficiently + if (isa(ignore(arg))) + return true; + report(DiagnosticsEngine::Warning, + "chained append, rather use single append call and + operator", + methodCall2->getBeginLoc()) + << methodCall2->getSourceRange(); + + return true; +} + +Expr const* StringAdd::ignore(Expr const* expr) +{ + return expr->IgnoreImplicit()->IgnoreParens()->IgnoreImplicit(); +} + +bool StringAdd::isSideEffectFree(Expr const* expr) +{ + expr = ignore(expr); + // I don't think the OUStringAppend functionality can handle this efficiently + if (isa(expr)) + return false; + // Multiple statements have a well defined evaluation order (sequence points between them) + // but a single expression may be evaluated in arbitrary order; + // if there are side effects in one of the sub-expressions that have an effect on another subexpression, + // the result may be incorrect, and you don't necessarily notice in tests because the order is compiler-dependent. + // for example see commit afd743141f7a7dd05914d0872c9afe079f16fe0c where such a refactoring introduced such a bug. + // So only consider simple RHS expressions. + if (!expr->HasSideEffects(compiler.getASTContext())) + return true; + + // check for chained adds which are side-effect free + if (auto operatorCall = dyn_cast(expr)) + { + auto op = operatorCall->getOperator(); + if (op == OO_PlusEqual || op == OO_Plus) + if (isSideEffectFree(operatorCall->getArg(0)) + && isSideEffectFree(operatorCall->getArg(1))) + return true; + } + + if (auto callExpr = dyn_cast(expr)) + { + // check for calls through OUString::number/OUString::unacquired + if (auto calleeMethodDecl = dyn_cast_or_null(callExpr->getCalleeDecl())) + { + if (calleeMethodDecl->getIdentifier()) + { + auto name = calleeMethodDecl->getName(); + if (callExpr->getNumArgs() > 0 + && (name == "number" || name == "unacquired" || name == "boolean" + || name == "copy")) + { + auto tc = loplugin::TypeCheck(calleeMethodDecl->getParent()); + if (tc.Class("OUString") || tc.Class("OString")) + { + if (isSideEffectFree(callExpr->getArg(0))) + return true; + } + } + } + else if (auto const d = dyn_cast(calleeMethodDecl)) + { + if (loplugin::TypeCheck(d->getConversionType()) + .ClassOrStruct("basic_string_view") + .StdNamespace()) + { + auto const tc = loplugin::TypeCheck(calleeMethodDecl->getParent()); + if (tc.Class("OUString").Namespace("rtl").GlobalNamespace() + || tc.Class("OString").Namespace("rtl").GlobalNamespace()) + { + if (isSideEffectFree(callExpr->getCallee())) + return true; + } + } + } + // Aggressively assume that calls to const member functions are side effect free (if + // all of the call's sub-expressions are): + if (calleeMethodDecl->isConst()) + { + auto sef = true; + // Other options besides CXXMemberCallExpr are e.g. CXXOperatorCallExpr which + // does not have such a target expression: + if (auto const mce = dyn_cast(callExpr)) + { + if (!isSideEffectFree(mce->getImplicitObjectArgument())) + { + sef = false; + } + } + if (sef) + { + for (unsigned i = 0; i != callExpr->getNumArgs(); ++i) + { + if (!isSideEffectFree(callExpr->getArg(i))) + { + sef = false; + break; + } + } + } + if (sef) + { + return true; + } + } + } + if (auto calleeFunctionDecl = dyn_cast_or_null(callExpr->getCalleeDecl())) + if (calleeFunctionDecl && calleeFunctionDecl->getIdentifier()) + { + auto name = calleeFunctionDecl->getName(); + // check for calls through OUStringToOString + if (name == "OUStringToOString" || name == "OStringToOUString") + if (isSideEffectFree(callExpr->getArg(0))) + return true; + // allowlist some known-safe methods + if (name.endswith("ResId") || name == "GetXMLToken") + if (isSideEffectFree(callExpr->getArg(0))) + return true; + } + } + + // sometimes we have a constructor call on the RHS + if (auto constructExpr = dyn_cast(expr)) + { + auto dc = loplugin::DeclCheck(constructExpr->getConstructor()); + if (dc.MemberFunction().Class("OUString") || dc.MemberFunction().Class("OString")) + if (constructExpr->getNumArgs() == 0 || isSideEffectFree(constructExpr->getArg(0))) + return true; + // Expr::HasSideEffects does not like stuff that passes through OUStringLiteral + auto dc2 = loplugin::DeclCheck(constructExpr->getConstructor()->getParent()); + if (dc2.Class("OUStringLiteral").Namespace("rtl").GlobalNamespace() + || dc2.Class("OStringLiteral").Namespace("rtl").GlobalNamespace()) + return true; + } + + // when adding literals, we sometimes get this + if (auto functionalCastExpr = dyn_cast(expr)) + { + auto tc = loplugin::TypeCheck(functionalCastExpr->getType()); + if (tc.Class("OUStringLiteral").Namespace("rtl").GlobalNamespace() + || tc.Class("OStringLiteral").Namespace("rtl").GlobalNamespace()) + return isSideEffectFree(functionalCastExpr->getSubExpr()); + } + + return false; +} + +bool StringAdd::isCompileTimeConstant(Expr const* expr) +{ + expr = expr->IgnoreImplicit(); + if (auto cxxConstructExpr = dyn_cast(expr)) + if (cxxConstructExpr->getNumArgs() > 0) + expr = cxxConstructExpr->getArg(0); + return isa(expr); +} + +loplugin::Plugin::Registration stringadd("stringadd"); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/stringconcatauto.cxx b/compilerplugins/clang/stringconcatauto.cxx new file mode 100644 index 000000000..1ff3f41d3 --- /dev/null +++ b/compilerplugins/clang/stringconcatauto.cxx @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +/* +This is a compile check. + +Warns about 'auto' declarations becoming rtl::OUStringConcat, such as +auto str = "string" + OUString::number( 10 ); +The type of the expression is rtl::OUStringConcat and those refer to temporaries +and so their lifecycle should not extend the lifecycle of those temporaries. +*/ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "config_clang.h" + +#include "plugin.hxx" +#include "check.hxx" + +namespace loplugin +{ + +class StringConcatAuto + : public FilteringPlugin< StringConcatAuto > + { + public: + StringConcatAuto( const InstantiationData& data ); + virtual void run() override; + bool shouldVisitTemplateInstantiations () const { return true; } + bool VisitVarDecl( const VarDecl* decl ); + bool VisitFunctionDecl( const FunctionDecl* decl ); + private: + enum class Check { Var, Return }; + bool checkDecl( const DeclaratorDecl* decl, const QualType type, const SourceRange& range, Check check ); + }; + +StringConcatAuto::StringConcatAuto( const InstantiationData& data ) + : FilteringPlugin( data ) + { + } + +void StringConcatAuto::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +bool StringConcatAuto::VisitVarDecl( const VarDecl* decl ) + { + return checkDecl( decl, decl->getType(), + decl->getTypeSourceInfo() + ? decl->getTypeSourceInfo()->getTypeLoc().getSourceRange() + : decl->getSourceRange(), + Check::Var ); + } + +bool StringConcatAuto::VisitFunctionDecl( const FunctionDecl* decl ) + { + return checkDecl( decl, decl->getReturnType(), decl->getReturnTypeSourceRange(), Check::Return ); + } + +bool StringConcatAuto::checkDecl( const DeclaratorDecl* decl, QualType type, const SourceRange& range, Check check ) + { + if( ignoreLocation( decl )) + return true; + if( isa< ParmVarDecl >( decl )) // parameters should be fine, temporaries should exist during the call + return true; + std::string fileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(decl->getBeginLoc())).str(); + loplugin::normalizeDotDotInFilePath(fileName); + if (loplugin::isSamePathname(fileName, SRCDIR "/include/rtl/string.hxx") + || loplugin::isSamePathname(fileName, SRCDIR "/include/rtl/ustring.hxx") + || loplugin::isSamePathname(fileName, SRCDIR "/include/rtl/strbuf.hxx") + || loplugin::isSamePathname(fileName, SRCDIR "/include/rtl/ustrbuf.hxx") + || loplugin::isSamePathname(fileName, SRCDIR "/include/rtl/stringconcat.hxx")) + return true; + auto const tc = loplugin::TypeCheck( type.getNonReferenceType().getCanonicalType()); + const char* typeString = nullptr; + if( tc.Struct("OUStringConcat").Namespace("rtl").GlobalNamespace()) + typeString = "OUString"; + else if( tc.Struct("OStringConcat").Namespace("rtl").GlobalNamespace()) + typeString = "OString"; + else + return true; + report( DiagnosticsEngine::Warning, + check == Check::Var + ? "creating a variable of type %0 will make it reference temporaries" + : "returning a variable of type %0 will make it reference temporaries", + decl->getLocation()) + << type; + report( DiagnosticsEngine::Note, + "use %0 instead", + range.getBegin()) + << typeString + << FixItHint::CreateReplacement( range, typeString ); + return true; + } + +static Plugin::Registration< StringConcatAuto > stringconcatauto( "stringconcatauto" ); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/stringconcatliterals.cxx b/compilerplugins/clang/stringconcatliterals.cxx new file mode 100644 index 000000000..2e89ddca6 --- /dev/null +++ b/compilerplugins/clang/stringconcatliterals.cxx @@ -0,0 +1,156 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "config_clang.h" + +#include "plugin.hxx" +#include "check.hxx" + +namespace { + +Expr const * stripCtor(Expr const * expr) { + auto e1 = expr; + if (auto const e = dyn_cast(e1)) { + e1 = e->getSubExpr()->IgnoreParenImpCasts(); + } + if (auto const e = dyn_cast(e1)) { + e1 = e->getSubExpr()->IgnoreParenImpCasts(); + } + auto const e2 = dyn_cast(e1); + if (e2 == nullptr) { + return expr; + } + auto qt = loplugin::DeclCheck(e2->getConstructor()); + if (qt.MemberFunction().Class("OStringLiteral").Namespace("rtl").GlobalNamespace() + || qt.MemberFunction().Class("OUStringLiteral").Namespace("rtl").GlobalNamespace()) + { + if (e2->getNumArgs() == 1) { + return e2->getArg(0)->IgnoreParenImpCasts(); + } + return expr; + } + if (!((qt.MemberFunction().Class("OString").Namespace("rtl") + .GlobalNamespace()) + || (qt.MemberFunction().Class("OUString").Namespace("rtl") + .GlobalNamespace()))) + { + return expr; + } + if (e2->getNumArgs() != 2) { + return expr; + } + return e2->getArg(0)->IgnoreParenImpCasts(); +} + +class StringConcatLiterals: + public loplugin::FilteringPlugin +{ +public: + explicit StringConcatLiterals(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCallExpr(CallExpr const * expr); + +private: + bool isStringLiteral(Expr const * expr); +}; + +bool StringConcatLiterals::VisitCallExpr(CallExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + FunctionDecl const * fdecl = expr->getDirectCallee(); + if (fdecl == nullptr) { + return true; + } + OverloadedOperatorKind oo = fdecl->getOverloadedOperator(); + if ((oo != OverloadedOperatorKind::OO_Plus + && oo != OverloadedOperatorKind::OO_LessLess) + || fdecl->getNumParams() != 2 || expr->getNumArgs() != 2 + || !isStringLiteral(expr->getArg(1)->IgnoreParenImpCasts())) + { + return true; + } + SourceLocation leftLoc; + auto const leftExpr = expr->getArg(0)->IgnoreParenImpCasts(); + if (isStringLiteral(leftExpr)) { + leftLoc = leftExpr->getBeginLoc(); + } else { + CallExpr const * left = dyn_cast(leftExpr); + if (left == nullptr) { + return true; + } + FunctionDecl const * ldecl = left->getDirectCallee(); + if (ldecl == nullptr) { + return true; + } + OverloadedOperatorKind loo = ldecl->getOverloadedOperator(); + if ((loo != OverloadedOperatorKind::OO_Plus + && loo != OverloadedOperatorKind::OO_LessLess) + || ldecl->getNumParams() != 2 || left->getNumArgs() != 2 + || !isStringLiteral(left->getArg(1)->IgnoreParenImpCasts())) + { + return true; + } + leftLoc = left->getArg(1)->getBeginLoc(); + } + + // We add an extra " " in the TOOLS_WARN_EXCEPTION macro, which triggers this plugin + if (loplugin::isSamePathname( + getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc( + compiler.getSourceManager().getImmediateMacroCallerLoc( + compiler.getSourceManager().getImmediateMacroCallerLoc( + compiler.getSourceManager().getImmediateMacroCallerLoc( + expr->getBeginLoc()))))), + SRCDIR "/include/tools/diagnose_ex.h")) + return true; + + StringRef name { + getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc())) }; + if (loplugin::isSamePathname( + name, SRCDIR "/sal/qa/rtl/oustringbuffer/test_oustringbuffer_assign.cxx") + || loplugin::isSamePathname( + name, SRCDIR "/sal/qa/rtl/strings/test_ostring_concat.cxx") + || loplugin::isSamePathname( + name, SRCDIR "/sal/qa/rtl/strings/test_oustring_concat.cxx")) + { + return true; + } + CXXOperatorCallExpr const * op = dyn_cast(expr); + report( + DiagnosticsEngine::Warning, + "replace '%0' between string literals with juxtaposition", + op == nullptr ? expr->getExprLoc() : op->getOperatorLoc()) + << (oo == OverloadedOperatorKind::OO_Plus ? "+" : "<<") + << SourceRange(leftLoc, expr->getArg(1)->getEndLoc()); + return true; +} + +bool StringConcatLiterals::isStringLiteral(Expr const * expr) { + expr = stripCtor(expr); + if (!isa(expr)) { + return false; + } + return true; +} + +loplugin::Plugin::Registration stringconcatliterals("stringconcatliterals"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/stringconstant.cxx b/compilerplugins/clang/stringconstant.cxx new file mode 100644 index 000000000..80b0b1388 --- /dev/null +++ b/compilerplugins/clang/stringconstant.cxx @@ -0,0 +1,2216 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" + +// Define a "string constant" to be a constant expression either of type "array +// of N char" where each array element is a non-NULL ASCII character---except +// that the last array element may be NULL, or, in some situations, of type char +// with an ASCII value (including NULL). Note that the former includes +// expressions denoting narrow string literals like "foo", and, with toolchains +// that support constexpr, constexpr variables declared like +// +// constexpr char str[] = "bar"; +// +// This plugin flags uses of OUString functions with string constant arguments +// that can be rewritten more directly, like +// +// OUString::createFromAscii("foo") -> "foo" +// +// and +// +// s.equals(OUString("bar")) -> s == "bar" + +namespace { + +SourceLocation getMemberLocation(Expr const * expr) { + CallExpr const * e1 = dyn_cast(expr); + MemberExpr const * e2 = e1 == nullptr + ? nullptr : dyn_cast(e1->getCallee()); + return e2 == nullptr ? expr->getExprLoc()/*TODO*/ : e2->getMemberLoc(); +} + +bool isLhsOfAssignment(FunctionDecl const * decl, unsigned parameter) { + if (parameter != 0) { + return false; + } + auto oo = decl->getOverloadedOperator(); + return oo == OO_Equal + || (oo >= OO_PlusEqual && oo <= OO_GreaterGreaterEqual); +} + +bool hasOverloads(FunctionDecl const * decl, unsigned arguments) { + int n = 0; + auto ctx = decl->getDeclContext(); + if (ctx->getDeclKind() == Decl::LinkageSpec) { + ctx = ctx->getParent(); + } + auto res = ctx->lookup(decl->getDeclName()); + for (auto d = res.begin(); d != res.end(); ++d) { + FunctionDecl const * f = dyn_cast(*d); + if (f != nullptr && f->getMinRequiredArguments() <= arguments + && f->getNumParams() >= arguments) + { + auto consDecl = dyn_cast(f); + if (consDecl && consDecl->isCopyOrMoveConstructor()) { + continue; + } + ++n; + if (n == 2) { + return true; + } + } + } + return false; +} + +CXXConstructExpr const * lookForCXXConstructExpr(Expr const * expr) { + if (auto e = dyn_cast(expr)) { + expr = e->getSubExpr(); + } + if (auto e = dyn_cast(expr)) { + expr = e->getSubExpr(); + } + if (auto e = dyn_cast(expr)) { + expr = e->getSubExpr(); + } + if (auto const e = dyn_cast(expr)) { + // Look through OString::operator std::string_view: + if (auto const d = dyn_cast_or_null(e->getCalleeDecl())) { + return lookForCXXConstructExpr(e->getImplicitObjectArgument()->IgnoreParenImpCasts()); + } + } + return dyn_cast(expr); +} + +char const * adviseNonArray(bool nonArray) { + return nonArray + ? ", and turn the non-array string constant into an array" : ""; +} + +class StringConstant: + public loplugin::FilteringRewritePlugin +{ +public: + explicit StringConstant(loplugin::InstantiationData const & data): + FilteringRewritePlugin(data) {} + + void run() override; + + bool TraverseFunctionDecl(FunctionDecl * decl) { + returnTypes_.push(decl->getDeclaredReturnType()); + auto const ret = RecursiveASTVisitor::TraverseFunctionDecl(decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getDeclaredReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl * decl) { + returnTypes_.push(decl->getDeclaredReturnType()); + auto const ret = RecursiveASTVisitor::TraverseCXXDeductionGuideDecl( + decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getDeclaredReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseCXXMethodDecl(CXXMethodDecl * decl) { + returnTypes_.push(decl->getDeclaredReturnType()); + auto const ret = RecursiveASTVisitor::TraverseCXXMethodDecl(decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getDeclaredReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseCXXConstructorDecl(CXXConstructorDecl * decl) { + returnTypes_.push(decl->getDeclaredReturnType()); + auto const ret = RecursiveASTVisitor::TraverseCXXConstructorDecl(decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getDeclaredReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseCXXDestructorDecl(CXXDestructorDecl * decl) { + returnTypes_.push(decl->getDeclaredReturnType()); + auto const ret = RecursiveASTVisitor::TraverseCXXDestructorDecl(decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getDeclaredReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseCXXConversionDecl(CXXConversionDecl * decl) { + returnTypes_.push(decl->getDeclaredReturnType()); + auto const ret = RecursiveASTVisitor::TraverseCXXConversionDecl(decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getDeclaredReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseObjCMethodDecl(ObjCMethodDecl * decl) { + returnTypes_.push(decl->getReturnType()); + auto const ret = RecursiveASTVisitor::TraverseObjCMethodDecl(decl); + assert(!returnTypes_.empty()); + assert(returnTypes_.top() == decl->getReturnType()); + returnTypes_.pop(); + return ret; + } + + bool TraverseCallExpr(CallExpr * expr); + + bool TraverseCXXMemberCallExpr(CXXMemberCallExpr * expr); + + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * expr); + + bool TraverseCXXConstructExpr(CXXConstructExpr * expr); + + bool VisitCallExpr(CallExpr const * expr); + + bool VisitCXXConstructExpr(CXXConstructExpr const * expr); + + bool VisitReturnStmt(ReturnStmt const * stmt); + +private: + enum class ContentKind { Ascii, Utf8, Arbitrary }; + + enum class TreatEmpty { DefaultCtor, CheckEmpty, Error }; + + enum class ChangeKind { Char, CharLen, SingleChar, OUStringChar }; + + enum class PassThrough { No, EmptyConstantString, NonEmptyConstantString }; + + std::string describeChangeKind(ChangeKind kind); + + bool isStringConstant( + Expr const * expr, unsigned * size, bool * nonArray, + ContentKind * content, bool * embeddedNuls, bool * terminatingNul, + std::vector * utf8Content = nullptr); + + bool isZero(Expr const * expr); + + void reportChange( + Expr const * expr, ChangeKind kind, std::string const & original, + std::string const & replacement, PassThrough pass, bool nonArray, + char const * rewriteFrom, char const * rewriteTo); + + void checkEmpty( + CallExpr const * expr, FunctionDecl const * callee, + TreatEmpty treatEmpty, unsigned size, std::string * replacement); + + void handleChar( + CallExpr const * expr, unsigned arg, FunctionDecl const * callee, + std::string const & replacement, TreatEmpty treatEmpty, bool literal, + char const * rewriteFrom = nullptr, char const * rewriteTo = nullptr); + + void handleCharLen( + CallExpr const * expr, unsigned arg1, unsigned arg2, + FunctionDecl const * callee, std::string const & replacement, + TreatEmpty treatEmpty); + + void handleOUStringCtor( + CallExpr const * expr, unsigned arg, FunctionDecl const * callee, + bool explicitFunctionalCastNotation); + + void handleOStringCtor( + CallExpr const * expr, unsigned arg, FunctionDecl const * callee, + bool explicitFunctionalCastNotation); + + void handleOUStringCtor( + Expr const * expr, Expr const * argExpr, FunctionDecl const * callee, + bool explicitFunctionalCastNotation); + + void handleOStringCtor( + Expr const * expr, Expr const * argExpr, FunctionDecl const * callee, + bool explicitFunctionalCastNotation); + + enum class StringKind { Unicode, Char }; + void handleStringCtor( + Expr const * expr, Expr const * argExpr, FunctionDecl const * callee, + bool explicitFunctionalCastNotation, StringKind stringKind); + + void handleFunArgOstring( + CallExpr const * expr, unsigned arg, FunctionDecl const * callee); + + std::stack returnTypes_; + std::stack calls_; +}; + +void StringConstant::run() { + if (compiler.getLangOpts().CPlusPlus + && compiler.getPreprocessor().getIdentifierInfo( + "LIBO_INTERNAL_ONLY")->hasMacroDefinition()) + //TODO: some parts of it are useful for external code, too + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } +} + +bool StringConstant::TraverseCallExpr(CallExpr * expr) { + if (!WalkUpFromCallExpr(expr)) { + return false; + } + calls_.push(expr); + bool bRes = true; + for (auto * e: expr->children()) { + if (!TraverseStmt(e)) { + bRes = false; + break; + } + } + calls_.pop(); + return bRes; +} + +bool StringConstant::TraverseCXXMemberCallExpr(CXXMemberCallExpr * expr) { + if (!WalkUpFromCXXMemberCallExpr(expr)) { + return false; + } + calls_.push(expr); + bool bRes = true; + for (auto * e: expr->children()) { + if (!TraverseStmt(e)) { + bRes = false; + break; + } + } + calls_.pop(); + return bRes; +} + +bool StringConstant::TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * expr) +{ + if (!WalkUpFromCXXOperatorCallExpr(expr)) { + return false; + } + calls_.push(expr); + bool bRes = true; + for (auto * e: expr->children()) { + if (!TraverseStmt(e)) { + bRes = false; + break; + } + } + calls_.pop(); + return bRes; +} + +bool StringConstant::TraverseCXXConstructExpr(CXXConstructExpr * expr) { + if (!WalkUpFromCXXConstructExpr(expr)) { + return false; + } + calls_.push(expr); + bool bRes = true; + for (auto * e: expr->children()) { + if (!TraverseStmt(e)) { + bRes = false; + break; + } + } + calls_.pop(); + return bRes; +} + +bool StringConstant::VisitCallExpr(CallExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + FunctionDecl const * fdecl = expr->getDirectCallee(); + if (fdecl == nullptr) { + return true; + } + for (unsigned i = 0; i != fdecl->getNumParams(); ++i) { + auto t = fdecl->getParamDecl(i)->getType(); + if (loplugin::TypeCheck(t).NotSubstTemplateTypeParmType() + .LvalueReference().Const().NotSubstTemplateTypeParmType() + .Class("OUString").Namespace("rtl").GlobalNamespace()) + { + if (!(isLhsOfAssignment(fdecl, i) + || hasOverloads(fdecl, expr->getNumArgs()))) + { + handleOUStringCtor(expr, i, fdecl, true); + } + } + if (loplugin::TypeCheck(t).NotSubstTemplateTypeParmType() + .LvalueReference().Const().NotSubstTemplateTypeParmType() + .Class("OString").Namespace("rtl").GlobalNamespace()) + { + if (!(isLhsOfAssignment(fdecl, i) + || hasOverloads(fdecl, expr->getNumArgs()))) + { + handleOStringCtor(expr, i, fdecl, true); + } + } + } + loplugin::DeclCheck dc(fdecl); + //TODO: u.compareToAscii("foo") -> u.???("foo") + //TODO: u.compareToIgnoreAsciiCaseAscii("foo") -> u.???("foo") + if ((dc.Function("createFromAscii").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 1) + { + // OUString::createFromAscii("foo") -> OUString("foo") + handleChar( + expr, 0, fdecl, "rtl::OUString constructor", + TreatEmpty::DefaultCtor, true); + return true; + } + if ((dc.Function("endsWithAsciiL").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + // u.endsWithAsciiL("foo", 3) -> u.endsWith("foo"): + handleCharLen( + expr, 0, 1, fdecl, "rtl::OUString::endsWith", TreatEmpty::Error); + return true; + } + if ((dc.Function("endsWithIgnoreAsciiCaseAsciiL").Class("OUString") + .Namespace("rtl").GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + // u.endsWithIgnoreAsciiCaseAsciiL("foo", 3) -> + // u.endsWithIgnoreAsciiCase("foo"): + handleCharLen( + expr, 0, 1, fdecl, "rtl::OUString::endsWithIgnoreAsciiCase", + TreatEmpty::Error); + return true; + } + if ((dc.Function("equalsAscii").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 1) + { + // u.equalsAscii("foo") -> u == "foo": + handleChar( + expr, 0, fdecl, "operator ==", TreatEmpty::CheckEmpty, false); + return true; + } + if ((dc.Function("equalsAsciiL").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + // u.equalsAsciiL("foo", 3) -> u == "foo": + handleCharLen(expr, 0, 1, fdecl, "operator ==", TreatEmpty::CheckEmpty); + return true; + } + if ((dc.Function("equalsIgnoreAsciiCaseAscii").Class("OUString") + .Namespace("rtl").GlobalNamespace()) + && fdecl->getNumParams() == 1) + { + // u.equalsIgnoreAsciiCaseAscii("foo") -> + // u.equalsIngoreAsciiCase("foo"): + + auto file = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc())); + if (loplugin::isSamePathname( + file, SRCDIR "/sal/qa/rtl/strings/test_oustring_compare.cxx")) + { + return true; + } + handleChar( + expr, 0, fdecl, "rtl::OUString::equalsIgnoreAsciiCase", + TreatEmpty::CheckEmpty, false); + return true; + } + if ((dc.Function("equalsIgnoreAsciiCaseAsciiL").Class("OUString") + .Namespace("rtl").GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + // u.equalsIgnoreAsciiCaseAsciiL("foo", 3) -> + // u.equalsIngoreAsciiCase("foo"): + auto file = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc())); + if (loplugin::isSamePathname( + file, SRCDIR "/sal/qa/rtl/strings/test_oustring_compare.cxx")) + { + return true; + } + handleCharLen( + expr, 0, 1, fdecl, "rtl::OUString::equalsIgnoreAsciiCase", + TreatEmpty::CheckEmpty); + return true; + } + if ((dc.Function("indexOfAsciiL").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 3) + { + assert(expr->getNumArgs() == 3); + // u.indexOfAsciiL("foo", 3, i) -> u.indexOf("foo", i): + handleCharLen( + expr, 0, 1, fdecl, "rtl::OUString::indexOf", TreatEmpty::Error); + return true; + } + if ((dc.Function("lastIndexOfAsciiL").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + // u.lastIndexOfAsciiL("foo", 3) -> u.lastIndexOf("foo"): + handleCharLen( + expr, 0, 1, fdecl, "rtl::OUString::lastIndexOf", TreatEmpty::Error); + return true; + } + if ((dc.Function("matchAsciiL").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 3) + { + assert(expr->getNumArgs() == 3); + // u.matchAsciiL("foo", 3, i) -> u.match("foo", i): + handleCharLen( + expr, 0, 1, fdecl, + (isZero(expr->getArg(2)) + ? std::string("rtl::OUString::startsWith") + : std::string("rtl::OUString::match")), + TreatEmpty::Error); + return true; + } + if ((dc.Function("matchIgnoreAsciiCaseAsciiL").Class("OUString") + .Namespace("rtl").GlobalNamespace()) + && fdecl->getNumParams() == 3) + { + assert(expr->getNumArgs() == 3); + // u.matchIgnoreAsciiCaseAsciiL("foo", 3, i) -> + // u.matchIgnoreAsciiCase("foo", i): + handleCharLen( + expr, 0, 1, fdecl, + (isZero(expr->getArg(2)) + ? std::string("rtl::OUString::startsWithIgnoreAsciiCase") + : std::string("rtl::OUString::matchIgnoreAsciiCase")), + TreatEmpty::Error); + return true; + } + if ((dc.Function("reverseCompareToAsciiL").Class("OUString") + .Namespace("rtl").GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + // u.reverseCompareToAsciiL("foo", 3) -> u.reverseCompareTo("foo"): + handleCharLen( + expr, 0, 1, fdecl, "rtl::OUString::reverseCompareTo", + TreatEmpty::Error); + return true; + } + if ((dc.Function("reverseCompareTo").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 1) + { + handleOUStringCtor(expr, 0, fdecl, false); + return true; + } + if ((dc.Function("equalsIgnoreAsciiCase").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 1) + { + handleOUStringCtor(expr, 0, fdecl, false); + return true; + } + if ((dc.Function("match").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + handleOUStringCtor(expr, 0, fdecl, false); + return true; + } + if ((dc.Function("matchIgnoreAsciiCase").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + handleOUStringCtor(expr, 0, fdecl, false); + return true; + } + if ((dc.Function("startsWith").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + handleOUStringCtor(expr, 0, fdecl, false); + return true; + } + if ((dc.Function("startsWithIgnoreAsciiCase").Class("OUString") + .Namespace("rtl").GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + handleOUStringCtor(expr, 0, fdecl, false); + return true; + } + if ((dc.Function("endsWith").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + handleOUStringCtor(expr, 0, fdecl, false); + return true; + } + if ((dc.Function("endsWithIgnoreAsciiCase").Class("OUString") + .Namespace("rtl").GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + handleOUStringCtor(expr, 0, fdecl, false); + return true; + } + if ((dc.Function("indexOf").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + handleOUStringCtor(expr, 0, fdecl, false); + return true; + } + if ((dc.Function("lastIndexOf").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 1) + { + handleOUStringCtor(expr, 0, fdecl, false); + return true; + } + if ((dc.Function("replaceFirst").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 3) + { + handleOUStringCtor(expr, 0, fdecl, false); + handleOUStringCtor(expr, 1, fdecl, false); + return true; + } + if ((dc.Function("replaceAll").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && (fdecl->getNumParams() == 2 || fdecl->getNumParams() == 3)) + { + handleOUStringCtor(expr, 0, fdecl, false); + handleOUStringCtor(expr, 1, fdecl, false); + return true; + } + if ((dc.Operator(OO_PlusEqual).Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 1) + { + handleOUStringCtor( + expr, dyn_cast(expr) == nullptr ? 0 : 1, + fdecl, false); + return true; + } + if ((dc.Function("equals").Class("OUString").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 1) + { + unsigned n; + bool nonArray; + ContentKind cont; + bool emb; + bool trm; + if (!isStringConstant( + expr->getArg(0)->IgnoreParenImpCasts(), &n, &nonArray, &cont, + &emb, &trm)) + { + return true; + } + if (cont != ContentKind::Ascii) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument containing" + " non-ASCII characters"), + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() << expr->getSourceRange(); + } + if (emb) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument containing" + " embedded NULLs"), + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() << expr->getSourceRange(); + } + if (n == 0) { + report( + DiagnosticsEngine::Warning, + ("rewrite call of '%0' with empty string constant argument as" + " call of 'rtl::OUString::isEmpty'"), + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() << expr->getSourceRange(); + return true; + } + } + if (dc.Operator(OO_EqualEqual).Namespace("rtl").GlobalNamespace() + && fdecl->getNumParams() == 2) + { + for (unsigned i = 0; i != 2; ++i) { + unsigned n; + bool nonArray; + ContentKind cont; + bool emb; + bool trm; + if (!isStringConstant( + expr->getArg(i)->IgnoreParenImpCasts(), &n, &nonArray, + &cont, &emb, &trm)) + { + continue; + } + if (cont != ContentKind::Ascii) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument containing" + " non-ASCII characters"), + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() + << expr->getSourceRange(); + } + if (emb) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument containing" + " embedded NULLs"), + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() + << expr->getSourceRange(); + } + if (n == 0) { + report( + DiagnosticsEngine::Warning, + ("rewrite call of '%0' with empty string constant argument" + " as call of 'rtl::OUString::isEmpty'"), + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() + << expr->getSourceRange(); + } + } + return true; + } + if (dc.Operator(OO_ExclaimEqual).Namespace("rtl").GlobalNamespace() + && fdecl->getNumParams() == 2) + { + for (unsigned i = 0; i != 2; ++i) { + unsigned n; + bool nonArray; + ContentKind cont; + bool emb; + bool trm; + if (!isStringConstant( + expr->getArg(i)->IgnoreParenImpCasts(), &n, &nonArray, + &cont, &emb, &trm)) + { + continue; + } + if (cont != ContentKind::Ascii) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument containing" + " non-ASCII characters"), + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() + << expr->getSourceRange(); + } + if (emb) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument containing" + " embedded NULLs"), + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() + << expr->getSourceRange(); + } + if (n == 0) { + report( + DiagnosticsEngine::Warning, + ("rewrite call of '%0' with empty string constant argument" + " as call of '!rtl::OUString::isEmpty'"), + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() + << expr->getSourceRange(); + } + } + return true; + } + if (dc.Operator(OO_Equal).Namespace("rtl").GlobalNamespace() + && fdecl->getNumParams() == 1) + { + unsigned n; + bool nonArray; + ContentKind cont; + bool emb; + bool trm; + if (!isStringConstant( + expr->getArg(1)->IgnoreParenImpCasts(), &n, &nonArray, &cont, + &emb, &trm)) + { + return true; + } + if (cont != ContentKind::Ascii) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument containing" + " non-ASCII characters"), + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() << expr->getSourceRange(); + } + if (emb) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument containing" + " embedded NULLs"), + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() << expr->getSourceRange(); + } + if (n == 0) { + report( + DiagnosticsEngine::Warning, + ("rewrite call of '%0' with empty string constant argument as" + " call of 'rtl::OUString::clear'"), + expr->getExprLoc()) + << fdecl->getQualifiedNameAsString() << expr->getSourceRange(); + return true; + } + return true; + } + if (dc.Function("append").Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + && fdecl->getNumParams() == 1) + { + handleChar(expr, 0, fdecl, "", TreatEmpty::Error, false); + return true; + } + if ((dc.Function("appendAscii").Class("OUStringBuffer").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 1) + { + // u.appendAscii("foo") -> u.append("foo") + handleChar( + expr, 0, fdecl, "rtl::OUStringBuffer::append", TreatEmpty::Error, + true, "appendAscii", "append"); + return true; + } + if ((dc.Function("appendAscii").Class("OUStringBuffer").Namespace("rtl") + .GlobalNamespace()) + && fdecl->getNumParams() == 2) + { + // u.appendAscii("foo", 3) -> u.append("foo"): + handleCharLen( + expr, 0, 1, fdecl, "rtl::OUStringBuffer::append", + TreatEmpty::Error); + return true; + } + if (dc.Function("append").Class("OStringBuffer").Namespace("rtl") + .GlobalNamespace()) + { + switch (fdecl->getNumParams()) { + case 1: + handleFunArgOstring(expr, 0, fdecl); + break; + case 2: + { + // b.append("foo", 3) -> b.append("foo"): + auto file = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc( + expr->getBeginLoc())); + if (loplugin::isSamePathname( + file, + SRCDIR "/sal/qa/OStringBuffer/rtl_OStringBuffer.cxx")) + { + return true; + } + handleCharLen( + expr, 0, 1, fdecl, "rtl::OStringBuffer::append", + TreatEmpty::Error); + } + break; + default: + break; + } + return true; + } + if (dc.Function("insert").Class("OStringBuffer").Namespace("rtl") + .GlobalNamespace()) + { + switch (fdecl->getNumParams()) { + case 2: + handleFunArgOstring(expr, 1, fdecl); + break; + case 3: + { + // b.insert(i, "foo", 3) -> b.insert(i, "foo"): + handleCharLen( + expr, 1, 2, fdecl, "rtl::OStringBuffer::insert", + TreatEmpty::Error); + break; + } + default: + break; + } + return true; + } + return true; +} + +bool StringConstant::VisitCXXConstructExpr(CXXConstructExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto classdecl = expr->getConstructor()->getParent(); + if (loplugin::DeclCheck(classdecl) + .Class("OUString").Namespace("rtl").GlobalNamespace()) + { + ChangeKind kind; + PassThrough pass; + bool simplify; + switch (expr->getConstructor()->getNumParams()) { + case 1: + if (!loplugin::TypeCheck( + expr->getConstructor()->getParamDecl(0)->getType()) + .Typedef("sal_Unicode").GlobalNamespace()) + { + return true; + } + kind = ChangeKind::SingleChar; + pass = PassThrough::NonEmptyConstantString; + simplify = false; + break; + case 2: + { + auto arg = expr->getArg(0); + if (loplugin::TypeCheck(arg->getType()) + .Class("OUStringChar_").Namespace("rtl") + .GlobalNamespace()) + { + kind = ChangeKind::OUStringChar; + pass = PassThrough::NonEmptyConstantString; + simplify = false; + } else { + unsigned n; + bool nonArray; + ContentKind cont; + bool emb; + bool trm; + if (!isStringConstant( + arg->IgnoreParenImpCasts(), &n, &nonArray, &cont, + &emb, &trm)) + { + return true; + } + if (cont != ContentKind::Ascii) { + report( + DiagnosticsEngine::Warning, + ("construction of %0 with string constant argument" + " containing non-ASCII characters"), + expr->getExprLoc()) + << classdecl << expr->getSourceRange(); + } + if (emb) { + report( + DiagnosticsEngine::Warning, + ("construction of %0 with string constant argument" + " containing embedded NULLs"), + expr->getExprLoc()) + << classdecl << expr->getSourceRange(); + } + kind = ChangeKind::Char; + pass = n == 0 + ? PassThrough::EmptyConstantString + : PassThrough::NonEmptyConstantString; + simplify = false; + } + break; + } + case 4: + { + unsigned n; + bool nonArray; + ContentKind cont; + bool emb; + bool trm; + std::vector utf8Cont; + if (!isStringConstant( + expr->getArg(0)->IgnoreParenImpCasts(), &n, &nonArray, + &cont, &emb, &trm, &utf8Cont)) + { + return true; + } + APSInt res; + if (!compat::EvaluateAsInt(expr->getArg(1), + res, compiler.getASTContext())) + { + return true; + } + if (res != n) { + report( + DiagnosticsEngine::Warning, + ("suspicious 'rtl::OUString' constructor with literal" + " of length %0 and non-matching length argument %1"), + expr->getExprLoc()) + << n << compat::toString(res, 10) << expr->getSourceRange(); + return true; + } + APSInt enc; + if (!compat::EvaluateAsInt(expr->getArg(2), + enc, compiler.getASTContext())) + { + return true; + } + auto const encIsAscii = enc == 11; // RTL_TEXTENCODING_ASCII_US + auto const encIsUtf8 = enc == 76; // RTL_TEXTENCODING_UTF8 + if (!compat::EvaluateAsInt(expr->getArg(3), + res, compiler.getASTContext()) + || res != 0x333) // OSTRING_TO_OUSTRING_CVTFLAGS + { + return true; + } + if (!encIsAscii && cont == ContentKind::Ascii) { + report( + DiagnosticsEngine::Warning, + ("suspicious 'rtl::OUString' constructor with text" + " encoding %0 but plain ASCII content; use" + " 'RTL_TEXTENCODING_ASCII_US' instead"), + expr->getArg(2)->getExprLoc()) + << compat::toString(enc, 10) << expr->getSourceRange(); + return true; + } + if (encIsUtf8) { + if (cont == ContentKind::Arbitrary) { + report( + DiagnosticsEngine::Warning, + ("suspicious 'rtl::OUString' constructor with text" + " encoding 'RTL_TEXTENCODING_UTF8' but non-UTF-8" + " content"), + expr->getArg(0)->getExprLoc()) + << expr->getSourceRange(); + } else { + assert(cont == ContentKind::Utf8); + //TODO: keep original content as much as possible + std::ostringstream s; + for (auto const c: utf8Cont) { + if (c == '\\') { + s << "\\\\"; + } else if (c == '"') { + s << "\\\""; + } else if (c == '\a') { + s << "\\a"; + } else if (c == '\b') { + s << "\\b"; + } else if (c == '\f') { + s << "\\f"; + } else if (c == '\n') { + s << "\\n"; + } else if (c == '\r') { + s << "\\r"; + } else if (c == '\t') { + s << "\\r"; + } else if (c == '\v') { + s << "\\v"; + } else if (c <= 0x1F || c == 0x7F) { + s << "\\x" << std::oct << std::setw(3) + << std::setfill('0') + << static_cast(c); + } else if (c < 0x7F) { + s << char(c); + } else if (c <= 0xFFFF) { + s << "\\u" << std::hex << std::uppercase + << std::setw(4) << std::setfill('0') + << static_cast(c); + } else { + assert(c <= 0x10FFFF); + s << "\\U" << std::hex << std::uppercase + << std::setw(8) << std::setfill('0') + << static_cast(c); + } + } + report( + DiagnosticsEngine::Warning, + ("simplify construction of %0 with UTF-8 content as" + " OUString(u\"%1\")"), + expr->getExprLoc()) + << classdecl << s.str() << expr->getSourceRange(); + + } + return true; + } + if (cont != ContentKind::Ascii || emb) { + // cf. remaining uses of RTL_CONSTASCII_USTRINGPARAM + return true; + } + kind = ChangeKind::Char; + pass = n == 0 + ? PassThrough::EmptyConstantString + : PassThrough::NonEmptyConstantString; + simplify = true; + break; + } + default: + return true; + } + if (!calls_.empty()) { + Expr const * call = calls_.top(); + CallExpr::const_arg_iterator argsBeg; + CallExpr::const_arg_iterator argsEnd; + if (isa(call)) { + argsBeg = cast(call)->arg_begin(); + argsEnd = cast(call)->arg_end(); + } else if (isa(call)) { + argsBeg = cast(call)->arg_begin(); + argsEnd = cast(call)->arg_end(); + } else { + assert(false); + } + for (auto i(argsBeg); i != argsEnd; ++i) { + Expr const * e = (*i)->IgnoreParenImpCasts(); + if (isa(e)) { + e = cast(e)->getSubExpr() + ->IgnoreParenImpCasts(); + } + if (isa(e)) { + e = cast(e)->getSubExpr() + ->IgnoreParenImpCasts(); + } + if (isa(e)) { + e = cast(e)->getSubExpr() + ->IgnoreParenImpCasts(); + } + if (e == expr) { + if (isa(call)) { + FunctionDecl const * fdecl + = cast(call)->getDirectCallee(); + if (fdecl == nullptr) { + break; + } + loplugin::DeclCheck dc(fdecl); + if (pass == PassThrough::EmptyConstantString) { + if ((dc.Function("equals").Class("OUString") + .Namespace("rtl").GlobalNamespace()) + || (dc.Operator(OO_EqualEqual).Namespace("rtl") + .GlobalNamespace())) + { + report( + DiagnosticsEngine::Warning, + ("rewrite call of '%0' with construction of" + " %1 with empty string constant argument" + " as call of 'rtl::OUString::isEmpty'"), + getMemberLocation(call)) + << fdecl->getQualifiedNameAsString() + << classdecl << call->getSourceRange(); + return true; + } + if (dc.Operator(OO_ExclaimEqual).Namespace("rtl") + .GlobalNamespace()) + { + report( + DiagnosticsEngine::Warning, + ("rewrite call of '%0' with construction of" + " %1 with empty string constant argument" + " as call of '!rtl::OUString::isEmpty'"), + getMemberLocation(call)) + << fdecl->getQualifiedNameAsString() + << classdecl << call->getSourceRange(); + return true; + } + if ((dc.Operator(OO_Plus).Namespace("rtl") + .GlobalNamespace()) + || (dc.Operator(OO_Plus).Class("OUString") + .Namespace("rtl").GlobalNamespace())) + { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with suspicious construction" + " of %1 with empty string constant" + " argument"), + getMemberLocation(call)) + << fdecl->getQualifiedNameAsString() + << classdecl << call->getSourceRange(); + return true; + } + if (dc.Operator(OO_Equal).Class("OUString") + .Namespace("rtl").GlobalNamespace()) + { + report( + DiagnosticsEngine::Warning, + ("rewrite call of '%0' with construction of" + " %1 with empty string constant argument" + " as call of 'rtl::OUString::clear'"), + getMemberLocation(call)) + << fdecl->getQualifiedNameAsString() + << classdecl << call->getSourceRange(); + return true; + } + } else { + assert(pass == PassThrough::NonEmptyConstantString); + if (dc.Function("equals").Class("OUString") + .Namespace("rtl").GlobalNamespace()) + { + report( + DiagnosticsEngine::Warning, + ("rewrite call of '%0' with construction of" + " %1 with %2 as 'operator =='"), + getMemberLocation(call)) + << fdecl->getQualifiedNameAsString() + << classdecl << describeChangeKind(kind) + << call->getSourceRange(); + return true; + } + if ((dc.Operator(OO_Plus).Namespace("rtl") + .GlobalNamespace()) + || (dc.Operator(OO_Plus).Class("OUString") + .Namespace("rtl").GlobalNamespace()) + || (dc.Operator(OO_EqualEqual).Namespace("rtl") + .GlobalNamespace()) + || (dc.Operator(OO_ExclaimEqual) + .Namespace("rtl").GlobalNamespace())) + { + if (dc.Operator(OO_Plus).Namespace("rtl") + .GlobalNamespace()) + { + auto file = getFilenameOfLocation( + compiler.getSourceManager() + .getSpellingLoc( + expr->getBeginLoc())); + if (loplugin::isSamePathname( + file, + (SRCDIR + "/sal/qa/rtl/strings/test_ostring_concat.cxx")) + || loplugin::isSamePathname( + file, + (SRCDIR + "/sal/qa/rtl/strings/test_oustring_concat.cxx"))) + { + return true; + } + } + auto loc = expr->getArg(0)->getBeginLoc(); + while (compiler.getSourceManager() + .isMacroArgExpansion(loc)) + { + loc = compiler.getSourceManager() + .getImmediateMacroCallerLoc(loc); + } + if (kind == ChangeKind::SingleChar) { + report( + DiagnosticsEngine::Warning, + ("rewrite construction of %0 with %1 in" + " call of '%2' as construction of" + " 'OUStringChar'"), + getMemberLocation(expr)) + << classdecl << describeChangeKind(kind) + << fdecl->getQualifiedNameAsString() + << expr->getSourceRange(); + } else { + report( + DiagnosticsEngine::Warning, + ("elide construction of %0 with %1 in" + " call of '%2'"), + getMemberLocation(expr)) + << classdecl << describeChangeKind(kind) + << fdecl->getQualifiedNameAsString() + << expr->getSourceRange(); + } + return true; + } + } + } else if (isa(call)) { + } else { + assert(false); + } + } + } + } + if (simplify) { + report( + DiagnosticsEngine::Warning, + "simplify construction of %0 with %1", expr->getExprLoc()) + << classdecl << describeChangeKind(kind) + << expr->getSourceRange(); + } + return true; + } + + auto consDecl = expr->getConstructor(); + for (unsigned i = 0; i != consDecl->getNumParams(); ++i) { + auto t = consDecl->getParamDecl(i)->getType(); + if (loplugin::TypeCheck(t).NotSubstTemplateTypeParmType() + .LvalueReference().Const().NotSubstTemplateTypeParmType() + .Class("OUString").Namespace("rtl").GlobalNamespace()) + { + auto argExpr = expr->getArg(i); + if (argExpr && i <= consDecl->getNumParams()) + { + if (!hasOverloads(consDecl, expr->getNumArgs())) + { + handleOUStringCtor(expr, argExpr, consDecl, true); + } + } + } + if (loplugin::TypeCheck(t).NotSubstTemplateTypeParmType() + .LvalueReference().Const().NotSubstTemplateTypeParmType() + .Class("OString").Namespace("rtl").GlobalNamespace()) + { + auto argExpr = expr->getArg(i); + if (argExpr && i <= consDecl->getNumParams()) + { + if (!hasOverloads(consDecl, expr->getNumArgs())) + { + handleOStringCtor(expr, argExpr, consDecl, true); + } + } + } + } + + return true; +} + +bool StringConstant::VisitReturnStmt(ReturnStmt const * stmt) { + if (ignoreLocation(stmt)) { + return true; + } + auto const e1 = stmt->getRetValue(); + if (e1 == nullptr) { + return true; + } + auto const tc1 = loplugin::TypeCheck(e1->getType().getTypePtr()); + if (!(tc1.Class("OString").Namespace("rtl").GlobalNamespace() + || tc1.Class("OUString").Namespace("rtl").GlobalNamespace())) + { + return true; + } + assert(!returnTypes_.empty()); + auto const tc2 = loplugin::TypeCheck(returnTypes_.top().getTypePtr()); + if (!(tc2.Class("OString").Namespace("rtl").GlobalNamespace() + || tc2.Class("OUString").Namespace("rtl").GlobalNamespace())) + { + return true; + } + auto const e2 = dyn_cast(e1->IgnoreImplicit()); + if (e2 == nullptr) { + return true; + } + auto const e3 = dyn_cast(e2->getSubExpr()); + if (e3 == nullptr) { + return true; + } + auto const e4 = dyn_cast(e3->getSubExpr()); + if (e4 == nullptr) { + return true; + } + if (e4->getNumArgs() != 2) { + return true; + } + auto const t = e4->getArg(0)->getType(); + if (!(t.isConstQualified() && t->isConstantArrayType())) { + return true; + } + auto const e5 = e4->getArg(1); + if (!(isa(e5) + && (loplugin::TypeCheck(e5->getType()).Struct("Dummy").Namespace("libreoffice_internal") + .Namespace("rtl").GlobalNamespace()))) + { + return true; + } + report(DiagnosticsEngine::Warning, "elide constructor call", e1->getBeginLoc()) + << e1->getSourceRange(); + return true; +} + +std::string StringConstant::describeChangeKind(ChangeKind kind) { + switch (kind) { + case ChangeKind::Char: + return "string constant argument"; + case ChangeKind::CharLen: + return "string constant and matching length arguments"; + case ChangeKind::SingleChar: + return "sal_Unicode argument"; + case ChangeKind::OUStringChar: + return "OUStringChar argument"; + } + llvm_unreachable("unknown change kind"); +} + +bool StringConstant::isStringConstant( + Expr const * expr, unsigned * size, bool * nonArray, ContentKind * content, + bool * embeddedNuls, bool * terminatingNul, + std::vector * utf8Content) +{ + assert(expr != nullptr); + assert(size != nullptr); + assert(nonArray != nullptr); + assert(content != nullptr); + assert(embeddedNuls != nullptr); + assert(terminatingNul != nullptr); + QualType t = expr->getType(); + // Look inside RTL_CONSTASCII_STRINGPARAM: + if (loplugin::TypeCheck(t).Pointer().Const().Char()) { + auto e2 = dyn_cast(expr); + if (e2 != nullptr && e2->getOpcode() == UO_AddrOf) { + auto e3 = dyn_cast( + e2->getSubExpr()->IgnoreParenImpCasts()); + if (e3 == nullptr || !isZero(e3->getIdx()->IgnoreParenImpCasts())) { + return false; + } + expr = e3->getBase()->IgnoreParenImpCasts(); + t = expr->getType(); + } + } + if (!t.isConstQualified()) { + return false; + } + DeclRefExpr const * dre = dyn_cast(expr); + if (dre != nullptr) { + VarDecl const * var = dyn_cast(dre->getDecl()); + if (var != nullptr) { + Expr const * init = var->getAnyInitializer(); + if (init != nullptr) { + expr = init->IgnoreParenImpCasts(); + } + } + } + bool isPtr; + if (loplugin::TypeCheck(t).Pointer().Const().Char()) { + isPtr = true; + } else if (t->isConstantArrayType() + && (loplugin::TypeCheck( + t->getAsArrayTypeUnsafe()->getElementType()) + .Char())) + { + isPtr = false; + } else { + return false; + } + clang::StringLiteral const * lit = dyn_cast(expr); + if (lit != nullptr) { + if (!(lit->isAscii() || lit->isUTF8())) { + return false; + } + unsigned n = lit->getLength(); + ContentKind cont = ContentKind::Ascii; + bool emb = false; + char32_t val = 0; + enum class Utf8State { Start, E0, EB, F0, F4, Trail1, Trail2, Trail3 }; + Utf8State s = Utf8State::Start; + StringRef str = lit->getString(); + for (unsigned i = 0; i != n; ++i) { + auto const c = static_cast(str[i]); + if (c == '\0') { + emb = true; + } + switch (s) { + case Utf8State::Start: + if (c >= 0x80) { + if (c >= 0xC2 && c <= 0xDF) { + val = c & 0x1F; + s = Utf8State::Trail1; + } else if (c == 0xE0) { + val = c & 0x0F; + s = Utf8State::E0; + } else if ((c >= 0xE1 && c <= 0xEA) + || (c >= 0xEE && c <= 0xEF)) + { + val = c & 0x0F; + s = Utf8State::Trail2; + } else if (c == 0xEB) { + val = c & 0x0F; + s = Utf8State::EB; + } else if (c == 0xF0) { + val = c & 0x03; + s = Utf8State::F0; + } else if (c >= 0xF1 && c <= 0xF3) { + val = c & 0x03; + s = Utf8State::Trail3; + } else if (c == 0xF4) { + val = c & 0x03; + s = Utf8State::F4; + } else { + cont = ContentKind::Arbitrary; + } + } else if (utf8Content != nullptr + && cont != ContentKind::Arbitrary) + { + utf8Content->push_back(c); + } + break; + case Utf8State::E0: + if (c >= 0xA0 && c <= 0xBF) { + val = (val << 6) | (c & 0x3F); + s = Utf8State::Trail1; + } else { + cont = ContentKind::Arbitrary; + s = Utf8State::Start; + } + break; + case Utf8State::EB: + if (c >= 0x80 && c <= 0x9F) { + val = (val << 6) | (c & 0x3F); + s = Utf8State::Trail1; + } else { + cont = ContentKind::Arbitrary; + s = Utf8State::Start; + } + break; + case Utf8State::F0: + if (c >= 0x90 && c <= 0xBF) { + val = (val << 6) | (c & 0x3F); + s = Utf8State::Trail2; + } else { + cont = ContentKind::Arbitrary; + s = Utf8State::Start; + } + break; + case Utf8State::F4: + if (c >= 0x80 && c <= 0x8F) { + val = (val << 6) | (c & 0x3F); + s = Utf8State::Trail2; + } else { + cont = ContentKind::Arbitrary; + s = Utf8State::Start; + } + break; + case Utf8State::Trail1: + if (c >= 0x80 && c <= 0xBF) { + cont = ContentKind::Utf8; + if (utf8Content != nullptr) + { + utf8Content->push_back((val << 6) | (c & 0x3F)); + val = 0; + } + } else { + cont = ContentKind::Arbitrary; + } + s = Utf8State::Start; + break; + case Utf8State::Trail2: + if (c >= 0x80 && c <= 0xBF) { + val = (val << 6) | (c & 0x3F); + s = Utf8State::Trail1; + } else { + cont = ContentKind::Arbitrary; + s = Utf8State::Start; + } + break; + case Utf8State::Trail3: + if (c >= 0x80 && c <= 0xBF) { + val = (val << 6) | (c & 0x3F); + s = Utf8State::Trail2; + } else { + cont = ContentKind::Arbitrary; + s = Utf8State::Start; + } + break; + } + } + *size = n; + *nonArray = isPtr; + *content = cont; + *embeddedNuls = emb; + *terminatingNul = true; + return true; + } + APValue v; + if (!expr->isCXX11ConstantExpr(compiler.getASTContext(), &v)) { + return false; + } + switch (v.getKind()) { + case APValue::LValue: + { + Expr const * e = v.getLValueBase().dyn_cast(); + if (e == nullptr) { + return false; + } + if (!v.getLValueOffset().isZero()) { + return false; //TODO + } + Expr const * e2 = e->IgnoreParenImpCasts(); + if (e2 != e) { + return isStringConstant( + e2, size, nonArray, content, embeddedNuls, terminatingNul); + } + //TODO: string literals are represented as recursive LValues??? + llvm::APInt n + = compiler.getASTContext().getAsConstantArrayType(t)->getSize(); + assert(n != 0); + --n; + assert(n.ule(std::numeric_limits::max())); + *size = static_cast(n.getLimitedValue()); + *nonArray = isPtr || *nonArray; + *content = ContentKind::Ascii; //TODO + *embeddedNuls = false; //TODO + *terminatingNul = true; + return true; + } + case APValue::Array: + { + if (v.hasArrayFiller()) { //TODO: handle final NULL filler? + return false; + } + unsigned n = v.getArraySize(); + assert(n != 0); + ContentKind cont = ContentKind::Ascii; + bool emb = false; + //TODO: check for ContentType::Utf8 + for (unsigned i = 0; i != n - 1; ++i) { + APValue e(v.getArrayInitializedElt(i)); + if (!e.isInt()) { //TODO: assert? + return false; + } + APSInt iv = e.getInt(); + if (iv == 0) { + emb = true; + } else if (iv.uge(0x80)) { + cont = ContentKind::Arbitrary; + } + } + APValue e(v.getArrayInitializedElt(n - 1)); + if (!e.isInt()) { //TODO: assert? + return false; + } + bool trm = e.getInt() == 0; + *size = trm ? n - 1 : n; + *nonArray = isPtr; + *content = cont; + *embeddedNuls = emb; + *terminatingNul = trm; + return true; + } + default: + assert(false); //TODO??? + return false; + } +} + +bool StringConstant::isZero(Expr const * expr) { + APSInt res; + return compat::EvaluateAsInt(expr, res, compiler.getASTContext()) && res == 0; +} + +void StringConstant::reportChange( + Expr const * expr, ChangeKind kind, std::string const & original, + std::string const & replacement, PassThrough pass, bool nonArray, + char const * rewriteFrom, char const * rewriteTo) +{ + assert((rewriteFrom == nullptr) == (rewriteTo == nullptr)); + if (pass != PassThrough::No && !calls_.empty()) { + Expr const * call = calls_.top(); + CallExpr::const_arg_iterator argsBeg; + CallExpr::const_arg_iterator argsEnd; + if (isa(call)) { + argsBeg = cast(call)->arg_begin(); + argsEnd = cast(call)->arg_end(); + } else if (isa(call)) { + argsBeg = cast(call)->arg_begin(); + argsEnd = cast(call)->arg_end(); + } else { + assert(false); + } + for (auto i(argsBeg); i != argsEnd; ++i) { + Expr const * e = (*i)->IgnoreParenImpCasts(); + if (isa(e)) { + e = cast(e)->getSubExpr() + ->IgnoreParenImpCasts(); + } + if (e == expr) { + if (isa(call)) { + FunctionDecl const * fdecl + = cast(call)->getDirectCallee(); + if (fdecl == nullptr) { + break; + } + loplugin::DeclCheck dc(fdecl); + if (pass == PassThrough::EmptyConstantString) { + if ((dc.Function("equals").Class("OUString") + .Namespace("rtl").GlobalNamespace()) + || (dc.Operator(OO_EqualEqual).Namespace("rtl") + .GlobalNamespace())) + { + report( + DiagnosticsEngine::Warning, + ("rewrite call of '%0' with call of %1 with" + " empty string constant argument as call of" + " 'rtl::OUString::isEmpty'"), + getMemberLocation(call)) + << fdecl->getQualifiedNameAsString() << original + << call->getSourceRange(); + return; + } + if (dc.Operator(OO_ExclaimEqual).Namespace("rtl") + .GlobalNamespace()) + { + report( + DiagnosticsEngine::Warning, + ("rewrite call of '%0' with call of %1 with" + " empty string constant argument as call of" + " '!rtl::OUString::isEmpty'"), + getMemberLocation(call)) + << fdecl->getQualifiedNameAsString() << original + << call->getSourceRange(); + return; + } + if ((dc.Operator(OO_Plus).Namespace("rtl") + .GlobalNamespace()) + || (dc.Operator(OO_Plus).Class("OUString") + .Namespace("rtl").GlobalNamespace())) + { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with suspicious call of %1 with" + " empty string constant argument"), + getMemberLocation(call)) + << fdecl->getQualifiedNameAsString() << original + << call->getSourceRange(); + return; + } + if (dc.Operator(OO_Equal).Class("OUString") + .Namespace("rtl").GlobalNamespace()) + { + report( + DiagnosticsEngine::Warning, + ("rewrite call of '%0' with call of %1 with" + " empty string constant argument as call of" + " rtl::OUString::call"), + getMemberLocation(call)) + << fdecl->getQualifiedNameAsString() << original + << call->getSourceRange(); + return; + } + report( + DiagnosticsEngine::Warning, + "TODO call inside %0", getMemberLocation(expr)) + << fdecl->getQualifiedNameAsString() + << expr->getSourceRange(); + return; + } else { + assert(pass == PassThrough::NonEmptyConstantString); + if ((dc.Function("equals").Class("OUString") + .Namespace("rtl").GlobalNamespace()) + || (dc.Operator(OO_Equal).Class("OUString") + .Namespace("rtl").GlobalNamespace()) + || (dc.Operator(OO_EqualEqual).Namespace("rtl") + .GlobalNamespace()) + || (dc.Operator(OO_ExclaimEqual).Namespace("rtl") + .GlobalNamespace())) + { + report( + DiagnosticsEngine::Warning, + "elide call of %0 with %1 in call of '%2'", + getMemberLocation(expr)) + << original << describeChangeKind(kind) + << fdecl->getQualifiedNameAsString() + << expr->getSourceRange(); + return; + } + report( + DiagnosticsEngine::Warning, + ("rewrite call of %0 with %1 in call of '%2' as" + " (implicit) construction of 'OUString'"), + getMemberLocation(expr)) + << original << describeChangeKind(kind) + << fdecl->getQualifiedNameAsString() + << expr->getSourceRange(); + return; + } + } else if (isa(call)) { + auto classdecl = cast(call) + ->getConstructor()->getParent(); + loplugin::DeclCheck dc(classdecl); + if (dc.Class("OUString").Namespace("rtl").GlobalNamespace() + || (dc.Class("OUStringBuffer").Namespace("rtl") + .GlobalNamespace())) + { + //TODO: propagate further out? + if (pass == PassThrough::EmptyConstantString) { + report( + DiagnosticsEngine::Warning, + ("rewrite construction of %0 with call of %1" + " with empty string constant argument as" + " default construction of %0"), + getMemberLocation(call)) + << classdecl << original + << call->getSourceRange(); + } else { + assert(pass == PassThrough::NonEmptyConstantString); + report( + DiagnosticsEngine::Warning, + ("elide call of %0 with %1 in construction of" + " %2"), + getMemberLocation(expr)) + << original << describeChangeKind(kind) + << classdecl << expr->getSourceRange(); + } + return; + } + } else { + assert(false); + } + } + } + } + if (rewriter != nullptr && !nonArray && rewriteFrom != nullptr) { + SourceLocation loc = getMemberLocation(expr); + while (compiler.getSourceManager().isMacroArgExpansion(loc)) { + loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc); + } + if (compiler.getSourceManager().isMacroBodyExpansion(loc)) { + loc = compiler.getSourceManager().getSpellingLoc(loc); + } + unsigned n = Lexer::MeasureTokenLength( + loc, compiler.getSourceManager(), compiler.getLangOpts()); + if ((std::string(compiler.getSourceManager().getCharacterData(loc), n) + == rewriteFrom) + && replaceText(loc, n, rewriteTo)) + { + return; + } + } + report( + DiagnosticsEngine::Warning, + "rewrite call of '%0' with %1 as call of '%2'%3", + getMemberLocation(expr)) + << original << describeChangeKind(kind) << replacement + << adviseNonArray(nonArray) << expr->getSourceRange(); +} + +void StringConstant::checkEmpty( + CallExpr const * expr, FunctionDecl const * callee, TreatEmpty treatEmpty, + unsigned size, std::string * replacement) +{ + assert(replacement != nullptr); + if (size == 0) { + switch (treatEmpty) { + case TreatEmpty::DefaultCtor: + *replacement = "rtl::OUString default constructor"; + break; + case TreatEmpty::CheckEmpty: + *replacement = "rtl::OUString::isEmpty"; + break; + case TreatEmpty::Error: + report( + DiagnosticsEngine::Warning, + "call of '%0' with suspicious empty string constant argument", + getMemberLocation(expr)) + << callee->getQualifiedNameAsString() << expr->getSourceRange(); + break; + } + } +} + +void StringConstant::handleChar( + CallExpr const * expr, unsigned arg, FunctionDecl const * callee, + std::string const & replacement, TreatEmpty treatEmpty, bool literal, + char const * rewriteFrom, char const * rewriteTo) +{ + unsigned n; + bool nonArray; + ContentKind cont; + bool emb; + bool trm; + if (!isStringConstant( + expr->getArg(arg)->IgnoreParenImpCasts(), &n, &nonArray, &cont, + &emb, &trm)) + { + return; + } + if (cont != ContentKind::Ascii) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument containing non-ASCII" + " characters"), + getMemberLocation(expr)) + << callee->getQualifiedNameAsString() << expr->getSourceRange(); + return; + } + if (emb) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument containing embedded" + " NULLs"), + getMemberLocation(expr)) + << callee->getQualifiedNameAsString() << expr->getSourceRange(); + return; + } + if (!trm) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument lacking a terminating" + " NULL"), + getMemberLocation(expr)) + << callee->getQualifiedNameAsString() << expr->getSourceRange(); + return; + } + std::string repl(replacement); + checkEmpty(expr, callee, treatEmpty, n, &repl); + if (!repl.empty()) { + reportChange( + expr, ChangeKind::Char, callee->getQualifiedNameAsString(), repl, + (literal + ? (n == 0 + ? PassThrough::EmptyConstantString + : PassThrough::NonEmptyConstantString) + : PassThrough::No), + nonArray, rewriteFrom, rewriteTo); + } +} + +void StringConstant::handleCharLen( + CallExpr const * expr, unsigned arg1, unsigned arg2, + FunctionDecl const * callee, std::string const & replacement, + TreatEmpty treatEmpty) +{ + // Especially for f(RTL_CONSTASCII_STRINGPARAM("foo")), where + // RTL_CONSTASCII_STRINGPARAM expands to complicated expressions involving + // (&(X)[0] sub-expressions (and it might or might not be better to handle + // that at the level of non-expanded macros instead, but I have not found + // out how to do that yet anyway): + unsigned n; + bool nonArray; + ContentKind cont; + bool emb; + bool trm; + if (!(isStringConstant( + expr->getArg(arg1)->IgnoreParenImpCasts(), &n, &nonArray, &cont, + &emb, &trm) + && trm)) + { + return; + } + APSInt res; + if (compat::EvaluateAsInt(expr->getArg(arg2), res, compiler.getASTContext())) { + if (res != n) { + return; + } + } else { + UnaryOperator const * op = dyn_cast( + expr->getArg(arg1)->IgnoreParenImpCasts()); + if (op == nullptr || op->getOpcode() != UO_AddrOf) { + return; + } + ArraySubscriptExpr const * subs = dyn_cast( + op->getSubExpr()->IgnoreParenImpCasts()); + if (subs == nullptr) { + return; + } + unsigned n2; + bool nonArray2; + ContentKind cont2; + bool emb2; + bool trm2; + if (!(isStringConstant( + subs->getBase()->IgnoreParenImpCasts(), &n2, &nonArray2, + &cont2, &emb2, &trm2) + && n2 == n && cont2 == cont && emb2 == emb && trm2 == trm + //TODO: same strings + && compat::EvaluateAsInt(subs->getIdx(), res, compiler.getASTContext()) + && res == 0)) + { + return; + } + } + if (cont != ContentKind::Ascii) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument containing non-ASCII" + " characters"), + getMemberLocation(expr)) + << callee->getQualifiedNameAsString() << expr->getSourceRange(); + } + if (emb) { + return; + } + std::string repl(replacement); + checkEmpty(expr, callee, treatEmpty, n, &repl); + reportChange( + expr, ChangeKind::CharLen, callee->getQualifiedNameAsString(), repl, + PassThrough::No, nonArray, nullptr, nullptr); +} + +void StringConstant::handleOUStringCtor( + CallExpr const * expr, unsigned arg, FunctionDecl const * callee, + bool explicitFunctionalCastNotation) +{ + handleOUStringCtor(expr, expr->getArg(arg), callee, explicitFunctionalCastNotation); +} + +void StringConstant::handleOStringCtor( + CallExpr const * expr, unsigned arg, FunctionDecl const * callee, + bool explicitFunctionalCastNotation) +{ + handleOStringCtor(expr, expr->getArg(arg), callee, explicitFunctionalCastNotation); +} + +void StringConstant::handleOUStringCtor( + Expr const * expr, Expr const * argExpr, FunctionDecl const * callee, + bool explicitFunctionalCastNotation) +{ + handleStringCtor(expr, argExpr, callee, explicitFunctionalCastNotation, StringKind::Unicode); +} + +void StringConstant::handleOStringCtor( + Expr const * expr, Expr const * argExpr, FunctionDecl const * callee, + bool explicitFunctionalCastNotation) +{ + handleStringCtor(expr, argExpr, callee, explicitFunctionalCastNotation, StringKind::Char); +} + +void StringConstant::handleStringCtor( + Expr const * expr, Expr const * argExpr, FunctionDecl const * callee, + bool explicitFunctionalCastNotation, StringKind stringKind) +{ + auto e0 = argExpr->IgnoreParenImpCasts(); + if (auto const e1 = dyn_cast(e0)) { + if (auto const e2 = dyn_cast(e1->getMethodDecl())) { + if (loplugin::TypeCheck(e2->getConversionType()).ClassOrStruct("basic_string_view") + .StdNamespace()) + { + e0 = e1->getImplicitObjectArgument()->IgnoreParenImpCasts(); + } + } + } + auto e1 = dyn_cast(e0); + if (e1 == nullptr) { + if (explicitFunctionalCastNotation) { + return; + } + } else { + e0 = e1->getSubExpr()->IgnoreParenImpCasts(); + } + auto e2 = dyn_cast(e0); + if (e2 == nullptr) { + return; + } + auto e3 = dyn_cast( + e2->getSubExpr()->IgnoreParenImpCasts()); + if (e3 == nullptr) { + return; + } + if (!loplugin::DeclCheck(e3->getConstructor()).MemberFunction() + .Class(stringKind == StringKind::Unicode ? "OUString" : "OString").Namespace("rtl").GlobalNamespace()) + { + return; + } + if (e3->getNumArgs() == 0) { + report( + DiagnosticsEngine::Warning, + ("in call of '%0', replace default-constructed 'OUString' with an" + " empty string literal"), + e3->getExprLoc()) + << callee->getQualifiedNameAsString() << expr->getSourceRange(); + return; + } + if (e3->getNumArgs() == 1 + && e3->getConstructor()->getNumParams() == 1 + && (loplugin::TypeCheck( + e3->getConstructor()->getParamDecl(0)->getType()) + .Typedef(stringKind == StringKind::Unicode ? "sal_Unicode" : "char").GlobalNamespace())) + { + // It may not be easy to rewrite OUString(c), esp. given there is no + // OUString ctor taking an OUStringChar arg, so don't warn there: + if (!explicitFunctionalCastNotation) { + report( + DiagnosticsEngine::Warning, + ("in call of '%0', replace 'OUString' constructed from a" + " 'sal_Unicode' with an 'OUStringChar'"), + e3->getExprLoc()) + << callee->getQualifiedNameAsString() << expr->getSourceRange(); + } + return; + } + if (e3->getNumArgs() != 2) { + return; + } + unsigned n; + bool nonArray; + ContentKind cont; + bool emb; + bool trm; + if (!isStringConstant( + e3->getArg(0)->IgnoreParenImpCasts(), &n, &nonArray, &cont, &emb, + &trm)) + { + return; + } + //TODO: cont, emb, trm + if (rewriter != nullptr) { + auto loc1 = e3->getBeginLoc(); + auto range = e3->getParenOrBraceRange(); + if (loc1.isFileID() && range.getBegin().isFileID() + && range.getEnd().isFileID()) + { + auto loc2 = range.getBegin(); + for (bool first = true;; first = false) { + unsigned n = Lexer::MeasureTokenLength( + loc2, compiler.getSourceManager(), compiler.getLangOpts()); + if (!first) { + StringRef s( + compiler.getSourceManager().getCharacterData(loc2), n); + while (s.startswith("\\\n")) { + s = s.drop_front(2); + while (!s.empty() + && (s.front() == ' ' || s.front() == '\t' + || s.front() == '\n' || s.front() == '\v' + || s.front() == '\f')) + { + s = s.drop_front(1); + } + } + if (!(s.empty() || s.startswith("/*") || s.startswith("//") + || s == "\\")) + { + break; + } + } + loc2 = loc2.getLocWithOffset(std::max(n, 1)); + } + auto loc3 = range.getEnd(); + for (;;) { + auto l = Lexer::GetBeginningOfToken( + loc3.getLocWithOffset(-1), compiler.getSourceManager(), + compiler.getLangOpts()); + unsigned n = Lexer::MeasureTokenLength( + l, compiler.getSourceManager(), compiler.getLangOpts()); + StringRef s(compiler.getSourceManager().getCharacterData(l), n); + while (s.startswith("\\\n")) { + s = s.drop_front(2); + while (!s.empty() + && (s.front() == ' ' || s.front() == '\t' + || s.front() == '\n' || s.front() == '\v' + || s.front() == '\f')) + { + s = s.drop_front(1); + } + } + if (!(s.empty() || s.startswith("/*") || s.startswith("//") + || s == "\\")) + { + break; + } + loc3 = l; + } + if (removeText(CharSourceRange(SourceRange(loc1, loc2), false))) { + if (removeText(SourceRange(loc3, range.getEnd()))) { + return; + } + report(DiagnosticsEngine::Fatal, "Corrupt rewrite", loc3) + << expr->getSourceRange(); + return; + } + } + } + report( + DiagnosticsEngine::Warning, + ("in call of '%0', replace 'OUString' constructed from a string literal" + " directly with the string literal"), + e3->getExprLoc()) + << callee->getQualifiedNameAsString() << expr->getSourceRange(); +} + +void StringConstant::handleFunArgOstring( + CallExpr const * expr, unsigned arg, FunctionDecl const * callee) +{ + auto argExpr = expr->getArg(arg)->IgnoreParenImpCasts(); + unsigned n; + bool nonArray; + ContentKind cont; + bool emb; + bool trm; + if (isStringConstant(argExpr, &n, &nonArray, &cont, &emb, &trm)) { + if (cont != ContentKind::Ascii || emb) { + return; + } + if (!trm) { + report( + DiagnosticsEngine::Warning, + ("call of '%0' with string constant argument lacking a" + " terminating NULL"), + getMemberLocation(expr)) + << callee->getQualifiedNameAsString() << expr->getSourceRange(); + return; + } + std::string repl; + checkEmpty(expr, callee, TreatEmpty::Error, n, &repl); + if (nonArray) { + report( + DiagnosticsEngine::Warning, + ("in call of '%0' with non-array string constant argument," + " turn the non-array string constant into an array"), + getMemberLocation(expr)) + << callee->getQualifiedNameAsString() << expr->getSourceRange(); + } + } else if (auto cexpr = lookForCXXConstructExpr(argExpr)) { + auto classdecl = cexpr->getConstructor()->getParent(); + if (loplugin::DeclCheck(classdecl).Class("OString").Namespace("rtl") + .GlobalNamespace()) + { + switch (cexpr->getConstructor()->getNumParams()) { + case 0: + report( + DiagnosticsEngine::Warning, + ("in call of '%0', replace empty %1 constructor with empty" + " string literal"), + cexpr->getLocation()) + << callee->getQualifiedNameAsString() << classdecl + << expr->getSourceRange(); + break; + case 2: + if (isStringConstant( + cexpr->getArg(0)->IgnoreParenImpCasts(), &n, &nonArray, + &cont, &emb, &trm)) + { + APSInt res; + if (compat::EvaluateAsInt(cexpr->getArg(1), + res, compiler.getASTContext())) + { + if (res == n && !emb && trm) { + report( + DiagnosticsEngine::Warning, + ("in call of '%0', elide explicit %1" + " constructor%2"), + cexpr->getLocation()) + << callee->getQualifiedNameAsString() + << classdecl << adviseNonArray(nonArray) + << expr->getSourceRange(); + } + } else { + if (emb) { + report( + DiagnosticsEngine::Warning, + ("call of %0 constructor with string constant" + " argument containing embedded NULLs"), + cexpr->getLocation()) + << classdecl << cexpr->getSourceRange(); + return; + } + if (!trm) { + report( + DiagnosticsEngine::Warning, + ("call of %0 constructor with string constant" + " argument lacking a terminating NULL"), + cexpr->getLocation()) + << classdecl << cexpr->getSourceRange(); + return; + } + report( + DiagnosticsEngine::Warning, + "in call of '%0', elide explicit %1 constructor%2", + cexpr->getLocation()) + << callee->getQualifiedNameAsString() << classdecl + << adviseNonArray(nonArray) + << expr->getSourceRange(); + } + } + break; + default: + break; + } + } + } +} + +loplugin::Plugin::Registration< StringConstant > X("stringconstant", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/stringliteraldefine.cxx b/compilerplugins/clang/stringliteraldefine.cxx new file mode 100644 index 000000000..8d7e77805 --- /dev/null +++ b/compilerplugins/clang/stringliteraldefine.cxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Find constant character array variables that are either +// (a) passed into O[U]String constructors +// (b) assigned to O[U]String +// and are declared using macro names +// and should thus be turned into O[U]StringLiteral variables. +// + +#include + +#include "config_clang.h" + +#include "check.hxx" +#include "plugin.hxx" + +namespace +{ +class StringLiteralDefine final : public loplugin::FilteringPlugin +{ +public: + explicit StringLiteralDefine(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool TraverseInitListExpr(InitListExpr* expr, DataRecursionQueue* queue = nullptr) + { + return WalkUpFromInitListExpr(expr) + && TraverseSynOrSemInitListExpr( + expr->isSemanticForm() ? expr : expr->getSemanticForm(), queue); + } + + bool VisitCXXConstructExpr(CXXConstructExpr const* expr) + { + if (ignoreLocation(expr)) + return true; + loplugin::TypeCheck const tc(expr->getType()); + if (!(tc.Class("OString").Namespace("rtl").GlobalNamespace() + || tc.Class("OUString").Namespace("rtl").GlobalNamespace())) + { + return true; + } + auto const ctor = expr->getConstructor(); + if (ctor->getNumParams() != 2) + return true; + + const Expr* arg0 = expr->getArg(0)->IgnoreParenImpCasts(); + auto const e1 = dyn_cast(arg0); + if (!e1) + return true; + auto argLoc = arg0->getBeginLoc(); + // check if the arg is a macro + auto macroLoc = compiler.getSourceManager().getSpellingLoc(argLoc); + if (argLoc == macroLoc) + return true; + // check if it is the right kind of macro (not particularly reliable checks) + if (!macroLoc.isValid() || !compiler.getSourceManager().isInMainFile(macroLoc) + || compiler.getSourceManager().isInSystemHeader(macroLoc) + || compiler.getSourceManager().isWrittenInBuiltinFile(macroLoc) + || compiler.getSourceManager().isWrittenInScratchSpace(macroLoc) + || compiler.getSourceManager().isWrittenInCommandLineFile(macroLoc) + || isInUnoIncludeFile(macroLoc)) + return true; + StringRef fileName = getFilenameOfLocation(macroLoc); + StringRef name{ Lexer::getImmediateMacroName( + arg0->getBeginLoc(), compiler.getSourceManager(), compiler.getLangOpts()) }; + if (loplugin::hasPathnamePrefix(fileName, SRCDIR "/config_host/")) + return true; + // used in both OUString and OString context + if (name == "FM_COL_LISTBOX" || name == "HID_RELATIONDIALOG_LEFTFIELDCELL" + || name == "OOO_HELP_INDEX" || name == "IMP_PNG" || name.startswith("MNI_ACTION_")) + return true; + if (loplugin::hasPathnamePrefix(fileName, SRCDIR "/svx/source/stbctrls/pszctrl.cxx")) + return true; + // used as a prefix and/or concatenated with other strings + if (name.startswith("UNO_JAVA_JFW") || name == "SETNODE_BINDINGS" || name == "PATHDELIMITER" + || name == "SETNODE_ALLFILEFORMATS" || name == "SETNODE_DISABLED" + || name == "XMLNS_DIALOGS_PREFIX" || name == "XMLNS_LIBRARY_PREFIX" + || name == "XMLNS_SCRIPT_PREFIX" || name == "XMLNS_TOOLBAR" || name == "XMLNS_XLINK" + || name == "XMLNS_XLINK_PREFIX") + return true; + if (loplugin::hasPathnamePrefix(fileName, + SRCDIR "/stoc/source/security/access_controller.cxx") + && (name == "SERVICE_NAME" || name == "USER_CREDS")) + return true; + if (loplugin::hasPathnamePrefix(fileName, SRCDIR "/stoc/source/security/file_policy.cxx") + && name == "IMPL_NAME") + return true; + if (loplugin::hasPathnamePrefix(fileName, + SRCDIR "/desktop/source/migration/services/jvmfwk.cxx") + && name == "IMPL_NAME") + return true; + if (loplugin::hasPathnamePrefix( + fileName, SRCDIR "/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx") + && name == "STRXMLNS") + return true; + if (loplugin::hasPathnamePrefix(fileName, SRCDIR "/sw/source/ui/fldui/fldvar.cxx") + && name == "USER_DATA_VERSION_1") + return true; + // not sure how to exclude the case where the whole block is in a macro + // (vs. what I am looking for - regular code with a macro name as the argument) + if (name == "assert" || name == "SAL_INFO" || name == "DECLIMPL_SERVICEINFO_DERIVED" + || name == "OSL_VERIFY" || name == "OSL_ENSURE" || name == "DECL_PROP_2" + || name == "DECL_PROP_3" || name == "DECL_PROP_1" || name == "DECL_DEP_PROP_2" + || name == "DECL_DEP_PROP_3" || name == "CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS" + || name == "IMPLEMENT_SERVICE_INFO" || name == "SQL_GET_REFERENCES" + || name == "SFX_IMPL_OBJECTFACTORY" || name == "IMPLEMENT_SERVICE_INFO1" + || name == "IMPLEMENT_SERVICE_INFO2" || name == "IMPLEMENT_SERVICE_INFO3" + || name == "IMPLEMENT_SERVICE_INFO_IMPLNAME" || name == "SC_SIMPLE_SERVICE_INFO" + || name == "SC_SIMPLE_SERVICE_INFO_COMPAT" || name == "OUT_COMMENT" + || name == "LOCALE_EN" || name == "LOCALE" || name == "VBAFONTBASE_PROPNAME" + || name == "VBAHELPER_IMPL_XHELPERINTERFACE" || name == "IMPRESS_MAP_ENTRIES" + || name == "DRAW_MAP_ENTRIES" || name == "DRAW_PAGE_NOTES_PROPERTIES" + || name == "COMMON_FLDTYP_PROPERTIES" || name == "GRAPHIC_PAGE_PROPERTIES" + || name == "makeDelay" || name == "makeEvent" || name == "OOO_IMPORTER" + || name == "DBG_ASSERT" || name.startswith("CPPUNIT_ASSERT")) + return true; + if (loplugin::hasPathnamePrefix(fileName, SRCDIR + "/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx") + && name == "DEFAULT_SIZE") + return true; + if (loplugin::hasPathnamePrefix(fileName, SRCDIR "/filter/source/t602/t602filter.cxx")) + return true; + if (loplugin::hasPathnamePrefix(fileName, SRCDIR "/hwpfilter/source/formula.cxx")) + return true; + if (loplugin::hasPathnamePrefix(fileName, SRCDIR "/hwpfilter/source/hwpreader.cxx")) + return true; + if (loplugin::hasPathnamePrefix(fileName, SRCDIR "/filter/source/svg/svgexport.cxx") + && name == "NSPREFIX") + return true; + + if (!reported_.insert(macroLoc).second) + return true; + + report(DiagnosticsEngine::Warning, + "change macro '%0' to 'constexpr " + "%select{OStringLiteral|OUStringLiteral}1'", + macroLoc) + << name << (tc.Class("OString").Namespace("rtl").GlobalNamespace() ? 0 : 1); + report(DiagnosticsEngine::Note, "macro used here", arg0->getBeginLoc()) + << arg0->getSourceRange(); + return true; + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + +private: + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + std::set reported_; +}; + +// Off by default because it needs some hand-holding +static loplugin::Plugin::Registration reg("stringliteraldefine", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/stringliteralvar.cxx b/compilerplugins/clang/stringliteralvar.cxx new file mode 100644 index 000000000..fcd369066 --- /dev/null +++ b/compilerplugins/clang/stringliteralvar.cxx @@ -0,0 +1,320 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Find constant character array variables that are either +// (a) passed into O[U]String constructors +// (b) assigned to O[U]String +// and should thus be turned into O[U]StringLiteral variables. +// +// Such a variable may have been used in multiple places, not all of which would be compatible with +// changing the variable's type to O[U]StringLiteral. However, this plugin is aggressive and +// ignores all but the first use of such a variable. In all cases of incompatible uses so far, it +// was possible to change to surrounding code (for the better) to make the changes work. +// +// The plugin also flags O[U]StringLiteral variables of automatic storage duration, and uses of such +// variables with sizeof---two likely errors that can occur once a variable has been changed from a +// character array to O[U]StringLiteral. +// +//TODO: In theory, we should not only look for variables, but also for non-static data members. In +// practice, those should be rare, though, as they should arguably have been static data members to +// begin with. + +#include + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" + +namespace +{ +bool isAutomaticVariable(VarDecl const* decl) +{ + switch (cast(decl)->getStorageDuration()) + { + case SD_Automatic: + return true; + case SD_Thread: + case SD_Static: + return false; + case SD_FullExpression: + case SD_Dynamic: + assert(false); + default: + llvm_unreachable("unknown StorageDuration"); + } +} + +class StringLiteralVar final : public loplugin::FilteringPlugin +{ +public: + explicit StringLiteralVar(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool TraverseInitListExpr(InitListExpr* expr, DataRecursionQueue* queue = nullptr) + { + return WalkUpFromInitListExpr(expr) + && TraverseSynOrSemInitListExpr( + expr->isSemanticForm() ? expr : expr->getSemanticForm(), queue); + } + + bool VisitCXXConstructExpr(CXXConstructExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + loplugin::TypeCheck const tc(expr->getType()); + if (!(tc.Class("OString").Namespace("rtl").GlobalNamespace() + || tc.Class("OUString").Namespace("rtl").GlobalNamespace())) + { + return true; + } + auto const ctor = expr->getConstructor(); + switch (ctor->getNumParams()) + { + case 1: + { + auto const e = dyn_cast(expr->getArg(0)->IgnoreParenImpCasts()); + if (e == nullptr) + { + return true; + } + auto const tc = loplugin::TypeCheck(e->getType()); + if (!(tc.Class("OStringLiteral").Namespace("rtl").GlobalNamespace() + || tc.Class("OUStringLiteral").Namespace("rtl").GlobalNamespace())) + { + return true; + } + auto const d = e->getDecl(); + if (!isAutomaticVariable(cast(d))) + { + return true; + } + if (!reportedAutomatic_.insert(d).second) + { + return true; + } + report(DiagnosticsEngine::Warning, + "variable %0 of type %1 with automatic storage duration most likely needs " + "to be static", + d->getLocation()) + << d << d->getType() << d->getSourceRange(); + report(DiagnosticsEngine::Note, "first converted to %0 here", expr->getLocation()) + << expr->getType() << expr->getSourceRange(); + } + break; + case 2: + { + auto const e1 = dyn_cast(expr->getArg(0)->IgnoreParenImpCasts()); + if (e1 == nullptr) + { + return true; + } + auto const t = e1->getType(); + if (!(t.isConstQualified() && t->isConstantArrayType())) + { + return true; + } + auto const e2 = expr->getArg(1); + if (!((isa(e2) + && loplugin::TypeCheck(e2->getType()) + .Struct("Dummy") + .Namespace("libreoffice_internal") + .Namespace("rtl") + .GlobalNamespace()) + || (loplugin::TypeCheck(ctor->getParamDecl(1)->getType()) + .Typedef("sal_Int32") + .GlobalNamespace() + && e2->isIntegerConstantExpr(compiler.getASTContext())))) + { + return true; + } + auto const d = e1->getDecl(); + if (isPotentiallyInitializedWithMalformedUtf16(d)) + { + return true; + } + if (!reportedArray_.insert(d).second) + { + return true; + } + report(DiagnosticsEngine::Warning, + "change type of variable %0 from constant character array (%1) to " + "%select{OStringLiteral|OUStringLiteral}2%select{|, and make it static}3", + d->getLocation()) + << d << d->getType() + << (tc.Class("OString").Namespace("rtl").GlobalNamespace() ? 0 : 1) + << isAutomaticVariable(cast(d)) << d->getSourceRange(); + report(DiagnosticsEngine::Note, "first passed into a %0 constructor here", + expr->getLocation()) + << expr->getType().getUnqualifiedType() << expr->getSourceRange(); + } + break; + } + return true; + } + + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + if (expr->getOperator() != OO_Equal) + { + return true; + } + loplugin::TypeCheck const tc(expr->getType()); + if (!(tc.Class("OString").Namespace("rtl").GlobalNamespace() + || tc.Class("OUString").Namespace("rtl").GlobalNamespace())) + { + return true; + } + if (expr->getNumArgs() != 2) + { + return true; + } + auto const e = dyn_cast(expr->getArg(1)->IgnoreParenImpCasts()); + if (e == nullptr) + { + return true; + } + auto const t = e->getType(); + if (!(t.isConstQualified() && t->isConstantArrayType())) + { + return true; + } + auto const d = e->getDecl(); + if (isPotentiallyInitializedWithMalformedUtf16(d)) + { + return true; + } + if (!reportedArray_.insert(d).second) + { + return true; + } + report(DiagnosticsEngine::Warning, + "change type of variable %0 from constant character array (%1) to " + "%select{OStringLiteral|OUStringLiteral}2%select{|, and make it static}3", + d->getLocation()) + << d << d->getType() << (tc.Class("OString").Namespace("rtl").GlobalNamespace() ? 0 : 1) + << isAutomaticVariable(cast(d)) << d->getSourceRange(); + report(DiagnosticsEngine::Note, "first assigned here", expr->getBeginLoc()) + << expr->getSourceRange(); + return true; + } + + bool VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + if (expr->getKind() != UETT_SizeOf) + { + return true; + } + if (expr->isArgumentType()) + { + return true; + } + auto const e = dyn_cast(expr->getArgumentExpr()->IgnoreParenImpCasts()); + if (e == nullptr) + { + return true; + } + auto const tc = loplugin::TypeCheck(e->getType()); + if (!(tc.Class("OStringLiteral").Namespace("rtl").GlobalNamespace() + || tc.Class("OUStringLiteral").Namespace("rtl").GlobalNamespace())) + { + return true; + } + auto const d = e->getDecl(); + report(DiagnosticsEngine::Warning, + "variable %0 of type %1 suspiciously used in a sizeof expression", e->getLocation()) + << d << d->getType() << expr->getSourceRange(); + return true; + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + +private: + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + // There is some confusion on the semantics of numeric-escape-sequences in string literals, see + // "Proposed resolution + // for core issues 411, 1656, and 2333; numeric and universal character escapes in character and + // string literals", so suppress warnings about arrays that are deliberately not written as + // UTF-16 string literals because they contain lone surrogates: + bool isPotentiallyInitializedWithMalformedUtf16(ValueDecl const* decl) const + { + if (!decl->getType()->getArrayElementTypeNoTypeQual()->isChar16Type()) + { + return false; + } + auto const init = cast(decl)->getAnyInitializer(); + if (init == nullptr) + { + return true; + } + auto const list = dyn_cast(init); + if (list == nullptr) + { + // Assuming that the initializer already is a string literal, assume that that string + // literal has no issues with malformed UTF-16: + if (isDebugMode()) + { + assert(isa(init)); + } + return false; + } + auto highSurrogate = false; + for (auto const e : list->inits()) + { + llvm::APSInt v; + if (!compat::EvaluateAsInt(e, v, compiler.getASTContext())) + { + return true; + } + if (highSurrogate) + { + if (v < 0xDC00 || v > 0xDFFF) + { + return true; + } + highSurrogate = false; + } + else if (v >= 0xD800 && v <= 0xDBFF) + { + highSurrogate = true; + } + else if (v >= 0xDC00 && v <= 0xDFFF) + { + return true; + } + } + return highSurrogate; + } + + std::set reportedAutomatic_; + std::set reportedArray_; +}; + +static loplugin::Plugin::Registration reg("stringliteralvar"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/stringloop.cxx b/compilerplugins/clang/stringloop.cxx new file mode 100644 index 000000000..3bae1a225 --- /dev/null +++ b/compilerplugins/clang/stringloop.cxx @@ -0,0 +1,292 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "check.hxx" +#include "plugin.hxx" +#include "config_clang.h" +#include + +/** Look for OUString/OString being appended to inside a loop, where OUStringBuffer/OStringBuffer would be a better idea + */ +namespace +{ +class StringLoop : public clang::RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit StringLoop(loplugin::InstantiationData const& rData) + : Plugin(rData) + { + } + + void run() override; + bool TraverseForStmt(ForStmt*); + bool TraverseCXXForRangeStmt(CXXForRangeStmt*); + bool TraverseDoStmt(DoStmt*); + bool TraverseWhileStmt(WhileStmt*); + bool VisitVarDecl(VarDecl const*); + bool VisitCallExpr(CallExpr const*); + +private: + int m_insideLoop = 0; + using VarDeclList = std::vector; + std::vector m_varsPerLoopLevel; +}; + +void StringLoop::run() +{ + // Various places are not worth changing, the code becomes too awkward + // Just exclude stuff as I go + StringRef fn(handler.getMainFileName()); + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/bridges/")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/cppuhelper/source/shlib.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/registry/source/regimpl.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/l10ntools/source/lngmerge.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/tools/qa/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/jvmfwk/")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svl/source/passwordcontainer/passwordcontainer.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svl/source/numbers/zformat.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svl/source/numbers/zforscan.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/control/combobox.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/gdi/pdfwriter_impl.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/svtools/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/idl/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/framework/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/basic/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sfx2/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/avmedia/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/connectivity/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/editeng/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/svx/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/basctl/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/filter/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/chart2/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/cui/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/dbaccess/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/oox/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/writerfilter/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/desktop/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/extensions/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/dtrans/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/i18npool/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/embeddedobj/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sd/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/xmloff/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/xmlhelp/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/forms/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/core/tool/address.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/core/tool/compiler.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/ui/docshell/impex.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/ui/miscdlgs/acredlin.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/ui/pagedlg/areasdlg.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/ui/view/gridwin2.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/filter/html/htmlpars.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/core/doc/doctxm.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/core/edit/edattr.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/core/layout/dbg_lay.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/filter/ascii/ascatr.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/filter/html/htmlforw.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/core/unocore/unosect.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/core/unocore/unochart.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/core/unocore/unoobj.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/filter/html/parcss1.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/filter/html/svxcss1.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/filter/html/swhtml.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/uibase/utlui/gloslst.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/uibase/utlui/content.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/uibase/docvw/edtwin.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/filter/ww8/ww8atr.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/filter/ww8/ww8scan.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/filter/ww8/ww8par5.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/ui/fldui/fldfunc.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/ui/misc/bookmark.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/ui/dbui/mmlayoutpage.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/ui/dbui/dbinsdlg.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/ui/dbui/mmresultdialogs.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/ui/index/cnttab.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/ucb/source/ucp/file/bc.cxx")) + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); +} + +bool StringLoop::TraverseForStmt(ForStmt* stmt) +{ + ++m_insideLoop; + m_varsPerLoopLevel.push_back({}); + auto const ret = RecursiveASTVisitor::TraverseForStmt(stmt); + m_varsPerLoopLevel.pop_back(); + --m_insideLoop; + return ret; +} + +bool StringLoop::TraverseCXXForRangeStmt(CXXForRangeStmt* stmt) +{ + ++m_insideLoop; + m_varsPerLoopLevel.push_back({}); + auto const ret = RecursiveASTVisitor::TraverseCXXForRangeStmt(stmt); + m_varsPerLoopLevel.pop_back(); + --m_insideLoop; + return ret; +} + +bool StringLoop::TraverseDoStmt(DoStmt* stmt) +{ + ++m_insideLoop; + m_varsPerLoopLevel.push_back({}); + auto const ret = RecursiveASTVisitor::TraverseDoStmt(stmt); + m_varsPerLoopLevel.pop_back(); + --m_insideLoop; + return ret; +} + +bool StringLoop::TraverseWhileStmt(WhileStmt* stmt) +{ + ++m_insideLoop; + m_varsPerLoopLevel.push_back({}); + auto const ret = RecursiveASTVisitor::TraverseWhileStmt(stmt); + m_varsPerLoopLevel.pop_back(); + --m_insideLoop; + return ret; +} + +bool StringLoop::VisitVarDecl(VarDecl const* varDecl) +{ + if (ignoreLocation(varDecl)) + return true; + if (!m_insideLoop) + return true; + m_varsPerLoopLevel.back().push_back(varDecl); + return true; +} + +bool StringLoop::VisitCallExpr(CallExpr const* callExpr) +{ + if (ignoreLocation(callExpr)) + return true; + if (!m_insideLoop) + return true; + auto operatorCallExpr = dyn_cast(callExpr); + if (!operatorCallExpr) + return true; + if (operatorCallExpr->getOperator() != OO_PlusEqual) + return true; + + if (auto memberExpr = dyn_cast(callExpr->getArg(0))) + { + auto tc = loplugin::TypeCheck(memberExpr->getType()); + if (!tc.Class("OUString").Namespace("rtl").GlobalNamespace() + && !tc.Class("OString").Namespace("rtl").GlobalNamespace()) + return true; + auto fieldDecl = dyn_cast(memberExpr->getMemberDecl()); + if (isInUnoIncludeFile( + compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocation()))) + return true; + if (ignoreLocation(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocation()))) + return true; + report(DiagnosticsEngine::Warning, + "appending to OUString in loop, rather use OUStringBuffer", + operatorCallExpr->getBeginLoc()) + << operatorCallExpr->getSourceRange(); + report(DiagnosticsEngine::Note, "field here", fieldDecl->getBeginLoc()) + << fieldDecl->getSourceRange(); + } + else if (auto declRefExpr = dyn_cast(callExpr->getArg(0))) + { + if (auto varDecl = dyn_cast(declRefExpr->getDecl())) + { + auto tc = loplugin::TypeCheck(varDecl->getType()); + if (!tc.Class("OUString").Namespace("rtl").GlobalNamespace() + && !tc.Class("OString").Namespace("rtl").GlobalNamespace()) + return true; + // if the var is at the same block scope as the +=, not interesting + auto vars = m_varsPerLoopLevel.back(); + if (std::find(vars.begin(), vars.end(), varDecl) != vars.end()) + return true; + report(DiagnosticsEngine::Warning, + "appending to OUString in loop, rather use OUStringBuffer", + operatorCallExpr->getBeginLoc()) + << operatorCallExpr->getSourceRange(); + report(DiagnosticsEngine::Note, "var here", varDecl->getBeginLoc()) + << varDecl->getSourceRange(); + } + } + return true; +} + +loplugin::Plugin::Registration X("stringloop", false); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/stringstatic.cxx b/compilerplugins/clang/stringstatic.cxx new file mode 100644 index 000000000..a0b83c465 --- /dev/null +++ b/compilerplugins/clang/stringstatic.cxx @@ -0,0 +1,202 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "plugin.hxx" + +#include "config_clang.h" + +#include + +/** Look for static O*String and O*String[], they can be more efficiently declared as: + + static constexpr OUStringLiteral our_aLBEntryMap[] = {u" ", u", "}; + static constexpr OUStringLiteral sName(u"name"); + + which is more efficient at startup time. + */ +namespace { + +class StringStatic + : public loplugin::FilteringPlugin +{ + +public: + explicit StringStatic(loplugin::InstantiationData const& rData): + FilteringPlugin(rData) {} + + void run() override; + bool preRun() override; + void postRun() override; + bool VisitVarDecl(VarDecl const*); + bool VisitReturnStmt(ReturnStmt const*); + bool VisitDeclRefExpr(DeclRefExpr const*); + bool VisitMemberExpr(MemberExpr const*); + +private: + std::unordered_set potentialVars; + std::unordered_set excludeVars; +}; + +void StringStatic::run() +{ + if( preRun()) + if( TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) + postRun(); +} + +bool StringStatic::preRun() +{ + StringRef fn(handler.getMainFileName()); + // passing around pointers to global OUString + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/filter/source/svg/")) + return false; + return true; +} + +void StringStatic::postRun() +{ + for (auto const & pVarDecl : excludeVars) { + potentialVars.erase(pVarDecl); + } + for (auto const & varDecl : potentialVars) { + report(DiagnosticsEngine::Warning, + "rather declare this using OUStringLiteral/OStringLiteral/char[]", + varDecl->getLocation()) + << varDecl->getSourceRange(); + } +} + +bool StringStatic::VisitVarDecl(VarDecl const* varDecl) +{ + if (ignoreLocation(varDecl)) + return true; + QualType qt = varDecl->getType(); + if (!varDecl->hasGlobalStorage()) + return true; + if (varDecl->hasGlobalStorage() && !varDecl->isStaticLocal()) { + //TODO: For a non-public static member variable from an included file, we could still + // examine it further if all its uses must be seen in that included file: + if (!compiler.getSourceManager().isInMainFile(varDecl->getLocation())) { + return true; + } + } + if (!varDecl->isThisDeclarationADefinition() + || !qt.isConstQualified()) + return true; + if (qt->isArrayType()) + qt = qt->getAsArrayTypeUnsafe()->getElementType(); + + auto tc = loplugin::TypeCheck(qt); + if (!tc.Class("OUString").Namespace("rtl").GlobalNamespace() + && !tc.Class("OString").Namespace("rtl").GlobalNamespace()) + return true; + if (varDecl->hasInit()) + { + Expr const * expr = varDecl->getInit(); + while (true) { + if (ExprWithCleanups const * exprWithCleanups = dyn_cast(expr)) { + expr = exprWithCleanups->getSubExpr(); + } + else if (CastExpr const * castExpr = dyn_cast(expr)) { + expr = castExpr->getSubExpr(); + } + else if (MaterializeTemporaryExpr const * materializeExpr = dyn_cast(expr)) { + expr = materializeExpr->getSubExpr(); + } + else if (CXXBindTemporaryExpr const * bindExpr = dyn_cast(expr)) { + expr = bindExpr->getSubExpr(); + } + else if (CXXConstructExpr const * constructExpr = dyn_cast(expr)) { + if (constructExpr->getNumArgs() == 0) { + return true; + } + expr = constructExpr->getArg(0); + } else if (isa(expr)) { + return true; + } else { + break; + } + } + } + potentialVars.insert(varDecl); + + return true; +} + +bool StringStatic::VisitReturnStmt(ReturnStmt const * returnStmt) +{ + if (ignoreLocation(returnStmt)) { + return true; + } + if (!returnStmt->getRetValue()) { + return true; + } + DeclRefExpr const * declRef = dyn_cast(returnStmt->getRetValue()); + if (!declRef) { + return true; + } + VarDecl const * varDecl = dyn_cast(declRef->getDecl()); + if (varDecl) { + excludeVars.insert(varDecl); + } + return true; +} + +bool StringStatic::VisitDeclRefExpr(DeclRefExpr const * declRef) +{ + if (ignoreLocation(declRef)) + return true; + VarDecl const * varDecl = dyn_cast(declRef->getDecl()); + if (!varDecl) + return true; + if (potentialVars.count(varDecl) == 0) + return true; + // ignore globals that are used in CPPUNIT_ASSERT expressions, otherwise we can end up + // trying to compare an OUStringLiteral and an OUString, and CPPUNIT can't handle that + auto loc = declRef->getBeginLoc(); + if (compiler.getSourceManager().isMacroArgExpansion(loc)) + { + StringRef name { Lexer::getImmediateMacroName(loc, compiler.getSourceManager(), compiler.getLangOpts()) }; + if (name.startswith("CPPUNIT_ASSERT")) + excludeVars.insert(varDecl); + } + return true; +} + +bool StringStatic::VisitMemberExpr(MemberExpr const * expr) +{ + if (ignoreLocation(expr)) + return true; + auto const declRef = dyn_cast(expr->getBase()); + if (declRef == nullptr) { + return true; + } + VarDecl const * varDecl = dyn_cast(declRef->getDecl()); + if (!varDecl) + return true; + if (potentialVars.count(varDecl) == 0) + return true; + auto const id = expr->getMemberDecl()->getIdentifier(); + if (id == nullptr || id->getName() != "pData") { + return true; + } + excludeVars.insert(varDecl); + return true; +} + +loplugin::Plugin::Registration stringstatic("stringstatic"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/stringview.cxx b/compilerplugins/clang/stringview.cxx new file mode 100644 index 000000000..1be16fb89 --- /dev/null +++ b/compilerplugins/clang/stringview.cxx @@ -0,0 +1,424 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +/** + Look for places where we are making a substring copy of an OUString, and then passing it to a + function that takes a u16string_view, in which case it is more efficient to pass a view + of the OUString, rather than making a copy. + + TODO currently does not check if there is some other visible overload of the callee, that can take + a string_view. + TODO handle OUStringBuffer/OStringBuffer similarly +*/ + +namespace +{ +class StringView : public loplugin::FilteringPlugin +{ +public: + explicit StringView(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override + { + auto const fn = handler.getMainFileName(); + return !( + loplugin::isSamePathname(fn, SRCDIR "/sal/qa/OStringBuffer/rtl_OStringBuffer.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/sal/qa/rtl/strings/test_ostring_concat.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/sal/qa/rtl/strings/test_oustring_concat.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/sal/qa/rtl/oustring/rtl_OUString2.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/sal/qa/rtl/strings/test_oustring_compare.cxx") + || loplugin::isSamePathname(fn, + SRCDIR "/sal/qa/rtl/strings/test_oustring_startswith.cxx") + || loplugin::isSamePathname(fn, SRCDIR + "/sal/qa/rtl/strings/test_strings_defaultstringview.cxx")); + } + + virtual void run() override + { + if (!preRun()) + return; + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitFunctionDecl(FunctionDecl const*); + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const*); + bool VisitImplicitCastExpr(ImplicitCastExpr const*); + bool VisitCXXMemberCallExpr(CXXMemberCallExpr const*); + bool VisitCXXConstructExpr(CXXConstructExpr const*); + +private: + void handleSubExprThatCouldBeView(Expr const* expr); + void handleCXXConstructExpr(CXXConstructExpr const* expr); + void handleCXXMemberCallExpr(CXXMemberCallExpr const* expr); +}; + +bool StringView::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* cxxOperatorCallExpr) +{ + if (ignoreLocation(cxxOperatorCallExpr)) + return true; + + auto op = cxxOperatorCallExpr->getOperator(); + if (op == OO_Plus && cxxOperatorCallExpr->getNumArgs() == 2) + { + handleSubExprThatCouldBeView(cxxOperatorCallExpr->getArg(0)); + handleSubExprThatCouldBeView(cxxOperatorCallExpr->getArg(1)); + } + if (cxxOperatorCallExpr->isComparisonOp()) + { + handleSubExprThatCouldBeView(cxxOperatorCallExpr->getArg(0)); + handleSubExprThatCouldBeView(cxxOperatorCallExpr->getArg(1)); + } + else if (op == OO_PlusEqual) + handleSubExprThatCouldBeView(cxxOperatorCallExpr->getArg(1)); + else if (op == OO_Subscript) + handleSubExprThatCouldBeView(cxxOperatorCallExpr->getArg(0)); + else if (op == OO_Equal) + { + if (loplugin::TypeCheck(cxxOperatorCallExpr->getType()) + .Class("OUStringBuffer") + .Namespace("rtl") + .GlobalNamespace() + || loplugin::TypeCheck(cxxOperatorCallExpr->getType()) + .Class("OStringBuffer") + .Namespace("rtl") + .GlobalNamespace()) + { + handleSubExprThatCouldBeView(cxxOperatorCallExpr->getArg(1)); + } + } + return true; +} + +bool StringView::VisitFunctionDecl(FunctionDecl const* functionDecl) +{ + if (ignoreLocation(functionDecl)) + return true; + // debugging + // if (functionDecl->getIdentifier() && functionDecl->getName() == "f1") + // functionDecl->dump(); + return true; +} + +bool StringView::VisitImplicitCastExpr(ImplicitCastExpr const* expr) +{ + if (ignoreLocation(expr)) + { + return true; + } + if (!loplugin::TypeCheck(expr->getType()).ClassOrStruct("basic_string_view").StdNamespace()) + { + return true; + } + handleSubExprThatCouldBeView(expr->getSubExprAsWritten()); + return true; +} + +void StringView::handleSubExprThatCouldBeView(Expr const* subExpr) +{ + auto const e0 = subExpr->IgnoreImplicit(); + auto const e = e0->IgnoreParens(); + auto const tc = loplugin::TypeCheck(e->getType()); + if (!(tc.Class("OString").Namespace("rtl").GlobalNamespace() + || tc.Class("OUString").Namespace("rtl").GlobalNamespace() + || tc.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace())) + { + return; + } + if (auto const e1 = dyn_cast(e)) + { + if (e0 == subExpr) + { + handleCXXConstructExpr(e1); + } + } + else if (auto const e2 = dyn_cast(e)) + { + auto e3 = e2->getSubExpr(); + if (auto const e4 = dyn_cast(e3)) + { + e3 = e4->getSubExpr(); + } + if (auto const e4 = dyn_cast(e3)) + { + handleCXXConstructExpr(e4); + } + } + else if (auto const e3 = dyn_cast(e)) + { + handleCXXMemberCallExpr(e3); + } +} + +void StringView::handleCXXConstructExpr(CXXConstructExpr const* expr) +{ + QualType argType; + enum + { + None, + OrChar, + ViaConcatenation + } extra + = None; + auto const d = expr->getConstructor(); + switch (d->getNumParams()) + { + case 0: + break; + case 1: + { + auto const t = d->getParamDecl(0)->getType(); + if (t->isAnyCharacterType()) + { + argType = expr->getArg(0)->IgnoreImplicit()->getType(); + extra = OrChar; + break; + } + loplugin::TypeCheck tc(t); + if (tc.LvalueReference() + .Const() + .Class("OStringLiteral") + .Namespace("rtl") + .GlobalNamespace() + || tc.LvalueReference() + .Const() + .Class("OUStringLiteral") + .Namespace("rtl") + .GlobalNamespace() + || tc.RvalueReference().Struct("OStringNumber").Namespace("rtl").GlobalNamespace() + || tc.RvalueReference().Struct("OUStringNumber").Namespace("rtl").GlobalNamespace() + || tc.ClassOrStruct("basic_string_view").StdNamespace()) + { + argType = expr->getArg(0)->IgnoreImplicit()->getType(); + break; + } + if (tc.RvalueReference().Struct("OStringConcat").Namespace("rtl").GlobalNamespace() + || tc.RvalueReference().Struct("OUStringConcat").Namespace("rtl").GlobalNamespace()) + { + argType = expr->getArg(0)->IgnoreImplicit()->getType(); + extra = ViaConcatenation; + break; + } + return; + } + case 2: + { + auto const t0 = d->getParamDecl(0)->getType(); + if (t0->isPointerType() && t0->getPointeeType()->isAnyCharacterType()) + { + auto const t = d->getParamDecl(1)->getType(); + if (t->isIntegralType(compiler.getASTContext()) + && !(t->isBooleanType() || t->isAnyCharacterType())) + { + auto const arg = expr->getArg(1); + if (!arg->isValueDependent()) + { + if (auto const val = arg->getIntegerConstantExpr(compiler.getASTContext())) + { + if (val->getExtValue() == 1) + { + extra = OrChar; + } + } + } + argType = expr->getArg(0)->IgnoreImplicit()->getType(); + break; + } + } + if (loplugin::TypeCheck(d->getParamDecl(1)->getType()) + .Struct("Dummy") + .Namespace("libreoffice_internal") + .Namespace("rtl") + .GlobalNamespace()) + { + argType = expr->getArg(0)->IgnoreImplicit()->getType(); + break; + } + return; + } + default: + return; + } + report(DiagnosticsEngine::Warning, + "instead of an %0%select{| constructed from a %2}1, pass a" + " '%select{std::string_view|std::u16string_view}3'" + "%select{| (or an '%select{rtl::OStringChar|rtl::OUStringChar}3')|" + " via '%select{rtl::OStringConcatenation|rtl::OUStringConcatenation}3'}4", + expr->getExprLoc()) + << expr->getType() << (argType.isNull() ? 0 : 1) << argType + << (loplugin::TypeCheck(expr->getType()).Class("OString").Namespace("rtl").GlobalNamespace() + ? 0 + : 1) + << extra << expr->getSourceRange(); +} + +void StringView::handleCXXMemberCallExpr(CXXMemberCallExpr const* expr) +{ + auto const dc1 = loplugin::DeclCheck(expr->getMethodDecl()); + if (auto const dc2 = dc1.Function("copy")) + { + if (dc2.Class("OString").Namespace("rtl").GlobalNamespace() + || dc2.Class("OUString").Namespace("rtl").GlobalNamespace() + || dc2.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace()) + { + report(DiagnosticsEngine::Warning, "rather than copy, pass with a view using subView()", + expr->getExprLoc()) + << expr->getSourceRange(); + } + return; + } + if (auto const dc2 = dc1.Function("getToken")) + { + if (dc2.Class("OString").Namespace("rtl").GlobalNamespace() + || dc2.Class("OUString").Namespace("rtl").GlobalNamespace() + || dc2.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace()) + { + report(DiagnosticsEngine::Warning, + "rather than getToken, pass with a view using o3tl::getToken()", + expr->getExprLoc()) + << expr->getSourceRange(); + } + return; + } + if (auto const dc2 = dc1.Function("trim")) + { + if (dc2.Class("OString").Namespace("rtl").GlobalNamespace() + || dc2.Class("OUString").Namespace("rtl").GlobalNamespace() + || dc2.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace()) + { + report(DiagnosticsEngine::Warning, + "rather than trim, pass with a view using o3tl::trim()", expr->getExprLoc()) + << expr->getSourceRange(); + } + return; + } + if (auto const dc2 = dc1.Function("makeStringAndClear")) + { + if (dc2.Class("OStringBuffer").Namespace("rtl").GlobalNamespace() + || dc2.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace()) + { + auto const obj = expr->getImplicitObjectArgument(); + if (!(obj->isLValue() || obj->getType()->isPointerType())) + { + report(DiagnosticsEngine::Warning, + "rather than call makeStringAndClear on an rvalue, pass with a view", + expr->getExprLoc()) + << expr->getSourceRange(); + } + } + return; + } + if (auto const dc2 = dc1.Function("toString")) + { + if (dc2.Class("OStringBuffer").Namespace("rtl").GlobalNamespace() + || dc2.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace()) + { + report(DiagnosticsEngine::Warning, "rather than call toString, pass with a view", + expr->getExprLoc()) + << expr->getSourceRange(); + } + return; + } +} + +bool StringView::VisitCXXMemberCallExpr(CXXMemberCallExpr const* expr) +{ + if (ignoreLocation(expr)) + { + return true; + } + /** check for calls to O[U]StringBuffer::append that could be passed as a + std::u16string_view */ + if (loplugin::TypeCheck(expr->getType()) + .Class("OUStringBuffer") + .Namespace("rtl") + .GlobalNamespace() + || loplugin::TypeCheck(expr->getType()) + .Class("OStringBuffer") + .Namespace("rtl") + .GlobalNamespace()) + { + auto const dc = loplugin::DeclCheck(expr->getMethodDecl()); + if (dc.Function("append") || dc.Function("indexOf") || dc.Function("lastIndexOf")) + { + handleSubExprThatCouldBeView(expr->getArg(0)); + } + else if (dc.Function("insert")) + { + handleSubExprThatCouldBeView(expr->getArg(1)); + } + } + + // rather than getToken...toInt32, use o3tl::toInt(o3tl::getToken(...) + auto tc = loplugin::TypeCheck(expr->getImplicitObjectArgument()->getType()); + if (tc.Class("OUString").Namespace("rtl").GlobalNamespace() + || tc.Class("OString").Namespace("rtl").GlobalNamespace()) + { + auto const dc = loplugin::DeclCheck(expr->getMethodDecl()); + if (dc.Function("toInt32") || dc.Function("toUInt32") || dc.Function("toInt64") + || dc.Function("toDouble") || dc.Function("equalsAscii") + || dc.Function("equalsIgnoreAsciiCase") || dc.Function("compareToIgnoreAsciiCase") + || dc.Function("matchIgnoreAsciiCase") || dc.Function("trim") + || dc.Function("startsWith") || dc.Function("endsWith") || dc.Function("match")) + { + handleSubExprThatCouldBeView(expr->getImplicitObjectArgument()); + } + } + return true; +} + +/** check for calls to O[U]StringBuffer constructor that could be passed as a + std::u16string_view */ +bool StringView::VisitCXXConstructExpr(CXXConstructExpr const* expr) +{ + if (ignoreLocation(expr)) + { + return true; + } + if (!loplugin::TypeCheck(expr->getType()) + .Class("OUStringBuffer") + .Namespace("rtl") + .GlobalNamespace() + && !loplugin::TypeCheck(expr->getType()) + .Class("OStringBuffer") + .Namespace("rtl") + .GlobalNamespace()) + { + return true; + } + if (!compiler.getLangOpts().CPlusPlus17 && expr->isElidable()) // external C++03 code + { + return true; + } + if (expr->getNumArgs() > 0) + handleSubExprThatCouldBeView(expr->getArg(0)); + return true; +} + +loplugin::Plugin::Registration stringview("stringview"); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/stringviewdangle.cxx b/compilerplugins/clang/stringviewdangle.cxx new file mode 100644 index 000000000..99cb852d0 --- /dev/null +++ b/compilerplugins/clang/stringviewdangle.cxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "compat.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +/** +Look for places where we are assigning a temporary O[U]String to a std::*string_view, which leads +to a view pointing to freed memory. +*/ + +namespace +{ +class StringViewDangle : public loplugin::FilteringPlugin +{ +public: + explicit StringViewDangle(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override { return true; } + + virtual void run() override + { + if (!preRun()) + return; + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const*); + bool VisitVarDecl(VarDecl const*); +}; + +static const Expr* IgnoreImplicitAndConversionOperator(const Expr* expr) +{ + expr = expr->IgnoreImplicit(); + if (auto memberCall = dyn_cast(expr)) + { + if (auto conversionDecl = dyn_cast_or_null(memberCall->getMethodDecl())) + { + if (!conversionDecl->isExplicit()) + expr = memberCall->getImplicitObjectArgument()->IgnoreImpCasts(); + } + } + return expr; +} + +bool StringViewDangle::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* cxxOperatorCallExpr) +{ + if (ignoreLocation(cxxOperatorCallExpr)) + return true; + + auto op = cxxOperatorCallExpr->getOperator(); + if (op != OO_Equal) + return true; + if (!loplugin::TypeCheck(cxxOperatorCallExpr->getType()) + .ClassOrStruct("basic_string_view") + .StdNamespace()) + return true; + auto expr = IgnoreImplicitAndConversionOperator(cxxOperatorCallExpr->getArg(1)); + auto tc = loplugin::TypeCheck(expr->getType()); + if (!tc.Class("OUString").Namespace("rtl").GlobalNamespace() + && !tc.Class("OString").Namespace("rtl").GlobalNamespace()) + return true; + if (!isa(expr)) + return true; + report(DiagnosticsEngine::Warning, "view pointing into temporary i.e. dangling", + cxxOperatorCallExpr->getExprLoc()) + << cxxOperatorCallExpr->getSourceRange(); + return true; +} + +bool StringViewDangle::VisitVarDecl(VarDecl const* varDecl) +{ + if (ignoreLocation(varDecl)) + return true; + if (!loplugin::TypeCheck(varDecl->getType()).ClassOrStruct("basic_string_view").StdNamespace()) + return true; + if (!varDecl->hasInit()) + return true; + auto expr = IgnoreImplicitAndConversionOperator(varDecl->getInit()); + auto tc = loplugin::TypeCheck(expr->getType()); + if (!tc.Class("OUString").Namespace("rtl").GlobalNamespace() + && !tc.Class("OString").Namespace("rtl").GlobalNamespace()) + return true; + if (!isa(expr)) + return true; + report(DiagnosticsEngine::Warning, "view pointing into temporary i.e. dangling", + varDecl->getLocation()) + << varDecl->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration stringviewdangle("stringviewdangle"); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/stringviewparam.cxx b/compilerplugins/clang/stringviewparam.cxx new file mode 100644 index 000000000..eed439d0a --- /dev/null +++ b/compilerplugins/clang/stringviewparam.cxx @@ -0,0 +1,575 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include "config_clang.h" + +#include "check.hxx" +#include "functionaddress.hxx" +#include "plugin.hxx" + +// Find functions that take rtl::O[U]String parameters that can be generalized to take +// std::[u16]string_view instead. + +//TODO: At least theoretically, there are issues with replacing parameters that are being assigned +// to, as in +// +// void f(OUString s) { +// { +// OUString t = ...; +// s = t; +// } +// ... use s ... // if s is now std::u16string_view, it points into destroyed contents of t +// } + +namespace +{ +bool hasSalDllpublicExportAttr(FunctionDecl const* decl) +{ + if (auto const attr = decl->getAttr()) + { + return attr->getVisibility() == VisibilityAttr::Default; + } + return decl->hasAttr(); +} + +enum class StringType +{ + None, + RtlOstring, + RtlOustring +}; + +StringType relevantStringType(QualType type) +{ + loplugin::TypeCheck const c(type); + if (c.Class("OString").Namespace("rtl")) + { + return StringType::RtlOstring; + } + else if (c.Class("OUString").Namespace("rtl")) + { + return StringType::RtlOustring; + } + else + { + return StringType::None; + } +} + +bool relevantParmVarDecl(ParmVarDecl const* decl) +{ + auto const t1 = decl->getType(); + if (auto const t2 = t1->getAs()) + { + if (!t2->getPointeeType().isConstQualified()) + { + return false; + } + } + if (relevantStringType(t1.getNonReferenceType()) == StringType::None) + { + return false; + } + if (decl->hasAttr()) + { + return false; + } + return true; +} + +DeclRefExpr const* relevantDeclRefExpr(Expr const* expr) +{ + //TODO: Look through BO_Comma and AbstractConditionalOperator + auto const e = dyn_cast(expr->IgnoreParenImpCasts()); + if (e == nullptr) + { + return nullptr; + } + auto const d = dyn_cast(e->getDecl()); + if (d == nullptr) + { + return nullptr; + } + if (!relevantParmVarDecl(d)) + { + return nullptr; + } + return e; +} + +bool isStringView(QualType qt) +{ + return bool(loplugin::TypeCheck(qt).ClassOrStruct("basic_string_view").StdNamespace()); +} + +DeclRefExpr const* relevantImplicitCastExpr(ImplicitCastExpr const* expr) +{ + if (!isStringView(expr->getType())) + { + return nullptr; + } + return relevantDeclRefExpr(expr->getSubExprAsWritten()); +} + +DeclRefExpr const* relevantCXXMemberCallExpr(CXXMemberCallExpr const* expr) +{ + StringType t = relevantStringType(expr->getObjectType()); + if (t == StringType::None) + { + return nullptr; + } + bool good = false; + auto const d = expr->getMethodDecl(); + if (d->getOverloadedOperator() == OO_Subscript) + { + good = true; + } + else if (auto const i = d->getIdentifier()) + { + auto const n = i->getName(); + if (n == "endsWith" || n == "isEmpty" || n == "startsWith" || n == "subView" + || n == "indexOf" || n == "lastIndexOf" || n == "compareTo" || n == "match" + || n == "trim" || n == "toInt32" || n == "toUInt32" || n == "toInt64" || n == "toDouble" + || n == "equalsIgnoreAsciiCase" || n == "compareToIgnoreAsciiCase" || n == "getToken" + || n == "copy" || n == "equalsAscii" || n == "matchIgnoreAsciiCase") + { + good = true; + } +#if 0 + //TODO: rtl::O[U]String::getLength would be awkward to replace with + // std::[u16]string_view::length/size due to the sal_Int32 vs. std::size_t return type + // mismatch (C++20 ssize might make that easier, though); and while rtl::OString::getStr is + // documented to be NUL-terminated (so not eligible for replacement with + // std::string_view::data in general), rtl::OUString::getStr is not (so should be eligible + // for replacement with std::u16string_view::data, but some call sites might nevertheless + // incorrectly rely on NUL termination, so any replacement would need careful review): + if (n == "getLength" || (t == StringType::RtlOustring && n == "getStr")) + { + good = true; + } +#endif + } + if (!good) + { + return nullptr; + } + return relevantDeclRefExpr(expr->getImplicitObjectArgument()); +} + +SmallVector wrap(DeclRefExpr const* expr) +{ + if (expr == nullptr) + { + return {}; + } + return { expr }; +} + +SmallVector relevantCXXOperatorCallExpr(CXXOperatorCallExpr const* expr) +{ + auto const op = expr->getOperator(); + if (op == OO_Subscript) + { + auto const e = expr->getArg(0); + if (relevantStringType(e->getType()) == StringType::None) + { + return {}; + } + return wrap(relevantDeclRefExpr(e)); + } + if (expr->isComparisonOp() || (op == OO_Plus && expr->getNumArgs() == 2)) + { + SmallVector v; + if (auto const e = relevantDeclRefExpr(expr->getArg(0))) + { + v.push_back(e); + } + if (auto const e = relevantDeclRefExpr(expr->getArg(1))) + { + v.push_back(e); + } + return v; + } + if (op == OO_PlusEqual) + { + if (relevantStringType(expr->getArg(0)->getType()) != StringType::RtlOustring) + { + return {}; + } + return wrap(relevantDeclRefExpr(expr->getArg(1))); + } + return {}; +} + +//TODO: current implementation is not at all general, just tests what we encounter in practice: +bool hasStringViewOverload(ParmVarDecl const* decl) +{ + auto const d1 = cast(decl->getDeclContext()); + auto const ctx = d1->getDeclContext(); + if (!ctx->isLookupContext()) + { + return false; + } + auto const res = ctx->lookup(d1->getDeclName()); + auto const idx = decl->getFunctionScopeIndex(); + auto const n = d1->getNumParams(); + assert(n > idx); + for (auto i = res.begin(); i != res.end(); ++i) + { + auto const d2 = dyn_cast(*i); + if (d2 == nullptr) + { + continue; + } + if (d2->getNumParams() != n) + { + continue; + } + auto match = true; + for (unsigned j = 0; j != n; ++j) + { + if (j == idx) + { + //TODO: check for exactly std::string_view or std::u16string_view: + if (!isStringView(d2->getParamDecl(j)->getType())) + { + match = false; + break; + } + } + else if (d1->getParamDecl(j)->getType().getCanonicalType() + != d2->getParamDecl(j)->getType().getCanonicalType()) + { + match = false; + break; + } + } + if (match) + { + return true; + } + } + return false; +} + +class StringViewParam final + : public loplugin::FunctionAddress> +{ +public: + explicit StringViewParam(loplugin::InstantiationData const& data) + : FunctionAddress(data) + { + } + + //TODO: Also check lambdas + bool TraverseFunctionDecl(FunctionDecl* decl) + { + if (ignoreLocation(decl)) + { + return true; + } + if (!relevantFunctionDecl(decl)) + { + return FunctionAddress::TraverseFunctionDecl(decl); + } + auto const oldParams = currentParams_; + auto const n = decl->getNumParams(); + for (unsigned i = 0; i != n; ++i) + { + auto const d = decl->getParamDecl(i); + if (relevantParmVarDecl(d)) + { + currentParams_.insert(d); + } + } + auto const ret = FunctionAddress::TraverseFunctionDecl(decl); + if (ret) + { + for (unsigned i = 0; i != n; ++i) + { + auto const d1 = decl->getParamDecl(i); + if (currentParams_.find(d1) == currentParams_.end()) + { + continue; + } + if (containsPreprocessingConditionalInclusion(decl->getSourceRange())) + { + break; + } + badParams_.push_back(d1); + } + } + currentParams_ = oldParams; + return ret; + } + + bool TraverseCXXMethodDecl(CXXMethodDecl* decl) + { + if (ignoreLocation(decl)) + { + return true; + } + if (!relevantFunctionDecl(decl)) + { + return FunctionAddress::TraverseCXXMethodDecl(decl); + } + auto const oldParams = currentParams_; + auto const n = decl->getNumParams(); + for (unsigned i = 0; i != n; ++i) + { + auto const d = decl->getParamDecl(i); + if (relevantParmVarDecl(d)) + { + currentParams_.insert(d); + } + } + auto const ret = FunctionAddress::TraverseCXXMethodDecl(decl); + if (ret) + { + for (unsigned i = 0; i != n; ++i) + { + auto const d1 = decl->getParamDecl(i); + if (currentParams_.find(d1) == currentParams_.end()) + { + continue; + } + if (containsPreprocessingConditionalInclusion(decl->getSourceRange())) + { + break; + } + badParams_.push_back(d1); + } + } + currentParams_ = oldParams; + return ret; + } + + bool TraverseCXXConstructorDecl(CXXConstructorDecl* decl) + { + if (ignoreLocation(decl)) + { + return true; + } + if (!relevantFunctionDecl(decl)) + { + return FunctionAddress::TraverseCXXConstructorDecl(decl); + } + auto const oldParams = currentParams_; + auto const n = decl->getNumParams(); + for (unsigned i = 0; i != n; ++i) + { + auto const d = decl->getParamDecl(i); + if (relevantParmVarDecl(d)) + { + currentParams_.insert(d); + } + } + auto const ret = FunctionAddress::TraverseCXXConstructorDecl(decl); + if (ret) + { + for (unsigned i = 0; i != n; ++i) + { + auto const d1 = decl->getParamDecl(i); + if (currentParams_.find(d1) == currentParams_.end()) + { + continue; + } + if (containsPreprocessingConditionalInclusion(decl->getSourceRange())) + { + break; + } + badParams_.push_back(d1); + } + } + currentParams_ = oldParams; + return ret; + } + + bool TraverseImplicitCastExpr(ImplicitCastExpr* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const e = relevantImplicitCastExpr(expr); + if (e == nullptr) + { + return FunctionAddress::TraverseImplicitCastExpr(expr); + } + currentGoodUses_.insert(e); + auto const ret = FunctionAddress::TraverseImplicitCastExpr(expr); + currentGoodUses_.erase(e); + return ret; + } + + bool TraverseCXXMemberCallExpr(CXXMemberCallExpr* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const e = relevantCXXMemberCallExpr(expr); + if (e == nullptr) + { + return FunctionAddress::TraverseCXXMemberCallExpr(expr); + } + currentGoodUses_.insert(e); + auto const ret = FunctionAddress::TraverseCXXMemberCallExpr(expr); + currentGoodUses_.erase(e); + return ret; + } + + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const es = relevantCXXOperatorCallExpr(expr); + if (es.empty()) + { + return FunctionAddress::TraverseCXXOperatorCallExpr(expr); + } + currentGoodUses_.insert(es.begin(), es.end()); + auto const ret = FunctionAddress::TraverseCXXOperatorCallExpr(expr); + for (auto const i : es) + { + currentGoodUses_.erase(i); + } + return ret; + } + + bool VisitDeclRefExpr(DeclRefExpr* expr) + { + if (!FunctionAddress::VisitDeclRefExpr(expr)) + { + return false; + } + if (ignoreLocation(expr)) + { + return true; + } + if (currentGoodUses_.find(expr) != currentGoodUses_.end()) + { + return true; + } + if (auto const d = dyn_cast(expr->getDecl())) + { + currentParams_.erase(d); + } + return true; + } + +private: + void run() override + { + if (!compiler.getLangOpts().CPlusPlus) + { + return; + } + if (compiler.getPreprocessor().getIdentifierInfo("NDEBUG")->hasMacroDefinition()) + { + return; + } + StringRef fn(handler.getMainFileName()); + // leave the string QA tests alone + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/")) + { + return; + } + if (!TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) + { + return; + } + auto const ignoredFns = getFunctionsWithAddressTaken(); + for (auto const i : badParams_) + { + auto const d1 = cast(i->getDeclContext()); + if (ignoredFns.find(d1) != ignoredFns.end()) + { + continue; + } + if (hasStringViewOverload(i)) + { + continue; + } + auto const t = relevantStringType(i->getType().getNonReferenceType()); + assert(t != StringType::None); + report(DiagnosticsEngine::Warning, + "replace function parameter of type %0 with " + "'%select{std::string_view|std::u16string_view}1'", + i->getLocation()) + << i->getType() << (int(t) - 1) << i->getSourceRange(); + for (auto d2 = d1;;) + { + d2 = d2->getPreviousDecl(); + if (d2 == nullptr) + { + break; + } + auto const d3 = d2->getParamDecl(i->getFunctionScopeIndex()); + report(DiagnosticsEngine::Note, "previous declaration is here", d3->getLocation()) + << d3->getSourceRange(); + } + } + } + + bool relevantFunctionDecl(FunctionDecl const* decl) + { + if (!decl->doesThisDeclarationHaveABody()) + { + return false; + } + if (decl->getBody() == nullptr) // unparsed template + { + return false; + } + if (auto const d = dyn_cast(decl)) + { + if (d->isVirtual()) + { + return false; + } + } + if (decl->isFunctionTemplateSpecialization()) + { + return false; + } + if (decl->getLocation().isMacroID()) + { + return false; + } + // Filter out functions that are presumably meant to be called dynamically (e.g., via + // dlopen, or backwards compatibility stubs in cppuhelper/cppu/sal compat.cxx): + if (decl->getPreviousDecl() == nullptr && !decl->isInlined() + && hasSalDllpublicExportAttr(decl) + && compiler.getSourceManager().isInMainFile(decl->getLocation())) + { + return false; + } + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(decl->getLocation()))) + { + return false; + } + return true; + } + + std::set currentParams_; + std::set currentGoodUses_; + std::vector badParams_; +}; + +static loplugin::Plugin::Registration reg("stringviewparam"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/stringviewvar.cxx b/compilerplugins/clang/stringviewvar.cxx new file mode 100644 index 000000000..06123531e --- /dev/null +++ b/compilerplugins/clang/stringviewvar.cxx @@ -0,0 +1,407 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include "config_clang.h" + +#include "check.hxx" +#include "functionaddress.hxx" +#include "plugin.hxx" + +// Find various of type rtl::O[U]String that can be converted to std::[u16]string_view instead. + +// This can generate false positives e.g. +// OUString sSave( aToken ); +// aToken.append("foo"); +// aToken = sSave; +// where the data that is backing the view is modified and then the view is used to assign to +// the same source data. + +namespace +{ +enum class StringType +{ + None, + RtlOstring, + RtlOustring +}; + +StringType relevantStringType(QualType type) +{ + loplugin::TypeCheck const c(type); + if (c.Class("OString").Namespace("rtl")) + { + return StringType::RtlOstring; + } + else if (c.Class("OUString").Namespace("rtl")) + { + return StringType::RtlOustring; + } + else + { + return StringType::None; + } +} + +bool relevantVarDecl(VarDecl const* decl) +{ + auto const t1 = decl->getType(); + if (relevantStringType(t1.getNonReferenceType()) == StringType::None) + { + return false; + } + if (isa(decl)) + { + return false; + } + return true; +} + +DeclRefExpr const* relevantDeclRefExpr(Expr const* expr) +{ + //TODO: Look through BO_Comma and AbstractConditionalOperator + auto const e = dyn_cast(expr->IgnoreParenImpCasts()); + if (e == nullptr) + { + return nullptr; + } + auto const d = dyn_cast(e->getDecl()); + if (d == nullptr) + { + return nullptr; + } + if (!relevantVarDecl(d)) + { + return nullptr; + } + return e; +} + +bool isStringView(QualType qt) +{ + return bool(loplugin::TypeCheck(qt).ClassOrStruct("basic_string_view").StdNamespace()); +} + +DeclRefExpr const* relevantImplicitCastExpr(ImplicitCastExpr const* expr) +{ + if (!isStringView(expr->getType())) + { + return nullptr; + } + return relevantDeclRefExpr(expr->getSubExprAsWritten()); +} + +DeclRefExpr const* relevantCStyleCastExpr(CStyleCastExpr const* expr) +{ + if (expr->getCastKind() != CK_ToVoid) + { + return nullptr; + } + return relevantDeclRefExpr(expr->getSubExprAsWritten()); +} + +DeclRefExpr const* relevantCXXMemberCallExpr(CXXMemberCallExpr const* expr) +{ + StringType t = relevantStringType(expr->getObjectType()); + if (t == StringType::None) + { + return nullptr; + } + bool good = false; + auto const d = expr->getMethodDecl(); + if (d->getOverloadedOperator() == OO_Subscript) + { + good = true; + } + else if (auto const i = d->getIdentifier()) + { + auto const n = i->getName(); + if (n == "endsWith" || n == "isEmpty" || n == "startsWith" || n == "subView" + || n == "indexOf" || n == "lastIndexOf" || n == "compareTo" || n == "match" + || n == "trim" || n == "toInt32" || n == "toInt64" || n == "toDouble" + || n == "equalsIgnoreAsciiCase" || n == "compareToIgnoreAsciiCase" || n == "getToken" + || n == "copy") + { + good = true; + } +#if 0 + //TODO: rtl::O[U]String::getLength would be awkward to replace with + // std::[u16]string_view::length/size due to the sal_Int32 vs. std::size_t return type + // mismatch (C++20 ssize might make that easier, though); and while rtl::OString::getStr is + // documented to be NUL-terminated (so not eligible for replacement with + // std::string_view::data in general), rtl::OUString::getStr is not (so should be eligible + // for replacement with std::u16string_view::data, but some call sites might nevertheless + // incorrectly rely on NUL termination, so any replacement would need careful review): + if (n == "getLength" || (t == StringType::RtlOustring && n == "getStr")) + { + good = true; + } +#endif + } + if (!good) + { + return nullptr; + } + return relevantDeclRefExpr(expr->getImplicitObjectArgument()); +} + +SmallVector wrap(DeclRefExpr const* expr) +{ + if (expr == nullptr) + { + return {}; + } + return { expr }; +} + +SmallVector relevantCXXOperatorCallExpr(CXXOperatorCallExpr const* expr) +{ + auto const op = expr->getOperator(); + if (op == OO_Subscript) + { + auto const e = expr->getArg(0); + if (relevantStringType(e->getType()) == StringType::None) + { + return {}; + } + return wrap(relevantDeclRefExpr(e)); + } + if (expr->isComparisonOp() || (op == OO_Plus && expr->getNumArgs() == 2)) + { + SmallVector v; + if (auto const e = relevantDeclRefExpr(expr->getArg(0))) + { + v.push_back(e); + } + if (auto const e = relevantDeclRefExpr(expr->getArg(1))) + { + v.push_back(e); + } + return v; + } + if (op == OO_PlusEqual) + { + if (relevantStringType(expr->getArg(0)->getType()) != StringType::RtlOustring) + { + return {}; + } + return wrap(relevantDeclRefExpr(expr->getArg(1))); + } + if (op == OO_Equal) + { + if (!isStringView(expr->getArg(1)->getType())) + { + return {}; + } + return wrap(relevantDeclRefExpr(expr->getArg(0))); + } + return {}; +} + +static const Expr* IgnoreImplicitAndConversionOperator(const Expr* expr) +{ + expr = expr->IgnoreImplicit(); + if (auto memberCall = dyn_cast(expr)) + { + if (auto conversionDecl = dyn_cast_or_null(memberCall->getMethodDecl())) + { + if (!conversionDecl->isExplicit()) + expr = memberCall->getImplicitObjectArgument()->IgnoreImplicit(); + } + } + return expr; +} + +class StringViewVar final + : public loplugin::FunctionAddress> +{ +public: + explicit StringViewVar(loplugin::InstantiationData const& data) + : FunctionAddress(data) + { + } + + bool VisitVarDecl(VarDecl* decl) + { + if (ignoreLocation(decl)) + { + return true; + } + if (decl->hasGlobalStorage()) + { + return true; + } + if (!decl->isThisDeclarationADefinition()) + { + return true; + } + if (!relevantVarDecl(decl)) + { + return true; + } + if (decl->getInit()) + { + auto expr = IgnoreImplicitAndConversionOperator(decl->getInit()); + if (auto castExpr = dyn_cast(expr)) + { + expr = IgnoreImplicitAndConversionOperator(castExpr->getSubExpr()); + } + if (auto cxxConstruct = dyn_cast(expr)) + { + if (cxxConstruct->getNumArgs() == 0) + currentVars_.insert(decl); // default constructor + else if (cxxConstruct->getNumArgs() == 1 + && isStringView(cxxConstruct->getArg(0)->getType())) + currentVars_.insert(decl); + } + } + return true; + } + + bool TraverseImplicitCastExpr(ImplicitCastExpr* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const e = relevantImplicitCastExpr(expr); + if (e == nullptr) + { + return FunctionAddress::TraverseImplicitCastExpr(expr); + } + currentGoodUses_.insert(e); + auto const ret = FunctionAddress::TraverseImplicitCastExpr(expr); + currentGoodUses_.erase(e); + return ret; + } + + bool TraverseCStyleCastExpr(CStyleCastExpr* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const e = relevantCStyleCastExpr(expr); + if (e == nullptr) + { + return FunctionAddress::TraverseCStyleCastExpr(expr); + } + currentGoodUses_.insert(e); + auto const ret = FunctionAddress::TraverseCStyleCastExpr(expr); + currentGoodUses_.erase(e); + return ret; + } + + bool TraverseCXXMemberCallExpr(CXXMemberCallExpr* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const e = relevantCXXMemberCallExpr(expr); + if (e == nullptr) + { + return FunctionAddress::TraverseCXXMemberCallExpr(expr); + } + currentGoodUses_.insert(e); + auto const ret = FunctionAddress::TraverseCXXMemberCallExpr(expr); + currentGoodUses_.erase(e); + return ret; + } + + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const es = relevantCXXOperatorCallExpr(expr); + if (es.empty()) + { + return FunctionAddress::TraverseCXXOperatorCallExpr(expr); + } + currentGoodUses_.insert(es.begin(), es.end()); + auto const ret = FunctionAddress::TraverseCXXOperatorCallExpr(expr); + for (auto const i : es) + { + currentGoodUses_.erase(i); + } + return ret; + } + + bool VisitDeclRefExpr(DeclRefExpr* expr) + { + if (!FunctionAddress::VisitDeclRefExpr(expr)) + { + return false; + } + if (ignoreLocation(expr)) + { + return true; + } + if (currentGoodUses_.find(expr) != currentGoodUses_.end()) + { + return true; + } + if (auto const d = dyn_cast(expr->getDecl())) + { + currentVars_.erase(d); + } + return true; + } + +private: + void run() override + { + if (!compiler.getLangOpts().CPlusPlus) + { + return; + } + if (compiler.getPreprocessor().getIdentifierInfo("NDEBUG")->hasMacroDefinition()) + { + return; + } + StringRef fn(handler.getMainFileName()); + // leave the string QA tests alone + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/")) + { + return; + } + // false + + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/svtools/source/svrtf/parrtf.cxx")) + { + return; + } + if (!TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) + { + return; + } + for (auto const i : currentVars_) + { + auto const t = relevantStringType(i->getType().getNonReferenceType()); + report(DiagnosticsEngine::Warning, + "replace var of type %0 with " + "'%select{std::string_view|std::u16string_view}1'", + i->getLocation()) + << i->getType() << (int(t) - 1) << i->getSourceRange(); + } + } + + std::set currentVars_; + std::set currentGoodUses_; +}; + +static loplugin::Plugin::Registration reg("stringviewvar", + false); // might generate false+ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/subtlezeroinit.cxx b/compilerplugins/clang/subtlezeroinit.cxx new file mode 100644 index 000000000..b1b91c847 --- /dev/null +++ b/compilerplugins/clang/subtlezeroinit.cxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" + +// Find occurrences of 'new T()' where the instance is zero-initialized upfront +// since C++11. For one, in many cases this may be unnecessary and unintended, +// as the code was written before C++11. For another, the zero-initialization +// would go away when T gets a user-provided default constructor, for example, +// so better make any necessary initialization more explicit in the code. + +namespace { + +class SubtleZeroInit final: + public loplugin::FilteringPlugin +{ +public: + explicit SubtleZeroInit(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + bool VisitCXXNewExpr(CXXNewExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + auto ce = expr->getConstructExpr(); + if (ce == nullptr) { + return true; + } + if (!ce->requiresZeroInitialization()) { + return true; + } + report( + DiagnosticsEngine::Warning, + ("if zero-initialization of %0 is intentional here, better make" + " that more explicit (e.g., assigning to members, default" + " constructor, default member initializers, std::memset)"), + expr->getExprLoc()) + << ce->getType() << expr->getSourceRange(); + return true; + } + + virtual bool preRun() override { + return compiler.getLangOpts().CPlusPlus; + } + + virtual void run() override { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } +}; + +static loplugin::Plugin::Registration subtlezeroinit("subtlezeroinit"); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/badstatics.cxx b/compilerplugins/clang/test/badstatics.cxx new file mode 100644 index 000000000..db9a023d9 --- /dev/null +++ b/compilerplugins/clang/test/badstatics.cxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +class Image { public: ~Image() { ::std::abort(); } }; +class Bitmap { public: ~Bitmap() { ::std::abort(); } }; + +struct WithImage +{ + Image image; +}; + +struct WithBitmap +{ + Bitmap bitmap; +}; + +WithImage g_bug1; // expected-error {{bad static variable causes crash on shutdown [loplugin:badstatics]}} +WithBitmap g_bug2; // expected-error {{bad static variable causes crash on shutdown [loplugin:badstatics]}} + +static WithImage g_bug3; // expected-error {{bad static variable causes crash on shutdown [loplugin:badstatics]}} + +void foo() { + static Image s_bug1; // expected-error {{bad static variable causes crash on shutdown [loplugin:badstatics]}} + Image nobug; +} + +::std::unique_ptr g_bug4; // expected-error {{bad static variable causes crash on shutdown [loplugin:badstatics]}} + +::std::shared_ptr g_bug5; // expected-error {{bad static variable causes crash on shutdown [loplugin:badstatics]}} + +::std::weak_ptr g_nobug; + +struct DerivedWithImage : WithImage +{ +}; + +DerivedWithImage g_bug6; // expected-error {{bad static variable causes crash on shutdown [loplugin:badstatics]}} + +::std::vector g_bug7; // expected-error {{bad static variable causes crash on shutdown [loplugin:badstatics]}} + +::std::vector<::std::unique_ptr> g_bug8; // expected-error {{bad static variable causes crash on shutdown [loplugin:badstatics]}} + +::std::map g_bug9; // expected-error {{bad static variable causes crash on shutdown [loplugin:badstatics]}} + +::std::map g_bug10; // expected-error {{bad static variable causes crash on shutdown [loplugin:badstatics]}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/blockblock.cxx b/compilerplugins/clang/test/blockblock.cxx new file mode 100644 index 000000000..422430f9c --- /dev/null +++ b/compilerplugins/clang/test/blockblock.cxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +int f(bool b1, bool b2) { + if (b1 || b2) { // no warning +#if 0 + if (b1) +#endif + { // expected-error {{block directly inside block [loplugin:blockblock]}} + { // expected-note {{inner block here [loplugin:blockblock]}} + return 0; + } + } + } + return 1; +} + +void foo(int x) +{ + switch (x) + { + case 1: break; + case 2: {} break; + case 3: + { // expected-error {{block directly inside block [loplugin:blockblock]}} + { + } + break; + } + } +} + + +int main() { // expected-error {{block directly inside block [loplugin:blockblock]}} + { // expected-note {{inner block here [loplugin:blockblock]}} + int x = 1; + (void)x; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/bufferadd.cxx b/compilerplugins/clang/test/bufferadd.cxx new file mode 100644 index 000000000..c8057a6f4 --- /dev/null +++ b/compilerplugins/clang/test/bufferadd.cxx @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +// --------------------------------------------------------------- +// replacing OUStringBuffer.append sequences to OUString+ +namespace test1 +{ +void f1() +{ + // expected-error@+1 {{convert this append sequence into a *String + sequence [loplugin:bufferadd]}} + OUStringBuffer v; + v.append("xxx"); + v.append("xxx"); +} +void f2() +{ + // expected-error@+1 {{convert this append sequence into a *String + sequence [loplugin:bufferadd]}} + OUStringBuffer v; + v.append("xxx").append("aaaa"); +} +void f3(OString class_name) +{ + // expected-error@+1 {{convert this append sequence into a *String + sequence [loplugin:bufferadd]}} + OStringBuffer sig_buf(5 + class_name.getLength()); + sig_buf.append("(I)L"); + //sig_buf.append( class_name.replace( '.', '/' ) ); + sig_buf.append(';'); + OString sig(sig_buf.makeStringAndClear()); + (void)sig; +} +void f4(sal_Unicode const* pPathBegin) +{ + // expected-error@+1 {{convert this append sequence into a *String + sequence [loplugin:bufferadd]}} + OUStringBuffer v; + v.append(pPathBegin, 12); + v.append("aaaa"); +} +void f5(OUStringBuffer& input) +{ + // expected-error@+1 {{convert this append sequence into a *String + sequence [loplugin:bufferadd]}} + OUStringBuffer v(input); + v.append("aaaa"); +} +void f6(OString const& s) +{ + // expected-error@+1 {{convert this append sequence into a *String + sequence [loplugin:bufferadd]}} + OUStringBuffer b("foo"); + b.append(OStringToOUString(s, RTL_TEXTENCODING_ASCII_US)); +} +struct Footer +{ + OStringBuffer m_descriptorStart; + OString m_descriptorEnd; + OString f8() const + { + // expected-error@+1 {{convert this append sequence into a *String + sequence [loplugin:bufferadd]}} + OStringBuffer buf(m_descriptorStart); + buf.append(m_descriptorEnd); + return buf.makeStringAndClear(); + } +}; +} + +namespace test2 +{ +void f2() +{ + // no warning expected + OUStringBuffer v; + v.append("xxx"); + if (true) + v.append("yyyy"); +} +void appendTo(OUStringBuffer&); +void f3() +{ + // no warning expected + OUStringBuffer v; + appendTo(v); + v.append("xxx"); +} +void f4() +{ + // no warning expected + OUStringBuffer v; + v.append("xxx"); + v.setLength(0); +} +void f5() +{ + // no warning expected + OUStringBuffer v; + v.append("xxx"); + v[1] = 'x'; +} +void f6() +{ + // no warning expected + OUStringBuffer noel1("xxx"); + while (true) + noel1.append("ffff").append("aaa"); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/buriedassign.cxx b/compilerplugins/clang/test/buriedassign.cxx new file mode 100644 index 000000000..0d9f01193 --- /dev/null +++ b/compilerplugins/clang/test/buriedassign.cxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +namespace test1 +{ +int foo(int); + +void main() +{ + int x = 1; + foo(x = 2); + // expected-error@-1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} + int y = x = 1; // no warning expected + (void)y; + int z = foo(x = 1); + // expected-error@-1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} + (void)z; + switch (x = 1) + { // expected-error@-1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} + } + std::map map1; + map1[x = 1] = 1; + // expected-error@-1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} +} +} + +namespace test2 +{ +struct MyInt +{ + int x; + MyInt(int i) + : x(i) + { + } + MyInt(MyInt const&) = default; + MyInt& operator=(MyInt const&) = default; + MyInt& operator=(int) { return *this; } + bool operator<(MyInt const& other) const { return x < other.x; } +}; + +MyInt foo(MyInt); + +void main() +{ + MyInt x = 1; + foo(x = 2); + // expected-error@-1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} + MyInt y = x = 1; // no warning expected + (void)y; + MyInt z = foo(x = 1); + // expected-error@-1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} + (void)z; + z = x; // no warning expected + std::map map1; + map1[x = 1] = 1; + // expected-error@-1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} +} +} + +namespace test3 +{ +void main(OUString sUserAutoCorrFile, OUString sExt) +{ + OUString sRet; + if (sUserAutoCorrFile == "xxx") + sRet = sUserAutoCorrFile; // no warning expected + if (sUserAutoCorrFile == "yyy") + (sRet = sUserAutoCorrFile) + += sExt; // expected-error@-1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} +} +} + +// no warning expected +namespace test4 +{ +struct Task +{ + void exec(); +}; +std::unique_ptr pop(); + +void foo() +{ + std::unique_ptr pTask; + while ((pTask = pop())) + pTask->exec(); +} +} + +namespace test5 +{ +void main(OUString sUserAutoCorrFile, int* p2) +{ + OUString sRet; + int* p1; + if (sUserAutoCorrFile == "yyy" && (p1 = p2)) + sRet = sUserAutoCorrFile; + if (sUserAutoCorrFile == "yyy" && nullptr != (p1 = p2)) + sRet = sUserAutoCorrFile; + // expected-error@+1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} + if (nullptr != (p1 = p2)) + sRet = sUserAutoCorrFile; + // expected-error@+1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} + if ((p1 = p2) != nullptr) + sRet = sUserAutoCorrFile; + // expected-error@+1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} + if ((p1 = p2)) + sRet = sUserAutoCorrFile; + // expected-error@+1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} + if ((p1 = p2) && sUserAutoCorrFile == "yyy") + sRet = sUserAutoCorrFile; + // expected-error@+1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} + if ((p1 = p2) || sUserAutoCorrFile == "yyy") + sRet = sUserAutoCorrFile; + // expected-error@+1 {{buried assignment, rather put on own line [loplugin:buriedassign]}} + if ((p1 = p2) && sUserAutoCorrFile == "yyy") + sRet = sUserAutoCorrFile; + (void)sRet; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/casttovoid.cxx b/compilerplugins/clang/test/casttovoid.cxx new file mode 100644 index 000000000..3d8c22b49 --- /dev/null +++ b/compilerplugins/clang/test/casttovoid.cxx @@ -0,0 +1,125 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#undef NDEBUG +#include + +#define CAST_N3 (void) n3 +#define ASSERT_N4 assert(n4 == 0) +#define ASSERT(x) assert(x) +#define USE(x) x + +int f1(int n1, int n2, int n3, int n4, int n5) { + (void) n1; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + int const & r1 = n1; // expected-note {{first consumption is here [loplugin:casttovoid]}} + (void) n2; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + int const & r2 = {n2}; // expected-note {{first consumption is here [loplugin:casttovoid]}} + (void) n3; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + int const & r3{n3}; // expected-note {{first consumption is here [loplugin:casttovoid]}} + (void) n4; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + int const & r4(n4); // expected-note {{first consumption is here [loplugin:casttovoid]}} + (void) n5; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + int const & r5 = (n5); // expected-note {{first consumption is here [loplugin:casttovoid]}} + return r1 + r2 + r3 + r4 + r5; +} + +int const & f2(int const & n) { + (void) n; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + return n; // expected-note {{first consumption is here [loplugin:casttovoid]}} +} + +int const & f3(int const & n) { + (void) n; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + return (n); // expected-note {{first consumption is here [loplugin:casttovoid]}} +} + +int const & f4(int const & n) { + (void) n; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + return {n}; // expected-note {{first consumption is here [loplugin:casttovoid]}} +} + +int const & f5(int const & n) { + (void) n; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + return {(n)}; // expected-note {{first consumption is here [loplugin:casttovoid]}} +} + +struct S1 { + S1(int n1, int n2): + n1_(n1), // expected-note {{first consumption is here [loplugin:casttovoid]}} + n2_{n2} // expected-note {{first consumption is here [loplugin:casttovoid]}} + { + (void) n1; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + (void) n2; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + } + int const n1_; + int const n2_; +}; + +struct S2 { int n; }; + +int fS2_1(S2 s) { + (void) s; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + return s.n; // expected-note {{first consumption is here [loplugin:casttovoid]}} +} + +int const & fS2_2(S2 const & s) { + (void) s; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + return s.n; // expected-note {{first consumption is here [loplugin:casttovoid]}} +} + +// Don't trigger assert in CastToVoid::VisitReturnStmt: +int n = [] { return 0; }(); + +int f() { + int n1 = n; + int n2 = [](int const & n) -> int const & { + (void) n; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + return n; // expected-note {{first consumption is here [loplugin:casttovoid]}} + }(n1); + return n2; +} + +int main() { + int n1 = 0; + (void) n1; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + (void const) n1; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + (void volatile) n1; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + (void const volatile) n1; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + (void) (n1); // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + (void) ((n1)); // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + (void(n1)); // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + static_cast(n1); // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + int n2 = 0; + assert(n2 == 0); + (void) n2; // expected-error {{unnecessary cast to void [loplugin:casttovoid]}} + int n3 = 0; + CAST_N3; + int n4 = 0; + ASSERT_N4; + (void) n4; + int n5 = 0; + assert(n5 == 0); + (void) n5; + int n6 = 0; + ASSERT(n6 == 0); + (void) n6; + int n7 = 0; + assert(USE(n7) == 0); + (void) n7; + int n8 = 0; + ASSERT(USE(USE(n8 == 0))); + (void) n8; + int volatile n9 = 0; + (void) n9; + return n1 // expected-note 8 {{first consumption is here [loplugin:casttovoid]}} + + n2 // expected-note {{first consumption is here [loplugin:casttovoid]}} + + n3; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/classmemaccess.cxx b/compilerplugins/clang/test/classmemaccess.cxx new file mode 100644 index 000000000..05bb457f8 --- /dev/null +++ b/compilerplugins/clang/test/classmemaccess.cxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +void f(struct Incomplete* p1, struct S* p2); + +struct S +{ + S(); +}; + +void f(struct Incomplete* p1, struct S* p2) +{ + S s; + // expected-error@+1 {{writing to an object of non-trivial type 'S'; use assignment instead [loplugin:classmemaccess]}} + std::memset(&s, 0, sizeof s); + // expected-error@+1 {{writing to an object of non-trivial type 'S'; use assignment instead [loplugin:classmemaccess]}} + std::memset(static_cast(&s), 0, sizeof s); + auto const disableWarning = static_cast(&s); + std::memset(disableWarning, 0, sizeof s); + S a[1][1]; + // expected-error@+1 {{writing to an object of non-trivial type 'S'; use assignment instead [loplugin:classmemaccess]}} + std::memset(a, 0, sizeof a); + std::memset(p1, 0, 10); // conservatively assume Incomplete may be trivial + // expected-error@+1 {{writing to an object of non-trivial type 'S'; use assignment instead [loplugin:classmemaccess]}} + std::memset(p2, 0, 10); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/collapseif.cxx b/compilerplugins/clang/test/collapseif.cxx new file mode 100644 index 000000000..6f8658473 --- /dev/null +++ b/compilerplugins/clang/test/collapseif.cxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +int f1(int x) +{ + // expected-error@+1 {{nested if should be collapsed into one statement 9 9 [loplugin:collapseif]}} + if (x == 1) + if (x == 2) + return 1; + + // expected-error@+1 {{nested if should be collapsed into one statement 9 9 [loplugin:collapseif]}} + if (x == 1) + { + if (x == 2) + return 1; + } + + // no warning expected + if (x == 1) + { + // comment here prevents warning + if (x == 2) + return 1; + } + + // no warning expected + if (x == 1) + { + if (x == 2) + return 1; + } + else + return 3; + + // no warning expected + if (x == 1) + { + if (x == 2) + return 1; + else + return 3; + } + + return 2; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/commaoperator.cxx b/compilerplugins/clang/test/commaoperator.cxx new file mode 100644 index 000000000..260aeab4e --- /dev/null +++ b/compilerplugins/clang/test/commaoperator.cxx @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +bool f(); + +struct S { S(); }; + +int main() { + f(), f(), f(); // expected-error {{comma operator hides code [loplugin:commaoperator]}} + (f(), f()); + for ( + f(), f(); + f(), f(); // expected-error {{comma operator hides code [loplugin:commaoperator]}} + f(), f()) + f(), f(); // expected-error {{comma operator hides code [loplugin:commaoperator]}} + S s; + (s = S(), s = S(), s = S()); + for (s = S(), f(); f(); s = S(), f()) {} + while (s = S(), f()) {} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/conditionalstring.cxx b/compilerplugins/clang/test/conditionalstring.cxx new file mode 100644 index 000000000..c044ee324 --- /dev/null +++ b/compilerplugins/clang/test/conditionalstring.cxx @@ -0,0 +1,27 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +void f(OUString s, bool b) +{ + // expected-error@+2 {{replace 2nd operand of conditional expression with `std::u16string_view` [loplugin:conditionalstring]}} + // expected-note@+1 {{conditional expression is here [loplugin:conditionalstring]}} + s += (b ? OUString("a") : throw 0); + // expected-error@+1 {{replace both 2nd and 3rd operands of conditional expression with `std::u16string_view` [loplugin:conditionalstring]}} + b = (b ? ("x") : (OUString(("y")))) == s; + // expected-error@+1 {{replace both 2nd and 3rd operands of conditional expression with `std::u16string_view` [loplugin:conditionalstring]}} + b = operator==(s, b ? OUString("x") : OUString("y")); + // expected-error@+1 {{replace both 2nd and 3rd operands of conditional expression with `std::u16string_view` [loplugin:conditionalstring]}} + s.operator+=(b ? OUString("x") : OUString("y")); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/constfields.cxx b/compilerplugins/clang/test/constfields.cxx new file mode 100644 index 000000000..c045396d5 --- /dev/null +++ b/compilerplugins/clang/test/constfields.cxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +struct Test0 +{ + void method1() {} +}; + +// checking for calling non-const method +struct Test1 +// expected-error@-1 {{notconst m_field1 [loplugin:constfields]}} +{ + Test0* m_field1; + + void method1() + { + if (m_field1) + m_field1->method1(); + } +}; + +// checking for assigning to field +struct Test2 +// expected-error@-1 {{notconst m_field1 [loplugin:constfields]}} +{ + Test0* m_field1; + + Test2() + : m_field1(nullptr) + { + } + + void method1() { m_field1 = nullptr; } +}; +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/constmethod.cxx b/compilerplugins/clang/test/constmethod.cxx new file mode 100644 index 000000000..e5efcae16 --- /dev/null +++ b/compilerplugins/clang/test/constmethod.cxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +class OutputDevice; + +struct Class1 +{ + struct Impl { + void foo_notconst(); + void foo_const() const; + int & foo_int_ref() const; + int const & foo_const_int_ref() const; + int * foo_int_ptr() const; + int const * foo_const_int_ptr() const; + }; + std::unique_ptr pImpl; + int* m_pint; + VclPtr m_pvcl; + + void GetFoo1() { + pImpl->foo_notconst(); + } + void GetFoo2() { + pImpl->foo_const(); + } + int& GetFoo3() { + return pImpl->foo_int_ref(); + } + int const & GetFoo3a() { // expected-error {{this method can be const [loplugin:constmethod]}} + return pImpl->foo_const_int_ref(); + } + int* GetFoo3b() { + return pImpl->foo_int_ptr(); + } + int const * GetFoo3c() { // expected-error {{this method can be const [loplugin:constmethod]}} + return pImpl->foo_const_int_ptr(); + } + Impl* GetFoo4() { + return pImpl.get(); // no warning expected + } + int* GetFoo5() { + return m_pint; // no warning expected + } + int& GetFoo6() { + return *m_pint; // no warning expected + } + OutputDevice* GetFoo7() { + return m_pvcl; // no warning expected + } +}; diff --git a/compilerplugins/clang/test/constparams.cxx b/compilerplugins/clang/test/constparams.cxx new file mode 100644 index 000000000..e6b22ca91 --- /dev/null +++ b/compilerplugins/clang/test/constparams.cxx @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#pragma clang diagnostic ignored "-Wunknown-warning-option" // for Clang < 13 +#pragma clang diagnostic ignored "-Wunused-but-set-variable" + +struct Class1 +{ + int const * m_f1; + Class1(int * f1) : m_f1(f1) {} // expected-error {{this parameter can be const Class1::Class1 [loplugin:constparams]}} +}; + +struct Class2 +{ + int * m_f2; + Class2(int * f2) : m_f2(f2) {} +}; +struct Class3 +{ + int * m_f2; + Class3(void * f2) : m_f2(static_cast(f2)) {} +}; + +int const * f1(int *); // expected-note {{canonical parameter declaration here [loplugin:constparams]}} +int const * f2(int *); +int const * f3(int *); +void g() { + int const * (*p1)(int *); + int n = 0; + f1(&n); + p1 = f2; + typedef void (*P2)(); + P2 p2; + p2 = (P2) (f3); +} +int const * f1(int * p) { // expected-error {{this parameter can be const f1 [loplugin:constparams]}} + return p; +} +void f4(std::string * p) { + *p = std::string("xxx"); +} + + +namespace test5 +{ +struct Rectangle {}; + +struct Foo +{ + void CallConst(const Rectangle*); + void CallNonConst(Rectangle*); + // expected-error@+1 {{this parameter can be const test5::Foo::ImplInvalidateParentFrameRegion [loplugin:constparams]}} + void ImplInvalidateParentFrameRegion( Rectangle& rRegion ) + { + CallConst( &rRegion ); + } + // no warning expected + void ImplInvalidateParentFrameRegion2( Rectangle& rRegion ) + { + CallNonConst( &rRegion ); + } +}; + +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/consttobool.cxx b/compilerplugins/clang/test/consttobool.cxx new file mode 100644 index 000000000..4fe41a814 --- /dev/null +++ b/compilerplugins/clang/test/consttobool.cxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include + +#pragma clang diagnostic ignored "-Wnull-conversion" + +enum E +{ + E0, + E1, + E2 +}; + +int const c1 = 1; +constexpr int c2 = 2; + +struct S +{ + S() + // expected-error-re@+1 {{implicit conversion of constant {{nullptr|0}} of type '{{(std::)?}}nullptr_t' to 'bool'; use 'false' instead [loplugin:consttobool]}} + : b(nullptr) + { + } + bool b; +}; + +int main() +{ + bool b; + // expected-error@+1 {{implicit conversion of constant 0 of type 'int' to 'bool'; use 'false' instead [loplugin:consttobool]}} + b = 0; + // expected-error@+1 {{implicit conversion of constant 1 of type 'sal_Bool' (aka 'unsigned char') to 'bool'; use 'true' instead [loplugin:consttobool]}} + b = sal_True; + // expected-error@+1 {{implicit conversion of constant 1.000000e+00 of type 'double' to 'bool'; use 'true' instead [loplugin:consttobool]}} + b = 1.0; + // expected-error@+1 {{implicit conversion of constant 2 of type 'E' to 'bool'; use 'true' instead [loplugin:consttobool]}} + b = E2; + // expected-error@+1 {{implicit conversion of constant 97 of type 'char' to 'bool'; use 'true' instead [loplugin:consttobool]}} + b = 'a'; + // expected-error@+1 {{implicit conversion of constant 1 of type 'int' to 'bool'; use 'true' instead [loplugin:consttobool]}} + b = c1; + // expected-error@+1 {{implicit conversion of constant 2 of type 'int' to 'bool'; use 'true' instead [loplugin:consttobool]}} + b = c2; + // expected-error@+1 {{implicit conversion of constant 3 of type 'int' to 'bool'; use 'true' instead [loplugin:consttobool]}} + b = (c1 | c2); + +#if !defined NDEBUG + assert(b); // no warnings from within assert macro itself + assert(b && "msg"); // no warnings for `&& "msg"` + if (b) + { + assert(!"msg"); // no warnings for `!"msg"` + } + // expected-error@+1 {{implicit conversion of constant &"msg"[0] of type 'const char *' to 'bool'; use 'true' instead [loplugin:consttobool]}} + assert("msg"); +#endif +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/constvars.cxx b/compilerplugins/clang/test/constvars.cxx new file mode 100644 index 000000000..88df50f8e --- /dev/null +++ b/compilerplugins/clang/test/constvars.cxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if defined _WIN32 //TODO, see corresponding TODO in compilerplugins/clang/writeonlyvars.cxx +// expected-no-diagnostics +#else + +#include +#include +#include +#include +#include +#include + +namespace test1 +{ +int const aFormalArgs[] = { 1, 2 }; +// expected-error@+1 {{var can be const [loplugin:constvars]}} +static sal_uInt16 nMediaArgsCount = SAL_N_ELEMENTS(aFormalArgs); +sal_uInt16 foo() +{ + (void)aFormalArgs; + return nMediaArgsCount; +} +}; + +// no warning expected +namespace test2 +{ +static char const* ar[] = { "xxxx" }; +static const char* lcl_DATA_OTHERS = "localedata_others"; +void foo() +{ + (void)ar; + (void)lcl_DATA_OTHERS; +} +}; + +// no warning expected +namespace test3 +{ +static sal_uInt16 nMediaArgsCount = 1; // loplugin:constvars:ignore +sal_uInt16 foo() { return nMediaArgsCount; } +}; + +// no warning expected, we don't handle these destructuring assignments properly yet +namespace test4 +{ +void foo() +{ + std::map aMap; + for (auto & [ rName, rEntry ] : aMap) + { + rEntry.clear(); + } +} +}; + +// no warning expected +namespace test5 +{ +struct Struct1 +{ +}; +void release(Struct1*); +void foo(std::list aList) +{ + for (Struct1* pItem : aList) + { + release(pItem); + } +} +}; + +// no warning expected +namespace test6 +{ +void foo(std::vector> aVecVec) +{ + for (auto& rVec : aVecVec) + for (auto& rElement : rVec) + rElement = 1; +} +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/convertlong.cxx b/compilerplugins/clang/test/convertlong.cxx new file mode 100644 index 000000000..020cdbb68 --- /dev/null +++ b/compilerplugins/clang/test/convertlong.cxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +int main() +{ + sal_uIntPtr x = 1; + sal_uInt32 y = x; + y = x; + (void)y; +} + +void main2() +{ + int x = 1; + int y = 1; + long tmp = x + y; + // expected-error@-1 {{rather replace type of decl 'long' with 'int' [loplugin:convertlong]}} + (void)tmp; + tmp = x + y; + + sal_uLong tmp1 = x + y; + // expected-error-re@-1 {{rather replace type of decl 'sal_uLong' (aka 'unsigned {{.+}}') with 'int' [loplugin:convertlong]}} + (void)tmp1; + + int tmp2 = (sal_uLong)1; + tmp2 = (long)1; + (void)tmp2; + + sal_uIntPtr tmp3 = x + y; + // expected-error-re@-1 {{rather replace type of decl 'sal_uIntPtr' (aka 'unsigned {{.+}}') with 'int' [loplugin:convertlong]}} + (void)tmp3; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/cow_wrapper.cxx b/compilerplugins/clang/test/cow_wrapper.cxx new file mode 100644 index 000000000..5c95f87f0 --- /dev/null +++ b/compilerplugins/clang/test/cow_wrapper.cxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "config_clang.h" +#include "o3tl/cow_wrapper.hxx" +#include + +struct ImplBitmapPalette +{ + void foo() const; +}; + +struct BitmapPalette +{ + void foo1() + { + // expected-error@+1 {{calling const method on o3tl::cow_wrapper impl class via non-const pointer, rather use std::as_const to prevent triggering an unnecessary copy [loplugin:cow_wrapper]}} + mpImpl->foo(); + } + void foo2() const + { + // no error expected + mpImpl->foo(); + } + void foo3() + { + // expected-error@+1 {{calling const method on o3tl::cow_wrapper impl class via non-const pointer, rather use std::as_const to prevent triggering an unnecessary copy [loplugin:cow_wrapper]}} + (*mpImpl).foo(); + } + void foo4() + { + // expected-error@+1 {{calling const method on o3tl::cow_wrapper impl class via non-const pointer, rather use std::as_const to prevent triggering an unnecessary copy [loplugin:cow_wrapper]}} + std::as_const(*mpImpl).foo(); + } + o3tl::cow_wrapper mpImpl; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/cppunitassertequals.cxx b/compilerplugins/clang/test/cppunitassertequals.cxx new file mode 100644 index 000000000..48bea83f6 --- /dev/null +++ b/compilerplugins/clang/test/cppunitassertequals.cxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" + +#include +#include +#include +#include + +#include "cppunitassertequals.hxx" + +#define TEST1 CPPUNIT_ASSERT(b1 == b2) +#define TEST2(x) x + +void test( + bool b1, bool b2, OUString const & s1, OUString const & s2, T t, void * p, std::nullptr_t n) +{ + CppUnit::Asserter::failIf(b1,""); + CPPUNIT_ASSERT(b1 && b2); // expected-error {{rather split into two CPPUNIT_ASSERT [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT((b1 && b2)); // expected-error {{rather split into two CPPUNIT_ASSERT [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT(!(b1 || b2)); // expected-error {{rather split into two CPPUNIT_ASSERT [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT(!(b1 && b2)); + CPPUNIT_ASSERT(!!(b1 && b2)); // expected-error {{rather split into two CPPUNIT_ASSERT [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT_MESSAGE("", b1 && b2); // expected-error {{rather split into two CPPUNIT_ASSERT_MESSAGE [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT(b1 == b2); // expected-error {{rather call CPPUNIT_ASSERT_EQUAL when comparing 'bool' and 'bool' (or rewrite as an explicit operator == call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT(b1 != b2); + CPPUNIT_ASSERT((b1 == b2)); // expected-error {{rather call CPPUNIT_ASSERT_EQUAL when comparing 'bool' and 'bool' (or rewrite as an explicit operator == call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT(!(b1 != b2)); // expected-error {{rather call CPPUNIT_ASSERT_EQUAL when comparing 'bool' and 'bool' (or rewrite as an explicit operator != call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT(!(b1 == b2)); + CPPUNIT_ASSERT(!!(b1 == b2)); // expected-error {{rather call CPPUNIT_ASSERT_EQUAL when comparing 'bool' and 'bool' (or rewrite as an explicit operator == call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT_MESSAGE("", b1 == b2); // expected-error {{rather call CPPUNIT_ASSERT_EQUAL_MESSAGE when comparing 'bool' and 'bool' (or rewrite as an explicit operator == call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT(s1 == s2); // expected-error {{rather call CPPUNIT_ASSERT_EQUAL when comparing 'const rtl::OUString' and 'const rtl::OUString' (or rewrite as an explicit operator == call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT(s1 != s2); + CPPUNIT_ASSERT((s1 == s2)); // expected-error {{rather call CPPUNIT_ASSERT_EQUAL when comparing 'const rtl::OUString' and 'const rtl::OUString' (or rewrite as an explicit operator == call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT(!(s1 != s2)); // expected-error {{rather call CPPUNIT_ASSERT_EQUAL when comparing 'const rtl::OUString' and 'const rtl::OUString' (or rewrite as an explicit operator != call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT(!(s1 == s2)); + CPPUNIT_ASSERT(!!(s1 == s2)); // expected-error {{rather call CPPUNIT_ASSERT_EQUAL when comparing 'const rtl::OUString' and 'const rtl::OUString' (or rewrite as an explicit operator == call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + TEST1; // expected-error {{rather call CPPUNIT_ASSERT_EQUAL when comparing 'bool' and 'bool' (or rewrite as an explicit operator == call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + TEST2(CPPUNIT_ASSERT(b1 == b2)); // expected-error {{rather call CPPUNIT_ASSERT_EQUAL when comparing 'bool' and 'bool' (or rewrite as an explicit operator == call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + TEST2(TEST1); // expected-error {{rather call CPPUNIT_ASSERT_EQUAL when comparing 'bool' and 'bool' (or rewrite as an explicit operator == call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + + // Useful when testing an equality iterator itself: + CPPUNIT_ASSERT(operator ==(s1, s1)); + CPPUNIT_ASSERT(t.operator ==(t)); + + // `P == nullptr` for P of pointer type is awkward to write with CPPUNIT_ASSERT_EQUAL, and the + // actual pointer values that would be printed if CPPUNIT_ASSERT_EQUAL failed would likely not be + // very meaningful, so let it use CPPUNIT_ASSERT (but stick to CPPUNIT_ASSERT_EQUAL for + // consistency in the unlikely case that P is of type std::nullptr_t): + CPPUNIT_ASSERT(p == nullptr); + CPPUNIT_ASSERT(n == nullptr); // expected-error-re {{rather call CPPUNIT_ASSERT_EQUAL when comparing 'std::nullptr_t'{{( \(aka 'nullptr_t'\))?}} and '{{(std::)?}}nullptr_t' (or rewrite as an explicit operator == call when the operator itself is the topic) [loplugin:cppunitassertequals]}} + + // There might even be good reasons(?) not to warn inside explicit casts: + CPPUNIT_ASSERT(bool(b1 && b2)); + CPPUNIT_ASSERT(bool(b1 == b2)); + CPPUNIT_ASSERT(bool(s1 == s2)); + + CPPUNIT_ASSERT_EQUAL(b1, true); // expected-error {{CPPUNIT_ASSERT_EQUALS parameters look switched, expected value should be first param [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT_EQUAL_MESSAGE("foo", b1, true); // expected-error {{CPPUNIT_ASSERT_EQUALS parameters look switched, expected value should be first param [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT_EQUAL(true, b1); + CPPUNIT_ASSERT_EQUAL_MESSAGE("foo", true, b1); + CPPUNIT_ASSERT_EQUAL(s1, OUString("xxx")); // expected-error {{CPPUNIT_ASSERT_EQUALS parameters look switched, expected value should be first param [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT_EQUAL_MESSAGE("foo", s1, OUString("xxx")); // expected-error {{CPPUNIT_ASSERT_EQUALS parameters look switched, expected value should be first param [loplugin:cppunitassertequals]}} + CPPUNIT_ASSERT_EQUAL(OUString("xxx"), s1); + CPPUNIT_ASSERT_EQUAL_MESSAGE("foo", OUString("xxx"), s1); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/cppunitassertequals.hxx b/compilerplugins/clang/test/cppunitassertequals.hxx new file mode 100644 index 000000000..2448d64e9 --- /dev/null +++ b/compilerplugins/clang/test/cppunitassertequals.hxx @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "sal/config.h" + +#include + +#include "rtl/ustring.hxx" + +struct T { bool operator ==(T); }; + +void test( + bool b1, bool b2, OUString const & s1, OUString const & s2, T t, void * p, std::nullptr_t n); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/cstylecast.cxx b/compilerplugins/clang/test/cstylecast.cxx new file mode 100644 index 000000000..8d212700a --- /dev/null +++ b/compilerplugins/clang/test/cstylecast.cxx @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +namespace N +{ +enum E +{ + E1 +}; + +using T = unsigned int; +} + +void FunctionalCast(void* p) +{ + // expected-error-re@+1 {{Function-style cast from 'void *' to 'sal_IntPtr' (aka '{{.+}}') (performs: reinterpret_cast) (PointerToIntegral) [loplugin:cstylecast]}} + auto n = sal_IntPtr(p); + (void(n)); // no warning expected (outer parens to disambiguate expr vs. decl) +} + +static const int C + = (int)0; // expected-error {{C-style cast from 'int' to 'int' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + +int main() +{ + constexpr int c1 = 0; + int const c2 = 0; + int n + = (int)0; // expected-error {{C-style cast from 'int' to 'int' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + n = (signed int)0; // expected-error {{C-style cast from 'int' to 'int' (performs: static_cast) (NoOp) [loplugin:cstylecast]}} + n = (int)~0; // expected-error {{C-style cast from 'int' to 'int' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + n = (int)-0; // expected-error {{C-style cast from 'int' to 'int' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + n = (int)+0; // expected-error {{C-style cast from 'int' to 'int' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + n = (int)!0; // expected-error {{C-style cast from 'bool' to 'int' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + n = (int) // expected-error {{C-style cast from 'int' to 'int' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + (0 << 0); + n = (int) // expected-error {{C-style cast from 'const int' to 'int' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + c1; + n = (int) // expected-error {{C-style cast from 'const int' to 'int' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + c2; + n = (int) // expected-error {{C-style cast from 'const int' to 'int' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + C; + n = (int) // expected-error {{C-style cast from 'N::E' to 'int' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + N::E1; + n = (N::E) // expected-error {{C-style cast from 'N::E' to 'N::E' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + N::E1; + n = (enum // expected-error {{C-style cast from 'N::E' to 'enum N::E' (performs: static_cast) (NoOp) [loplugin:cstylecast]}} + N::E)N::E1; + n = (N::T)0; // expected-error {{C-style cast from 'int' to 'N::T' (aka 'unsigned int') (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + n = (int) // expected-error-re {{C-style cast from {{.*}} to 'int' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + sizeof(int); + n = (int) // expected-error {{C-style cast from 'int' to 'int' (performs: static_cast) (NoOp) [loplugin:cstylecast]}} + n; + n = (int)~n; // expected-error {{C-style cast from 'int' to 'int' (performs: static_cast) (NoOp) [loplugin:cstylecast]}} + n = (int)-n; // expected-error {{C-style cast from 'int' to 'int' (performs: static_cast) (NoOp) [loplugin:cstylecast]}} + n = (int)+n; // expected-error {{C-style cast from 'int' to 'int' (performs: static_cast) (NoOp) [loplugin:cstylecast]}} + n = (int)!n; // expected-error {{C-style cast from 'bool' to 'int' (performs: static_cast) (NoOp) [loplugin:cstylecast]}} + n = (int) // expected-error {{C-style cast from 'int' to 'int' (performs: static_cast) (NoOp) [loplugin:cstylecast]}} + (0 << n); + n = (double)0; // expected-error {{C-style cast from 'int' to 'double' (performs: functional cast) (NoOp) [loplugin:cstylecast]}} + (void)n; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/datamembershadow.cxx b/compilerplugins/clang/test/datamembershadow.cxx new file mode 100644 index 000000000..ef8722d5c --- /dev/null +++ b/compilerplugins/clang/test/datamembershadow.cxx @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +struct Bar +{ + int x; // expected-note {{superclass member here [loplugin:datamembershadow]}} +}; + +struct Foo : public Bar +{ + int x; // expected-error {{data member x is shadowing member in superclass, through inheritance path Foo->Bar [loplugin:datamembershadow]}} +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/dbgunhandledexception.cxx b/compilerplugins/clang/test/dbgunhandledexception.cxx new file mode 100644 index 000000000..4ae15a58e --- /dev/null +++ b/compilerplugins/clang/test/dbgunhandledexception.cxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +void func1(); + +int main() +{ + try + { + func1(); + } + catch (std::exception const&) + { + SAL_WARN("xmloff", "message"); + DBG_UNHANDLED_EXCEPTION( + "xmloff", + "message"); // expected-error@-2 {{DBG_UNHANDLED_EXCEPTION must be first statement in catch block [loplugin:dbgunhandledexception]}} + } + try + { + func1(); + } + catch (std::exception const&) + { + DBG_UNHANDLED_EXCEPTION("xmloff", "message"); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/dodgyswitch.cxx b/compilerplugins/clang/test/dodgyswitch.cxx new file mode 100644 index 000000000..826971d27 --- /dev/null +++ b/compilerplugins/clang/test/dodgyswitch.cxx @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +int foo(); + +int main() { + switch (foo()) + { + case 1: { break; } + case 2: { + [[fallthrough]]; + { + case 3: // expected-error {{case statement not directly under switch [loplugin:dodgyswitch]}} + break; + } + default: // expected-error {{default statement not directly under switch [loplugin:dodgyswitch]}} + break; + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/doubleconvert.cxx b/compilerplugins/clang/test/doubleconvert.cxx new file mode 100644 index 000000000..12763d966 --- /dev/null +++ b/compilerplugins/clang/test/doubleconvert.cxx @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" +#include "tools/color.hxx" + +int main() +{ + constexpr Color col1; + Color col2; + col2 = sal_Int32( + col1); // expected-error@-1 {{redundant double conversion [loplugin:doubleconvert]}} + (void)col2; + // expected-error@+1 {{redundant double conversion [loplugin:doubleconvert]}} + Color col3 = sal_Int32(Color()); + (void)col3; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/elidestringvar.cxx b/compilerplugins/clang/test/elidestringvar.cxx new file mode 100644 index 000000000..0b2164472 --- /dev/null +++ b/compilerplugins/clang/test/elidestringvar.cxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" + +#include "rtl/ustring.hxx" + +template OUString f(sal_Unicode c, int n) +{ + OUString s0(C); + OUString s1(c); + // expected-note@+1 {{literal 'rtl::OUString' variable defined here [loplugin:elidestringvar]}} + OUString s2('a'); + // expected-note@+1 {{literal 'rtl::OUString' variable defined here [loplugin:elidestringvar]}} + OUString s3(u'a'); + static constexpr OUStringLiteral s4lit(u"a"); + // expected-note@+1 {{literal 'rtl::OUString' variable defined here [loplugin:elidestringvar]}} + OUString s4 = s4lit; + switch (n) + { + case 0: + return s0; + case 1: + return s1; + case 2: + // expected-error@+1 {{replace single use of literal 'rtl::OUString' variable with a literal [loplugin:elidestringvar]}} + return s2; + case 3: + // expected-error@+1 {{replace single use of literal 'rtl::OUString' variable with a literal [loplugin:elidestringvar]}} + return s3; + default: + // expected-error@+1 {{replace single use of literal 'rtl::OUString' variable with a literal [loplugin:elidestringvar]}} + return s4; + } +} + +// Trigger clang-cl to actually parse f under MSVC template instantiation model: +template OUString f<'a'>(sal_Unicode, int); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/emptyif.cxx b/compilerplugins/clang/test/emptyif.cxx new file mode 100644 index 000000000..15dd79627 --- /dev/null +++ b/compilerplugins/clang/test/emptyif.cxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +int main() +{ + int x = 1; + + if (x == 1) // expected-error {{empty if body [loplugin:emptyif]}} + ; + + if (x == 1) + { + } + // expected-error@-3 {{empty if body [loplugin:emptyif]}} + + if (x == 1) + { + } + else + { + } + // expected-error@-2 {{empty else body [loplugin:emptyif]}} + + if (x == 1) + { + } + else + ; // expected-error {{empty else body [loplugin:emptyif]}} + + if (x == 1) + { + } + else + { + x = 2; + } + + // no warning expected + if (x == 1) + { + x = 3; + } + if (x == 1) + x = 3; + if (x == 1) + { + // + } + if (x == 1) + { + /* */ + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/expressionalwayszero.cxx b/compilerplugins/clang/test/expressionalwayszero.cxx new file mode 100644 index 000000000..23d3e2652 --- /dev/null +++ b/compilerplugins/clang/test/expressionalwayszero.cxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +constexpr auto ONE = 1; +constexpr auto TWO = 2; + +enum class Enum1 { + ONE = 1, + TWO = 2, +}; +namespace o3tl { + template<> struct typed_flags : is_typed_flags {}; +} + +enum class Enum2 { + ZERO = 0, + ONE = 1, + TWO = 2, +}; +namespace o3tl { + template<> struct typed_flags : is_typed_flags {}; +} + +int main() +{ + auto v1 = ONE & TWO; // expected-error {{expression always evaluates to zero, lhs=1 rhs=2 [loplugin:expressionalwayszero]}} + (void)v1; + auto v2 = Enum1::ONE & Enum1::TWO; // expected-error {{expression always evaluates to zero, lhs=1 rhs=2 [loplugin:expressionalwayszero]}} + (void)v2; + + auto v3 = Enum2::ONE; + auto v4 = v3 & Enum2::ZERO; // expected-error {{expression always evaluates to zero, lhs=unknown rhs=0 [loplugin:expressionalwayszero]}} + (void)v4; + + auto v5 = Enum2::ONE; + v5 &= Enum2::ZERO; // expected-error {{expression always evaluates to zero, lhs=unknown rhs=0 [loplugin:expressionalwayszero]}} + (void)v5; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/external.cxx b/compilerplugins/clang/test/external.cxx new file mode 100644 index 000000000..77bb53c6b --- /dev/null +++ b/compilerplugins/clang/test/external.cxx @@ -0,0 +1,195 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include "external.hxx" + +int n0; // no warning, see external.hxx + +// expected-error@+1 {{externally available entity 'n1' is not previously declared in an included file (if it is only used in this translation unit, make it static or put it in an unnamed namespace; otherwise, provide a declaration of it in an included file) [loplugin:external]}} +int n1 = 0; +// expected-note@+1 {{another declaration is here [loplugin:external]}} +extern int n1; + +int const n2 = 0; // no warning, internal linkage + +constexpr int n3 = 0; // no warning, internal linkage + +static int n4; // no warning, internal linkage + +// expected-note@+1 {{another declaration is here [loplugin:external]}} +extern int n5; +// expected-error@+1 {{externally available entity 'n5' is not previously declared in an included file (if it is only used in this translation unit, make it static or put it in an unnamed namespace; otherwise, provide a declaration of it in an included file) [loplugin:external]}} +int n5; + +// expected-note@+1 {{another declaration is here [loplugin:external]}} +extern "C" int n6; +// expected-error@+1 {{externally available entity 'n6' is not previously declared in an included file (if it is only used in this translation unit, make it static or put it in an unnamed namespace; otherwise, provide a declaration of it in an included file) [loplugin:external]}} +int n6; + +extern "C" { +// expected-error@+1 {{externally available entity 'n7' is not previously declared in an included file (if it is only used in this translation unit, make it static or put it in an unnamed namespace; otherwise, provide a declaration of it in an included file) [loplugin:external]}} +int n7; +} + +namespace +{ +int u1; // no warning, internal linkage + +static int u2; // no warning, internal linkage + +extern "C" int u3; +int u3; // no warning, see the comment about DR1113 in compilerplugins/clang/external.cxx + +extern "C" { +int u4; // no warning, internal linkage +} +} + +namespace N +{ +int v1; // no warning, see external.hxx + +// expected-error@+1 {{externally available entity 'v2' is not previously declared in an included file (if it is only used in this translation unit, make it static or put it in an unnamed namespace; otherwise, provide a declaration of it in an included file) [loplugin:external]}} +int v2; + +static int v3; // no warning, internal linkage +} + +struct S +{ + static int f() + { + static int s = 0; + return s; + } + + static int m; +}; + +int S::m = 0; // no warning + +int f(int a) // no warning about parameters +{ + static int s = 0; // no warning about local static variables + ++s; + int b = a + s; // no warning about local variables + return b; +} + +// expected-error@+1 {{externally available entity 'S1' is not previously declared in an included file (if it is only used in this translation unit, put it in an unnamed namespace; otherwise, provide a declaration of it in an included file) [loplugin:external]}} +struct S1 +{ + friend void f1() {} // no warning for injected function (no place where to mark it `static`) + template friend void ft1() {} // ...nor for injected function template + // expected-error@+1 {{externally available entity 'f2' is not previously declared in an included file (if it is only used in this translation unit, make it static; otherwise, provide a declaration of it in an included file) [loplugin:external]}} + friend void f2() {} +}; + +// expected-error@+1 {{externally available entity 'S2' is not previously declared in an included file (if it is only used in this translation unit, put it in an unnamed namespace; otherwise, provide a declaration of it in an included file) [loplugin:external]}} +struct S2 +{ + friend void f1(); + template friend void ft1(); + // expected-note@+1 {{another declaration is here [loplugin:external]}} + friend void f2(); +}; + +static void g() +{ + void f1(); + // expected-note@+1 {{another declaration is here [loplugin:external]}} + void f2(); +} + +// expected-note@+1 {{another declaration is here [loplugin:external]}} +void f2(); + +namespace N +{ +inline namespace I1 +{ +extern "C++" { +// expected-note@+1 {{another declaration is here [loplugin:external]}} +enum E : int; + +// expected-error@+1 {{externally available entity 'E' is not previously declared in an included file (if it is only used in this translation unit, put it in an unnamed namespace; otherwise, provide a declaration of it in an included file) [loplugin:external]}} +enum E : int +{ +}; +} +} + +// expected-note-re@+1 {{a function associating 'N{{(::I1)?}}::E' is declared here [loplugin:external]}} +static void g(std::vector) +{ + // expected-note@+1 {{another declaration is here [loplugin:external]}} + void f(E const*); +} + +// expected-note-re@+1 {{a function associating 'N{{(::I1)?}}::E' is declared here [loplugin:external]}} +void f(E const*); + +extern "C++" { +// expected-note-re@+1 {{a function associating 'N{{(::I1)?}}::E' is declared here [loplugin:external]}} +void fc(E const*); +} + +// expected-error@+1 {{externally available entity 'S1' is not previously declared in an included file (if it is only used in this translation unit, put it in an unnamed namespace; otherwise, provide a declaration of it in an included file) [loplugin:external]}} +struct S1 +{ + struct S2; + // No note about associating function; injected friend function not found by ADL: + friend void f2(E const*); + // expected-note@+1 {{a function associating 'N::S1' is declared here [loplugin:external]}} + friend void h(S1); +}; + +// expected-error@+1 {{externally available entity 'S3' is not previously declared in an included file (if it is only used in this translation unit, put it in an unnamed namespace; otherwise, provide a declaration of it in an included file) [loplugin:external]}} +struct S3 +{ + // expected-note@+1 {{another declaration is here [loplugin:external]}} + friend void h(S1); +}; + +inline namespace I2 +{ +// expected-note-re@+1 {{a function associating 'N{{(::I1)?}}::E' is declared here [loplugin:external]}} +void f3(E); + +inline namespace I3 +{ +// expected-note-re@+1 {{a function associating 'N{{(::I1)?}}::E' is declared here [loplugin:external]}} +void f4(E); +} +} +} + +struct N::S1::S2 +{ + // expected-note@+1 {{another declaration is here [loplugin:external]}} + friend void f(E const*); +}; + +int main() +{ + (void)n2; + (void)n3; + (void)n4; + (void)u1; + (void)u2; + (void)N::v3; + g(); + (void)&N::g; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/external.hxx b/compilerplugins/clang/test/external.hxx new file mode 100644 index 000000000..40e8d55c0 --- /dev/null +++ b/compilerplugins/clang/test/external.hxx @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +extern int n0; + +namespace N +{ +extern int v1; +} + +struct S; + +int f(int a); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/faileddyncast.cxx b/compilerplugins/clang/test/faileddyncast.cxx new file mode 100644 index 000000000..7d835e041 --- /dev/null +++ b/compilerplugins/clang/test/faileddyncast.cxx @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +struct S1 { virtual ~S1(); }; +struct S2 final: S1 {}; +struct S3: S1 {}; + +void f(S1 * s1, S2 * s2) { + (void) dynamic_cast(s1); + (void) dynamic_cast(s2); + (void) dynamic_cast(s2); + (void) dynamic_cast(s2); // expected-error {{dynamic_cast from 'S2 *' to 'S3 *' always fails [loplugin:faileddyncast]}} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/fakebool.cxx b/compilerplugins/clang/test/fakebool.cxx new file mode 100644 index 000000000..144bf4a28 --- /dev/null +++ b/compilerplugins/clang/test/fakebool.cxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +namespace { + +struct S { + sal_Bool b; // expected-error {{FieldDecl, use "bool" instead of 'sal_Bool' (aka 'unsigned char') [loplugin:fakebool]}} +}; + +struct S2 { + sal_Bool & b_; + // The following should arguably not warn, but currently does (and does find cases that actually + // can be cleaned up; if it ever produces false warnings for cases that cannot, we need to fix + // it): + S2(sal_Bool & b): // expected-error {{ParmVarDecl, use "bool" instead of 'sal_Bool' (aka 'unsigned char') [loplugin:fakebool]}} + b_(b) {} +}; + +} + +struct S3 { + sal_Bool b_; + void f() { S2 s(b_); } +}; + +namespace { + +struct S4 { + sal_Bool b; +}; + +} + +void f() { + sal_Bool b; + (void) &b; + (void) &S4::b; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/flatten.cxx b/compilerplugins/clang/test/flatten.cxx new file mode 100644 index 000000000..300067b9b --- /dev/null +++ b/compilerplugins/clang/test/flatten.cxx @@ -0,0 +1,191 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +extern int foo(); +extern int bar(int = 0); +class Class {}; + +void top1() { + if (foo() == 1) { // expected-note {{if condition here [loplugin:flatten]}} + foo(); + } else { + throw std::exception(); // expected-error {{unconditional throw in else branch, rather invert the condition, throw early, and flatten the normal case [loplugin:flatten]}} + } + if (foo() == 1) { + Class aClass; + (void)aClass; + } else { + throw std::exception(); // no warning expected + } + if (foo() == 1) { // expected-note {{if condition here [loplugin:flatten]}} + Class aClass; + (void)aClass; + } else { + throw std::exception(); // expected-error {{unconditional throw in else branch, rather invert the condition, throw early, and flatten the normal case [loplugin:flatten]}} + } +} + +void top2() { + if (foo() == 2) { + throw std::exception(); // expected-error {{unconditional throw in then branch, just flatten the else [loplugin:flatten]}} + } else { + foo(); + } + if (foo() == 2) { + throw std::exception(); // no warning expected + } else { + Class aClass; + (void)aClass; + } + if (foo() == 2) { + throw std::exception(); // expected-error {{unconditional throw in then branch, just flatten the else [loplugin:flatten]}} + } else { + Class aClass; + (void)aClass; + } +} + +void top3() { + // no warning expected + if (foo() == 2) { + throw std::exception(); + } else { + Class aClass; + (void)aClass; + } + int x = 1; + (void)x; +} + +void top4() { + // no warning expected + if (foo() == 2) { + Class aClass; + (void)aClass; + } else { + throw std::exception(); + } + int x = 1; + (void)x; +} + +void top5() { +#if 1 + if (foo() == 2) { + if (foo() == 3) { // expected-note {{if condition here [loplugin:flatten]}} + bar(); + } else { + throw std::exception(); // expected-error {{unconditional throw in else branch, rather invert the condition, throw early, and flatten the normal case [loplugin:flatten]}} + } + } else +#endif + throw std::exception(); // no warning expected +} + +int main() { + // no warning expected + if (bar() == 3) { + throw std::exception(); + } else { + throw std::exception(); + } +} + +void top6() { + // no warning expected + if (foo() == 2) { + Class aClass; + (void)aClass; + } else if (foo() == 2) { + Class aClass; + (void)aClass; + } else { + throw std::exception(); + } + int x = 1; + (void)x; +} + +void top7() { + // no warning expected + if (foo() == 1) { + throw std::exception(); + } else if (foo() == 2) { + throw std::exception(); + } else { + throw std::exception(); + } +} + +void top8() { + if (foo() == 1) { + if (foo() == 2) { + throw std::exception(); // expected-error {{unconditional throw in then branch, just flatten the else [loplugin:flatten]}} + } else { + bar(); + } + } else if (foo() == 2) { + bar(1); + } else { + bar(2); + } +} + +void top9() { + if (foo() == 1) { // expected-error {{large if statement at end of function, rather invert the condition and exit early, and flatten the function [loplugin:flatten]}} + Class aClass1; + (void)aClass1; + Class aClass2; + (void)aClass2; + Class aClass3; + (void)aClass3; + Class aClass4; + (void)aClass4; + Class aClass5; + (void)aClass5; + Class aClass6; + (void)aClass6; + } +} + +void top10() { + // no warning expected + if (foo() == 2) { + if (foo() == 1) { + Class aClass1; + (void)aClass1; + Class aClass2; + (void)aClass2; + Class aClass3; + (void)aClass3; + } + } +} + +int top11() { + // no warning expected + if (foo() == 1) { + Class aClass1; + (void)aClass1; + Class aClass2; + (void)aClass2; + Class aClass3; + (void)aClass3; + Class aClass4; + (void)aClass4; + Class aClass5; + (void)aClass5; + Class aClass6; + (void)aClass6; + } + return 1; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/fragiledestructor.cxx b/compilerplugins/clang/test/fragiledestructor.cxx new file mode 100644 index 000000000..e2fbfc596 --- /dev/null +++ b/compilerplugins/clang/test/fragiledestructor.cxx @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" + +// no warning expected +namespace test1 +{ +class Foo +{ + ~Foo() { f(); } + void f(); +}; +} + +namespace test2 +{ +class Foo +{ + ~Foo() { f(); } + // expected-error@-1 {{calling virtual method from destructor, either make the virtual method final, or make this class final [loplugin:fragiledestructor]}} + virtual void f(); + // expected-note@-1 {{callee method here [loplugin:fragiledestructor]}} +}; +} + +// no warning expected +namespace test3 +{ +class Foo final +{ + ~Foo() { f(); } + virtual void f(); +}; +} + +namespace test4 +{ +struct Bar +{ + virtual ~Bar(); + virtual void f(); + // expected-note@-1 {{callee method here [loplugin:fragiledestructor]}} +}; +class Foo : public Bar +{ + ~Foo() { f(); } + // expected-error@-1 {{calling virtual method from destructor, either make the virtual method final, or make this class final [loplugin:fragiledestructor]}} +}; +} + +// no warning expected +namespace test5 +{ +struct Bar +{ + virtual ~Bar(); + virtual void f(); +}; +class Foo : public Bar +{ + ~Foo() { f(); } + virtual void f() final override; +}; +} + +// no warning expected +namespace test6 +{ +struct Bar +{ + virtual ~Bar(); + virtual void f(); +}; +class Foo : public Bar +{ + ~Foo() { Foo::f(); } + virtual void f() override; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/getstr.cxx b/compilerplugins/clang/test/getstr.cxx new file mode 100644 index 000000000..976d39c25 --- /dev/null +++ b/compilerplugins/clang/test/getstr.cxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include +#include +#include +#include + +// Determine whether std::ostream operator << for sal_Unicode* (aka char16_t*) is deleted (see +// "char8_t backward +// compatibility remediation", as implemented now by +// +// "libstdc++: P1423R3 char8_t remediation (2/4)" for -std=c++2a; TODO: the checks here and the +// relevant code in loplugin:getstr should eventually be removed once support for the deleted +// operators is widespread): +#if __cplusplus > 201703L && (defined __GLIBCXX__ || defined _MSC_VER) +#define HAVE_DELETED_OPERATORS true +#else +#define HAVE_DELETED_OPERATORS false +#endif + +using S = OString; + +void f(std::ostream& st, OString const& s1, OStringBuffer const& s2, + OUString const& s3[[maybe_unused]], OUStringBuffer const& s4[[maybe_unused]], S const& s5, + OString* p1, OStringBuffer* p2, OUString* p3[[maybe_unused]], + OUStringBuffer* p4[[maybe_unused]], S* p5, char const* (OString::*pf)() const) +{ + st << s1.getStr() // expected-error {{directly use object of type 'rtl::OString' in a call of 'operator <<', instead of calling 'getStr' first [loplugin:getstr]}} + << s2.getStr() +#if !HAVE_DELETED_OPERATORS + << s3.getStr() // expected-error {{suspicious use of 'getStr' on an object of type 'rtl::OUString'; the result is implicitly cast to a void pointer in a call of 'operator <<' [loplugin:getstr]}} + << s4.getStr() // expected-error {{suspicious use of 'getStr' on an object of type 'rtl::OUStringBuffer'; the result is implicitly cast to a void pointer in a call of 'operator <<' [loplugin:getstr]}} +#endif + << s5.getStr() // expected-error {{directly use object of type 'S' (aka 'rtl::OString') in a call of 'operator <<', instead of calling 'getStr' first [loplugin:getstr]}} + << p1->getStr() // expected-error {{directly use object of type 'rtl::OString' in a call of 'operator <<', instead of calling 'getStr' first [loplugin:getstr]}} + << p2->getStr() +#if !HAVE_DELETED_OPERATORS + << p3->getStr() // expected-error {{suspicious use of 'getStr' on an object of type 'rtl::OUString'; the result is implicitly cast to a void pointer in a call of 'operator <<' [loplugin:getstr]}} + << p4->getStr() // expected-error {{suspicious use of 'getStr' on an object of type 'rtl::OUStringBuffer'; the result is implicitly cast to a void pointer in a call of 'operator <<' [loplugin:getstr]}} +#endif + << p5->getStr() // expected-error {{directly use object of type 'rtl::OString' in a call of 'operator <<', instead of calling 'getStr' first [loplugin:getstr]}} + << (s1.*pf)(); + SAL_INFO( // expected-error 1+ {{directly use object of type 'rtl::OString' in a call of 'operator <<', instead of calling 'getStr' first [loplugin:getstr]}} + "test", s1.getStr()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/implicitboolconversion.cxx b/compilerplugins/clang/test/implicitboolconversion.cxx new file mode 100644 index 000000000..122ee363a --- /dev/null +++ b/compilerplugins/clang/test/implicitboolconversion.cxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include + +#include +#include + +template struct Sequence +{ + Sequence(std::initializer_list); +}; + +template struct Wrap1 +{ + T element; +}; + +template struct Wrap2 +{ + Wrap2(T const& e) + : element(e) + { + } + T element; +}; + +bool g(); + +void h(bool); + +void f() +{ + // expected-error@+1 {{implicit conversion (IntegralCast) from 'bool' to 'int' [loplugin:implicitboolconversion]}} + int i = false; + // expected-error@+1 {{implicit conversion (IntegralCast) from 'bool' to 'int' [loplugin:implicitboolconversion]}} + i = true; + (void)i; + std::atomic b = false; + (void)b; + //TODO: Emit only one diagnostic here: + // expected-error@+2 {{implicit conversion (ConstructorConversion) from 'bool' to 'std::atomic' [loplugin:implicitboolconversion]}} + // expected-error-re@+1 {{implicit conversion (IntegralCast) from 'bool' to {{.+}} [loplugin:implicitboolconversion]}} + std::atomic a = false; + (void)a; + bool b2 = true; + b2 &= g(); + (void)b2; + Sequence s1{ false }; + (void)s1; + Sequence> s2{ { false } }; + (void)s2; + // expected-error@+1 {{implicit conversion (IntegralCast) from 'bool' to 'const int' [loplugin:implicitboolconversion]}} + Sequence s3{ false }; + (void)s3; + // expected-error@+1 {{implicit conversion (IntegralCast) from 'bool' to 'const int' [loplugin:implicitboolconversion]}} + Sequence> s4{ { false } }; + (void)s4; + Wrap1 w1{ false }; + Sequence> s5{ { false } }; + (void)s5; + Wrap2 w2{ false }; + (void)w2; + Sequence> s6{ { false } }; + (void)s6; + h(w1.element); + css::uno::Sequence s7(1); + h(s7[0]); + std::array s8; + s8[0] = false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/indentation.cxx b/compilerplugins/clang/test/indentation.cxx new file mode 100644 index 000000000..1c57c6cee --- /dev/null +++ b/compilerplugins/clang/test/indentation.cxx @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +int foo(); +int foo2(int); + +#define SOME_MACRO(x) foo2(x) + +void top1(int x) { + { + foo(); // expected-note {{measured against this one [loplugin:indentation]}} + foo(); // expected-error {{statement mis-aligned compared to neighbours [loplugin:indentation]}} + } + { + foo(); // expected-note {{measured against this one [loplugin:indentation]}} + SOME_MACRO(1); // expected-error {{statement mis-aligned compared to neighbours SOME_MACRO [loplugin:indentation]}} + } + // no warning expected + { + foo(); foo(); + } + // no warning expected + /*xxx*/ foo(); + + +// disable this for now, ends up touching some very large switch statements in sw/ and sc/ + switch (x) + { + case 1: foo(); break; // 1expected-note {{measured against this one [loplugin:indentation]}} + case 2: foo(); break; // 1expected-error {{statement mis-aligned compared to neighbours [loplugin:indentation]}} + }; + + + if (x) + foo(); // expected-error {{if body should be indented [loplugin:indentation]}} + + if (x) + { + foo(); + } + + if (x) + { // expected-note {{start brace here [loplugin:indentation]}} + foo(); + } // expected-error {{start and end brace not aligned [loplugin:indentation]}} + + if (x) // expected-note {{statement beginning here [loplugin:indentation]}} + { // expected-error {{start brace not aligned with beginning of parent statement [loplugin:indentation]}} + foo(); + } + + if (x) + ; + else + foo(); // expected-error {{else body should be indented [loplugin:indentation]}} + + if (x) + ; + else + { + foo(); + } + + if (x) + ; + else // expected-error {{if and else not aligned [loplugin:indentation]}} + foo(); + + if (x) + { + } else + { + foo(); + } + +#if 0 + if (x) + foo(); + else +#endif + foo(); +} + +void attr() { + [[maybe_unused]] int i = foo(); + foo(); +} + +void attr_bad() { + [[maybe_unused]] int i = foo(); // expected-note {{measured against this one [loplugin:indentation]}} + foo(); // expected-error {{statement mis-aligned compared to neighbours [loplugin:indentation]}} +} + +void xxx(); +void test5(bool x) +{ + if (x) + { + xxx(); // expected-error {{body inside brace not indented [loplugin:indentation]}} + } +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/intvsfloat.cxx b/compilerplugins/clang/test/intvsfloat.cxx new file mode 100644 index 000000000..4746873e7 --- /dev/null +++ b/compilerplugins/clang/test/intvsfloat.cxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +static const float PI = 3.4; +struct Class1 +{ + float getFloat() const { return 1.5; } + int getInt() const { return 1; } + static constexpr float PI = 3.4; + static constexpr float E() { return 3.4; } +}; + +void func1(Class1 const& class1) +{ + // expected-error@+1 {{comparing integer to float constant, can never be true [loplugin:intvsfloat]}} + if (1 == PI) + return; + // expected-error@+1 {{comparing integer to float constant, can never be true [loplugin:intvsfloat]}} + if (1 == class1.PI) + return; + // expected-error@+1 {{comparing integer to float constant, can never be true [loplugin:intvsfloat]}} + if (true == class1.PI) + return; + if (1 == class1.getInt()) // no warning expected + return; + // expected-error@+1 {{comparing integer to float constant, can never be true [loplugin:intvsfloat]}} + if (1 == class1.E()) + return; + // expected-error@+1 {{comparing integer to float constant, can never be true [loplugin:intvsfloat]}} + if (true == class1.E()) + return; + if (1 == class1.getFloat()) // no warning expected + return; +} + +void func2(Class1 const& class1) +{ + // expected-error@+1 {{assigning constant float value to int truncates data [loplugin:intvsfloat]}} + int i0 = PI; + (void)i0; + // expected-error@+1 {{assigning constant float value to int truncates data [loplugin:intvsfloat]}} + int i1 = class1.PI; + (void)i1; + // expected-error@+1 {{assigning constant float value to int truncates data [loplugin:intvsfloat]}} + int i2 = class1.E(); + (void)i2; + int i3 = class1.getFloat(); // no warning expected + (void)i3; + int i4 = class1.getInt(); // no warning expected + (void)i4; + // expected-error@+1 {{assigning constant float value to int truncates data [loplugin:intvsfloat]}} + bool b1 = class1.E(); + (void)b1; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/logexceptionnicely.cxx b/compilerplugins/clang/test/logexceptionnicely.cxx new file mode 100644 index 000000000..458eef8c4 --- /dev/null +++ b/compilerplugins/clang/test/logexceptionnicely.cxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +void func1(); + +int main() +{ + // no warning expected + try + { + func1(); + } + catch (css::uno::Exception const&) + { + css::uno::Any ex(cppu::getCaughtException()); + SAL_WARN("avmedia", "exception: " << exceptionToString(ex)); + } + + try + { + func1(); + } + catch (css::uno::Exception const& ex) + { + SAL_WARN("xmloff", "message " << ex); + // expected-error@-1 {{use TOOLS_WARN_EXCEPTION/TOOLS_INFO_EXCEPTION/exceptionToString to print exception nicely [loplugin:logexceptionnicely]}} + } + + try + { + func1(); + } + catch (const css::lang::IndexOutOfBoundsException& ex) + { + SAL_WARN("xmloff", "message " << ex); + // expected-error@-1 {{use TOOLS_WARN_EXCEPTION/TOOLS_INFO_EXCEPTION/exceptionToString to print exception nicely [loplugin:logexceptionnicely]}} + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/loopvartoosmall.cxx b/compilerplugins/clang/test/loopvartoosmall.cxx new file mode 100644 index 000000000..bebf88c79 --- /dev/null +++ b/compilerplugins/clang/test/loopvartoosmall.cxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * +*/ + +#include + +std::int32_t size() { return 1; } + +int main() { + for (std::int16_t i = 0; i < size(); ++i) {} // expected-error {{[loplugin:loopvartoosmall]}} + for (std::int16_t i = 0; i <= size(); ++i) {} // expected-error {{[loplugin:loopvartoosmall]}} + for (std::int16_t i = 0; i != size(); ++i) {} // expected-error {{[loplugin:loopvartoosmall]}} + std::int16_t j; + for (j = 0; j < size(); ++j) {} // expected-error {{[loplugin:loopvartoosmall]}} + for (j = 0; j <= size(); ++j) {} // expected-error {{[loplugin:loopvartoosmall]}} + for (j = 0; j != size(); ++j) {} // expected-error {{[loplugin:loopvartoosmall]}} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/makeshared.cxx b/compilerplugins/clang/test/makeshared.cxx new file mode 100644 index 000000000..d6c3cbdac --- /dev/null +++ b/compilerplugins/clang/test/makeshared.cxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include + +struct S1 +{ + friend void test1(); + +private: + S1() {} +}; + +void test1() +{ + // expected-error@+1 {{rather use make_shared than constructing from 'int *' [loplugin:makeshared]}} + std::shared_ptr x(new int); + // expected-error@+1 {{rather use make_shared [loplugin:makeshared]}} + x.reset(new int); + // expected-error@+1 {{rather use make_shared than constructing from 'int *' [loplugin:makeshared]}} + x = std::shared_ptr(new int); + + // no warning expected + std::shared_ptr y(new int, o3tl::default_delete()); + y.reset(new int, o3tl::default_delete()); + // no warning expected, no public constructor + std::shared_ptr z(new S1); + z.reset(new S1); + + // no warning expected - this constructor takes an initializer-list, which make_shared does not support + auto a = std::shared_ptr>(new o3tl::sorted_vector({ 1, 2 })); +}; + +void test2() +{ + // expected-error-re@+1 {{rather use make_shared than constructing from {{.*}}'unique_ptr'{{.*}} [loplugin:makeshared]}} + std::shared_ptr x = std::make_unique(1); + // expected-error-re@+1 {{rather use make_shared than constructing from {{.*}}'unique_ptr'{{.*}} [loplugin:makeshared]}} + x = std::make_unique(1); + (void)x; + + // expected-error-re@+1 {{rather use make_shared than constructing from {{.*}}'unique_ptr'{{.*}} [loplugin:makeshared]}} + std::shared_ptr y(std::make_unique(1)); + (void)y; + + std::unique_ptr u1; + // expected-error-re@+1 {{rather use make_shared than constructing from {{.+}} (aka 'std{{.*}}::unique_ptr') [loplugin:makeshared]}} + std::shared_ptr z = std::move(u1); + // expected-error-re@+1 {{rather use make_shared than constructing from {{.+}} (aka 'std{{.*}}::unique_ptr') [loplugin:makeshared]}} + z = std::move(u1); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/mapindex.cxx b/compilerplugins/clang/test/mapindex.cxx new file mode 100644 index 000000000..de7dd2590 --- /dev/null +++ b/compilerplugins/clang/test/mapindex.cxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +struct CallbackFlushHandler +{ +}; + +struct LibLODocument_Impl +{ + std::map> mpCallbackFlushHandlers; +}; + +void foo(LibLODocument_Impl* pDoc) +{ + std::map aMap; + if (aMap[0]) // expected-error {{will create an empty entry in the map, you sure about that, rather use count()2 [loplugin:mapindex]}} + ; + + // expected-error@+1 {{will create an empty entry in the map, you sure about that, rather use count()1 [loplugin:mapindex]}} + if (pDoc->mpCallbackFlushHandlers[0]) + ; +} + +void no_warning_expected(const std::string& payload) +{ + for (size_t numberPos = 0; numberPos < payload.length(); ++numberPos) + { + if (payload[numberPos] == ',') + break; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/moveit.cxx b/compilerplugins/clang/test/moveit.cxx new file mode 100644 index 000000000..06424a6d9 --- /dev/null +++ b/compilerplugins/clang/test/moveit.cxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "config_clang.h" +#include + +// expected-note@+3 {{type declared here [loplugin:moveit]}} +// expected-note@+2 {{type declared here [loplugin:moveit]}} +// expected-note@+1 {{type declared here [loplugin:moveit]}} +struct Movable +{ + std::shared_ptr x; +}; + +namespace test1 +{ +struct F +{ + // expected-note@+1 {{passing to this param [loplugin:moveit]}} + void call_by_value(Movable); + // expected-note@+1 {{passing to this param [loplugin:moveit]}} + F(Movable); + void foo() + { + // expected-note@+2 {{local var declared here [loplugin:moveit]}} + // expected-note@+1 {{local var declared here [loplugin:moveit]}} + Movable m; + // expected-error@+1 {{can std::move this var into this param [loplugin:moveit]}} + call_by_value(m); + // expected-error@+1 {{can std::move this var into this param [loplugin:moveit]}} + F a(m); + (void)a; + } +}; +} + +namespace test2 +{ +struct F +{ + // expected-note@+1 {{passing to this param [loplugin:moveit]}} + F(Movable); + void foo() + { + // expected-note@+1 {{local var declared here [loplugin:moveit]}} + Movable m; + // expected-error@+1 {{can std::move this var into this param [loplugin:moveit]}} + F a(m); + (void)a; + } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/moveparam.cxx b/compilerplugins/clang/test/moveparam.cxx new file mode 100644 index 000000000..4e3df5b9c --- /dev/null +++ b/compilerplugins/clang/test/moveparam.cxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "config_clang.h" +#include "o3tl/cow_wrapper.hxx" +#include + +namespace drawinglayer::primitive2d +{ +class Primitive2DContainer +{ +}; +} + +struct Foo +{ + drawinglayer::primitive2d::Primitive2DContainer maMine; + + // expected-error@+2 {{rather use move && param3 [loplugin:moveparam]}} + Foo(drawinglayer::primitive2d::Primitive2DContainer const& rContainer) + : maMine(rContainer) + { + } + + // no warning expected + Foo(drawinglayer::primitive2d::Primitive2DContainer&& rContainer) + : maMine(rContainer) + { + } + + void foo1(const drawinglayer::primitive2d::Primitive2DContainer& rContainer) + { + // expected-error@+1 {{rather use move && param1 [loplugin:moveparam]}} + maMine = rContainer; + } +}; + +namespace test2 +{ +typedef std::map Map2Map; + +struct Foo +{ + Map2Map maMine; + + // expected-error@+2 {{rather use move && param3 [loplugin:moveparam]}} + Foo(Map2Map const& rContainer) + : maMine(rContainer) + { + } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/namespaceindentation.cxx b/compilerplugins/clang/test/namespaceindentation.cxx new file mode 100644 index 000000000..f97f781fc --- /dev/null +++ b/compilerplugins/clang/test/namespaceindentation.cxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "config_clang.h" + +// no warning expected +namespace xxx::yyy +{ +} +namespace xxx::yyy { +} +// expected-error@+1 {{statement left brace mis-aligned [loplugin:namespaceindentation]}} +namespace xxx::yyy + { +// expected-error@+1 {{statement right brace mis-aligned [loplugin:namespaceindentation]}} + } +namespace xxx::yyy +{ + // expected-error@+1 {{statement right brace mis-aligned [loplugin:namespaceindentation]}} + } +// expected-error@+1 {{statement left brace mis-aligned [loplugin:namespaceindentation]}} +namespace xxx::yyy + { +} +namespace xxx::yyy { +// expected-error@+1 {{statement right brace mis-aligned [loplugin:namespaceindentation]}} + } +namespace xxx::yyy +{ +} // fooo baaaar +// expected-error@-1 {{incorrect comment at end of namespace xxx::yyy [loplugin:namespaceindentation]}} +namespace aaa::bbb +{ +} // namespace foo +// expected-error@-1 {{incorrect comment at end of namespace aaa::bbb [loplugin:namespaceindentation]}} +namespace xxx::yyy +{ +} // xxx::yyy +// no warning expected +namespace com { namespace sun { namespace star { } } } +// no warning expected +namespace com::sun::star::uno { class XComponentContext; } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/noexcept.cxx b/compilerplugins/clang/test/noexcept.cxx new file mode 100644 index 000000000..f46a3d87f --- /dev/null +++ b/compilerplugins/clang/test/noexcept.cxx @@ -0,0 +1,16 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// expected-error@+1 {{Replace legacy dynamic 'throw ()' exception specification with 'noexcept' [loplugin:noexcept]}} +void f() throw(); + +// expected-error@+1 {{Replace legacy dynamic 'throw ()' exception specification with 'noexcept' [loplugin:noexcept]}} +using F = void() throw(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/noexceptmove.cxx b/compilerplugins/clang/test/noexceptmove.cxx new file mode 100644 index 000000000..c0742c828 --- /dev/null +++ b/compilerplugins/clang/test/noexceptmove.cxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +namespace test1 +{ +class Mapping +{ + char* m_pMapping; + + // expected-error@+1 {{move constructor can be noexcept [loplugin:noexceptmove]}} + Mapping(Mapping&& other) + : m_pMapping(other.m_pMapping) + { + other.m_pMapping = nullptr; + } + + // expected-error@+1 {{move operator= can be noexcept [loplugin:noexceptmove]}} + Mapping& operator=(Mapping&& other) + { + m_pMapping = other.m_pMapping; + other.m_pMapping = nullptr; + return *this; + } +}; +}; + +// No warning expected, because calling throwing function. +namespace test2 +{ +void foo() noexcept(false); + +class Bar +{ + Bar(Bar&&) { foo(); } +}; +}; + +// no warning expected, because calling throwing constructor +namespace test3 +{ +struct Foo +{ + Foo() noexcept(false); +}; +class Bar +{ + Bar(Bar&&) { Foo aFoo; } +}; + +class Bar2 +{ + Foo m_foo; + + Bar2(Bar2&&) {} +}; +}; + +// No warning expected, because calling throwing destructor. +namespace test4 +{ +struct Foo +{ + ~Foo() noexcept(false); +}; + +class Bar +{ + Bar(Bar&&) { Foo aFoo; } +}; +}; + +// Check for calls to defaulted constructors. +namespace test5 +{ +struct Foo +{ + Foo() = default; // non-throwing +}; +class Bar +{ + Bar(Bar&&) // expected-error {{move constructor can be noexcept [loplugin:noexceptmove]}} + { + Foo aFoo; + (void)aFoo; + } +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/nullptr.cxx b/compilerplugins/clang/test/nullptr.cxx new file mode 100644 index 000000000..bf7376cb6 --- /dev/null +++ b/compilerplugins/clang/test/nullptr.cxx @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +struct S +{ + void* p; +}; + +int main() +{ + S s{ + 0 // expected-error {{NullToPointer ValueDependentIsNotNull ZeroLiteral -> nullptr [loplugin:nullptr]}} + }; + (void)s; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/oncevar.cxx b/compilerplugins/clang/test/oncevar.cxx new file mode 100644 index 000000000..c8cc7bc13 --- /dev/null +++ b/compilerplugins/clang/test/oncevar.cxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +/*int foo() { return 1; }*/ + +void call_value(int); +void call_const_ref(int const &); +void call_ref(int &); +void call_value(OUString); +void call_const_ref(OUString const &); +void call_ref(OUString &); + +template void f() { + int i = sizeof (T) + 1; // expected-error {{var used only once, should be inlined or declared const [loplugin:oncevar]}} + call_value(i); // expected-note {{used here [loplugin:oncevar]}} +} +template void f(); // needed for clang-cl + +class Foo; +void method1(const Foo**); + +int main() { +/* TODO + int i; + int x = 2; + if ( (i = foo()) == 0 ) { + x = 1; + } +*/ + + + int i1 = 2; // expected-error {{var used only once, should be inlined or declared const [loplugin:oncevar]}} + call_value(i1); // expected-note {{used here [loplugin:oncevar]}} + int i2 = 2; // expected-error {{var used only once, should be inlined or declared const [loplugin:oncevar]}} + call_const_ref(i2); // expected-note {{used here [loplugin:oncevar]}} + + // don't expect warnings here + int i3; + call_ref(i3); + int const i4 = 2; + call_value(i4); + + OUString s1("xxx"); // expected-error {{var used only once, should be inlined or declared const [loplugin:oncevar]}} + call_value(s1); // expected-note {{used here [loplugin:oncevar]}} + OUString s2("xxx"); // expected-error {{var used only once, should be inlined or declared const [loplugin:oncevar]}} + call_const_ref(s2); // expected-note {{used here [loplugin:oncevar]}} + + // don't expect warnings here + OUString s3; + call_ref(s3); + OUString const s4("xxx"); + call_value(s4); + + const Foo* pInternalArgs[] = { nullptr }; + method1(pInternalArgs); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/optmove.cxx b/compilerplugins/clang/test/optmove.cxx new file mode 100644 index 000000000..976806772 --- /dev/null +++ b/compilerplugins/clang/test/optmove.cxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#include "config_clang.h" +#include + +namespace test1 +{ +void foo1(std::vector x) +{ + std::vector y; + // expected-error@+1 {{can std::move value instead of copy [loplugin:optmove]}} + y = x; +} +} + +namespace test2 +{ +void foo(std::vector x) +{ + // expected-error@+1 {{can std::move value instead of copy [loplugin:optmove]}} + std::vector y = x; +} +} + +namespace test3 +{ +void foo1(std::vector x) +{ + std::vector y, z; + y = x; + // expected-error@+1 {{can std::move value instead of copy [loplugin:optmove]}} + z = x; +} +} + +namespace test4 +{ +void foo1(std::vector x) +{ + std::vector y; + // no warning expected, don't even try to follow loop + for (int i = 0; i < 10; i++) + y = x; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/oslendian-1.cxx b/compilerplugins/clang/test/oslendian-1.cxx new file mode 100644 index 000000000..7d0023037 --- /dev/null +++ b/compilerplugins/clang/test/oslendian-1.cxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#if defined OSL_BIGENDIAN || defined OSL_LITENDIAN +#endif +#ifdef OSL_BIGENDIAN +#endif +#ifdef OSL_LITENDIAN +#endif +#ifndef OSL_BIGENDIAN +#endif +#ifndef OSL_LITENDIAN +#endif + +#if !defined OSL_BIGENDIAN +#define OSL_BIGENDIAN +// expected-error@-1 {{macro 'OSL_BIGENDIAN' defined in addition to 'OSL_LITENDIAN' [loplugin:oslendian]}} +// expected-note@osl/endian.h:* {{conflicting macro definition is here [loplugin:oslendian]}} +#endif + +#if !defined OSL_LITENDIAN +#define OSL_LITENDIAN +// expected-error@-1 {{macro 'OSL_LITENDIAN' defined in addition to 'OSL_BIGENDIAN' [loplugin:oslendian]}} +// expected-note@osl/endian.h:* {{conflicting macro definition is here [loplugin:oslendian]}} +#endif + +#if defined OSL_BIGENDIAN +#undef OSL_BIGENDIAN +// expected-error@-1 {{macro 'OSL_BIGENDIAN' undefinition [loplugin:oslendian]}} +#endif + +#if defined OSL_LITENDIAN +#undef OSL_LITENDIAN +// expected-error@-1 {{macro 'OSL_LITENDIAN' undefinition [loplugin:oslendian]}} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/oslendian-2.cxx b/compilerplugins/clang/test/oslendian-2.cxx new file mode 100644 index 000000000..76e1a6b38 --- /dev/null +++ b/compilerplugins/clang/test/oslendian-2.cxx @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#if defined OSL_BIGENDIAN || defined OSL_LITENDIAN // expected-error {{definition of macro 'OSL_BIGENDIAN' checked but 'osl/endian.h' is not included [loplugin:oslendian]}} // expected-error {{definition of macro 'OSL_LITENDIAN' checked but 'osl/endian.h' is not included [loplugin:oslendian]}} +#endif +#ifdef OSL_BIGENDIAN // expected-error {{definition of macro 'OSL_BIGENDIAN' checked but 'osl/endian.h' is not included [loplugin:oslendian]}} +#endif +#ifdef OSL_LITENDIAN // expected-error {{definition of macro 'OSL_LITENDIAN' checked but 'osl/endian.h' is not included [loplugin:oslendian]}} +#endif +#ifndef OSL_BIGENDIAN // expected-error {{definition of macro 'OSL_BIGENDIAN' checked but 'osl/endian.h' is not included [loplugin:oslendian]}} +#endif +#ifndef OSL_LITENDIAN // expected-error {{definition of macro 'OSL_LITENDIAN' checked but 'osl/endian.h' is not included [loplugin:oslendian]}} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/oslendian-3.cxx b/compilerplugins/clang/test/oslendian-3.cxx new file mode 100644 index 000000000..90de9643c --- /dev/null +++ b/compilerplugins/clang/test/oslendian-3.cxx @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#if defined OSL_BIGENDIAN || defined OSL_LITENDIAN // expected-error {{definition of macro 'OSL_BIGENDIAN' checked but 'osl/endian.h' is not included [loplugin:oslendian]}} // expected-error {{definition of macro 'OSL_LITENDIAN' checked but 'osl/endian.h' is not included [loplugin:oslendian]}} +#endif +#ifdef OSL_BIGENDIAN // expected-error {{definition of macro 'OSL_BIGENDIAN' checked but 'osl/endian.h' is not included [loplugin:oslendian]}} +#endif +#ifdef OSL_LITENDIAN // expected-error {{definition of macro 'OSL_LITENDIAN' checked but 'osl/endian.h' is not included [loplugin:oslendian]}} +#endif +#ifndef OSL_BIGENDIAN // expected-error {{definition of macro 'OSL_BIGENDIAN' checked but 'osl/endian.h' is not included [loplugin:oslendian]}} +#endif +#ifndef OSL_LITENDIAN // expected-error {{definition of macro 'OSL_LITENDIAN' checked but 'osl/endian.h' is not included [loplugin:oslendian]}} +#endif + +#include + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/overridevirtual.cxx b/compilerplugins/clang/test/overridevirtual.cxx new file mode 100644 index 000000000..0f11d86b1 --- /dev/null +++ b/compilerplugins/clang/test/overridevirtual.cxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +struct S1 +{ + // expected-note@+1 {{overridden declaration is here [loplugin:overridevirtual]}} + virtual ~S1(); +}; + +struct S2 : S1 +{ + // expected-error@+1 {{overriding virtual function declaration not marked 'override' [loplugin:overridevirtual]}} + ~S2(); +}; + +template struct T1 +{ + virtual ~T1(); +}; + +template struct T2 : T1 +{ + ~T2(); +}; + +template struct U1 +{ + // expected-note@+1 {{overridden declaration is here [loplugin:overridevirtual]}} + virtual ~U1(); +}; + +template struct U2 : U1 +{ + // expected-error@+1 {{overriding virtual function declaration not marked 'override' [loplugin:overridevirtual]}} + ~U2(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/passparamsbyref.cxx b/compilerplugins/clang/test/passparamsbyref.cxx new file mode 100644 index 000000000..010556a67 --- /dev/null +++ b/compilerplugins/clang/test/passparamsbyref.cxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#pragma clang diagnostic ignored "-Wunknown-warning-option" // for Clang < 13 +#pragma clang diagnostic ignored "-Wunused-but-set-variable" + +struct S { + OUString mv1; + OUString mv2; + + // make sure we ignore cases where the passed in parameter is std::move'd + S(OUString v1, OUString v2) + : mv1(std::move(v1)), mv2((std::move(v2))) {} +}; + + +void f() +{ + S* s; + OUString v1, v2; + s = new S(v1, v2); +} + + +// check that we don't warn when the param is modified +OUString trim_string(OUString aString) +{ + aString += "xxx"; + return aString; +} + +// expected-no-diagnostics + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/passstuffbyref.cxx b/compilerplugins/clang/test/passstuffbyref.cxx new file mode 100644 index 000000000..d90d6f05b --- /dev/null +++ b/compilerplugins/clang/test/passstuffbyref.cxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#pragma clang diagnostic ignored "-Wunknown-warning-option" // for Clang < 13 +#pragma clang diagnostic ignored "-Wunused-but-set-variable" + +struct S1 { + OUString mv1; + OUString const & get() const { return mv1; } + OUString const & get2(bool) const { return mv1; } +}; +struct S2 { + OUString mv1; + OUString mv2; + OUString mv3[2]; + S1 child; + static OUString gs1; + o3tl::cow_wrapper mxCow; + + // make sure we ignore cases where the passed in parameter is std::move'd + S2(OUString v1, OUString v2) + : mv1(std::move(v1)), mv2((std::move(v2))) {} + + OUString get1() { return mv1; } // expected-error {{rather return class rtl::OUString by const& than by value, to avoid unnecessary copying [loplugin:passstuffbyref]}} + OUString get2(bool b) { return b ? mv1 : mv2; } // expected-error {{rather return class rtl::OUString by const& than by value, to avoid unnecessary copying [loplugin:passstuffbyref]}} + OUString get3() { return child.mv1; } // expected-error {{rather return class rtl::OUString by const& than by value, to avoid unnecessary copying [loplugin:passstuffbyref]}} + OUString get4() { return mv3[0]; } // expected-error {{rather return class rtl::OUString by const& than by value, to avoid unnecessary copying [loplugin:passstuffbyref]}} + OUString get5() { return gs1; } // expected-error {{rather return class rtl::OUString by const& than by value, to avoid unnecessary copying [loplugin:passstuffbyref]}} + OUString const & get6() { return gs1; } + OUString get7() { return get6(); } // expected-error {{rather return class rtl::OUString by const& than by value, to avoid unnecessary copying [loplugin:passstuffbyref]}} + OUString & get8() { return gs1; } + OUString get9() { return get8(); } // expected-error {{rather return class rtl::OUString by const& than by value, to avoid unnecessary copying [loplugin:passstuffbyref]}} + // TODO + OUString get10() { return OUString(*&get6()); } // todoexpected-error {{rather return class rtl::OUString by const& than by value, to avoid unnecessary copying [loplugin:passstuffbyref]}} + OUString get11() const { return mxCow->get(); } // expected-error {{rather return class rtl::OUString by const& than by value, to avoid unnecessary copying [loplugin:passstuffbyref]}} + OUString get12() { return child.get2(false); } // expected-error {{rather return class rtl::OUString by const& than by value, to avoid unnecessary copying [loplugin:passstuffbyref]}} + + // no warning expected + OUString set1() { return OUString("xxx"); } + OUString set2() { OUString v1("xxx"); return v1; } + OUString set3() { S1 v1; return v1.get(); } + OUString set4() { OUString v1[1]; return v1[0]; } + OUString set5(OUString const & s) { return s; } + OUString set6() { std::vector v1(1); return v1[0]; } + OUString set7(S1 const & s) { return s.get(); } + OUString set8() { OUString * p = nullptr; return *p; } +}; + + +// no warning expected + +// Don't flag stuff where the local var is hidden behind a self-returning operation like -=: +S2 &operator -= ( S2 &t1, const S2 &t2 ); +S2 operator-( const S2 &t1, const S2 &t2 ) +{ + S2 t0 = t1; + return t0 -= t2; +} + +void f() +{ + S2* s; + OUString v1, v2; + s = new S2(v1, v2); +} + +struct S3 { S3(int); }; + +S3 f2() { + static int n; + return n; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/pointerbool.cxx b/compilerplugins/clang/test/pointerbool.cxx new file mode 100644 index 000000000..fcb4a9a31 --- /dev/null +++ b/compilerplugins/clang/test/pointerbool.cxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +#define FALSE 0 + +void func_ptr(int*); +void func_bool(bool); // expected-note {{method here [loplugin:pointerbool]}} +void func_salbool(sal_Bool); + +void test1(int* p1) +{ + func_ptr(p1); + func_bool( + p1); // expected-error {{possibly unwanted implicit conversion when calling bool param [loplugin:pointerbool]}} + // no warning expected + func_bool(FALSE); + func_salbool(sal_False); + func_salbool(sal_True); + css::uno::Sequence aSeq; + func_bool(aSeq[0]); +} + +void func_bool2(bool); // expected-note {{method here [loplugin:pointerbool]}} + +template void func_bool_via_forward_template(Args&&... args) +{ + // expected-error@+1 {{possibly unwanted implicit conversion when calling bool param [loplugin:pointerbool]}} + func_bool2(std::forward(args)...); +} + +void test2(int p1) +{ + // expected-note@+1 {{instantiated from here [loplugin:pointerbool]}} + func_bool_via_forward_template(p1); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/putpoolitem.cxx b/compilerplugins/clang/test/putpoolitem.cxx new file mode 100644 index 000000000..fb44612a0 --- /dev/null +++ b/compilerplugins/clang/test/putpoolitem.cxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +class SfxPoolItem +{ +public: + virtual ~SfxPoolItem(); +}; +class SfxPoolItemSubclass : public SfxPoolItem +{ +}; +class SfxItemSet +{ +public: + void Put(SfxPoolItem&); +}; + +void foo(SfxItemSet* pSet) +{ + std::unique_ptr foo; + SfxItemSet aSet; + // expected-error@+1 {{could use std::move? [loplugin:putpoolitem]}} + aSet.Put(*foo); + + // expected-error@+1 {{could use std::move? [loplugin:putpoolitem]}} + pSet->Put(*foo); +} + +class Foo2 +{ + std::unique_ptr m_foo; + void foo() + { + SfxItemSet aSet; + // no warning expected + aSet.Put(*m_foo); + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/reducevarscope.cxx b/compilerplugins/clang/test/reducevarscope.cxx new file mode 100644 index 000000000..ca4ed09be --- /dev/null +++ b/compilerplugins/clang/test/reducevarscope.cxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#pragma clang diagnostic ignored "-Wunknown-warning-option" // for Clang < 13 +#pragma clang diagnostic ignored "-Wunused-but-set-variable" + +void test1() +{ + int i = 2; // expected-error {{can reduce scope of var [loplugin:reducevarscope]}} + { + i = 3; // expected-note {{used here [loplugin:reducevarscope]}} + } + int j = 2; // expected-error {{can reduce scope of var [loplugin:reducevarscope]}} + { + j = 3; // expected-note {{used here [loplugin:reducevarscope]}} + { + j = 4; // expected-note {{used here [loplugin:reducevarscope]}} + } + } +} + +// negative test - seen inside a loop +void test2() +{ + int i = 2; + for (int j = 1; j < 10; ++j) + { + i = 3; + } +} + +// negative test - initial assignment from non-constant +void test3() +{ + int j = 1; + int i = j; + { + i = 3; + } +} + +// negative test +void test4() +{ + int i = 2; + { + i = 3; + } + i = 4; +} + +// negative test +void test5() +{ + int i = 2; + i = 3; +} + +// negative test - seen in 2 child blocks +void test6() +{ + int i; + { + i = 3; + } + { + i = 3; + } +} + +// TODO negative test - storing pointer to OUString data +// void test7() +// { +// OUString s; +// const sal_Unicode* p = nullptr; +// { +// p = s.getStr(); +// } +// auto p2 = p; +// (void)p2; +// } + +// negative test - passing var into lambda +void test8() +{ + int i; + auto l1 = [&]() { i = 1; }; + (void)l1; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/redundantcast.cxx b/compilerplugins/clang/test/redundantcast.cxx new file mode 100644 index 000000000..7a102cca5 --- /dev/null +++ b/compilerplugins/clang/test/redundantcast.cxx @@ -0,0 +1,458 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include + +#include "redundantcast.hxx" + +void f1(char *) {} +void f2(char const *) {} + +struct D: S {}; + +enum Enum1 { X }; + +void testConstCast() { + char * p1; + char const * p2; + p1 = nullptr; + p2 = ""; + f1(const_cast(p1)); // expected-error {{redundant const_cast from 'char *' lvalue to 'char *' prvalue [loplugin:redundantcast]}} + f1(const_cast(p1)); // expected-error {{redundant const_cast from 'char *' lvalue to 'char *const' prvalue [loplugin:redundantcast]}} + f1(const_cast(p2)); + f1(const_cast(p2)); + f2(const_cast(p1)); // expected-error {{redundant const_cast from 'char *' lvalue to 'char *' prvalue [loplugin:redundantcast]}} + f2(const_cast(p1)); // expected-error {{redundant const_cast from 'char *' lvalue to 'char *const' prvalue [loplugin:redundantcast]}} + f2(const_cast(p1)); + f2(const_cast(p1)); + f2(const_cast(p2)); // expected-error {{redundant const_cast from 'const char *' to 'char *', result is implicitly cast to 'const char *' [loplugin:redundantcast]}} + f2(const_cast(p2)); // expected-error {{redundant const_cast from 'const char *' to 'char *', result is implicitly cast to 'const char *' [loplugin:redundantcast]}} + f2(const_cast(p2)); // expected-error {{redundant const_cast from 'const char *' lvalue to 'const char *' prvalue [loplugin:redundantcast]}} + f2(const_cast(p2)); // expected-error {{redundant const_cast from 'const char *' lvalue to 'const char *const' prvalue [loplugin:redundantcast]}} + + void * vp = nullptr; + (void) const_cast(static_cast(vp)); // expected-error {{redundant static_cast/const_cast combination from 'void *' via 'const char *' to 'char *' [loplugin:redundantcast]}} + (void) const_cast(static_cast(nullptr)); // expected-error-re {{redundant static_cast/const_cast combination from '{{(std::)?}}nullptr_t' via 'const char *' to 'char *' [loplugin:redundantcast]}} + (void) const_cast(static_cast(D{})); // expected-error {{redundant static_cast/const_cast combination from 'D' via 'const S &' to 'S &' [loplugin:redundantcast]}} + + S const s{}; + const_cast(s).f1(); + const_cast(s).f2(); // expected-error {{redundant const_cast from 'const S' to 'S', result is implicitly cast to 'const S' [loplugin:redundantcast]}} + const_cast(s).f3(); + s.f3(); + + // non-class lvalue, non-const: + int ni{}; +// (void) const_cast(ni); + (void) const_cast(ni); // expected-error {{redundant const_cast from 'int' lvalue to 'int &' lvalue [loplugin:redundantcast]}} + (void) const_cast(ni); +// (void) const_cast(ni); + (void) const_cast(ni); + (void) const_cast(ni); + + // non-class lvalue, const: + int const ci{}; +// (void) const_cast(ci); + (void) const_cast(ci); + (void) const_cast(ci); +// (void) const_cast(ci); + (void) const_cast(ci); // expected-error {{redundant const_cast from 'const int' lvalue to 'const int &' lvalue [loplugin:redundantcast]}} + (void) const_cast(ci); + + // non-class xvalue, non-const: +// (void) const_cast(nix()); +// (void) const_cast(nix()); + (void) const_cast(nix()); // expected-error {{redundant const_cast from 'int' xvalue to 'int &&' xvalue [loplugin:redundantcast]}} +// (void) const_cast(nix()); +// (void) const_cast(nix()); + (void) const_cast(nix()); + + // non-class xvalue, const: +// (void) const_cast(cix()); +// (void) const_cast(cix()); + (void) const_cast(cix()); +// (void) const_cast(cix()); +// (void) const_cast(cix()); + (void) const_cast(cix()); // expected-error {{redundant const_cast from 'const int' xvalue to 'const int &&' xvalue [loplugin:redundantcast]}} + + // non-class prvalue, non-const: +// (void) const_cast(nir()); +// (void) const_cast(nir()); +// (void) const_cast(nir()); +// (void) const_cast(nir()); +// (void) const_cast(nir()); +// (void) const_cast(nir()); + + // non-class prvalue, const: +// (void) const_cast(cir()); +// (void) const_cast(cir()); +// (void) const_cast(cir()); +// (void) const_cast(cir()); +// (void) const_cast(cir()); +// (void) const_cast(cir()); + + // class lvalue, non-const: + S ns{}; +// (void) const_cast(ns); + (void) const_cast(ns); // expected-error {{redundant const_cast from 'S' lvalue to 'S &' lvalue [loplugin:redundantcast]}} + (void) const_cast(ns); +// (void) const_cast(ns); + (void) const_cast(ns); + (void) const_cast(ns); + + // class lvalue, const: + S const cs{}; +// (void) const_cast(cs); + (void) const_cast(cs); + (void) const_cast(cs); +// (void) const_cast(cs); + (void) const_cast(cs); // expected-error {{redundant const_cast from 'const S' lvalue to 'const S &' lvalue [loplugin:redundantcast]}} + (void) const_cast(cs); + + // class xvalue, non-const: +// (void) const_cast(nsx()); +// (void) const_cast(nsx()); + (void) const_cast(nsx()); // expected-error {{redundant const_cast from 'S' xvalue to 'S &&' xvalue [loplugin:redundantcast]}} +// (void) const_cast(nsx()); +// (void) const_cast(nsx()); + (void) const_cast(nsx()); + + // class xvalue, const: +// (void) const_cast(csx()); +// (void) const_cast(csx()); + (void) const_cast(csx()); +// (void) const_cast(csx()); +// (void) const_cast(csx()); + (void) const_cast(csx()); // expected-error {{redundant const_cast from 'const S' xvalue to 'const S &&' xvalue [loplugin:redundantcast]}} + + // class prvalue, non-const: +// (void) const_cast(nsr()); +// (void) const_cast(nsr()); + (void) const_cast(nsr()); +// (void) const_cast(nsr()); +// (void) const_cast(nsr()); + (void) const_cast(nsr()); + + // class prvalue, const: +// (void) const_cast(csr()); +// (void) const_cast(csr()); + (void) const_cast(csr()); +// (void) const_cast(csr()); +// (void) const_cast(csr()); + (void) const_cast(csr()); +} + +void testStaticCast() { + // non-class lvalue, non-const: + int ni{}; + (void) static_cast(ni); // expected-error {{static_cast from 'int' lvalue to 'int' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) int(ni); + (void) static_cast(ni); // expected-error {{static_cast from 'int' lvalue to 'int &' lvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(ni); + (void) static_cast(ni); // expected-error {{in static_cast from 'int' lvalue to 'const int' prvalue, remove redundant top-level const qualifier [loplugin:redundantcast]}} + /* => */ (void) static_cast(ni); // expected-error {{static_cast from 'int' lvalue to 'int' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) int(ni); + (void) static_cast(ni); // expected-error {{static_cast from 'int' lvalue to 'const int &' lvalue should be written as const_cast [loplugin:redundantcast]}} + /* => */ (void) const_cast(ni); + (void) static_cast(ni); // expected-error {{static_cast from 'int' lvalue to 'const int &&' xvalue should be written as const_cast [loplugin:redundantcast]}} + /* => */ (void) const_cast(ni); + + // non-class lvalue, const: + int const ci{}; + (void) static_cast(ci); // expected-error {{static_cast from 'const int' lvalue to 'int' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) int(ci); +// (void) static_cast(ci); +// (void) static_cast(ci); + (void) static_cast(ci); // expected-error {{in static_cast from 'const int' lvalue to 'const int' prvalue, remove redundant top-level const qualifier [loplugin:redundantcast]}} + /* => */ (void) static_cast(ci); // expected-error {{static_cast from 'const int' lvalue to 'int' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) int(ci); + (void) static_cast(ci); // expected-error {{static_cast from 'const int' lvalue to 'const int &' lvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(ci); + + // non-class xvalue, non-const: + (void) static_cast(nix()); // expected-error {{static_cast from 'int' xvalue to 'int' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) int(nix()); +// (void) static_cast(nix()); + (void) static_cast(nix()); // expected-error {{static_cast from 'int' xvalue to 'int &&' xvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(nix()); // expected-error {{in static_cast from 'int' xvalue to 'const int' prvalue, remove redundant top-level const qualifier [loplugin:redundantcast]}} + /* => */ (void) static_cast(nix()); // expected-error {{static_cast from 'int' xvalue to 'int' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + (void) static_cast(nix()); + (void) static_cast(nix()); // expected-error {{static_cast from 'int' xvalue to 'const int &&' xvalue should be written as const_cast [loplugin:redundantcast]}} + /* => */ (void) const_cast(nix()); + + // non-class xvalue, const: + (void) static_cast(cix()); // expected-error {{static_cast from 'const int' xvalue to 'int' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) int(cix()); +// (void) static_cast(cix()); +// (void) static_cast(cix()); + (void) static_cast(cix()); // expected-error {{in static_cast from 'const int' xvalue to 'const int' prvalue, remove redundant top-level const qualifier [loplugin:redundantcast]}} + /* => */ (void) static_cast(cix()); // expected-error {{static_cast from 'const int' xvalue to 'int' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) int(cix()); + (void) static_cast(cix()); + (void) static_cast(cix()); // expected-error {{static_cast from 'const int' xvalue to 'const int &&' xvalue is redundant [loplugin:redundantcast]}} + + // non-class prvalue, non-const: + (void) static_cast(nir()); // expected-error {{static_cast from 'int' prvalue to 'int' prvalue is redundant [loplugin:redundantcast]}} +// (void) static_cast(nir()); + (void) static_cast(nir()); + (void) static_cast(nir()); // expected-error {{in static_cast from 'int' prvalue to 'const int' prvalue, remove redundant top-level const qualifier [loplugin:redundantcast]}} + /* => */ (void) static_cast(nir()); // expected-error {{static_cast from 'int' prvalue to 'int' prvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(nir()); // expected-error {{static_cast from 'int' prvalue to 'const int &' lvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(nir()); + + // non-class prvalue, const: + (void) static_cast(cir()); // expected-error {{static_cast from 'int' prvalue to 'int' prvalue is redundant [loplugin:redundantcast]}} +// (void) static_cast(cir()); + (void) static_cast(cir()); + (void) static_cast(cir()); // expected-error {{in static_cast from 'int' prvalue to 'const int' prvalue, remove redundant top-level const qualifier [loplugin:redundantcast]}} + /* => */ (void) static_cast(cir()); // expected-error {{static_cast from 'int' prvalue to 'int' prvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(cir()); // expected-error {{static_cast from 'int' prvalue to 'const int &' lvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(cir()); + + // class lvalue, non-const: + S ns{}; + (void) static_cast(ns); // expected-error {{static_cast from 'S' lvalue to 'S' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) S(ns); + (void) static_cast(ns); // expected-error {{static_cast from 'S' lvalue to 'S &' lvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(ns); + (void) static_cast(ns); // expected-error {{static_cast from 'S' lvalue to 'const S' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ using CS = const S; (void) CS(ns); + (void) static_cast(ns); // expected-error {{static_cast from 'S' lvalue to 'const S &' lvalue should be written as const_cast [loplugin:redundantcast]}} + /* => */ (void) const_cast(ns); + (void) static_cast(ns); // expected-error {{static_cast from 'S' lvalue to 'const S &&' xvalue should be written as const_cast [loplugin:redundantcast]}} + /* => */ (void) const_cast(ns); + + // class lvalue, const: + S const cs{}; + (void) static_cast(cs); // expected-error {{static_cast from 'const S' lvalue to 'S' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) S(cs); +// (void) static_cast(cs); +// (void) static_cast(cs); + (void) static_cast(cs); // expected-error {{static_cast from 'const S' lvalue to 'const S' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) CS(cs); + (void) static_cast(cs); // expected-error {{static_cast from 'const S' lvalue to 'const S &' lvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(cs); + + // class xvalue, non-const: + (void) static_cast(nsx()); // expected-error {{static_cast from 'S' xvalue to 'S' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) S(nsx()); +// (void) static_cast(nsx()); + (void) static_cast(nsx()); // expected-error {{static_cast from 'S' xvalue to 'S &&' xvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(nsx()); // expected-error {{static_cast from 'S' xvalue to 'const S' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) CS(nsx()); + (void) static_cast(nsx()); + (void) static_cast(nsx()); // expected-error {{static_cast from 'S' xvalue to 'const S &&' xvalue should be written as const_cast [loplugin:redundantcast]}} + /* => */ (void) const_cast(nsx()); + + // class xvalue, const: + (void) static_cast(csx()); // expected-error {{static_cast from 'const S' xvalue to 'S' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) S(csx()); +// (void) static_cast(csx()); +// (void) static_cast(csx()); + (void) static_cast(csx()); // expected-error {{static_cast from 'const S' xvalue to 'const S' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) CS(csx()); + (void) static_cast(csx()); + (void) static_cast(csx()); // expected-error {{static_cast from 'const S' xvalue to 'const S &&' xvalue is redundant [loplugin:redundantcast]}} + + // class prvalue, non-const: + (void) static_cast(nsr()); // expected-error {{static_cast from 'S' prvalue to 'S' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) S(nsr()); +// (void) static_cast(nsr()); + (void) static_cast(nsr()); + (void) static_cast(nsr()); // expected-error {{static_cast from 'S' prvalue to 'const S' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) CS(nsr()); + (void) static_cast(nsr()); // expected-error {{static_cast from 'S' prvalue to 'const S &' lvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(nsr()); // expected-error {{static_cast from 'S' prvalue to 'const S &&' xvalue should be written as const_cast [loplugin:redundantcast]}} + /* => */ (void) const_cast(nsr()); + + // class prvalue, const: + (void) static_cast(csr()); // expected-error {{static_cast from 'const S' prvalue to 'S' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) S(csr()); +// (void) static_cast(csr()); +// (void) static_cast(csr()); + (void) static_cast(csr()); // expected-error {{static_cast from 'const S' prvalue to 'const S' prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + /* => */ (void) CS(csr()); + (void) static_cast(csr()); // expected-error {{static_cast from 'const S' prvalue to 'const S &' lvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(csr()); +} + +int & testReturnStaticCast(int && x) { return static_cast(x); } + +void testFunctionalCast() { + (void) int(nir()); // expected-error {{redundant functional cast from 'int' to 'int' [loplugin:redundantcast]}} + (void) S(nsr()); +} + +void testCStyleCast() { + Enum1 e = (Enum1)Enum1::X; // expected-error {{redundant cstyle cast from 'Enum1' to 'Enum1' [loplugin:redundantcast]}} + (void)e; +} + +template +struct EnumItemInterface { + T GetValue() { return static_cast(0); } +}; +class Enum1Item : public EnumItemInterface { +}; +bool testCStyleCastOfTemplateMethodResult(Enum1Item* item) { + return (Enum1)item->GetValue() == Enum1::X; // expected-error {{redundant cstyle cast from 'Enum1' to 'Enum1' [loplugin:redundantcast]}} +} + +using T1 = int; +T1 nt1r() { return 0; } +void testArithmeticTypedefs() { + (void) static_cast(nir()); + (void) T1(nir()); + (void) (T1) nir(); + (void) static_cast(nt1r()); + (void) int(nt1r()); + (void) (int) nt1r(); + using T2 = T1; + (void) static_cast(nt1r()); + (void) T2(nt1r()); + (void) (T2) nt1r(); + (void) static_cast(nt1r()); // expected-error {{redundant}} + (void) T1(nt1r()); // expected-error {{redundant}} + (void) (T1) nt1r(); // expected-error {{redundant}} + + T1 const c{}; + (void) static_cast(c); // expected-error {{redundant}} +} + +void testReinterpretCast() { + int * p; + (void) reinterpret_cast(p); // expected-error {{redundant reinterpret_cast from 'int *' to 'int *' [loplugin:redundantcast]}} +} + +void testReinterpretConstCast() { + int n = 0; + (void) reinterpret_cast((const_cast(&n))); // expected-error-re {{redundant const_cast from 'int *' to 'const int *' within reinterpret_cast to fundamental type 'std::size_t' (aka 'unsigned {{.+}}') [loplugin:redundantcast]}} +} + +void testDynamicCast() { + + struct S1 { virtual ~S1(); }; + struct S2 final: S1 {}; + struct S3: S1 {}; + + S1 * s1 = nullptr; + S2 * s2 = nullptr; + S3 * s3 = nullptr; + + (void) dynamic_cast(s1); + (void) dynamic_cast(s2); // expected-error {{redundant dynamic upcast from 'S2 *' to 'S1 *' [loplugin:redundantcast]}} + (void) dynamic_cast(s2); // expected-error {{redundant dynamic cast from 'S2 *' to 'S2 *' [loplugin:redundantcast]}} + (void) dynamic_cast(s2); + (void) dynamic_cast(s2); // expected-error {{redundant dynamic cast from 'S2 *' to 'const S2 *' [loplugin:redundantcast]}} + (void) dynamic_cast(s3); // expected-error {{redundant dynamic upcast from 'S3 *' to 'S1 *' [loplugin:redundantcast]}} +} + +void overload(int); +void overload(long); +void nonOverload(); + +struct Overload { + int overload(); + long overload() const; + void nonOverload(); +}; + +void testOverloadResolution() { + (void) static_cast(overload); + (void) static_cast((overload)); + (void) static_cast(&overload); + (void) static_cast((&overload)); + (void) static_cast(&((overload))); + (void) static_cast(nonOverload); // expected-error {{static_cast from 'void (*)()' prvalue to 'void (*)()' prvalue is redundant [loplugin:redundantcast]}} + (void) static_cast((nonOverload)); // expected-error {{static_cast from 'void (*)()' prvalue to 'void (*)()' prvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(&nonOverload); // expected-error {{static_cast from 'void (*)()' prvalue to 'void (*)()' prvalue is redundant [loplugin:redundantcast]}} + (void) static_cast((&nonOverload)); // expected-error {{static_cast from 'void (*)()' prvalue to 'void (*)()' prvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(&((nonOverload))); // expected-error {{static_cast from 'void (*)()' prvalue to 'void (*)()' prvalue is redundant [loplugin:redundantcast]}} + (void) static_cast(&Overload::overload); + (void) static_cast(&Overload::nonOverload); // expected-error {{static_cast from 'void (Overload::*)()' prvalue to 'void (Overload::*)()' prvalue is redundant [loplugin:redundantcast]}} + + using OverloadFn = void (*)(long); + (void) OverloadFn(overload); + using NonOverloadFn = void (*)(); + (void) NonOverloadFn(nonOverload); // expected-error {{redundant functional cast from 'void (*)()' to 'NonOverloadFn' (aka 'void (*)()') [loplugin:redundantcast]}} + using OverloadMemFn = long (Overload::*)() const; + (void) OverloadMemFn(&Overload::overload); + using NonOverloadMemFn = void (Overload::*)(); + (void) NonOverloadMemFn(&Overload::nonOverload); // expected-error {{redundant functional cast from 'void (Overload::*)()' to 'NonOverloadMemFn' (aka 'void (Overload::*)()') [loplugin:redundantcast]}} +}; + +void testIntermediaryStaticCast() { + int n = 0; + n = static_cast(n); // expected-error {{suspicious static_cast from 'int' to 'double', result is implicitly cast to 'int' [loplugin:redundantcast]}} + n = double(n); // expected-error {{suspicious functional cast from 'int' to 'double', result is implicitly cast to 'int' [loplugin:redundantcast]}} + double d = 0.0; + d = static_cast(d) + 1.0; // expected-error {{suspicious static_cast from 'double' to 'int', result is implicitly cast to 'double' [loplugin:redundantcast]}} + d = int(d) + 1.0; // expected-error {{suspicious functional cast from 'double' to 'int', result is implicitly cast to 'double' [loplugin:redundantcast]}} +}; + +void testArrayDecay() { + (void) static_cast(""); // expected-error-re {{redundant static_cast from 'const char{{ ?}}[1]' to 'const char *' [loplugin:redundantcast]}} + (void) reinterpret_cast(""); // expected-error-re {{redundant reinterpret_cast from 'const char{{ ?}}[1]' to 'const char *' [loplugin:redundantcast]}} + (void) reinterpret_cast(u8""); +} + +void testNew() { + class A {}; + class B : public A {}; + A* p = static_cast(new B); // expected-error {{redundant static_cast from 'B *' to 'A *' [loplugin:redundantcast]}} + (void)p; + // no warning expected for resolving-ambiguity cast + class C : public A {}; + class D : public B, public C {}; + p = static_cast(new D); + // no warning expected for down-cast + auto p2 = static_cast(p); + (void)p2; +} + +using F = void (*)(); +auto testNullFunctionPointer(int i, F p) { + switch (i) { + case 0: + return static_cast(nullptr); + case 1: + return F(nullptr); + default: + return p; + } +} + +void testSalIntTypes() { + sal_Int16 const n = 0; + (void) static_cast(n); // expected-error-re {{static_cast from 'const sal_Int16' (aka 'const {{.+}}') lvalue to 'sal_Int16' (aka '{{.+}}') prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + (void) static_cast<::sal_Int16>(n); // expected-error-re {{static_cast from 'const sal_Int16' (aka 'const {{.+}}') lvalue to '::sal_Int16' (aka '{{.+}}') prvalue is redundant or should be written as an explicit construction of a temporary [loplugin:redundantcast]}} + (void) static_cast(n); // doesn't warn, even if 'sal_Int16' is 'short' + using Other = sal_Int16; + (void) static_cast(n); // doesn't warn either +} + +int main() { + testConstCast(); + testStaticCast(); + testFunctionalCast(); + testCStyleCast(); + testCStyleCastOfTemplateMethodResult(nullptr); + testReinterpretCast(); + testReinterpretConstCast(); + testDynamicCast(); + testIntermediaryStaticCast(); + testArrayDecay(); + testSalIntTypes(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/redundantcast.hxx b/compilerplugins/clang/test/redundantcast.hxx new file mode 100644 index 000000000..0afab0c2d --- /dev/null +++ b/compilerplugins/clang/test/redundantcast.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +struct S +{ + void f1(); + void f2() const; + void f3(); + void f3() const; +}; + +int&& nix(); +int const&& cix(); +int nir(); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wignored-qualifiers" +int const cir(); +#pragma clang diagnostic pop + +S&& nsx(); +S const&& csx(); +S nsr(); +S const csr(); + +void testArithmeticTypedefs(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/redundantfcast.cxx b/compilerplugins/clang/test/redundantfcast.cxx new file mode 100644 index 000000000..20c939cb2 --- /dev/null +++ b/compilerplugins/clang/test/redundantfcast.cxx @@ -0,0 +1,224 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" + +#include "rtl/ustring.hxx" +#include "tools/color.hxx" + +#include +#include +#include + +void method1(OUString const&); // expected-note {{in call to method here [loplugin:redundantfcast]}} + +struct Foo +{ + Foo(int) {} +}; + +void func1(Foo const& f); // expected-note {{in call to method here [loplugin:redundantfcast]}} + +namespace tools +{ +struct Polygon +{ + Polygon() = default; +}; +struct PolyPolygon +{ + PolyPolygon( + Polygon const&); // expected-note {{in call to method here [loplugin:redundantfcast]}} +}; +} + +void ImplWritePolyPolygonRecord(const tools::PolyPolygon& rPolyPoly); + +int main() +{ + OUString s; + (void)OUString( + s); // expected-error@-1 {{redundant functional cast from 'rtl::OUString' to 'rtl::OUString' [loplugin:redundantfcast]}} + using T1 = OUString; + (void)T1( + s); // expected-error@-1 {{redundant functional cast from 'rtl::OUString' to 'T1' (aka 'rtl::OUString') [loplugin:redundantfcast]}} + using T2 = OUString const; + (void)T2( + s); // expected-error@-1 {{redundant functional cast from 'rtl::OUString' to 'T2' (aka 'const rtl::OUString') [loplugin:redundantfcast]}} + + (void)std::unique_ptr(std::unique_ptr( + new int{})); // expected-error@-1 {{redundant functional cast from 'std::unique_ptr' to 'std::unique_ptr' [loplugin:redundantfcast]}} + + OUString s1; + method1(OUString( + s1)); // expected-error@-1 {{redundant functional cast from 'rtl::OUString' to 'rtl::OUString' [loplugin:redundantfcast]}} + OUString s2; + s2 = OUString( + s1); // expected-error@-1 {{redundant functional cast from 'rtl::OUString' to 'rtl::OUString' [loplugin:redundantfcast]}} + (void)s2; + + Color col1; + Color col2 = Color( + col1); // expected-error@-1 {{redundant functional cast from 'Color' to 'Color' [loplugin:redundantfcast]}} + (void)col2; + + Foo foo(1); + func1(Foo( + foo)); // expected-error@-1 {{redundant functional cast from 'Foo' to 'Foo' [loplugin:redundantfcast]}} + + const tools::Polygon aPolygon; + ImplWritePolyPolygonRecord(tools::PolyPolygon(tools::Polygon( + aPolygon))); // expected-error@-1 {{redundant functional cast from 'const tools::Polygon' to 'tools::Polygon' in construct expression [loplugin:redundantfcast]}} +} + +class Class1 +{ + Foo foo; + Foo func2() + { + return Foo( + foo); // expected-error@-1 {{redundant functional cast from 'Foo' to 'Foo' [loplugin:redundantfcast]}} + } +}; + +// casting of lambdas +namespace test5 +{ +void f1(std::function x); +void f2() +{ + // expected-error-re@+1 {{redundant functional cast {{.+}} [loplugin:redundantfcast]}} + f1(std::function([&]() {})); +} +}; +namespace test6 +{ +void f1(std::function); +void f1(std::function); +void f2() +{ + f1(std::function([&](int) {})); // should not warn here +} +} + +namespace test7 +{ +// expected-note@+1 6 {{in call to method here [loplugin:redundantfcast]}} +void f1(std::initializer_list const&); +// expected-note@+1 6 {{in call to method here [loplugin:redundantfcast]}} +template void f2(std::initializer_list const&); +// expected-note@+1 4 {{in call to method here [loplugin:redundantfcast]}} +template void f3(T const&); +// expected-note@+1 4 {{in call to method here [loplugin:redundantfcast]}} +template void f4(T const&...); +void f5(int, ...); +void g(std::initializer_list il) +{ + f1(il); + f2(il); + f3(il); + f4(il); + f5(0, il); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f1(std::initializer_list(il)); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f2(std::initializer_list(il)); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f3(std::initializer_list(il)); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f4(std::initializer_list(il)); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f5(0, std::initializer_list(il)); + f1({}); + f1(std::initializer_list{}); // should warn, but not modelled as CXXFunctionalCastExpr + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f1(std::initializer_list({})); + // f2({}); //error + f2(std::initializer_list{}); // should warn, but not modelled as CXXFunctionalCastExpr + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f2(std::initializer_list({})); + // f3({}); //error + f3(std::initializer_list{}); // (not modelled as CXXFunctionalCastExpr anyway) + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f3(std::initializer_list({})); // arguably rather subtle, remove "("...")" + // f4({}); //error + f4(std::initializer_list{}); // (not modelled as CXXFunctionalCastExpr anyway) + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f4(std::initializer_list({})); // arguably rather subtle, remove "("...")" + // f5(0, {}); //error + f5(0, std::initializer_list{}); // (not modelled as CXXFunctionalCastExpr anyway) + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f5(0, std::initializer_list({})); // arguably rather subtle, remove "("...")" + f1({ 1 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f1(std::initializer_list{ 1 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f1(std::initializer_list({ 1 })); + f2({ 1 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f2(std::initializer_list{ 1 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f2(std::initializer_list({ 1 })); + // f3({1}); //error + f3(std::initializer_list{ 1 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f3(std::initializer_list({ 1 })); // arguably rather subtle, remove "("...")" + // f4({1}); //error + f4(std::initializer_list{ 1 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f4(std::initializer_list({ 1 })); // arguably rather subtle, remove "("...")" + // f5(0, {1}); //error + f5(0, std::initializer_list{ 1 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f5(0, std::initializer_list({ 1 })); // arguably rather subtle, remove "("...")" + f1({ 1, 2, 3 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f1(std::initializer_list{ 1, 2, 3 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f1(std::initializer_list({ 1, 2, 3 })); + f2({ 1, 2, 3 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f2(std::initializer_list{ 1, 2, 3 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f2(std::initializer_list({ 1, 2, 3 })); + // f3({1, 2, 3}); //error + f3(std::initializer_list{ 1, 2, 3 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f3(std::initializer_list({ 1, 2, 3 })); // arguably rather subtle, remove "("...")" + // f4({1, 2, 3}); //error + f4(std::initializer_list{ 1, 2, 3 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f4(std::initializer_list({ 1, 2, 3 })); // arguably rather subtle, remove "("...")" + // f5(0, {1, 2, 3}); //error + f5(0, std::initializer_list{ 1, 2, 3 }); + // expected-error@+1 {{redundant functional cast from 'std::initializer_list' to 'std::initializer_list' [loplugin:redundantfcast]}} + f5(0, std::initializer_list({ 1, 2, 3 })); // arguably rather subtle, remove "("...")" +} +} + +namespace test8 +{ +class Primitive2DContainer +{ +}; +struct GroupPrimitive +{ + GroupPrimitive(Primitive2DContainer&&); +}; + +const Primitive2DContainer& getChildren(); + +void foo() +{ + // no warning expected, we have to create a temporary for this constructor + GroupPrimitive aGroup((Primitive2DContainer(getChildren()))); + (void)aGroup; +} +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/redundantinline.cxx b/compilerplugins/clang/test/redundantinline.cxx new file mode 100644 index 000000000..f69e0a3b8 --- /dev/null +++ b/compilerplugins/clang/test/redundantinline.cxx @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "redundantinline.hxx" + +S1::~S1() = default; + +static inline int f8() { return 0; } // expected-error {{function has no external linkage but is explicitly declared 'inline' [loplugin:redundantinline]}} + +namespace { + +static inline int f9() { return 0; } // expected-error {{function has no external linkage but is explicitly declared 'inline' [loplugin:redundantinline]}} + +} + +int main() { return f8() + f9(); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/redundantinline.hxx b/compilerplugins/clang/test/redundantinline.hxx new file mode 100644 index 000000000..9b1460d58 --- /dev/null +++ b/compilerplugins/clang/test/redundantinline.hxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +struct S1 { + inline S1(); + inline ~S1(); +}; + +S1::S1() = default; + +struct S2 { + inline S2() = default; // expected-error {{[loplugin:redundantinline]}} + inline ~S2() = default; // expected-error {{[loplugin:redundantinline]}} +}; + +struct S3 { + inline S3(); + inline ~S3(); + + inline void f1(); + + static inline void f2(); + + inline void operator +(); + + inline operator int(); + + friend inline void f3(); +}; + +S3::S3() {} + +S3::~S3() { f1(); } + +void S3::f1() { (void)this; } + +void S3::f2() {} + +void S3::operator +() {} + +void f3() {} + +S3::operator int() { return 0; } + +struct S4 { + inline S4() {} // expected-error {{function definition redundantly declared 'inline' [loplugin:redundantinline]}} + inline ~S4() { f1(); } // expected-error {{function definition redundantly declared 'inline' [loplugin:redundantinline]}} + + inline void f1() { (void)this; } // expected-error {{function definition redundantly declared 'inline' [loplugin:redundantinline]}} + + static inline void f2() {} // expected-error {{function definition redundantly declared 'inline' [loplugin:redundantinline]}} + + inline void operator +() {} // expected-error {{function definition redundantly declared 'inline' [loplugin:redundantinline]}} + + inline operator int() { return 0; } // expected-error {{function definition redundantly declared 'inline' [loplugin:redundantinline]}} + + friend inline void f4() {} // expected-error {{function definition redundantly declared 'inline' [loplugin:redundantinline]}} + + static constexpr int f5() { return 0; } + + static constexpr inline int f6() { return 0; } // expected-error {{function definition redundantly declared 'inline' [loplugin:redundantinline]}} +}; + +constexpr int f5() { return 0; } + +constexpr inline int f6() { return 0; } // expected-error {{function definition redundantly declared 'inline' [loplugin:redundantinline]}} + +static inline int f7() { return 0; } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/redundantpointerops.cxx b/compilerplugins/clang/test/redundantpointerops.cxx new file mode 100644 index 000000000..c766099fc --- /dev/null +++ b/compilerplugins/clang/test/redundantpointerops.cxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include +#include +#include +#include + +struct Struct1 { + int x; +}; + +void function1(Struct1& s) +{ + (&s)->x = 1; // expected-error {{'&' followed by '->' operating on 'Struct1', rather use '.' [loplugin:redundantpointerops]}} +}; + +struct Struct2 { + int x; + Struct2* operator&() { return this; } +}; + +void function2(Struct2 s) +{ + (&s)->x = 1; // expected-error {{'&' followed by '->' operating on 'Struct2', rather use '.' [loplugin:redundantpointerops]}} +}; + +void function3(Struct1& s) +{ + (*(&s)).x = 1; // expected-error {{'&' followed by '*' operating on 'Struct1', rather use '.' [loplugin:redundantpointerops]}} +}; + +//void function4(Struct1* s) +//{ +// (*s).x = 1; // xxexpected-error {{'*' followed by '.', rather use '->' [loplugin:redundantpointerops]}} +//}; + +int function5(std::unique_ptr x) +{ + return *x.get(); // expected-error-re {{'*' followed by '.get()' operating on '{{.*}}unique_ptr{{.*}}', just use '*' [loplugin:redundantpointerops]}} +}; + +void function6(std::shared_ptr x) +{ + (void) *x.get(); // expected-error-re {{'*' followed by '.get()' operating on '{{.*}}shared_ptr{{.*}}', just use '*' [loplugin:redundantpointerops]}} +} + +void function6b(std::shared_ptr x) +{ + x.get()->x = 1; // expected-error-re {{'get()' followed by '->' operating on '{{.*}}shared_ptr{{.*}}', just use '->' [loplugin:redundantpointerops]}} +} + +void function7(rtl::Reference x) +{ + (void) *x.get(); // expected-error {{'*' followed by '.get()' operating on 'rtl::Reference', just use '*' [loplugin:redundantpointerops]}} +} + +void function8(css::uno::Reference x) +{ + (void) *x.get(); // expected-error {{'*' followed by '.get()' operating on 'css::uno::Reference', just use '*' [loplugin:redundantpointerops]}} +} + +void function9(tools::SvRef x) +{ + (void) *x.get(); // expected-error {{'*' followed by '.get()' operating on 'tools::SvRef', just use '*' [loplugin:redundantpointerops]}} +} + +struct DerivedRtlReference: public rtl::Reference {}; + +void function10(DerivedRtlReference x) +{ + (void) *x.get(); // expected-error {{'*' followed by '.get()' operating on 'DerivedRtlReference', just use '*' [loplugin:redundantpointerops]}} +} + +struct DerivedUnoReference: public css::uno::Reference {}; + +void function11(DerivedUnoReference x) +{ + (void) *x.get(); // expected-error {{'*' followed by '.get()' operating on 'DerivedUnoReference', just use '*' [loplugin:redundantpointerops]}} +} + +// tools::SvRef is final + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/redundantpreprocessor.cxx b/compilerplugins/clang/test/redundantpreprocessor.cxx new file mode 100644 index 000000000..18ab10559 --- /dev/null +++ b/compilerplugins/clang/test/redundantpreprocessor.cxx @@ -0,0 +1,15 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifdef __clang__ // expected-note {{previous ifdef [loplugin:redundantpreprocessor]}} +#ifdef __clang__ // expected-error {{nested ifdef [loplugin:redundantpreprocessor]}} +#endif +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/refassign.cxx b/compilerplugins/clang/test/refassign.cxx new file mode 100644 index 000000000..7fc20cbe2 --- /dev/null +++ b/compilerplugins/clang/test/refassign.cxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +int& f1(); +int& f2(); + +void test1() +{ + int& v1 = f1(); + v1 = f2(); // expected-error {{assigning a 'int &' to a var of type 'int &' probably does not do what you think [loplugin:refassign]}} + f1() + = f2(); // expected-error {{assigning a 'int &' to a var of type 'int &' probably does not do what you think [loplugin:refassign]}} + + // no warning expected + int x = 1; + x = f1(); + std::vector v; + v[0] = f1(); + v1 = std::min(1, 2); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/refcounting.cxx b/compilerplugins/clang/test/refcounting.cxx new file mode 100644 index 000000000..7ab830fc9 --- /dev/null +++ b/compilerplugins/clang/test/refcounting.cxx @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include + +namespace cppu +{ +class OWeakObject +{ +public: + void acquire(); + void release(); +}; +} + +struct UnoObject : public cppu::OWeakObject +{ +}; +struct UnoSubObject : public UnoObject +{ +}; + +// +// Note, getting duplicate warnings for some reason I cannot fathom +// + +struct Foo +{ + // expected-error@+2 {{cppu::OWeakObject subclass 'UnoObject' being managed via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}} + // expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being managed via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}} + std::unique_ptr m_foo1; + // expected-error@+2 {{cppu::OWeakObject subclass 'UnoObject' being managed via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}} + // expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being managed via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}} + std::shared_ptr m_foo2; + // expected-error@+2 {{cppu::OWeakObject subclass 'UnoObject' being managed via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}} + // expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being managed via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}} + boost::intrusive_ptr m_foo3; + rtl::Reference m_foo4; // no warning expected +}; + +// expected-error@+2 {{cppu::OWeakObject subclass 'UnoObject' being managed via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}} +// expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being managed via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}} +std::unique_ptr foo1(); +rtl::Reference foo2(); // no warning expected +// expected-error@+2 {{cppu::OWeakObject subclass 'UnoObject' being managed via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}} +// expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being managed via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}} +void foo3(std::unique_ptr p); + +void test2(UnoObject* pUnoObject) +{ + // expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being deleted via delete, should be managed via rtl::Reference [loplugin:refcounting]}} + delete pUnoObject; +} + +template struct Dependent : T +{ + void f() { delete this; } + //TODO: missing expected error@+1 {{cppu::OWeakObject subclass 'Dependent' being deleted via delete, should be managed via rtl::Reference [loplugin:refcounting]}} + void g() { delete this; } +}; +struct Dummy +{ +}; +void dummy(Dependent* p1, Dependent* p2) +{ + p1->f(); + p2->g(); +} + +void foo4() +{ + // expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being managed via raw pointer, should be managed via rtl::Reference [loplugin:refcounting]}} + UnoObject* p = new UnoObject; + (void)p; + // expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being managed via raw pointer, should be managed via rtl::Reference [loplugin:refcounting]}} + p = new UnoObject; +} + +UnoObject* foo5() +{ + // expected-error@+1 {{new object of cppu::OWeakObject subclass 'UnoObject' being returned via raw pointer, should be returned by via rtl::Reference [loplugin:refcounting]}} + return new UnoObject; +} +rtl::Reference foo6() +{ + // no warning expected + return new UnoObject; +} +const rtl::Reference& getConstRef(); +void foo7() +{ + // expected-error@+1 {{cppu::OWeakObject subclass 'UnoSubObject' being managed via raw pointer, should be managed via rtl::Reference [loplugin:refcounting]}} + UnoSubObject* p1 = static_cast(foo6().get()); + (void)p1; + // expected-error@+1 {{cppu::OWeakObject subclass 'UnoSubObject' being managed via raw pointer, should be managed via rtl::Reference [loplugin:refcounting]}} + p1 = static_cast(foo6().get()); + + rtl::Reference u2; + // no warning expected + UnoSubObject* p2 = static_cast(u2.get()); + (void)p2; + p2 = static_cast(u2.get()); + // no warning expected + UnoSubObject* p3 = static_cast(getConstRef().get()); + (void)p3; + p3 = static_cast(getConstRef().get()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/referencecasting.cxx b/compilerplugins/clang/test/referencecasting.cxx new file mode 100644 index 000000000..1f3480dbe --- /dev/null +++ b/compilerplugins/clang/test/referencecasting.cxx @@ -0,0 +1,212 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" + +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/io/XStreamListener.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/lang/XTypeProvider.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "cppuhelper/implbase.hxx" +#include "cppuhelper/weak.hxx" +#include "rtl/ref.hxx" + +void test1(const css::uno::Reference& a) +{ + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + css::uno::Reference b(a, css::uno::UNO_QUERY); + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + auto c = css::uno::Reference::query(a); +} + +namespace test2 +{ +css::uno::Reference getListener(); + +void test() +{ + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + css::uno::Reference b(getListener(), css::uno::UNO_QUERY); +} +} + +namespace test3 +{ +void callListener(css::uno::Reference const&); + +void test(css::uno::Reference const& l) +{ + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + callListener(css::uno::Reference(l, css::uno::UNO_QUERY)); +} +} + +void test4(const css::uno::Reference& a) +{ + // no warning expected, used to reject null references + css::uno::Reference b(a, css::uno::UNO_SET_THROW); +} + +// no warning expected +namespace test5 +{ +void test(css::uno::Reference l) +{ + css::uno::Reference a = l; +} +} + +namespace test6 +{ +void test(css::uno::Reference l) +{ + css::uno::Reference a; + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + a.set(l, css::uno::UNO_QUERY); +} +} + +namespace test7 +{ +void test(css::uno::Reference l) +{ + // expected-error@+1 {{unnecessary get() call [loplugin:referencecasting]}} + css::uno::Reference a(l.get(), css::uno::UNO_QUERY); + // expected-error@+1 {{unnecessary get() call [loplugin:referencecasting]}} + a.set(l.get(), css::uno::UNO_QUERY); +} + +class FooStream : public css::io::XStreamListener +{ + virtual ~FooStream(); +}; +void test(rtl::Reference l) +{ + // expected-error@+1 {{unnecessary get() call [loplugin:referencecasting]}} + css::uno::Reference a(l.get()); + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + a.set(l.get(), css::uno::UNO_QUERY); + // expected-error@+1 {{unnecessary get() call [loplugin:referencecasting]}} + a.set(l.get()); + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + css::uno::Reference b(l.get(), css::uno::UNO_QUERY); + // no warning expected + css::uno::Reference c(l.get(), css::uno::UNO_QUERY); + // no warning expected + css::uno::Reference a2 = l; + (void)a2; +} +css::uno::Sequence> getContinuations() +{ + rtl::Reference noel1; + // expected-error@+1 {{unnecessary get() call [loplugin:referencecasting]}} + return { noel1.get() }; +} +} + +namespace test8 +{ +void test(css::io::XStreamListener* l) +{ + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + css::uno::Reference a(l, css::uno::UNO_QUERY); + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + a.set(l, css::uno::UNO_QUERY); +} +} + +// check for looking through casts +namespace test9 +{ +class StatusbarController : public css::io::XStreamListener, public ::cppu::OWeakObject +{ +}; + +void test(StatusbarController* pController) +{ + css::uno::Reference xController; + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + xController.set(static_cast<::cppu::OWeakObject*>(pController), css::uno::UNO_QUERY); +} +} + +// no warning expected when we have an ambiguous base +namespace test10 +{ +class Foo : public css::lang::XTypeProvider, public css::lang::XComponent +{ + virtual ~Foo(); + void bar() + { + css::uno::Reference xSource( + static_cast(this), css::uno::UNO_QUERY); + } +}; +} + +// no warning expected for SAL_NO_ACQUIRE +namespace test11 +{ +void test(css::io::XStreamListener* l) +{ + css::uno::Reference a(l, SAL_NO_ACQUIRE); + a.set(l, SAL_NO_ACQUIRE); +} +} + +// no warning expected: querying for XInterface (instead of doing an upcast) has special semantics, +// to check for UNO object equivalence. +void test12(const css::uno::Reference& a) +{ + css::uno::Reference b(a, css::uno::UNO_QUERY); +} + +// no warning expected: querying for XInterface (instead of doing an upcast) has special semantics, +// to check for UNO object equivalence. +struct Test13 +{ + css::uno::Reference m_xNormalizedIFace; + void newObject(const css::uno::Reference& _rxIFace) + { + m_xNormalizedIFace.set(_rxIFace, css::uno::UNO_QUERY); + } +}; + +void test14(css::uno::Sequence> seq) +{ + for (sal_Int32 i = 0; i < seq.getLength(); ++i) + { + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + css::uno::Reference xDataSeries(seq[i], css::uno::UNO_QUERY); + } +} + +namespace test15 +{ +class Foo : public cppu::WeakImplHelper +{ + virtual ~Foo(); + css::uno::Reference bar() + { + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + return css::uno::Reference( + static_cast(this), css::uno::UNO_QUERY); + } + css::uno::Reference bar2() + { + // expected-error@+1 {{the source reference is already a subtype of the destination reference, just use = [loplugin:referencecasting]}} + return css::uno::Reference(static_cast(this), + css::uno::UNO_QUERY); + } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/returnconstval.cxx b/compilerplugins/clang/test/returnconstval.cxx new file mode 100644 index 000000000..481ae84df --- /dev/null +++ b/compilerplugins/clang/test/returnconstval.cxx @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +struct S2 +{ + OUString mv1; + // expected-error@+1 {{either return non-const, or by const ref [loplugin:returnconstval]}} + const OUString get1() { return mv1; } + const OUString& get2() { return mv1; } + OUString get3() { return mv1; } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/salcall.cxx b/compilerplugins/clang/test/salcall.cxx new file mode 100644 index 000000000..a4464cee6 --- /dev/null +++ b/compilerplugins/clang/test/salcall.cxx @@ -0,0 +1,188 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#define VOID void + +class Class1 +{ + SAL_CALL Class1() {} // expected-error {{SAL_CALL unnecessary here [loplugin:salcall]}} + SAL_CALL ~Class1() {} // expected-error {{SAL_CALL unnecessary here [loplugin:salcall]}} + SAL_CALL operator int() // expected-error {{SAL_CALL unnecessary here [loplugin:salcall]}} + { + return 0; + } + + void SAL_CALL method1(); // expected-error {{SAL_CALL unnecessary here [loplugin:salcall]}} + VOID method2() {} + // no SAL_CALL for above method2, even though "SAL_CALL" appears between definition of VOID and + // the declaration's name, "method2" +}; +void SAL_CALL Class1::method1() +{ // expected-error@-1 {{SAL_CALL unnecessary here [loplugin:salcall]}} +} + +class Class2 +{ + void method1(); // expected-note {{SAL_CALL inconsistency [loplugin:salcall]}} +}; +void SAL_CALL Class2::method1() {} // expected-error {{SAL_CALL inconsistency [loplugin:salcall]}} + +// comment this out because it seems to generate a warning in some internal buffer of clang that I can't annotate +#if 0 +// no warning, this appears to be legal +class Class3 +{ + void SAL_CALL method1(); // expected-error {{SAL_CALL unnecessary here [loplugin:salcall]}} +}; +void Class3::method1() {} +#endif + +// no warning, normal case for reference +class Class4 +{ + void method1(); +}; +void Class4::method1() {} + +class Class5_1 +{ + virtual void method1(); // expected-note {{SAL_CALL inconsistency [loplugin:salcall]}} + virtual ~Class5_1(); +}; +class Class5_2 +{ + virtual void SAL_CALL method1(); + virtual ~Class5_2(); +}; +class Class5_3 : public Class5_1, public Class5_2 +{ + virtual void SAL_CALL + method1() override; // expected-error {{SAL_CALL inconsistency [loplugin:salcall]}} + virtual ~Class5_3(); +}; + +class Class6_1 +{ + virtual void SAL_CALL method1(); + virtual ~Class6_1(); +}; +class Class6_2 +{ + virtual void SAL_CALL method1(); + virtual ~Class6_2(); +}; +class Class6_3 : public Class6_1, public Class6_2 +{ + virtual void SAL_CALL method1() override; + virtual ~Class6_3(); +}; + +class Class7_1 +{ + virtual void method1(); + virtual ~Class7_1(); +}; +class Class7_2 +{ + virtual void method1(); + virtual ~Class7_2(); +}; +class Class7_3 : public Class7_1, public Class7_2 +{ + virtual void method1() override; + virtual ~Class7_3(); +}; + +class Class8_1 +{ + virtual void method2(); + virtual ~Class8_1(); +}; +class Class8_2 +{ + virtual void SAL_CALL method2(); // expected-note {{SAL_CALL inconsistency [loplugin:salcall]}} + virtual ~Class8_2(); +}; +class Class8_3 : public Class8_1, public Class8_2 +{ + virtual void method2() override; // expected-error {{SAL_CALL inconsistency [loplugin:salcall]}} + virtual ~Class8_3(); +}; + +#define M1(m) VOID m +class Class9 +{ + Class9(); // expected-note {{SAL_CALL inconsistency [loplugin:salcall]}} + M1(method1)(); // expected-note {{SAL_CALL inconsistency [loplugin:salcall]}} + void method2(); // expected-note {{SAL_CALL inconsistency [loplugin:salcall]}} +}; +#define MC(num) \ + Class##num::Class##num() {} +SAL_CALL MC(9) // expected-error {{SAL_CALL inconsistency [loplugin:salcall]}} + ; // to appease clang-format +void SAL_CALL Class9::method1() // expected-error {{SAL_CALL inconsistency [loplugin:salcall]}} +{ +} +#define M2(T) T SAL_CALL +M2(void) Class9::method2() {} // expected-error {{SAL_CALL inconsistency [loplugin:salcall]}} + +void SAL_CALL f0() {} // expected-error {{SAL_CALL unnecessary here [loplugin:salcall]}} + +void SAL_CALL f1() {} + +void SAL_CALL f2() {} + +void SAL_CALL f3() {} + +void SAL_CALL f4() {} + +typedef void SAL_CALL (*Ptr)(); + +void takePtr(Ptr); + +void usePtr() +{ + f0(); + takePtr(f1); + takePtr(&f2); + Ptr p = f3; + takePtr(p); + p = f4; + takePtr(p); +} + +#if 0 // see TODO in SalCall::isSalCallFunction +class Class10 +{ + void method1(); +}; +#define M3(T, SAL_CALL) T SAL_CALL:: +M3(void, Class10) method1() {} // false "SAL_CALL inconsistency" +#endif + +#if 0 //TODO +template struct S { + virtual ~S(); + virtual void f(); +}; +template S::~S() {} +template void S::f() {} +struct S2: S { + ~S2(); + void f() {} +}; +int main() { + S2 s2; + s2->f(); +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/sallogareas.cxx b/compilerplugins/clang/test/sallogareas.cxx new file mode 100644 index 000000000..1b172ebd0 --- /dev/null +++ b/compilerplugins/clang/test/sallogareas.cxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +void func1(); + +int main() +{ + SAL_WARN( + "bob.none", + "message"); // expected-error@-2 {{unknown log area 'bob.none' (check or extend include/sal/log-areas.dox) [loplugin:sallogareas]}} + + SAL_WARN("xmloff", "message"); + + try + { + func1(); + } + catch (std::exception const&) + { + DBG_UNHANDLED_EXCEPTION( + "bob.none", + "message"); // expected-error@-2 {{unknown log area 'bob.none' (check or extend include/sal/log-areas.dox) [loplugin:sallogareas]}} + } + try + { + func1(); + } + catch (std::exception const&) + { + DBG_UNHANDLED_EXCEPTION("xmloff", "message"); + } + try + { + func1(); + } + catch (std::exception const&) + { + DBG_UNHANDLED_EXCEPTION("xmloff"); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/salunicodeliteral.cxx b/compilerplugins/clang/test/salunicodeliteral.cxx new file mode 100644 index 000000000..bf14e4843 --- /dev/null +++ b/compilerplugins/clang/test/salunicodeliteral.cxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" + +#include "sal/types.h" + +#include "salunicodeliteral.hxx" + +#define TEST1 'x' +#define TEST2 sal_Unicode('x') + +namespace { + +void f(sal_Unicode) {} + +} + +void test() { + f(sal_Unicode('x')); // expected-error {{in LIBO_INTERNAL_ONLY code, replace literal cast to 'sal_Unicode' (aka 'char16_t') with a u'...' char16_t character literal [loplugin:salunicodeliteral]}} + f(static_cast('x')); // expected-error {{in LIBO_INTERNAL_ONLY code, replace literal cast to 'sal_Unicode' (aka 'char16_t') with a u'...' char16_t character literal [loplugin:salunicodeliteral]}} + using T = sal_Unicode const; + f(static_cast('x')); // expected-error {{in LIBO_INTERNAL_ONLY code, replace literal cast to 'T' (aka 'const char16_t') with a u'...' char16_t character literal [loplugin:salunicodeliteral]}} + f((sal_Unicode) 'x'); // expected-error {{in LIBO_INTERNAL_ONLY code, replace literal cast to 'sal_Unicode' (aka 'char16_t') with a u'...' char16_t character literal [loplugin:salunicodeliteral]}} + f(sal_Unicode(('x'))); // expected-error {{in LIBO_INTERNAL_ONLY code, replace literal cast to 'sal_Unicode' (aka 'char16_t') with a u'...' char16_t character literal [loplugin:salunicodeliteral]}} + f(sal_Unicode(120)); // expected-error {{in LIBO_INTERNAL_ONLY code, replace literal cast to 'sal_Unicode' (aka 'char16_t') with a u'...' char16_t character literal [loplugin:salunicodeliteral]}} + f(sal_Unicode(TEST1)); + f(TEST2); // expected-error {{in LIBO_INTERNAL_ONLY code, replace literal cast to 'sal_Unicode' (aka 'char16_t') with a u'...' char16_t character literal [loplugin:salunicodeliteral]}} + char c = 'x'; + f(sal_Unicode(c)); + f(char16_t('x')); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/salunicodeliteral.hxx b/compilerplugins/clang/test/salunicodeliteral.hxx new file mode 100644 index 000000000..91bc224e7 --- /dev/null +++ b/compilerplugins/clang/test/salunicodeliteral.hxx @@ -0,0 +1,14 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +void test(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/selfinit.cxx b/compilerplugins/clang/test/selfinit.cxx new file mode 100644 index 000000000..412a65b70 --- /dev/null +++ b/compilerplugins/clang/test/selfinit.cxx @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +extern int i; +int i = i; +// expected-error@-1 {{referencing a variable during its own initialization is error-prone and thus suspicious [loplugin:selfinit]}} +// expected-note@-2 {{variable declared here [loplugin:selfinit]}} + +int j = [](int n) { return j + n; }(0); +// expected-error@-1 {{referencing a variable during its own initialization is error-prone and thus suspicious [loplugin:selfinit]}} +// expected-note@-2 {{variable declared here [loplugin:selfinit]}} + +int k = sizeof k; + +int f(std::type_info const&); + +int l = f(typeid(l)); + +bool m = noexcept(m); + +template int g(); + +int n = g(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/sequentialassign.cxx b/compilerplugins/clang/test/sequentialassign.cxx new file mode 100644 index 000000000..b7182db5c --- /dev/null +++ b/compilerplugins/clang/test/sequentialassign.cxx @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#pragma clang diagnostic ignored "-Wunknown-warning-option" // for Clang < 13 +#pragma clang diagnostic ignored "-Wunused-but-set-variable" + +namespace test1 +{ +void f(OUString s1) +{ + OUString s2 = s1; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:sequentialassign]}} + s2 = s2.getToken(0, '('); +} +} + +namespace test2 +{ +OUString s2; +void f(OUString s1) +{ + s2 = s1; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:sequentialassign]}} + s2 = s2.getToken(0, '('); +} +} + +namespace test3 +{ +struct VolumeInfo +{ + OUString getFileSystemName(); +}; +OUString aNullURL(""); +void f(VolumeInfo _aVolumeInfo) +{ + OUString aFileSysName(aNullURL); + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:sequentialassign]}} + aFileSysName = _aVolumeInfo.getFileSystemName(); +} +} + +namespace test4 +{ +struct B3DVector +{ + B3DVector getPerpendicular(); +}; +void f(B3DVector aNewVPN) +{ + B3DVector aNewToTheRight = aNewVPN; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:sequentialassign]}} + aNewToTheRight = aNewToTheRight.getPerpendicular(); +} +} + +namespace test5 +{ +void f(OUString s, int x) +{ + int nPos = x; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:sequentialassign]}} + nPos = s.indexOf("x", nPos); +} +} + +namespace test6 +{ +void f() +{ + OUString s2("xxxx"); + s2 = s2.getToken(0, '('); // no warning expected +} +} + +namespace test7 +{ +class Class1 +{ + OUString m_field1; + void foo(Class1& rOther) + { + OUString s = rOther.m_field1; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:sequentialassign]}} + s = s.copy(1, 2); + } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/shouldreturnbool.cxx b/compilerplugins/clang/test/shouldreturnbool.cxx new file mode 100644 index 000000000..03a698e30 --- /dev/null +++ b/compilerplugins/clang/test/shouldreturnbool.cxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +int foo1(char ch) +{ + // expected-error@-2 {{only returning one or zero is an indication you want to return bool [loplugin:shouldreturnbool]}} + if (ch == 'x') + return 1; + return 0; +} + +long foo2() +{ + // expected-error@-2 {{only returning one or zero is an indication you want to return bool [loplugin:shouldreturnbool]}} + return 1; +} + +enum Enum1 +{ + NONE +}; + +Enum1 foo3() { return Enum1::NONE; } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/simplifyconstruct.cxx b/compilerplugins/clang/test/simplifyconstruct.cxx new file mode 100644 index 000000000..d44738f78 --- /dev/null +++ b/compilerplugins/clang/test/simplifyconstruct.cxx @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +namespace test1 +{ +struct Foo +{ + void acquire(); + void release(); +}; +class Foo1 +{ + std::unique_ptr m_pbar1; + rtl::Reference m_pbar2; + Foo1() + : m_pbar1(nullptr) + // expected-error@-1 {{no need to explicitly init an instance of 'std::unique_ptr' with nullptr, just use default constructor [loplugin:simplifyconstruct]}} + , m_pbar2(nullptr) + // expected-error@-1 {{no need to explicitly init an instance of 'rtl::Reference' with nullptr, just use default constructor [loplugin:simplifyconstruct]}} + { + } +}; +} + +// no warning expected when using std::unique_ptr constructor with a custom deleter +namespace test2 +{ +struct ITypeLib +{ +}; +struct IUnknown +{ + void Release(); +}; +void func2() +{ + std::unique_ptr aITypeLibGuard(nullptr, [](IUnknown* p) { + if (p) + p->Release(); + }); +} +} + +namespace test3 +{ +struct Foo +{ + void acquire(); + void release(); +}; +void f(Foo* f) +{ + // expected-error@+1 {{simplify [loplugin:simplifyconstruct]}} + rtl::Reference x = rtl::Reference(f); +} +} + +// no warning expected +namespace test4 +{ +struct Foo +{ + void acquire(); + void release(); +}; +void f(Foo* f) { auto x = rtl::Reference(f); } +} + +namespace test5 +{ +void f() +{ + // expected-error@+1 {{simplify [loplugin:simplifyconstruct]}} + tools::Rectangle x = tools::Rectangle(10, 10, 10, 10); + (void)x; +} +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/simplifydynamiccast.cxx b/compilerplugins/clang/test/simplifydynamiccast.cxx new file mode 100644 index 000000000..111734f0a --- /dev/null +++ b/compilerplugins/clang/test/simplifydynamiccast.cxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +struct ClassA +{ + virtual ~ClassA() {} +}; + +struct ClassB : public ClassA +{ + void foo() {} +}; + +void f1(ClassA* p1) +{ + if (dynamic_cast(p1)) // expected-note {{if here [loplugin:simplifydynamiccast]}} + { + static_cast(p1) + ->foo(); // expected-error@-1 {{simplify, use var in if [loplugin:simplifydynamiccast]}} + } + if (dynamic_cast(p1) != nullptr) + { // expected-note@-1 {{if here [loplugin:simplifydynamiccast]}} + static_cast(p1) + ->foo(); // expected-error@-1 {{simplify, use var in if [loplugin:simplifydynamiccast]}} + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/simplifypointertobool.cxx b/compilerplugins/clang/test/simplifypointertobool.cxx new file mode 100644 index 000000000..2980003e1 --- /dev/null +++ b/compilerplugins/clang/test/simplifypointertobool.cxx @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include "com/sun/star/uno/XInterface.hpp" + +void foo(); + +bool test1(std::unique_ptr p2) +{ + // expected-error@+1 {{simplify, drop the get() [loplugin:simplifypointertobool]}} + if (p2.get()) + foo(); + // expected-error@+1 {{simplify, drop the get() and wrap the expression in a functional cast to bool [loplugin:simplifypointertobool]}} + bool b1 = p2.get(); + // expected-error@+3 {{simplify, drop the get() and turn the surrounding parentheses into a functional cast to bool [loplugin:simplifypointertobool]}} + // expected-note@+1 {{surrounding parentheses here [loplugin:simplifypointertobool]}} + bool b2 = ( // deliberately spread across multiple lines + p2.get()); + return b1 && b2; +} + +void test2(std::shared_ptr p) +{ + // expected-error@+1 {{simplify, drop the get() [loplugin:simplifypointertobool]}} + if (p.get()) + foo(); + // expected-error@+1 {{simplify, convert to '!x' [loplugin:simplifypointertobool]}} + if (p.get() == nullptr) + foo(); + // TODOexpected-error@+1 {{simplify, convert to '!x' [loplugin:simplifypointertobool]}} + if (p == nullptr) + foo(); + // TODOexpected-error@+1 {{simplify, convert to 'x' [loplugin:simplifypointertobool]}} + if (p != nullptr) + foo(); + // expected-error@+1 {{simplify, convert to '!x' [loplugin:simplifypointertobool]}} + if (nullptr == p.get()) + foo(); + // expected-error@+1 {{simplify, convert to 'x' [loplugin:simplifypointertobool]}} + if (p.get() != nullptr) + foo(); + // expected-error@+1 {{simplify, convert to 'x' [loplugin:simplifypointertobool]}} + if (nullptr != p.get()) + foo(); +} + +void test2(int* p) +{ + // TODOexpected-error@+1 {{simplify, convert to '!x' [loplugin:simplifypointertobool]}} + if (p == nullptr) + foo(); + // TODOexpected-error@+1 {{simplify, convert to 'x' [loplugin:simplifypointertobool]}} + if (p != nullptr) + foo(); +} + +void test2(css::uno::Reference const& p) +{ + // expected-error@+1 {{simplify, drop the get() [loplugin:simplifypointertobool]}} + if (p.get()) + foo(); + // expected-error@+1 {{simplify, convert to '!x' [loplugin:simplifypointertobool]}} + if (p.get() == nullptr) + foo(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/singlevalfields.cxx b/compilerplugins/clang/test/singlevalfields.cxx new file mode 100644 index 000000000..14be377c3 --- /dev/null +++ b/compilerplugins/clang/test/singlevalfields.cxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +struct Foo +{ + // expected-error@+1 {{assign XXX [loplugin:singlevalfields]}} + OUString m_aMenuResourceURL; + + Foo() + : m_aMenuResourceURL("XXX") + { + m_aMenuResourceURL = "XXX"; + m_aMenuResourceURL = "X" + "XX"; + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/staticconstfield.cxx b/compilerplugins/clang/test/staticconstfield.cxx new file mode 100644 index 000000000..fd36a6452 --- /dev/null +++ b/compilerplugins/clang/test/staticconstfield.cxx @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +class Class1 +{ + OUString const + m_field1; // expected-error {{const field can be static [loplugin:staticconstfield]}} + Class1() + : m_field1("xxxx") + // expected-note@-1 {{init here [loplugin:staticconstfield]}} + { + (void)m_field1; + } +}; + +class Class2 +{ + OString const + m_field2; // expected-error {{const field can be static [loplugin:staticconstfield]}} + Class2() + : m_field2("yyyy") + // expected-note@-1 {{init here [loplugin:staticconstfield]}} + { + (void)m_field2; + } +}; + +// no warning expected +class Class4 +{ + OUString m_field3; + Class4() + : m_field3("zzzz") + { + (void)m_field3; + } +}; + +class Class5 +{ + enum class Enum + { + ONE + }; + float const + m_fielda1; // expected-error {{const field can be static [loplugin:staticconstfield]}} + int const m_fielda2; // expected-error {{const field can be static [loplugin:staticconstfield]}} + bool const + m_fielda3; // expected-error {{const field can be static [loplugin:staticconstfield]}} + Enum const + m_fielda4; // expected-error {{const field can be static [loplugin:staticconstfield]}} + Class5() + : m_fielda1(1.0) + // expected-note@-1 {{init here [loplugin:staticconstfield]}} + , m_fielda2(1) + // expected-note@-1 {{init here [loplugin:staticconstfield]}} + , m_fielda3(true) + // expected-note@-1 {{init here [loplugin:staticconstfield]}} + , m_fielda4(Enum::ONE) + // expected-note@-1 {{init here [loplugin:staticconstfield]}} + { + (void)m_fielda1; + (void)m_fielda2; + (void)m_fielda3; + (void)m_fielda4; + } +}; + +// no warning expected +class Class6 +{ + enum class Enum + { + ONE + }; + float m_fieldb1; + int m_fieldb2; + bool m_fieldb3; + Enum m_fieldb4; + Class6() + : m_fieldb1(1.0) + , m_fieldb2(1) + , m_fieldb3(true) + , m_fieldb4(Enum::ONE) + { + (void)m_fieldb1; + (void)m_fieldb2; + (void)m_fieldb3; + (void)m_fieldb4; + } +}; + +// no warning expected, checking for assigning to const field from multiple constructors +class Class7 +{ + bool const m_field7; + Class7() + : m_field7(true) + { + (void)m_field7; + } + Class7(bool b) + : m_field7(b) + { + (void)m_field7; + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/staticdynamic.cxx b/compilerplugins/clang/test/staticdynamic.cxx new file mode 100644 index 000000000..aa6ca7559 --- /dev/null +++ b/compilerplugins/clang/test/staticdynamic.cxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +struct ClassA +{ + virtual ~ClassA() {} +}; + +struct ClassB : public ClassA +{ + void foo() const {} +}; + +void f1(ClassA* p1) +{ + // expected-note@+1 {{static_cast here [loplugin:staticdynamic]}} + static_cast(p1)->foo(); + // expected-error@+1 {{dynamic_cast after static_cast [loplugin:staticdynamic]}} + dynamic_cast(p1)->foo(); +}; + +void f2(ClassA* p1) +{ + // expected-note@+1 {{dynamic_cast here [loplugin:staticdynamic]}} + dynamic_cast(p1)->foo(); + // expected-error@+1 {{static_cast after dynamic_cast [loplugin:staticdynamic]}} + static_cast(p1)->foo(); +}; + +void f3(ClassA* p1) +{ + // expected-note@+1 {{dynamic_cast here [loplugin:staticdynamic]}} + dynamic_cast(p1)->foo(); + // expected-error@+1 {{static_cast after dynamic_cast [loplugin:staticdynamic]}} + static_cast(p1)->foo(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/staticvar.cxx b/compilerplugins/clang/test/staticvar.cxx new file mode 100644 index 000000000..5c0a86fc4 --- /dev/null +++ b/compilerplugins/clang/test/staticvar.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include + +struct S1 +{ + int x, y; +}; + +S1 const& f1(int a) +{ + static S1 s1[]{ + // expected-error@-1 {{var should be static const, or allowlisted [loplugin:staticvar]}} + { 1, 1 } + }; + // no warning expected + const S1 s2[]{ { a, 1 } }; + (void)s2; + return s1[0]; +} + +struct S2 +{ + OUString x; +}; + +S2 const& f2() +{ + static S2 const s1[]{ + // expected-error@-1 {{static const var requires runtime initialization? [loplugin:staticvar]}} + { "xxx" } + }; + return s1[0]; +} + +// no warning expected +S2 const& f3() +{ + static S2 s1[]{ { "xxx" } }; + return s1[0]; +} + +// no warning expected +struct S4 +{ + std::u16string_view const cName; + bool const bCanBeVisible; +}; +S4 const& f4() +{ + static const S4 s1[] = { + { std::u16string_view(u"/DocColor"), false }, + }; + return s1[0]; +} + +struct S5 +{ + bool const bCanBeVisible; +}; +void f5(bool b) +{ + const S5 s1[] = { + { b }, + }; + (void)s1; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stdfunction.cxx b/compilerplugins/clang/test/stdfunction.cxx new file mode 100644 index 000000000..492ba4249 --- /dev/null +++ b/compilerplugins/clang/test/stdfunction.cxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +struct S +{ + bool empty() const; +}; + +template struct ST +{ + bool empty() const; +}; + +namespace std +{ +bool empty( //expected-error {{Do not declare a function in namespace 'std' [loplugin:stdfunction]}} + S const&); + +template <> +bool empty( //expected-error {{Do not declare a function template specialization in namespace 'std' [loplugin:stdfunction]}} + S const&); + +template +bool empty( //expected-error {{Do not declare a function template in namespace 'std' [loplugin:stdfunction]}} + ST const&); + +template <> class vector +{ +public: + [[nodiscard]] constexpr bool empty() const noexcept; +}; + +[[nodiscard]] constexpr bool vector::empty() const noexcept { return true; } +} + +namespace std::inner +{ +bool empty( //expected-error {{Do not declare a function in namespace 'std' [loplugin:stdfunction]}} + S const&); +} + +namespace outer::std +{ +bool empty(S const&); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringadd.cxx b/compilerplugins/clang/test/stringadd.cxx new file mode 100644 index 000000000..f76464b9a --- /dev/null +++ b/compilerplugins/clang/test/stringadd.cxx @@ -0,0 +1,262 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#pragma clang diagnostic ignored "-Wunknown-warning-option" // for Clang < 13 +#pragma clang diagnostic ignored "-Wunused-but-set-parameter" +#pragma clang diagnostic ignored "-Wunused-but-set-variable" + +// --------------------------------------------------------------- +// += tests + +namespace test1 +{ +static const char XXX1[] = "xxx"; +static constexpr char16_t XXX1u[] = u"xxx"; +static const char XXX2[] = "xxx"; +void f1(OUString s1, int i, OString o) +{ + OUString s2 = s1; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += "xxx"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += "xxx"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += s1; + s2 = s1 + "xxx"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += s1; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += OUString::number(i); + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += XXX1; + // expected-error-re@+2 {{rather use O[U]String::Concat than constructing 'rtl::OUStringLiteral<4>' from 'const char16_t{{ ?}}[4]' on LHS of + (where RHS is of type 'const char{{ ?}}[4]') [loplugin:stringadd]}} + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += OUStringLiteral(XXX1u) + XXX2; + + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += OStringToOUString(o, RTL_TEXTENCODING_UTF8); +} +void f2(OString s1, int i, OUString u) +{ + OString s2 = s1; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += "xxx"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += "xxx"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += s1; + s2 = s1 + "xxx"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += s1; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += OString::number(i); + + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += OUStringToOString(u, RTL_TEXTENCODING_ASCII_US); +} +void f3(OUString aStr, int nFirstContent) +{ + OUString aFirstStr = aStr.copy(0, nFirstContent); + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + aFirstStr += "..."; +} +OUString side_effect(); +void f4(int i) +{ + OUString s1; + OUString s2("xxx"); + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += "xxx"; + ++i; + // any other kind of statement breaks the chain (at least for now) + s2 += "xxx"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s2 += side_effect(); + s1 += "yyy"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s1 += "yyy"; +} +} + +namespace test2 +{ +void f(OUString s3) +{ + s3 += "xxx"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s3 += "xxx"; +} +void g(OString s3) +{ + s3 += "xxx"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s3 += "xxx"; +} +} + +namespace test3 +{ +struct Bar +{ + OUString m_field; +}; +void f(Bar b1, Bar& b2, Bar* b3) +{ + OUString s3 = "xxx"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s3 += b1.m_field; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s3 += b2.m_field; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s3 += b3->m_field; +} +OUString side_effect(); +void f2(OUString s) +{ + OUString sRet = "xxx"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + sRet += side_effect(); + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + sRet += "xxx"; + sRet += side_effect(); + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + sRet += "xxx"; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + sRet += "xxx"; + sRet += s; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + sRet += "xxx"; +} +} + +// no warning expected +namespace test4 +{ +OUString side_effect(); +void f() +{ + OUString sRet = "xxx"; +#if OSL_DEBUG_LEVEL > 0 + sRet += ";"; +#endif + sRet += " "; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + sRet += side_effect(); +} +} + +// no warning expected +namespace test5 +{ +OUString side_effect(); +void f() +{ + OUString sRet = side_effect(); + sRet += side_effect(); +} +} + +namespace test6 +{ +void f(OUString sComma, OUString maExtension, int mnDocumentIconID) +{ + OUString sValue; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + sValue += sComma + sComma + maExtension + sComma; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + sValue += OUString::number(mnDocumentIconID) + sComma; +} +struct Foo +{ + OUString sFormula1; +}; +void g(int x, const Foo& aValidation) +{ + OUString sCondition; + switch (x) + { + case 1: + sCondition += "cell-content-is-in-list("; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + sCondition += aValidation.sFormula1 + ")"; + } +} +} + +// --------------------------------------------------------------- +// detecting OUString temporary construction in + + +namespace test9 +{ +OUString getByValue(); +const OUString& getByRef(); +void f1(OUString s, OUString t, int i, const char* pChar) +{ + // no warning expected + t = t + "xxx"; + // expected-error-re@+1 {{rather use O[U]String::Concat than constructing 'rtl::OUString' from 'const char{{ ?}}[4]' on RHS of + (where LHS is of type 'rtl::OUString') [loplugin:stringadd]}} + s = s + OUString("xxx"); + // expected-error@+1 {{rather use O[U]String::Concat than constructing 'rtl::OUString' from 'const rtl::OUString' on RHS of + (where LHS is of type 'rtl::OUString') [loplugin:stringadd]}} + s = s + OUString(getByRef()); + + // no warning expected + OUString a; + a = a + getByValue(); + + // no warning expected + OUString b; + b = b + (i == 1 ? "aaa" : "bbb"); + + // no warning expected + OUString c; + c = c + OUString(pChar, strlen(pChar), RTL_TEXTENCODING_UTF8); + + OUStringBuffer buf; + // expected-error@+1 {{chained append, rather use single append call and + operator [loplugin:stringadd]}} + buf.append(" ").append(b); +} +void f2(char ch) +{ + OString s; + // expected-error-re@+1 {{rather use O[U]String::Concat than constructing 'rtl::OString' from 'const char{{ ?}}[4]' on RHS of + (where LHS is of type 'rtl::OString') [loplugin:stringadd]}} + s = s + OString("xxx"); + // expected-error@+1 {{rather use O[U]String::Concat than constructing 'rtl::OString' from 'char' on RHS of + (where LHS is of type 'rtl::OString') [loplugin:stringadd]}} + s = s + OString(ch); +} +} + +namespace test10 +{ +struct C +{ + OString constStringFunction(int) const; + OString nonConstStringFunction(); + int constIntFunction() const; + int nonConstIntFunction(); +}; + +C getC(); + +void f1(C c) +{ + OString s; + // expected-error@+1 {{simplify by merging with the preceding assignment [loplugin:stringadd]}} + s += c.constStringFunction(c.constIntFunction()); + s += c.constStringFunction(c.nonConstIntFunction()); + s += c.nonConstStringFunction(); + s += getC().constStringFunction(c.constIntFunction()); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringbuffer.cxx b/compilerplugins/clang/test/stringbuffer.cxx new file mode 100644 index 000000000..929eb4782 --- /dev/null +++ b/compilerplugins/clang/test/stringbuffer.cxx @@ -0,0 +1,22 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" +#include "rtl/string.hxx" +#include "rtl/ustring.hxx" +#include "rtl/ustrbuf.hxx" + +void func2(OUString s1, OUString s2) +{ + OUStringBuffer buf; + buf.append(s1 + s2); + // expected-error@-1 {{appending added result of OUString to OUStringBuffer, rather do .append(x).append(y) [loplugin:stringbuffer]}} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringconcatauto.cxx b/compilerplugins/clang/test/stringconcatauto.cxx new file mode 100644 index 000000000..678d12dd6 --- /dev/null +++ b/compilerplugins/clang/test/stringconcatauto.cxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include + +void foo() +{ + auto str1 = "str1" + OUString::number(10); + // expected-error-re@-1 {{creating a variable of type {{.+}} will make it reference temporaries}} + // expected-note@-2 {{use OUString instead}} + OUString str2 = "str2" + OUString::number(20) + "ing"; + const auto& str3 = "str3" + OUString::number(30); + // expected-error-re@-1 {{creating a variable of type {{.+}} will make it reference temporaries}} + // expected-note@-2 {{use OUString instead}} + const auto str4 = "str4" + OString::number(40); + // expected-error-re@-1 {{creating a variable of type {{.+}} will make it reference temporaries}} + // expected-note@-2 {{use OString instead}} + auto str5 = OUString::number(50); + (void)str1; + (void)str2; + (void)str3; + (void)str4; + (void)str5; +} + +struct A +{ + auto bar() + // expected-error-re@-1 {{returning a variable of type {{.+}} will make it reference temporaries}} + // expected-note@-2 {{use OString instead}} + { + return "bar" + OString::number(110); + } + auto baz() { return OString::number(120); } +}; + +template void fun(const T& par) +// parameters are without warnings +{ + const T& var = par; + // expected-error-re@-1 {{creating a variable of type 'const rtl::OUStringConcat<{{.*}}> &' will make it reference temporaries}} + // expected-note@-2 {{use OUString instead}} + (void)var; +} + +void testfun() { fun("fun" + OUString::number(200)); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/test/stringconcatliterals.cxx b/compilerplugins/clang/test/stringconcatliterals.cxx new file mode 100644 index 000000000..8b390f28f --- /dev/null +++ b/compilerplugins/clang/test/stringconcatliterals.cxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include + +#pragma clang diagnostic ignored "-Wunknown-warning-option" // for Clang < 13 +#pragma clang diagnostic ignored "-Wunused-but-set-variable" + +#define FOO "foo" +#define FOOu u"foo" + +void f(std::ostream& s1) +{ + static constexpr char foo[] = "foo"; + static constexpr char16_t foou[] = u"foo"; + s1 << "foo" + << "foo"; + // expected-error@-1 {{replace '<<' between string literals with juxtaposition}} + s1 << "foo" << FOO; + // expected-error@-1 {{replace '<<' between string literals with juxtaposition}} + s1 << "foo" << foo; + s1 << "foo" << OString("foo"); + // expected-error@-1 {{replace '<<' between string literals with juxtaposition}} + s1 << "foo" << OString(FOO); + // expected-error@-1 {{replace '<<' between string literals with juxtaposition}} + s1 << "foo" << OString(foo); + s1 << "foo" << OUString("foo"); + // expected-error@-1 {{replace '<<' between string literals with juxtaposition}} + s1 << "foo" << OUString(FOO); + // expected-error@-1 {{replace '<<' between string literals with juxtaposition}} + s1 << "foo" << OUString(foo); + OString s2; + s2 = "foo" + OString("foo"); + // expected-error@-1 {{replace '+' between string literals with juxtaposition}} + s2 = "foo" + OString(FOO); + // expected-error@-1 {{replace '+' between string literals with juxtaposition}} + s2 = "foo" + OString(foo); + s2 = "foo" + OStringLiteral("foo"); + // expected-error@-1 {{replace '+' between string literals with juxtaposition}} + s2 = "foo" + OStringLiteral(FOO); + // expected-error@-1 {{replace '+' between string literals with juxtaposition}} + s2 = "foo" + OStringLiteral(foo); + OUString s3; + s3 = "foo" + OUString("foo"); + // expected-error@-1 {{replace '+' between string literals with juxtaposition}} + s3 = "foo" + OUString(FOO); + // expected-error@-1 {{replace '+' between string literals with juxtaposition}} + s3 = "foo" + OUString(foo); + s3 = "foo" + OUStringLiteral(u"foo"); + // expected-error@-1 {{replace '+' between string literals with juxtaposition}} + s3 = "foo" + OUStringLiteral(FOOu); + // expected-error@-1 {{replace '+' between string literals with juxtaposition}} + s3 = "foo" + OUStringLiteral(foou); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringconstant.cxx b/compilerplugins/clang/test/stringconstant.cxx new file mode 100644 index 000000000..02f83b531 --- /dev/null +++ b/compilerplugins/clang/test/stringconstant.cxx @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" + +#include + +#include "com/sun/star/uno/Reference.hxx" +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" + +extern void foo(OUString const &); + +struct Foo { + Foo(OUString const &, int) {} + Foo(OUString const &) {} + void foo(OUString const &) const {} +}; + +struct Foo2 { + Foo2(OString const &, int) {} + Foo2(OString const &) {} + void foo(OString const &) const {} +}; + +OString ret1() { + return OString("foo"); // expected-error {{elide constructor call [loplugin:stringconstant]}} +} + +OString const ret2() { + return OString("foo"); // expected-error {{elide constructor call [loplugin:stringconstant]}} +} + +auto ret3() { + return OString("foo"); +} + +OUString ret4() { + return OUString("foo"); // expected-error {{elide constructor call [loplugin:stringconstant]}} +} + +OUString const ret5() { + return OUString("foo"); // expected-error {{elide constructor call [loplugin:stringconstant]}} +} + +auto ret6() { + return OUString("foo"); +} + +int main() { + char const s1[] = "foo"; + char const * const s2 = "foo"; + + OStringBuffer sb; + + sb.append(OString()); // expected-error {{in call of 'rtl::OStringBuffer::append', replace empty 'OString' constructor with empty string literal [loplugin:stringconstant]}} + sb.append(OString("foo")); // expected-error {{in call of 'rtl::OStringBuffer::append', elide explicit 'OString' constructor [loplugin:stringconstant]}} + sb.append(OString(s1)); // expected-error {{in call of 'rtl::OStringBuffer::append', elide explicit 'OString' constructor [loplugin:stringconstant]}} + sb.append(OString(s2)); // expected-error {{in call of 'rtl::OStringBuffer::append', elide explicit 'OString' constructor, and turn the non-array string constant into an array [loplugin:stringconstant]}} + sb.append(OString("foo", std::strlen("foo"))); // expected-error {{in call of 'rtl::OStringBuffer::append', elide explicit 'OString' constructor [loplugin:stringconstant]}} + sb.append(OString(s1, std::strlen(s1))); // expected-error {{in call of 'rtl::OStringBuffer::append', elide explicit 'OString' constructor [loplugin:stringconstant]}} + sb.append(OString(s2, std::strlen(s2))); // expected-error {{in call of 'rtl::OStringBuffer::append', elide explicit 'OString' constructor, and turn the non-array string constant into an array [loplugin:stringconstant]}} + sb.append("foo"); + sb.append(s1); + sb.append(s2); // expected-error {{in call of 'rtl::OStringBuffer::append' with non-array string constant argument, turn the non-array string constant into an array [loplugin:stringconstant]}} + sb.append("foo", std::strlen("foo")); // expected-error {{rewrite call of 'rtl::OStringBuffer::append' with string constant and matching length arguments as call of 'rtl::OStringBuffer::append' [loplugin:stringconstant]}} + sb.append(s1, 3/*std::strlen(s1)*/); // expected-error {{rewrite call of 'rtl::OStringBuffer::append' with string constant and matching length arguments as call of 'rtl::OStringBuffer::append' [loplugin:stringconstant]}} + sb.append(s2, 3/*std::strlen(s2)*/); // expected-error {{rewrite call of 'rtl::OStringBuffer::append' with string constant and matching length arguments as call of 'rtl::OStringBuffer::append', and turn the non-array string constant into an array [loplugin:stringconstant]}} + + sb.insert(0, OString()); // expected-error {{in call of 'rtl::OStringBuffer::insert', replace empty 'OString' constructor with empty string literal [loplugin:stringconstant]}} + sb.insert(0, OString("foo")); // expected-error {{in call of 'rtl::OStringBuffer::insert', elide explicit 'OString' constructor [loplugin:stringconstant]}} + sb.insert(0, OString(s1)); // expected-error {{in call of 'rtl::OStringBuffer::insert', elide explicit 'OString' constructor [loplugin:stringconstant]}} + sb.insert(0, OString(s2)); // expected-error {{in call of 'rtl::OStringBuffer::insert', elide explicit 'OString' constructor, and turn the non-array string constant into an array [loplugin:stringconstant]}} + sb.insert(0, OString("foo", std::strlen("foo"))); // expected-error {{in call of 'rtl::OStringBuffer::insert', elide explicit 'OString' constructor [loplugin:stringconstant]}} + sb.insert(0, OString(s1, std::strlen(s1))); // expected-error {{in call of 'rtl::OStringBuffer::insert', elide explicit 'OString' constructor [loplugin:stringconstant]}} + sb.insert(0, OString(s2, std::strlen(s2))); // expected-error {{in call of 'rtl::OStringBuffer::insert', elide explicit 'OString' constructor, and turn the non-array string constant into an array [loplugin:stringconstant]}} + sb.insert(0, "foo"); + sb.insert(0, s1); + sb.insert(0, s2); // expected-error {{in call of 'rtl::OStringBuffer::insert' with non-array string constant argument, turn the non-array string constant into an array [loplugin:stringconstant]}} + sb.insert(0, "foo", std::strlen("foo")); // expected-error {{rewrite call of 'rtl::OStringBuffer::insert' with string constant and matching length arguments as call of 'rtl::OStringBuffer::insert' [loplugin:stringconstant]}} + sb.insert(0, s1, 3/*std::strlen(s1)*/); // expected-error {{rewrite call of 'rtl::OStringBuffer::insert' with string constant and matching length arguments as call of 'rtl::OStringBuffer::insert' [loplugin:stringconstant]}} + sb.insert(0, s2, 3/*std::strlen(s2)*/); // expected-error {{rewrite call of 'rtl::OStringBuffer::insert' with string constant and matching length arguments as call of 'rtl::OStringBuffer::insert', and turn the non-array string constant into an array [loplugin:stringconstant]}} + + foo(OUString("xxx")); // expected-error {{in call of 'foo', replace 'OUString' constructed from a string literal directly with the string literal [loplugin:stringconstant}} + Foo aFoo(OUString("xxx"), 1); // expected-error {{in call of 'Foo::Foo', replace 'OUString' constructed from a string literal directly with the string literal}} + (void)aFoo; + Foo aFoo2(OUString("xxx")); // expected-error {{in call of 'Foo::Foo', replace 'OUString' constructed from a string literal directly with the string literal}} + aFoo2.foo(OUString("xxx")); // expected-error {{in call of 'Foo::foo', replace 'OUString' constructed from a string literal directly with the string literal}} + + Foo2 aFoo3(OString("xxx")); // expected-error {{in call of 'Foo2::Foo2', replace 'OUString' constructed from a string literal directly with the string literal}} + aFoo3.foo(OString("xxx")); // expected-error {{in call of 'Foo2::foo', replace 'OUString' constructed from a string literal directly with the string literal}} + + (void) OUString("xxx", 3, RTL_TEXTENCODING_ASCII_US); // expected-error {{simplify construction of 'OUString' with string constant argument [loplugin:stringconstant]}} + (void) OUString("xxx", 3, RTL_TEXTENCODING_ISO_8859_1); // expected-error {{suspicious 'rtl::OUString' constructor with text encoding 12 but plain ASCII content; use 'RTL_TEXTENCODING_ASCII_US' instead [loplugin:stringconstant]}} + (void) OUString("x\xA0x", 3, RTL_TEXTENCODING_ISO_8859_1); + + (void) OUString("xxx", 2, RTL_TEXTENCODING_ASCII_US); // expected-error {{suspicious 'rtl::OUString' constructor with literal of length 3 and non-matching length argument 2 [loplugin:stringconstant]}} + +#if !defined __cpp_char8_t + (void) OUString(u8"xxx", 3, RTL_TEXTENCODING_ASCII_US); // expected-error {{simplify construction of 'OUString' with string constant argument [loplugin:stringconstant]}} +#endif + + (void) OUString("\x80", 1, RTL_TEXTENCODING_UTF8); // expected-error {{suspicious 'rtl::OUString' constructor with text encoding 'RTL_TEXTENCODING_UTF8' but non-UTF-8 content [loplugin:stringconstant]}} + + (void) OUString("\xC2\x80", 2, RTL_TEXTENCODING_UTF8); // expected-error {{simplify construction of 'OUString' with UTF-8 content as OUString(u"\u0080") [loplugin:stringconstant]}} + + OUString().reverseCompareTo(OUString()); // expected-error {{in call of 'rtl::OUString::reverseCompareTo', replace default-constructed 'OUString' with an empty string literal [loplugin:stringconstant]}} + + OUStringBuffer ub; + ub.append(""); // expected-error {{call of 'rtl::OUStringBuffer::append' with suspicious empty string constant argument [loplugin:stringconstant]}} + ub.append("foo\0bar"); // expected-error {{call of 'rtl::OUStringBuffer::append' with string constant argument containing embedded NULLs [loplugin:stringconstant]}} + ub.append("foo\x80" "bar"); // expected-error {{call of 'rtl::OUStringBuffer::append' with string constant argument containing non-ASCII characters [loplugin:stringconstant]}} + char const sc1[] = ""; + ub.append(sc1); // expected-error {{call of 'rtl::OUStringBuffer::append' with suspicious empty string constant argument [loplugin:stringconstant]}} + char const sc2[] = "foo\0bar"; + ub.append(sc2); // expected-error {{call of 'rtl::OUStringBuffer::append' with string constant argument containing embedded NULLs [loplugin:stringconstant]}} + char const sc3[] = "foo\x80" "bar"; + ub.append(sc3); // expected-error {{call of 'rtl::OUStringBuffer::append' with string constant argument containing non-ASCII characters [loplugin:stringconstant]}} + char const sc4[] = {'f', 'o', 'o', 'b', 'a', 'r'}; + ub.append(sc4); // expected-error {{call of 'rtl::OUStringBuffer::append' with string constant argument lacking a terminating NULL [loplugin:stringconstant]}} + ub.append(static_cast(sc1)); + ub.append(static_cast(sc2)); // at runtime: append "foo" + ub.append(static_cast(sc3)); // at runtime: assert + ub.append(static_cast(sc4)); // at runtime: UB +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringliteraldefine.cxx b/compilerplugins/clang/test/stringliteraldefine.cxx new file mode 100644 index 000000000..ba5f718ed --- /dev/null +++ b/compilerplugins/clang/test/stringliteraldefine.cxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include + +void f(OUString const&); + +void f1() +{ +// expected-error@+1 {{change macro 'XXX' to 'constexpr OUStringLiteral' [loplugin:stringliteraldefine]}} +#define XXX "xxx" + + // expected-note@+1 {{macro used here [loplugin:stringliteraldefine]}} + f(OUString(XXX)); + + // FIXME no warning expected + //#define FOO f(OUString("xxx")) + // FOO; +} + +void f2() +{ + struct DataFlavorRepresentation + { + OUString pMimeType; + }; + +// expected-error@+1 {{change macro 'MIMETYPE_VND_SUN_XML_WRITER_ASCII' to 'constexpr OUStringLiteral' [loplugin:stringliteraldefine]}} +#define MIMETYPE_VND_SUN_XML_WRITER_ASCII "xxx" + static const DataFlavorRepresentation aInstance[] = { + // expected-note@+1 {{macro used here [loplugin:stringliteraldefine]}} + { MIMETYPE_VND_SUN_XML_WRITER_ASCII }, + }; +} + +void f3() +{ +// expected-error@+1 {{change macro 'YYY' to 'constexpr OUStringLiteral' [loplugin:stringliteraldefine]}} +#define YYY "yyy" + + // expected-note@+1 {{macro used here [loplugin:stringliteraldefine]}} + f(YYY); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringliteralvar.cxx b/compilerplugins/clang/test/stringliteralvar.cxx new file mode 100644 index 000000000..b79ee95a0 --- /dev/null +++ b/compilerplugins/clang/test/stringliteralvar.cxx @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include + +// expected-error-re@+1 {{change type of variable 'literal1' from constant character array ('const char{{ ?}}[4]') to OStringLiteral [loplugin:stringliteralvar]}} +char const literal1[] = "foo"; +OString f1() +{ + // expected-note@+1 {{first passed into a 'rtl::OString' constructor here [loplugin:stringliteralvar]}} + return literal1; +} + +void f(OUString const&); +void f2() +{ + // expected-error-re@+1 {{change type of variable 'literal' from constant character array ('const char{{ ?}}[4]') to OUStringLiteral, and make it static [loplugin:stringliteralvar]}} + char const literal[] = "foo"; + // expected-note@+1 {{first passed into a 'rtl::OUString' constructor here [loplugin:stringliteralvar]}} + f(literal); +} + +struct S3 +{ + // expected-error-re@+1 {{change type of variable 'literal' from constant character array ('const char16_t{{ ?}}[4]') to OUStringLiteral [loplugin:stringliteralvar]}} + static constexpr char16_t literal[] = u"foo"; +}; +void f3() +{ + // expected-note@+1 {{first passed into a 'rtl::OUString' constructor here [loplugin:stringliteralvar]}} + f(S3::literal); +} + +std::vector f4() +{ + // expected-error-re@+1 {{change type of variable 'literal' from constant character array ('const char16_t{{ ?}}[4]') to OUStringLiteral [loplugin:stringliteralvar]}} + static constexpr char16_t literal[] = u"foo"; + // expected-note@+1 {{first passed into a 'rtl::OUString' constructor here [loplugin:stringliteralvar]}} + return { literal }; +} + +void f5() +{ + // expected-error@+1 {{variable 'literal' of type 'const rtl::OUStringLiteral<4>' with automatic storage duration most likely needs to be static [loplugin:stringliteralvar]}} + OUStringLiteral const literal = u"foo"; + // expected-note@+1 {{first converted to 'rtl::OUString' here [loplugin:stringliteralvar]}} + f(literal); +} + +void f6() +{ + // expected-error@+1 {{variable 'literal' of type 'const rtl::OUStringLiteral<4>' with automatic storage duration most likely needs to be static [loplugin:stringliteralvar]}} + constexpr OUStringLiteral literal = u"foo"; + // expected-note@+1 {{first converted to 'rtl::OUString' here [loplugin:stringliteralvar]}} + f(literal); +} + +void f7() +{ + static constexpr OUStringLiteral const literal = u"foo"; + f(literal); +} + +void f8() +{ + static constexpr OUStringLiteral const literal = u"foo"; + // expected-error@+1 {{variable 'literal' of type 'const rtl::OUStringLiteral<4>' suspiciously used in a sizeof expression [loplugin:stringliteralvar]}} + (void)sizeof literal; +} + +void f9() +{ + // expected-error-re@+1 {{change type of variable 'literal' from constant character array ('const sal_Unicode{{ ?}}[3]'{{( \(aka 'const char16_t\[3\]'\))?}}) to OUStringLiteral [loplugin:stringliteralvar]}} + static sal_Unicode const literal[] = { 'f', 'o', 'o' }; + // expected-note@+1 {{first passed into a 'rtl::OUString' constructor here [loplugin:stringliteralvar]}} + f(OUString(literal, SAL_N_ELEMENTS(literal))); +} + +void f10() +{ + // expected-error-re@+1 {{change type of variable 'literal' from constant character array ('const sal_Unicode{{ ?}}[3]'{{( \(aka 'const char16_t\[3\]'\))?}}) to OUStringLiteral [loplugin:stringliteralvar]}} + static sal_Unicode const literal[] = { 'f', 'o', 'o' }; + // expected-note@+1 {{first passed into a 'rtl::OUString' constructor here [loplugin:stringliteralvar]}} + f(OUString(literal, 3)); +} + +void f11(int nStreamType) +{ + // expected-error-re@+1 {{change type of variable 'sDocumentType' from constant character array ('const char{{ ?}}[4]') to OUStringLiteral, and make it static [loplugin:stringliteralvar]}} + const char sDocumentType[] = "foo"; + OUString sStreamType; + switch (nStreamType) + { + case 1: + // expected-note@+1 {{first assigned here [loplugin:stringliteralvar]}} + sStreamType = sDocumentType; + break; + } + (void)sStreamType; +} + +extern sal_Unicode const extarr[1]; + +sal_Unicode init(); + +void f12() +{ + // Suppress warnings if the array contains a malformed sequence of UTF-16 code units...: + static sal_Unicode const arr1[] = { 0xD800 }; + f(OUString(arr1, 1)); + // ...Or potentially contains a malformed sequence of UTF-16 code units...: + f(OUString(extarr, 1)); + sal_Unicode const arr2[] = { init() }; + f(OUString(arr2, 1)); + // ...But generate a warning if the array contains a well-formed sequence of UTF-16 code units + // containing surrogates: + // expected-error-re@+1 {{change type of variable 'arr3' from constant character array ('const sal_Unicode{{ ?}}[2]'{{( \(aka 'const char16_t\[2\]'\))?}}) to OUStringLiteral [loplugin:stringliteralvar]}} + static sal_Unicode const arr3[] = { 0xD800, 0xDC00 }; + // expected-note-re@+1 {{first passed into a '{{(rtl::)?}}OUString' constructor here [loplugin:stringliteralvar]}} + f(OUString(arr3, 2)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringloop.cxx b/compilerplugins/clang/test/stringloop.cxx new file mode 100644 index 000000000..7a02cd9ce --- /dev/null +++ b/compilerplugins/clang/test/stringloop.cxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" +#include "rtl/string.hxx" +#include "rtl/ustring.hxx" + +#pragma clang diagnostic ignored "-Wunknown-warning-option" // for Clang < 13 +#pragma clang diagnostic ignored "-Wunused-but-set-variable" + +struct Foo +{ + OUString m_field; // expected-note {{field here [loplugin:stringloop]}} + void func1() + { + for (int i = 0; i < 10; ++i) + m_field += "xxx"; + // expected-error@-1 {{appending to OUString in loop, rather use OUStringBuffer [loplugin:stringloop]}} + // no warning expected + m_field += "xxx"; + } +}; + +void func2() +{ + OUString s; // expected-note {{var here [loplugin:stringloop]}} + for (int i = 0; i < 10; ++i) + s += "xxx"; // expected-error {{appending to OUString in loop, rather use OUStringBuffer [loplugin:stringloop]}} + + // no warning expected + OUString s2; + s2 += "xxx"; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringstatic.cxx b/compilerplugins/clang/test/stringstatic.cxx new file mode 100644 index 000000000..3c26d961c --- /dev/null +++ b/compilerplugins/clang/test/stringstatic.cxx @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include "stringstatic.hxx" + +// expected-error@+1 {{rather declare this using OUStringLiteral/OStringLiteral/char[] [loplugin:stringstatic]}} +static const OUString TEST1 = "xxx"; + +void f(rtl_uString const*); + +void test2() +{ + // expected-error@+1 {{rather declare this using OUStringLiteral/OStringLiteral/char[] [loplugin:stringstatic]}} + static const OUString XXX = "xxx"; + // expected-error@+1 {{rather declare this using OUStringLiteral/OStringLiteral/char[] [loplugin:stringstatic]}} + static const OUString XXX2 = "xxx"; + (void)XXX; + (void)XXX2; + static const OUString DATA = "xxx"; + f(DATA.pData); +} diff --git a/compilerplugins/clang/test/stringstatic.hxx b/compilerplugins/clang/test/stringstatic.hxx new file mode 100644 index 000000000..ec82a8bf5 --- /dev/null +++ b/compilerplugins/clang/test/stringstatic.hxx @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" + +#include "rtl/ustring.hxx" + +OUString const INCLUDED = "xxx"; + +inline void f() +{ + // expected-error@+1 {{rather declare this using OUStringLiteral/OStringLiteral/char[] [loplugin:stringstatic]}} + static OUString const XXX = "xxx"; + (void)XXX; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringview-c++03.cxx b/compilerplugins/clang/test/stringview-c++03.cxx new file mode 100644 index 000000000..1824ac9d0 --- /dev/null +++ b/compilerplugins/clang/test/stringview-c++03.cxx @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +// expected-no-diagnostics + +rtl::OUStringBuffer nowarn(rtl::OUStringBuffer const& s, sal_Int32 n) +{ + return s.copy(n, s.getLength() - n); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringview.cxx b/compilerplugins/clang/test/stringview.cxx new file mode 100644 index 000000000..398f14b3d --- /dev/null +++ b/compilerplugins/clang/test/stringview.cxx @@ -0,0 +1,221 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +void call_view(std::u16string_view) {} +void call_view(std::string_view) {} +struct ConstructWithView +{ + ConstructWithView(std::u16string_view) {} + ConstructWithView(std::string_view) {} +}; + +namespace test1 +{ +void f1(std::u16string_view s1) +{ + // no warning expected + call_view(s1); +} +void f1(std::string_view s1) +{ + // no warning expected + call_view(s1); +} +void f1(OUString s1) +{ + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + call_view(s1.copy(1, 2)); + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + call_view(s1.copy(1)); + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + ConstructWithView(s1.copy(1, 2)); + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + ConstructWithView(s1.copy(1)); +} +void f1(OString s1) +{ + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + call_view(s1.copy(1, 2)); + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + call_view(s1.copy(1)); + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + ConstructWithView(s1.copy(1, 2)); + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + ConstructWithView(s1.copy(1)); +} +void f1(OUStringBuffer s1) +{ + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + call_view(s1.copy(1, 2)); + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + call_view(s1.copy(1)); + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + ConstructWithView(s1.copy(1, 2)); + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + ConstructWithView(s1.copy(1)); + // expected-error@+1 {{rather than call toString, pass with a view [loplugin:stringview]}} + call_view(s1.toString()); + // expected-error@+1 {{rather than call toString, pass with a view [loplugin:stringview]}} + ConstructWithView(s1.toString()); +} +void f1(OStringBuffer s1) +{ + // expected-error@+1 {{rather than call toString, pass with a view [loplugin:stringview]}} + call_view(s1.toString()); + // expected-error@+1 {{rather than call toString, pass with a view [loplugin:stringview]}} + ConstructWithView(s1.toString()); +} +void makeStringAndClear(OUStringBuffer s) +{ + call_view(s.makeStringAndClear()); + ConstructWithView(s.makeStringAndClear()); + call_view((&s)->makeStringAndClear()); + ConstructWithView((&s)->makeStringAndClear()); + // expected-error@+1 {{rather than call makeStringAndClear on an rvalue, pass with a view [loplugin:stringview]}} + call_view(std::move(s).makeStringAndClear()); + // expected-error@+1 {{rather than call makeStringAndClear on an rvalue, pass with a view [loplugin:stringview]}} + ConstructWithView(std::move(s).makeStringAndClear()); + // expected-error@+1 {{rather than call makeStringAndClear on an rvalue, pass with a view [loplugin:stringview]}} + call_view((s).copy(1).makeStringAndClear()); + // expected-error@+1 {{rather than call makeStringAndClear on an rvalue, pass with a view [loplugin:stringview]}} + ConstructWithView(s.copy(1).makeStringAndClear()); +} +void makeStringAndClear(OStringBuffer s) +{ + call_view(s.makeStringAndClear()); + ConstructWithView(s.makeStringAndClear()); + call_view((&s)->makeStringAndClear()); + ConstructWithView((&s)->makeStringAndClear()); + // expected-error@+1 {{rather than call makeStringAndClear on an rvalue, pass with a view [loplugin:stringview]}} + call_view(std::move(s).makeStringAndClear()); + // expected-error@+1 {{rather than call makeStringAndClear on an rvalue, pass with a view [loplugin:stringview]}} + ConstructWithView(std::move(s).makeStringAndClear()); +} +} + +namespace test2 +{ +void f3(OUString s1) +{ + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + OUString s2 = s1.copy(1, 2) + "xxx"; + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + s2 = s1.copy(1) + "xxx"; + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + s2 = "xxx" + s1.copy(1); + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + s2 += s1.copy(1); + (void)s2; +} +void f3(OString s1) +{ + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + OString s2 = s1.copy(1, 2) + "xxx"; + (void)s2; + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + OString s3 = s1.copy(1) + "xxx"; + (void)s3; +} +} + +namespace test3 +{ +void f4(OUString s1, OUString s2) +{ + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + sal_Unicode x = s2.copy(1, 2)[12]; + (void)x; + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + if (s2.copy(1, 2) < s1) + ; +} +} + +void f5(char const* s1, sal_Int32 n1, char16_t const* s2, sal_Int32 n2, OString s3, OUString s4) +{ + // expected-error@+1 {{instead of an 'rtl::OString', pass a 'std::string_view' [loplugin:stringview]}} + call_view(OString()); + // expected-error-re@+1 {{instead of an 'rtl::OString' constructed from a 'const char{{ ?}}[4]', pass a 'std::string_view' [loplugin:stringview]}} + call_view(OString("foo")); + // expected-error@+1 {{instead of an 'rtl::OString' constructed from a 'const char', pass a 'std::string_view' (or an 'rtl::OStringChar') [loplugin:stringview]}} + call_view(OString(*s1)); + // expected-error@+1 {{instead of an 'rtl::OString' constructed from a 'const char *', pass a 'std::string_view' [loplugin:stringview]}} + call_view(OString(s1)); + // expected-error@+1 {{instead of an 'rtl::OString' constructed from a 'const char *', pass a 'std::string_view' [loplugin:stringview]}} + call_view(OString(s1, n1)); + constexpr OStringLiteral l1("foo"); + // expected-error@+1 {{instead of an 'rtl::OString' constructed from a 'const rtl::OStringLiteral<4>', pass a 'std::string_view' [loplugin:stringview]}} + call_view(OString(l1)); + // expected-error@+1 {{instead of an 'rtl::OString' constructed from a 'std::string_view' (aka 'basic_string_view'), pass a 'std::string_view' [loplugin:stringview]}} + call_view(OString(std::string_view("foo"))); + // expected-error@+1 {{instead of an 'rtl::OString' constructed from a 'OStringNumber', pass a 'std::string_view' [loplugin:stringview]}} + call_view(OString(OString::number(0))); + // expected-error-re@+1 {{instead of an 'rtl::OString' constructed from a 'typename std::enable_if_t::allowOStringConcat && ToStringHelper::allowOStringConcat, OStringConcat{{ ?}}>' (aka 'rtl::OStringConcat'), pass a 'std::string_view' via 'rtl::OStringConcatenation' [loplugin:stringview]}} + call_view(OString(s3 + s3)); + // expected-error@+1 {{instead of an 'rtl::OUString', pass a 'std::u16string_view' [loplugin:stringview]}} + call_view(OUString()); + // expected-error-re@+1 {{instead of an 'rtl::OUString' constructed from a 'const char{{ ?}}[4]', pass a 'std::u16string_view' [loplugin:stringview]}} + call_view(OUString("foo")); + // expected-error-re@+1 {{instead of an 'rtl::OUString' constructed from a 'const char16_t{{ ?}}[4]', pass a 'std::u16string_view' [loplugin:stringview]}} + call_view(OUString(u"foo")); + // expected-error@+1 {{instead of an 'rtl::OUString' constructed from a 'const char', pass a 'std::u16string_view' (or an 'rtl::OUStringChar') [loplugin:stringview]}} + call_view(OUString(*s1)); + // expected-error@+1 {{instead of an 'rtl::OUString' constructed from a 'const char16_t', pass a 'std::u16string_view' (or an 'rtl::OUStringChar') [loplugin:stringview]}} + call_view(OUString(*s2)); + // expected-error@+1 {{instead of an 'rtl::OUString' constructed from a 'const char16_t *', pass a 'std::u16string_view' [loplugin:stringview]}} + call_view(OUString(s2)); + // expected-error@+1 {{instead of an 'rtl::OUString' constructed from a 'const char16_t *', pass a 'std::u16string_view' [loplugin:stringview]}} + call_view(OUString(s2, n2)); + // expected-error@+1 {{instead of an 'rtl::OUString' constructed from a 'const char16_t *', pass a 'std::u16string_view' (or an 'rtl::OUStringChar') [loplugin:stringview]}} + call_view(OUString(s2, 1)); + constexpr OUStringLiteral l2(u"foo"); + // expected-error@+1 {{instead of an 'rtl::OUString' constructed from a 'const rtl::OUStringLiteral<4>', pass a 'std::u16string_view' [loplugin:stringview]}} + call_view(OUString(l2)); + // expected-error@+1 {{instead of an 'rtl::OUString' constructed from a 'std::u16string_view' (aka 'basic_string_view'), pass a 'std::u16string_view' [loplugin:stringview]}} + call_view(OUString(std::u16string_view(u"foo"))); + // expected-error@+1 {{instead of an 'rtl::OUString' constructed from a 'OUStringNumber', pass a 'std::u16string_view' [loplugin:stringview]}} + call_view(OUString(OUString::number(0))); + // expected-error-re@+1 {{instead of an 'rtl::OUString' constructed from a 'typename std::enable_if_t::allowOUStringConcat && ToStringHelper::allowOUStringConcat, OUStringConcat{{ ?}}>' (aka 'rtl::OUStringConcat'), pass a 'std::u16string_view' via 'rtl::OUStringConcatenation' [loplugin:stringview]}} + call_view(OUString(s4 + s4)); + + (void)(s3 == l1); + (void)(s4 == l2); +} + +void f5(OUString s) +{ + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + OUStringBuffer buf(s.copy(5)); + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + buf = s.copy(5); + // expected-error@+1 {{rather than copy, pass with a view using subView() [loplugin:stringview]}} + buf.append(s.copy(12)); + // expected-error@+1 {{instead of an 'rtl::OUString' constructed from a 'std::u16string_view' (aka 'basic_string_view'), pass a 'std::u16string_view' [loplugin:stringview]}} + buf.append(OUString(std::u16string_view(u"foo"))); + // expected-error@+1 {{instead of an 'rtl::OUString' constructed from a 'std::u16string_view' (aka 'basic_string_view'), pass a 'std::u16string_view' [loplugin:stringview]}} + s += OUString(std::u16string_view(u"foo")); +} + +void f6(OUString s) +{ + // expected-error@+1 {{rather than getToken, pass with a view using o3tl::getToken() [loplugin:stringview]}} + s.getToken(1, ' ').toInt32(); +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringviewdangle.cxx b/compilerplugins/clang/test/stringviewdangle.cxx new file mode 100644 index 000000000..0a8d2aa54 --- /dev/null +++ b/compilerplugins/clang/test/stringviewdangle.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace test1 +{ +OUString foo1(); +OUString& foo2(); +void f1() +{ + // expected-error@+1 {{view pointing into temporary i.e. dangling [loplugin:stringviewdangle]}} + std::u16string_view v = foo1(); + // expected-error@+1 {{view pointing into temporary i.e. dangling [loplugin:stringviewdangle]}} + v = foo1(); + + // no warning expected + std::u16string_view v2 = foo2(); + v2 = foo2(); +} +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringviewparam.cxx b/compilerplugins/clang/test/stringviewparam.cxx new file mode 100644 index 000000000..f5f165804 --- /dev/null +++ b/compilerplugins/clang/test/stringviewparam.cxx @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#undef NDEBUG + +#include "sal/config.h" + +#include + +#include "rtl/string.hxx" +#include "rtl/ustring.hxx" +#include "rtl/ustrbuf.hxx" +#include "sal/types.h" + +void f1a(std::string_view); +// expected-error@+1 {{replace function parameter of type 'const rtl::OString &' with 'std::string_view' [loplugin:stringviewparam]}} +char f1b(OString const& s) +{ + f1a(s); + OString rest; + if (s.isEmpty() || s.startsWith("foo", &rest) || s.endsWith("foo")) + { + f1a(std::string_view(s)); + } + return s[0]; +} + +void f2a(std::u16string_view); +// expected-error@+1 {{replace function parameter of type 'const rtl::OUString &' with 'std::u16string_view' [loplugin:stringviewparam]}} +sal_Unicode f2b(OUString const& s) +{ + f2a(s); + OUString rest; + if (s.isEmpty() || s.startsWith("foo", &rest) || s.endsWith("foo")) + { + f2a(std::u16string_view(s)); + } + return s[0]; +} + +void f3a(OUString const&) {} +using F3 = void(OUString const&); +F3* f3b() { return f3a; } + +SAL_DLLPUBLIC_EXPORT void f4(OUString const&) {} + +template void f5(T const&); +template <> void f5(OUString const&) {} + +void f6([[maybe_unused]] OUString const&) {} + +bool f7( + // expected-error@+1 {{replace function parameter of type 'const rtl::OUString &' with 'std::u16string_view' [loplugin:stringviewparam]}} + const OUString& p1, + // expected-error@+1 {{replace function parameter of type 'const rtl::OUString &' with 'std::u16string_view' [loplugin:stringviewparam]}} + const OUString& p2) +{ + return p1 == p2; +} +// expected-error@+1 {{replace function parameter of type 'const rtl::OUString &' with 'std::u16string_view' [loplugin:stringviewparam]}} +bool f8(const OUString& p1, std::u16string_view p2) { return p1 == p2; } + +struct Converter +{ + // expected-error@+1 {{replace function parameter of type 'const rtl::OUString &' with 'std::u16string_view' [loplugin:stringviewparam]}} + static bool convertBool(bool& rBool, const OUString& rString) + { + rBool = rString == "true"; + return rBool || (rString == "false"); + } +}; + +void f9(std::u16string_view); +void f9(OUString const& s) { return f9(std::u16string_view(s)); } + +struct S10 +{ + S10(std::u16string_view); + S10(OUString const& s) + : S10(std::u16string_view(s)) + { + } +}; + +// expected-error@+1 {{replace function parameter of type 'const rtl::OUString &' with 'std::u16string_view' [loplugin:stringviewparam]}} +void f11(const OUString& f11rString) +{ + OUStringBuffer buf; + buf.append(f11rString); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/stringviewvar.cxx b/compilerplugins/clang/test/stringviewvar.cxx new file mode 100644 index 000000000..016f0fcc8 --- /dev/null +++ b/compilerplugins/clang/test/stringviewvar.cxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#undef NDEBUG + +#include "sal/config.h" +#include +#include "rtl/string.hxx" +#include "rtl/ustring.hxx" +#include "rtl/ustrbuf.hxx" +#include "sal/types.h" + +void f1(std::string_view sv) +{ + // expected-error@+1 {{replace var of type 'rtl::OString' with 'std::string_view' [loplugin:stringviewvar]}} + OString s1(sv); + (void)s1; +} + +void f2(const OString s1) +{ + // no warning expected + OString s2(s1); + (void)s2; +} + +std::string_view f3a(); +void f3() +{ + // expected-error@+1 {{replace var of type 'rtl::OString' with 'std::string_view' [loplugin:stringviewvar]}} + OString s1 = OString(f3a()); + (void)s1; +} + +void f4a(const OString&); +void f4(std::string_view sv) +{ + // no warning expected + OString s1(sv); + f4a(s1); +} + +void f5(std::string_view sv) +{ + // expected-error@+1 {{replace var of type 'rtl::OString' with 'std::string_view' [loplugin:stringviewvar]}} + OString s1(sv); + if (s1 == "xxxx") + f5(sv); +} + +void f6(std::u16string_view sv) +{ + // expected-error@+1 {{replace var of type 'rtl::OUString' with 'std::u16string_view' [loplugin:stringviewvar]}} + OUString s6; + s6 = sv; + (void)s6; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/trivialconstructor.cxx b/compilerplugins/clang/test/trivialconstructor.cxx new file mode 100644 index 000000000..eed26f8bf --- /dev/null +++ b/compilerplugins/clang/test/trivialconstructor.cxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +struct S1 +{ + // expected-error@+1 {{no need for explicit constructor decl [loplugin:trivialconstructor]}} + S1() {} +}; + +struct S2 +{ + S2() {} + S2(int) {} +}; + +struct S3 +{ + S3() {} + template S3(T); +}; + +template struct S4 +{ +#if !defined _MSC_VER +// expected-error@+2 {{no need for explicit constructor decl [loplugin:trivialconstructor]}} +#endif + S4() {} +}; + +template struct S5 +{ + S5() {} + S5(int); +}; + +template struct S6 +{ + S6() {} + template S6(T); +}; + +struct S7 +{ + S7(int = 0) {} +}; + +struct S8 +{ + template S8(T = 0) {} +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/trivialdestructor.cxx b/compilerplugins/clang/test/trivialdestructor.cxx new file mode 100644 index 000000000..b6ba4e968 --- /dev/null +++ b/compilerplugins/clang/test/trivialdestructor.cxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +struct S1 +{ + // expected-note@+1 {{previous declaration is here [loplugin:trivialdestructor]}} + ~S1(); +}; + +// expected-error@+1 {{no need for explicit destructor decl [loplugin:trivialdestructor]}} +S1::~S1() {} + +struct S2 +{ + // expected-note@+1 {{previous declaration is here [loplugin:trivialdestructor]}} + ~S2(); +}; + +// expected-error@+1 {{no need for explicit destructor decl [loplugin:trivialdestructor]}} +S2::~S2() = default; + +struct S3 +{ + ~S3() = delete; +}; + +struct S4 +{ + union { + int i; + float f; + }; + // expected-error@+1 {{no need for explicit destructor decl [loplugin:trivialdestructor]}} + ~S4() {} +}; + +struct Nontrivial +{ + ~Nontrivial(); +}; + +struct S5 +{ + union { + int i; + Nontrivial n; + }; + ~S5() {} +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/typedefparam.cxx b/compilerplugins/clang/test/typedefparam.cxx new file mode 100644 index 000000000..777a5128d --- /dev/null +++ b/compilerplugins/clang/test/typedefparam.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "tools/solar.h" + +namespace test1 +{ +class Foo +{ + void bar(sal_uIntPtr x); // expected-note {{declaration site here [loplugin:typedefparam]}} + sal_uIntPtr bar(); // expected-note {{declaration site here [loplugin:typedefparam]}} +}; + +void Foo::bar(sal_uLong) +// expected-error-re@-1 {{function param 1 at definition site does not match function param at declaration site, 'sal_uLong' (aka 'unsigned {{.+}}') vs 'sal_uIntPtr' (aka 'unsigned {{.+}}') [loplugin:typedefparam]}} +{ +} + +sal_uLong Foo::bar() +// expected-error-re@-1 {{function return type at definition site does not match function param at declaration site, 'sal_uLong' (aka 'unsigned {{.+}}') vs 'sal_uIntPtr' (aka 'unsigned {{.+}}') [loplugin:typedefparam]}} +{ + return 1; +} +}; + +// Carve out an exception for the "typedef struct S {...} T" idiom we use in the UNO code +namespace test2 +{ +typedef struct Foo +{ + int x; +} FooT; + +void bar(struct Foo*); + +void bar(FooT*){ + // no warning expected +}; +}; +namespace test3 +{ +typedef struct Foo +{ + int x; +} FooT; + +void bar(Foo*); + +void bar(FooT*){ + // no warning expected +}; +}; + +// check method overrides +namespace test4 +{ +struct Struct1 +{ + virtual sal_uIntPtr foo1(); + // expected-note@-1 {{super-class method here [loplugin:typedefparam]}} + virtual void foo2(sal_uIntPtr); + // expected-note@-1 {{super-class method here [loplugin:typedefparam]}} + virtual ~Struct1(); +}; +struct Struct2 : public Struct1 +{ + virtual sal_uLong foo1() override; + // expected-error-re@-1 {{method return type does not match overridden method 'sal_uLong' (aka 'unsigned {{.+}}') vs 'sal_uIntPtr' (aka 'unsigned {{.+}}') [loplugin:typedefparam]}} + virtual void foo2(sal_uLong) override; + // expected-error-re@-1 {{method param 1 does not match overridden method param 'sal_uLong' (aka 'unsigned {{.+}}') vs 'sal_uIntPtr' (aka 'unsigned {{.+}}') [loplugin:typedefparam]}} +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/typeidcomparison.cxx b/compilerplugins/clang/test/typeidcomparison.cxx new file mode 100644 index 000000000..31ab749a2 --- /dev/null +++ b/compilerplugins/clang/test/typeidcomparison.cxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +struct Base +{ + virtual ~Base(); +}; + +struct Derived : Base +{ +}; + +void good(Base* p) +{ + (void)(typeid(*p) == typeid(Derived)); + (void)(typeid(Derived) == typeid(*p)); + (void)(typeid(*p) != typeid(Derived)); + (void)(typeid(Derived) != typeid(*p)); +} + +void bad(Base* p) +{ + // expected-error@+1 {{comparison of type info of mixed pointer and non-pointer types 'Base *' and 'Derived' can never succeed [loplugin:typeidcomparison]}} + (void)(typeid(p) == typeid(Derived)); + // expected-error@+1 {{comparison of type info of mixed pointer and non-pointer types 'Derived' and 'Base *' can never succeed [loplugin:typeidcomparison]}} + (void)(typeid(Derived) == typeid(p)); + // expected-error@+1 {{comparison of type info of mixed pointer and non-pointer types 'Base *' and 'Derived' can never succeed [loplugin:typeidcomparison]}} + (void)(typeid(p) != typeid(Derived)); + // expected-error@+1 {{comparison of type info of mixed pointer and non-pointer types 'Derived' and 'Base *' can never succeed [loplugin:typeidcomparison]}} + (void)(typeid(Derived) != typeid(p)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unnecessarycatchthrow.cxx b/compilerplugins/clang/test/unnecessarycatchthrow.cxx new file mode 100644 index 000000000..a9b32d86f --- /dev/null +++ b/compilerplugins/clang/test/unnecessarycatchthrow.cxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +void foo(); + +int main() +{ + try { + foo(); + } catch(int const &) { // expected-error {{unnecessary catch and throw [loplugin:unnecessarycatchthrow]}} + throw; + } + try { + foo(); + } catch(int const & ex) { // expected-error {{unnecessary catch and throw [loplugin:unnecessarycatchthrow]}} + throw ex; + } + try { + foo(); + } catch(int const &) { + std::cout << "test"; + throw; + } + +} + +void test1() +{ + // cannot remove catch/throw where the throw is of a non-final class + struct B {}; + struct D: B {}; + try { + throw D(); + } catch (B & b) { + throw b; // must not be removed + } +}; + +void test2() +{ + struct F final {}; + try { + throw F(); + } catch (F const & f) { // expected-error {{unnecessary catch and throw [loplugin:unnecessarycatchthrow]}} + throw f; + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unnecessarylocking.cxx b/compilerplugins/clang/test/unnecessarylocking.cxx new file mode 100644 index 000000000..6dda5d333 --- /dev/null +++ b/compilerplugins/clang/test/unnecessarylocking.cxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +static std::mutex gSolarMutex; + +class SolarMutexGuard : public std::unique_lock +{ +public: + SolarMutexGuard() + : std::unique_lock(gSolarMutex) + { + } +}; + +namespace test1 +{ +struct Foo +{ + int m_foo; + // expected-error@+1 {{unnecessary locking [loplugin:unnecessarylocking]}} + int bar1() + { + SolarMutexGuard guard; + return 1; + } + // no warning expected + int bar2() + { + SolarMutexGuard guard; + return m_foo; + } +}; +} + +namespace test2 +{ +struct Foo +{ + std::mutex m_aMutex; + int m_foo; + + // expected-error@+1 {{unnecessary locking [loplugin:unnecessarylocking]}} + int bar1() + { + std::unique_lock guard(m_aMutex); + return 1; + } + // expected-error@+1 {{unnecessary locking [loplugin:unnecessarylocking]}} + int bar2() + { + std::scoped_lock guard(m_aMutex); + return 1; + } + // no warning expected + int bar3() + { + std::scoped_lock guard(m_aMutex); + return m_foo; + } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unnecessaryoverride-dtor.cxx b/compilerplugins/clang/test/unnecessaryoverride-dtor.cxx new file mode 100644 index 000000000..960909b4e --- /dev/null +++ b/compilerplugins/clang/test/unnecessaryoverride-dtor.cxx @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include "unnecessaryoverride-dtor.hxx" + +struct NonVirtualBase {}; + +struct NonVirtualDerived1: NonVirtualBase { + ~NonVirtualDerived1() {} // expected-error {{unnecessary user-declared destructor [loplugin:unnecessaryoverride]}} +}; + +struct NonVirtualDerived2: NonVirtualBase { + virtual ~NonVirtualDerived2() {} +}; + +struct PrivateDerived: VirtualBase { +private: + ~PrivateDerived() override {} +}; + +struct ProtectedDerived: VirtualBase { +protected: + ~ProtectedDerived() override {} +}; + +IncludedDerived2::~IncludedDerived2() {} + +struct Incomplete: salhelper::SimpleReferenceObject {}; + +IncludedDerived3::IncludedDerived3() {} + +IncludedDerived3::~IncludedDerived3() {} + +// vmiklos likes these because he can quickly add a DEBUG or something similar without +// massive recompile +IncludedNotDerived::~IncludedNotDerived() {} + +struct NoExSpecDerived: VirtualBase { + ~NoExSpecDerived() override {} // expected-error {{unnecessary user-declared destructor [loplugin:unnecessaryoverride]}} +}; + +struct NoThrowDerived: VirtualBase { + ~NoThrowDerived() throw () override {} // expected-error {{unnecessary user-declared destructor [loplugin:unnecessaryoverride]}} +}; + +struct NoexceptDerived: VirtualBase { + ~NoexceptDerived() noexcept override {} // expected-error {{unnecessary user-declared destructor [loplugin:unnecessaryoverride]}} +}; + +struct NoexceptTrueDerived: VirtualBase { + ~NoexceptTrueDerived() noexcept(true) override {} // expected-error {{unnecessary user-declared destructor [loplugin:unnecessaryoverride]}} +}; + +#if 0 +struct NoexceptFalseBase { + virtual ~NoexceptFalseBase() noexcept(false) {} +}; + +struct NoexceptFalseDerived: NoexceptFalseBase { + ~NoexceptFalseDerived() noexcept(false) override {} +}; +#endif + +struct NoDtorDerived: VirtualBase {}; + +struct DefaultDerived1: VirtualBase { + ~DefaultDerived1() override = default; // expected-error {{unnecessary user-declared destructor [loplugin:unnecessaryoverride]}} +}; + +struct DefaultDerived2: VirtualBase { + ~DefaultDerived2() override; +}; + +DefaultDerived2::~DefaultDerived2() = default; + +struct EmptyDerived1: VirtualBase { + ~EmptyDerived1() override {}; // expected-error {{unnecessary user-declared destructor [loplugin:unnecessaryoverride]}} +}; + +struct EmptyDerived2: VirtualBase { + ~EmptyDerived2() override; // expected-note {{declared here [loplugin:unnecessaryoverride]}} +}; + +EmptyDerived2::~EmptyDerived2() {} // expected-error {{unnecessary user-declared destructor [loplugin:unnecessaryoverride]}} + +struct NonEmptyDerived: VirtualBase { + ~NonEmptyDerived() override { (void) 0; } +}; + +struct CatchDerived: VirtualBase { + ~CatchDerived() override try {} catch (...) {} +}; + +struct DeleteBase { + virtual ~DeleteBase() = delete; +}; + +struct DeleteDerived: DeleteBase { + ~DeleteDerived() override = delete; +}; + +struct PureBase { + virtual ~PureBase() = 0; +}; + +struct PureDerived: PureBase { + ~PureDerived() override {} // expected-error {{unnecessary user-declared destructor [loplugin:unnecessaryoverride]}} +}; + +struct CompleteBase { + ~CompleteBase() {} // expected-error {{unnecessary user-declared destructor [loplugin:unnecessaryoverride]}} +}; + +// noelgrandin, there's one other corner case one can imagine: +// a class defined in a .hxx with the dtor declared (but not defined) as inline in the .hxx, +// and then defined in the cxx (making it effectively only callable from within the cxx); +// removing the dtor declaration from the class definition would change the dtor to be callable from everywhere +MarkedInlineButNotDefined::~MarkedInlineButNotDefined() = default; + +// avoid loplugin:unreffun: +int main() { + (void) NonVirtualDerived1(); + (void) DefaultDerived1(); + (void) CompleteBase(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unnecessaryoverride-dtor.hxx b/compilerplugins/clang/test/unnecessaryoverride-dtor.hxx new file mode 100644 index 000000000..9f722375a --- /dev/null +++ b/compilerplugins/clang/test/unnecessaryoverride-dtor.hxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include + +struct VirtualBase { + virtual ~VirtualBase() {} +}; + +struct IncludedDerived1: VirtualBase { + ~IncludedDerived1() override {}; // expected-error {{unnecessary user-declared destructor [loplugin:unnecessaryoverride]}} +}; + +struct IncludedDerived2: VirtualBase { + ~IncludedDerived2() override; +}; + +struct IncludedNotDerived { + ~IncludedNotDerived(); +}; + +struct Incomplete; +struct IncludedDerived3: VirtualBase { + IncludedDerived3(); + ~IncludedDerived3() override; + +private: + IncludedDerived3(IncludedDerived3 &) = delete; + void operator =(IncludedDerived3) = delete; + + rtl::Reference m; +}; + +struct MarkedInlineButNotDefined { + inline ~MarkedInlineButNotDefined(); +}; + +template struct TemplateBase: T { + virtual ~TemplateBase() {} +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unnecessaryoverride.cxx b/compilerplugins/clang/test/unnecessaryoverride.cxx new file mode 100644 index 000000000..bf1e61352 --- /dev/null +++ b/compilerplugins/clang/test/unnecessaryoverride.cxx @@ -0,0 +1,196 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include + +struct Base +{ + Base(); + Base(Base const&); + virtual ~Base(); + Base& operator=(Base const&); + virtual void f(); + void variadic(int, ...); + void cv() const volatile; + void ref(); + static void staticFn(); + void defaults(void* = nullptr, int = 0, double = 1, Base const& = {}, char const* = "foo"); +}; + +struct SimpleDerived : Base +{ + void + f() override // expected-error {{public virtual function just calls public parent [loplugin:unnecessaryoverride]}} + { + Base::f(); + } +}; + +struct Intermediate1 : Base +{ +}; + +struct MultiFunctionIntermediate2 : Base +{ + void f() override; +}; + +struct MultiFunctionDerived : Intermediate1, MultiFunctionIntermediate2 +{ + void f() override { Intermediate1::f(); } // no warning +}; + +struct MultiClassIntermediate2 : Base +{ +}; + +struct MultiClassDerived : Intermediate1, MultiClassIntermediate2 +{ + void f() override { Intermediate1::f(); } // no warning +}; + +struct DerivedDifferent : Base +{ + void variadic(int x) { Base::variadic(x); } // no warning + void cv() { Base::cv(); } // no warning + void ref() && { Base::ref(); } // no warning + void staticFn() { Base::staticFn(); } // no warning + void defaults(void* x1, int x2, double x3, Base const& x4, char const* x5) + { + Base::defaults(x1, x2, x3, x4, x5); // no warning + } +}; + +struct DerivedSame : Base +{ + void + defaults( // expected-error {{public function just calls public parent [loplugin:unnecessaryoverride]}} + void* x1 = 0, int x2 = (1 - 1), double x3 = 1.0, Base const& x4 = (Base()), + char const* x5 = "f" + "oo") + { + Base::defaults(x1, x2, x3, x4, x5); + } +}; + +struct DerivedSlightlyDifferent : Base +{ + void defaults( // no warning + void* x1 = nullptr, int x2 = 0, double x3 = 1, Base const& x4 = DerivedSlightlyDifferent(), + char const* x5 = "foo") + { + Base::defaults(x1, x2, x3, x4, x5); + } +}; + +enum class E +{ + E1 = 1, + E2 = 2, + E3 = 4 +}; +namespace o3tl +{ +template <> struct typed_flags : is_typed_flags +{ +}; +} + +struct Base2 +{ + void default1(Base const& = SimpleDerived()); + void default2(Base const& = SimpleDerived()); + void default3(Base = Base()); + void default4(E = (E::E1 | E::E2 | E::E3)); +}; + +struct Derived2 : Base2 +{ + void default1(Base const& x = Intermediate1()) { Base2::default1(x); } // no warning + void + default2( // expected-error {{public function just calls public parent [loplugin:unnecessaryoverride]}} + Base const& x = SimpleDerived()) + { + Base2::default2(x); + } + void + default3( // expected-error {{public function just calls public parent [loplugin:unnecessaryoverride]}} + Base x = Base()) + { + (Base2::default3(x)); + } + void + default4( // expected-error {{public function just calls public parent [loplugin:unnecessaryoverride]}} + E x = (E::E1 | E::E2 | E::E3)) + { + Base2::default4(x); + } +}; + +class Base3 +{ +public: + void f1(); +}; + +class Derived3 : protected Base3 +{ +public: + // effectively changing access from protected to public + void f1() { Base3::f1(); } +}; + +// check the case where the method occurs more than once in a direct path up the class hierarchy +struct Base4 +{ + void f1(); +}; +struct Derived4_1 : public Base4 +{ + void f1(); +}; +struct Derived4_2 : public Derived4_1 +{ + void + f1() // expected-error {{public function just calls public parent [loplugin:unnecessaryoverride]}} + { + Derived4_1::f1(); + } +}; + +struct Base5_1 +{ + void f1(); +}; +struct Base5_2 +{ + void f1(); +}; +struct Derived5 : public Base5_1, public Base5_2 +{ + void f1() { Base5_1::f1(); } // no warning expected +}; + +struct Base6_1 +{ + bool f1(); +}; +struct Derived6 : public Base6_1 +{ + bool + f1() // expected-error {{public function just calls public parent [loplugin:unnecessaryoverride]}} + { + bool ret = Base6_1::f1(); + return ret; + } +}; +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unnecessaryparen.cxx b/compilerplugins/clang/test/unnecessaryparen.cxx new file mode 100644 index 000000000..ccc2b4ce6 --- /dev/null +++ b/compilerplugins/clang/test/unnecessaryparen.cxx @@ -0,0 +1,143 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#define MACRO (1) + +bool foo(int); + +enum class EFoo { Bar }; + +struct S { operator bool(); }; + +enum class BrowseMode +{ + Modules = 0x01, + Top = 0x02, + Bottom = 0x04, + Left = 0x08, +}; +namespace o3tl +{ +template <> struct typed_flags : is_typed_flags +{ +}; +} + +int main() +{ + int x = 1; + x = ((2)); // expected-error {{parentheses around parentheses [loplugin:unnecessaryparen]}} + + if ((foo(1))) foo(2); // expected-error {{parentheses immediately inside if statement [loplugin:unnecessaryparen]}} + + foo((1)); // expected-error {{parentheses immediately inside single-arg call [loplugin:unnecessaryparen]}} + + int y = (x); // expected-error {{parentheses immediately inside vardecl statement [loplugin:unnecessaryparen]}} + (void)y; + + EFoo efoo = EFoo::Bar; + switch (efoo) { + case (EFoo::Bar): break; // expected-error {{parentheses immediately inside case statement [loplugin:unnecessaryparen]}} + } + + int z = (y) ? 1 : 0; // expected-error {{unnecessary parentheses around identifier [loplugin:unnecessaryparen]}} + (void)z; + + int v1 = (static_cast(1)) + 1; // expected-error {{unnecessary parentheses around cast [loplugin:unnecessaryparen]}} + (void)v1; + + // No warnings, used to silence -Wunreachable-code: + if ((false)) { + return 0; + } + x = (true) ? 0 : 1; + + // More "no warnings", at least potentially used to silence -Wunreachable-code: + while ((false)) { + return 0; + } + for (; (false);) { + return 0; + } + x = foo(0) && (false) ? 0 : 1; + x = MACRO < (0) ? 0 : 1; + // cf. odd Clang -Wunreachable-code--suppression mechanism when the macro itself contains + // parentheses, causing the issue that lead to c421ac3f9432f2e9468d28447dc4c2e45b6f4da3 + // "Revert loplugin:unnecessaryparen warning around integer literals" + + int v2 = (1); // expected-error {{parentheses immediately inside vardecl statement [loplugin:unnecessaryparen]}} + (void)v2; + + std::string v3; + v3 = (std::string("xx") + "xx"); // expected-error {{parentheses immediately inside assignment [loplugin:unnecessaryparen]}} + (void)v3; + + S s1; + if ((s1)) { // expected-error {{parentheses immediately inside if statement [loplugin:unnecessaryparen]}} + return 0; + } + S s2; + if ((s2 = s1)) { + return 0; + } + + (void) sizeof (int); + (void) sizeof (x); // expect no warning (for whatever reason; for symmetry with above case?) + + // Expecting just one error, not reported twice during TraverseInitListExpr: + int a[] = {(x)}; // expected-error {{unnecessary parentheses around identifier [loplugin:unnecessaryparen]}} + (void) a; + + (void) (+1); // expected-error {{unnecessary parentheses around signed numeric literal [loplugin:unnecessaryparen]}} + (void) (-1); // expected-error {{unnecessary parentheses around signed numeric literal [loplugin:unnecessaryparen]}} + + // For simplicity's sake, even warn about pathological cases that would require adding + // whitespace when removing the parentheses (as is also necessary in other cases anyway, like + // "throw(x);"); it is unlikely that there are any actual occurrences of code like "-(-1)" that + // would benefit from the parentheses readability-wise, compared to "- -1": + (void) -(-1); // expected-error {{unnecessary parentheses around signed numeric literal [loplugin:unnecessaryparen]}} + + char *p = nullptr; + delete (p); // expected-error {{parentheses immediately inside delete expr [loplugin:unnecessaryparen]}} + + BrowseMode nBits = ( BrowseMode::Modules | BrowseMode::Top ); // expected-error {{parentheses immediately inside vardecl statement [loplugin:unnecessaryparen]}} + (void)nBits; + + OUString::number((v2+1)); // expected-error {{parentheses immediately inside single-arg call [loplugin:unnecessaryparen]}} +}; + +struct B { operator bool() const; }; + +struct N { bool operator !(); }; + +class Foo2 +{ + int* p; + B b; + N n; + + int foo2() + { + return (p) ? 1 : 0; // expected-error {{unnecessary parentheses around member expr [loplugin:unnecessaryparen]}} + } + + static int foo3(Foo2 & foo) { + (void) !(foo.p); + (void) !(foo.b); + (void) !(foo.n); + return (foo.p) ? 1 : 0; + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unoany.cxx b/compilerplugins/clang/test/unoany.cxx new file mode 100644 index 000000000..b5d91007f --- /dev/null +++ b/compilerplugins/clang/test/unoany.cxx @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" + +#include "com/sun/star/uno/Any.hxx" + +#pragma clang diagnostic ignored "-Wunknown-warning-option" // for Clang < 13 +#pragma clang diagnostic ignored "-Wunused-but-set-variable" + +css::uno::Any getAny() { return css::uno::Any(true); } + +int main() +{ + css::uno::Any a; + css::uno::Any b; + a = b; + a = getAny(); + a = css::uno::Any(true); // expected-error {{unnecessary copy, rather use <<= operator directly with the 'Any' constructor argument [loplugin:unoany]}} +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unoquery.cxx b/compilerplugins/clang/test/unoquery.cxx new file mode 100644 index 000000000..a80786a17 --- /dev/null +++ b/compilerplugins/clang/test/unoquery.cxx @@ -0,0 +1,19 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" +#include "com/sun/star/beans/XProperty.hpp" + +void foo(css::uno::Reference model) +{ + css::uno::Reference(model, css::uno::UNO_QUERY)->getAsProperty(); + // expected-error@-1 {{calling UNO_QUERY followed by unconditional method call might result in SIGSEGV, rather use UNO_QUERY_THROW [loplugin:unoquery]}} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unreffun.cxx b/compilerplugins/clang/test/unreffun.cxx new file mode 100644 index 000000000..b61171a87 --- /dev/null +++ b/compilerplugins/clang/test/unreffun.cxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "unreffun.hxx" + +template struct S +{ + friend void f(); +}; + +void f() {} + +void g(); // expected-error {{Unreferenced function declaration [loplugin:unreffun]}} + +void h() // expected-error {{Unreferenced externally visible function definition [loplugin:unreffun]}} +{ +} + +void i() {} + +extern void j(); // expected-error {{Unreferenced function declaration [loplugin:unreffun]}} + +extern void +k() // expected-error {{Unreferenced externally visible function definition [loplugin:unreffun]}} +{ +} + +extern void l(); // expected-note {{first declaration is here [loplugin:unreffun]}} +void l() // expected-error {{Unreferenced externally visible function definition [loplugin:unreffun]}} +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unreffun.hxx b/compilerplugins/clang/test/unreffun.hxx new file mode 100644 index 000000000..a209dd7b6 --- /dev/null +++ b/compilerplugins/clang/test/unreffun.hxx @@ -0,0 +1,16 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +void f(); + +extern void i(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unsignedcompare.cxx b/compilerplugins/clang/test/unsignedcompare.cxx new file mode 100644 index 000000000..32b9af813 --- /dev/null +++ b/compilerplugins/clang/test/unsignedcompare.cxx @@ -0,0 +1,16 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +bool f(int i1, unsigned i2) +{ + // expected-error@+1 {{explicit cast from 'int' to 'unsigned int' (of equal rank) in comparison against 'unsigned int': if the cast value is known to be non-negative, use o3tl::make_unsigned instead of the cast [loplugin:unsignedcompare]}} + return unsigned(i1) < i2; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unusedcapturedefault.cxx b/compilerplugins/clang/test/unusedcapturedefault.cxx new file mode 100644 index 000000000..d98eec04d --- /dev/null +++ b/compilerplugins/clang/test/unusedcapturedefault.cxx @@ -0,0 +1,16 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +auto f1() +{ + // expected-error@+1 {{unused capture-default [loplugin:unusedcapturedefault]}} + return [=] { return 0; }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unusedenumconstants.cxx b/compilerplugins/clang/test/unusedenumconstants.cxx new file mode 100644 index 000000000..3f69e8993 --- /dev/null +++ b/compilerplugins/clang/test/unusedenumconstants.cxx @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +namespace test1 +{ +void test1() +{ + enum NameClashMode + { + NONE, + NO_CLASH // expected-error {{write NO_CLASH [loplugin:unusedenumconstants]}} + }; + NameClashMode eNameClashMode = NO_CLASH; + (void)eNameClashMode; +} +}; + +enum class BrowseMode +{ + Modules = 0x01, // expected-error {{read Modules [loplugin:unusedenumconstants]}} + Top = 0x02, // expected-error {{write Top [loplugin:unusedenumconstants]}} + Bottom = 0x04, // expected-error {{read Bottom [loplugin:unusedenumconstants]}} + Left = 0x08, // expected-error {{write Left [loplugin:unusedenumconstants]}} +}; +namespace o3tl +{ +template <> struct typed_flags : is_typed_flags +{ +}; +} +BrowseMode g_flags; +int test2(BrowseMode nMode) +{ + if (nMode & BrowseMode::Modules) + return 1; + g_flags |= BrowseMode::Top; + return 0; +} +bool test2b(BrowseMode nMode) { return bool(nMode & BrowseMode::Bottom); } +BrowseMode test2c() { return BrowseMode::Left; } + +enum class Enum3 +{ + One = 0x01, // expected-error {{write One [loplugin:unusedenumconstants]}} + Two = 0x02 // expected-error {{write Two [loplugin:unusedenumconstants]}} +}; +namespace o3tl +{ +template <> struct typed_flags : is_typed_flags +{ +}; +} +void test3_foo(Enum3); +void test3() { test3_foo(Enum3::One | Enum3::Two); } + +namespace test4 +{ +enum Enum4 +{ + ONE, // expected-error {{write ONE [loplugin:unusedenumconstants]}} + TWO +}; +struct Test4Base +{ + Test4Base(Enum4) {} +}; +struct Test4 : public Test4Base +{ + Test4() + : Test4Base(Enum4::ONE) + { + } +}; +}; + +//----------------------------------------------------------------------------------- + +// check that conditional operator walks up the tree +namespace test5 +{ +enum Enum +{ + ONE, // expected-error {{write ONE [loplugin:unusedenumconstants]}} + TWO // expected-error {{write TWO [loplugin:unusedenumconstants]}} +}; + +Enum foo(int x) { return x == 1 ? Enum::ONE : Enum::TWO; } +}; + +//----------------------------------------------------------------------------------- +// Ignore a common pattern that does not introduce any new information, merely removes +// information. +enum class Enum6 +{ + Modules = 0x01, // expected-error {{write Modules [loplugin:unusedenumconstants]}} + Top = 0x02, +}; +namespace o3tl +{ +template <> struct typed_flags : is_typed_flags +{ +}; +} +void test6() +{ + Enum6 foo = Enum6::Modules; + foo &= ~Enum6::Top; + foo &= (~Enum6::Top); + (void)foo; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unusedfields.cxx b/compilerplugins/clang/test/unusedfields.cxx new file mode 100644 index 000000000..b545f4b1a --- /dev/null +++ b/compilerplugins/clang/test/unusedfields.cxx @@ -0,0 +1,382 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if defined _WIN32 // TODO, see corresponding TODO in compilerplugins/clang/unusedfields.cxx +// expected-no-diagnostics +#else + +#include +#include +#include +#include +#include +#include +#include + +struct Foo +// expected-error@-1 {{read m_foo1 [loplugin:unusedfields]}} +// expected-error@-2 {{outside m_foo1 [loplugin:unusedfields]}} +{ + int m_foo1; +}; + +struct Bar +// expected-error@-1 {{read m_bar2 [loplugin:unusedfields]}} +// expected-error@-2 {{read m_bar4 [loplugin:unusedfields]}} +// expected-error@-3 {{read m_bar5 [loplugin:unusedfields]}} +// expected-error@-4 {{read m_bar6 [loplugin:unusedfields]}} +// expected-error@-5 {{read m_barfunctionpointer [loplugin:unusedfields]}} +// expected-error@-6 {{read m_bar8 [loplugin:unusedfields]}} +// expected-error@-7 {{read m_bar10 [loplugin:unusedfields]}} +// expected-error@-8 {{read m_bar11 [loplugin:unusedfields]}} +// expected-error@-9 {{write m_bar1 [loplugin:unusedfields]}} +// expected-error@-10 {{write m_bar2 [loplugin:unusedfields]}} +// expected-error@-11 {{write m_bar3 [loplugin:unusedfields]}} +// expected-error@-12 {{write m_bar3b [loplugin:unusedfields]}} +// expected-error@-13 {{write m_bar4 [loplugin:unusedfields]}} +// expected-error@-14 {{write m_bar7 [loplugin:unusedfields]}} +// expected-error@-15 {{write m_bar9 [loplugin:unusedfields]}} +// expected-error@-16 {{write m_bar12 [loplugin:unusedfields]}} +// expected-error@-17 {{outside-constructor m_bar2 [loplugin:unusedfields]}} +// expected-error@-18 {{outside-constructor m_bar3 [loplugin:unusedfields]}} +// expected-error@-19 {{outside-constructor m_bar3b [loplugin:unusedfields]}} +// expected-error@-20 {{outside-constructor m_bar4 [loplugin:unusedfields]}} +// expected-error@-21 {{outside-constructor m_bar5 [loplugin:unusedfields]}} +// expected-error@-22 {{outside-constructor m_bar6 [loplugin:unusedfields]}} +// expected-error@-23 {{outside-constructor m_bar7 [loplugin:unusedfields]}} +// expected-error@-24 {{outside-constructor m_bar8 [loplugin:unusedfields]}} +// expected-error@-25 {{outside-constructor m_bar9 [loplugin:unusedfields]}} +// expected-error@-26 {{outside-constructor m_bar10 [loplugin:unusedfields]}} +// expected-error@-27 {{outside-constructor m_bar11 [loplugin:unusedfields]}} +// expected-error@-28 {{outside-constructor m_bar12 [loplugin:unusedfields]}} +// expected-error@-29 {{outside-constructor m_barfunctionpointer [loplugin:unusedfields]}} +// expected-error@-30 {{outside m_barstream [loplugin:unusedfields]}} +{ + int m_bar1; + int m_bar2 = 1; + int* m_bar3; + int* m_bar3b; + int m_bar4; + void (*m_barfunctionpointer)(int&); + int m_bar5; + std::vector m_bar6; + int m_bar7[5]; + int m_bar8; + int m_barstream; + sal_Int32 m_bar9; + sal_Int32 m_bar10; + css::uno::Any m_bar11; + css::uno::Any m_bar12; + + // check that we see reads of fields like m_foo1 when referred to via constructor initializer + Bar(Foo const & foo) : m_bar1(foo.m_foo1) {} + + // check that we don't see reads when inside copy/move constructor + Bar(Bar const & other) { m_bar3 = other.m_bar3; } + + // check that we don't see reads when inside copy/move assignment operator + Bar& operator=(Bar const & other) { m_bar3 = other.m_bar3; return *this; } + + // check that we DON'T see reads here + int bar2() { return m_bar2; } + + // check that we DON'T see reads here + void bar3() + { + m_bar3 = nullptr; + m_bar3b = m_bar3 = nullptr; + } + + // check that we see reads of field when passed to a function pointer + // check that we see read of a field that is a function pointer + void bar4() { m_barfunctionpointer(m_bar4); } + + // check that we see reads of a field when used in variable init + void bar5() { int x = m_bar5; (void) x; } + + // check that we see reads of a field when used in ranged-for + void bar6() { for (auto i : m_bar6) { (void)i; } } + + // check that we see don't see reads of array fields + void bar7() { m_bar7[3] = 1; } + + // check that we see reads when a field is used in an array expression + char bar8() + { + char tmp[5]; + return tmp[m_bar8]; + } + + // check that we don't see reads when calling operator>>= + void bar9() + { + css::uno::Any any; + any >>= m_bar9; + } + + // check that we see don't see writes when calling operator<<= + void bar10() + { + css::uno::Any any; + any <<= m_bar10; + (void)any; + } + + // check that we see reads of the LHS when calling operator>>= + void bar11() + { + int x; + m_bar11 >>= x; + } + + // check that we see writes of the LHS when calling operator<<= + void bar12() + { + int x = 0; + m_bar12 <<= x; + } +}; + +// check that we __dont__ see a read of m_barstream +std::ostream& operator<<(std::ostream& s, Bar const & bar) +{ + s << bar.m_barstream; + return s; +}; + +struct ReadOnly1 { ReadOnly1(int&); }; + +struct ReadOnlyAnalysis +// expected-error@-1 {{read m_f2 [loplugin:unusedfields]}} +// expected-error@-2 {{read m_f3 [loplugin:unusedfields]}} +// expected-error@-3 {{read m_f5 [loplugin:unusedfields]}} +// expected-error@-4 {{read m_f6 [loplugin:unusedfields]}} +// expected-error@-5 {{write m_f2 [loplugin:unusedfields]}} +// expected-error@-6 {{write m_f3 [loplugin:unusedfields]}} +// expected-error@-7 {{write m_f4 [loplugin:unusedfields]}} +// expected-error@-8 {{write m_f5 [loplugin:unusedfields]}} +// expected-error@-9 {{write m_f6 [loplugin:unusedfields]}} +// expected-error@-10 {{outside-constructor m_f2 [loplugin:unusedfields]}} +// expected-error@-11 {{outside-constructor m_f3 [loplugin:unusedfields]}} +// expected-error@-12 {{outside-constructor m_f4 [loplugin:unusedfields]}} +// expected-error@-13 {{outside-constructor m_f5 [loplugin:unusedfields]}} +// expected-error@-14 {{outside-constructor m_f6 [loplugin:unusedfields]}} +{ + int m_f1; + int m_f2; + int m_f3; + std::vector m_f4; + int m_f5; + int m_f6; + + // check that we don't see a write of m_f1 + ReadOnlyAnalysis() : m_f1(0) {} + + void method1(int&); + + // check that we see a write when we pass by non-const ref + void method2() { method1(m_f2); } + + int& method3() { return m_f3; } + + void method4() { m_f4.push_back(1); } + + // check that we see a write when we pass by non-const ref + void method5() { ReadOnly1 a(m_f5); } + + // check that we see a write when we pass by non-const ref + void method6() + { + int& r = m_f6; + r = 1; + } +}; + +struct ReadOnlyAnalysis2 +// expected-error@-1 {{write m_r2f1 [loplugin:unusedfields]}} +{ + int m_r2f1; +}; + +ReadOnlyAnalysis2 global { 1 }; + +struct ReadOnlyAnalysis3 +// expected-error@-1 {{read m_f1 [loplugin:unusedfields]}} +// expected-error@-2 {{outside-constructor m_f1 [loplugin:unusedfields]}} +{ + int m_f1; + + void func1() + { + if (m_f1) + m_f1 = 1; + } +}; + +// Verify the special logic for container fields that only contains mutations that +// add elements. +struct ReadOnlyAnalysis4 +// expected-error@-1 {{read m_readonly [loplugin:unusedfields]}} +// expected-error@-2 {{write m_writeonly [loplugin:unusedfields]}} +// expected-error@-3 {{read m_readonlyCss [loplugin:unusedfields]}} +// expected-error@-4 {{outside-constructor m_readonly [loplugin:unusedfields]}} +// expected-error@-5 {{outside-constructor m_readonlyCss [loplugin:unusedfields]}} +// expected-error@-6 {{outside-constructor m_writeonly [loplugin:unusedfields]}} +{ + std::vector m_readonly; + std::vector m_writeonly; + css::uno::Sequence m_readonlyCss; + + void func1() + { + int x = m_readonly[0]; + (void)x; + *m_readonly.begin() = 1; + + m_writeonly.push_back(0); + m_writeonly.clear(); + + x = m_readonlyCss.getArray()[0]; + } +}; + +template +struct VclPtr +{ + VclPtr(T*); + void clear(); +}; + +// Check calls to operators +struct WriteOnlyAnalysis2 +// expected-error@-1 {{write m_vclwriteonly [loplugin:unusedfields]}} +// expected-error@-2 {{outside-constructor m_vclwriteonly [loplugin:unusedfields]}} +{ + VclPtr m_vclwriteonly; + + WriteOnlyAnalysis2() : m_vclwriteonly(nullptr) + { + m_vclwriteonly = nullptr; + } + + ~WriteOnlyAnalysis2() + { + m_vclwriteonly.clear(); + } +}; + +namespace WriteOnlyAnalysis3 +{ + void setFoo(int); + struct Foo1 + // expected-error@-1 {{read m_field1 [loplugin:unusedfields]}} + // expected-error@-2 {{write m_field1 [loplugin:unusedfields]}} + // expected-error@-3 {{outside-constructor m_field1 [loplugin:unusedfields]}} + { + int m_field1; + Foo1() : m_field1(1) {} + ~Foo1() + { + setFoo(m_field1); + } + }; +}; + +// Check that writes to fields that are wrapped by conditional checks are ignored, +// where those conditional checks use an 'operator bool' +namespace ReadOnlyAnalysis5 +{ + struct RefTarget + { + void acquire(); + void release(); + }; + struct Foo1 + // expected-error@-1 {{read m_field1 [loplugin:unusedfields]}} + // expected-error@-2 {{read m_field2 [loplugin:unusedfields]}} + // expected-error@-3 {{read m_field3xx [loplugin:unusedfields]}} + // expected-error@-4 {{outside-constructor m_field1 [loplugin:unusedfields]}} + // expected-error@-5 {{outside-constructor m_field2 [loplugin:unusedfields]}} + // expected-error@-6 {{outside-constructor m_field3xx [loplugin:unusedfields]}} + { + std::unique_ptr m_field1; + rtl::Reference m_field2; + css::uno::Reference m_field3xx; + void f1(css::uno::Reference a) + { + if (m_field1) + m_field1.reset(new int); + if (m_field1.get()) + m_field1.reset(new int); + if (m_field2) + m_field2 = new RefTarget; + if (m_field2.get()) + m_field2 = new RefTarget; + if (m_field3xx) + m_field3xx = a; + if (m_field3xx.get()) + m_field3xx = a; + } + }; +}; + + +namespace TouchFromOutsideConstructorAnalysis1 +{ + struct RenderContextGuard + // expected-error@-1 {{write m_pRef [loplugin:unusedfields]}} + // expected-error@-2 {{read m_pRef [loplugin:unusedfields]}} + // expected-error@-3 {{write m_pOriginalValue [loplugin:unusedfields]}} + { + int& m_pRef; + int m_pOriginalValue; + + RenderContextGuard(int& pRef, int pValue) + : m_pRef(pRef), + m_pOriginalValue(m_pRef) + { + m_pRef = pValue; + } + }; +}; + +namespace TouchFromOutsideAnalysis1 +{ + struct SwViewShell + { + int* GetWin(); + int* Imp(); + }; + struct RenderContextGuard + // expected-error@-1 {{write m_pShell [loplugin:unusedfields]}} + // expected-error@-2 {{read m_pShell [loplugin:unusedfields]}} + { + SwViewShell* m_pShell; + + RenderContextGuard(SwViewShell* pShell) + : m_pShell(pShell) + { + if (m_pShell->GetWin()) + { + int* pDrawView(m_pShell->Imp()); + + if (nullptr != pDrawView) + { + FindPageWindow(*m_pShell->GetWin()); + } + } + } + + void FindPageWindow(int x); + }; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unusedindex.cxx b/compilerplugins/clang/test/unusedindex.cxx new file mode 100644 index 000000000..4d08b5be0 --- /dev/null +++ b/compilerplugins/clang/test/unusedindex.cxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#pragma clang diagnostic ignored "-Wunknown-warning-option" // for Clang < 13 +#pragma clang diagnostic ignored "-Wunused-but-set-variable" + +void func1() +{ + std::vector v1; + int n = 0; + + for (int i = 0; i < 10; ++i) // expected-error {{loop variable not used [loplugin:unusedindex]}} + n += 1; + for (int i = 0; i < 10; ++i) + n += i; + + for (int i = 0; i < 10; ++i) // expected-error {{loop variable not used [loplugin:unusedindex]}} + { + for (int j = 0; j < 10; ++j) + { + n += j; + } + } + for (int i = 0; i < 10; ++i) + { + for (int j = 0; j < 10; ++j) + { + n += j; + n += i; + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unusedmember.cxx b/compilerplugins/clang/test/unusedmember.cxx new file mode 100644 index 000000000..a495b7869 --- /dev/null +++ b/compilerplugins/clang/test/unusedmember.cxx @@ -0,0 +1,238 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +namespace Enum +{ +namespace +{ +struct S +{ + enum E1 + { + E11, + E12 + }; + E1 e1; + enum E2 + { + E21, + E22 + }; + E2 e2; // expected-error {{unused class member [loplugin:unusedmember]}} + enum E3 + { + E31, + E32 + } e3; + enum E4 + { + E41, + E42 + } e4; // expected-error {{unused class member [loplugin:unusedmember]}} +}; +} +void f(S s) +{ + (void)s.e1; + (void)s.e3; +} +} + +namespace ElaboratedEnum +{ +namespace +{ +struct S +{ + S() + { + enum E1 e1 = E11; + (void)e1; + } + enum E1 + { + E11, + E12 + }; + enum E2 + { + E21, + E22 + }; + enum E2 e2; +}; +} +void f() +{ + S s; + (void)s; + (void)s.e2; +} +} + +namespace UnusedEnum +{ +namespace +{ +struct S +{ + enum E // expected-error {{unused class member [loplugin:unusedmember]}} + { + E1, + E2 + }; +}; +} +void f() { (void)S::E1; } +} + +namespace UnusedDataMember +{ +namespace +{ +struct NT +{ + NT(int = 0) {} + ~NT() {} +}; +struct __attribute__((warn_unused)) T +{ + T(int = 0) {} + ~T() {} +}; +struct S +{ + int i1; + int i2; // expected-error {{unused class member [loplugin:unusedmember]}} + int const& i3; // expected-error {{unused class member [loplugin:unusedmember]}} + NT nt; + T t1; + T t2; // expected-error {{unused class member [loplugin:unusedmember]}} + T const& t3; // expected-error {{unused class member [loplugin:unusedmember]}} + S() + : i1(0) + , i3(i1) + , t1(0) + , t3(t1) + { + (void)i1; + (void)t1; + } +}; +} +void f() +{ + S s; + (void)s; +} +} + +namespace Alignof +{ +namespace +{ +struct S +{ + int i; +}; +} +void f() { (void)alignof(S const(&)[][10]); } +} + +namespace Aligned +{ +namespace +{ +struct S1 +{ + int i; +}; +struct S2 +{ + int i __attribute__((aligned(__alignof__(S1)))); +}; +} +void f() +{ + S2 s; + s.i = 0; +} +} + +namespace Bases +{ +namespace +{ +struct S1 +{ + int i1; +}; +struct S2 : S1 +{ + int i2; +}; +struct S3 : S2 +{ +}; +} +void f() { (void)sizeof(S3); } +} + +namespace Unnamed +{ +namespace +{ +struct S +{ + struct + { + struct + { + int i; + } s2; + struct // anonymous struct extension (widely supported) + { + int j; + }; + int k; + } s1; +#if false //TODO: see corresponding TODO in compilerplugins/clang/unusedmember.cxx + static constexpr struct + { + int l; // expected-error {{unused class member [loplugin:unusedmember]}} + } s = {}; +#endif + typedef struct + { + int m; // expected-error {{unused class member [loplugin:unusedmember]}} + } t; // expected-error {{unused class member [loplugin:unusedmember]}} +}; +} +void f() +{ + (void)sizeof(S); +#if false //TODO: see corresponding TODO in compilerplugins/clang/unusedmember.cxx + (void)S::s; // avoid "unused variable 's'" (non-loplugin) warning +#endif +} +} + +int main() +{ + (void)&Enum::f; + (void)&ElaboratedEnum::f; + (void)&UnusedEnum::f; + (void)&UnusedDataMember::f; + (void)&Alignof::f; + (void)&Aligned::f; + (void)&Bases::f; + (void)&Unnamed::f; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unusedvariablecheck.cxx b/compilerplugins/clang/test/unusedvariablecheck.cxx new file mode 100644 index 000000000..b020fba3e --- /dev/null +++ b/compilerplugins/clang/test/unusedvariablecheck.cxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include + +namespace +{ +template using Vec = std::vector; +} + +struct S : std::unique_ptr +{ + S(int* = nullptr); +}; + +int main() +{ + std::list v1; // expected-error {{unused variable 'v1' [loplugin:unusedvariablecheck]}} + std::string v2; // expected-error {{unused variable 'v2' [loplugin:unusedvariablecheck]}} + Vec v3; // expected-error {{unused variable 'v3' [loplugin:unusedvariablecheck]}} + std::unique_ptr + v4; // expected-error {{unused variable 'v4' [loplugin:unusedvariablecheck]}} + S v5; // expected-error {{unused variable 'v5' [loplugin:unusedvariablecheck]}} + S v6(nullptr); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unusedvariablemore.cxx b/compilerplugins/clang/test/unusedvariablemore.cxx new file mode 100644 index 000000000..712bcf403 --- /dev/null +++ b/compilerplugins/clang/test/unusedvariablemore.cxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +struct SAL_WARN_UNUSED Point +{ +}; +struct SAL_WARN_UNUSED Rectangle +{ + Rectangle(); + Rectangle(int width, int height); + Rectangle& Union(const Rectangle&) { return *this; } + Rectangle& Intersection(const Rectangle&); + Rectangle& operator+=(const Point& rPt); +}; + +void func1() +{ + Rectangle aTmp1; // expected-error {{unused variable 'aTmp1' [loplugin:unusedvariablemore]}} + aTmp1.Union(Rectangle(10, 10)); +} + +void func2() +{ + Rectangle aViewArea( + 10, 10); // expected-error@-1 {{unused variable 'aViewArea' [loplugin:unusedvariablemore]}} + aViewArea += Point(); + aViewArea.Intersection(Rectangle(0, 0)); +} + +//--------------------------------------------------------------------- +// Negative tests +//--------------------------------------------------------------------- + +Rectangle func3(const Rectangle& rRect) +{ + Rectangle aTmpRect(Rectangle(10, 10)); + return aTmpRect.Union(rRect); +} + +void func4() +{ + std::map aMimeTypeMap; + aMimeTypeMap[1] = 0; + int aExportMimeType(aMimeTypeMap[0]); + (void)aExportMimeType; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/unusedvarsglobal.cxx b/compilerplugins/clang/test/unusedvarsglobal.cxx new file mode 100644 index 000000000..e7a0316d4 --- /dev/null +++ b/compilerplugins/clang/test/unusedvarsglobal.cxx @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if defined _WIN32 // TODO, see corresponding TODO in compilerplugins/clang/unusedfields.cxx +// expected-no-diagnostics +#else + +#include + +namespace something +{ +// expected-error@+1 {{write [loplugin:unusedvarsglobal]}} +extern const std::u16string_view literal1; +} +const std::u16string_view something::literal1(u"xxx"); + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/useuniqueptr.cxx b/compilerplugins/clang/test/useuniqueptr.cxx new file mode 100644 index 000000000..f169959d6 --- /dev/null +++ b/compilerplugins/clang/test/useuniqueptr.cxx @@ -0,0 +1,311 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include + +struct XXX { + ~XXX() {} +}; + +class Foo1 { + XXX* m_pbar; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Foo1() + { + delete m_pbar; // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + m_pbar = nullptr; + } +}; + + +class Foo2 { + char* m_pbar1; // expected-note {{member is here [loplugin:useuniqueptr]}} + char* m_pbar2; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Foo2() + { + delete[] m_pbar1; // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + delete[] m_pbar2; // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + } +}; + +class Foo3 { + char* m_pbar; + bool bMine; + ~Foo3() + { + if (bMine) + delete[] m_pbar; + } +}; + +class Class4 { + int* m_pbar[10]; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Class4() + { + for (int i = 0; i < 10; ++i) + delete m_pbar[i]; // expected-error {{rather manage this member with std::some_container> [loplugin:useuniqueptr]}} + } +}; +class Class5 { + int* m_pbar[10]; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Class5() + { + for (auto p : m_pbar) // expected-note {{var is here [loplugin:useuniqueptr]}} + delete p; // expected-error {{rather manage this with std::some_container> [loplugin:useuniqueptr]}} expected-error {{call to delete on a var, should be using std::unique_ptr [loplugin:useuniqueptr]}} + } +}; +class Class5a { + int* m_pbar[10]; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Class5a() + { + for (auto p : m_pbar) // expected-note {{var is here [loplugin:useuniqueptr]}} + { + int x = 1; + x = x + 2; + delete p; // expected-error {{rather manage this with std::some_container> [loplugin:useuniqueptr]}} expected-error {{call to delete on a var, should be using std::unique_ptr [loplugin:useuniqueptr]}} + } + } +}; +class Class6 { + std::array m_pbar; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Class6() + { + for (auto p : m_pbar) // expected-note {{var is here [loplugin:useuniqueptr]}} + delete p; // expected-error {{rather manage this with std::some_container> [loplugin:useuniqueptr]}} expected-error {{call to delete on a var, should be using std::unique_ptr [loplugin:useuniqueptr]}} + } +}; +class Class7 { + std::array m_pbar; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Class7() + { + for (int i = 0; i < 10; ++i) + delete m_pbar[i]; // expected-error {{rather manage this member with std::some_container> [loplugin:useuniqueptr]}} + } +}; +class Class8 { + std::unordered_map m_pbar; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Class8() + { + for (auto & i : m_pbar) + delete i.second; // expected-error {{rather manage this with std::some_container> [loplugin:useuniqueptr]}} + } +}; +class Foo8 { + XXX* m_pbar1; // expected-note {{member is here [loplugin:useuniqueptr]}} + XXX* m_pbar2; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Foo8() + { + delete m_pbar1; // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + delete m_pbar2; // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + } +}; +class Foo9 { + XXX* m_pbar1; // expected-note {{member is here [loplugin:useuniqueptr]}} + XXX* m_pbar2; // expected-note {{member is here [loplugin:useuniqueptr]}} + XXX* m_pbar3; // expected-note {{member is here [loplugin:useuniqueptr]}} + XXX* m_pbar4; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Foo9() + { + if (m_pbar1) + { + delete m_pbar1; // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + } + if (m_pbar2 != nullptr) + { + delete m_pbar2; // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + } + if (m_pbar3 != nullptr) + delete m_pbar3; // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + if (m_pbar4 != nullptr) + { + int x = 1; + (void)x; + delete m_pbar4; // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + } + } +}; +// no warning expected +class Foo10 { + XXX* m_pbar1; + ~Foo10() + { + if (m_pbar1 != getOther()) + { + delete m_pbar1; + } + } + XXX* getOther() { return nullptr; } +}; +class Foo11 { + std::vector m_pbar1; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Foo11() + { + for (const auto & p : m_pbar1) // expected-note {{var is here [loplugin:useuniqueptr]}} + { + delete p; // expected-error {{rather manage this with std::some_container> [loplugin:useuniqueptr]}} expected-error {{call to delete on a var, should be using std::unique_ptr [loplugin:useuniqueptr]}} + } + } +}; +class Foo12 { + std::array m_pbar; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Foo12() + { + int i = 0; + while (i < 10) + delete m_pbar[i++]; // expected-error {{rather manage this member with std::some_container> [loplugin:useuniqueptr]}} + } +}; +#define DELETEZ( p ) ( delete p,p = NULL ) +class Foo13 { + int * m_pbar1; // expected-note {{member is here [loplugin:useuniqueptr]}} + int * m_pbar2; // expected-note {{member is here [loplugin:useuniqueptr]}} + int * m_pbar3; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Foo13() + { + if (m_pbar1) + DELETEZ(m_pbar1); // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + DELETEZ(m_pbar2); // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + if (m_pbar3) + { + DELETEZ(m_pbar3); // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + } + } +}; + +// check for unconditional inner compound statements +class Foo14 { + int * m_pbar1; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Foo14() + { + { + delete m_pbar1; // expected-error {{unconditional call to delete on a member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + } + } +}; + +void Foo15(int * p) +{ + delete p; // expected-error {{calling delete on a pointer param, should be either allowlisted or simplified [loplugin:useuniqueptr]}} +}; + +class Foo16 { + Foo16(int * p) + { + delete p; // expected-error {{calling delete on a pointer param, should be either allowlisted or simplified [loplugin:useuniqueptr]}} + }; + void foo(int * p) + { + delete p; // expected-error {{calling delete on a pointer param, should be either allowlisted or simplified [loplugin:useuniqueptr]}} + }; +}; + +// check for delete on array members +class Foo17 { + int * m_pbar1[6]; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Foo17() + { + delete m_pbar1[0]; // expected-error {{unconditional call to delete on an array member, should be using std::unique_ptr [loplugin:useuniqueptr]}} + } +}; + +// this only starts to work somewhere after clang 3.8 and before clang7 +class Foo18 { + std::vector m_pbar1; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Foo18() + { + for (auto aIter = m_pbar1.begin(); aIter != m_pbar1.end(); ++aIter) + delete *aIter; // expected-error {{rather manage this member with std::some_container> [loplugin:useuniqueptr]}} + } +}; + +void foo19() +{ + std::vector vec; // expected-note {{var is here [loplugin:useuniqueptr]}} + for(char * p : vec) // expected-note {{var is here [loplugin:useuniqueptr]}} + delete p; // expected-error {{rather manage this var with std::some_container> [loplugin:useuniqueptr]}} expected-error {{call to delete on a var, should be using std::unique_ptr [loplugin:useuniqueptr]}} +} + +// no warning expected +namespace foo20 +{ + struct struct20_1 {}; + struct struct20_2 : public struct20_1 { + char * p; + }; + void foo20(struct20_1 * pMapping) + { + delete static_cast< struct20_2 * >( pMapping )->p; + } +}; + +// ------------------------------------------------------------------------------------------------ +// tests for deleting when looping via iterators +// ------------------------------------------------------------------------------------------------ + +void foo21() +{ + std::vector vec; // expected-note {{var is here [loplugin:useuniqueptr]}} + for(auto it = vec.begin(); it != vec.end(); ++it) + delete *it; // expected-error {{rather manage this var with std::some_container> [loplugin:useuniqueptr]}} +} + +void foo22() +{ + std::unordered_map map; // expected-note {{var is here [loplugin:useuniqueptr]}} + for(auto it = map.begin(); it != map.end(); ++it) + delete it->second; // expected-error {{rather manage this var with std::some_container> [loplugin:useuniqueptr]}} +} + +class Foo23 +{ + std::unordered_map map; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Foo23() + { + for(auto it = map.begin(); it != map.end(); ++it) + delete it->second; // expected-error {{rather manage this member with std::some_container> [loplugin:useuniqueptr]}} + } +}; + +class Foo24 +{ + typedef std::vector HTMLAttrs; + HTMLAttrs m_aSetAttrTab; // expected-note {{member is here [loplugin:useuniqueptr]}} + ~Foo24() + { + for ( HTMLAttrs::const_iterator it = m_aSetAttrTab.begin(); it != m_aSetAttrTab.end(); ++it ) + delete *it; // expected-error {{rather manage this member with std::some_container> [loplugin:useuniqueptr]}} + } +}; + +// ------------------------------------------------------------------------------------------------ +// tests for passing owning pointers to constructors +// ------------------------------------------------------------------------------------------------ + + +class Bravo1 +{ + std::unique_ptr m_field1; + Bravo1(int* p) + : m_field1(p) // expected-error {{should be passing via std::unique_ptr param [loplugin:useuniqueptr]}} + {} +}; +class Bravo2 +{ + std::unique_ptr m_field1; + Bravo2(std::unique_ptr p) + : m_field1(std::move(p)) // no warning expected + {} +}; + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/vclwidgets.cxx b/compilerplugins/clang/test/vclwidgets.cxx new file mode 100644 index 000000000..1ff828e28 --- /dev/null +++ b/compilerplugins/clang/test/vclwidgets.cxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include + +struct Widget : public VclReferenceBase +{ + VclPtr mpParent; + + void widget1() + { + // test that we ignore assignments from a member field + Widget* p = mpParent; + (void)p; + // test against false+ + p = (true) ? mpParent.get() : nullptr; + } + + ~Widget() override + { + disposeOnce(); + } + + void dispose() override + { + mpParent.clear(); + VclReferenceBase::dispose(); + } +}; + +VclPtr f() +{ + return nullptr; +} + +Widget* g() +{ + return nullptr; +} + +// test the variable init detection +void bar() +{ + Widget* p = f(); // expected-error {{assigning a returned-by-value VclPtr to a T* variable is dodgy, should be assigned to a VclPtr. If you know that the RHS does not return a newly created T, then add a '.get()' to the RHS [loplugin:vclwidgets]}} + (void)p; + Widget* q = g(); + (void)q; + Widget* r = nullptr; + (void)r; +} + +// test the assignment detection +void bar2() +{ + Widget* p; + p = nullptr; + p = f(); // expected-error {{assigning a returned-by-value VclPtr to a T* variable is dodgy, should be assigned to a VclPtr. If you know that the RHS does not return a newly created T, then add a '.get()' to the RHS [loplugin:vclwidgets]}} + (void)p; + Widget* q; + q = g(); + (void)q; +} + + +// test against false+ + +template +T * get() { return nullptr; } + +void bar3() +{ + Widget* p; + p = get(); + (void)p; +} + +void bar4() { + VclPtr p1; + //TODO: one error should be enough here? + // expected-error@+2 {{calling delete on instance of VclReferenceBase subclass, must rather call disposeAndClear() [loplugin:vclwidgets]}} + // expected-error@+1 {{calling delete on instance of VclPtr, must rather call disposeAndClear() [loplugin:vclwidgets]}} + delete p1; + std::atomic p2; + // No false positive here: + delete p2; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/weakbase.cxx b/compilerplugins/clang/test/weakbase.cxx new file mode 100644 index 000000000..a59a53728 --- /dev/null +++ b/compilerplugins/clang/test/weakbase.cxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +namespace tools +{ +struct WeakBase +{ + virtual ~WeakBase(); +}; +} + +struct Foo1 : public tools::WeakBase +{ + virtual ~Foo1(); +}; + +struct Foo2 : public tools::WeakBase +{ + virtual ~Foo2(); +}; + +// expected-error@+1 {{multiple copies of WeakBase, through inheritance paths Bar->Foo1->WeakBase, Bar->Foo2->WeakBase [loplugin:weakbase]}} +struct Bar : public Foo1, public Foo2 +{ + virtual ~Bar(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/weakobject.cxx b/compilerplugins/clang/test/weakobject.cxx new file mode 100644 index 000000000..7c7da5566 --- /dev/null +++ b/compilerplugins/clang/test/weakobject.cxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "config_clang.h" + +namespace cppu +{ +class OWeakObject +{ +}; +} + +class Foo1 : public cppu::OWeakObject +{ +}; +class Foo2 : public cppu::OWeakObject +{ +}; + +// expected-error@+1 {{more than one copy of cppu::OWeakObject inherited [loplugin:weakobject]}} +class Foo3 : public Foo1, public Foo2 +{ +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/writeonlyvars.cxx b/compilerplugins/clang/test/writeonlyvars.cxx new file mode 100644 index 000000000..0fc141f62 --- /dev/null +++ b/compilerplugins/clang/test/writeonlyvars.cxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if defined _WIN32 //TODO, see corresponding TODO in compilerplugins/clang/writeonlyvars.cxx +// expected-no-diagnostics +#else + +#include +#include +#include +#include + +// See 1d0bc2139759f087d50432f8a2116060676f34e1 "use std::experimental::source_location in +// uno::Exception" modification to +// workdir/UnoApiHeadersTarget/udkapi/normal/com/sun/star/uno/Exception.hdl, which is indirectly +// included through the above #include directives, in turn causing conditional inclusion of +// include/o3tl/runtimetooustring.hxx (and where `ok` is only read in an assert in !NDEBUG builds): +#if defined LIBO_USE_SOURCE_LOCATION +// expected-error@o3tl/runtimetooustring.hxx:* {{read s [loplugin:writeonlyvars]}} +// expected-error@o3tl/runtimetooustring.hxx:* {{write s [loplugin:writeonlyvars]}} +#if !defined NDEBUG +// expected-error@o3tl/runtimetooustring.hxx:* {{read ok [loplugin:writeonlyvars]}} +#endif +#endif + +namespace Bar +{ +void test() +{ + // check that we DON'T see reads here + // expected-error@+1 {{write m_bar3 [loplugin:writeonlyvars]}} + int* m_bar3; + // expected-error@+1 {{write m_bar3b [loplugin:writeonlyvars]}} + int* m_bar3b; + m_bar3 = nullptr; + m_bar3b = m_bar3 = nullptr; + (void)m_bar3b; + + // check that we see reads of field when passed to a function pointer + // check that we see read of a field that is a function pointer + // expected-error@+2 {{write m_bar4 [loplugin:writeonlyvars]}} + // expected-error@+1 {{read m_bar4 [loplugin:writeonlyvars]}} + int m_bar4; + // expected-error@+1 {{read m_barfunctionpointer [loplugin:writeonlyvars]}} + void (*m_barfunctionpointer)(int&) = nullptr; + m_barfunctionpointer(m_bar4); + + // check that we see reads of a field when used in variable init + // expected-error@+1 {{read m_bar5 [loplugin:writeonlyvars]}} + int m_bar5 = 1; + int x = m_bar5; + (void)x; + + // check that we see reads of a field when used in ranged-for + // expected-error@+1 {{read m_bar6 [loplugin:writeonlyvars]}} + std::vector m_bar6; + for (auto i : m_bar6) + { + (void)i; + } + + // check that we see writes of array fields + // expected-error@+1 {{write m_bar7 [loplugin:writeonlyvars]}} + int m_bar7[5]; + m_bar7[3] = 1; + + // check that we see reads when a field is used in an array expression + // expected-error@+1 {{read m_bar8 [loplugin:writeonlyvars]}} + int m_bar8 = 1; + // expected-error@+1 {{read tmp [loplugin:writeonlyvars]}} + char tmp[5]; + auto x2 = tmp[m_bar8]; + (void)x2; + + // check that we don't see reads when calling operator>>= + // expected-error@+1 {{write m_bar9 [loplugin:writeonlyvars]}} + sal_Int32 m_bar9; + // expected-error@+1 {{read any [loplugin:writeonlyvars]}} + css::uno::Any any; + any >>= m_bar9; + + // check that we don't see writes when calling operator<<= + // expected-error@+1 {{read m_bar10 [loplugin:writeonlyvars]}} + sal_Int32 m_bar10 = 0; + // expected-error@+2 {{write any2 [loplugin:writeonlyvars]}} + // expected-error@+1 {{read any2 [loplugin:writeonlyvars]}} + css::uno::Any any2; + any2 <<= m_bar10; + (void)any2; +}; +}; + +struct ReadOnly1 +{ + ReadOnly1(int&); +}; + +namespace ReadOnlyAnalysis +{ +void method1(int&); + +void test() +{ + // check that we see a write when we pass by non-const ref + // expected-error@+2 {{read m_f2 [loplugin:writeonlyvars]}} + // expected-error@+1 {{write m_f2 [loplugin:writeonlyvars]}} + int m_f2; + method1(m_f2); + + // expected-error@+1 {{write m_f4 [loplugin:writeonlyvars]}} + std::vector m_f4; + m_f4.push_back(1); + + // check that we see a write when we pass by non-const ref + // expected-error@+2 {{read m_f5 [loplugin:writeonlyvars]}} + // expected-error@+1 {{write m_f5 [loplugin:writeonlyvars]}} + int m_f5; + ReadOnly1 a(m_f5); + + // check that we see a write when we pass by non-const ref + // expected-error@+2 {{read m_f6 [loplugin:writeonlyvars]}} + // expected-error@+1 {{write m_f6 [loplugin:writeonlyvars]}} + int m_f6; + // expected-error@+1 {{write r [loplugin:writeonlyvars]}} + int& r = m_f6; + r = 1; +}; +}; + +void ReadOnlyAnalysis3() +{ + // expected-error@+1 {{read m_f1 [loplugin:writeonlyvars]}} + int m_f1 = 0; + + if (m_f1) + m_f1 = 1; +}; + +// Verify the special logic for container fields that only contains mutations that +// add elements. +void ReadOnlyAnalysis4() +{ + // expected-error@+1 {{read m_readonly [loplugin:writeonlyvars]}} + std::vector m_readonly; + // expected-error@+1 {{write m_writeonly [loplugin:writeonlyvars]}} + std::vector m_writeonly; + // expected-error@+1 {{read m_readonlyCss [loplugin:writeonlyvars]}} + css::uno::Sequence m_readonlyCss; + + // expected-error@+1 {{write x [loplugin:writeonlyvars]}} + int x = m_readonly[0]; + (void)x; + *m_readonly.begin() = 1; // TODO? + + m_writeonly.push_back(0); + + x = m_readonlyCss.getArray()[0]; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/test/xmlimport.cxx b/compilerplugins/clang/test/xmlimport.cxx new file mode 100644 index 000000000..fa1d42a2f --- /dev/null +++ b/compilerplugins/clang/test/xmlimport.cxx @@ -0,0 +1,233 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sal/config.h" + +// Cannot include this, makes clang crash +//#include "xmloff/xmlimp.hxx" +// Cannot include this, cannot be found +//#include + +#include +#include + +namespace com::sun::star::xml::sax +{ +class XAttributeList; +class XFastContextHandler; +} + +class SvXMLImportContext; +typedef rtl::Reference SvXMLImportContextRef; +class SvXMLImportContext +{ +public: + virtual ~SvXMLImportContext() {} + + virtual void startFastElement() {} + virtual void endFastElement() {} + virtual void characters(const OUString&) {} + virtual css::uno::Reference createFastChildContext() + { + return nullptr; + } + virtual css::uno::Reference createUnknownChildContext() + { + return nullptr; + } + + virtual void StartElement(const css::uno::Reference&) {} + virtual void EndElement() {} + virtual void Characters(const OUString&) {} + virtual SvXMLImportContextRef CreateChildContext() { return nullptr; } + + void acquire(); + void release(); + + void xxx(); // just here to avoid triggering a warning I don't want to check for +}; + +class Test1 : public SvXMLImportContext +{ +public: + // expected-error@+1 {{cannot override both startFastElement and StartElement [loplugin:xmlimport]}} + virtual void startFastElement() override { xxx(); } + // expected-error@+1 {{cannot override both startFastElement and StartElement [loplugin:xmlimport]}} + virtual void StartElement(const css::uno::Reference&) override + { + xxx(); + } +}; + +class Test2 : public SvXMLImportContext +{ +public: + // expected-error@+1 {{cannot override both endFastElement and EndElement [loplugin:xmlimport]}} + virtual void endFastElement() override { xxx(); } + // expected-error@+1 {{cannot override both endFastElement and EndElement [loplugin:xmlimport]}} + virtual void EndElement() override { xxx(); } +}; + +class Test3 : public SvXMLImportContext +{ +public: + // expected-error@+1 {{cannot override both characters and Characters [loplugin:xmlimport]}} + virtual void Characters(const OUString&) override { xxx(); } + // expected-error@+1 {{cannot override both characters and Characters [loplugin:xmlimport]}} + virtual void characters(const OUString&) override { xxx(); } +}; + +class Test7 : public SvXMLImportContext +{ +public: + virtual void startFastElement() override + { + // expected-error@+1 {{don't call this superclass method [loplugin:xmlimport]}} + SvXMLImportContext::startFastElement(); + } + virtual void endFastElement() override + { + // expected-error@+1 {{don't call this superclass method [loplugin:xmlimport]}} + SvXMLImportContext::endFastElement(); + } + virtual void characters(const OUString& rChars) override + { + // expected-error@+1 {{don't call this superclass method [loplugin:xmlimport]}} + SvXMLImportContext::characters(rChars); + } + virtual css::uno::Reference + createFastChildContext() override + { + // expected-error@+1 {{don't call this superclass method [loplugin:xmlimport]}} + return SvXMLImportContext::createFastChildContext(); + } + virtual css::uno::Reference + createUnknownChildContext() override + { + // expected-error@+1 {{don't call this superclass method [loplugin:xmlimport]}} + return SvXMLImportContext::createUnknownChildContext(); + } +}; + +class Test8 : public SvXMLImportContext +{ +public: + virtual void + StartElement(const css::uno::Reference& xAttrList) override + { + // expected-error@+1 {{don't call this superclass method [loplugin:xmlimport]}} + SvXMLImportContext::StartElement(xAttrList); + } + virtual void EndElement() override + { + // expected-error@+1 {{don't call this superclass method [loplugin:xmlimport]}} + SvXMLImportContext::EndElement(); + } + virtual void Characters(const OUString& rChars) override + { + // expected-error@+1 {{don't call this superclass method [loplugin:xmlimport]}} + SvXMLImportContext::Characters(rChars); + } + virtual SvXMLImportContextRef CreateChildContext() override + { + // expected-error@+1 {{don't call this superclass method [loplugin:xmlimport]}} + return SvXMLImportContext::CreateChildContext(); + } +}; + +// no warning expected +class Test9a : public SvXMLImportContext +{ +public: + virtual void StartElement(const css::uno::Reference&) override + { + xxx(); + } +}; +class Test9b : public Test9a +{ +public: + virtual void + StartElement(const css::uno::Reference& xAttrList) override + { + Test9a::StartElement(xAttrList); + } +}; + +class Test10a : public SvXMLImportContext +{ +public: + // expected-error@+1 {{empty, should be removed [loplugin:xmlimport]}} + virtual void startFastElement() override {} + // expected-error@+1 {{empty, should be removed [loplugin:xmlimport]}} + virtual void endFastElement() override {} + // expected-error@+1 {{empty, should be removed [loplugin:xmlimport]}} + virtual void characters(const OUString&) override {} + // expected-error@+1 {{empty, should be removed [loplugin:xmlimport]}} + virtual css::uno::Reference + createFastChildContext() override + { + return nullptr; + } + // expected-error@+1 {{empty, should be removed [loplugin:xmlimport]}} + virtual css::uno::Reference + createUnknownChildContext() override + { + return nullptr; + } +}; +// no warning expected +class Test10b : public SvXMLImportContext +{ +public: + virtual void StartElement(const css::uno::Reference&) override {} + virtual void EndElement() override {} + virtual void Characters(const OUString&) override {} + virtual SvXMLImportContextRef CreateChildContext() override { return nullptr; } +}; + +enum XmlTokens +{ + XML_TOK_1 +}; + +void test20(sal_uInt32 p, sal_uInt16 q, XmlTokens e) +{ + // expected-error@+1 {{comparing XML_TOK enum to 'sal_uInt32', expected sal_uInt16 [loplugin:xmlimport]}} + if (p == XML_TOK_1) + ; + // no warning expected + if (q == XML_TOK_1) + ; + switch (p) + { + // expected-error@+1 {{comparing XML_TOK enum to 'sal_uInt32', expected sal_uInt16 [loplugin:xmlimport]}} + case XML_TOK_1: + break; + } + switch (q) + { + // no warning expected + case XML_TOK_1: + break; + } + switch (e) + { + // no warning expected + case XML_TOK_1: + break; + } +} +void callInt32(sal_Int32); +void test21() +{ + // expected-error@+1 {{passing XML_TOK enum to 'sal_Int32', wrong param or XML token type [loplugin:xmlimport]}} + callInt32(XML_TOK_1); +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/toolslong.cxx b/compilerplugins/clang/toolslong.cxx new file mode 100644 index 000000000..35a7223bd --- /dev/null +++ b/compilerplugins/clang/toolslong.cxx @@ -0,0 +1,653 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include + +#include "clang/AST/Attr.h" +#include "clang/Basic/Builtins.h" + +#include "config_clang.h" + +#include "check.hxx" +#include "plugin.hxx" + +namespace +{ +bool isLong(QualType type) +{ + type = type.getNonReferenceType(); + // ignore sal_Int64 + if (type->getAs()) + return false; + // some parts of the STL have ::difference_type => long + if (type->getAs() || type->getAs()) + return false; + if (type->isSpecificBuiltinType(BuiltinType::Kind::Long)) + return true; + auto arrayType = type->getAsArrayTypeUnsafe(); + if (arrayType) + return isLong(arrayType->getElementType()); + if (type->isPointerType()) + return isLong(type->getPointeeType()); + return false; +} + +enum class OverrideKind +{ + NO, + YES, + MAYBE +}; + +OverrideKind getOverrideKind(FunctionDecl const* decl) +{ + CXXMethodDecl const* m = dyn_cast(decl); + if (m == nullptr) + return OverrideKind::NO; + if (m->size_overridden_methods() != 0 || m->hasAttr()) + return OverrideKind::YES; + if (!dyn_cast(m->getDeclContext())->hasAnyDependentBases()) + return OverrideKind::NO; + return OverrideKind::MAYBE; +} + +class ToolsLong : public loplugin::FilteringRewritePlugin +{ +public: + explicit ToolsLong(loplugin::InstantiationData const& data) + : loplugin::FilteringRewritePlugin(data) + { + } + + virtual void run() override; + + bool VisitCStyleCastExpr(CStyleCastExpr* expr); + + bool VisitCXXStaticCastExpr(CXXStaticCastExpr* expr); + + bool VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr* expr); + + bool WalkUpFromParmVarDecl(ParmVarDecl const* decl); + bool VisitParmVarDecl(ParmVarDecl const* decl); + + bool WalkUpFromVarDecl(VarDecl const* decl); + bool VisitVarDecl(VarDecl const* decl); + + bool WalkUpFromFieldDecl(FieldDecl const* decl); + bool VisitFieldDecl(FieldDecl const* decl); + + bool WalkUpFromFunctionDecl(FunctionDecl const* decl); + bool VisitFunctionDecl(FunctionDecl const* decl); + + bool VisitCallExpr(CallExpr const* expr); + +private: + bool rewrite(SourceLocation location); + bool isExcludedFile(SourceLocation spellingLocation) const; + /** sort by the reverse of source order, so we can do replacing from the end of the file backwards, + which means we reduce the chances of having overlapping changes. */ + template + std::vector> reverseSourceOrder(std::map const& map) const + { + std::vector> vec(map.begin(), map.end()); + std::sort(vec.begin(), vec.end(), + [&](std::pair const& lhs, std::pair const& rhs) { + return compiler.getSourceManager().getCharacterData(lhs.first->getBeginLoc()) + > compiler.getSourceManager().getCharacterData( + rhs.first->getBeginLoc()); + }); + return vec; + } + + std::map varDecls_; + std::map fieldDecls_; + std::map parmVarDecls_; + std::map functionDecls_; + std::map staticCasts_; + std::map functionalCasts_; +}; + +void ToolsLong::run() +{ + if (!compiler.getLangOpts().CPlusPlus) + return; + + StringRef fn(handler.getMainFileName()); + // sberg says this is fine + if (loplugin::isSamePathname(fn, SRCDIR "/avmedia/source/win/framegrabber.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/avmedia/source/win/manager.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/avmedia/source/win/player.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/avmedia/source/win/window.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/connectivity/source/drivers/ado/AStatement.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/connectivity/source/drivers/ado/Awrapado.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/desktop/win32/source/loader.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/extensions/source/activex/SOActiveX.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/pyuno/source/module/pyuno.cxx") + || loplugin::isSamePathname(fn, SRCDIR + "/setup_native/source/win32/customactions/sellang/sellang.cxx") + || loplugin::isSamePathname(fn, SRCDIR + "/shell/source/win32/shlxthandler/ooofilt/stream_helper.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/shell/source/win32/zipfile/zipfile.cxx") + || loplugin::isSamePathname(fn, SRCDIR "/ucb/source/ucp/webdav-curl/CurlSession.cxx")) + return; + // these are places where the external API is actually "long" + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/filter/jpeg/JpegReader.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/writerperfect/source/common/DirectoryStream.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/writerperfect/source/common/WPXSvInputStream.cxx")) + return; + if (loplugin::isSamePathname(fn, + SRCDIR "/writerperfect/source/calc/MSWorksCalcImportFilter.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/writerperfect/qa/unit/WPXSvStreamTest.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/desktop/source/lib/init.cxx")) + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + for (auto const& dcl : reverseSourceOrder(varDecls_)) + { + auto const decl = dcl.first; + SourceLocation loc{ decl->getBeginLoc() }; + TypeSourceInfo* tsi = decl->getTypeSourceInfo(); + if (tsi != nullptr) + { + SourceLocation l{ compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getBeginLoc()) }; + SourceLocation end{ compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getEndLoc()) }; + assert(l.isFileID() && end.isFileID()); + if (l == end || compiler.getSourceManager().isBeforeInTranslationUnit(l, end)) + { + for (;;) + { + unsigned n = Lexer::MeasureTokenLength(l, compiler.getSourceManager(), + compiler.getLangOpts()); + std::string s{ compiler.getSourceManager().getCharacterData(l), n }; + if (s == "long") + { + loc = l; + break; + } + if (l == end) + { + break; + } + l = l.getLocWithOffset(std::max(n, 1)); + } + } + } + if (!rewrite(loc)) + { + report(DiagnosticsEngine::Warning, "VarDecl, use \"tools::Long\" instead of %0", loc) + << decl->getType().getLocalUnqualifiedType() << decl->getSourceRange(); + } + } + for (auto const& dcl : reverseSourceOrder(fieldDecls_)) + { + auto const decl = dcl.first; + SourceLocation loc{ decl->getBeginLoc() }; + TypeSourceInfo* tsi = decl->getTypeSourceInfo(); + if (tsi != nullptr) + { + SourceLocation l{ compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getBeginLoc()) }; + SourceLocation end{ compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getEndLoc()) }; + assert(l.isFileID() && end.isFileID()); + if (l == end || compiler.getSourceManager().isBeforeInTranslationUnit(l, end)) + { + for (;;) + { + unsigned n = Lexer::MeasureTokenLength(l, compiler.getSourceManager(), + compiler.getLangOpts()); + std::string s{ compiler.getSourceManager().getCharacterData(l), n }; + if (s == "long") + { + loc = l; + break; + } + if (l == end) + { + break; + } + l = l.getLocWithOffset(std::max(n, 1)); + } + } + } + if (!rewrite(loc)) + { + report(DiagnosticsEngine::Warning, "FieldDecl, use \"tools::Long\" instead of %0", loc) + << decl->getType().getLocalUnqualifiedType() << decl->getSourceRange(); + } + } + for (auto const& dcl : reverseSourceOrder(parmVarDecls_)) + { + auto const decl = dcl.first; + SourceLocation loc{ decl->getBeginLoc() }; + TypeSourceInfo* tsi = decl->getTypeSourceInfo(); + if (tsi != nullptr) + { + SourceLocation l{ compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getBeginLoc()) }; + SourceLocation end{ compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getEndLoc()) }; + assert(l.isFileID() && end.isFileID()); + if (l == end || (compiler.getSourceManager().isBeforeInTranslationUnit(l, end))) + { + for (;;) + { + unsigned n = Lexer::MeasureTokenLength(l, compiler.getSourceManager(), + compiler.getLangOpts()); + std::string s{ compiler.getSourceManager().getCharacterData(l), n }; + if (s == "long") + { + loc = l; + break; + } + if (l == end) + { + break; + } + l = l.getLocWithOffset(std::max(n, 1)); + } + } + } + FunctionDecl const* f = dyn_cast_or_null(decl->getDeclContext()); + if (f) + f = f->getCanonicalDecl(); + OverrideKind k = f ? getOverrideKind(f) : OverrideKind::NO; + if (k == OverrideKind::MAYBE || !rewrite(loc)) + { + report(DiagnosticsEngine::Warning, + ("ParmVarDecl, use \"tools::Long\" instead of" + " %0%1"), + loc) + << decl->getType().getNonReferenceType().getLocalUnqualifiedType() + << (k == OverrideKind::MAYBE ? (" (unless this member function overrides a" + " dependent base member function, even" + " though it is not marked 'override')") + : "") + << decl->getSourceRange(); + } + } + for (auto const& dcl : functionDecls_) + { + auto const decl = dcl.first; + SourceLocation loc{ decl->getBeginLoc() }; + SourceLocation l{ compiler.getSourceManager().getExpansionLoc(loc) }; + SourceLocation end{ compiler.getSourceManager().getExpansionLoc( + decl->getNameInfo().getLoc()) }; + assert(l.isFileID() && end.isFileID()); + if (compiler.getSourceManager().isBeforeInTranslationUnit(l, end)) + { + while (l != end) + { + unsigned n = Lexer::MeasureTokenLength(l, compiler.getSourceManager(), + compiler.getLangOpts()); + std::string s{ compiler.getSourceManager().getCharacterData(l), n }; + if (s == "long") + { + loc = l; + break; + } + l = l.getLocWithOffset(std::max(n, 1)); + } + } + if (rewrite(loc)) + continue; + report(DiagnosticsEngine::Warning, "use \"tools::Long\" instead of %0 as return type%1", + loc) + << decl->getReturnType().getNonReferenceType().getLocalUnqualifiedType() + << (getOverrideKind(decl) == OverrideKind::MAYBE + ? (" (unless this member function overrides a dependent" + " base member function, even though it is not marked" + " 'override')") + : "") + << decl->getSourceRange(); + } + + for (auto const& dcl : staticCasts_) + { + auto const expr = dcl.first; + SourceLocation loc{ expr->getBeginLoc() }; + TypeSourceInfo* tsi = expr->getTypeInfoAsWritten(); + if (tsi != nullptr) + { + SourceLocation l{ compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getBeginLoc()) }; + SourceLocation end{ compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getEndLoc()) }; + assert(l.isFileID() && end.isFileID()); + if (l == end || compiler.getSourceManager().isBeforeInTranslationUnit(l, end)) + { + for (;;) + { + unsigned n = Lexer::MeasureTokenLength(l, compiler.getSourceManager(), + compiler.getLangOpts()); + std::string s{ compiler.getSourceManager().getCharacterData(l), n }; + if (s == "long") + { + loc = l; + break; + } + if (l == end) + { + break; + } + l = l.getLocWithOffset(std::max(n, 1)); + } + } + } + if (!rewrite(loc)) + { + report(DiagnosticsEngine::Warning, "CXXStaticCastExpr, suspicious cast from %0 to %1", + expr->getBeginLoc()) + << expr->getSubExpr()->IgnoreParenImpCasts()->getType() << expr->getType() + << expr->getSourceRange(); + } + } + + for (auto const& dcl : functionalCasts_) + { + auto const expr = dcl.first; + SourceLocation loc{ expr->getBeginLoc() }; + TypeSourceInfo* tsi = expr->getTypeInfoAsWritten(); + if (tsi != nullptr) + { + SourceLocation l{ compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getBeginLoc()) }; + SourceLocation end{ compiler.getSourceManager().getExpansionLoc( + tsi->getTypeLoc().getEndLoc()) }; + assert(l.isFileID() && end.isFileID()); + if (l == end || compiler.getSourceManager().isBeforeInTranslationUnit(l, end)) + { + for (;;) + { + unsigned n = Lexer::MeasureTokenLength(l, compiler.getSourceManager(), + compiler.getLangOpts()); + std::string s{ compiler.getSourceManager().getCharacterData(l), n }; + if (s == "long") + { + loc = l; + break; + } + if (l == end) + { + break; + } + l = l.getLocWithOffset(std::max(n, 1)); + } + } + } + if (!rewrite(loc)) + { + report(DiagnosticsEngine::Warning, + "CXXFunctionalCastExpr, suspicious cast from %0 to %1", expr->getBeginLoc()) + << expr->getSubExpr()->IgnoreParenImpCasts()->getType() << expr->getType() + << expr->getSourceRange(); + } + } +} + +bool ToolsLong::VisitCStyleCastExpr(CStyleCastExpr* expr) +{ + if (ignoreLocation(expr)) + return true; + if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc()))) + return true; + auto const k = isLong(expr->getType()); + if (!k) + return true; + SourceLocation loc{ expr->getBeginLoc() }; + while (compiler.getSourceManager().isMacroArgExpansion(loc)) + loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc); + if (compiler.getSourceManager().isMacroBodyExpansion(loc) + && compiler.getSourceManager().isInSystemHeader( + compiler.getSourceManager().getSpellingLoc(loc))) + { + return true; + } + report(DiagnosticsEngine::Warning, "CStyleCastExpr, suspicious cast from %0 to %1", + expr->getBeginLoc()) + << expr->getSubExpr()->IgnoreParenImpCasts()->getType() << expr->getType() + << expr->getSourceRange(); + return true; +} + +bool ToolsLong::VisitCXXStaticCastExpr(CXXStaticCastExpr* expr) +{ + if (ignoreLocation(expr)) + return true; + if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc()))) + return true; + auto const k = isLong(expr->getType()); + if (!k) + return true; + staticCasts_.insert({ expr, k }); + return true; +} + +bool ToolsLong::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr* expr) +{ + if (ignoreLocation(expr)) + return true; + if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc()))) + return true; + auto const k = isLong(expr->getType()); + if (!k) + return true; + functionalCasts_.insert({ expr, k }); + return true; +} + +bool ToolsLong::WalkUpFromParmVarDecl(ParmVarDecl const* decl) { return VisitParmVarDecl(decl); } + +bool ToolsLong::VisitParmVarDecl(ParmVarDecl const* decl) +{ + if (ignoreLocation(decl)) + return true; + if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(decl->getLocation()))) + return true; + auto const fbk = isLong(decl->getType()); + if (!fbk) + return true; + FunctionDecl const* f = dyn_cast(decl->getDeclContext()); + if (f) // e.g.: typedef sal_Bool (* FuncPtr )( sal_Bool ); + { + // ignore the function in include/test/cppunitasserthelper.hxx + if (f->getIdentifier() && f->getName() == "assertEquals") + return true; + auto canonicalF = f->getCanonicalDecl(); + if (canonicalF->isDeletedAsWritten() && isa(canonicalF)) + return true; + if (auto const d = dyn_cast(canonicalF)) + { + if (d->isVirtual()) + { + return true; + } + } + // Only rewrite declarations in include files if a definition is + // also seen, to avoid compilation of a definition (in a main file + // only processed later) to fail with a "mismatch" error before the + // rewriter had a chance to act upon the definition: + bool ok = canonicalF->isDefined() + || compiler.getSourceManager().isInMainFile( + compiler.getSourceManager().getSpellingLoc(f->getNameInfo().getLoc())); + if (!ok) + return true; + } + parmVarDecls_.insert({ decl, fbk }); + return true; +} + +bool ToolsLong::WalkUpFromVarDecl(VarDecl const* decl) { return VisitVarDecl(decl); } + +bool ToolsLong::VisitVarDecl(VarDecl const* decl) +{ + if (ignoreLocation(decl)) + return true; + if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(decl->getLocation()))) + return true; + auto k = isLong(decl->getType()); + if (!k) + return true; + varDecls_.insert({ decl, k }); + return true; +} + +bool ToolsLong::WalkUpFromFieldDecl(FieldDecl const* decl) { return VisitFieldDecl(decl); } + +bool ToolsLong::VisitFieldDecl(FieldDecl const* decl) +{ + if (ignoreLocation(decl)) + return true; + if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(decl->getLocation()))) + return true; + auto k = isLong(decl->getType()); + if (!k) + return true; + TagDecl const* td = dyn_cast(decl->getDeclContext()); + if (td == nullptr) + { + //TODO: ObjCInterface + return true; + } + fieldDecls_.insert({ decl, k }); + return true; +} + +bool ToolsLong::WalkUpFromFunctionDecl(FunctionDecl const* decl) { return VisitFunctionDecl(decl); } + +bool ToolsLong::VisitFunctionDecl(FunctionDecl const* decl) +{ + if (ignoreLocation(decl)) + return true; + if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(decl->getLocation()))) + return true; + auto const fbk = isLong(decl->getReturnType()); + if (!fbk) + return true; + if (decl->isDeletedAsWritten() && isa(decl)) + return true; + if (auto const d = dyn_cast(decl)) + { + if (d->isVirtual()) + { + return true; + } + } + if (decl->isDefined() + || compiler.getSourceManager().isInMainFile( + compiler.getSourceManager().getSpellingLoc(decl->getNameInfo().getLoc()))) + { + functionDecls_.insert({ decl, fbk }); + } + return true; +} + +bool ToolsLong::VisitCallExpr(CallExpr const* expr) +{ + if (ignoreLocation(expr)) + { + return true; + } + auto const d1 = expr->getDirectCallee(); + if (d1 == nullptr || !loplugin::DeclCheck(d1).Function("curl_easy_getinfo").GlobalNamespace()) + { + return true; + } + if (expr->getNumArgs() != 3) + { + return true; + } + //TODO: Check expr->getArg(1) is CURLINFO_RESPONSE_CODE + auto const e1 = dyn_cast(expr->getArg(2)->IgnoreParenImpCasts()); + if (e1 == nullptr || e1->getOpcode() != UO_AddrOf) + { + return true; + } + auto const e2 = dyn_cast(e1->getSubExpr()->IgnoreParenImpCasts()); + if (e2 == nullptr) + { + return true; + } + auto const d2 = e2->getDecl(); + if (auto const d3 = dyn_cast(d2)) + { + parmVarDecls_.erase(d3); + } + else if (auto const d4 = dyn_cast(d2)) + { + varDecls_.erase(d4); + } + else if (auto const d5 = dyn_cast(d2)) + { + fieldDecls_.erase(d5); + } + return true; +} + +bool ToolsLong::rewrite(SourceLocation location) +{ + if (rewriter != nullptr) + { + SourceLocation loc{ compiler.getSourceManager().getExpansionLoc(location) }; + unsigned n + = Lexer::MeasureTokenLength(loc, compiler.getSourceManager(), compiler.getLangOpts()); + if (std::string(compiler.getSourceManager().getCharacterData(loc), n) == "long") + { + return replaceText(loc, n, "tools::Long"); + } + } + return false; +} + +bool ToolsLong::isExcludedFile(SourceLocation spellingLocation) const +{ + if (isInUnoIncludeFile(spellingLocation)) + return true; + auto f = getFilenameOfLocation(spellingLocation); + return loplugin::hasPathnamePrefix(f, SRCDIR "/include/cppu/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/include/cppuhelper/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/include/registry/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/include/osl/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/include/rtl/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/include/sal/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/include/salhelper/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/include/typelib/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/include/LibreOfficeKit/") // TODO + || loplugin::hasPathnamePrefix(f, SRCDIR "/bridges/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/codemaker/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/configmgr/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/cppu/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/cppuhelper/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/external/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/libreofficekit/") // TODO + || loplugin::hasPathnamePrefix(f, SRCDIR "/registry/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/rtl/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/sal/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/salhelper/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/soltools/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/unoidl/") + || loplugin::hasPathnamePrefix(f, SRCDIR "/workdir/"); +} + +loplugin::Plugin::Registration X("toolslong", true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/trivialconstructor.cxx b/compilerplugins/clang/trivialconstructor.cxx new file mode 100644 index 000000000..c991d71ae --- /dev/null +++ b/compilerplugins/clang/trivialconstructor.cxx @@ -0,0 +1,156 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +// Look for declared constructors that can be trivial (and therefore don't need to be declared) + +namespace +{ +class TrivialConstructor : public loplugin::FilteringPlugin +{ +public: + explicit TrivialConstructor(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXConstructorDecl(CXXConstructorDecl const*); + +private: + bool HasTrivialConstructorBody(const CXXRecordDecl* BaseClassDecl, + const CXXRecordDecl* MostDerivedClassDecl); + bool FieldHasTrivialConstructorBody(const FieldDecl* Field); +}; + +bool TrivialConstructor::VisitCXXConstructorDecl(CXXConstructorDecl const* constructorDecl) +{ + if (ignoreLocation(constructorDecl)) + return true; + if (!constructorDecl->hasTrivialBody()) + return true; + if (constructorDecl->isExplicit()) + return true; + if (!constructorDecl->isDefaultConstructor()) + return true; + if (constructorDecl->getNumParams() != 0) + return true; + if (!constructorDecl->inits().empty()) + return true; + if (constructorDecl->getExceptionSpecType() != EST_None) + return true; + if (constructorDecl->getAccess() != AS_public) + return true; + if (!constructorDecl->isThisDeclarationADefinition()) + return true; + if (isInUnoIncludeFile( + compiler.getSourceManager().getSpellingLoc(constructorDecl->getLocation()))) + return true; + const CXXRecordDecl* recordDecl = constructorDecl->getParent(); + if (std::distance(recordDecl->ctor_begin(), recordDecl->ctor_end()) != 1) + return true; + // Constructor templates are not included in ctor_begin()..ctor_end() above, so also do a slow + // check across all decls(): + for (auto d : recordDecl->decls()) + { + if (auto const d2 = dyn_cast(d)) + { + if (isa(d2->getTemplatedDecl())) + { + return true; + } + } + } + if (!HasTrivialConstructorBody(recordDecl, recordDecl)) + return true; + + report(DiagnosticsEngine::Warning, "no need for explicit constructor decl", + constructorDecl->getLocation()) + << constructorDecl->getSourceRange(); + if (constructorDecl->getCanonicalDecl() != constructorDecl) + { + constructorDecl = constructorDecl->getCanonicalDecl(); + report(DiagnosticsEngine::Warning, "no need for explicit constructor decl", + constructorDecl->getLocation()) + << constructorDecl->getSourceRange(); + } + return true; +} + +bool TrivialConstructor::HasTrivialConstructorBody(const CXXRecordDecl* BaseClassDecl, + const CXXRecordDecl* MostDerivedClassDecl) +{ + if (BaseClassDecl != MostDerivedClassDecl && !BaseClassDecl->hasTrivialDefaultConstructor()) + return false; + + // Check fields. + for (const auto* field : BaseClassDecl->fields()) + if (!FieldHasTrivialConstructorBody(field)) + return false; + + // Check non-virtual bases. + for (const auto& I : BaseClassDecl->bases()) + { + if (I.isVirtual()) + continue; + if (!I.getType()->isRecordType()) + continue; + const CXXRecordDecl* NonVirtualBase = I.getType()->getAsCXXRecordDecl(); + if (NonVirtualBase && !HasTrivialConstructorBody(NonVirtualBase, MostDerivedClassDecl)) + return false; + } + + if (BaseClassDecl == MostDerivedClassDecl) + { + // Check virtual bases. + for (const auto& I : BaseClassDecl->vbases()) + { + if (!I.getType()->isRecordType()) + continue; + const CXXRecordDecl* VirtualBase = I.getType()->getAsCXXRecordDecl(); + if (VirtualBase && !HasTrivialConstructorBody(VirtualBase, MostDerivedClassDecl)) + return false; + } + } + return true; +} + +bool TrivialConstructor::FieldHasTrivialConstructorBody(const FieldDecl* Field) +{ + QualType FieldBaseElementType = compiler.getASTContext().getBaseElementType(Field->getType()); + + const RecordType* RT = FieldBaseElementType->getAs(); + if (!RT) + return true; + + CXXRecordDecl* FieldClassDecl = cast(RT->getDecl()); + + // The constructor for an implicit anonymous union member is never invoked. + if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion()) + return false; + + return FieldClassDecl->hasTrivialDefaultConstructor(); +} + +loplugin::Plugin::Registration X("trivialconstructor", true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/trivialdestructor.cxx b/compilerplugins/clang/trivialdestructor.cxx new file mode 100644 index 000000000..5db1bbab7 --- /dev/null +++ b/compilerplugins/clang/trivialdestructor.cxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +// Look for explicit destructors that can be trivial (and therefore don't need to be declared) + +namespace +{ +class TrivialDestructor : public loplugin::FilteringPlugin +{ +public: + explicit TrivialDestructor(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXDestructorDecl(CXXDestructorDecl const*); + +private: + bool HasTrivialDestructorBody(const CXXRecordDecl* ClassDecl); + bool FieldHasTrivialDestructor(const FieldDecl* Field); +}; + +bool TrivialDestructor::VisitCXXDestructorDecl(CXXDestructorDecl const* destructorDecl) +{ + if (ignoreLocation(destructorDecl)) + return true; + if (!destructorDecl->isThisDeclarationADefinition()) + return true; + if (!destructorDecl->hasTrivialBody()) + return true; + if (destructorDecl->isVirtual()) + return true; + if (destructorDecl->getExceptionSpecType() != EST_None) + return true; + if (destructorDecl->getAccess() != AS_public) + return true; + if (isInUnoIncludeFile( + compiler.getSourceManager().getSpellingLoc(destructorDecl->getLocation()))) + return true; + if (!HasTrivialDestructorBody(destructorDecl->getParent())) + return true; + + report(DiagnosticsEngine::Warning, "no need for explicit destructor decl", + destructorDecl->getLocation()) + << destructorDecl->getSourceRange(); + for (FunctionDecl const* d2 = destructorDecl;;) + { + d2 = d2->getPreviousDecl(); + if (d2 == nullptr) + { + break; + } + report(DiagnosticsEngine::Note, "previous declaration is here", d2->getLocation()) + << d2->getSourceRange(); + } + return true; +} + +bool TrivialDestructor::HasTrivialDestructorBody(const CXXRecordDecl* ClassDecl) +{ + // Check fields. + for (const auto* field : ClassDecl->fields()) + if (!FieldHasTrivialDestructor(field)) + return false; + + // Check bases. + for (const auto& I : ClassDecl->bases()) + { + const CXXRecordDecl* Base = I.getType()->getAsCXXRecordDecl(); + if (!Base->hasTrivialDestructor()) + return false; + } + + return true; +} + +bool TrivialDestructor::FieldHasTrivialDestructor(const FieldDecl* Field) +{ + QualType FieldBaseElementType = compiler.getASTContext().getBaseElementType(Field->getType()); + + const RecordType* RT = FieldBaseElementType->getAs(); + if (!RT) + return true; + + CXXRecordDecl* FieldClassDecl = cast(RT->getDecl()); + + return FieldClassDecl->hasTrivialDestructor(); +} + +loplugin::Plugin::Registration X("trivialdestructor", true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/typedefparam.cxx b/compilerplugins/clang/typedefparam.cxx new file mode 100644 index 000000000..b7e57b2a1 --- /dev/null +++ b/compilerplugins/clang/typedefparam.cxx @@ -0,0 +1,334 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include "config_clang.h" + +#include "check.hxx" +#include "plugin.hxx" + +/** + Check that parameters at the declaration site and the definition site are the same. + This can be important when refactoring, and can sometimes make a difference when compiling + for platforms with different pointer-sizes (e.g. 32 vs 64 bit) + */ +namespace +{ +class TypedefParam : public loplugin::FilteringRewritePlugin +{ +public: + explicit TypedefParam(loplugin::InstantiationData const& data) + : FilteringRewritePlugin(data) + { + } + + void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitFunctionDecl(FunctionDecl const*); + bool VisitCXXMethodDecl(CXXMethodDecl const*); +}; + +static bool areTypesEqual(QualType lhs, QualType rhs); + +bool TypedefParam::VisitFunctionDecl(FunctionDecl const* functionDecl) +{ + if (ignoreLocation(functionDecl)) + return true; + if (functionDecl->isFunctionTemplateSpecialization()) + return true; + auto canonicalDecl = functionDecl->getCanonicalDecl(); + if (canonicalDecl == functionDecl) + return true; + + for (unsigned i = 0; i < functionDecl->getNumParams(); ++i) + { + ParmVarDecl const* thisParam = functionDecl->getParamDecl(i); + ParmVarDecl const* canonicalParam = canonicalDecl->getParamDecl(i); + if (!areTypesEqual(thisParam->getType(), canonicalParam->getType())) + { +#if defined _WIN32 + // SAL_IMPLEMENT_MAIN (include/sal/main.h) declares the third parameter of WinMain to be + // of type 'char *' rather than 'LPSTR', but using that typedef there would require + // including windows.h, which would require including include/prewin.h and + // include/postwin.h (to undo macros like Yield defined in windows.h) but which (unlike + // include/sal/main.h) are not part of the stable URE interface; so just ignore that + // here: + if (loplugin::DeclCheck(functionDecl).Function("WinMain").GlobalNamespace()) + { + continue; + } +#endif + report(DiagnosticsEngine::Warning, + "function param %0 at definition site does not match function param at " + "declaration site, %1 vs %2", + thisParam->getLocation()) + << (i + 1) << thisParam->getType() << canonicalParam->getType() + << functionDecl->getSourceRange(); + report(DiagnosticsEngine::Note, "declaration site here", canonicalParam->getLocation()) + << canonicalDecl->getSourceRange(); + } + } + + if (!areTypesEqual(functionDecl->getReturnType(), canonicalDecl->getReturnType())) + { + report(DiagnosticsEngine::Warning, + "function return type at definition site does not match function param at " + "declaration site, %0 vs %1", + functionDecl->getBeginLoc()) + << functionDecl->getReturnType() << canonicalDecl->getReturnType() + << functionDecl->getSourceRange(); + report(DiagnosticsEngine::Note, "declaration site here", canonicalDecl->getBeginLoc()) + << canonicalDecl->getSourceRange(); + } + return true; +} + +bool TypedefParam::VisitCXXMethodDecl(CXXMethodDecl const* methodDecl) +{ + if (ignoreLocation(methodDecl)) + return true; + if (methodDecl->isFunctionTemplateSpecialization()) + return true; + // only warn on the declaration site + if (methodDecl->getCanonicalDecl() != methodDecl) + return true; + + StringRef aFileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(methodDecl->getBeginLoc())); + // seems to be using typedefs as a form of documentation for method params + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/sw/source/filter/ww8/ww8scan.hxx")) + return true; + // necessary to work around changes in popplers API + if (loplugin::hasPathnamePrefix(aFileName, SRCDIR + "/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.hxx")) + return true; + + for (auto superMethodIt = methodDecl->begin_overridden_methods(); + superMethodIt != methodDecl->end_overridden_methods(); ++superMethodIt) + { + const CXXMethodDecl* superMethodDecl = *superMethodIt; + int i = 0; + for (const ParmVarDecl* superParmVarDecl : superMethodDecl->parameters()) + { + const ParmVarDecl* parmVarDecl = methodDecl->getParamDecl(i); + if (!areTypesEqual(parmVarDecl->getType(), superParmVarDecl->getType())) + { + report(DiagnosticsEngine::Warning, + "method param %0 does not match overridden method param " + "%1 vs %2", + parmVarDecl->getLocation()) + << (i + 1) << parmVarDecl->getType() << superParmVarDecl->getType() + << methodDecl->getSourceRange(); + report(DiagnosticsEngine::Note, "super-class method here", + superParmVarDecl->getLocation()) + << superMethodDecl->getSourceRange(); + } + ++i; + } + + // it is quite normal to override a method and return a more specific pointer/reference type + auto returnType = methodDecl->getReturnType(); + if (!returnType->isPointerType() && !returnType->isReferenceType()) + if (!areTypesEqual(returnType, superMethodDecl->getReturnType())) + { + report(DiagnosticsEngine::Warning, + "method return type does not match overridden method " + "%0 vs %1", + methodDecl->getBeginLoc()) + << methodDecl->getReturnType() << superMethodDecl->getReturnType() + << methodDecl->getSourceRange(); + report(DiagnosticsEngine::Note, "super-class method here", + superMethodDecl->getBeginLoc()) + << superMethodDecl->getSourceRange(); + } + } + return true; +} + +static bool areTypesEqual(QualType lhs, QualType rhs) +{ + if (lhs == rhs) + return true; + + // ignore template stuff + if (lhs->isDependentType() || rhs->isDependentType()) + return true; + // there are some places, e.g. chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx + // where just unwrapping these types does not work, so just ignore them + if (isa(lhs) || isa(rhs)) + return true; + + auto lhsType = lhs.getTypePtr(); + auto rhsType = rhs.getTypePtr(); + + // this is the carve-out exception for the "typedef struct S {...} T" idiom we use in the UNO code + if (auto lhsPointer = dyn_cast(lhsType)) + { + if (auto rhsPointer = dyn_cast(rhsType)) + { + auto extractRecordType = [](clang::QualType type) { + auto recordType = dyn_cast(type); + if (recordType) + return recordType; + auto elaboratedType = dyn_cast(type); + if (!elaboratedType) + return static_cast(nullptr); + return dyn_cast(elaboratedType->desugar()); + }; + auto containsTypedefToRecord = [](clang::QualType type, RecordType const* recordType) { + TypedefType const* typedefType = dyn_cast(type); + if (!typedefType) + return false; + auto tmp = typedefType->desugar(); + if (auto elaboratedType = dyn_cast(tmp)) + tmp = elaboratedType->desugar(); + return tmp.getTypePtr() == recordType; + }; + if (auto recordType = extractRecordType(lhsPointer->getPointeeType())) + if (containsTypedefToRecord(rhsPointer->getPointeeType(), recordType)) + return true; + if (auto recordType = extractRecordType(rhsPointer->getPointeeType())) + if (containsTypedefToRecord(lhsPointer->getPointeeType(), recordType)) + return true; + } + } + + if (auto lhsElaborated = dyn_cast(lhsType)) + { + return areTypesEqual(lhsElaborated->getNamedType(), rhs); + } + if (auto rhsElaborated = dyn_cast(rhsType)) + { + return areTypesEqual(lhs, rhsElaborated->getNamedType()); + } + if (auto lhsTemplate = dyn_cast(lhsType)) + { + return areTypesEqual(lhsTemplate->desugar(), rhs); + } + if (auto rhsTemplate = dyn_cast(rhsType)) + { + return areTypesEqual(lhs, rhsTemplate->desugar()); + } + + if (auto lhsLValue = dyn_cast(lhsType)) + { + auto rhsLValue = dyn_cast(rhsType); + if (!rhsLValue) + return false; + return areTypesEqual(lhsLValue->getPointeeType(), rhsLValue->getPointeeType()); + } + if (auto lhsRValue = dyn_cast(lhsType)) + { + auto rhsRValue = dyn_cast(rhsType); + if (!rhsRValue) + return false; + return areTypesEqual(lhsRValue->getPointeeType(), rhsRValue->getPointeeType()); + } + if (auto lhsPointer = dyn_cast(lhsType)) + { + auto rhsPointer = dyn_cast(rhsType); + if (!rhsPointer) + return false; + return areTypesEqual(lhsPointer->getPointeeType(), rhsPointer->getPointeeType()); + } + if (auto lhsTypedef = dyn_cast(lhsType)) + { + auto rhsTypedef = dyn_cast(rhsType); + if (!rhsTypedef) + return false; + // comparing the underlying Decl's here doesn't work, they are not unique + if (lhsTypedef->getDecl()->getName() != rhsTypedef->getDecl()->getName()) + return false; +#if defined __APPLE__ + // My Clang trunk .../lib/clang/9.0.0/include/stddef.h has a + // + // typedef long unsigned int size_t; + // + // while /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/ + // SDKs/MacOSX10.14.sdk/usr/include/sys/_types/_size_t.h has a + // + // typedef __darwin_size_t size_t; + // + // where __darwin_size_t is a typedef for long unsigned int, too, so that, depending on the + // order in which those two files get included, either of those two typedefs can act as a + // redeclaration of the other one. However, areTypesEqual would unhelpfully consider such + // different occurrences of size_t to be non-equal, so filter them out here. And, at least + // with my libcxx trunk .../include/c++/v1/cstddef, std::size_t is a using declaration that + // brings size_t from the global namespace into namespace std, so that the above checks for + // ElaboratedType sugar will already have unwrapped those to the size_t typedefs in the + // global namespace here. + if (loplugin::TypeCheck(lhsTypedef).Typedef("size_t").GlobalNamespace() + && loplugin::TypeCheck(rhsTypedef).Typedef("size_t").GlobalNamespace()) + { + return true; + } +#endif + return areTypesEqual(lhsTypedef->desugar(), rhsTypedef->desugar()); + } + if (auto lhsTemplate = dyn_cast(lhsType)) + { + auto rhsTemplate = dyn_cast(rhsType); + if (!rhsTemplate) + return false; + return areTypesEqual(lhsTemplate->desugar(), rhsTemplate->desugar()); + } + if (auto lhsMember = dyn_cast(lhsType)) + { + auto rhsMember = dyn_cast(rhsType); + if (!rhsMember) + return false; + if (lhsMember->getClass() != rhsMember->getClass()) + return true; + return areTypesEqual(lhsMember->getPointeeType(), rhsMember->getPointeeType()); + } + if (auto lhsParen = dyn_cast(lhsType)) + { + auto rhsParen = dyn_cast(rhsType); + if (!rhsParen) + return false; + return areTypesEqual(lhsParen->getInnerType(), rhsParen->getInnerType()); + } + if (dyn_cast(lhsType)) + { + auto rhsFunction = dyn_cast(rhsType); + if (!rhsFunction) + return false; + return true; // TODO + } + if (auto lhsDecayed = dyn_cast(lhsType)) + { + auto rhsDecayed = dyn_cast(rhsType); + if (!rhsDecayed) + return false; + return areTypesEqual(lhsDecayed->getAdjustedType(), rhsDecayed->getAdjustedType()); + } + if (auto lhsAttr = dyn_cast(lhsType)) + { + auto rhsAttr = dyn_cast(rhsType); + if (!rhsAttr) + return false; + return areTypesEqual(lhsAttr->getModifiedType(), rhsAttr->getModifiedType()); + } + return lhsType == rhsType; +} + +loplugin::Plugin::Registration typedefparam("typedefparam"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/typeidcomparison.cxx b/compilerplugins/clang/typeidcomparison.cxx new file mode 100644 index 000000000..359231f26 --- /dev/null +++ b/compilerplugins/clang/typeidcomparison.cxx @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Find (in-)equality comparisons between typeid expressions that can never succeed. For now, just +// detects cases where the two involved types are structurally different, one a pointer type and the +// other a non-pointer type. + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" + +namespace +{ +class TypeidComparison final : public loplugin::FilteringPlugin +{ +public: + explicit TypeidComparison(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + // For CXXRewrittenBinaryOperator `typeid(...) != typeid(...)`: + bool shouldVisitImplicitCode() const { return true; } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const op = expr->getOperator(); + if (op != OO_EqualEqual && op != OO_ExclaimEqual) + { + return true; + } + assert(expr->getNumArgs() == 2); + auto const e1 = dyn_cast(expr->getArg(0)->IgnoreParenImpCasts()); + if (e1 == nullptr) + { + return true; + } + auto const e2 = dyn_cast(expr->getArg(1)->IgnoreParenImpCasts()); + if (e2 == nullptr) + { + return true; + } + auto const t1 = getOperandType(e1); + auto const t2 = getOperandType(e2); + if (t1->isPointerType() == t2->isPointerType()) + { + return true; + } + report(DiagnosticsEngine::Warning, + "comparison of type info of mixed pointer and non-pointer types %0 and %1 can never " + "succeed", + expr->getExprLoc()) + << t1 << t2 << expr->getSourceRange(); + return true; + } + +private: + QualType getOperandType(CXXTypeidExpr const* expr) + { + return expr->isTypeOperand() ? expr->getTypeOperand(compiler.getASTContext()) + : expr->getExprOperand()->getType(); + } +}; + +static loplugin::Plugin::Registration typeidcomparison("typeidcomparison"); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/unicodetochar.cxx b/compilerplugins/clang/unicodetochar.cxx new file mode 100644 index 000000000..e404211ff --- /dev/null +++ b/compilerplugins/clang/unicodetochar.cxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" + +// In C++, find implicit conversions from char16_t (aka sal_Unicode) to char. +// Such places are probably meant to properly work on char16_t instead. + +namespace { + +class UnicodeToChar final: + public loplugin::FilteringPlugin +{ +public: + explicit UnicodeToChar(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + bool PreTraverseCStyleCastExpr(CStyleCastExpr * expr) { + subExprs_.push(expr->getSubExpr()); + return true; + } + bool PostTraverseCStyleCastExpr(CStyleCastExpr *, bool ) { + subExprs_.pop(); + return true; + } + bool TraverseCStyleCastExpr(CStyleCastExpr * expr) { + PreTraverseCStyleCastExpr(expr); + bool ret = RecursiveASTVisitor::TraverseCStyleCastExpr(expr); + PostTraverseCStyleCastExpr(expr, ret); + return ret; + } + + bool PreTraverseCXXStaticCastExpr(CXXStaticCastExpr * expr) { + subExprs_.push(expr->getSubExpr()); + return true; + } + bool PostTraverseCXXStaticCastExpr(CXXStaticCastExpr *, bool) { + subExprs_.pop(); + return true; + } + bool TraverseCXXStaticCastExpr(CXXStaticCastExpr * expr) { + PreTraverseCXXStaticCastExpr(expr); + bool ret = RecursiveASTVisitor::TraverseCXXStaticCastExpr(expr); + PostTraverseCXXStaticCastExpr(expr, ret); + return ret; + } + + bool PreTraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr * expr) { + subExprs_.push(expr->getSubExpr()); + return true; + } + bool PostTraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr *, bool) { + subExprs_.pop(); + return true; + } + bool TraverseCXXFunctionalCastExpr(CXXFunctionalCastExpr * expr) { + PreTraverseCXXFunctionalCastExpr(expr); + bool ret = RecursiveASTVisitor::TraverseCXXFunctionalCastExpr(expr); + PostTraverseCXXFunctionalCastExpr(expr, ret); + return ret; + } + + bool VisitImplicitCastExpr(ImplicitCastExpr const * expr) { + if ((!subExprs_.empty() && expr == subExprs_.top()) + || ignoreLocation(expr)) + { + return true; + } + if (!(loplugin::TypeCheck(expr->getType()).Char() + && expr->getSubExpr()->getType()->isSpecificBuiltinType( + clang::BuiltinType::Char16))) + { + return true; + } + APSInt res; + if (compat::EvaluateAsInt(expr->getSubExpr(), res, compiler.getASTContext()) + && res >= 0 && res <= 0x7F) + { + return true; + } + report( + DiagnosticsEngine::Warning, + "suspicious implicit cast from %0 to %1", + expr->getExprLoc()) + << expr->getSubExpr()->getType() << expr->getType() + << expr->getSourceRange(); + return true; + } + + bool preRun() override { + return compiler.getLangOpts().CPlusPlus; + } + + void run() override { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + +private: + std::stack subExprs_; +}; + +static loplugin::Plugin::Registration unicodetochar("unicodetochar"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/unnecessarycatchthrow.cxx b/compilerplugins/clang/unnecessarycatchthrow.cxx new file mode 100644 index 000000000..0a8265b17 --- /dev/null +++ b/compilerplugins/clang/unnecessarycatchthrow.cxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include +#include "plugin.hxx" + +/** +look for unnecessary blocks that just catch and rethrow: + try { + stuff + } catch (exception const &) { + throw; + } +*/ + +namespace { + +class UnnecessaryCatchThrow: + public loplugin::FilteringPlugin +{ +public: + explicit UnnecessaryCatchThrow(loplugin::InstantiationData const & data): FilteringPlugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXTryStmt(CXXTryStmt const *); +}; + +bool UnnecessaryCatchThrow::VisitCXXTryStmt(CXXTryStmt const * tryStmt) +{ + if (ignoreLocation(tryStmt)) + return true; + if (tryStmt->getNumHandlers() != 1) + return true; + auto catchStmt = tryStmt->getHandler(0); + auto compoundStmt = dyn_cast(catchStmt->getHandlerBlock()); + if (!compoundStmt || compoundStmt->size() != 1) + return true; + auto throwExpr = dyn_cast(compoundStmt->body_front()); + if (!throwExpr) + return true; + auto subExpr = throwExpr->getSubExpr(); + if (subExpr) + { + if (auto cxxConstructExpr = dyn_cast(subExpr)) { + if (!cxxConstructExpr->getConstructor()->isCopyConstructor()) + return true; + if (!cxxConstructExpr->getConstructor()->getParent()->hasAttr()) + return true; + if (cxxConstructExpr->getNumArgs() != 1) + return true; + subExpr = cxxConstructExpr->getArg(0); + } + auto declRefExpr = dyn_cast(subExpr->IgnoreImpCasts()); + if (!declRefExpr) + return true; + if (declRefExpr->getDecl() != catchStmt->getExceptionDecl()) + return true; + } + + report( DiagnosticsEngine::Warning, "unnecessary catch and throw", + catchStmt->getBeginLoc()) + << catchStmt->getSourceRange(); + return true; +} + + +loplugin::Plugin::Registration< UnnecessaryCatchThrow > unnecessarycatchthrow("unnecessarycatchthrow"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unnecessarylocking.cxx b/compilerplugins/clang/unnecessarylocking.cxx new file mode 100644 index 000000000..c00758b81 --- /dev/null +++ b/compilerplugins/clang/unnecessarylocking.cxx @@ -0,0 +1,215 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "config_clang.h" + +#include "plugin.hxx" +#include "check.hxx" + +/** +Look for methods that are taking a lock at the top of the method, but then not +touching any object-local state. In which case the method might not need locking. + +TODO + +(*) check if the data being returned is never modified, in which case locking is not necessary + +*/ + +namespace +{ +class UnnecessaryLocking : public loplugin::FilteringPlugin +{ +public: + explicit UnnecessaryLocking(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual bool preRun() override + { + // StringRef fn(handler.getMainFileName()); + // if (loplugin::isSamePathname(fn, WORKDIR "/YaccTarget/unoidl/source/sourceprovider-parser.cxx")) + // return false; + return true; + } + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool TraverseCXXMethodDecl(CXXMethodDecl*); + bool VisitCXXThisExpr(const CXXThisExpr*); + +private: + bool isSolarMutexLockGuardStmt(const Stmt*); + const Stmt* isOtherMutexLockGuardStmt(const Stmt*); + std::vector m_TouchesThis; + // so we ignore the CxxThisEpxr that references the maMutex in the guard expression + std::vector m_IgnoreThis; +}; + +bool UnnecessaryLocking::TraverseCXXMethodDecl(CXXMethodDecl* cxxMethodDecl) +{ + if (ignoreLocation(cxxMethodDecl)) + return true; + + if (!cxxMethodDecl->isInstance()) + return true; + if (!cxxMethodDecl->isThisDeclarationADefinition()) + return true; + + auto compoundStmt = dyn_cast_or_null(cxxMethodDecl->getBody()); + if (!compoundStmt || compoundStmt->size() < 1) + return true; + + const Stmt* firstStmt = *compoundStmt->body_begin(); + bool solarMutex = isSolarMutexLockGuardStmt(firstStmt); + const Stmt* ignoreThisStmt = nullptr; + if (!solarMutex) + ignoreThisStmt = isOtherMutexLockGuardStmt(firstStmt); + if (!solarMutex && ignoreThisStmt == nullptr) + return true; + + m_TouchesThis.push_back(false); + m_IgnoreThis.push_back(ignoreThisStmt); + + bool rv = FilteringPlugin::TraverseCXXMethodDecl(cxxMethodDecl); + + if (!m_TouchesThis.back()) + { + StringRef fn = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(cxxMethodDecl->getBeginLoc())); + if ( + // template magic + !loplugin::isSamePathname(fn, SRCDIR "/include/comphelper/unique_disposing_ptr.hxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sw/inc/unobaseclass.hxx") + // toolkit needs to lock around access to static methods in vcl + && !loplugin::isSamePathname(fn, SRCDIR "/toolkit/source/awt/vclxtoolkit.cxx") + && !loplugin::isSamePathname(fn, + SRCDIR "/toolkit/source/controls/tree/treecontrolpeer.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/toolkit/source/awt/vclxcontainer.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/toolkit/source/awt/vclxdevice.cxx") + // touching shared global data + && !loplugin::isSamePathname(fn, SRCDIR + "/framework/source/fwi/classes/protocolhandlercache.cxx") + // lock around access to static methods in vcl + && !loplugin::isSamePathname(fn, SRCDIR "/framework/source/services/taskcreatorsrv.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/svx/source/dialog/SafeModeUI.cxx") + && !loplugin::isSamePathname(fn, SRCDIR + "/svx/source/accessibility/AccessibleFrameSelector.cxx") + // not sure + && !loplugin::isSamePathname(fn, SRCDIR "/sfx2/source/dialog/filedlghelper.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sfx2/source/appl/appdispatchprovider.cxx") + // touching shared global data + && !loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/unocore/unoftn.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/unocore/unolinebreak.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/unocore/unoobj.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/unocore/unorefmk.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/unocore/unotbl.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/xml/xmltexti.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/uno/dlelstnr.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/access/accdoc.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/access/acccontext.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/unocore/unocontentcontrol.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/unocore/unobkm.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/docuno.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/afmtuno.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/appluno.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/unoxml/source/dom/documentbuilder.cxx") + && !loplugin::isSamePathname( + fn, SRCDIR "/sd/source/ui/accessibility/AccessibleDrawDocumentView.cxx") + && !loplugin::isSamePathname(fn, SRCDIR "/starmath/source/accessibility.cxx") + && !loplugin::isSamePathname(fn, + SRCDIR "/starmath/source/AccessibleSmElementsControl.cxx")) + { + report(DiagnosticsEngine::Warning, "unnecessary locking", cxxMethodDecl->getBeginLoc()) + << cxxMethodDecl->getSourceRange(); + } + } + + m_TouchesThis.pop_back(); + m_IgnoreThis.pop_back(); + + return rv; +} + +bool UnnecessaryLocking::isSolarMutexLockGuardStmt(const Stmt* stmt) +{ + auto declStmt = dyn_cast(stmt); + if (!declStmt) + return false; + if (!declStmt->isSingleDecl()) + return false; + auto varDecl = dyn_cast(declStmt->getSingleDecl()); + if (!varDecl) + return false; + auto tc = loplugin::TypeCheck(varDecl->getType()); + if (!tc.Class("SolarMutexGuard").GlobalNamespace() + && !tc.Class("SolarMutexClearableGuard").GlobalNamespace() + && !tc.Class("SolarMutexResettableGuard").GlobalNamespace() + && !tc.Class("SolarMutexTryAndBuyGuard").GlobalNamespace()) + return false; + return true; +} + +const Stmt* UnnecessaryLocking::isOtherMutexLockGuardStmt(const Stmt* stmt) +{ + auto declStmt = dyn_cast(stmt); + if (!declStmt) + return nullptr; + if (!declStmt->isSingleDecl()) + return nullptr; + auto varDecl = dyn_cast(declStmt->getSingleDecl()); + if (!varDecl) + return nullptr; + auto tc = loplugin::TypeCheck(varDecl->getType()); + if (!tc.Class("unique_lock").StdNamespace() && !tc.Class("scoped_lock").StdNamespace()) + return nullptr; + auto cxxConstructExpr = dyn_cast(varDecl->getInit()); + if (!cxxConstructExpr || cxxConstructExpr->getNumArgs() < 1) + return nullptr; + auto memberExpr = dyn_cast(cxxConstructExpr->getArg(0)); + if (!memberExpr) + return nullptr; + auto thisStmt = memberExpr->getBase(); + return thisStmt; +} + +bool UnnecessaryLocking::VisitCXXThisExpr(const CXXThisExpr* cxxThisExpr) +{ + if (ignoreLocation(cxxThisExpr)) + return true; + // just in case + if (m_TouchesThis.empty()) + return true; + // already found something + if (m_TouchesThis.back()) + return true; + if (m_IgnoreThis.back() && m_IgnoreThis.back() == cxxThisExpr) + return true; + m_TouchesThis.back() = true; + return true; +} + +/** off by default because each warning needs to be carefully inspected */ +loplugin::Plugin::Registration unnecessarylocking("unnecessarylocking", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unnecessaryoverride.cxx b/compilerplugins/clang/unnecessaryoverride.cxx new file mode 100644 index 000000000..d3c67b492 --- /dev/null +++ b/compilerplugins/clang/unnecessaryoverride.cxx @@ -0,0 +1,539 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include + +#include +#include "config_clang.h" +#include "plugin.hxx" +#include "check.hxx" + +/** +look for methods where all they do is call their superclass method +*/ + +namespace { + +bool hasMultipleBaseInstances_( + CXXRecordDecl const * derived, CXXRecordDecl const * canonicBase, + bool & hasAsNonVirtualBase, bool & hasAsVirtualBase) +{ + for (auto i = derived->bases_begin(); i != derived->bases_end(); ++i) { + auto const cls = i->getType()->getAsCXXRecordDecl(); + if (cls == nullptr) { + assert(i->getType()->isDependentType()); + // Conservatively assume "yes" for dependent bases: + return true; + } + if (cls->getCanonicalDecl() == canonicBase) { + if (i->isVirtual()) { + if (hasAsNonVirtualBase) { + return true; + } + hasAsVirtualBase = true; + } else { + if (hasAsNonVirtualBase || hasAsVirtualBase) { + return true; + } + hasAsNonVirtualBase = true; + } + } else if (hasMultipleBaseInstances_( + cls, canonicBase, hasAsNonVirtualBase, hasAsVirtualBase)) + { + return true; + } + } + return false; +} + +bool hasMultipleBaseInstances( + CXXRecordDecl const * derived, CXXRecordDecl const * base) +{ + bool nonVirt = false; + bool virt = false; + return hasMultipleBaseInstances_( + derived, base->getCanonicalDecl(), nonVirt, virt); +} + +class UnnecessaryOverride: + public loplugin::FilteringPlugin +{ +public: + explicit UnnecessaryOverride(loplugin::InstantiationData const & data): FilteringPlugin(data) {} + + virtual bool preRun() override + { + // ignore some files with problematic macros + StringRef fn(handler.getMainFileName()); + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/framework/factories/ChildWindowPane.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/Date.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/Time.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/dialog/hyperdlg.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/dialog/rubydialog.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/canvas/")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/view/spelldialog.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/dlg/SpellDialogChildWindow.cxx")) + return false; + // HAVE_ODBC_ADMINISTRATION + if (loplugin::isSamePathname(fn, SRCDIR "/dbaccess/source/ui/dlg/dsselect.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/unotools/source/streaming/streamhelper.cxx")) + return false; + return true; + } + + virtual void run() override + { + if( preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXMethodDecl(const CXXMethodDecl *); + +private: + const CXXMethodDecl * findOverriddenOrSimilarMethodInSuperclasses(const CXXMethodDecl *); + bool BaseCheckCallback(const CXXRecordDecl *BaseDefinition); + CXXMemberCallExpr const * extractCallExpr(Expr const *); +}; + +bool UnnecessaryOverride::VisitCXXMethodDecl(const CXXMethodDecl* methodDecl) +{ + if (ignoreLocation(methodDecl->getCanonicalDecl())) { + return true; + } + if (isa(methodDecl)) { + return true; + } + + StringRef aFileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(methodDecl->getBeginLoc())); + + if (isa(methodDecl) + && !isInUnoIncludeFile(methodDecl)) + { + // the code is this method is only __compiled__ if OSL_DEBUG_LEVEL > 1 + if (loplugin::isSamePathname(aFileName, SRCDIR "/tools/source/stream/strmunx.cxx")) + return true; + + // Warn about unnecessarily user-declared destructors. + // A destructor is deemed unnecessary if: + // * it is public; + // * its class is only defined in the .cxx file (i.e., the virtual + // destructor is neither used to control the place of vtable + // emission, nor is its definition depending on types that may still + // be incomplete); + // or + // the destructor is inline, the class definition is complete, + // and the class has no superclasses + // * it either does not have an explicit exception specification, or has + // a non-dependent explicit exception specification that is compatible + // with a non-dependent exception specification the destructor would + // have if it did not have an explicit one (TODO); + // * it is either defined as defaulted or with an empty body. + // Removing the user-declared destructor may cause the class to get an + // implicitly declared move constructor and/or move assignment operator; + // that is considered acceptable: If any subobject cannot be moved, the + // implicitly declared function will be defined as deleted (which is in + // practice not much different from not having it declared), and + // otherwise offering movability is likely even an improvement over not + // offering it due to a "pointless" user-declared destructor. + // Similarly, removing the user-declared destructor may cause the + // implicit definition of a copy constructor and/or copy assignment + // operator to change from being an obsolete feature to being a standard + // feature. That difference is not taken into account here. + auto cls = methodDecl->getParent(); + if (methodDecl->getAccess() != AS_public) + { + return true; + } + if (!compiler.getSourceManager().isInMainFile( + methodDecl->getCanonicalDecl()->getLocation()) + && !( methodDecl->isInlined())) + { + return true; + } + // if it's virtual, but it has a base-class with a non-virtual destructor + if (methodDecl->isVirtual()) + { + bool baseWithVirtualDtor = false; + for (auto baseSpecifier = cls->bases_begin(); baseSpecifier != cls->bases_end(); ++baseSpecifier) + { + const RecordType* baseRecordType = baseSpecifier->getType()->getAs(); + if (baseRecordType) + { + const CXXRecordDecl* baseRecordDecl = dyn_cast(baseRecordType->getDecl()); + if (baseRecordDecl && baseRecordDecl->getDestructor() + && baseRecordDecl->getDestructor()->isVirtual()) + { + baseWithVirtualDtor = true; + break; + } + } + } + if (!baseWithVirtualDtor) + { + return true; + } + } + if (methodDecl->isExplicitlyDefaulted()) { + if (methodDecl->getPreviousDecl() != nullptr) { + return true; + } + } else { + if (!methodDecl->doesThisDeclarationHaveABody() + || methodDecl->isLateTemplateParsed()) + { + return true; + } + auto stmt = dyn_cast(methodDecl->getBody()); + if (stmt == nullptr || stmt->size() != 0) { + return true; + } + } + //TODO: exception specification + if (!(cls->hasUserDeclaredCopyConstructor() + || cls->hasUserDeclaredCopyAssignment() + || cls->hasUserDeclaredMoveConstructor() + || cls->hasUserDeclaredMoveAssignment())) + { + } + if ((cls->needsImplicitMoveConstructor() + && !(cls->hasUserDeclaredCopyConstructor() + || cls->hasUserDeclaredCopyAssignment() + || cls->hasUserDeclaredMoveAssignment())) + || (cls->needsImplicitMoveAssignment() + && !(cls->hasUserDeclaredCopyConstructor() + || cls->hasUserDeclaredCopyAssignment() + || cls->hasUserDeclaredMoveConstructor()))) + { + report(DiagnosticsEngine::Fatal, "TODO", methodDecl->getLocation()); + return true; + } + report( + DiagnosticsEngine::Warning, "unnecessary user-declared destructor", + methodDecl->getLocation()) + << methodDecl->getSourceRange(); + auto cd = methodDecl->getCanonicalDecl(); + if (cd->getLocation() != methodDecl->getLocation()) { + report(DiagnosticsEngine::Note, "declared here", cd->getLocation()) + << cd->getSourceRange(); + } + return true; + } + + if (!methodDecl->doesThisDeclarationHaveABody() + || methodDecl->isLateTemplateParsed()) + { + return true; + } + + // If overriding more than one base member function, or one base member + // function that is available in multiple (non-virtual) base class + // instances, then this is a disambiguating override: + if (methodDecl->isVirtual()) { + if (methodDecl->size_overridden_methods() != 1) + { + return true; + } + if (hasMultipleBaseInstances( + methodDecl->getParent(), + (*methodDecl->begin_overridden_methods())->getParent())) + { + return true; + } + } + + const CXXMethodDecl* overriddenMethodDecl = findOverriddenOrSimilarMethodInSuperclasses(methodDecl); + if (!overriddenMethodDecl) { + return true; + } + + // Check for differences in default parameters: + unsigned const numParams = methodDecl->getNumParams(); + assert(overriddenMethodDecl->getNumParams() == numParams); + for (unsigned i = 0; i != numParams; ++i) { + if (checkIdenticalDefaultArguments( + methodDecl->getParamDecl(i)->getDefaultArg(), + overriddenMethodDecl->getParamDecl(i)->getDefaultArg()) + != IdenticalDefaultArgumentsResult::Yes) + { + return true; + } + } + + if (methodDecl->getReturnType().getCanonicalType() + != overriddenMethodDecl->getReturnType().getCanonicalType()) + { + return true; + } + + //TODO: check for identical exception specifications + + const CompoundStmt* compoundStmt = dyn_cast(methodDecl->getBody()); + if (!compoundStmt || compoundStmt->size() > 2) + return true; + + const CXXMemberCallExpr* callExpr = nullptr; + if (compoundStmt->size() == 1) + { + if (methodDecl->getReturnType().getCanonicalType()->isVoidType()) + { + if (auto const e = dyn_cast(*compoundStmt->body_begin())) { + callExpr = dyn_cast(e->IgnoreImplicit()->IgnoreParens()); + } + } + else + { + auto returnStmt = dyn_cast(*compoundStmt->body_begin()); + if (returnStmt == nullptr) { + return true; + } + auto returnExpr = returnStmt->getRetValue(); + if (returnExpr == nullptr) { + return true; + } + callExpr = extractCallExpr(returnExpr); + } + } + else if (!methodDecl->getReturnType().getCanonicalType()->isVoidType()) + { + /** handle constructions like + bool foo() { + bool ret = Base::foo(); + return ret; + } + */ + auto bodyIt = compoundStmt->body_begin(); + if (bodyIt == compoundStmt->body_end()) { + return true; + } + auto declStmt = dyn_cast(*bodyIt); + if (!declStmt || !declStmt->isSingleDecl()) + return true; + auto varDecl = dyn_cast(declStmt->getSingleDecl()); + ++bodyIt; + auto returnStmt = dyn_cast(*bodyIt); + if (!varDecl || !returnStmt) + return true; + Expr const * retValue = returnStmt->getRetValue()->IgnoreParenImpCasts(); + if (auto exprWithCleanups = dyn_cast(retValue)) + retValue = exprWithCleanups->getSubExpr()->IgnoreParenImpCasts(); + if (auto constructExpr = dyn_cast(retValue)) { + if (constructExpr->getNumArgs() == 1) + retValue = constructExpr->getArg(0)->IgnoreParenImpCasts(); + } + if (!isa(retValue)) + return true; + callExpr = extractCallExpr(varDecl->getInit()); + } + + if (!callExpr || callExpr->getMethodDecl() != overriddenMethodDecl) + return true; + const Expr* expr1 = callExpr->getImplicitObjectArgument()->IgnoreImpCasts(); + if (!expr1) + return true; + const CXXThisExpr* expr2 = dyn_cast_or_null(expr1); + if (!expr2) + return true; + for (unsigned i = 0; igetNumArgs(); ++i) { + auto e = callExpr->getArg(i)->IgnoreImplicit(); + if (auto const e1 = dyn_cast(e)) { + if (e1->getConstructor()->isCopyOrMoveConstructor() && e1->getNumArgs() == 1) { + e = e1->getArg(0)->IgnoreImpCasts(); + } + } + const DeclRefExpr * declRefExpr = dyn_cast(e); + if (!declRefExpr || declRefExpr->getDecl() != methodDecl->getParamDecl(i)) + return true; + } + + const CXXMethodDecl* pOther = nullptr; + if (methodDecl->getCanonicalDecl()->getLocation() != methodDecl->getLocation()) + pOther = methodDecl->getCanonicalDecl(); + + if (pOther) { + StringRef aFileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(pOther->getBeginLoc())); + // SFX_DECL_CHILDWINDOW_WITHID macro + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/sfx2/childwin.hxx")) + return true; + } + + if (containsPreprocessingConditionalInclusion(methodDecl->getBody()->getSourceRange())) { + return true; + } + + report( + DiagnosticsEngine::Warning, "%0%1 function just calls %2 parent", + methodDecl->getLocation()) + << methodDecl->getAccess() + << (methodDecl->isVirtual() ? " virtual" : "") + << overriddenMethodDecl->getAccess() + << methodDecl->getSourceRange(); + if (methodDecl->getCanonicalDecl()->getLocation() != methodDecl->getLocation()) { + const CXXMethodDecl* pOther = methodDecl->getCanonicalDecl(); + report( + DiagnosticsEngine::Note, + "method declaration here", + pOther->getLocation()) + << pOther->getSourceRange(); + } + return true; +} + +const CXXMethodDecl* UnnecessaryOverride::findOverriddenOrSimilarMethodInSuperclasses(const CXXMethodDecl* methodDecl) +{ + if (methodDecl->isVirtual()) { + return *methodDecl->begin_overridden_methods(); + } + if (!methodDecl->getDeclName().isIdentifier()) { + return nullptr; + } + + const CXXMethodDecl* similarMethod = nullptr; + CXXBasePath similarBasePath; + + auto BaseMatchesCallback = [&](const CXXBaseSpecifier *cxxBaseSpecifier, CXXBasePath& path) + { + if (cxxBaseSpecifier->getAccessSpecifier() != AS_public && cxxBaseSpecifier->getAccessSpecifier() != AS_protected) + return false; + if (!cxxBaseSpecifier->getType().getTypePtr()) + return false; + const CXXRecordDecl* baseCXXRecordDecl = cxxBaseSpecifier->getType()->getAsCXXRecordDecl(); + if (!baseCXXRecordDecl) + return false; + if (baseCXXRecordDecl->isInvalidDecl()) + return false; + for (const CXXMethodDecl* baseMethod : baseCXXRecordDecl->methods()) + { + auto effectiveBaseMethodAccess = baseMethod->getAccess(); + if (effectiveBaseMethodAccess == AS_public && path.Access == AS_protected) + effectiveBaseMethodAccess = AS_protected; + if (effectiveBaseMethodAccess != methodDecl->getAccess()) + continue; + if (!baseMethod->getDeclName().isIdentifier() || methodDecl->getName() != baseMethod->getName()) { + continue; + } + if (methodDecl->isStatic() != baseMethod->isStatic() + || methodDecl->isConst() != baseMethod->isConst() + || methodDecl->isVolatile() != baseMethod->isVolatile() + || (methodDecl->getRefQualifier() + != baseMethod->getRefQualifier()) + || methodDecl->isVariadic() != baseMethod->isVariadic()) + { + continue; + } + if (methodDecl->getReturnType().getCanonicalType() + != baseMethod->getReturnType().getCanonicalType()) + { + continue; + } + if (methodDecl->getNumParams() != baseMethod->getNumParams()) + continue; + bool bParamsMatch = true; + for (unsigned i=0; iparam_size(); ++i) + { + if (methodDecl->parameters()[i]->getType() != baseMethod->parameters()[i]->getType()) + { + bParamsMatch = false; + break; + } + } + if (bParamsMatch) + { + // if we have already found a method directly below us in the inheritance hierarchy, just ignore this one + auto Compare = [&](CXXBasePathElement const & lhs, CXXBasePathElement const & rhs) + { + return lhs.Class == rhs.Class; + }; + if (similarMethod + && similarBasePath.size() < path.size() + && std::equal(similarBasePath.begin(), similarBasePath.end(), + path.begin(), Compare)) + break; + if (similarMethod) + return true; // short circuit the process + similarMethod = baseMethod; + similarBasePath = path; + } + } + return false; + }; + + CXXBasePaths aPaths; + if (methodDecl->getParent()->lookupInBases(BaseMatchesCallback, aPaths)) + return nullptr; + + return similarMethod; +} + +CXXMemberCallExpr const * UnnecessaryOverride::extractCallExpr(Expr const *returnExpr) +{ + returnExpr = returnExpr->IgnoreImplicit(); + + // In something like + // + // Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( + // const rtl::OUString& sql) + // throw(SQLException, RuntimeException, std::exception) + // { + // return OCommonStatement::executeQuery( sql ); + // } + // + // look down through all the + // + // ReturnStmt + // `-ExprWithCleanups + // `-CXXConstructExpr + // `-MaterializeTemporaryExpr + // `-ImplicitCastExpr + // `-CXXBindTemporaryExpr + // `-CXXMemberCallExpr + // + // where the fact that the overriding and overridden function have identical + // return types makes us confident that all we need to check here is whether + // there's an (arbitrary, one-argument) CXXConstructorExpr and + // CXXBindTemporaryExpr in between: + if (auto ctorExpr = dyn_cast(returnExpr)) { + if (ctorExpr->getNumArgs() == 1) { + auto tempExpr1 = ctorExpr->getArg(0)->IgnoreImplicit(); + if (auto tempExpr2 = dyn_cast(tempExpr1)) + { + returnExpr = tempExpr2->getSubExpr(); + } + else if (auto tempExpr2 = dyn_cast(tempExpr1)) + { + returnExpr = tempExpr2; + } + } + } + + return dyn_cast(returnExpr->IgnoreParenImpCasts()); +} + +loplugin::Plugin::Registration< UnnecessaryOverride > unnecessaryoverride("unnecessaryoverride", true); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unnecessaryparen.cxx b/compilerplugins/clang/unnecessaryparen.cxx new file mode 100644 index 000000000..29a790702 --- /dev/null +++ b/compilerplugins/clang/unnecessaryparen.cxx @@ -0,0 +1,680 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include +#include + +#include + +#include "config_clang.h" + +#include "plugin.hxx" + +/** +look for unnecessary parentheses +*/ + +namespace { + +// Like clang::Stmt::IgnoreImplicit (lib/AST/Stmt.cpp), but also ignoring CXXConstructExpr and +// looking through implicit UserDefinedConversion's member function call: +Expr const * ignoreAllImplicit(Expr const * expr) { + while (true) + { + auto oldExpr = expr; + if (auto const e = dyn_cast(expr)) { + expr = e->getSubExpr(); + } + else if (auto const e = dyn_cast(expr)) { + if (e->getNumArgs() == 1) { + expr = e->getArg(0); + } + } + else if (auto const e = dyn_cast(expr)) { + expr = e->getSubExpr(); + } + else if (auto const e = dyn_cast(expr)) { + expr = e->getSubExpr(); + } + else if (auto const e = dyn_cast(expr)) { + expr = e->getSubExpr(); + if (e->getCastKind() == CK_UserDefinedConversion) { + auto const ce = cast(expr); + assert(ce->getNumArgs() == 0); + expr = ce->getImplicitObjectArgument(); + } + } + else if (auto const e = dyn_cast(expr)) { + expr = e->getSubExpr(); + } + if (expr == oldExpr) + return expr; + } + return expr; +} + +bool isParenWorthyOpcode(BinaryOperatorKind op) { + return !(BinaryOperator::isMultiplicativeOp(op) || BinaryOperator::isAdditiveOp(op) + || BinaryOperator::isPtrMemOp(op)); +} + +class UnnecessaryParen: + public loplugin::FilteringRewritePlugin +{ +public: + explicit UnnecessaryParen(loplugin::InstantiationData const & data): + FilteringRewritePlugin(data) {} + + virtual bool preRun() override + { + StringRef fn(handler.getMainFileName()); + // fixing this, makes the source in the .y files look horrible + if (loplugin::isSamePathname(fn, WORKDIR "/YaccTarget/unoidl/source/sourceprovider-parser.cxx")) + return false; + if (loplugin::isSamePathname(fn, WORKDIR "/YaccTarget/idlc/source/parser.cxx")) + return false; + return true; + } + virtual void run() override + { + if( preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitParenExpr(const ParenExpr *); + bool VisitIfStmt(const IfStmt *); + bool VisitDoStmt(const DoStmt *); + bool VisitWhileStmt(const WhileStmt *); + bool VisitForStmt(ForStmt const * stmt); + bool VisitSwitchStmt(const SwitchStmt *); + bool VisitCaseStmt(const CaseStmt *); + bool VisitReturnStmt(const ReturnStmt* ); + bool VisitCallExpr(const CallExpr *); + bool VisitVarDecl(const VarDecl *); + bool VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *); + bool VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr const *); + bool VisitConditionalOperator(ConditionalOperator const * expr); + bool VisitBinaryConditionalOperator(BinaryConditionalOperator const * expr); + bool VisitMemberExpr(const MemberExpr *f); + bool VisitCXXDeleteExpr(const CXXDeleteExpr *); + + bool VisitImplicitCastExpr(ImplicitCastExpr const * expr) { + if (ignoreLocation(expr)) { + return true; + } + if (expr->getCastKind() != CK_UserDefinedConversion) { + return true; + } + // Filter out a MemberExpr (resp. a ParenExpr sub-expr, if any, as would be found by + // VisitMemberExpr) that is part of a CXXMemberCallExpr which in turn is part of an + // ImplicitCastExpr, so that VisitMemberExpr doesn't erroneously pick it up (and note that + // CXXMemberCallExpr's getImplicitObjectArgument() skips past the underlying MemberExpr): + if (auto const e1 = dyn_cast(expr->getSubExpr())) { + if (auto const e2 = dyn_cast( + e1->getImplicitObjectArgument()->IgnoreImpCasts())) + { + handled_.insert(e2); + } + } + return true; + } + +private: + void VisitSomeStmt(Stmt const * stmt, const Expr* cond, StringRef stmtName); + + void handleUnreachableCodeConditionParens(Expr const * expr); + + // Hack for libxml2's BAD_CAST object-like macro (expanding to "(xmlChar *)"), which is + // typically used as if it were a function-like macro, e.g., as "BAD_CAST(pName)" in + // SwNode::dumpAsXml (sw/source/core/docnode/node.cxx): + bool isPrecededBy_BAD_CAST(Expr const * expr); + + bool badCombination(SourceLocation loc, int prevOffset, int nextOffset); + + bool removeParens(ParenExpr const * expr); + + std::unordered_set handled_; +}; + +bool UnnecessaryParen::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr const * expr) +{ + if (expr->getKind() == UETT_SizeOf && !expr->isArgumentType()) { + if (auto const e = dyn_cast(ignoreAllImplicit(expr->getArgumentExpr()))) { + handled_.insert(e); + } + } + return true; +} + +bool UnnecessaryParen::VisitConditionalOperator(ConditionalOperator const * expr) { + handleUnreachableCodeConditionParens(expr->getCond()); + return true; +} + +bool UnnecessaryParen::VisitBinaryConditionalOperator(BinaryConditionalOperator const * expr) { + handleUnreachableCodeConditionParens(expr->getCond()); + return true; +} + +bool UnnecessaryParen::VisitParenExpr(const ParenExpr* parenExpr) +{ + if (ignoreLocation(parenExpr)) + return true; + if (parenExpr->getBeginLoc().isMacroID()) + return true; + if (handled_.find(parenExpr) != handled_.end()) + return true; + + auto subExpr = ignoreAllImplicit(parenExpr->getSubExpr()); + + if (auto subParenExpr = dyn_cast(subExpr)) + { + if (subParenExpr->getBeginLoc().isMacroID()) + return true; + report( + DiagnosticsEngine::Warning, "parentheses around parentheses", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + handled_.insert(subParenExpr); + } + + // Somewhat redundantly add parenExpr to handled_, so that issues within InitListExpr don't get + // reported twice (without having to change TraverseInitListExpr to only either traverse the + // syntactic or semantic form, as other plugins do): + + if (isa(subExpr)) { + if (!isPrecededBy_BAD_CAST(parenExpr)) { + report( + DiagnosticsEngine::Warning, "unnecessary parentheses around identifier", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + handled_.insert(parenExpr); + } + } else if (isa(subExpr) || isa(subExpr) + || isa(subExpr) || isa(subExpr) + || isa(subExpr) || isa(subExpr) + || isa(subExpr)) + { + auto const loc = subExpr->getBeginLoc(); + if (loc.isMacroID() && compiler.getSourceManager().isAtStartOfImmediateMacroExpansion(loc)) + { + // just in case the macro could also expand to something that /would/ require + // parentheses here + return true; + } + report( + DiagnosticsEngine::Warning, "unnecessary parentheses around literal", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + handled_.insert(parenExpr); + } else if (auto const e = dyn_cast(subExpr)) { + if (e->getNumConcatenated() == 1 && !isPrecededBy_BAD_CAST(parenExpr)) { + report( + DiagnosticsEngine::Warning, + "unnecessary parentheses around single-token string literal", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + handled_.insert(parenExpr); + } + } else if (auto const e = dyn_cast(subExpr)) { + auto const op = e->getOpcode(); + if (op == UO_Plus || op == UO_Minus) { + auto const e2 = e->getSubExpr(); + if (isa(e2) || isa(e2) || isa(e2)) { + report( + DiagnosticsEngine::Warning, + "unnecessary parentheses around signed numeric literal", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + handled_.insert(parenExpr); + } + } + } else if (isa(subExpr)) { + if (!removeParens(parenExpr)) { + report( + DiagnosticsEngine::Warning, "unnecessary parentheses around cast", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + } + handled_.insert(parenExpr); + } else if (auto memberExpr = dyn_cast(subExpr)) { + if (isa(ignoreAllImplicit(memberExpr->getBase()))) { + report( + DiagnosticsEngine::Warning, "unnecessary parentheses around member expr", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + handled_.insert(parenExpr); + } + } + + return true; +} + +bool UnnecessaryParen::VisitIfStmt(const IfStmt* ifStmt) +{ + handleUnreachableCodeConditionParens(ifStmt->getCond()); + VisitSomeStmt(ifStmt, ifStmt->getCond(), "if"); + return true; +} + +bool UnnecessaryParen::VisitDoStmt(const DoStmt* doStmt) +{ + VisitSomeStmt(doStmt, doStmt->getCond(), "do"); + return true; +} + +bool UnnecessaryParen::VisitWhileStmt(const WhileStmt* whileStmt) +{ + handleUnreachableCodeConditionParens(whileStmt->getCond()); + VisitSomeStmt(whileStmt, whileStmt->getCond(), "while"); + return true; +} + +bool UnnecessaryParen::VisitForStmt(ForStmt const * stmt) { + if (auto const cond = stmt->getCond()) { + handleUnreachableCodeConditionParens(cond); + } + return true; +} + +bool UnnecessaryParen::VisitSwitchStmt(const SwitchStmt* switchStmt) +{ + VisitSomeStmt(switchStmt, switchStmt->getCond(), "switch"); + return true; +} + +bool UnnecessaryParen::VisitCaseStmt(const CaseStmt* caseStmt) +{ + VisitSomeStmt(caseStmt, caseStmt->getLHS(), "case"); + return true; +} + +bool UnnecessaryParen::VisitReturnStmt(const ReturnStmt* returnStmt) +{ + if (ignoreLocation(returnStmt)) + return true; + + if (!returnStmt->getRetValue()) + return true; + auto parenExpr = dyn_cast(ignoreAllImplicit(returnStmt->getRetValue())); + if (!parenExpr) + return true; + if (parenExpr->getBeginLoc().isMacroID()) + return true; + // assignments need extra parentheses or they generate a compiler warning + auto binaryOp = dyn_cast(parenExpr->getSubExpr()); + if (binaryOp && binaryOp->getOpcode() == BO_Assign) + return true; + + // only non-operator-calls for now + auto subExpr = ignoreAllImplicit(parenExpr->getSubExpr()); + if (isa(subExpr) && !isa(subExpr)) + { + report( + DiagnosticsEngine::Warning, "parentheses immediately inside return statement", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + handled_.insert(parenExpr); + } + return true; +} + +void UnnecessaryParen::VisitSomeStmt(const Stmt * stmt, const Expr* cond, StringRef stmtName) +{ + if (ignoreLocation(stmt)) + return; + + auto parenExpr = dyn_cast(ignoreAllImplicit(cond)); + if (parenExpr) { + if (handled_.find(parenExpr) != handled_.end()) { + return; + } + if (parenExpr->getBeginLoc().isMacroID()) + return; + // assignments need extra parentheses or they generate a compiler warning + auto binaryOp = dyn_cast(parenExpr->getSubExpr()); + if (binaryOp && binaryOp->getOpcode() == BO_Assign) + return; + if (auto const opCall = dyn_cast(parenExpr->getSubExpr())) { + if (opCall->getOperator() == OO_Equal) { + return; + } + } + report( + DiagnosticsEngine::Warning, "parentheses immediately inside %0 statement", + parenExpr->getBeginLoc()) + << stmtName + << parenExpr->getSourceRange(); + handled_.insert(parenExpr); + } +} + +bool UnnecessaryParen::VisitCallExpr(const CallExpr* callExpr) +{ + if (ignoreLocation(callExpr)) + return true; + if (callExpr->getNumArgs() == 0 || isa(callExpr)) + return true; + + // if we are calling a >1 arg method, are we using the defaults? + if (callExpr->getNumArgs() > 1) + { + if (!isa(callExpr->getArg(1))) + return true; + } + + auto parenExpr = dyn_cast(ignoreAllImplicit(callExpr->getArg(0))); + if (!parenExpr) + return true; + if (parenExpr->getBeginLoc().isMacroID()) + return true; + // assignments need extra parentheses or they generate a compiler warning + auto binaryOp = dyn_cast(parenExpr->getSubExpr()); + if (binaryOp && binaryOp->getOpcode() == BO_Assign) + return true; + report( + DiagnosticsEngine::Warning, "parentheses immediately inside single-arg call", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + handled_.insert(parenExpr); + return true; +} + +bool UnnecessaryParen::VisitCXXDeleteExpr(const CXXDeleteExpr* deleteExpr) +{ + if (ignoreLocation(deleteExpr)) + return true; + + auto parenExpr = dyn_cast(ignoreAllImplicit(deleteExpr->getArgument())); + if (!parenExpr) + return true; + if (parenExpr->getBeginLoc().isMacroID()) + return true; + // assignments need extra parentheses or they generate a compiler warning + auto binaryOp = dyn_cast(parenExpr->getSubExpr()); + if (binaryOp && binaryOp->getOpcode() == BO_Assign) + return true; + report( + DiagnosticsEngine::Warning, "parentheses immediately inside delete expr", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + handled_.insert(parenExpr); + return true; +} + +bool UnnecessaryParen::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr* callExpr) +{ + if (ignoreLocation(callExpr)) + return true; + if (callExpr->getNumArgs() != 2) + return true; + + // Same logic as CXXOperatorCallExpr::isAssignmentOp(), which our supported clang + // doesn't have yet. + auto Opc = callExpr->getOperator(); + if (Opc != OO_Equal && Opc != OO_StarEqual && + Opc != OO_SlashEqual && Opc != OO_PercentEqual && + Opc != OO_PlusEqual && Opc != OO_MinusEqual && + Opc != OO_LessLessEqual && Opc != OO_GreaterGreaterEqual && + Opc != OO_AmpEqual && Opc != OO_CaretEqual && + Opc != OO_PipeEqual) + return true; + auto parenExpr = dyn_cast(ignoreAllImplicit(callExpr->getArg(1))); + if (!parenExpr) + return true; + if (parenExpr->getBeginLoc().isMacroID()) + return true; + // Sometimes parentheses make the RHS of an assignment easier to read by + // visually disambiguating the = from a call to == + auto sub = parenExpr->getSubExpr(); + if (auto const e = dyn_cast(sub)) { + if (isParenWorthyOpcode(e->getDecomposedForm().Opcode)) { + return true; + } + } + if (auto subBinOp = dyn_cast(sub)) + { + if (isParenWorthyOpcode(subBinOp->getOpcode())) + return true; + } + if (auto subOperatorCall = dyn_cast(sub)) + { + auto op = subOperatorCall->getOperator(); + if (!((op >= OO_Plus && op <= OO_Exclaim) || (op >= OO_ArrowStar && op <= OO_Subscript))) + return true; + } + if (isa(sub)) + return true; + + report( + DiagnosticsEngine::Warning, "parentheses immediately inside assignment", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + handled_.insert(parenExpr); + return true; +} + +bool UnnecessaryParen::VisitVarDecl(const VarDecl* varDecl) +{ + if (ignoreLocation(varDecl)) + return true; + if (!varDecl->getInit()) + return true; + + auto parenExpr = dyn_cast(ignoreAllImplicit(varDecl->getInit())); + if (!parenExpr) + return true; + if (parenExpr->getBeginLoc().isMacroID()) + return true; + + // Sometimes parentheses make the RHS of an assignment easier to read by + // visually disambiguating the = from a call to == + auto sub = parenExpr->getSubExpr(); + if (auto const e = dyn_cast(sub)) { + sub = e->getDecomposedForm().InnerBinOp; + } + if (auto subBinOp = dyn_cast(sub)) + { + if (!(subBinOp->isMultiplicativeOp() || subBinOp->isAdditiveOp() || subBinOp->isPtrMemOp())) + return true; + } + if (auto subOperatorCall = dyn_cast(sub)) + { + auto op = subOperatorCall->getOperator(); + if (!((op >= OO_Plus && op <= OO_Exclaim) || (op >= OO_ArrowStar && op <= OO_Subscript))) + return true; + } + if (isa(sub)) + return true; + + // these two are for "parentheses were disambiguated as a function declaration [-Werror,-Wvexing-parse]" + auto const sub2 = sub->IgnoreImplicit(); + if (isa(sub2) + || isa(sub2)) + return true; + + report( + DiagnosticsEngine::Warning, "parentheses immediately inside vardecl statement", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + handled_.insert(parenExpr); + return true; +} + +bool UnnecessaryParen::VisitMemberExpr(const MemberExpr* memberExpr) +{ + if (ignoreLocation(memberExpr)) + return true; + + auto parenExpr = dyn_cast(ignoreAllImplicit(memberExpr->getBase())); + if (!parenExpr) + return true; + if (handled_.find(parenExpr) != handled_.end()) + return true; + if (parenExpr->getBeginLoc().isMacroID()) + return true; + + auto sub = parenExpr->getSubExpr(); + if (isa(sub)) { + if (isa(sub)) + return true; + } else if (isa(sub)) { + // warn + } else if (isa(sub)) { + // warn + } else if (isa(sub)) { + // warn + } else + return true; + + report( + DiagnosticsEngine::Warning, "unnecessary parentheses around member expr", + parenExpr->getBeginLoc()) + << parenExpr->getSourceRange(); + handled_.insert(parenExpr); + return true; +} + +// Conservatively assume any parenthesised integer or Boolean (incl. Objective-C ones) literal in +// certain condition expressions (i.e., those for which handleUnreachableCodeConditionParens is +// called) to be parenthesised to silence Clang -Wunreachable-code, if that is either the whole +// condition expression or appears as a certain sub-expression (looking at what isConfigurationValue +// in Clang's lib/Analysis/ReachableCode.cpp looks for, descending into certain unary and binary +// operators): +void UnnecessaryParen::handleUnreachableCodeConditionParens(Expr const * expr) { + // Cf. : + auto const e = ignoreAllImplicit(expr); + if (auto const e1 = dyn_cast(e)) { + auto const sub = e1->getSubExpr(); + if (isa(sub) || isa(sub) + || isa(sub)) + { + handled_.insert(e1); + } + } else if (auto const e1 = dyn_cast(e)) { + if (e1->getOpcode() == UO_LNot) { + handleUnreachableCodeConditionParens(e1->getSubExpr()); + } + } else if (auto const e1 = dyn_cast(e)) { + if (e1->isLogicalOp() || e1->isComparisonOp()) { + handleUnreachableCodeConditionParens(e1->getLHS()); + handleUnreachableCodeConditionParens(e1->getRHS()); + } + } +} + +bool UnnecessaryParen::isPrecededBy_BAD_CAST(Expr const * expr) { + if (expr->getBeginLoc().isMacroID()) { + return false; + } + SourceManager& SM = compiler.getSourceManager(); + const char *p1 = SM.getCharacterData( expr->getBeginLoc().getLocWithOffset(-10) ); + const char *p2 = SM.getCharacterData( expr->getBeginLoc() ); + return std::string(p1, p2 - p1).find("BAD_CAST") != std::string::npos; +} + +namespace { + +bool badCombinationChar(char c) { + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' + || c == '+' || c == '-' || c == '\'' || c == '"'; +} + +} + +bool UnnecessaryParen::badCombination(SourceLocation loc, int prevOffset, int nextOffset) { + //TODO: check for start/end of file; take backslash-newline line concatenation into account + auto const c1 + = compiler.getSourceManager().getCharacterData(loc.getLocWithOffset(prevOffset))[0]; + auto const c2 + = compiler.getSourceManager().getCharacterData(loc.getLocWithOffset(nextOffset))[0]; + // An approximation of avoiding whatever combinations that would cause two adjacent tokens to be + // lexed differently, using, for now, letters (TODO: non-ASCII ones) and digits and '_'; '+' and + // '-' (to avoid ++, etc.); '\'' and '"' (to avoid u'x' or "foo"bar, etc.): + return badCombinationChar(c1) && badCombinationChar(c2); +} + +bool UnnecessaryParen::removeParens(ParenExpr const * expr) { + if (rewriter == nullptr) { + return false; + } + auto const firstBegin = expr->getBeginLoc(); + auto secondBegin = expr->getEndLoc(); + if (firstBegin.isMacroID() || secondBegin.isMacroID()) { + return false; + } + unsigned firstLen = Lexer::MeasureTokenLength( + firstBegin, compiler.getSourceManager(), compiler.getLangOpts()); + for (auto l = firstBegin.getLocWithOffset(std::max(firstLen, 1));; + l = l.getLocWithOffset(1)) + { + unsigned n = Lexer::MeasureTokenLength( + l, compiler.getSourceManager(), compiler.getLangOpts()); + if (n != 0) { + break; + } + ++firstLen; + } + unsigned secondLen = Lexer::MeasureTokenLength( + secondBegin, compiler.getSourceManager(), compiler.getLangOpts()); + for (;;) { + auto l = secondBegin.getLocWithOffset(-1); + auto const c = compiler.getSourceManager().getCharacterData(l)[0]; + if (c == '\n') { + if (compiler.getSourceManager().getCharacterData(l.getLocWithOffset(-1))[0] == '\\') { + break; + } + } else if (!(c == ' ' || c == '\t' || c == '\v' || c == '\f')) { + break; + } + secondBegin = l; + ++secondLen; + } + if (!replaceText(firstBegin, firstLen, badCombination(firstBegin, -1, firstLen) ? " " : "")) { + if (isDebugMode()) { + report( + DiagnosticsEngine::Fatal, + "TODO: cannot rewrite opening parenthesis, needs investigation", + firstBegin); + report( + DiagnosticsEngine::Note, "when removing these parentheses", expr->getExprLoc()) + << expr->getSourceRange(); + } + return false; + } + if (!replaceText(secondBegin, secondLen, badCombination(secondBegin, -1, secondLen) ? " " : "")) + { + //TODO: roll back first change + if (isDebugMode()) { + report( + DiagnosticsEngine::Fatal, + "TODO: cannot rewrite closing parenthesis, needs investigation", + secondBegin); + report( + DiagnosticsEngine::Note, "when removing these parentheses", expr->getExprLoc()) + << expr->getSourceRange(); + } + return false; + } + return true; +} + +loplugin::Plugin::Registration< UnnecessaryParen > unnecessaryparen("unnecessaryparen", true); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unnecessaryvirtual-dead.results b/compilerplugins/clang/unnecessaryvirtual-dead.results new file mode 100644 index 000000000..db84d0412 --- /dev/null +++ b/compilerplugins/clang/unnecessaryvirtual-dead.results @@ -0,0 +1,30 @@ +basic/source/comp/codegen.cxx:477 + void (anonymous namespace)::OffSetAccumulator::start(const unsigned char *,) +canvas/inc/base/bufferedgraphicdevicebase.hxx:105 + void canvas::BufferedGraphicDeviceBase::destroyBuffers() +canvas/inc/base/graphicdevicebase.hxx:305 + void canvas::GraphicDeviceBase::removePropertyChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) +canvas/inc/base/graphicdevicebase.hxx:318 + void canvas::GraphicDeviceBase::removeVetoableChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) +include/basegfx/utils/unopolypolygon.hxx:92 + void basegfx::unotools::UnoPolyPolygon::modifying()const +sc/source/core/opencl/formulagroupcl.cxx:1070 + void sc::opencl::(anonymous namespace)::DynamicKernelSlidingArgument::GenSlidingWindowFunction(class std::basic_stringstream &,) +slideshow/source/engine/animationfactory.cxx:616 + void slideshow::internal::(anonymous namespace)::GenericAnimation::prefetch() +vcl/inc/salframe.hxx:147 + void SalFrame::SetRepresentedURL(const class rtl::OUString &,) +vcl/inc/salinst.hxx:204 + void SalInstance::releaseMainThread() +vcl/inc/salinst.hxx:213 + void SalInstance::BeforeAbort(const class rtl::OUString &,_Bool,) +vcl/inc/salobj.hxx:49 + void SalObject::Enable(_Bool,) +writerfilter/source/ooxml/OOXMLFactory.hxx:66 + void writerfilter::ooxml::OOXMLFactory_ns::startAction(class writerfilter::ooxml::OOXMLFastContextHandler *,) +writerfilter/source/ooxml/OOXMLFactory.hxx:67 + void writerfilter::ooxml::OOXMLFactory_ns::charactersAction(class writerfilter::ooxml::OOXMLFastContextHandler *,const class rtl::OUString &,) +writerfilter/source/ooxml/OOXMLFactory.hxx:68 + void writerfilter::ooxml::OOXMLFactory_ns::endAction(class writerfilter::ooxml::OOXMLFastContextHandler *,) +writerfilter/source/ooxml/OOXMLFactory.hxx:69 + void writerfilter::ooxml::OOXMLFactory_ns::attributeAction(class writerfilter::ooxml::OOXMLFastContextHandler *,int,const class tools::SvRef &,) diff --git a/compilerplugins/clang/unnecessaryvirtual.cxx b/compilerplugins/clang/unnecessaryvirtual.cxx new file mode 100644 index 000000000..c3c73923b --- /dev/null +++ b/compilerplugins/clang/unnecessaryvirtual.cxx @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" +#include + +/** +Dump a list of virtual methods and a list of methods overriding virtual methods. +Then we will post-process the 2 lists and find the set of virtual methods which don't need to be virtual. + +Also, we look for virtual methods where the bodies of all the overrides are empty i.e. this is leftover code +that no longer has a purpose. + +The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='unnecessaryvirtual' check + $ ./compilerplugins/clang/unnecessaryvirtual.py + $ for dir in *; do make FORCE_COMPILE=all UPDATE_FILES=$dir COMPILER_PLUGIN_TOOL='removevirtuals' $dir; done + +Note that the actual process may involve a fair amount of undoing, hand editing, and general messing around +to get it to work :-) + +TODO some boost bind stuff appears to confuse it, notably in the xmloff module +*/ + +namespace { + +struct MyFuncInfo +{ + std::string name; + std::string sourceLocation; + +}; +bool operator < (const MyFuncInfo &lhs, const MyFuncInfo &rhs) +{ + return lhs.name < rhs.name; +} + +// try to limit the voluminous output a little +static std::set definitionSet; +static std::unordered_set overridingSet; +static std::unordered_set nonEmptySet; + +class UnnecessaryVirtual: + public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit UnnecessaryVirtual(loplugin::InstantiationData const & data): + Plugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + std::string output; + for (const MyFuncInfo & s : definitionSet) + output += "definition:\t" + s.name + "\t" + s.sourceLocation + "\n"; + for (const std::string & s : overridingSet) + output += "overriding:\t" + s + "\n"; + for (const std::string & s : nonEmptySet) + output += "nonempty:\t" + s + "\n"; + std::ofstream myfile; + myfile.open( WORKDIR "/loplugin.unnecessaryvirtual.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + bool shouldVisitTemplateInstantiations () const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitCXXMethodDecl( const CXXMethodDecl* decl ); +private: + void MarkRootOverridesNonEmpty( const CXXMethodDecl* methodDecl ); + std::string toString(SourceLocation loc); +}; + +std::string niceName(const CXXMethodDecl* cxxMethodDecl) +{ + while (cxxMethodDecl->getTemplateInstantiationPattern()) + cxxMethodDecl = dyn_cast(cxxMethodDecl->getTemplateInstantiationPattern()); + while (cxxMethodDecl->getInstantiatedFromMemberFunction()) + cxxMethodDecl = dyn_cast(cxxMethodDecl->getInstantiatedFromMemberFunction()); + std::string s = cxxMethodDecl->getReturnType().getCanonicalType().getAsString() + + " " + cxxMethodDecl->getQualifiedNameAsString() + "("; + for (const ParmVarDecl *pParmVarDecl : cxxMethodDecl->parameters()) { + s += pParmVarDecl->getType().getCanonicalType().getAsString(); + s += ","; + } + s += ")"; + if (cxxMethodDecl->isConst()) { + s += "const"; + } + return s; +} + +bool UnnecessaryVirtual::VisitCXXMethodDecl( const CXXMethodDecl* methodDecl ) +{ + if (!methodDecl->isVirtual() || methodDecl->isDeleted()) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(methodDecl->getCanonicalDecl())) { + return true; + } + + auto body = methodDecl->getBody(); + if (body) { + auto compoundStmt = dyn_cast(body); + if (!compoundStmt) + MarkRootOverridesNonEmpty(methodDecl->getCanonicalDecl()); + else if (compoundStmt->size() > 0) + MarkRootOverridesNonEmpty(methodDecl->getCanonicalDecl()); + } + + if (!methodDecl->isThisDeclarationADefinition()) + return true; + + methodDecl = methodDecl->getCanonicalDecl(); + if (!methodDecl) + return true; + std::string aNiceName = niceName(methodDecl); + + // for destructors, we need to check if any of the superclass' destructors are virtual + if (isa(methodDecl)) { + const CXXRecordDecl* cxxRecordDecl = methodDecl->getParent(); + if (cxxRecordDecl->getNumBases() == 0) { + definitionSet.insert( { aNiceName, toString( methodDecl->getLocation() ) } ); + return true; + } + for(auto baseSpecifier = cxxRecordDecl->bases_begin(); + baseSpecifier != cxxRecordDecl->bases_end(); ++baseSpecifier) + { + if (baseSpecifier->getType()->isRecordType()) + { + const CXXRecordDecl* superclassCXXRecordDecl = baseSpecifier->getType()->getAsCXXRecordDecl(); + if (superclassCXXRecordDecl->getDestructor()) + { + std::string aOverriddenNiceName = niceName(superclassCXXRecordDecl->getDestructor()); + overridingSet.insert(aOverriddenNiceName); + } + } + } + return true; + } + + if (methodDecl->size_overridden_methods() == 0) { + definitionSet.insert( { aNiceName, toString( methodDecl->getLocation() ) } ); + } else { + for (auto iter = methodDecl->begin_overridden_methods(); + iter != methodDecl->end_overridden_methods(); ++iter) + { + const CXXMethodDecl *overriddenMethod = *iter; + // we only care about the first level override to establish that a virtual qualifier was useful. + if (overriddenMethod->isPure() || overriddenMethod->size_overridden_methods() == 0) + { + std::string aOverriddenNiceName = niceName(overriddenMethod); + overridingSet.insert(aOverriddenNiceName); + } + } + } + return true; +} + +void UnnecessaryVirtual::MarkRootOverridesNonEmpty( const CXXMethodDecl* methodDecl ) +{ + if (!methodDecl) + return; + if (methodDecl->size_overridden_methods() == 0) { + nonEmptySet.insert(niceName(methodDecl)); + return; + } + for (auto iter = methodDecl->begin_overridden_methods(); + iter != methodDecl->end_overridden_methods(); ++iter) + { + MarkRootOverridesNonEmpty(*iter); + } +} + +std::string UnnecessaryVirtual::toString(SourceLocation loc) +{ + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( loc ); + StringRef name = getFilenameOfLocation(expansionLoc); + std::string sourceLocation = std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(sourceLocation); + return sourceLocation; +} + + +loplugin::Plugin::Registration< UnnecessaryVirtual > X("unnecessaryvirtual", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unnecessaryvirtual.py b/compilerplugins/clang/unnecessaryvirtual.py new file mode 100755 index 000000000..01a32bfc3 --- /dev/null +++ b/compilerplugins/clang/unnecessaryvirtual.py @@ -0,0 +1,104 @@ +#!/usr/bin/python3 + +import io +import re +import sys + +definitionSet = set() +definitionToSourceLocationMap = dict() +overridingSet = set() +nonEmptySet = set() + + +with io.open("workdir/loplugin.unnecessaryvirtual.log", "r", buffering=1024*1024) as txt: + for line in txt: + tokens = line.strip().split("\t") + if tokens[0] == "definition:": + fullMethodName = tokens[1] + sourceLocation = tokens[2] + definitionSet.add(fullMethodName) + definitionToSourceLocationMap[fullMethodName] = sourceLocation + elif tokens[0] == "overriding:": + fullMethodName = tokens[1] + overridingSet.add(fullMethodName) + elif tokens[0] == "nonempty:": + fullMethodName = tokens[1] + nonEmptySet.add(fullMethodName) + else: + print( "unknown line: " + line) + +unnecessaryVirtualSet = set() + +for clazz in (definitionSet - overridingSet): + # windows-specific stuff + if clazz.startswith("canvas::"): continue + if clazz.startswith("psp::PrinterInfoManager"): continue + if clazz.startswith("DdeTopic::"): continue + if clazz == "basegfx::unotools::UnoPolyPolygon::void-modifying()const": continue + if clazz == "SalLayout::_Bool-IsKashidaPosValid(int,)const": continue + if clazz == "SalLayout::void-DisableGlyphInjection(_Bool,)": continue + # Linux-TDF specific + if clazz == "X11SalFrame::void-updateGraphics(_Bool,)": continue + # OSX specific + if clazz == "SalFrame::void-SetRepresentedURL(const class rtl::OUString &,)": continue + if clazz == "SalMenu::_Bool-AddMenuBarButton(const struct SalMenuButtonItem &,)": continue + if clazz == "SalMenu::class Rectangle-GetMenuBarButtonRectPixel(sal_uInt16,class SalFrame *,)": continue + if clazz == "SalMenu::void-RemoveMenuBarButton(sal_uInt16,)": continue + if clazz == "SalLayout::_Bool-DrawTextSpecial(class SalGraphics &,sal_uInt32,)const": continue + # GTK < 3 + if clazz == "GtkSalDisplay::int-CaptureMouse(class SalFrame *,)": continue + # some test magic + if clazz.startswith("apitest::"): continue + + loc = definitionToSourceLocationMap[clazz] + + # ignore external code + if loc.startswith("external/"): continue + # there is a bunch of Windows specific code that we don't see + if loc.startswith("include/canvas/"): continue + # not sure what the problem is here + if loc.startswith("include/test/"): continue + + unnecessaryVirtualSet.add( (clazz,loc) ) + + +deadSet = set() + +for clazz in (definitionSet - nonEmptySet): + + # ignore destructors + if "::~" in clazz: continue + + loc = definitionToSourceLocationMap[clazz] + + # ignore external code + if loc.startswith("external/"): continue + + deadSet.add( (clazz,loc) ) + + +# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[1]) + [v[0]] + +# sort results by name and line number +tmp1list = sorted(unnecessaryVirtualSet, key=lambda v: v_sort_key(v)) +tmp2list = sorted(deadSet, key=lambda v: v_sort_key(v)) + +with open("compilerplugins/clang/unnecessaryvirtual.results", "wt") as f: + for t in tmp1list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) + # add an empty line at the end to make it easier for the removevirtuals plugin to mmap() the output file + f.write("\n") + +with open("compilerplugins/clang/unnecessaryvirtual-dead.results", "wt") as f: + for t in tmp2list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) + diff --git a/compilerplugins/clang/unnecessaryvirtual.results b/compilerplugins/clang/unnecessaryvirtual.results new file mode 100644 index 000000000..a108383cd --- /dev/null +++ b/compilerplugins/clang/unnecessaryvirtual.results @@ -0,0 +1,475 @@ +basic/source/comp/codegen.cxx:477 + void (anonymous namespace)::OffSetAccumulator::start(const unsigned char *,) +basic/source/comp/codegen.cxx:478 + void (anonymous namespace)::OffSetAccumulator::processOpCode0(enum SbiOpcode,) +basic/source/comp/codegen.cxx:479 + void (anonymous namespace)::OffSetAccumulator::processOpCode1(enum SbiOpcode,type-parameter-0-0,) +basic/source/comp/codegen.cxx:480 + void (anonymous namespace)::OffSetAccumulator::processOpCode2(enum SbiOpcode,type-parameter-0-0,type-parameter-0-0,) +basic/source/comp/codegen.cxx:489 + _Bool (anonymous namespace)::OffSetAccumulator::processParams() +basic/source/comp/codegen.cxx:500 + void (anonymous namespace)::BufferTransformer::start(const unsigned char *,) +basic/source/comp/codegen.cxx:501 + void (anonymous namespace)::BufferTransformer::processOpCode0(enum SbiOpcode,) +basic/source/comp/codegen.cxx:505 + void (anonymous namespace)::BufferTransformer::processOpCode1(enum SbiOpcode,type-parameter-0-0,) +basic/source/comp/codegen.cxx:530 + void (anonymous namespace)::BufferTransformer::processOpCode2(enum SbiOpcode,type-parameter-0-0,type-parameter-0-0,) +basic/source/comp/codegen.cxx:539 + _Bool (anonymous namespace)::BufferTransformer::processParams() +canvas/inc/base/basemutexhelper.hxx:58 + void canvas::BaseMutexHelper::disposing() +canvas/inc/base/bitmapcanvasbase.hxx:72 + struct com::sun::star::geometry::IntegerSize2D canvas::BitmapCanvasBase::getSize() +canvas/inc/base/bitmapcanvasbase.hxx:79 + unsigned char canvas::BitmapCanvasBase::hasAlpha() +canvas/inc/base/bitmapcanvasbase.hxx:84 + class com::sun::star::uno::Reference canvas::BitmapCanvasBase::getScaledBitmap(const struct com::sun::star::geometry::RealSize2D &,unsigned char,) +canvas/inc/base/bitmapcanvasbase.hxx:105 + void canvas::BitmapCanvasBase2::copyRect(const class com::sun::star::uno::Reference &,const struct com::sun::star::geometry::RealRectangle2D &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const struct com::sun::star::geometry::RealRectangle2D &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +canvas/inc/base/bufferedgraphicdevicebase.hxx:92 + class com::sun::star::uno::Reference canvas::BufferedGraphicDeviceBase::getBufferController() +canvas/inc/base/bufferedgraphicdevicebase.hxx:98 + int canvas::BufferedGraphicDeviceBase::createBuffers(int,) +canvas/inc/base/bufferedgraphicdevicebase.hxx:105 + void canvas::BufferedGraphicDeviceBase::destroyBuffers() +canvas/inc/base/bufferedgraphicdevicebase.hxx:109 + unsigned char canvas::BufferedGraphicDeviceBase::showBuffer(unsigned char,) +canvas/inc/base/bufferedgraphicdevicebase.hxx:116 + unsigned char canvas::BufferedGraphicDeviceBase::switchBuffer(unsigned char,) +canvas/inc/base/bufferedgraphicdevicebase.hxx:160 + void canvas::BufferedGraphicDeviceBase::disposeThis() +canvas/inc/base/bufferedgraphicdevicebase.hxx:207 + void canvas::BufferedGraphicDeviceBase::disposeEventSource(const struct com::sun::star::lang::EventObject &,) +canvas/inc/base/bufferedgraphicdevicebase.hxx:217 + void canvas::BufferedGraphicDeviceBase::windowResized(const struct com::sun::star::awt::WindowEvent &,) +canvas/inc/base/bufferedgraphicdevicebase.hxx:222 + void canvas::BufferedGraphicDeviceBase::windowMoved(const struct com::sun::star::awt::WindowEvent &,) +canvas/inc/base/bufferedgraphicdevicebase.hxx:227 + void canvas::BufferedGraphicDeviceBase::windowShown(const struct com::sun::star::lang::EventObject &,) +canvas/inc/base/bufferedgraphicdevicebase.hxx:234 + void canvas::BufferedGraphicDeviceBase::windowHidden(const struct com::sun::star::lang::EventObject &,) +canvas/inc/base/canvasbase.hxx:123 + void canvas::CanvasBase::disposeThis() +canvas/inc/base/canvasbase.hxx:134 + void canvas::CanvasBase::clear() +canvas/inc/base/canvasbase.hxx:143 + void canvas::CanvasBase::drawPoint(const struct com::sun::star::geometry::RealPoint2D &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +canvas/inc/base/canvasbase.hxx:156 + void canvas::CanvasBase::drawLine(const struct com::sun::star::geometry::RealPoint2D &,const struct com::sun::star::geometry::RealPoint2D &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +canvas/inc/base/canvasbase.hxx:172 + void canvas::CanvasBase::drawBezier(const struct com::sun::star::geometry::RealBezierSegment2D &,const struct com::sun::star::geometry::RealPoint2D &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +canvas/inc/base/canvasbase.hxx:189 + class com::sun::star::uno::Reference canvas::CanvasBase::drawPolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +canvas/inc/base/canvasbase.hxx:205 + class com::sun::star::uno::Reference canvas::CanvasBase::strokePolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const struct com::sun::star::rendering::StrokeAttributes &,) +canvas/inc/base/canvasbase.hxx:222 + class com::sun::star::uno::Reference canvas::CanvasBase::strokeTexturedPolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const class com::sun::star::uno::Sequence &,const struct com::sun::star::rendering::StrokeAttributes &,) +canvas/inc/base/canvasbase.hxx:240 + class com::sun::star::uno::Reference canvas::CanvasBase::strokeTextureMappedPolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const class com::sun::star::uno::Sequence &,const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::StrokeAttributes &,) +canvas/inc/base/canvasbase.hxx:259 + class com::sun::star::uno::Reference canvas::CanvasBase::queryStrokeShapes(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const struct com::sun::star::rendering::StrokeAttributes &,) +canvas/inc/base/canvasbase.hxx:276 + class com::sun::star::uno::Reference canvas::CanvasBase::fillPolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +canvas/inc/base/canvasbase.hxx:292 + class com::sun::star::uno::Reference canvas::CanvasBase::fillTexturedPolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const class com::sun::star::uno::Sequence &,) +canvas/inc/base/canvasbase.hxx:309 + class com::sun::star::uno::Reference canvas::CanvasBase::fillTextureMappedPolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const class com::sun::star::uno::Sequence &,const class com::sun::star::uno::Reference &,) +canvas/inc/base/canvasbase.hxx:328 + class com::sun::star::uno::Reference canvas::CanvasBase::createFont(const struct com::sun::star::rendering::FontRequest &,const class com::sun::star::uno::Sequence &,const struct com::sun::star::geometry::Matrix2D &,) +canvas/inc/base/canvasbase.hxx:346 + class com::sun::star::uno::Sequence canvas::CanvasBase::queryAvailableFonts(const struct com::sun::star::rendering::FontInfo &,const class com::sun::star::uno::Sequence &,) +canvas/inc/base/canvasbase.hxx:360 + class com::sun::star::uno::Reference canvas::CanvasBase::drawText(const struct com::sun::star::rendering::StringContext &,const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,signed char,) +canvas/inc/base/canvasbase.hxx:382 + class com::sun::star::uno::Reference canvas::CanvasBase::drawTextLayout(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +canvas/inc/base/canvasbase.hxx:399 + class com::sun::star::uno::Reference canvas::CanvasBase::drawBitmap(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +canvas/inc/base/canvasbase.hxx:415 + class com::sun::star::uno::Reference canvas::CanvasBase::drawBitmapModulated(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +canvas/inc/base/canvasbase.hxx:431 + class com::sun::star::uno::Reference canvas::CanvasBase::getDevice() +canvas/inc/base/canvascustomspritebase.hxx:93 + void canvas::CanvasCustomSpriteBase::disposeThis() +canvas/inc/base/canvascustomspritebase.hxx:104 + void canvas::CanvasCustomSpriteBase::clear() +canvas/inc/base/canvascustomspritebase.hxx:115 + class com::sun::star::uno::Reference canvas::CanvasCustomSpriteBase::drawBitmap(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +canvas/inc/base/canvascustomspritebase.hxx:141 + void canvas::CanvasCustomSpriteBase::setAlpha(double,) +canvas/inc/base/canvascustomspritebase.hxx:150 + void canvas::CanvasCustomSpriteBase::move(const struct com::sun::star::geometry::RealPoint2D &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +canvas/inc/base/canvascustomspritebase.hxx:163 + void canvas::CanvasCustomSpriteBase::transform(const struct com::sun::star::geometry::AffineMatrix2D &,) +canvas/inc/base/canvascustomspritebase.hxx:174 + void canvas::CanvasCustomSpriteBase::clip(const class com::sun::star::uno::Reference &,) +canvas/inc/base/canvascustomspritebase.hxx:183 + void canvas::CanvasCustomSpriteBase::setPriority(double,) +canvas/inc/base/canvascustomspritebase.hxx:190 + void canvas::CanvasCustomSpriteBase::show() +canvas/inc/base/canvascustomspritebase.hxx:197 + void canvas::CanvasCustomSpriteBase::hide() +canvas/inc/base/canvascustomspritebase.hxx:206 + class com::sun::star::uno::Reference canvas::CanvasCustomSpriteBase::getContentCanvas() +canvas/inc/base/canvascustomspritebase.hxx:214 + _Bool canvas::CanvasCustomSpriteBase::isAreaUpdateOpaque(const class basegfx::B2DRange &,)const +canvas/inc/base/canvascustomspritebase.hxx:221 + _Bool canvas::CanvasCustomSpriteBase::isContentChanged()const +canvas/inc/base/canvascustomspritebase.hxx:228 + class basegfx::B2DPoint canvas::CanvasCustomSpriteBase::getPosPixel()const +canvas/inc/base/canvascustomspritebase.hxx:235 + class basegfx::B2DVector canvas::CanvasCustomSpriteBase::getSizePixel()const +canvas/inc/base/canvascustomspritebase.hxx:242 + class basegfx::B2DRange canvas::CanvasCustomSpriteBase::getUpdateArea()const +canvas/inc/base/canvascustomspritebase.hxx:249 + double canvas::CanvasCustomSpriteBase::getPriority()const +canvas/inc/base/disambiguationhelper.hxx:70 + void canvas::DisambiguationHelper::disposing() +canvas/inc/base/disambiguationhelper.hxx:73 + void canvas::DisambiguationHelper::disposing(const struct com::sun::star::lang::EventObject &,) +canvas/inc/base/graphicdevicebase.hxx:134 + void canvas::GraphicDeviceBase::disposeThis() +canvas/inc/base/graphicdevicebase.hxx:145 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::getBufferController() +canvas/inc/base/graphicdevicebase.hxx:150 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::getDeviceColorSpace() +canvas/inc/base/graphicdevicebase.hxx:157 + struct com::sun::star::geometry::RealSize2D canvas::GraphicDeviceBase::getPhysicalResolution() +canvas/inc/base/graphicdevicebase.hxx:164 + struct com::sun::star::geometry::RealSize2D canvas::GraphicDeviceBase::getPhysicalSize() +canvas/inc/base/graphicdevicebase.hxx:171 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createCompatibleLinePolyPolygon(const class com::sun::star::uno::Sequence > &,) +canvas/inc/base/graphicdevicebase.hxx:178 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createCompatibleBezierPolyPolygon(const class com::sun::star::uno::Sequence > &,) +canvas/inc/base/graphicdevicebase.hxx:185 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createCompatibleBitmap(const struct com::sun::star::geometry::IntegerSize2D &,) +canvas/inc/base/graphicdevicebase.hxx:196 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createVolatileBitmap(const struct com::sun::star::geometry::IntegerSize2D &,) +canvas/inc/base/graphicdevicebase.hxx:207 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createCompatibleAlphaBitmap(const struct com::sun::star::geometry::IntegerSize2D &,) +canvas/inc/base/graphicdevicebase.hxx:218 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createVolatileAlphaBitmap(const struct com::sun::star::geometry::IntegerSize2D &,) +canvas/inc/base/graphicdevicebase.hxx:229 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::getParametricPolyPolygonFactory() +canvas/inc/base/graphicdevicebase.hxx:234 + unsigned char canvas::GraphicDeviceBase::hasFullScreenMode() +canvas/inc/base/graphicdevicebase.hxx:239 + unsigned char canvas::GraphicDeviceBase::enterFullScreenMode(unsigned char,) +canvas/inc/base/graphicdevicebase.hxx:245 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createInstance(const class rtl::OUString &,) +canvas/inc/base/graphicdevicebase.hxx:253 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createInstanceWithArguments(const class rtl::OUString &,const class com::sun::star::uno::Sequence &,) +canvas/inc/base/graphicdevicebase.hxx:261 + class com::sun::star::uno::Sequence canvas::GraphicDeviceBase::getAvailableServiceNames() +canvas/inc/base/graphicdevicebase.hxx:268 + void canvas::GraphicDeviceBase::update() +canvas/inc/base/graphicdevicebase.hxx:278 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::getPropertySetInfo() +canvas/inc/base/graphicdevicebase.hxx:284 + void canvas::GraphicDeviceBase::setPropertyValue(const class rtl::OUString &,const class com::sun::star::uno::Any &,) +canvas/inc/base/graphicdevicebase.hxx:291 + class com::sun::star::uno::Any canvas::GraphicDeviceBase::getPropertyValue(const class rtl::OUString &,) +canvas/inc/base/graphicdevicebase.hxx:297 + void canvas::GraphicDeviceBase::addPropertyChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) +canvas/inc/base/graphicdevicebase.hxx:305 + void canvas::GraphicDeviceBase::removePropertyChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) +canvas/inc/base/graphicdevicebase.hxx:310 + void canvas::GraphicDeviceBase::addVetoableChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) +canvas/inc/base/graphicdevicebase.hxx:318 + void canvas::GraphicDeviceBase::removeVetoableChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) +canvas/inc/base/integerbitmapbase.hxx:43 + class com::sun::star::uno::Sequence canvas::IntegerBitmapBase::getData(struct com::sun::star::rendering::IntegerBitmapLayout &,const struct com::sun::star::geometry::IntegerRectangle2D &,) +canvas/inc/base/integerbitmapbase.hxx:57 + void canvas::IntegerBitmapBase::setData(const class com::sun::star::uno::Sequence &,const struct com::sun::star::rendering::IntegerBitmapLayout &,const struct com::sun::star::geometry::IntegerRectangle2D &,) +canvas/inc/base/integerbitmapbase.hxx:71 + void canvas::IntegerBitmapBase::setPixel(const class com::sun::star::uno::Sequence &,const struct com::sun::star::rendering::IntegerBitmapLayout &,const struct com::sun::star::geometry::IntegerPoint2D &,) +canvas/inc/base/integerbitmapbase.hxx:85 + class com::sun::star::uno::Sequence canvas::IntegerBitmapBase::getPixel(struct com::sun::star::rendering::IntegerBitmapLayout &,const struct com::sun::star::geometry::IntegerPoint2D &,) +canvas/inc/base/integerbitmapbase.hxx:99 + struct com::sun::star::rendering::IntegerBitmapLayout canvas::IntegerBitmapBase::getMemoryLayout() +canvas/inc/base/spritecanvasbase.hxx:84 + void canvas::SpriteCanvasBase::disposeThis() +canvas/inc/base/spritecanvasbase.hxx:95 + class com::sun::star::uno::Reference canvas::SpriteCanvasBase::createSpriteFromAnimation(const class com::sun::star::uno::Reference &,) +canvas/inc/base/spritecanvasbase.hxx:106 + class com::sun::star::uno::Reference canvas::SpriteCanvasBase::createSpriteFromBitmaps(const class com::sun::star::uno::Sequence > &,signed char,) +canvas/inc/base/spritecanvasbase.hxx:121 + class com::sun::star::uno::Reference canvas::SpriteCanvasBase::createCustomSprite(const struct com::sun::star::geometry::RealSize2D &,) +canvas/inc/base/spritecanvasbase.hxx:132 + class com::sun::star::uno::Reference canvas::SpriteCanvasBase::createClonedSprite(const class com::sun::star::uno::Reference &,) +canvas/inc/base/spritecanvasbase.hxx:144 + void canvas::SpriteCanvasBase::showSprite(const class rtl::Reference &,) +canvas/inc/base/spritecanvasbase.hxx:153 + void canvas::SpriteCanvasBase::hideSprite(const class rtl::Reference &,) +canvas/inc/base/spritecanvasbase.hxx:162 + void canvas::SpriteCanvasBase::moveSprite(const class rtl::Reference &,const class basegfx::B2DPoint &,const class basegfx::B2DPoint &,const class basegfx::B2DVector &,) +canvas/inc/base/spritecanvasbase.hxx:174 + void canvas::SpriteCanvasBase::updateSprite(const class rtl::Reference &,const class basegfx::B2DPoint &,const class basegfx::B2DRange &,) +canvas/inc/rendering/icolorbuffer.hxx:43 + void canvas::IColorBuffer::~IColorBuffer() +canvas/inc/rendering/irendermodule.hxx:59 + void canvas::IRenderModule::~IRenderModule() +canvas/inc/rendering/isurface.hxx:34 + void canvas::ISurface::~ISurface() +chart2/source/inc/DataInterpreter.hxx:136 + class rtl::Reference chart::DataInterpreter::mergeInterpretedData(const struct chart::InterpretedData &,) +chart2/source/inc/WeakListenerAdapter.hxx:56 + void chart::WeakListenerAdapter::disposing(const struct com::sun::star::lang::EventObject &,) +extensions/source/dbpilots/unoautopilot.hxx:80 + class cppu::IPropertyArrayHelper * dbp::OUnoAutoPilot::createArrayHelper()const +extensions/source/propctrlr/commoncontrol.hxx:129 + short pcr::CommonBehaviourControl::getControlType() +extensions/source/propctrlr/commoncontrol.hxx:131 + class com::sun::star::uno::Reference pcr::CommonBehaviourControl::getControlContext() +extensions/source/propctrlr/commoncontrol.hxx:133 + void pcr::CommonBehaviourControl::setControlContext(const class com::sun::star::uno::Reference &,) +extensions/source/propctrlr/commoncontrol.hxx:135 + class com::sun::star::uno::Reference pcr::CommonBehaviourControl::getControlWindow() +extensions/source/propctrlr/commoncontrol.hxx:137 + unsigned char pcr::CommonBehaviourControl::isModified() +extensions/source/propctrlr/commoncontrol.hxx:139 + void pcr::CommonBehaviourControl::notifyModifiedValue() +extensions/source/propctrlr/commoncontrol.hxx:154 + void pcr::CommonBehaviourControl::disposing() +forms/source/xforms/datatypes.hxx:215 + class cppu::IPropertyArrayHelper * xforms::ODerivedDataType::createArrayHelper()const +forms/source/xforms/datatypes.hxx:218 + class com::sun::star::uno::Reference xforms::ODerivedDataType::getPropertySetInfo() +forms/source/xforms/datatypes.hxx:219 + class cppu::IPropertyArrayHelper & xforms::ODerivedDataType::getInfoHelper() +forms/source/xforms/namedcollection.hxx:81 + class com::sun::star::uno::Type NamedCollection::getElementType() +forms/source/xforms/namedcollection.hxx:86 + unsigned char NamedCollection::hasElements() +forms/source/xforms/namedcollection.hxx:92 + class com::sun::star::uno::Any NamedCollection::getByName(const class rtl::OUString &,) +forms/source/xforms/namedcollection.hxx:100 + class com::sun::star::uno::Sequence NamedCollection::getElementNames() +forms/source/xforms/namedcollection.hxx:105 + unsigned char NamedCollection::hasByName(const class rtl::OUString &,) +include/basegfx/utils/unopolypolygon.hxx:92 + void basegfx::unotools::UnoPolyPolygon::modifying()const +include/comphelper/interaction.hxx:53 + void comphelper::OInteraction::select() +include/comphelper/proparrhlp.hxx:83 + class cppu::IPropertyArrayHelper * comphelper::OAggregationArrayUsageHelper::createArrayHelper()const +include/comphelper/solarmutex.hxx:59 + _Bool comphelper::SolarMutex::tryToAcquire() +include/comphelper/unique_disposing_ptr.hxx:169 + void comphelper::unique_disposing_solar_mutex_reset_ptr::reset(type-parameter-0-0 *,) +include/comphelper/weakeventlistener.hxx:120 + void comphelper::OWeakListenerAdapter::disposing(const struct com::sun::star::lang::EventObject &,) +include/svl/svdde.hxx:236 + class DdeData * DdeTopic::Get(enum SotClipboardFormatId,) +include/svl/svdde.hxx:237 + _Bool DdeTopic::Put(const class DdeData *,) +include/svl/svdde.hxx:238 + _Bool DdeTopic::Execute(const class rtl::OUString *,) +include/svl/svdde.hxx:240 + _Bool DdeTopic::MakeItem(const class rtl::OUString &,) +include/svl/svdde.hxx:243 + _Bool DdeTopic::StartAdviseLoop() +include/svl/svdde.hxx:300 + void DdeService::~DdeService() +include/vbahelper/vbacollectionimpl.hxx:289 + int ScVbaCollectionBase::getCount() +include/vbahelper/vbacollectionimpl.hxx:294 + class com::sun::star::uno::Any ScVbaCollectionBase::Item(const class com::sun::star::uno::Any &,const class com::sun::star::uno::Any &,) +include/vbahelper/vbacollectionimpl.hxx:323 + unsigned char ScVbaCollectionBase::hasElements() +include/vbahelper/vbahelperinterface.hxx:74 + int InheritedHelperInterfaceImpl::getCreator() +include/vbahelper/vbahelperinterface.hxx:78 + class com::sun::star::uno::Reference InheritedHelperInterfaceImpl::getParent() +include/vbahelper/vbahelperinterface.hxx:80 + class com::sun::star::uno::Any InheritedHelperInterfaceImpl::Application() +include/vbahelper/vbahelperinterface.hxx:88 + class rtl::OUString InheritedHelperInterfaceImpl::getImplementationName() +include/vbahelper/vbahelperinterface.hxx:89 + unsigned char InheritedHelperInterfaceImpl::supportsService(const class rtl::OUString &,) +include/vbahelper/vbahelperinterface.hxx:99 + class com::sun::star::uno::Sequence InheritedHelperInterfaceImpl::getSupportedServiceNames() +include/vbahelper/vbareturntypes.hxx:38 + void ooo::vba::DefaultReturnHelper::setValue(type-parameter-0-0,) +include/vbahelper/vbareturntypes.hxx:39 + type-parameter-0-0 ooo::vba::DefaultReturnHelper::getValue() +include/vcl/customweld.hxx:45 + class rtl::OUString weld::CustomWidgetController::GetHelpText()const +include/vcl/weld.hxx:104 + void weld::Widget::set_visible(_Bool,) +sc/source/core/opencl/formulagroupcl.cxx:1062 + _Bool sc::opencl::(anonymous namespace)::DynamicKernelSlidingArgument::NeedParallelReduction()const +sc/source/core/opencl/formulagroupcl.cxx:1070 + void sc::opencl::(anonymous namespace)::DynamicKernelSlidingArgument::GenSlidingWindowFunction(class std::basic_stringstream &,) +sc/source/core/opencl/formulagroupcl.cxx:1353 + void sc::opencl::(anonymous namespace)::ParallelReductionVectorRef::GenSlidingWindowFunction(class std::basic_stringstream &,) +sc/source/core/opencl/formulagroupcl.cxx:1355 + class std::basic_string sc::opencl::(anonymous namespace)::ParallelReductionVectorRef::GenSlidingWindowDeclRef(_Bool,)const +sc/source/core/opencl/formulagroupcl.cxx:1369 + unsigned long sc::opencl::(anonymous namespace)::ParallelReductionVectorRef::Marshal(struct _cl_kernel *,int,int,struct _cl_program *,) +sc/source/ui/vba/vbacondition.hxx:40 + class rtl::OUString ScVbaCondition::Formula1() +sc/source/ui/vba/vbacondition.hxx:41 + class rtl::OUString ScVbaCondition::Formula2() +sc/source/ui/vba/vbacondition.hxx:43 + int ScVbaCondition::Operator(_Bool,) +sc/source/ui/vba/vbaformat.hxx:73 + class com::sun::star::uno::Any ScVbaFormat::Borders(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:76 + class com::sun::star::uno::Reference ScVbaFormat::Font() +sc/source/ui/vba/vbaformat.hxx:79 + class com::sun::star::uno::Reference ScVbaFormat::Interior() +sc/source/ui/vba/vbaformat.hxx:82 + void ScVbaFormat::setNumberFormat(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:85 + class com::sun::star::uno::Any ScVbaFormat::getNumberFormat() +sc/source/ui/vba/vbaformat.hxx:88 + void ScVbaFormat::setNumberFormatLocal(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:91 + class com::sun::star::uno::Any ScVbaFormat::getNumberFormatLocal() +sc/source/ui/vba/vbaformat.hxx:94 + void ScVbaFormat::setIndentLevel(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:97 + class com::sun::star::uno::Any ScVbaFormat::getIndentLevel() +sc/source/ui/vba/vbaformat.hxx:100 + void ScVbaFormat::setHorizontalAlignment(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:103 + class com::sun::star::uno::Any ScVbaFormat::getHorizontalAlignment() +sc/source/ui/vba/vbaformat.hxx:106 + void ScVbaFormat::setVerticalAlignment(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:109 + class com::sun::star::uno::Any ScVbaFormat::getVerticalAlignment() +sc/source/ui/vba/vbaformat.hxx:112 + void ScVbaFormat::setOrientation(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:115 + class com::sun::star::uno::Any ScVbaFormat::getOrientation() +sc/source/ui/vba/vbaformat.hxx:118 + void ScVbaFormat::setShrinkToFit(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:121 + class com::sun::star::uno::Any ScVbaFormat::getShrinkToFit() +sc/source/ui/vba/vbaformat.hxx:124 + void ScVbaFormat::setWrapText(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:127 + class com::sun::star::uno::Any ScVbaFormat::getWrapText() +sc/source/ui/vba/vbaformat.hxx:130 + void ScVbaFormat::setLocked(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:133 + class com::sun::star::uno::Any ScVbaFormat::getLocked() +sc/source/ui/vba/vbaformat.hxx:136 + void ScVbaFormat::setFormulaHidden(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:139 + class com::sun::star::uno::Any ScVbaFormat::getFormulaHidden() +sc/source/ui/vba/vbaformat.hxx:148 + void ScVbaFormat::setReadingOrder(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:151 + class com::sun::star::uno::Any ScVbaFormat::getReadingOrder() +sc/source/ui/vba/vbapagebreak.hxx:44 + int ScVbaPageBreak::getType() +sc/source/ui/vba/vbapagebreak.hxx:45 + void ScVbaPageBreak::setType(int,) +sc/source/ui/vba/vbapagebreak.hxx:47 + void ScVbaPageBreak::Delete() +sc/source/ui/vba/vbapagebreak.hxx:48 + class com::sun::star::uno::Reference ScVbaPageBreak::Location() +shell/inc/i_xml_parser_event_handler.hxx:41 + void i_xml_parser_event_handler::~i_xml_parser_event_handler() +slideshow/source/engine/activities/activitiesfactory.cxx:172 + void slideshow::internal::(anonymous namespace)::FromToByActivity::startAnimation() +slideshow/source/engine/activities/activitiesfactory.cxx:241 + void slideshow::internal::(anonymous namespace)::FromToByActivity::endAnimation() +slideshow/source/engine/activities/activitiesfactory.cxx:331 + void slideshow::internal::(anonymous namespace)::FromToByActivity::performEnd() +slideshow/source/engine/activities/activitiesfactory.cxx:344 + void slideshow::internal::(anonymous namespace)::FromToByActivity::dispose() +slideshow/source/engine/activities/activitiesfactory.cxx:525 + void slideshow::internal::(anonymous namespace)::ValuesActivity::startAnimation() +slideshow/source/engine/activities/activitiesfactory.cxx:536 + void slideshow::internal::(anonymous namespace)::ValuesActivity::endAnimation() +slideshow/source/engine/activities/activitiesfactory.cxx:581 + void slideshow::internal::(anonymous namespace)::ValuesActivity::performEnd() +slideshow/source/engine/animationfactory.cxx:616 + void slideshow::internal::(anonymous namespace)::GenericAnimation::prefetch() +slideshow/source/engine/animationfactory.cxx:619 + void slideshow::internal::(anonymous namespace)::GenericAnimation::start(const class std::shared_ptr &,const class std::shared_ptr &,) +slideshow/source/inc/shape.hxx:221 + void slideshow::internal::Shape::setIsForeground(const _Bool,) +sw/inc/flypos.hxx:37 + void SwPosFlyFrame::~SwPosFlyFrame() +toolkit/inc/controls/geometrycontrolmodel.hxx:185 + void OGeometryControlModel::fillProperties(class com::sun::star::uno::Sequence &,class com::sun::star::uno::Sequence &,)const +vcl/inc/jsdialog/jsdialogbuilder.hxx:158 + void JSDialogSender::sendFullUpdate(_Bool,) +vcl/inc/jsdialog/jsdialogbuilder.hxx:161 + void JSDialogSender::sendAction(class VclPtr,class std::unique_ptr, class rtl::OUString> >,) +vcl/inc/jsdialog/jsdialogbuilder.hxx:162 + void JSDialogSender::sendPopup(class VclPtr,class rtl::OUString,class rtl::OUString,) +vcl/inc/jsdialog/jsdialogbuilder.hxx:163 + void JSDialogSender::sendClosePopup(unsigned int,) +vcl/inc/jsdialog/jsdialogbuilder.hxx:353 + void JSWidget::show() +vcl/inc/jsdialog/jsdialogbuilder.hxx:365 + void JSWidget::hide() +vcl/inc/jsdialog/jsdialogbuilder.hxx:378 + void JSWidget::set_sensitive(_Bool,) +vcl/inc/jsdialog/jsdialogbuilder.hxx:386 + class com::sun::star::uno::Reference JSWidget::get_drop_target() +vcl/inc/jsdialog/jsdialogbuilder.hxx:394 + void JSWidget::freeze() +vcl/inc/jsdialog/jsdialogbuilder.hxx:400 + void JSWidget::thaw() +vcl/inc/jsdialog/jsdialogbuilder.hxx:505 + void JSComboBox::set_entry_text_without_notify(const class rtl::OUString &,) +vcl/inc/salframe.hxx:147 + void SalFrame::SetRepresentedURL(const class rtl::OUString &,) +vcl/inc/salframe.hxx:196 + void SalFrame::Flush(const class tools::Rectangle &,) +vcl/inc/salinst.hxx:95 + _Bool SalInstance::SVMainHook(int *,) +vcl/inc/salinst.hxx:204 + void SalInstance::releaseMainThread() +vcl/inc/salinst.hxx:213 + void SalInstance::BeforeAbort(const class rtl::OUString &,_Bool,) +vcl/inc/salobj.hxx:49 + void SalObject::Enable(_Bool,) +vcl/inc/salprn.hxx:116 + enum SalPrinterError SalPrinter::GetErrorCode() +vcl/inc/salvtables.hxx:1603 + _Bool SalInstanceTreeView::get_iter_abs_pos(class weld::TreeIter &,int,)const +vcl/inc/skia/gdiimpl.hxx:229 + void SkiaSalGraphicsImpl::createSurface() +vcl/inc/skia/gdiimpl.hxx:239 + void SkiaSalGraphicsImpl::flushSurfaceToWindowContext() +vcl/inc/skia/gdiimpl.hxx:262 + int SkiaSalGraphicsImpl::getWindowScaling()const +vcl/inc/unx/gtk/gtkdata.hxx:335 + int GtkSalDisplay::CaptureMouse(class SalFrame *,) +vcl/inc/unx/saldata.hxx:50 + void X11SalData::Init() +vcl/inc/unx/saldisp.hxx:405 + void SalX11Display::Yield() +vcl/inc/unx/salframe.h:208 + void X11SalFrame::updateGraphics(_Bool,) +vcl/inc/unx/salinst.h:41 + class SalX11Display * X11SalInstance::CreateDisplay()const +workdir/../vcl/inc/qt5/QtFrame.hxx:159 + void QtFrame::registerDragSource(class QtDragSource *,) +workdir/../vcl/inc/qt5/QtFrame.hxx:160 + void QtFrame::deregisterDragSource(const class QtDragSource *,) +workdir/../vcl/inc/qt5/QtFrame.hxx:161 + void QtFrame::registerDropTarget(class QtDropTarget *,) +workdir/../vcl/inc/qt5/QtFrame.hxx:162 + void QtFrame::deregisterDropTarget(const class QtDropTarget *,) +writerfilter/source/dmapper/TableManager.hxx:492 + void writerfilter::dmapper::TableManager::tableExceptionProps(const class tools::SvRef &,) +writerfilter/source/ooxml/OOXMLFactory.hxx:66 + void writerfilter::ooxml::OOXMLFactory_ns::startAction(class writerfilter::ooxml::OOXMLFastContextHandler *,) +writerfilter/source/ooxml/OOXMLFactory.hxx:67 + void writerfilter::ooxml::OOXMLFactory_ns::charactersAction(class writerfilter::ooxml::OOXMLFastContextHandler *,const class rtl::OUString &,) +writerfilter/source/ooxml/OOXMLFactory.hxx:68 + void writerfilter::ooxml::OOXMLFactory_ns::endAction(class writerfilter::ooxml::OOXMLFastContextHandler *,) +writerfilter/source/ooxml/OOXMLFactory.hxx:69 + void writerfilter::ooxml::OOXMLFactory_ns::attributeAction(class writerfilter::ooxml::OOXMLFastContextHandler *,int,const class tools::SvRef &,) +xmloff/source/forms/elementimport.hxx:549 + class com::sun::star::uno::Reference xmloff::OColumnImport::createElement() + diff --git a/compilerplugins/clang/unoany.cxx b/compilerplugins/clang/unoany.cxx new file mode 100644 index 000000000..0ab5657c1 --- /dev/null +++ b/compilerplugins/clang/unoany.cxx @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "config_clang.h" + +#include "check.hxx" +#include "plugin.hxx" + +namespace { + +class UnoAny: + public loplugin::FilteringPlugin +{ +public: + explicit UnoAny(loplugin::InstantiationData const & data): FilteringPlugin(data) {} + + bool preRun() override { + return compiler.getLangOpts().CPlusPlus; + } + + void run() override { + if (preRun()) { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const * expr); +}; + +bool UnoAny::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const * expr) +{ + if (ignoreLocation(expr)) { + return true; + } + StringRef aFileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc())); + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/com/sun/star/uno/Any.hxx")) { + return true; + } + if (expr->getOperator() != OO_Equal) { + return true; + } + if (!loplugin::TypeCheck(expr->getArg(0)->getType()).Class("Any"). + Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()) + { + return true; + } + if (auto expr2 = dyn_cast(expr->getArg(1))) { + if (auto expr3 = dyn_cast(expr2->getSubExpr())) { + if (auto expr4 = dyn_cast(expr3->getSubExpr())) { + if (loplugin::DeclCheck(expr4->getDirectCallee()).Function("makeAny"). + Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()) { + report( + DiagnosticsEngine::Warning, + ("unnecessary copy, rather use <<= operator directly with the 'makeAny'" + " argument"), + expr->getOperatorLoc()) + << expr->getSourceRange(); + return true; + } + } + } + if (isa(expr2->getSubExpr())) { + //expr->getArg(1)->dump(); + report( + DiagnosticsEngine::Warning, + ("unnecessary copy, rather use <<= operator directly with the 'Any' constructor" + " argument"), + expr->getOperatorLoc()) + << expr->getSourceRange(); + return true; + } + } + //expr->getArg(1)->dump(); + return true; +} + +loplugin::Plugin::Registration unoany("unoany"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/unoquery.cxx b/compilerplugins/clang/unoquery.cxx new file mode 100644 index 000000000..1fe2d4b5b --- /dev/null +++ b/compilerplugins/clang/unoquery.cxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "check.hxx" +#include "plugin.hxx" + +// TODO it would be better if we were running some kind of nullability analysis here, where we marked +// the results of expressions like Reference(..UNO_QUERY) as being nullable, and then looked for +// places where we unconditionally deference the results of that expression. + +namespace +{ +class UnoQuery : public loplugin::FilteringPlugin +{ +public: + explicit UnoQuery(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitCXXMemberCallExpr(CXXMemberCallExpr const*); +}; + +bool UnoQuery::VisitCXXMemberCallExpr(CXXMemberCallExpr const* memberCallExpr) +{ + if (ignoreLocation(memberCallExpr)) + return true; + + auto isXInterface = [](Decl const* decl) -> bool { + return bool(loplugin::DeclCheck(decl) + .Class("XInterface") + .Namespace("uno") + .Namespace("star") + .Namespace("sun") + .Namespace("com") + .GlobalNamespace()); + }; + if (!loplugin::isDerivedFrom(memberCallExpr->getRecordDecl(), isXInterface)) + return true; + auto operatorCallExpr = dyn_cast( + memberCallExpr->getImplicitObjectArgument()->IgnoreImplicit()); + if (!operatorCallExpr) + return true; + + Expr const* expr = operatorCallExpr->getArg(0)->IgnoreImplicit(); + // depending on the version of clang, the IgnoreImplicit may or may not look through these nodes + if (auto matTemp = dyn_cast(expr)) + expr = matTemp->getSubExpr(); + if (auto bindTemp = dyn_cast(expr)) + expr = bindTemp->getSubExpr(); + + auto temporaryExpr = dyn_cast(expr); + if (!temporaryExpr) + return true; + if (temporaryExpr->getNumArgs() < 2) + return true; + auto declRefExpr = dyn_cast(temporaryExpr->getArg(1)->IgnoreImplicit()); + if (!declRefExpr) + return true; + auto enumConstant = dyn_cast(declRefExpr->getDecl()); + if (!enumConstant) + return true; + if (enumConstant->getName() != "UNO_QUERY") + return true; + + report(DiagnosticsEngine::Warning, + "calling UNO_QUERY followed by unconditional method call might result in SIGSEGV, " + "rather use UNO_QUERY_THROW", + memberCallExpr->getExprLoc()) + << memberCallExpr->getSourceRange(); + + return true; +} + +loplugin::Plugin::Registration unoquery("unoquery"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/unreffun.cxx b/compilerplugins/clang/unreffun.cxx new file mode 100644 index 000000000..353eee5f0 --- /dev/null +++ b/compilerplugins/clang/unreffun.cxx @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include + +#include "clang/AST/Attr.h" +#include "clang/Sema/SemaInternal.h" // warn_unused_function + +#include "plugin.hxx" + +namespace { + +bool isFriendDecl(Decl const * decl) { + return decl->getFriendObjectKind() != Decl::FOK_None; +} + +Decl const * getPreviousNonFriendDecl(Decl const * decl) { + for (;;) { + decl = decl->getPreviousDecl(); + if (decl == nullptr || !isFriendDecl(decl)) { + return decl; + } + } +} + +bool isSpecialMemberFunction(FunctionDecl const * decl) { + if (auto const ctor = dyn_cast(decl)) { + return ctor->isDefaultConstructor() || ctor->isCopyOrMoveConstructor(); + } + if (isa(decl)) { + return true; + } + if (auto const meth = dyn_cast(decl)) { + return meth->isCopyAssignmentOperator() || meth->isMoveAssignmentOperator(); + } + return false; +} + +class UnrefFun: public loplugin::FilteringPlugin { +public: + explicit UnrefFun(loplugin::InstantiationData const & data): FilteringPlugin(data) {} + + void run() override + { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool PreTraverseFriendDecl(FriendDecl * decl) { + friendFunction.push( dyn_cast_or_null(decl->getFriendDecl())); + return true; + } + bool PostTraverseFriendDecl(FriendDecl *, bool ) { + friendFunction.pop(); + return true; + } + bool TraverseFriendDecl(FriendDecl * decl) { + PreTraverseFriendDecl(decl); + auto const ret = RecursiveASTVisitor::TraverseFriendDecl(decl); + PostTraverseFriendDecl(decl, ret); + return ret; + } + + bool VisitFunctionDecl(FunctionDecl const * decl); + +private: + std::stack friendFunction; +}; + +bool UnrefFun::VisitFunctionDecl(FunctionDecl const * decl) { + if (ignoreLocation(decl)) { + return true; + } + + //TODO, filtering out any functions relating to (class) templates for now: + CXXRecordDecl const * r = dyn_cast(decl->getDeclContext()); + if (r != nullptr + && (r->getTemplateSpecializationKind() != TSK_Undeclared + || r->isDependentContext())) + { + return true; + } + if (!friendFunction.empty() && decl == friendFunction.top()) { + if (auto const lex = dyn_cast(decl->getLexicalDeclContext())) { + if (lex->isDependentContext()) { + return true; + } + } + } + + if (!(decl->isThisDeclarationADefinition() || isFriendDecl(decl) + || decl->isFunctionTemplateSpecialization())) + { + Decl const * prev = getPreviousNonFriendDecl(decl); + if (prev != nullptr/* && prev != decl->getPrimaryTemplate()*/) { + // Workaround for redeclarations that introduce visibility attributes + // (as is done with + // + // SAL_DLLPUBLIC_EXPORT GType lok_doc_view_get_type(); + // + // in libreofficekit/source/gtk/lokdocview.cxx): + if (decl->getAttr() != nullptr + && prev->getAttr() == nullptr) + { + return true; + } + report( + DiagnosticsEngine::Warning, + "redundant function%0 redeclaration", decl->getLocation()) + << ((decl->getTemplatedKind() + == FunctionDecl::TK_FunctionTemplate) + ? " template" : "") + << decl->getSourceRange(); + report( + DiagnosticsEngine::Note, "previous declaration is here", + prev->getLocation()) + << prev->getSourceRange(); + return true; + } + } + + FunctionDecl const * canon = decl->getCanonicalDecl(); + //TODO: is that the first? + if (canon->isDeleted() || canon->isReferenced() + || !(canon->isDefined() + ? decl->isThisDeclarationADefinition() : decl->isFirstDecl()) + || !compiler.getSourceManager().isInMainFile(canon->getLocation()) + || isInUnoIncludeFile(canon) + || canon->isMain() || canon->isMSVCRTEntryPoint() + || (decl->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate + && (decl->getDescribedFunctionTemplate()->spec_begin() + != decl->getDescribedFunctionTemplate()->spec_end())) + || (compiler.getDiagnostics().getDiagnosticLevel( + diag::warn_unused_function, decl->getLocation()) + < DiagnosticsEngine::Warning)) + { + return true; + } + if (canon->isExplicitlyDefaulted() && isSpecialMemberFunction(canon)) { + // If a special member function is explicitly defaulted on the first declaration, assume + // that its presence is always due to some interface design consideration, not to explicitly + // request a definition that might be worth to flag as unused (and C++20 may extend + // defaultability beyond special member functions to comparison operators, therefore + // explicitly check here for special member functions only): + return true; + } + LinkageInfo info(canon->getLinkageAndVisibility()); + if (info.getLinkage() == ExternalLinkage + && loplugin::hasCLanguageLinkageType(canon) && canon->isDefined() + && ((decl == canon && info.getVisibility() == DefaultVisibility) + || ((canon->hasAttr() + || canon->hasAttr()) + && info.getVisibility() == HiddenVisibility))) + { + return true; + } + auto loc = decl->getLocation(); + if (compiler.getSourceManager().isMacroBodyExpansion(loc) + && (Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()) + == "MDDS_MTV_DEFINE_ELEMENT_CALLBACKS")) + { + return true; + } + report( + DiagnosticsEngine::Warning, + (canon->isDefined() + ? (canon->isExternallyVisible() + ? "Unreferenced externally visible function%0 definition" + : "Unreferenced externally invisible function%0 definition") + : "Unreferenced function%0 declaration"), + decl->getLocation()) + << (decl->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate + ? " template" : "") + << decl->getSourceRange(); + if (canon->isDefined() && !decl->isFirstDecl()) { + report( + DiagnosticsEngine::Note, "first declaration is here", + canon->getLocation()) + << canon->getSourceRange(); + } + return true; +} + +loplugin::Plugin::Registration unreffun("unreffun"); + +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unsignedcompare.cxx b/compilerplugins/clang/unsignedcompare.cxx new file mode 100644 index 000000000..5b55edea2 --- /dev/null +++ b/compilerplugins/clang/unsignedcompare.cxx @@ -0,0 +1,232 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +// Find explicit casts from signed to unsigned integer in comparison against unsigned integer, where +// the cast is presumably used to avoid warnings about signed vs. unsigned comparisons, and could +// thus be replaced with o3tl::make_unsigned for clarity. + +#include + +#include "plugin.hxx" + +namespace +{ +// clang::Type::isSignedIntegerType returns true for more types than what C++ defines as signed +// integer types: +bool isSignedIntegerType(QualType type) +{ + if (auto const t = type->getAs()) + { + // Assumes that the only extended signed integer type supported by Clang is Int128: + switch (t->getKind()) + { + case BuiltinType::SChar: + case BuiltinType::Short: + case BuiltinType::Int: + case BuiltinType::Long: + case BuiltinType::LongLong: + case BuiltinType::Int128: + return true; + default: + break; + } + } + return false; +} + +// clang::Type::isUnsignedIntegerType returns true for more types than what C++ defines as signed +// integer types: +bool isUnsignedIntegerType(QualType type) +{ + if (auto const t = type->getAs()) + { + // Assumes that the only extended unsigned integer type supported by Clang is UInt128: + switch (t->getKind()) + { + case BuiltinType::UChar: + case BuiltinType::UShort: + case BuiltinType::UInt: + case BuiltinType::ULong: + case BuiltinType::ULongLong: + case BuiltinType::UInt128: + return true; + default: + break; + } + } + return false; +} + +int getRank(QualType type) +{ + auto const t = type->getAs(); + assert(t != nullptr); + // Assumes that the only extended signed/unsigned integer types supported by Clang are Int128 + // and UInt128: + switch (t->getKind()) + { + case BuiltinType::SChar: + case BuiltinType::UChar: + return 0; + case BuiltinType::Short: + case BuiltinType::UShort: + return 1; + case BuiltinType::Int: + case BuiltinType::UInt: + return 2; + case BuiltinType::Long: + case BuiltinType::ULong: + return 3; + case BuiltinType::LongLong: + case BuiltinType::ULongLong: + return 4; + case BuiltinType::Int128: + case BuiltinType::UInt128: + return 5; + default: + llvm_unreachable("bad integer type"); + } +} + +int orderTypes(QualType type1, QualType type2) +{ + auto const r1 = getRank(type1); + auto const r2 = getRank(type2); + return r1 < r2 ? -1 : r1 == r2 ? 0 : 1; +} + +class UnsignedCompare : public loplugin::FilteringPlugin +{ +public: + explicit UnsignedCompare(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool VisitBinaryOperator(BinaryOperator const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + // o3tl::make_unsigned requires its argument to be non-negative, but this plugin doesn't + // check that when it reports its finding, so will produce false positives when the cast is + // actually meant to e.g. clamp from a large signed type to a small unsigned type. The + // assumption is that this will only be likely the case for BO_EQ (==) and BO_NE (!=) + // comparisons, so filter these out here (not sure what case BO_Cmp (<=>) will turn out to + // be, so lets keep it here at least for now): + switch (expr->getOpcode()) + { + case BO_Cmp: + case BO_LT: + case BO_GT: + case BO_LE: + case BO_GE: + break; + default: + return true; + } + auto const castL = isCastToUnsigned(expr->getLHS()); + auto const castR = isCastToUnsigned(expr->getRHS()); + //TODO(?): Also report somewhat suspicious cases where both sides are cast to unsigned: + if ((castL == nullptr) == (castR == nullptr)) + { + return true; + } + auto const cast = castL != nullptr ? castL : castR; + auto const other = castL != nullptr ? expr->getRHS() : expr->getLHS(); + auto const otherT = other->IgnoreImpCasts()->getType(); + if (!isUnsignedIntegerType(otherT)) + { + return true; + } + auto const castFromT = cast->getSubExprAsWritten()->getType(); + auto const castToT = cast->getTypeAsWritten(); + report(DiagnosticsEngine::Warning, + "explicit cast from %0 to %1 (of %select{smaller|equal|larger}2 rank) in comparison " + "against %3: if the cast value is known to be non-negative, use o3tl::make_unsigned " + "instead of the cast", + cast->getExprLoc()) + << castFromT << castToT << (orderTypes(castToT, castFromT) + 1) << otherT + << expr->getSourceRange(); + return true; + } + + bool preRun() override + { + return compiler.getLangOpts().CPlusPlus + && compiler.getPreprocessor() + .getIdentifierInfo("LIBO_INTERNAL_ONLY") + ->hasMacroDefinition(); + } + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + +private: + ExplicitCastExpr const* isCastToUnsigned(Expr const* expr) + { + auto const e = dyn_cast(expr->IgnoreParenImpCasts()); + if (e == nullptr) + { + return nullptr; + } + auto const t1 = e->getTypeAsWritten(); + if (!isUnsignedIntegerType(t1)) + { + return nullptr; + } + auto const e2 = e->getSubExprAsWritten(); + auto const t2 = e2->getType(); + if (!isSignedIntegerType(t2)) + { + return nullptr; + } + // Filter out e.g. `size_t(-1)`: + if (!e2->isValueDependent()) + { + if (auto const val = e2->getIntegerConstantExpr(compiler.getASTContext())) + { + if (val->isNegative()) + { + return nullptr; + } + } + } + auto loc = e->getBeginLoc(); + while (compiler.getSourceManager().isMacroArgExpansion(loc)) + { + loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc); + } + // This covers both "plain" code in such include files, as well as expansion of (object-like) macros like + // + // #define SAL_MAX_INT8 ((sal_Int8) 0x7F) + // + // defined in such include files: + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(loc))) + { //TODO: '#ifdef LIBO_INTERNAL_ONLY' within UNO include files + return nullptr; + } + return e; + } +}; + +loplugin::Plugin::Registration unsignedcompare("unsignedcompare"); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/unusedcapturedefault.cxx b/compilerplugins/clang/unusedcapturedefault.cxx new file mode 100644 index 000000000..57f6669dc --- /dev/null +++ b/compilerplugins/clang/unusedcapturedefault.cxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" + +namespace +{ +class UnusedCaptureDefault : public loplugin::FilteringPlugin +{ +public: + explicit UnusedCaptureDefault(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + + bool VisitLambdaExpr(LambdaExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + if (expr->getCaptureDefault() == LCD_None) + { + return true; + } + if (expr->implicit_capture_begin() != expr->implicit_capture_end()) + { + return true; + } + report(DiagnosticsEngine::Warning, "unused capture-default", expr->getCaptureDefaultLoc()) + << expr->getSourceRange(); + return true; + } + +private: + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } +}; + +loplugin::Plugin::Registration unusedcapturedefault("unusedcapturedefault"); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/unusedenumconstants.cxx b/compilerplugins/clang/unusedenumconstants.cxx new file mode 100644 index 000000000..a04117343 --- /dev/null +++ b/compilerplugins/clang/unusedenumconstants.cxx @@ -0,0 +1,301 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" + +/** +This looks for unused enum constants + +We search for 3 things +(a) constants that are declared but never used +(b) constants only used in a "read" fashion i.e. we compare stuff against them, but we never store a value anywhere +(c) constants only used in a "write" fashion i.e. we store a value, but never check for that value + +(a) is fairly reliable but (b) and (c) will need some checking before acting on. + +Be warned that it produces around 5G of log file. + +The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='unusedenumconstants' check + $ ./compilerplugins/clang/unusedenumconstants.py + +Note that the actual process may involve a fair amount of undoing, hand editing, and general messing around +to get it to work :-) + +*/ + +namespace { + +struct MyFieldInfo +{ + std::string parentClass; + std::string fieldName; + std::string sourceLocation; + SourceLocation loc; +}; +bool operator < (const MyFieldInfo &lhs, const MyFieldInfo &rhs) +{ + return std::tie(lhs.parentClass, lhs.fieldName) + < std::tie(rhs.parentClass, rhs.fieldName); +} + + +// try to limit the voluminous output a little +static std::set definitionSet; +static std::set writeSet; +static std::set readSet; + + +class UnusedEnumConstants: + public loplugin::FilteringPlugin +{ +public: + explicit UnusedEnumConstants(loplugin::InstantiationData const & data): FilteringPlugin(data) {} + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + if (!isUnitTestMode()) + { + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + std::string output; + for (const MyFieldInfo & s : definitionSet) + output += "definition:\t" + s.parentClass + "\t" + s.fieldName + "\t" + s.sourceLocation + "\n"; + for (const MyFieldInfo & s : writeSet) + output += "write:\t" + s.parentClass + "\t" + s.fieldName + "\n"; + for (const MyFieldInfo & s : readSet) + output += "read:\t" + s.parentClass + "\t" + s.fieldName + "\n"; + std::ofstream myfile; + myfile.open( WORKDIR "/loplugin.unusedenumconstants.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + else + { + for (const MyFieldInfo& s : writeSet) + report(DiagnosticsEngine::Warning, "write %0", s.loc) + << s.fieldName; + for (const MyFieldInfo& s : readSet) + report(DiagnosticsEngine::Warning, "read %0", s.loc) + << s.fieldName; + } + } + + bool shouldVisitTemplateInstantiations () const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitEnumConstantDecl( const EnumConstantDecl * ); + bool VisitDeclRefExpr( const DeclRefExpr * ); +private: + MyFieldInfo niceName(const EnumConstantDecl*); +}; + +MyFieldInfo UnusedEnumConstants::niceName(const EnumConstantDecl* enumConstantDecl) +{ + MyFieldInfo aInfo; + + aInfo.parentClass = enumConstantDecl->getType().getAsString(); + aInfo.fieldName = enumConstantDecl->getNameAsString(); + // sometimes the name (if it's anonymous thing) contains the full path of the build folder, which we don't need + size_t idx = aInfo.fieldName.find(SRCDIR); + if (idx != std::string::npos) { + aInfo.fieldName = aInfo.fieldName.replace(idx, strlen(SRCDIR), ""); + } + + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( enumConstantDecl->getLocation() ); + StringRef name = getFilenameOfLocation(expansionLoc); + aInfo.loc = expansionLoc; + aInfo.sourceLocation = std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(aInfo.sourceLocation); + + return aInfo; +} + +bool UnusedEnumConstants::VisitEnumConstantDecl( const EnumConstantDecl* enumConstantDecl ) +{ + enumConstantDecl = enumConstantDecl->getCanonicalDecl(); + if (ignoreLocation( enumConstantDecl )) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(enumConstantDecl->getLocation()))) { + return true; + } + + definitionSet.insert(niceName(enumConstantDecl)); + return true; +} + +bool UnusedEnumConstants::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) +{ + auto enumConstantDecl = dyn_cast(declRefExpr->getDecl()); + if (!enumConstantDecl) { + return true; + } + enumConstantDecl = enumConstantDecl->getCanonicalDecl(); + if (ignoreLocation(enumConstantDecl)) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(enumConstantDecl->getLocation()))) { + return true; + } + + const Stmt * parent = declRefExpr; + const Stmt * child = nullptr; + +walk_up: + child = parent; + parent = getParentStmt(parent); + bool bWrite = false; + bool bRead = false; + bool bDump = false; + if (!parent) + { + // Could probably do better here. + // Sometimes this is a constructor-initialiser-expression, so just make a pessimistic assumption. + bWrite = true; + } + else if (const CXXOperatorCallExpr * operatorCall = dyn_cast(parent)) + { + auto oo = operatorCall->getOperator(); + if (oo == OO_AmpEqual) + { + // Ignore a common pattern that does not introduce any new information, merely removes + // information: foo &= ~Enum6::Top + bool found = false; + if (auto innerOperatorCall = dyn_cast(operatorCall->getArg(1)->IgnoreImplicit()->IgnoreParens()->IgnoreImplicit())) + { + found = innerOperatorCall->getOperator() == OO_Tilde; + } + if (!found) + bWrite = true; + } + // if assignment op + else if (oo == OO_Equal || oo == OO_StarEqual || oo == OO_SlashEqual || oo == OO_PercentEqual + || oo == OO_PlusEqual || oo == OO_MinusEqual || oo == OO_LessLessEqual + || oo == OO_CaretEqual || oo == OO_PipeEqual) + bWrite = true; + // else if comparison op + else if (oo == OO_AmpAmp || oo == OO_PipePipe || oo == OO_Subscript + || oo == OO_Less || oo == OO_Greater || oo == OO_LessEqual || oo == OO_GreaterEqual || oo == OO_EqualEqual || oo == OO_ExclaimEqual) + bRead = true; + else + goto walk_up; + } + else if (const CXXMemberCallExpr * memberCall = dyn_cast(parent)) + { + // happens a lot with o3tl::typed_flags + if (*memberCall->child_begin() == child) + { + if (auto conversionDecl = dyn_cast(memberCall->getMethodDecl())) + { + if (conversionDecl->getConversionType()->isSpecificBuiltinType(clang::BuiltinType::Bool)) + bRead = true; + else + goto walk_up; + } + else + goto walk_up; + } + else + bWrite = true; + } + else if (isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) + || isa(parent)) + { + bWrite = true; + } + else if (isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) || isa(parent) || isa(parent)) + { + bRead = true; + } + else if (const BinaryOperator * binaryOp = dyn_cast(parent)) + { + if (BinaryOperator::isAssignmentOp(binaryOp->getOpcode())) { + bWrite = true; + } else if (BinaryOperator::isComparisonOp(binaryOp->getOpcode())) { + bRead = true; + } else { + goto walk_up; + } + } + else if (isa(parent)) + { + goto walk_up; + } + else if (isa(parent) || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent)) + { + goto walk_up; + } + else if (isa(parent)) + { + // TODO this could be improved + bWrite = true; + } + else if (isa(parent)) + { + // slightly weird case I saw in basegfx where the enum is being used as a template param + bWrite = true; + } + else if (isa(parent)) + { + goto walk_up; + } + else if (isa(parent) + || isa(parent)) + { + bRead = true; + bWrite = true; + } + else + { + bDump = true; + } + + // to let me know if I missed something + if (bDump) { + parent->dump(); + declRefExpr->dump(); + report( DiagnosticsEngine::Warning, + "unhandled clang AST node type", + parent->getBeginLoc()); + } + + if (bWrite) { + writeSet.insert(niceName(enumConstantDecl)); + } + if (bRead) { + readSet.insert(niceName(enumConstantDecl)); + } + return true; +} + +loplugin::Plugin::Registration< UnusedEnumConstants > X("unusedenumconstants", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unusedenumconstants.py b/compilerplugins/clang/unusedenumconstants.py new file mode 100755 index 000000000..72de38503 --- /dev/null +++ b/compilerplugins/clang/unusedenumconstants.py @@ -0,0 +1,262 @@ +#!/usr/bin/python3 + +import sys +import re +import io + +definitionSet = set() +definitionToSourceLocationMap = dict() +readSet = set() +writeSet = set() +sourceLocationSet = set() + +# clang does not always use exactly the same numbers in the type-parameter vars it generates +# so I need to substitute them to ensure we can match correctly. +normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") +def normalizeTypeParams( line ): + return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) + +def parseFieldInfo( tokens ): + if len(tokens) == 3: + return (normalizeTypeParams(tokens[1]), tokens[2]) + else: + return (normalizeTypeParams(tokens[1]), "") + +with io.open("workdir/loplugin.unusedenumconstants.log", "r", buffering=1024*1024) as txt: + for line in txt: + tokens = line.strip().split("\t") + if tokens[0] == "definition:": + fieldInfo = (normalizeTypeParams(tokens[1]), tokens[2]) + srcLoc = tokens[3] + # ignore external source code + if (srcLoc.startswith("external/")): + continue + # ignore build folder + if (srcLoc.startswith("workdir/")): + continue + definitionSet.add(fieldInfo) + definitionToSourceLocationMap[fieldInfo] = srcLoc + elif tokens[0] == "read:": + readSet.add(parseFieldInfo(tokens)) + elif tokens[0] == "write:": + writeSet.add(parseFieldInfo(tokens)) + else: + print( "unknown line: " + line) + +def startswith_one_of( srcLoc, fileSet ): + for f in fileSet: + if srcLoc.startswith(f): + return True; + return False; + +def is_ignore(srcLoc): + if startswith_one_of(srcLoc, + [ + # this is all representations of on-disk or external data structures + "basic/source/inc/filefmt.hxx", + "basic/source/sbx/sbxscan.cxx", + "cppcanvas/source/mtfrenderer/emfpbrush.hxx", + "filter/source/graphicfilter/ipcd/ipcd.cxx", + "filter/source/t602/t602filter.hxx", + "include/filter/msfilter/escherex.hxx", + "include/filter/msfilter/svdfppt.hxx", + "hwpfilter/", + "include/registry/types.hxx", + "lotuswordpro/", + "include/sot/formats.hxx", + "include/svx/msdffdef.hxx", + "sc/source/filter/inc/xlconst.hxx", + "include/unotools/saveopt.hxx", + "sw/inc/fldbas.hxx", + "sw/source/filter/inc/wwstyles.hxx", + "sw/source/filter/ww8/fields.hxx", + "vcl/source/fontsubset/cff.cxx", + "include/vcl/settings.hxx", # stored in a setting, can't remove it without potentially triggering UBSAN + "basic/source/inc/opcodes.hxx", # can't touch this without breaking unit tests, not sure why + "include/unotools/securityoptions.hxx", # comes from the UI + "sot/source/sdstor/stgelem.hxx", + "sd/source/filter/eppt/epptbase.hxx", + "include/registry/refltype.hxx", + "include/registry/version.h", + "include/svtools/rtftoken.h", + "sc/source/filter/inc/xltracer.hxx", + "writerfilter/source/dmapper/FieldTypes.hxx", + "vcl/source/fontsubset/cff.cxx", + "vcl/source/filter/wmf/winmtf.hxx", + "vcl/source/filter/sgvmain.hxx", + "vcl/source/filter/jpeg/transupp.h", + "include/vcl/bitmapex.hxx", # TransparentType + "vcl/inc/sft.hxx", # CompositeFlags, WidthClass, WeightClass + "vcl/inc/CommonSalLayout.hxx", # VerticalOrientation + "include/tools/fontenum.hxx", # part of GDI file format + "svx/inc/galobj.hxx", # GalSoundType + "include/svx/msdffdef.hxx", + "include/svtools/rtftoken.h", # RTF_TOKEN_IDS + "starmath/source/mathtype.hxx", # MathType::MTOKENS + "sd/source/filter/eppt/epptbase.hxx", # PPTExTextAttr + "sc/source/filter/inc/tokstack.hxx", # E_TYPE + "filter/source/graphicfilter/icgm/cgmtypes.hxx", + "basic/source/inc/filefmt.hxx", # FileOffset + "include/basic/sbxdef.hxx", # SbxDataType + "connectivity/source/inc/dbase/DTable.hxx", # ODbaseTable::DBFType + "codemaker/source/javamaker/classfile.hxx", # AccessFlags + "basic/source/inc/filefmt.hxx", # FileOffset + "basic/source/inc/opcodes.hxx", # SbiOpcode + "sc/source/filter/inc/flttypes.hxx", # BiffTyp + "sc/inc/optutil.hxx", # ScOptionsUtil::KeyBindingType + "include/sfx2/chalign.hxx", # SfxChildAlignment + "drawinglayer/source/tools/emfpbrush.hxx", + "drawinglayer/source/tools/emfppen.cxx", + "include/oox/ppt/animationspersist.hxx", + "include/vcl/fontcapabilities.hxx", + "sw/inc/poolfmt.hxx", + "include/xmloff/xmltoken.hxx", + # unit test code + "cppu/source/uno/check.cxx", + # general weird nonsense going on + "framework/inc/helper/mischelper.hxx" + "include/sfx2/shell.hxx", + "framework/inc/helper/mischelper.hxx", + "include/svtools/htmltokn.h", + "include/sfx2/shell.hxx", + "sw/inc/iodetect.hxx", + "sw/inc/fmtfordr.hxx", + "sw/inc/flddat.hxx", + "sw/source/uibase/config/modcfg.cxx", # InsertConfigProp + "sw/inc/calc.hxx", # SwCalcOper + "svtools/source/config/helpopt.cxx", # HelpProperty + "include/svtools/htmltokn.h", + "include/sfx2/sidebar/Theme.hxx", # ThemeItem + "sc/source/ui/docshell/impex.cxx", # SylkVersion + "include/i18nutil/paper.hxx", # Paper + "cppcanvas/source/mtfrenderer/emfplus.cxx", # EmfPlusCombineMode + "cppcanvas/source/mtfrenderer/emfpbrush.hxx", # EmfPlusHatchStyle + "include/filter/msfilter/svdfppt.hxx", # PptPlaceholder, PptSlideLayout + "include/filter/msfilter/escherex.hxx", # various + "basic/source/inc/opcodes.hxx", # SbiOpcode + "basic/source/inc/token.hxx", # SbiToken + "binaryurp/source/specialfunctionids.hxx", # binaryurp::SpecialFunctionIds + "connectivity/source/inc/odbc/OTools.hxx", # ODBC3SQLFunctionId + "include/formula/grammar.hxx", # FormulaGrammar::Grammar + "basic/source/sbx/sbxres.hxx", # StringId + "sc/source/core/tool/chartpos.cxx", # CellState + "sc/source/core/data/global2.cxx", # State + "sc/inc/global.hxx", # ScAggregateFunc + "registry/source/reflcnst.hxx", #CPInfoTag + # Windows or OSX only + "include/canvas/rendering/icolorbuffer.hxx", + "include/vcl/commandevent.hxx", + "vcl/inc/unx/gendata.hxx", + "vcl/inc/salwtype.hxx", + "include/vcl/svapp.hxx", + "include/vcl/commandevent.hxx", # CommandEvent, MediaCommand, ShowDialogId + "include/canvas/rendering/irendermodule.hxx", # canvas::IRenderModule::PrimitiveType + "sal/osl/unx/file.cxx", # FileHandle_Impl::Kind + # must match some other enum + "include/editeng/bulletitem.hxx", + "include/editeng/svxenum.hxx", + "include/formula/opcode.hxx", # OpCode + "include/i18nutil/paper.hxx", + "include/oox/drawingml/shapepropertymap.hxx", + "include/svl/nfkeytab.hx", + "include/svl/zforlist.hxx", + "include/vcl/svtabbx.hxx", + "include/vcl/print.hxx", # NupOrderType, from UI combobox + "sw/source/uibase/inc/swcont.hxx", # RegionMode, from UI; ContentTypeId, from UI(registry) + "sw/inc/toxe.hxx", # ToxAuthorityType (from UI) + "include/svx/sxekitm.hxx", # SdrEdgeKind (from UI) + "include/svx/paraprev.hxx", # SvxPrevLineSpace (from UI) + "include/svx/ctredlin.hxx", # SvxRedlinDateMode (from UI) + "sd/source/ui/inc/animobjs.hxx", # BitmapAdjustment (from UI) + "sd/source/ui/dlg/PhotoAlbumDialog.hxx", # SlideImageLayout (from UI) + "sd/inc/pres.hxx", # AutoLayout (from UI) + "sc/source/ui/inc/scuitphfedit.hxx", # ScHFEntryId (from UI) + "include/i18nlangtag/languagetag.hxx", # LanguageTag::ScriptType + "extensions/source/scanner/grid.hxx", # ResetType (from UI) + "dbaccess/source/inc/dsntypes.hxx", # dbaccess::DATASOURCE_TYPE (from UI) + "cui/source/tabpages/tparea.cxx", # FillType (from UI) + "include/editeng/svxenum.hxx", # css::style::NumberingType + "include/editeng/bulletitem.hxx", # css::style::NumberingType + "basic/source/sbx/sbxdec.hxx", # SbxDecimal::CmpResult, must match some Windows API + "codemaker/source/javamaker/javatype.cxx", # TypeInfo::Flags, from UNO + "chart2/source/view/inc/AbstractShapeFactory.hxx", # chart::SymbolEnum, called via int UNO param + # represents constants from an external API + "opencl/inc/opencl_device_selection.h", + "vcl/inc/sft.hxx", + "vcl/unx/gtk/xid_fullscreen_on_all_monitors.c", + "vcl/unx/gtk/salnativewidgets-gtk.cxx", + "sc/inc/callform.hxx", # ParamType + "include/i18nlangtag/applelangid.hxx", # AppleLanguageId + "connectivity/source/drivers/firebird/Util.hxx", # firebird::BlobSubtype + "include/xmloff/xmltoken.hxx", + "writerfilter/source/rtftok/rtfcontrolwords.hxx", + ]): + return True + if d[1] == "UNKNOWN" or d[1] == "LAST" or d[1].endswith("NONE") or d[1].endswith("None") or d[1].endswith("EQUAL_SIZE"): + return True + return False + + +untouchedSet = set() +for d in definitionSet: + if d in readSet or d in writeSet: + continue + srcLoc = definitionToSourceLocationMap[d]; + if (is_ignore(srcLoc)): + continue + + untouchedSet.add((d[0] + " " + d[1], srcLoc)) + +writeonlySet = set() +for d in writeSet: + if d in readSet: + continue + # can happen with stuff in workdir or external + if d not in definitionSet: + continue + srcLoc = definitionToSourceLocationMap[d]; + if (is_ignore(srcLoc)): + continue + writeonlySet.add((d[0] + " " + d[1], srcLoc)) + +readonlySet = set() +for d in readSet: + if d in writeSet: + continue + # can happen with stuff in workdir or external + if d not in definitionSet: + continue + srcLoc = definitionToSourceLocationMap[d]; + if (is_ignore(srcLoc)): + continue + readonlySet.add((d[0] + " " + d[1], srcLoc)) + +# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[1]) + [v[0]] + +# sort results by name and line number +tmp1list = sorted(untouchedSet, key=lambda v: v_sort_key(v)) +tmp2list = sorted(writeonlySet, key=lambda v: v_sort_key(v)) +tmp3list = sorted(readonlySet, key=lambda v: v_sort_key(v)) + +# print out the results +with open("compilerplugins/clang/unusedenumconstants.untouched.results", "wt") as f: + for t in tmp1list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) +with open("compilerplugins/clang/unusedenumconstants.writeonly.results", "wt") as f: + for t in tmp2list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) +with open("compilerplugins/clang/unusedenumconstants.readonly.results", "wt") as f: + for t in tmp3list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) + + diff --git a/compilerplugins/clang/unusedenumconstants.readonly.results b/compilerplugins/clang/unusedenumconstants.readonly.results new file mode 100644 index 000000000..02ec1e8a7 --- /dev/null +++ b/compilerplugins/clang/unusedenumconstants.readonly.results @@ -0,0 +1,1030 @@ +bridges/source/cpp_uno/gcc3_linux_x86-64/abi.cxx:79 + enum (anonymous namespace)::x86_64_reg_class X86_64_SSEUP_CLASS +bridges/source/cpp_uno/gcc3_linux_x86-64/abi.cxx:80 + enum (anonymous namespace)::x86_64_reg_class X86_64_X87_CLASS +bridges/source/cpp_uno/gcc3_linux_x86-64/abi.cxx:81 + enum (anonymous namespace)::x86_64_reg_class X86_64_X87UP_CLASS +chart2/source/inc/CharacterProperties.hxx:120 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) FAST_PROPERTY_ID_END_CHAR_PROP +chart2/source/inc/TitleHelper.hxx:47 + enum chart::TitleHelper::eTitleType NORMAL_TITLE_END +chart2/source/view/inc/ShapeFactory.hxx:49 + enum chart::SymbolEnum Symbol_Square +chart2/source/view/inc/ShapeFactory.hxx:50 + enum chart::SymbolEnum Symbol_Diamond +chart2/source/view/inc/ShapeFactory.hxx:51 + enum chart::SymbolEnum Symbol_DownArrow +chart2/source/view/inc/ShapeFactory.hxx:52 + enum chart::SymbolEnum Symbol_UpArrow +chart2/source/view/inc/ShapeFactory.hxx:53 + enum chart::SymbolEnum Symbol_RightArrow +chart2/source/view/inc/ShapeFactory.hxx:54 + enum chart::SymbolEnum Symbol_LeftArrow +chart2/source/view/inc/ShapeFactory.hxx:55 + enum chart::SymbolEnum Symbol_Bowtie +chart2/source/view/inc/ShapeFactory.hxx:56 + enum chart::SymbolEnum Symbol_Sandglass +chart2/source/view/inc/ShapeFactory.hxx:57 + enum chart::SymbolEnum Symbol_Circle +chart2/source/view/inc/ShapeFactory.hxx:58 + enum chart::SymbolEnum Symbol_Star +chart2/source/view/inc/ShapeFactory.hxx:59 + enum chart::SymbolEnum Symbol_X +chart2/source/view/inc/ShapeFactory.hxx:60 + enum chart::SymbolEnum Symbol_Plus +chart2/source/view/inc/ShapeFactory.hxx:61 + enum chart::SymbolEnum Symbol_Asterisk +chart2/source/view/inc/ShapeFactory.hxx:62 + enum chart::SymbolEnum Symbol_HorizontalBar +chart2/source/view/inc/ShapeFactory.hxx:63 + enum chart::SymbolEnum Symbol_VerticalBar +configmgr/source/access.hxx:443 + enum configmgr::Access::(anonymous at /home/noel/libo2/configmgr/source/access.hxx:441:5) IS_GROUP_MEMBER +configmgr/source/access.hxx:443 + enum configmgr::Access::(anonymous at /home/noel/libo2/configmgr/source/access.hxx:441:5) IS_SET_MEMBER +configmgr/source/components.hxx:149 + enum configmgr::Components::ModificationTarget Dconf +configmgr/source/parsemanager.hxx:43 + enum configmgr::ParseManager::(anonymous at /home/noel/libo2/configmgr/source/parsemanager.hxx:43:5) NAMESPACE_OOR +configmgr/source/parsemanager.hxx:43 + enum configmgr::ParseManager::(anonymous at /home/noel/libo2/configmgr/source/parsemanager.hxx:43:5) NAMESPACE_XS +configmgr/source/parsemanager.hxx:43 + enum configmgr::ParseManager::(anonymous at /home/noel/libo2/configmgr/source/parsemanager.hxx:43:5) NAMESPACE_XSI +connectivity/source/drivers/evoab2/NConnection.hxx:37 + connectivity::evoab::SDBCAddress::sdbc_address_type Unknown +cui/source/options/optgenrl.cxx:63 + enum (anonymous namespace)::RowType nRowCount +dbaccess/source/core/inc/SingleSelectQueryComposer.hxx:71 + enum dbaccess::OSingleSelectQueryComposer::EColumnType SelectColumns +dbaccess/source/ui/inc/sqlmessage.hxx:56 + enum dbaui::MessBoxStyle DefaultCancel +drawinglayer/source/tools/emfphelperdata.cxx:61 + enum emfplushelper::(anonymous at /home/noel/libo2/drawinglayer/source/tools/emfphelperdata.cxx:59:5) WrapModeTile +drawinglayer/source/tools/emfphelperdata.cxx:62 + enum emfplushelper::(anonymous at /home/noel/libo2/drawinglayer/source/tools/emfphelperdata.cxx:59:5) WrapModeTileFlipX +drawinglayer/source/tools/emfphelperdata.cxx:63 + enum emfplushelper::(anonymous at /home/noel/libo2/drawinglayer/source/tools/emfphelperdata.cxx:59:5) WrapModeTileFlipY +drawinglayer/source/tools/emfphelperdata.cxx:64 + enum emfplushelper::(anonymous at /home/noel/libo2/drawinglayer/source/tools/emfphelperdata.cxx:59:5) WrapModeTileFlipXY +drawinglayer/source/tools/emfphelperdata.hxx:107 + enum emfplushelper::PixelOffsetMode PixelOffsetModeDefault +drawinglayer/source/tools/emfphelperdata.hxx:108 + enum emfplushelper::PixelOffsetMode PixelOffsetModeHighSpeed +drawinglayer/source/tools/emfphelperdata.hxx:109 + enum emfplushelper::PixelOffsetMode PixelOffsetModeHighQuality +drawinglayer/source/tools/emfphelperdata.hxx:111 + enum emfplushelper::PixelOffsetMode PixelOffsetModeHalf +drawinglayer/source/tools/emfphelperdata.hxx:116 + enum emfplushelper::SmoothingMode SmoothingModeDefault +drawinglayer/source/tools/emfphelperdata.hxx:117 + enum emfplushelper::SmoothingMode SmoothingModeHighSpeed +drawinglayer/source/tools/emfphelperdata.hxx:118 + enum emfplushelper::SmoothingMode SmoothingModeHighQuality +drawinglayer/source/tools/emfphelperdata.hxx:120 + enum emfplushelper::SmoothingMode SmoothingModeAntiAlias8x4 +drawinglayer/source/tools/emfphelperdata.hxx:121 + enum emfplushelper::SmoothingMode SmoothingModeAntiAlias8x8 +drawinglayer/source/tools/emfphelperdata.hxx:126 + enum emfplushelper::InterpolationMode InterpolationModeDefault +drawinglayer/source/tools/emfphelperdata.hxx:127 + enum emfplushelper::InterpolationMode InterpolationModeLowQuality +drawinglayer/source/tools/emfphelperdata.hxx:128 + enum emfplushelper::InterpolationMode InterpolationModeHighQuality +drawinglayer/source/tools/emfphelperdata.hxx:129 + enum emfplushelper::InterpolationMode InterpolationModeBilinear +drawinglayer/source/tools/emfphelperdata.hxx:130 + enum emfplushelper::InterpolationMode InterpolationModeBicubic +drawinglayer/source/tools/emfphelperdata.hxx:131 + enum emfplushelper::InterpolationMode InterpolationModeNearestNeighbor +drawinglayer/source/tools/emfphelperdata.hxx:132 + enum emfplushelper::InterpolationMode InterpolationModeHighQualityBilinear +drawinglayer/source/tools/emfphelperdata.hxx:133 + enum emfplushelper::InterpolationMode InterpolationModeHighQualityBicubic +drawinglayer/source/tools/emfphelperdata.hxx:138 + enum emfplushelper::TextRenderingHint TextRenderingHintSystemDefault +drawinglayer/source/tools/emfphelperdata.hxx:139 + enum emfplushelper::TextRenderingHint TextRenderingHintSingleBitPerPixelGridFit +drawinglayer/source/tools/emfphelperdata.hxx:140 + enum emfplushelper::TextRenderingHint TextRenderingHintSingleBitPerPixel +drawinglayer/source/tools/emfphelperdata.hxx:141 + enum emfplushelper::TextRenderingHint TextRenderingHintAntialiasGridFit +drawinglayer/source/tools/emfphelperdata.hxx:142 + enum emfplushelper::TextRenderingHint TextRenderingHintAntialias +drawinglayer/source/tools/emfphelperdata.hxx:143 + enum emfplushelper::TextRenderingHint TextRenderingHintClearTypeGridFit +drawinglayer/source/tools/emfphelperdata.hxx:148 + enum emfplushelper::UnitType UnitTypeWorld +drawinglayer/source/tools/emfphelperdata.hxx:149 + enum emfplushelper::UnitType UnitTypeDisplay +drawinglayer/source/tools/emfphelperdata.hxx:150 + enum emfplushelper::UnitType UnitTypePixel +drawinglayer/source/tools/emfphelperdata.hxx:151 + enum emfplushelper::UnitType UnitTypePoint +drawinglayer/source/tools/emfphelperdata.hxx:152 + enum emfplushelper::UnitType UnitTypeInch +drawinglayer/source/tools/emfphelperdata.hxx:153 + enum emfplushelper::UnitType UnitTypeDocument +drawinglayer/source/tools/emfphelperdata.hxx:154 + enum emfplushelper::UnitType UnitTypeMillimeter +drawinglayer/source/tools/emfphelperdata.hxx:159 + enum emfplushelper::EmfPlusCombineMode EmfPlusCombineModeReplace +drawinglayer/source/tools/emfphelperdata.hxx:160 + enum emfplushelper::EmfPlusCombineMode EmfPlusCombineModeIntersect +drawinglayer/source/tools/emfphelperdata.hxx:161 + enum emfplushelper::EmfPlusCombineMode EmfPlusCombineModeUnion +drawinglayer/source/tools/emfphelperdata.hxx:162 + enum emfplushelper::EmfPlusCombineMode EmfPlusCombineModeXOR +drawinglayer/source/tools/emfphelperdata.hxx:163 + enum emfplushelper::EmfPlusCombineMode EmfPlusCombineModeExclude +drawinglayer/source/tools/emfphelperdata.hxx:164 + enum emfplushelper::EmfPlusCombineMode EmfPlusCombineModeComplement +drawinglayer/source/tools/emfpimage.hxx:31 + emfplushelper::ImageDataType ImageDataTypeBitmap +drawinglayer/source/tools/emfpimage.hxx:32 + emfplushelper::ImageDataType ImageDataTypeMetafile +drawinglayer/source/tools/emfppen.hxx:58 + enum emfplushelper::LineCapType LineCapTypeFlat +drawinglayer/source/tools/emfppen.hxx:59 + enum emfplushelper::LineCapType LineCapTypeSquare +drawinglayer/source/tools/emfppen.hxx:60 + enum emfplushelper::LineCapType LineCapTypeRound +drawinglayer/source/tools/emfppen.hxx:61 + enum emfplushelper::LineCapType LineCapTypeTriangle +drawinglayer/source/tools/emfppen.hxx:62 + enum emfplushelper::LineCapType LineCapTypeNoAnchor +drawinglayer/source/tools/emfppen.hxx:63 + enum emfplushelper::LineCapType LineCapTypeSquareAnchor +drawinglayer/source/tools/emfppen.hxx:64 + enum emfplushelper::LineCapType LineCapTypeRoundAnchor +drawinglayer/source/tools/emfppen.hxx:65 + enum emfplushelper::LineCapType LineCapTypeDiamondAnchor +drawinglayer/source/tools/emfppen.hxx:66 + enum emfplushelper::LineCapType LineCapTypeArrowAnchor +drawinglayer/source/tools/emfppen.hxx:67 + enum emfplushelper::LineCapType LineCapTypeAnchorMask +drawinglayer/source/tools/emfppen.hxx:68 + enum emfplushelper::LineCapType LineCapTypeCustom +drawinglayer/source/tools/emfppen.hxx:73 + enum emfplushelper::LineJoinType LineJoinTypeMiter +drawinglayer/source/tools/emfppen.hxx:74 + enum emfplushelper::LineJoinType LineJoinTypeBevel +drawinglayer/source/tools/emfppen.hxx:75 + enum emfplushelper::LineJoinType LineJoinTypeRound +drawinglayer/source/tools/emfppen.hxx:76 + enum emfplushelper::LineJoinType LineJoinTypeMiterClipped +drawinglayer/source/tools/emfppen.hxx:81 + enum emfplushelper::DashedLineCapType DashedLineCapTypeFlat +drawinglayer/source/tools/emfppen.hxx:82 + enum emfplushelper::DashedLineCapType DashedLineCapTypeRound +drawinglayer/source/tools/emfppen.hxx:83 + enum emfplushelper::DashedLineCapType DashedLineCapTypeTriangle +drawinglayer/source/tools/emfppen.hxx:88 + enum emfplushelper::PenAlignment PenAlignmentCenter +drawinglayer/source/tools/emfppen.hxx:89 + enum emfplushelper::PenAlignment PenAlignmentInset +drawinglayer/source/tools/emfppen.hxx:90 + enum emfplushelper::PenAlignment PenAlignmentLeft +drawinglayer/source/tools/emfppen.hxx:91 + enum emfplushelper::PenAlignment PenAlignmentOutset +drawinglayer/source/tools/emfppen.hxx:92 + enum emfplushelper::PenAlignment PenAlignmentRight +drawinglayer/source/tools/emfpregion.hxx:28 + emfplushelper::RegionNodeDataType RegionNodeDataTypeAnd +drawinglayer/source/tools/emfpregion.hxx:29 + emfplushelper::RegionNodeDataType RegionNodeDataTypeOr +drawinglayer/source/tools/emfpregion.hxx:30 + emfplushelper::RegionNodeDataType RegionNodeDataTypeXor +drawinglayer/source/tools/emfpregion.hxx:31 + emfplushelper::RegionNodeDataType RegionNodeDataTypeExclude +drawinglayer/source/tools/emfpregion.hxx:32 + emfplushelper::RegionNodeDataType RegionNodeDataTypeComplement +drawinglayer/source/tools/emfpregion.hxx:33 + emfplushelper::RegionNodeDataType RegionNodeDataTypeRect +drawinglayer/source/tools/emfpregion.hxx:34 + emfplushelper::RegionNodeDataType RegionNodeDataTypePath +drawinglayer/source/tools/emfpregion.hxx:35 + emfplushelper::RegionNodeDataType RegionNodeDataTypeEmpty +drawinglayer/source/tools/emfpregion.hxx:36 + emfplushelper::RegionNodeDataType RegionNodeDataTypeInfinite +drawinglayer/source/tools/emfpstringformat.hxx:39 + enum emfplushelper::StringAlignment StringAlignmentNear +drawinglayer/source/tools/emfpstringformat.hxx:40 + enum emfplushelper::StringAlignment StringAlignmentCenter +drawinglayer/source/tools/emfpstringformat.hxx:41 + enum emfplushelper::StringAlignment StringAlignmentFar +drawinglayer/source/tools/emfpstringformat.hxx:46 + enum emfplushelper::StringDigitSubstitution StringDigitSubstitutionUser +drawinglayer/source/tools/emfpstringformat.hxx:48 + enum emfplushelper::StringDigitSubstitution StringDigitSubstitutionNational +drawinglayer/source/tools/emfpstringformat.hxx:49 + enum emfplushelper::StringDigitSubstitution StringDigitSubstitutionTraditional +drawinglayer/source/tools/emfpstringformat.hxx:55 + enum emfplushelper::HotkeyPrefix HotkeyPrefixShow +drawinglayer/source/tools/emfpstringformat.hxx:56 + enum emfplushelper::HotkeyPrefix HotkeyPrefixHide +drawinglayer/source/tools/emfpstringformat.hxx:62 + enum emfplushelper::StringTrimming StringTrimmingCharacter +drawinglayer/source/tools/emfpstringformat.hxx:63 + enum emfplushelper::StringTrimming StringTrimmingWord +drawinglayer/source/tools/emfpstringformat.hxx:64 + enum emfplushelper::StringTrimming StringTrimmingEllipsisCharacter +drawinglayer/source/tools/emfpstringformat.hxx:65 + enum emfplushelper::StringTrimming StringTrimmingEllipsisWord +drawinglayer/source/tools/emfpstringformat.hxx:66 + enum emfplushelper::StringTrimming StringTrimmingEllipsisPath +editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx:26 + enum SvXMLAutoCorrectToken BLOCK +editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx:27 + enum SvXMLAutoCorrectToken BLOCKLIST +emfio/inc/mtftools.hxx:83 + enum emfio::WMFRasterOp Nop +framework/inc/xml/imagesdocumenthandler.hxx:39 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ELEMENT_IMAGECONTAINER +framework/inc/xml/imagesdocumenthandler.hxx:40 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ELEMENT_IMAGES +framework/inc/xml/imagesdocumenthandler.hxx:41 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ELEMENT_ENTRY +framework/inc/xml/imagesdocumenthandler.hxx:46 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ATTRIBUTE_COMMAND +framework/inc/xml/statusbardocumenthandler.hxx:43 + enum framework::OReadStatusBarDocumentHandler::StatusBar_XML_Entry SB_ELEMENT_STATUSBAR +framework/inc/xml/statusbardocumenthandler.hxx:44 + enum framework::OReadStatusBarDocumentHandler::StatusBar_XML_Entry SB_ELEMENT_STATUSBARITEM +framework/inc/xml/statusbardocumenthandler.hxx:45 + enum framework::OReadStatusBarDocumentHandler::StatusBar_XML_Entry SB_ATTRIBUTE_URL +framework/inc/xml/statusbardocumenthandler.hxx:46 + enum framework::OReadStatusBarDocumentHandler::StatusBar_XML_Entry SB_ATTRIBUTE_ALIGN +framework/inc/xml/statusbardocumenthandler.hxx:47 + enum framework::OReadStatusBarDocumentHandler::StatusBar_XML_Entry SB_ATTRIBUTE_STYLE +framework/inc/xml/statusbardocumenthandler.hxx:48 + enum framework::OReadStatusBarDocumentHandler::StatusBar_XML_Entry SB_ATTRIBUTE_AUTOSIZE +framework/inc/xml/statusbardocumenthandler.hxx:49 + enum framework::OReadStatusBarDocumentHandler::StatusBar_XML_Entry SB_ATTRIBUTE_OWNERDRAW +framework/inc/xml/statusbardocumenthandler.hxx:50 + enum framework::OReadStatusBarDocumentHandler::StatusBar_XML_Entry SB_ATTRIBUTE_WIDTH +framework/inc/xml/statusbardocumenthandler.hxx:51 + enum framework::OReadStatusBarDocumentHandler::StatusBar_XML_Entry SB_ATTRIBUTE_OFFSET +framework/inc/xml/statusbardocumenthandler.hxx:52 + enum framework::OReadStatusBarDocumentHandler::StatusBar_XML_Entry SB_ATTRIBUTE_HELPURL +framework/inc/xml/statusbardocumenthandler.hxx:53 + enum framework::OReadStatusBarDocumentHandler::StatusBar_XML_Entry SB_ATTRIBUTE_MANDATORY +framework/inc/xml/toolboxdocumenthandler.hxx:43 + enum framework::OReadToolBoxDocumentHandler::ToolBox_XML_Entry TB_ELEMENT_TOOLBAR +framework/inc/xml/toolboxdocumenthandler.hxx:44 + enum framework::OReadToolBoxDocumentHandler::ToolBox_XML_Entry TB_ELEMENT_TOOLBARITEM +framework/inc/xml/toolboxdocumenthandler.hxx:45 + enum framework::OReadToolBoxDocumentHandler::ToolBox_XML_Entry TB_ELEMENT_TOOLBARSPACE +framework/inc/xml/toolboxdocumenthandler.hxx:46 + enum framework::OReadToolBoxDocumentHandler::ToolBox_XML_Entry TB_ELEMENT_TOOLBARBREAK +framework/inc/xml/toolboxdocumenthandler.hxx:47 + enum framework::OReadToolBoxDocumentHandler::ToolBox_XML_Entry TB_ELEMENT_TOOLBARSEPARATOR +framework/inc/xml/toolboxdocumenthandler.hxx:48 + enum framework::OReadToolBoxDocumentHandler::ToolBox_XML_Entry TB_ATTRIBUTE_TEXT +framework/inc/xml/toolboxdocumenthandler.hxx:49 + enum framework::OReadToolBoxDocumentHandler::ToolBox_XML_Entry TB_ATTRIBUTE_URL +framework/inc/xml/toolboxdocumenthandler.hxx:50 + enum framework::OReadToolBoxDocumentHandler::ToolBox_XML_Entry TB_ATTRIBUTE_VISIBLE +framework/inc/xml/toolboxdocumenthandler.hxx:51 + enum framework::OReadToolBoxDocumentHandler::ToolBox_XML_Entry TB_ATTRIBUTE_STYLE +framework/inc/xml/toolboxdocumenthandler.hxx:52 + enum framework::OReadToolBoxDocumentHandler::ToolBox_XML_Entry TB_ATTRIBUTE_UINAME +include/connectivity/dbtools.hxx:817 + enum connectivity::dbase::DBFType dBaseIII +include/connectivity/dbtools.hxx:818 + enum connectivity::dbase::DBFType dBaseIV +include/connectivity/dbtools.hxx:819 + enum connectivity::dbase::DBFType dBaseV +include/connectivity/dbtools.hxx:820 + enum connectivity::dbase::DBFType VisualFoxPro +include/connectivity/dbtools.hxx:821 + enum connectivity::dbase::DBFType VisualFoxProAuto +include/connectivity/dbtools.hxx:822 + enum connectivity::dbase::DBFType dBaseFS +include/connectivity/dbtools.hxx:823 + enum connectivity::dbase::DBFType dBaseFSMemo +include/connectivity/dbtools.hxx:824 + enum connectivity::dbase::DBFType dBaseIIIMemo +include/connectivity/dbtools.hxx:826 + enum connectivity::dbase::DBFType dBaseIVMemoSQL +include/connectivity/dbtools.hxx:827 + enum connectivity::dbase::DBFType FoxProMemo +include/connectivity/sqliterator.hxx:42 + enum connectivity::TraversalParts TableNames +include/desktop/exithelper.h:30 + int EXITHELPER_CRASH_WITH_RESTART +include/desktop/exithelper.h:32 + int EXITHELPER_NORMAL_RESTART +include/editeng/editeng.hxx:126 + enum GetAttribsFlags STYLESHEET +include/editeng/editeng.hxx:127 + enum GetAttribsFlags PARAATTRIBS +include/editeng/editstat.hxx:46 + enum EEControlBits AUTOCOMPLETE +include/editeng/flditem.hxx:91 + enum SvxDateFormat System +include/editeng/flditem.hxx:260 + enum SvxTimeFormat System +include/editeng/flditem.hxx:268 + enum SvxTimeFormat HH12_MM_AMPM +include/editeng/flditem.hxx:269 + enum SvxTimeFormat HH12_MM_SS_AMPM +include/editeng/flditem.hxx:270 + enum SvxTimeFormat HH12_MM_SS_00_AMPM +include/editeng/flditem.hxx:357 + enum SvxAuthorFormat LastName +include/editeng/flditem.hxx:358 + enum SvxAuthorFormat FirstName +include/framework/framelistanalyzer.hxx:40 + enum FrameAnalyzerFlags Model +include/framework/framelistanalyzer.hxx:45 + enum FrameAnalyzerFlags Zombie +include/i18nutil/casefolding.hxx:40 + enum MappingType CasedLetterMask +include/i18nutil/casefolding.hxx:41 + enum MappingType NotValue +include/LibreOfficeKit/LibreOfficeKitEnums.h:33 + LibreOfficeKitPartMode LOK_PARTMODE_SLIDES +include/LibreOfficeKit/LibreOfficeKitEnums.h:34 + LibreOfficeKitPartMode LOK_PARTMODE_NOTES +include/LibreOfficeKit/LibreOfficeKitEnums.h:40 + LibreOfficeKitTileMode LOK_TILEMODE_RGBA +include/LibreOfficeKit/LibreOfficeKitEnums.h:99 + LibreOfficeKitOptionalFeatures LOK_FEATURE_RANGE_HEADERS +include/o3tl/unit_conversion.hxx:47 + enum o3tl::Length count +include/oox/core/filterbase.hxx:77 + enum oox::core::OoxmlVersion ISOIEC_29500_2008 +include/oox/mathml/export.hxx:33 + enum oox::FormulaExportBase::eFormulaAlign GROUPEDCENTER +include/sfx2/lnkbase.hxx:54 + enum sfx2::SvBaseLinkObjectType DdeExternal +include/svl/ctloptions.hxx:64 + enum SvtCTLOptions::TextNumerals NUMERALS_HINDI +include/svl/ctloptions.hxx:65 + enum SvtCTLOptions::TextNumerals NUMERALS_SYSTEM +include/svl/ctloptions.hxx:66 + enum SvtCTLOptions::TextNumerals NUMERALS_CONTEXT +include/svl/ctloptions.hxx:77 + enum SvtCTLOptions::EOption E_CTLSEQUENCECHECKINGRESTRICTED +include/svl/ctloptions.hxx:78 + enum SvtCTLOptions::EOption E_CTLSEQUENCECHECKINGTYPEANDREPLACE +include/svl/languageoptions.hxx:60 + enum SvtLanguageOptions::EOption E_CJKFONT +include/svl/languageoptions.hxx:61 + enum SvtLanguageOptions::EOption E_VERTICALTEXT +include/svl/languageoptions.hxx:62 + enum SvtLanguageOptions::EOption E_ASIANTYPOGRAPHY +include/svl/languageoptions.hxx:63 + enum SvtLanguageOptions::EOption E_JAPANESEFIND +include/svl/languageoptions.hxx:64 + enum SvtLanguageOptions::EOption E_RUBY +include/svl/languageoptions.hxx:65 + enum SvtLanguageOptions::EOption E_CHANGECASEMAP +include/svl/languageoptions.hxx:66 + enum SvtLanguageOptions::EOption E_DOUBLELINES +include/svl/languageoptions.hxx:67 + enum SvtLanguageOptions::EOption E_EMPHASISMARKS +include/svl/languageoptions.hxx:68 + enum SvtLanguageOptions::EOption E_VERTICALCALLOUT +include/svl/languageoptions.hxx:72 + enum SvtLanguageOptions::EOption E_CTLSEQUENCECHECKING +include/svl/languageoptions.hxx:73 + enum SvtLanguageOptions::EOption E_CTLCURSORMOVEMENT +include/svl/languageoptions.hxx:74 + enum SvtLanguageOptions::EOption E_CTLTEXTNUMERALS +include/svl/lockfilecommon.hxx:36 + enum LockFileComponent EDITTIME +include/svl/lockfilecommon.hxx:36 + enum LockFileComponent LOCALHOST +include/svl/lockfilecommon.hxx:36 + enum LockFileComponent OOOUSERNAME +include/svl/lockfilecommon.hxx:36 + enum LockFileComponent SYSUSERNAME +include/svl/srchdefs.hxx:40 + enum SearchOptionFlags WILDCARD +include/svtools/apearcfg.hxx:29 + enum SnapType ToMiddle +include/svtools/apearcfg.hxx:34 + enum DragMode FullWindow +include/svtools/apearcfg.hxx:35 + enum DragMode Frame +include/svx/EnhancedCustomShapeGeometry.hxx:47 + enum SvxMSDffHandleFlags MIRRORED_X +include/svx/EnhancedCustomShapeGeometry.hxx:48 + enum SvxMSDffHandleFlags MIRRORED_Y +include/svx/EnhancedCustomShapeGeometry.hxx:51 + enum SvxMSDffHandleFlags MAP +include/svx/EnhancedCustomShapeGeometry.hxx:57 + enum SvxMSDffHandleFlags CENTER_X_IS_SPECIAL +include/svx/EnhancedCustomShapeGeometry.hxx:58 + enum SvxMSDffHandleFlags CENTER_Y_IS_SPECIAL +include/svx/flagsdef.hxx:106 + enum TabulatorDisableFlags TypeRight +include/svx/flagsdef.hxx:107 + enum TabulatorDisableFlags TypeCenter +include/svx/flagsdef.hxx:108 + enum TabulatorDisableFlags TypeDecimal +include/svx/flagsdef.hxx:112 + enum TabulatorDisableFlags FillPoint +include/svx/flagsdef.hxx:113 + enum TabulatorDisableFlags FillDashLine +include/svx/flagsdef.hxx:114 + enum TabulatorDisableFlags FillSolidLine +include/svx/flagsdef.hxx:115 + enum TabulatorDisableFlags FillSpecial +include/svx/ruler.hxx:60 + enum SvxRulerDragFlags OBJECT_LEFT_INDENT_ONLY +include/svx/sdtakitm.hxx:31 + enum SdrTextAniKind Blink +include/svx/svdhdl.hxx:108 + enum BitmapMarkerKind RectPlus_7x7 +include/svx/svdograf.hxx:51 + enum SdrGrafObjTransformsAttrs ROTATE +include/svx/swframeposstrings.hxx:79 + enum SvxSwFramePosString::StringId STR_MAX +include/svx/swframetypes.hxx:41 + enum RndStdIds HEADERR +include/tools/inetmsg.hxx:72 + enum InetMessageMime NUMHDR +include/unotools/extendedsecurityoptions.hxx:27 + enum SvtExtendedSecurityOptions::OpenHyperlinkMode OPEN_NEVER +include/unotools/fontcfg.hxx:51 + enum ImplFontAttrs Default +include/unotools/fontcfg.hxx:52 + enum ImplFontAttrs Standard +include/unotools/fontcfg.hxx:53 + enum ImplFontAttrs Normal +include/unotools/fontcfg.hxx:59 + enum ImplFontAttrs Special +include/unotools/fontcfg.hxx:68 + enum ImplFontAttrs CTL +include/unotools/fontcfg.hxx:69 + enum ImplFontAttrs NoneLatin +include/unotools/fontcfg.hxx:70 + enum ImplFontAttrs Full +include/unotools/fontcfg.hxx:83 + enum ImplFontAttrs CJK_AllLang +include/unotools/fontcfg.hxx:85 + enum ImplFontAttrs AllSubscript +include/unotools/fontcfg.hxx:86 + enum ImplFontAttrs AllSerifStyle +include/unotools/fontdefs.hxx:73 + enum DefaultFontType LATIN_DISPLAY +include/unotools/fontdefs.hxx:74 + enum DefaultFontType LATIN_FIXED +include/unotools/fontdefs.hxx:84 + enum DefaultFontType CTL_DISPLAY +include/vcl/bitmap.hxx:83 + enum BmpCombine And +include/vcl/errinf.hxx:89 + enum DialogMask ButtonsYesNo +include/vcl/errinf.hxx:92 + enum DialogMask ButtonDefaultsCancel +include/vcl/errinf.hxx:93 + enum DialogMask ButtonDefaultsYes +include/vcl/errinf.hxx:94 + enum DialogMask ButtonDefaultsNo +include/vcl/gfxlink.hxx:54 + enum GfxLinkType NativeFirst +include/vcl/gfxlink.hxx:55 + enum GfxLinkType NativeLast +include/vcl/GraphicObject.hxx:35 + enum GraphicAdjustmentFlags DRAWMODE +include/vcl/GraphicObject.hxx:36 + enum GraphicAdjustmentFlags COLORS +include/vcl/GraphicObject.hxx:37 + enum GraphicAdjustmentFlags MIRROR +include/vcl/GraphicObject.hxx:38 + enum GraphicAdjustmentFlags ROTATE +include/vcl/GraphicObject.hxx:39 + enum GraphicAdjustmentFlags TRANSPARENCY +include/vcl/graphictools.hxx:227 + enum SvtGraphicFill::FillType fillSolid +include/vcl/headbar.hxx:187 + enum HeaderBarItemBits RIGHTIMAGE +include/vcl/help.hxx:41 + enum QuickHelpFlags NoAutoPos +include/vcl/keycod.hxx:31 + enum KeyFuncType REDO +include/vcl/keycodes.hxx:174 + enum ModKeyFlags Mod1Msk +include/vcl/keycodes.hxx:175 + enum ModKeyFlags Mod2Msk +include/vcl/menu.hxx:78 + enum PopupMenuFlags ExecuteUp +include/vcl/pdf/PDFAnnotationSubType.hxx:17 + enum vcl::pdf::PDFAnnotationSubType Unknown +include/vcl/pdf/PDFAnnotationSubType.hxx:26 + enum vcl::pdf::PDFAnnotationSubType Highlight +include/vcl/pdf/PDFAnnotationSubType.hxx:30 + enum vcl::pdf::PDFAnnotationSubType Stamp +include/vcl/pdf/PDFAnnotationSubType.hxx:45 + enum vcl::pdf::PDFAnnotationSubType Redact +include/vcl/pdf/PDFBitmapType.hxx:17 + enum vcl::pdf::PDFBitmapType Unknown +include/vcl/pdf/PDFBitmapType.hxx:18 + enum vcl::pdf::PDFBitmapType Gray +include/vcl/pdf/PDFBitmapType.hxx:19 + enum vcl::pdf::PDFBitmapType BGR +include/vcl/pdf/PDFBitmapType.hxx:20 + enum vcl::pdf::PDFBitmapType BGRx +include/vcl/pdf/PDFBitmapType.hxx:21 + enum vcl::pdf::PDFBitmapType BGRA +include/vcl/pdf/PDFErrorType.hxx:17 + enum vcl::pdf::PDFErrorType Success +include/vcl/pdf/PDFErrorType.hxx:18 + enum vcl::pdf::PDFErrorType Unknown +include/vcl/pdf/PDFErrorType.hxx:19 + enum vcl::pdf::PDFErrorType File +include/vcl/pdf/PDFErrorType.hxx:20 + enum vcl::pdf::PDFErrorType Format +include/vcl/pdf/PDFErrorType.hxx:21 + enum vcl::pdf::PDFErrorType Password +include/vcl/pdf/PDFErrorType.hxx:22 + enum vcl::pdf::PDFErrorType Security +include/vcl/pdf/PDFErrorType.hxx:23 + enum vcl::pdf::PDFErrorType Page +include/vcl/pdf/PDFFillMode.hxx:19 + enum vcl::pdf::PDFFillMode Winding +include/vcl/pdf/PDFFindFlags.hxx:22 + enum vcl::pdf::PDFFindFlags Consecutive +include/vcl/pdf/PDFObjectType.hxx:17 + enum vcl::pdf::PDFObjectType Unknown +include/vcl/pdf/PDFObjectType.hxx:18 + enum vcl::pdf::PDFObjectType Boolean +include/vcl/pdf/PDFObjectType.hxx:19 + enum vcl::pdf::PDFObjectType Number +include/vcl/pdf/PDFObjectType.hxx:21 + enum vcl::pdf::PDFObjectType Name +include/vcl/pdf/PDFObjectType.hxx:22 + enum vcl::pdf::PDFObjectType Array +include/vcl/pdf/PDFObjectType.hxx:23 + enum vcl::pdf::PDFObjectType Dictionary +include/vcl/pdf/PDFObjectType.hxx:24 + enum vcl::pdf::PDFObjectType Stream +include/vcl/pdf/PDFObjectType.hxx:25 + enum vcl::pdf::PDFObjectType Nullobj +include/vcl/pdf/PDFObjectType.hxx:26 + enum vcl::pdf::PDFObjectType Reference +include/vcl/pdf/PDFPageObjectType.hxx:17 + enum vcl::pdf::PDFPageObjectType Unknown +include/vcl/pdf/PDFPageObjectType.hxx:19 + enum vcl::pdf::PDFPageObjectType Path +include/vcl/pdf/PDFPageObjectType.hxx:21 + enum vcl::pdf::PDFPageObjectType Shading +include/vcl/pdf/PDFSegmentType.hxx:17 + enum vcl::pdf::PDFSegmentType Unknown +include/vcl/pdf/PDFSegmentType.hxx:19 + enum vcl::pdf::PDFSegmentType Bezierto +include/vcl/pdf/PDFTextRenderMode.hxx:17 + enum vcl::pdf::PDFTextRenderMode Unknown +include/vcl/pdf/PDFTextRenderMode.hxx:19 + enum vcl::pdf::PDFTextRenderMode Stroke +include/vcl/pdf/PDFTextRenderMode.hxx:20 + enum vcl::pdf::PDFTextRenderMode FillStroke +include/vcl/pdf/PDFTextRenderMode.hxx:21 + enum vcl::pdf::PDFTextRenderMode Invisible +include/vcl/pdf/PDFTextRenderMode.hxx:22 + enum vcl::pdf::PDFTextRenderMode FillClip +include/vcl/pdf/PDFTextRenderMode.hxx:23 + enum vcl::pdf::PDFTextRenderMode StrokeClip +include/vcl/pdf/PDFTextRenderMode.hxx:24 + enum vcl::pdf::PDFTextRenderMode FillStrokeClip +include/vcl/pdf/PDFTextRenderMode.hxx:25 + enum vcl::pdf::PDFTextRenderMode Clip +include/vcl/pdfwriter.hxx:109 + enum vcl::PDFWriter::PDFVersion PDF_1_2 +include/vcl/pdfwriter.hxx:109 + enum vcl::PDFWriter::PDFVersion PDF_1_3 +include/vcl/pdfwriter.hxx:121 + enum vcl::PDFWriter::StructElement Article +include/vcl/pdfwriter.hxx:121 + enum vcl::PDFWriter::StructElement Part +include/vcl/pdfwriter.hxx:125 + enum vcl::PDFWriter::StructElement H2 +include/vcl/pdfwriter.hxx:125 + enum vcl::PDFWriter::StructElement H3 +include/vcl/pdfwriter.hxx:125 + enum vcl::PDFWriter::StructElement H4 +include/vcl/pdfwriter.hxx:125 + enum vcl::PDFWriter::StructElement H5 +include/vcl/pdfwriter.hxx:125 + enum vcl::PDFWriter::StructElement H6 +include/vcl/pdfwriter.hxx:130 + enum vcl::PDFWriter::StructElement Reference +include/vcl/pdfwriter.hxx:139 + enum vcl::PDFWriter::StructAttribute BlockAlign +include/vcl/pdfwriter.hxx:139 + enum vcl::PDFWriter::StructAttribute InlineAlign +include/vcl/pdfwriter.hxx:140 + enum vcl::PDFWriter::StructAttribute LineHeight +include/vcl/pdfwriter.hxx:140 + enum vcl::PDFWriter::StructAttribute ListNumbering +include/vcl/pdfwriter.hxx:162 + enum vcl::PDFWriter::StructAttributeValue After +include/vcl/pdfwriter.hxx:162 + enum vcl::PDFWriter::StructAttributeValue Before +include/vcl/pdfwriter.hxx:162 + enum vcl::PDFWriter::StructAttributeValue Start +include/vcl/pdfwriter.hxx:168 + enum vcl::PDFWriter::StructAttributeValue Auto +include/vcl/pdfwriter.hxx:170 + enum vcl::PDFWriter::StructAttributeValue Middle +include/vcl/pdfwriter.hxx:172 + enum vcl::PDFWriter::StructAttributeValue Normal +include/vcl/pdfwriter.hxx:176 + enum vcl::PDFWriter::StructAttributeValue Circle +include/vcl/pdfwriter.hxx:176 + enum vcl::PDFWriter::StructAttributeValue Decimal +include/vcl/pdfwriter.hxx:176 + enum vcl::PDFWriter::StructAttributeValue Disc +include/vcl/pdfwriter.hxx:176 + enum vcl::PDFWriter::StructAttributeValue LowerAlpha +include/vcl/pdfwriter.hxx:176 + enum vcl::PDFWriter::StructAttributeValue LowerRoman +include/vcl/pdfwriter.hxx:176 + enum vcl::PDFWriter::StructAttributeValue Square +include/vcl/pdfwriter.hxx:176 + enum vcl::PDFWriter::StructAttributeValue UpperAlpha +include/vcl/pdfwriter.hxx:176 + enum vcl::PDFWriter::StructAttributeValue UpperRoman +include/vcl/prntypes.hxx:37 + enum PrintQueueFlags Ready +include/vcl/prntypes.hxx:38 + enum PrintQueueFlags Paused +include/vcl/prntypes.hxx:39 + enum PrintQueueFlags PendingDeletion +include/vcl/prntypes.hxx:40 + enum PrintQueueFlags Busy +include/vcl/prntypes.hxx:41 + enum PrintQueueFlags Initializing +include/vcl/prntypes.hxx:42 + enum PrintQueueFlags Waiting +include/vcl/prntypes.hxx:43 + enum PrintQueueFlags WarmingUp +include/vcl/prntypes.hxx:44 + enum PrintQueueFlags Processing +include/vcl/prntypes.hxx:45 + enum PrintQueueFlags Printing +include/vcl/prntypes.hxx:46 + enum PrintQueueFlags Offline +include/vcl/prntypes.hxx:47 + enum PrintQueueFlags Error +include/vcl/prntypes.hxx:48 + enum PrintQueueFlags StatusUnknown +include/vcl/prntypes.hxx:49 + enum PrintQueueFlags PaperJam +include/vcl/prntypes.hxx:50 + enum PrintQueueFlags PaperOut +include/vcl/prntypes.hxx:51 + enum PrintQueueFlags ManualFeed +include/vcl/prntypes.hxx:52 + enum PrintQueueFlags PaperProblem +include/vcl/prntypes.hxx:53 + enum PrintQueueFlags IOActive +include/vcl/prntypes.hxx:54 + enum PrintQueueFlags OutputBinFull +include/vcl/prntypes.hxx:55 + enum PrintQueueFlags TonerLow +include/vcl/prntypes.hxx:56 + enum PrintQueueFlags NoToner +include/vcl/prntypes.hxx:57 + enum PrintQueueFlags PagePunt +include/vcl/prntypes.hxx:58 + enum PrintQueueFlags UserIntervention +include/vcl/prntypes.hxx:59 + enum PrintQueueFlags OutOfMemory +include/vcl/prntypes.hxx:60 + enum PrintQueueFlags DoorOpen +include/vcl/prntypes.hxx:61 + enum PrintQueueFlags PowerSave +include/vcl/ptrstyle.hxx:56 + enum PointerStyle Pen +include/vcl/rendercontext/DrawImageFlags.hxx:29 + enum DrawImageFlags Highlight +include/vcl/rendercontext/DrawImageFlags.hxx:30 + enum DrawImageFlags Deactive +include/vcl/rendercontext/DrawTextFlags.hxx:41 + enum DrawTextFlags NewsEllipsis +include/vcl/Scanline.hxx:44 + enum ScanlineFormat N32BitTcMask +include/vcl/vclenum.hxx:39 + enum MenuItemBits POPUPSELECT +include/vcl/vclenum.hxx:112 + enum WindowBorderStyle NWF +include/vcl/vclenum.hxx:149 + enum ExtTimeFieldFormat Long24H +include/vcl/vclenum.hxx:149 + enum ExtTimeFieldFormat Short24H +include/vcl/vclenum.hxx:150 + enum ExtTimeFieldFormat Long12H +include/vcl/vclenum.hxx:150 + enum ExtTimeFieldFormat Short12H +include/vcl/vclenum.hxx:151 + enum ExtTimeFieldFormat ShortDuration +include/vcl/vclevent.hxx:120 + enum VclEventId TabpageRemovedAll +include/vcl/wall.hxx:38 + enum WallpaperStyle Center +include/vcl/wall.hxx:40 + enum WallpaperStyle TopLeft +include/vcl/wall.hxx:41 + enum WallpaperStyle Top +include/vcl/wall.hxx:43 + enum WallpaperStyle Left +include/vcl/wall.hxx:44 + enum WallpaperStyle Right +include/vcl/wall.hxx:45 + enum WallpaperStyle BottomLeft +include/vcl/wall.hxx:46 + enum WallpaperStyle Bottom +include/xmloff/families.hxx:62 + enum XmlStyleFamily TEXT_ENDNOTECONFIG +include/xmloff/xmlimp.hxx:120 + enum SvXMLImportFlags EMBEDDED +linguistic/source/convdicxml.hxx:67 + enum ConvDicXMLToken TEXT_CONVERSION_DICTIONARY +linguistic/source/convdicxml.hxx:68 + enum ConvDicXMLToken RIGHT_TEXT +linguistic/source/convdicxml.hxx:69 + enum ConvDicXMLToken ENTRY +o3tl/qa/test-enumarray.cxx:30 + enum MyEnum ONE +o3tl/qa/test-enumarray.cxx:30 + enum MyEnum TWO +o3tl/qa/test-typed_flags.cxx:20 + enum (anonymous namespace)::ConfigurationChangedHint TWO +reportdesign/inc/conditionalexpression.hxx:78 + enum rptui::ComparisonOperation eNotBetween +reportdesign/inc/conditionalexpression.hxx:79 + enum rptui::ComparisonOperation eEqualTo +reportdesign/inc/conditionalexpression.hxx:80 + enum rptui::ComparisonOperation eNotEqualTo +reportdesign/inc/conditionalexpression.hxx:81 + enum rptui::ComparisonOperation eGreaterThan +reportdesign/inc/conditionalexpression.hxx:82 + enum rptui::ComparisonOperation eLessThan +reportdesign/inc/conditionalexpression.hxx:83 + enum rptui::ComparisonOperation eGreaterOrEqual +reportdesign/inc/conditionalexpression.hxx:84 + enum rptui::ComparisonOperation eLessOrEqual +sal/qa/osl/file/osl_File.cxx:285 + enum (anonymous namespace)::oslCheckMode Exist +sc/inc/dociter.hxx:258 + enum ScQueryCellIterator::StopOnMismatchBits nStopOnMismatchExecuted +sc/inc/dociter.hxx:266 + enum ScQueryCellIterator::TestEqualConditionBits nTestEqualConditionFulfilled +sc/inc/token.hxx:215 + enum ScTableRefToken::Item HEADERS_DATA +sc/inc/token.hxx:216 + enum ScTableRefToken::Item DATA_TOTALS +sc/inc/types.hxx:37 + enum ScMatValType NonvalueMask +sc/inc/types.hxx:60 + enum ScFormulaVectorState FormulaVectorUnknown +sc/qa/unit/ucalc_copypaste.cxx:261 + enum TestCopyPaste::CalcMode RecalcAtEnd +sc/source/ui/inc/viewdata.hxx:42 + enum ScSplitMode SC_SPLIT_MODE_MAX_ENUM +sc/source/ui/inc/viewdata.hxx:44 + enum ScSplitPos SC_SPLIT_POS_MAX_ENUM +sc/source/ui/StatisticsDialogs/RegressionDialog.cxx:102 + enum (anonymous namespace)::ScRegType LOGARITHMIC +sc/source/ui/StatisticsDialogs/RegressionDialog.cxx:103 + enum (anonymous namespace)::ScRegType POWER +sc/source/ui/unoobj/condformatuno.cxx:274 + enum (anonymous namespace)::DateProperties Date_StyleName +sc/source/ui/unoobj/condformatuno.cxx:275 + enum (anonymous namespace)::DateProperties DateType +scaddins/source/datefunc/datefunc.hxx:40 + enum ScaCategory Finance +scaddins/source/datefunc/datefunc.hxx:41 + enum ScaCategory Inf +scaddins/source/datefunc/datefunc.hxx:42 + enum ScaCategory Math +scaddins/source/datefunc/datefunc.hxx:43 + enum ScaCategory Tech +scaddins/source/pricing/pricing.hxx:48 + enum sca::pricing::ScaCategory DateTime +scaddins/source/pricing/pricing.hxx:49 + enum sca::pricing::ScaCategory Text +scaddins/source/pricing/pricing.hxx:51 + enum sca::pricing::ScaCategory Inf +scaddins/source/pricing/pricing.hxx:52 + enum sca::pricing::ScaCategory Math +scaddins/source/pricing/pricing.hxx:53 + enum sca::pricing::ScaCategory Tech +sd/source/ui/slidesorter/cache/SlsRequestPriorityClass.hxx:39 + enum sd::slidesorter::cache::RequestPriorityClass MAX_CLASS +slideshow/source/engine/shapes/viewshape.hxx:276 + enum slideshow::internal::ViewShape::(anonymous at /home/noel/libo2/slideshow/source/engine/shapes/viewshape.hxx:276:13) MAX_RENDER_CACHE_ENTRIES +slideshow/source/engine/slideview.cxx:242 + enum slideshow::internal::(anonymous namespace)::LayerSpriteContainer::(anonymous at /home/noel/libo2/slideshow/source/engine/slideview.cxx:242:5) SPRITE_ULLAGE +slideshow/source/engine/slideview.cxx:722 + enum slideshow::internal::(anonymous namespace)::SlideView::(anonymous at /home/noel/libo2/slideshow/source/engine/slideview.cxx:722:5) LAYER_ULLAGE +slideshow/source/inc/box2dtools.hxx:46 + enum box2d::utils::box2DNonsimulatedShapeUpdateType BOX2D_UPDATE_SIZE +soltools/cpp/cpp.h:42 + int WS +starmath/inc/mathml/def.hxx:55 + enum SmMlElementType NMlStructural +starmath/inc/mathml/def.hxx:56 + enum SmMlElementType NMlSmNode +starmath/inc/mathml/def.hxx:58 + enum SmMlElementType MlMath +starmath/inc/mathml/def.hxx:59 + enum SmMlElementType MlMi +starmath/inc/mathml/def.hxx:60 + enum SmMlElementType MlMerror +starmath/inc/mathml/def.hxx:61 + enum SmMlElementType MlMn +starmath/inc/mathml/def.hxx:62 + enum SmMlElementType MlMo +starmath/inc/mathml/def.hxx:63 + enum SmMlElementType MlMrow +starmath/inc/mathml/def.hxx:64 + enum SmMlElementType MlMtext +starmath/inc/mathml/def.hxx:65 + enum SmMlElementType MlMstyle +svgio/inc/svgstyleattributes.hxx:60 + enum svgio::svgreader::FontSize notset +svl/source/numbers/zformat.cxx:305 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_DBNUM2 +svl/source/numbers/zformat.cxx:306 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_DBNUM3 +svl/source/numbers/zformat.cxx:307 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_DBNUM4 +svl/source/numbers/zformat.cxx:308 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_DBNUM5 +svl/source/numbers/zformat.cxx:309 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_DBNUM6 +svl/source/numbers/zformat.cxx:310 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_DBNUM7 +svl/source/numbers/zformat.cxx:311 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_DBNUM8 +svl/source/numbers/zformat.cxx:312 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_DBNUM9 +svl/source/numbers/zformat.cxx:315 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM1 +svl/source/numbers/zformat.cxx:316 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM2 +svl/source/numbers/zformat.cxx:317 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM3 +svl/source/numbers/zformat.cxx:318 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM4 +svl/source/numbers/zformat.cxx:319 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM5 +svl/source/numbers/zformat.cxx:320 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM6 +svl/source/numbers/zformat.cxx:321 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM7 +svl/source/numbers/zformat.cxx:322 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM8 +svl/source/numbers/zformat.cxx:323 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM9 +svl/source/numbers/zformat.cxx:324 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM10 +svl/source/numbers/zformat.cxx:325 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM11 +svl/source/numbers/zformat.cxx:326 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM12 +svl/source/numbers/zformat.cxx:327 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM13 +svl/source/numbers/zformat.cxx:328 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM14 +svl/source/numbers/zformat.cxx:329 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM15 +svl/source/numbers/zformat.cxx:330 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM16 +svl/source/numbers/zformat.cxx:331 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM17 +svl/source/numbers/zformat.cxx:332 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM18 +svl/source/numbers/zformat.cxx:333 + enum (anonymous namespace)::BracketFormatSymbolType BRACKET_SYMBOLTYPE_NATNUM19 +svtools/inc/table/tablemodel.hxx:49 + enum ColumnAttributeGroup ALL +svx/source/inc/docrecovery.hxx:77 + enum EDocStates TryLoadBackup +svx/source/inc/docrecovery.hxx:78 + enum EDocStates TryLoadOriginal +svx/source/inc/docrecovery.hxx:83 + enum EDocStates Damaged +svx/source/inc/docrecovery.hxx:85 + enum EDocStates Incomplete +svx/source/inc/docrecovery.hxx:87 + enum EDocStates Succeeded +sw/inc/accmap.hxx:75 + enum AccessibleStates OPAQUE +sw/inc/crstate.hxx:32 + enum SwFillMode Space +sw/inc/crstate.hxx:33 + enum SwFillMode Margin +sw/inc/crstate.hxx:34 + enum SwFillMode Indent +sw/inc/dbmgr.hxx:486 + enum sw::DBConnURIType MSJET +sw/inc/dbmgr.hxx:487 + enum sw::DBConnURIType MSACE +sw/inc/docary.hxx:73 + enum SwVectorModifyBase::DestructorPolicy FreeElements +sw/inc/docary.hxx:73 + enum SwVectorModifyBase::DestructorPolicy FreeElements +sw/inc/docary.hxx:73 + enum SwVectorModifyBase::DestructorPolicy FreeElements +sw/inc/docufld.hxx:117 + enum SwExtUserSubType EU_FATHERSNAME +sw/inc/docufld.hxx:118 + enum SwExtUserSubType EU_APARTMENT +sw/inc/ndtyp.hxx:42 + enum SwNodeType ContentMask +sw/inc/reffld.hxx:40 + enum REFERENCESUBTYPE REF_OUTLINE +sw/inc/undobj.hxx:136 + enum DelContentType Fly +sw/inc/undobj.hxx:137 + enum DelContentType Bkm +sw/source/core/inc/dbg_lay.hxx:28 + enum PROT Init +sw/source/core/inc/rootfrm.hxx:50 + enum sw::FieldmarkMode ShowCommand +sw/source/core/inc/rootfrm.hxx:50 + enum sw::FieldmarkMode ShowResult +sw/source/core/inc/SwXMLBlockImport.hxx:78 + enum SwXMLTextBlockToken OFFICE_BODY +sw/source/core/inc/SwXMLBlockImport.hxx:79 + enum SwXMLTextBlockToken OFFICE_TEXT +sw/source/core/inc/SwXMLBlockImport.hxx:80 + enum SwXMLTextBlockToken OFFICE_DOCUMENT +sw/source/core/inc/SwXMLBlockImport.hxx:81 + enum SwXMLTextBlockToken OFFICE_DOCUMENT_CONTENT +sw/source/core/inc/SwXMLBlockImport.hxx:82 + enum SwXMLTextBlockToken TEXT_P +sw/source/core/inc/SwXMLBlockImport.hxx:103 + enum SwXMLBlockListToken BLOCK +sw/source/core/inc/SwXMLBlockImport.hxx:104 + enum SwXMLBlockListToken BLOCK_LIST +sw/source/core/text/pormulti.hxx:47 + enum RubyPosition RIGHT +sw/source/filter/ww8/ww8scan.hxx:604 + enum WW8PLCFx_Fc_FKP::Limits eMaxCache +sw/source/uibase/inc/envimg.hxx:31 + enum SwEnvAlign ENV_HOR_CNTR +sw/source/uibase/inc/envimg.hxx:32 + enum SwEnvAlign ENV_HOR_RGHT +sw/source/uibase/inc/envimg.hxx:33 + enum SwEnvAlign ENV_VER_LEFT +sw/source/uibase/inc/envimg.hxx:34 + enum SwEnvAlign ENV_VER_CNTR +tools/source/generic/poly.cxx:1122 + enum (anonymous at /home/noel/libo2/tools/source/generic/poly.cxx:1122:5) maxRecursionDepth +ucbhelper/source/client/proxydecider.cxx:126 + enum ucbhelper::proxydecider_impl::InternetProxyDecider_Impl::ProxyType Automatic +vcl/inc/driverblocklist.hxx:65 + enum DriverBlocklist::OperatingSystem DRIVER_OS_WINDOWS_LAST +vcl/inc/driverblocklist.hxx:73 + enum DriverBlocklist::OperatingSystem DRIVER_OS_OSX_LAST +vcl/inc/fontsubset.hxx:42 + enum FontType ANY_TYPE1 +vcl/inc/salptype.hxx:44 + enum SalPrinterError Abort +vcl/source/app/svapp.cxx:1145 + enum (anonymous at /home/noel/libo2/vcl/source/app/svapp.cxx:1145:1) hwEnv +vcl/source/app/svapp.cxx:1145 + enum (anonymous at /home/noel/libo2/vcl/source/app/svapp.cxx:1145:1) hwUI +vcl/source/filter/jpeg/Exif.hxx:40 + enum Tag ORIENTATION +vcl/source/gdi/CommonSalLayout.cxx:134 + enum (anonymous namespace)::VerticalOrientation Upright +vcl/source/gdi/CommonSalLayout.cxx:137 + enum (anonymous namespace)::VerticalOrientation TransformedRotated +vcl/source/gdi/pdfwriter_impl.hxx:84 + enum vcl::pdf::GraphicsStateUpdateFlags MapMode +vcl/source/gdi/pdfwriter_impl.hxx:89 + enum vcl::pdf::GraphicsStateUpdateFlags TransparentPercent +vcl/source/window/printdlg.cxx:58 + enum (anonymous at /home/noel/libo2/vcl/source/window/printdlg.cxx:55:1) ORIENTATION_PORTRAIT +writerfilter/source/dmapper/PropertyIds.hxx:229 + enum writerfilter::dmapper::PropertyIds PROP_PARA_HYPHENATION_NO_CAPS +writerfilter/source/ooxml/OOXMLFactory.hxx:32 + enum writerfilter::ooxml::ResourceType List +writerfilter/source/ooxml/OOXMLFactory.hxx:33 + enum writerfilter::ooxml::ResourceType Integer +writerfilter/source/ooxml/OOXMLFactory.hxx:35 + enum writerfilter::ooxml::ResourceType Hex +writerfilter/source/ooxml/OOXMLFactory.hxx:36 + enum writerfilter::ooxml::ResourceType HexColor +writerfilter/source/ooxml/OOXMLFactory.hxx:37 + enum writerfilter::ooxml::ResourceType String +writerfilter/source/ooxml/OOXMLFactory.hxx:39 + enum writerfilter::ooxml::ResourceType Boolean +writerfilter/source/ooxml/OOXMLFactory.hxx:48 + enum writerfilter::ooxml::ResourceType TwipsMeasure_asSigned +writerfilter/source/ooxml/OOXMLFactory.hxx:49 + enum writerfilter::ooxml::ResourceType TwipsMeasure_asZero +writerfilter/source/ooxml/OOXMLFactory.hxx:50 + enum writerfilter::ooxml::ResourceType HpsMeasure +writerfilter/source/ooxml/OOXMLFactory.hxx:51 + enum writerfilter::ooxml::ResourceType MeasurementOrPercent +xmlsecurity/source/helper/ooxmlsecparser.cxx:964 + enum OOXMLSecParser::DsSignaturePropertyContext::SignatureProperty Info diff --git a/compilerplugins/clang/unusedenumconstants.untouched.results b/compilerplugins/clang/unusedenumconstants.untouched.results new file mode 100644 index 000000000..58b8091b9 --- /dev/null +++ b/compilerplugins/clang/unusedenumconstants.untouched.results @@ -0,0 +1,388 @@ +canvas/inc/rendering/icolorbuffer.hxx:37 + enum canvas::IColorBuffer::Format A8R8G8B8 +canvas/inc/rendering/icolorbuffer.hxx:40 + enum canvas::IColorBuffer::Format X8R8G8B8 +canvas/inc/rendering/irendermodule.hxx:54 + enum canvas::IRenderModule::PrimitiveType Unknown +cui/source/options/optfltr.cxx:35 + enum MSFltrPg2_CheckBoxEntries InvalidCBEntry +drawinglayer/source/tools/emfphelperdata.cxx:65 + enum emfplushelper::(anonymous at /home/noel/libo2/drawinglayer/source/tools/emfphelperdata.cxx:59:5) WrapModeClamp +drawinglayer/source/tools/emfpimage.hxx:30 + emfplushelper::ImageDataType ImageDataTypeUnknown +framework/inc/xml/imagesdocumenthandler.hxx:42 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ELEMENT_EXTERNALIMAGES +framework/inc/xml/imagesdocumenthandler.hxx:43 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ELEMENT_EXTERNALENTRY +framework/inc/xml/imagesdocumenthandler.hxx:44 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ATTRIBUTE_HREF +framework/inc/xml/imagesdocumenthandler.hxx:45 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ATTRIBUTE_MASKCOLOR +framework/inc/xml/imagesdocumenthandler.hxx:47 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ATTRIBUTE_BITMAPINDEX +framework/inc/xml/imagesdocumenthandler.hxx:48 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ATTRIBUTE_MASKURL +framework/inc/xml/imagesdocumenthandler.hxx:49 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ATTRIBUTE_MASKMODE +framework/inc/xml/imagesdocumenthandler.hxx:50 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ATTRIBUTE_HIGHCONTRASTURL +framework/inc/xml/imagesdocumenthandler.hxx:51 + enum framework::OReadImagesDocumentHandler::Image_XML_Entry IMG_ATTRIBUTE_HIGHCONTRASTMASKURL +framework/source/fwe/classes/actiontriggerseparatorpropertyset.cxx:44 + enum (anonymous namespace)::EPROPERTIES PROPERTYCOUNT +include/connectivity/dbtools.hxx:825 + enum connectivity::dbase::DBFType dBaseIVMemo +include/desktop/exithelper.h:26 + enum EExitCodes EXITHELPER_NO_ERROR +include/desktop/exithelper.h:26 + int EXITHELPER_NO_ERROR +include/desktop/exithelper.h:28 + int EXITHELPER_FATAL_ERROR +include/editeng/borderline.hxx:131 + enum SvxBorderLineStyle BORDER_LINE_STYLE_MAX +include/filter/msfilter/ww8fields.hxx:28 + enum ww::eField ePOSSIBLEBOOKMARK +include/filter/msfilter/ww8fields.hxx:112 + enum ww::eField eUNKNOWN2 +include/i18nutil/transliteration.hxx:45 + enum TransliterationFlags NumToTextLower_zh_CN +include/i18nutil/transliteration.hxx:47 + enum TransliterationFlags NumToTextUpper_zh_CN +include/i18nutil/transliteration.hxx:49 + enum TransliterationFlags NumToTextLower_zh_TW +include/i18nutil/transliteration.hxx:51 + enum TransliterationFlags NumToTextUpper_zh_TW +include/i18nutil/transliteration.hxx:53 + enum TransliterationFlags NumToTextFormalHangul_ko +include/i18nutil/transliteration.hxx:55 + enum TransliterationFlags NumToTextFormalLower_ko +include/i18nutil/transliteration.hxx:57 + enum TransliterationFlags NumToTextFormalUpper_ko +include/i18nutil/transliteration.hxx:117 + enum TransliterationFlags smallToLarge_ja_JP +include/i18nutil/transliteration.hxx:119 + enum TransliterationFlags largeToSmall_ja_JP +include/LibreOfficeKit/LibreOfficeKitEnums.h:56 + LibreOfficeKitSelectionType LOK_SELTYPE_LARGE_TEXT +include/LibreOfficeKit/LibreOfficeKitEnums.h:792 + LibreOfficeKitExtTextInputType LOK_EXT_TEXTINPUT_POS +include/oox/ole/axfontdata.hxx:39 + enum AxFontFlags Disabled +include/oox/ole/axfontdata.hxx:40 + enum AxFontFlags AutoColor +include/unotools/eventcfg.hxx:29 + enum GlobalEventId STARTAPP +include/unotools/eventcfg.hxx:30 + enum GlobalEventId CLOSEAPP +include/unotools/extendedsecurityoptions.hxx:28 + enum SvtExtendedSecurityOptions::OpenHyperlinkMode OPEN_WITHSECURITYCHECK +include/unotools/sharedunocomponent.hxx:149 + enum utl::SharedUNOComponent::AssignmentMode NoTakeOwnership +include/unotools/sharedunocomponent.hxx:149 + enum utl::SharedUNOComponent::AssignmentMode NoTakeOwnership +include/unotools/sharedunocomponent.hxx:149 + enum utl::SharedUNOComponent::AssignmentMode NoTakeOwnership +include/unotools/sharedunocomponent.hxx:149 + enum utl::SharedUNOComponent::AssignmentMode NoTakeOwnership +include/unotools/sharedunocomponent.hxx:149 + enum utl::SharedUNOComponent::AssignmentMode NoTakeOwnership +include/unotools/sharedunocomponent.hxx:149 + enum utl::SharedUNOComponent::AssignmentMode NoTakeOwnership +include/unotools/sharedunocomponent.hxx:149 + enum utl::SharedUNOComponent::AssignmentMode NoTakeOwnership +include/vcl/pdf/PDFAnnotationMarker.hxx:59 + enum vcl::pdf::PDFTextMarkerType Underline +include/vcl/pdf/PDFAnnotationMarker.hxx:60 + enum vcl::pdf::PDFTextMarkerType Squiggly +include/vcl/pdf/PDFAnnotationMarker.hxx:61 + enum vcl::pdf::PDFTextMarkerType StrikeOut +include/vcl/pdf/PDFAnnotationSubType.hxx:19 + enum vcl::pdf::PDFAnnotationSubType Link +include/vcl/pdf/PDFAnnotationSubType.hxx:25 + enum vcl::pdf::PDFAnnotationSubType Polyline +include/vcl/pdf/PDFAnnotationSubType.hxx:27 + enum vcl::pdf::PDFAnnotationSubType Underline +include/vcl/pdf/PDFAnnotationSubType.hxx:28 + enum vcl::pdf::PDFAnnotationSubType Squiggly +include/vcl/pdf/PDFAnnotationSubType.hxx:29 + enum vcl::pdf::PDFAnnotationSubType Strikeout +include/vcl/pdf/PDFAnnotationSubType.hxx:31 + enum vcl::pdf::PDFAnnotationSubType Caret +include/vcl/pdf/PDFAnnotationSubType.hxx:34 + enum vcl::pdf::PDFAnnotationSubType FileAttachment +include/vcl/pdf/PDFAnnotationSubType.hxx:35 + enum vcl::pdf::PDFAnnotationSubType Sound +include/vcl/pdf/PDFAnnotationSubType.hxx:36 + enum vcl::pdf::PDFAnnotationSubType Movie +include/vcl/pdf/PDFAnnotationSubType.hxx:37 + enum vcl::pdf::PDFAnnotationSubType Widget +include/vcl/pdf/PDFAnnotationSubType.hxx:38 + enum vcl::pdf::PDFAnnotationSubType Screen +include/vcl/pdf/PDFAnnotationSubType.hxx:39 + enum vcl::pdf::PDFAnnotationSubType Printermark +include/vcl/pdf/PDFAnnotationSubType.hxx:40 + enum vcl::pdf::PDFAnnotationSubType Trapnet +include/vcl/pdf/PDFAnnotationSubType.hxx:41 + enum vcl::pdf::PDFAnnotationSubType Watermark +include/vcl/pdf/PDFAnnotationSubType.hxx:42 + enum vcl::pdf::PDFAnnotationSubType Threed +include/vcl/pdf/PDFAnnotationSubType.hxx:43 + enum vcl::pdf::PDFAnnotationSubType Richmedia +include/vcl/pdf/PDFAnnotationSubType.hxx:44 + enum vcl::pdf::PDFAnnotationSubType XFAWidget +include/vcl/toolkit/svtabbx.hxx:37 + enum SvTabJustify AdjustRight +include/vcl/toolkit/svtabbx.hxx:38 + enum SvTabJustify AdjustLeft +include/vcl/toolkit/treelistbox.hxx:150 + enum DragDropMode APP_COPY +include/vcl/toolkit/treelistbox.hxx:154 + enum DragDropMode ALL +include/vcl/vclenum.hxx:310 + enum WindowStateState Rollup +include/vcl/vclenum.hxx:313 + enum WindowStateState FullScreen +include/vcl/vclenum.hxx:408 + enum TrackingEventFlags Focus +libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx:70 + enum (anonymous at /home/noel/libo2/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx:68:1) PROP_0 +libreofficekit/source/gtk/lokdocview.cxx:295 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:293:1) PROP_0 +reportdesign/source/filter/xml/xmlEnums.hxx:42 + enum rptxml::XMLReportToken XML_TOK_REPORT_ELEMENT +sc/qa/unit/ucalc_copypaste.cxx:259 + enum TestCopyPaste::CalcMode NoCalc +sc/source/filter/excel/xiescher.cxx:473 + enum (anonymous at /home/noel/libo2/sc/source/filter/excel/xiescher.cxx:473:17) eCreateFromOffice +sc/source/filter/inc/decl.h:23 + enum WKTYP eWK4 +sc/source/ui/inc/anyrefdg.hxx:142 + enum ScRefHdlrControllerImpl::(anonymous at /home/noel/libo2/sc/source/ui/inc/anyrefdg.hxx:142:5) SLOTID +sc/source/ui/inc/anyrefdg.hxx:142 + enum ScRefHdlrControllerImpl::(anonymous at /home/noel/libo2/sc/source/ui/inc/anyrefdg.hxx:142:5) SLOTID +sc/source/ui/inc/anyrefdg.hxx:142 + enum ScRefHdlrControllerImpl::(anonymous at /home/noel/libo2/sc/source/ui/inc/anyrefdg.hxx:142:5) SLOTID +sc/source/ui/StatisticsDialogs/RegressionDialog.cxx:101 + enum (anonymous namespace)::ScRegType LINEAR +starmath/inc/mathml/def.hxx:29 + enum SmLengthUnit MlEx +starmath/inc/mathml/def.hxx:30 + enum SmLengthUnit MlPx +starmath/inc/mathml/def.hxx:31 + enum SmLengthUnit MlIn +starmath/inc/mathml/def.hxx:32 + enum SmLengthUnit MlCm +starmath/inc/mathml/def.hxx:33 + enum SmLengthUnit MlMM +starmath/inc/mathml/def.hxx:34 + enum SmLengthUnit MlPt +starmath/inc/mathml/def.hxx:35 + enum SmLengthUnit MlPc +starmath/inc/mathml/def.hxx:98 + enum SmMlAttributeValueEmpty MlEmpty +starmath/inc/mathml/def.hxx:104 + enum SmMlAttributeValueAccent MlTrue +starmath/inc/mathml/def.hxx:110 + enum SmMlAttributeValueDir MlRtl +starmath/inc/mathml/def.hxx:116 + enum SmMlAttributeValueDisplaystyle MlTrue +starmath/inc/mathml/def.hxx:122 + enum SmMlAttributeValueFence MlTrue +starmath/inc/mathml/def.hxx:128 + enum SmMlAttributeValueHref NMlValie +starmath/inc/mathml/def.hxx:133 + enum SmMlAttributeValueLspace NMlEmpty +starmath/inc/mathml/def.hxx:139 + enum SmMlAttributeValueMathbackground MlRgb +starmath/inc/mathml/def.hxx:145 + enum SmMlAttributeValueMathcolor MlRgb +starmath/inc/mathml/def.hxx:150 + enum SmMlAttributeValueMathsize NMlEmpty +starmath/inc/mathml/def.hxx:156 + enum SmMlAttributeValueMathvariant bold +starmath/inc/mathml/def.hxx:157 + enum SmMlAttributeValueMathvariant italic +starmath/inc/mathml/def.hxx:158 + enum SmMlAttributeValueMathvariant double_struck +starmath/inc/mathml/def.hxx:159 + enum SmMlAttributeValueMathvariant script +starmath/inc/mathml/def.hxx:160 + enum SmMlAttributeValueMathvariant fraktur +starmath/inc/mathml/def.hxx:161 + enum SmMlAttributeValueMathvariant sans_serif +starmath/inc/mathml/def.hxx:162 + enum SmMlAttributeValueMathvariant monospace +starmath/inc/mathml/def.hxx:163 + enum SmMlAttributeValueMathvariant bold_italic +starmath/inc/mathml/def.hxx:164 + enum SmMlAttributeValueMathvariant bold_fraktur +starmath/inc/mathml/def.hxx:165 + enum SmMlAttributeValueMathvariant bold_script +starmath/inc/mathml/def.hxx:166 + enum SmMlAttributeValueMathvariant bold_sans_serif +starmath/inc/mathml/def.hxx:167 + enum SmMlAttributeValueMathvariant sans_serif_italic +starmath/inc/mathml/def.hxx:168 + enum SmMlAttributeValueMathvariant sans_serif_bold_italic +starmath/inc/mathml/def.hxx:170 + enum SmMlAttributeValueMathvariant initial +starmath/inc/mathml/def.hxx:171 + enum SmMlAttributeValueMathvariant tailed +starmath/inc/mathml/def.hxx:172 + enum SmMlAttributeValueMathvariant looped +starmath/inc/mathml/def.hxx:173 + enum SmMlAttributeValueMathvariant stretched +starmath/inc/mathml/def.hxx:179 + enum SmMlAttributeValueMaxsize MlFinite +starmath/inc/mathml/def.hxx:185 + enum SmMlAttributeValueMinsize MlFinite +starmath/inc/mathml/def.hxx:195 + enum SmMlAttributeValueMovablelimits MlTrue +starmath/inc/mathml/def.hxx:200 + enum SmMlAttributeValueRspace NMlEmpty +starmath/inc/mathml/def.hxx:206 + enum SmMlAttributeValueSeparator MlTrue +starmath/inc/mathml/def.hxx:212 + enum SmMlAttributeValueStretchy MlTrue +starmath/inc/mathml/def.hxx:218 + enum SmMlAttributeValueSymmetric MlTrue +starmath/inc/mathml/mathmlMo.hxx:45 + enum moOpDP movablelimits +starmath/inc/mathml/mathmlMo.hxx:46 + enum moOpDP starmathCustom +starmath/inc/mathml/mathmlMo.hxx:47 + enum moOpDP starmathCustomMo +starmath/inc/mathml/mathmlMo.hxx:54 + enum moOpDF nonedf +svx/inc/sxmkitm.hxx:25 + enum SdrMeasureKind SDRMEASURE_RADIUS +svx/source/inc/datanavi.hxx:60 + enum svxform::DataGroupType DGTUnknown +sw/inc/docary.hxx:72 + enum SwVectorModifyBase::DestructorPolicy KeepElements +sw/inc/docary.hxx:72 + enum SwVectorModifyBase::DestructorPolicy KeepElements +sw/inc/docary.hxx:72 + enum SwVectorModifyBase::DestructorPolicy KeepElements +sw/inc/docary.hxx:72 + enum SwVectorModifyBase::DestructorPolicy KeepElements +sw/inc/docary.hxx:73 + enum SwVectorModifyBase::DestructorPolicy FreeElements +sw/inc/tblenum.hxx:34 + enum TableChgWidthHeightType InvalidPos +sw/source/filter/ww8/ww8scan.hxx:385 + enum ePLCFT SEP +sw/source/filter/ww8/ww8struc.hxx:950 + enum WW8_FSPA::FSPAOrient RelPgMargin +sw/source/filter/ww8/ww8struc.hxx:950 + enum WW8_FSPA::FSPAOrient RelText +sw/source/ui/fldui/fldref.cxx:735 + enum (anonymous namespace)::FMT_REF_IDX FMT_REF_PAGE_IDX +sw/source/ui/fldui/fldref.cxx:736 + enum (anonymous namespace)::FMT_REF_IDX FMT_REF_CHAPTER_IDX +sw/source/ui/fldui/fldref.cxx:737 + enum (anonymous namespace)::FMT_REF_IDX FMT_REF_TEXT_IDX +sw/source/ui/fldui/fldref.cxx:738 + enum (anonymous namespace)::FMT_REF_IDX FMT_REF_UPDOWN_IDX +sw/source/ui/fldui/fldref.cxx:740 + enum (anonymous namespace)::FMT_REF_IDX FMT_REF_ONLYNUMBER_IDX +sw/source/ui/fldui/fldref.cxx:741 + enum (anonymous namespace)::FMT_REF_IDX FMT_REF_ONLYCAPTION_IDX +sw/source/uibase/utlui/content.cxx:1015 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_OUTLINE_LEVEL +sw/source/uibase/utlui/content.cxx:1016 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_DRAGMODE +sw/source/uibase/utlui/content.cxx:1018 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_LINK_REGION +sw/source/uibase/utlui/content.cxx:1019 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_COPY_REGION +sw/source/uibase/utlui/content.cxx:1020 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_DISPLAY +sw/source/uibase/utlui/content.cxx:1024 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_INACTIVE +sw/source/uibase/utlui/content.cxx:1025 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_EDIT_ENTRY +sw/source/uibase/utlui/content.cxx:1026 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_DELETE_ENTRY +sw/source/uibase/utlui/content.cxx:1027 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_SEND_OUTLINE_TO_CLIPBOARD_ENTRY +sw/source/uibase/utlui/content.cxx:1029 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_OUTLINE_TRACKING_DEFAULT +sw/source/uibase/utlui/content.cxx:1030 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_OUTLINE_TRACKING_FOCUS +sw/source/uibase/utlui/content.cxx:1031 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_OUTLINE_TRACKING_OFF +sw/source/uibase/utlui/glbltree.cxx:90 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_UPDATE +sw/source/uibase/utlui/glbltree.cxx:91 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_EDIT_CONTENT +sw/source/uibase/utlui/glbltree.cxx:92 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_EDIT_INSERT +sw/source/uibase/utlui/glbltree.cxx:93 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_INDEX +sw/source/uibase/utlui/glbltree.cxx:94 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_FILE +sw/source/uibase/utlui/glbltree.cxx:95 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_NEW_FILE +sw/source/uibase/utlui/glbltree.cxx:97 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_DELETE +sw/source/uibase/utlui/glbltree.cxx:98 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_UPDATE_SEL +sw/source/uibase/utlui/glbltree.cxx:99 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_UPDATE_INDEX +sw/source/uibase/utlui/glbltree.cxx:100 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_UPDATE_LINK +sw/source/uibase/utlui/glbltree.cxx:101 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_UPDATE_ALL +sw/source/uibase/utlui/glbltree.cxx:103 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_EDIT_LINK +ucb/source/ucp/webdav-neon/DAVTypes.hxx:191 + enum webdav_ucp::Depth DAVINFINITY +ucbhelper/source/client/proxydecider.cxx:126 + enum ucbhelper::proxydecider_impl::InternetProxyDecider_Impl::ProxyType Manual +vcl/inc/salptype.hxx:43 + enum SalPrinterError General +vcl/inc/unx/saldisp.hxx:62 + srv_vendor_t vendor_none +vcl/source/app/svapp.cxx:1145 + enum (anonymous at /home/noel/libo2/vcl/source/app/svapp.cxx:1145:1) hwAll +vcl/source/filter/ipcd/ipcd.cxx:41 + enum (anonymous namespace)::PCDResolution PCDRES_4BASE +vcl/source/filter/ipcd/ipcd.cxx:42 + enum (anonymous namespace)::PCDResolution PCDRES_16BASE +vcl/source/gdi/CommonSalLayout.cxx:135 + enum (anonymous namespace)::VerticalOrientation Rotated +vcl/unx/gtk3/gtkinst.cxx:6949 + enum (anonymous at /home/noel/libo2/vcl/unx/gtk3/gtkinst.cxx:6947:1) PROP_0 +vcl/unx/gtk3/gtkinst.cxx:6954 + enum (anonymous at /home/noel/libo2/vcl/unx/gtk3/gtkinst.cxx:6947:1) PROP_SHADOW_TYPE +writerfilter/source/ooxml/OOXMLFactory.hxx:29 + enum writerfilter::ooxml::ResourceType NoResource +writerfilter/source/ooxml/OOXMLFactory.hxx:30 + enum writerfilter::ooxml::ResourceType Table +writerfilter/source/ooxml/OOXMLFactory.hxx:31 + enum writerfilter::ooxml::ResourceType Stream +writerfilter/source/ooxml/OOXMLFactory.hxx:34 + enum writerfilter::ooxml::ResourceType Properties +writerfilter/source/ooxml/OOXMLFactory.hxx:38 + enum writerfilter::ooxml::ResourceType Shape +writerfilter/source/ooxml/OOXMLFactory.hxx:40 + enum writerfilter::ooxml::ResourceType Value +writerfilter/source/ooxml/OOXMLFactory.hxx:41 + enum writerfilter::ooxml::ResourceType XNote +writerfilter/source/ooxml/OOXMLFactory.hxx:42 + enum writerfilter::ooxml::ResourceType TextTableCell +writerfilter/source/ooxml/OOXMLFactory.hxx:43 + enum writerfilter::ooxml::ResourceType TextTableRow +writerfilter/source/ooxml/OOXMLFactory.hxx:44 + enum writerfilter::ooxml::ResourceType TextTable +writerfilter/source/ooxml/OOXMLFactory.hxx:45 + enum writerfilter::ooxml::ResourceType PropertyTable +writerfilter/source/ooxml/OOXMLFactory.hxx:46 + enum writerfilter::ooxml::ResourceType Math +writerfilter/source/ooxml/OOXMLFactory.hxx:47 + enum writerfilter::ooxml::ResourceType Any +writerfilter/source/ooxml/OOXMLFactory.hxx:52 + enum writerfilter::ooxml::ResourceType CommentEx +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:200 + enum writerfilter::ooxml::OOXMLFastContextHandler::eMathParaJc INLINE diff --git a/compilerplugins/clang/unusedenumconstants.writeonly.results b/compilerplugins/clang/unusedenumconstants.writeonly.results new file mode 100644 index 000000000..07c5ebb31 --- /dev/null +++ b/compilerplugins/clang/unusedenumconstants.writeonly.results @@ -0,0 +1,6230 @@ +basctl/source/basicide/baside3.cxx:900 + enum NameClashMode NO_CLASH +basctl/source/basicide/doceventnotifier.cxx:58 + enum basctl::(anonymous namespace)::ListenerAction RemoveListener +basctl/source/basicide/macrodlg.hxx:32 + enum basctl::MacroExitCode Macro_Close +basctl/source/basicide/macrodlg.hxx:34 + enum basctl::MacroExitCode Macro_New +basctl/source/basicide/macrodlg.hxx:35 + enum basctl::MacroExitCode Macro_Edit +basctl/source/inc/bastype2.hxx:40 + enum BrowseMode All +basctl/source/inc/dlged.hxx:100 + enum basctl::DlgEditor::Mode SELECT +basctl/source/inc/layout.hxx:82 + enum basctl::Layout::SplittedSide::Side Bottom +basctl/source/inc/sbxitem.hxx:30 + enum basctl::ItemType TYPE_SHELL +basctl/source/inc/sbxitem.hxx:31 + enum basctl::ItemType TYPE_LIBRARY +basctl/source/inc/scriptdocument.hxx:46 + enum basctl::LibraryLocation LIBRARY_LOCATION_UNKNOWN +basegfx/source/range/b2drangeclipper.cxx:150 + enum basegfx::(anonymous namespace)::SweepLineEvent::EdgeType FINISHING_EDGE +basegfx/source/range/b2drangeclipper.cxx:156 + enum basegfx::(anonymous namespace)::SweepLineEvent::EdgeDirection PROCEED_UP +basegfx/source/range/b2drangeclipper.cxx:791 + enum basegfx::(anonymous namespace)::(anonymous at /home/noel/libo2/basegfx/source/range/b2drangeclipper.cxx:791:9) NoErase +basegfx/source/range/b2drangeclipper.cxx:791 + enum basegfx::(anonymous namespace)::(anonymous at /home/noel/libo2/basegfx/source/range/b2drangeclipper.cxx:791:9) PerformErase +basic/source/inc/expr.hxx:61 + enum SbiExprMode EXPRMODE_STANDARD +basic/source/inc/expr.hxx:78 + enum SbiNodeType SbxDUMMY +basic/source/inc/expr.hxx:85 + enum RecursiveMode PREVENT_CALL +basic/source/inc/image.hxx:34 + enum SbiImageFlags EXPLICIT +basic/source/inc/image.hxx:35 + enum SbiImageFlags COMPARETEXT +basic/source/inc/image.hxx:36 + enum SbiImageFlags INITCODE +basic/source/inc/image.hxx:37 + enum SbiImageFlags CLASSMODULE +basic/source/inc/iosys.hxx:39 + enum SbiStreamFlags Output +basic/source/inc/namecont.hxx:224 + enum basic::SfxLibraryContainer::InitMode LIBRARY_INIT_FILE +basic/source/inc/namecont.hxx:226 + enum basic::SfxLibraryContainer::InitMode OLD_BASIC_STORAGE +basic/source/runtime/methods.cxx:4371 + enum BasicResponse Ok +basic/source/runtime/methods.cxx:4372 + enum BasicResponse Cancel +basic/source/runtime/methods.cxx:4373 + enum BasicResponse Abort +basic/source/runtime/methods.cxx:4374 + enum BasicResponse Retry +basic/source/runtime/methods.cxx:4375 + enum BasicResponse Ignore +basic/source/runtime/methods.cxx:4376 + enum BasicResponse Yes +basic/source/runtime/methods.cxx:4377 + enum BasicResponse No +binaryurp/source/cache.hxx:35 + enum binaryurp::cache::(anonymous at /home/noel/libo2/binaryurp/qa/../source/cache.hxx:35:1) size +canvas/inc/rendering/irendermodule.hxx:55 + enum canvas::IRenderModule::PrimitiveType Triangle +canvas/inc/rendering/irendermodule.hxx:56 + enum canvas::IRenderModule::PrimitiveType Quad +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:67 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_MAX +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:68 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_MIN +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:69 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_STEPMAIN +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:70 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_STEPHELP +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:71 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_STEPHELP_COUNT +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:72 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_AUTO_MAX +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:73 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_AUTO_MIN +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:74 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_AUTO_STEPMAIN +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:75 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_AUTO_STEPHELP +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:76 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_TYPE +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:77 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_TIME_INCREMENT +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:78 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_EXPLICIT_TIME_INCREMENT +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:79 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_LOGARITHMIC +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:80 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_REVERSEDIRECTION +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:81 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_VISIBLE +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:82 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_CROSSOVER_POSITION +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:83 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_CROSSOVER_VALUE +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:84 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_ORIGIN +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:85 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_AUTO_ORIGIN +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:86 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_MARKS +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:87 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_HELPMARKS +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:88 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_MARK_POSITION +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:89 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_DISPLAY_LABELS +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:90 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_NUMBERFORMAT +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:91 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:92 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_LABEL_POSITION +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:93 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_TEXT_ROTATION +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:94 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_ARRANGE_ORDER +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:95 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_TEXTBREAK +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:96 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_CAN_OVERLAP +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:97 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_STACKEDTEXT +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:98 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_OVERLAP +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:99 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_GAP_WIDTH +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:100 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_DISPLAY_UNITS +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:101 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_BUILTINUNIT +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:102 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_TRY_STAGGERING_FIRST +chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:103 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx:65:1) PROP_AXIS_MAJOR_ORIGIN +chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:133 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:131:1) PROP_DOCUMENT_HAS_MAIN_TITLE +chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:134 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:131:1) PROP_DOCUMENT_HAS_SUB_TITLE +chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:135 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:131:1) PROP_DOCUMENT_HAS_LEGEND +chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:136 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:131:1) PROP_DOCUMENT_LABELS_IN_FIRST_ROW +chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:137 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:131:1) PROP_DOCUMENT_LABELS_IN_FIRST_COLUMN +chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:138 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:131:1) PROP_DOCUMENT_ADDIN +chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:139 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:131:1) PROP_DOCUMENT_BASEDIAGRAM +chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:140 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:131:1) PROP_DOCUMENT_ADDITIONAL_SHAPES +chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:141 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:131:1) PROP_DOCUMENT_UPDATE_ADDIN +chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:142 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:131:1) PROP_DOCUMENT_NULL_DATE +chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:143 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:131:1) PROP_DOCUMENT_ENABLE_COMPLEX_CHARTTYPES +chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:144 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:131:1) PROP_DOCUMENT_ENABLE_DATATABLE_DIALOG +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:70 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_SOLIDTYPE +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:71 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_SEGMENT_OFFSET +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:72 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_PERCENT_DIAGONAL +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:73 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_LABEL_SEPARATOR +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:74 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_NUMBERFORMAT +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:75 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_LINK_NUMBERFORMAT_TO_SOURCE +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:76 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_PERCENTAGE_NUMBERFORMAT +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:77 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_TEXT_WORD_WRAP +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:78 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_LABEL_PLACEMENT +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:80 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_ATTACHED_AXIS +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:81 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_SHOW_CUSTOM_LEADERLINES +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:82 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_TEXT_ROTATION +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:83 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_LABEL_BORDER_STYLE +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:84 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_LABEL_BORDER_WIDTH +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:85 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_LABEL_BORDER_COLOR +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:86 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_LABEL_BORDER_TRANS +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:87 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_LABEL_FILL_STYLE +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:88 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_LABEL_FILL_COLOR +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:89 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_LABEL_FILL_BACKGROUND +chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:90 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:67:1) PROP_SERIES_DATAPOINT_LABEL_FILL_HATCH_NAME +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:82 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_ATTRIBUTED_DATA_POINTS +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:83 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_PERCENT_STACKED +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:84 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_STACKED +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:85 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_THREE_D +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:86 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_SOLIDTYPE +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:87 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_DEEP +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:88 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_VERTICAL +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:89 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_NUMBER_OF_LINES +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:90 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_STACKED_BARS_CONNECTED +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:91 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_DATAROW_SOURCE +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:93 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_GROUP_BARS_PER_AXIS +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:94 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:96 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_SORT_BY_X_VALUES +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:98 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_STARTING_ANGLE +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:100 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_RIGHT_ANGLED_AXES +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:101 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_PERSPECTIVE +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:102 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_ROTATION_HORIZONTAL +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:103 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_ROTATION_VERTICAL +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:105 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_MISSING_VALUE_TREATMENT +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:107 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_X_AXIS +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:108 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_X_AXIS_DESCR +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:109 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_X_AXIS_TITLE +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:110 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_X_AXIS_GRID +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:111 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_X_AXIS_HELP_GRID +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:113 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_Y_AXIS +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:114 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_Y_AXIS_DESCR +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:115 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_Y_AXIS_TITLE +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:116 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_Y_AXIS_GRID +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:117 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_Y_AXIS_HELP_GRID +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:119 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_Z_AXIS +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:120 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_Z_AXIS_DESCR +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:121 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_Z_AXIS_TITLE +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:122 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_Z_AXIS_GRID +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:123 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_Z_AXIS_HELP_GRID +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:125 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_SECOND_X_AXIS +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:126 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_SECOND_X_AXIS_DESCR +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:128 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_SECOND_Y_AXIS +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:129 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_SECOND_Y_AXIS_DESCR +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:131 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_SECOND_X_AXIS_TITLE +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:132 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_HAS_SECOND_Y_AXIS_TITLE +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:134 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_AUTOMATIC_SIZE +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:135 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_DATATABLEHBORDER +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:136 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_DATATABLEVBORDER +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:137 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_DATATABLEOUTLINE +chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:138 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:80:1) PROP_DIAGRAM_EXTERNALDATA +chart2/source/controller/chartapiwrapper/LegendWrapper.cxx:208 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/LegendWrapper.cxx:206:1) PROP_LEGEND_ALIGNMENT +chart2/source/controller/chartapiwrapper/LegendWrapper.cxx:209 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/LegendWrapper.cxx:206:1) PROP_LEGEND_EXPANSION +chart2/source/controller/chartapiwrapper/TitleWrapper.cxx:131 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/TitleWrapper.cxx:129:1) PROP_TITLE_STRING +chart2/source/controller/chartapiwrapper/TitleWrapper.cxx:132 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/TitleWrapper.cxx:129:1) PROP_TITLE_TEXT_ROTATION +chart2/source/controller/chartapiwrapper/TitleWrapper.cxx:133 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/TitleWrapper.cxx:129:1) PROP_TITLE_TEXT_STACKED +chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.cxx:102 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.cxx:100:1) PROP_CHART_AUTOMATIC_POSITION +chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.cxx:53 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.cxx:50:1) PROP_CHART_DATAPOINT_DATA_CAPTION +chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.cxx:116 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.cxx:114:1) PROP_CHART_SCALE_TEXT +chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx:174 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx:171:1) PROP_CHART_SPLINE_TYPE +chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx:175 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx:171:1) PROP_CHART_SPLINE_ORDER +chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx:176 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx:171:1) PROP_CHART_SPLINE_RESOLUTION +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:935 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_CONST_ERROR_LOW +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:936 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_CONST_ERROR_HIGH +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:937 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_MEAN_VALUE +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:938 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_ERROR_CATEGORY +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:939 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_ERROR_BAR_STYLE +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:940 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_PERCENT_ERROR +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:941 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_ERROR_MARGIN +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:942 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_ERROR_INDICATOR +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:943 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_ERROR_RANGE_POSITIVE +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:944 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_ERROR_RANGE_NEGATIVE +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:945 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_REGRESSION_CURVES +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:946 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_REGRESSION_PROPERTIES +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:947 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_ERROR_PROPERTIES +chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:948 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:932:1) PROP_CHART_STATISTIC_MEAN_VALUE_PROPERTIES +chart2/source/controller/chartapiwrapper/WrappedStockProperties.cxx:250 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStockProperties.cxx:247:1) PROP_CHART_STOCK_VOLUME +chart2/source/controller/chartapiwrapper/WrappedStockProperties.cxx:251 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedStockProperties.cxx:247:1) PROP_CHART_STOCK_UPDOWN +chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx:106 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx:103:1) PROP_CHART_SYMBOL_TYPE +chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx:107 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx:103:1) PROP_CHART_SYMBOL_BITMAP_URL +chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx:108 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx:103:1) PROP_CHART_SYMBOL_BITMAP +chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx:109 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx:103:1) PROP_CHART_SYMBOL_SIZE +chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx:110 + enum chart::wrapper::(anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx:103:1) PROP_CHART_SYMBOL_AND_LINES +chart2/source/controller/dialogs/DialogModel.hxx:103 + enum chart::DialogModel::MoveDirection Up +chart2/source/controller/dialogs/tp_Scale.cxx:208 + enum chart::(anonymous namespace)::AxisTypeListBoxEntry TYPE_TEXT +chart2/source/controller/inc/AccessibleBase.hxx:286 + enum chart::AccessibleBase::eColorType ACC_BASE_BACKGROUND +chart2/source/controller/inc/ChartController.hxx:92 + enum chart::ChartDrawMode CHARTDRAW_SELECT +chart2/source/controller/main/ChartModelClone.hxx:33 + enum chart::ModelFacet E_MODEL +chart2/source/controller/main/DragMethod_RotateDiagram.hxx:36 + enum chart::DragMethod_RotateDiagram::RotationDirection ROTATIONDIRECTION_FREE +chart2/source/controller/sidebar/ChartElementsPanel.cxx:50 + enum chart::sidebar::(anonymous namespace)::GridType VERT_MINOR +chart2/source/controller/sidebar/ChartElementsPanel.cxx:57 + enum chart::sidebar::(anonymous namespace)::AxisType X_MAIN +chart2/source/controller/sidebar/ChartErrorBarPanel.cxx:39 + enum chart::sidebar::(anonymous namespace)::ErrorBarDirection POSITIVE +chart2/source/inc/CharacterProperties.hxx:44 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_FONT_NAME +chart2/source/inc/CharacterProperties.hxx:45 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_FONT_STYLE_NAME +chart2/source/inc/CharacterProperties.hxx:46 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_FONT_FAMILY +chart2/source/inc/CharacterProperties.hxx:47 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_FONT_CHAR_SET +chart2/source/inc/CharacterProperties.hxx:48 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_FONT_PITCH +chart2/source/inc/CharacterProperties.hxx:49 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_COLOR +chart2/source/inc/CharacterProperties.hxx:52 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_ESCAPEMENT +chart2/source/inc/CharacterProperties.hxx:53 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_CHAR_HEIGHT +chart2/source/inc/CharacterProperties.hxx:54 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_UNDERLINE +chart2/source/inc/CharacterProperties.hxx:55 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_UNDERLINE_COLOR +chart2/source/inc/CharacterProperties.hxx:56 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_UNDERLINE_HAS_COLOR +chart2/source/inc/CharacterProperties.hxx:57 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_OVERLINE +chart2/source/inc/CharacterProperties.hxx:58 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_OVERLINE_COLOR +chart2/source/inc/CharacterProperties.hxx:59 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_OVERLINE_HAS_COLOR +chart2/source/inc/CharacterProperties.hxx:60 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_WEIGHT +chart2/source/inc/CharacterProperties.hxx:61 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_POSTURE +chart2/source/inc/CharacterProperties.hxx:62 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_AUTO_KERNING +chart2/source/inc/CharacterProperties.hxx:63 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_KERNING +chart2/source/inc/CharacterProperties.hxx:68 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_ESCAPEMENT_HEIGHT +chart2/source/inc/CharacterProperties.hxx:71 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_STRIKE_OUT +chart2/source/inc/CharacterProperties.hxx:72 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_WORD_MODE +chart2/source/inc/CharacterProperties.hxx:74 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_LOCALE +chart2/source/inc/CharacterProperties.hxx:77 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_SHADOWED +chart2/source/inc/CharacterProperties.hxx:78 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_CONTOURED +chart2/source/inc/CharacterProperties.hxx:79 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_RELIEF +chart2/source/inc/CharacterProperties.hxx:84 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_EMPHASIS +chart2/source/inc/CharacterProperties.hxx:92 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_ASIAN_FONT_NAME +chart2/source/inc/CharacterProperties.hxx:93 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_ASIAN_FONT_STYLE_NAME +chart2/source/inc/CharacterProperties.hxx:94 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_ASIAN_FONT_FAMILY +chart2/source/inc/CharacterProperties.hxx:95 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_ASIAN_CHAR_SET +chart2/source/inc/CharacterProperties.hxx:96 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_ASIAN_FONT_PITCH +chart2/source/inc/CharacterProperties.hxx:97 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_ASIAN_CHAR_HEIGHT +chart2/source/inc/CharacterProperties.hxx:98 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_ASIAN_WEIGHT +chart2/source/inc/CharacterProperties.hxx:99 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_ASIAN_POSTURE +chart2/source/inc/CharacterProperties.hxx:100 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_ASIAN_LOCALE +chart2/source/inc/CharacterProperties.hxx:106 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_COMPLEX_FONT_NAME +chart2/source/inc/CharacterProperties.hxx:107 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_COMPLEX_FONT_STYLE_NAME +chart2/source/inc/CharacterProperties.hxx:108 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_COMPLEX_FONT_FAMILY +chart2/source/inc/CharacterProperties.hxx:109 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_COMPLEX_CHAR_SET +chart2/source/inc/CharacterProperties.hxx:110 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_COMPLEX_FONT_PITCH +chart2/source/inc/CharacterProperties.hxx:111 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_COMPLEX_CHAR_HEIGHT +chart2/source/inc/CharacterProperties.hxx:112 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_COMPLEX_WEIGHT +chart2/source/inc/CharacterProperties.hxx:113 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_COMPLEX_POSTURE +chart2/source/inc/CharacterProperties.hxx:114 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_CHAR_COMPLEX_LOCALE +chart2/source/inc/CharacterProperties.hxx:115 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_PARA_IS_CHARACTER_DISTANCE +chart2/source/inc/CharacterProperties.hxx:117 + enum chart::CharacterProperties::(anonymous at /home/noel/libo2/chart2/source/inc/CharacterProperties.hxx:41:5) PROP_WRITING_MODE +chart2/source/inc/ChartResourceGroups.hxx:38 + enum chart::(anonymous at /home/noel/libo2/chart2/source/inc/ChartResourceGroups.hxx:35:1) POS_3DSCHEME_REALISTIC +chart2/source/inc/DiagramHelper.hxx:45 + enum chart::DiagramPositioningMode DiagramPositioningMode_AUTO +chart2/source/inc/FastPropertyIdRanges.hxx:25 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START +chart2/source/inc/FastPropertyIdRanges.hxx:26 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_DATA_SERIES +chart2/source/inc/FastPropertyIdRanges.hxx:27 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_DATA_POINT +chart2/source/inc/FastPropertyIdRanges.hxx:29 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_LINE_PROP +chart2/source/inc/FastPropertyIdRanges.hxx:30 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_FILL_PROP +chart2/source/inc/FastPropertyIdRanges.hxx:31 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_USERDEF_PROP +chart2/source/inc/FastPropertyIdRanges.hxx:32 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_SCENE_PROP +chart2/source/inc/FastPropertyIdRanges.hxx:35 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_CHART_STATISTIC_PROP +chart2/source/inc/FastPropertyIdRanges.hxx:36 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_CHART_SYMBOL_PROP +chart2/source/inc/FastPropertyIdRanges.hxx:37 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_CHART_DATACAPTION_PROP +chart2/source/inc/FastPropertyIdRanges.hxx:38 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_CHART_SPLINE_PROP +chart2/source/inc/FastPropertyIdRanges.hxx:39 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_CHART_STOCK_PROP +chart2/source/inc/FastPropertyIdRanges.hxx:40 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_CHART_AUTOPOSITION_PROP +chart2/source/inc/FastPropertyIdRanges.hxx:41 + enum chart::FastPropertyIdRanges FAST_PROPERTY_ID_START_SCALE_TEXT_PROP +chart2/source/inc/FillProperties.hxx:39 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_STYLE +chart2/source/inc/FillProperties.hxx:40 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_COLOR +chart2/source/inc/FillProperties.hxx:41 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_TRANSPARENCE +chart2/source/inc/FillProperties.hxx:42 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_TRANSPARENCE_GRADIENT_NAME +chart2/source/inc/FillProperties.hxx:44 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_GRADIENT_NAME +chart2/source/inc/FillProperties.hxx:45 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_GRADIENT_STEPCOUNT +chart2/source/inc/FillProperties.hxx:47 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_HATCH_NAME +chart2/source/inc/FillProperties.hxx:50 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_BITMAP_NAME +chart2/source/inc/FillProperties.hxx:53 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_BITMAP_OFFSETX +chart2/source/inc/FillProperties.hxx:54 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_BITMAP_OFFSETY +chart2/source/inc/FillProperties.hxx:55 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_BITMAP_POSITION_OFFSETX +chart2/source/inc/FillProperties.hxx:56 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_BITMAP_POSITION_OFFSETY +chart2/source/inc/FillProperties.hxx:57 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_BITMAP_RECTANGLEPOINT +chart2/source/inc/FillProperties.hxx:58 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_BITMAP_LOGICALSIZE +chart2/source/inc/FillProperties.hxx:59 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_BITMAP_SIZEX +chart2/source/inc/FillProperties.hxx:60 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_BITMAP_SIZEY +chart2/source/inc/FillProperties.hxx:61 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_BITMAP_MODE +chart2/source/inc/FillProperties.hxx:63 + enum chart::FillProperties::(anonymous at /home/noel/libo2/chart2/source/inc/FillProperties.hxx:36:5) PROP_FILL_BACKGROUND +chart2/source/inc/LinePropertiesHelper.hxx:41 + enum chart::LinePropertiesHelper::(anonymous at /home/noel/libo2/chart2/source/inc/LinePropertiesHelper.hxx:38:5) PROP_LINE_STYLE +chart2/source/inc/LinePropertiesHelper.hxx:42 + enum chart::LinePropertiesHelper::(anonymous at /home/noel/libo2/chart2/source/inc/LinePropertiesHelper.hxx:38:5) PROP_LINE_DASH +chart2/source/inc/LinePropertiesHelper.hxx:43 + enum chart::LinePropertiesHelper::(anonymous at /home/noel/libo2/chart2/source/inc/LinePropertiesHelper.hxx:38:5) PROP_LINE_DASH_NAME +chart2/source/inc/LinePropertiesHelper.hxx:44 + enum chart::LinePropertiesHelper::(anonymous at /home/noel/libo2/chart2/source/inc/LinePropertiesHelper.hxx:38:5) PROP_LINE_COLOR +chart2/source/inc/LinePropertiesHelper.hxx:45 + enum chart::LinePropertiesHelper::(anonymous at /home/noel/libo2/chart2/source/inc/LinePropertiesHelper.hxx:38:5) PROP_LINE_TRANSPARENCE +chart2/source/inc/LinePropertiesHelper.hxx:46 + enum chart::LinePropertiesHelper::(anonymous at /home/noel/libo2/chart2/source/inc/LinePropertiesHelper.hxx:38:5) PROP_LINE_WIDTH +chart2/source/inc/LinePropertiesHelper.hxx:47 + enum chart::LinePropertiesHelper::(anonymous at /home/noel/libo2/chart2/source/inc/LinePropertiesHelper.hxx:38:5) PROP_LINE_JOINT +chart2/source/inc/LinePropertiesHelper.hxx:48 + enum chart::LinePropertiesHelper::(anonymous at /home/noel/libo2/chart2/source/inc/LinePropertiesHelper.hxx:38:5) PROP_LINE_CAP +chart2/source/inc/ReferenceSizeProvider.hxx:46 + enum chart::ReferenceSizeProvider::AutoResizeState AUTO_RESIZE_NO +chart2/source/inc/SceneProperties.hxx:39 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_TRANSF_MATRIX +chart2/source/inc/SceneProperties.hxx:40 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_DISTANCE +chart2/source/inc/SceneProperties.hxx:41 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_FOCAL_LENGTH +chart2/source/inc/SceneProperties.hxx:42 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_SHADOW_SLANT +chart2/source/inc/SceneProperties.hxx:43 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_SHADE_MODE +chart2/source/inc/SceneProperties.hxx:44 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_AMBIENT_COLOR +chart2/source/inc/SceneProperties.hxx:45 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_TWO_SIDED_LIGHTING +chart2/source/inc/SceneProperties.hxx:46 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_CAMERA_GEOMETRY +chart2/source/inc/SceneProperties.hxx:47 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_PERSPECTIVE +chart2/source/inc/SceneProperties.hxx:48 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_COLOR_1 +chart2/source/inc/SceneProperties.hxx:49 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_DIRECTION_1 +chart2/source/inc/SceneProperties.hxx:50 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_ON_1 +chart2/source/inc/SceneProperties.hxx:51 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_COLOR_2 +chart2/source/inc/SceneProperties.hxx:52 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_DIRECTION_2 +chart2/source/inc/SceneProperties.hxx:53 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_ON_2 +chart2/source/inc/SceneProperties.hxx:54 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_COLOR_3 +chart2/source/inc/SceneProperties.hxx:55 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_DIRECTION_3 +chart2/source/inc/SceneProperties.hxx:56 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_ON_3 +chart2/source/inc/SceneProperties.hxx:57 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_COLOR_4 +chart2/source/inc/SceneProperties.hxx:58 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_DIRECTION_4 +chart2/source/inc/SceneProperties.hxx:59 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_ON_4 +chart2/source/inc/SceneProperties.hxx:60 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_COLOR_5 +chart2/source/inc/SceneProperties.hxx:61 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_DIRECTION_5 +chart2/source/inc/SceneProperties.hxx:62 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_ON_5 +chart2/source/inc/SceneProperties.hxx:63 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_COLOR_6 +chart2/source/inc/SceneProperties.hxx:64 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_DIRECTION_6 +chart2/source/inc/SceneProperties.hxx:65 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_ON_6 +chart2/source/inc/SceneProperties.hxx:66 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_COLOR_7 +chart2/source/inc/SceneProperties.hxx:67 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_DIRECTION_7 +chart2/source/inc/SceneProperties.hxx:68 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_ON_7 +chart2/source/inc/SceneProperties.hxx:69 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_COLOR_8 +chart2/source/inc/SceneProperties.hxx:70 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_DIRECTION_8 +chart2/source/inc/SceneProperties.hxx:71 + enum chart::SceneProperties::(anonymous at /home/noel/libo2/chart2/source/inc/SceneProperties.hxx:36:5) PROP_SCENE_LIGHT_ON_8 +chart2/source/inc/ThreeDHelper.hxx:42 + enum chart::CuboidPlanePosition CuboidPlanePosition_Top +chart2/source/inc/TitleHelper.hxx:39 + enum chart::TitleHelper::eTitleType TITLE_BEGIN +chart2/source/inc/UserDefinedProperties.hxx:38 + enum chart::UserDefinedProperties::(anonymous at /home/noel/libo2/chart2/source/inc/UserDefinedProperties.hxx:35:5) PROP_XML_USERDEF_CHART +chart2/source/inc/UserDefinedProperties.hxx:39 + enum chart::UserDefinedProperties::(anonymous at /home/noel/libo2/chart2/source/inc/UserDefinedProperties.hxx:35:5) PROP_XML_USERDEF_TEXT +chart2/source/inc/UserDefinedProperties.hxx:40 + enum chart::UserDefinedProperties::(anonymous at /home/noel/libo2/chart2/source/inc/UserDefinedProperties.hxx:35:5) PROP_XML_USERDEF_PARA +chart2/source/inc/UserDefinedProperties.hxx:45 + enum chart::UserDefinedProperties::(anonymous at /home/noel/libo2/chart2/source/inc/UserDefinedProperties.hxx:35:5) PROP_XML_USERDEF +chart2/source/model/main/Axis.cxx:58 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_SHOW +chart2/source/model/main/Axis.cxx:59 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_CROSSOVER_POSITION +chart2/source/model/main/Axis.cxx:60 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_CROSSOVER_VALUE +chart2/source/model/main/Axis.cxx:61 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_DISPLAY_LABELS +chart2/source/model/main/Axis.cxx:62 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_NUMBERFORMAT +chart2/source/model/main/Axis.cxx:63 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE +chart2/source/model/main/Axis.cxx:64 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_LABEL_POSITION +chart2/source/model/main/Axis.cxx:65 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_TEXT_ROTATION +chart2/source/model/main/Axis.cxx:66 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_TEXT_BREAK +chart2/source/model/main/Axis.cxx:67 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_TEXT_OVERLAP +chart2/source/model/main/Axis.cxx:68 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_TEXT_STACKED +chart2/source/model/main/Axis.cxx:69 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_TEXT_ARRANGE_ORDER +chart2/source/model/main/Axis.cxx:70 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_REFERENCE_DIAGRAM_SIZE +chart2/source/model/main/Axis.cxx:72 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_MAJOR_TICKMARKS +chart2/source/model/main/Axis.cxx:73 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_MINOR_TICKMARKS +chart2/source/model/main/Axis.cxx:74 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_MARK_POSITION +chart2/source/model/main/Axis.cxx:76 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_DISPLAY_UNITS +chart2/source/model/main/Axis.cxx:77 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_BUILTINUNIT +chart2/source/model/main/Axis.cxx:79 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_TRY_STAGGERING_FIRST +chart2/source/model/main/Axis.cxx:80 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Axis.cxx:56:1) PROP_AXIS_MAJOR_ORIGIN +chart2/source/model/main/BaseCoordinateSystem.cxx:45 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/BaseCoordinateSystem.cxx:43:1) PROP_COORDINATESYSTEM_SWAPXANDYAXIS +chart2/source/model/main/DataPointProperties.hxx:37 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_FILL_STYLE +chart2/source/model/main/DataPointProperties.hxx:38 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_FILL_COLOR +chart2/source/model/main/DataPointProperties.hxx:39 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_FILL_BACKGROUND +chart2/source/model/main/DataPointProperties.hxx:40 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_FILL_HATCH_NAME +chart2/source/model/main/DataPointProperties.hxx:43 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_COLOR +chart2/source/model/main/DataPointProperties.hxx:44 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_TRANSPARENCY +chart2/source/model/main/DataPointProperties.hxx:47 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_FILL_STYLE +chart2/source/model/main/DataPointProperties.hxx:48 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_TRANSPARENCY_GRADIENT_NAME +chart2/source/model/main/DataPointProperties.hxx:49 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_GRADIENT_NAME +chart2/source/model/main/DataPointProperties.hxx:50 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_GRADIENT_STEPCOUNT +chart2/source/model/main/DataPointProperties.hxx:51 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_HATCH_NAME +chart2/source/model/main/DataPointProperties.hxx:52 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_FILL_BITMAP_NAME +chart2/source/model/main/DataPointProperties.hxx:53 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_FILL_BACKGROUND +chart2/source/model/main/DataPointProperties.hxx:56 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_BORDER_COLOR +chart2/source/model/main/DataPointProperties.hxx:57 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_BORDER_STYLE +chart2/source/model/main/DataPointProperties.hxx:58 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_BORDER_WIDTH +chart2/source/model/main/DataPointProperties.hxx:59 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_BORDER_DASH_NAME +chart2/source/model/main/DataPointProperties.hxx:60 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_BORDER_TRANSPARENCY +chart2/source/model/main/DataPointProperties.hxx:63 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_SYMBOL_PROP +chart2/source/model/main/DataPointProperties.hxx:64 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_OFFSET +chart2/source/model/main/DataPointProperties.hxx:65 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_GEOMETRY3D +chart2/source/model/main/DataPointProperties.hxx:66 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_NUMBER_FORMAT +chart2/source/model/main/DataPointProperties.hxx:67 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LINK_NUMBERFORMAT_TO_SOURCE +chart2/source/model/main/DataPointProperties.hxx:68 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_PERCENTAGE_NUMBER_FORMAT +chart2/source/model/main/DataPointProperties.hxx:69 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_PLACEMENT +chart2/source/model/main/DataPointProperties.hxx:70 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_REFERENCE_DIAGRAM_SIZE +chart2/source/model/main/DataPointProperties.hxx:71 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_TEXT_ROTATION +chart2/source/model/main/DataPointProperties.hxx:76 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_SHOW_ERROR_BOX +chart2/source/model/main/DataPointProperties.hxx:77 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_PERCENT_DIAGONAL +chart2/source/model/main/DataPointProperties.hxx:80 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL +chart2/source/model/main/DataPointProperties.hxx:81 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_SEPARATOR +chart2/source/model/main/DataPointProperties.hxx:82 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_TEXT_WORD_WRAP +chart2/source/model/main/DataPointProperties.hxx:83 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_BORDER_STYLE +chart2/source/model/main/DataPointProperties.hxx:84 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_BORDER_COLOR +chart2/source/model/main/DataPointProperties.hxx:85 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_BORDER_WIDTH +chart2/source/model/main/DataPointProperties.hxx:86 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_BORDER_DASH +chart2/source/model/main/DataPointProperties.hxx:87 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_BORDER_DASH_NAME +chart2/source/model/main/DataPointProperties.hxx:88 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_BORDER_TRANS +chart2/source/model/main/DataPointProperties.hxx:89 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_CUSTOM_LABEL_FIELDS +chart2/source/model/main/DataPointProperties.hxx:90 + enum chart::DataPointProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataPointProperties.hxx:35:5) PROP_DATAPOINT_LABEL_CUSTOM_POS +chart2/source/model/main/DataSeriesProperties.hxx:33 + enum chart::DataSeriesProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataSeriesProperties.hxx:30:5) PROP_DATASERIES_STACKING_DIRECTION +chart2/source/model/main/DataSeriesProperties.hxx:34 + enum chart::DataSeriesProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataSeriesProperties.hxx:30:5) PROP_DATASERIES_VARY_COLORS_BY_POINT +chart2/source/model/main/DataSeriesProperties.hxx:35 + enum chart::DataSeriesProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataSeriesProperties.hxx:30:5) PROP_DATASERIES_ATTACHED_AXIS_INDEX +chart2/source/model/main/DataSeriesProperties.hxx:36 + enum chart::DataSeriesProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataSeriesProperties.hxx:30:5) PROP_DATASERIES_SHOW_LEGEND_ENTRY +chart2/source/model/main/DataSeriesProperties.hxx:37 + enum chart::DataSeriesProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataSeriesProperties.hxx:30:5) PROP_DATASERIES_DELETED_LEGEND_ENTRIES +chart2/source/model/main/DataSeriesProperties.hxx:38 + enum chart::DataSeriesProperties::(anonymous at /home/noel/libo2/chart2/source/model/main/DataSeriesProperties.hxx:30:5) PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES +chart2/source/model/main/Diagram.cxx:60 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_REL_POS +chart2/source/model/main/Diagram.cxx:61 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_REL_SIZE +chart2/source/model/main/Diagram.cxx:62 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS +chart2/source/model/main/Diagram.cxx:63 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_SORT_BY_X_VALUES +chart2/source/model/main/Diagram.cxx:64 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_CONNECT_BARS +chart2/source/model/main/Diagram.cxx:65 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_GROUP_BARS_PER_AXIS +chart2/source/model/main/Diagram.cxx:66 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS +chart2/source/model/main/Diagram.cxx:67 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_STARTING_ANGLE +chart2/source/model/main/Diagram.cxx:68 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_RIGHT_ANGLED_AXES +chart2/source/model/main/Diagram.cxx:72 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_MISSING_VALUE_TREATMENT +chart2/source/model/main/Diagram.cxx:73 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_3DRELATIVEHEIGHT +chart2/source/model/main/Diagram.cxx:74 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_DATATABLEHBORDER +chart2/source/model/main/Diagram.cxx:75 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_DATATABLEVBORDER +chart2/source/model/main/Diagram.cxx:76 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_DATATABLEOUTLINE +chart2/source/model/main/Diagram.cxx:77 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Diagram.cxx:58:1) PROP_DIAGRAM_EXTERNALDATA +chart2/source/model/main/GridProperties.cxx:44 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/GridProperties.cxx:42:1) PROP_GRID_SHOW +chart2/source/model/main/Legend.cxx:53 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Legend.cxx:51:1) PROP_LEGEND_ANCHOR_POSITION +chart2/source/model/main/Legend.cxx:54 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Legend.cxx:51:1) PROP_LEGEND_EXPANSION +chart2/source/model/main/Legend.cxx:55 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Legend.cxx:51:1) PROP_LEGEND_SHOW +chart2/source/model/main/Legend.cxx:56 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Legend.cxx:51:1) PROP_LEGEND_OVERLAY +chart2/source/model/main/Legend.cxx:57 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Legend.cxx:51:1) PROP_LEGEND_REF_PAGE_SIZE +chart2/source/model/main/Legend.cxx:58 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Legend.cxx:51:1) PROP_LEGEND_REL_POS +chart2/source/model/main/Legend.cxx:59 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Legend.cxx:51:1) PROP_LEGEND_REL_SIZE +chart2/source/model/main/Title.cxx:51 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Title.cxx:49:1) PROP_TITLE_PARA_ADJUST +chart2/source/model/main/Title.cxx:52 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Title.cxx:49:1) PROP_TITLE_PARA_LAST_LINE_ADJUST +chart2/source/model/main/Title.cxx:53 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Title.cxx:49:1) PROP_TITLE_PARA_LEFT_MARGIN +chart2/source/model/main/Title.cxx:54 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Title.cxx:49:1) PROP_TITLE_PARA_RIGHT_MARGIN +chart2/source/model/main/Title.cxx:55 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Title.cxx:49:1) PROP_TITLE_PARA_TOP_MARGIN +chart2/source/model/main/Title.cxx:56 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Title.cxx:49:1) PROP_TITLE_PARA_BOTTOM_MARGIN +chart2/source/model/main/Title.cxx:57 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Title.cxx:49:1) PROP_TITLE_PARA_IS_HYPHENATION +chart2/source/model/main/Title.cxx:58 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Title.cxx:49:1) PROP_TITLE_VISIBLE +chart2/source/model/main/Title.cxx:60 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Title.cxx:49:1) PROP_TITLE_TEXT_ROTATION +chart2/source/model/main/Title.cxx:61 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Title.cxx:49:1) PROP_TITLE_TEXT_STACKED +chart2/source/model/main/Title.cxx:62 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Title.cxx:49:1) PROP_TITLE_REL_POS +chart2/source/model/main/Title.cxx:64 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/main/Title.cxx:49:1) PROP_TITLE_REF_PAGE_SIZE +chart2/source/model/template/AreaChartTypeTemplate.cxx:44 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/AreaChartTypeTemplate.cxx:42:1) PROP_AREA_TEMPLATE_DIMENSION +chart2/source/model/template/BarChartTypeTemplate.cxx:46 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/BarChartTypeTemplate.cxx:44:1) PROP_BAR_TEMPLATE_DIMENSION +chart2/source/model/template/BarChartTypeTemplate.cxx:47 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/BarChartTypeTemplate.cxx:44:1) PROP_BAR_TEMPLATE_GEOMETRY3D +chart2/source/model/template/CandleStickChartType.cxx:42 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/CandleStickChartType.cxx:40:1) PROP_CANDLESTICKCHARTTYPE_JAPANESE +chart2/source/model/template/CandleStickChartType.cxx:46 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/CandleStickChartType.cxx:40:1) PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST +chart2/source/model/template/CandleStickChartType.cxx:47 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/CandleStickChartType.cxx:40:1) PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW +chart2/source/model/template/ColumnChartType.cxx:37 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/ColumnChartType.cxx:35:1) PROP_BARCHARTTYPE_OVERLAP_SEQUENCE +chart2/source/model/template/ColumnChartType.cxx:38 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/ColumnChartType.cxx:35:1) PROP_BARCHARTTYPE_GAPWIDTH_SEQUENCE +chart2/source/model/template/ColumnLineChartTypeTemplate.cxx:50 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/ColumnLineChartTypeTemplate.cxx:48:1) PROP_COL_LINE_NUMBER_OF_LINES +chart2/source/model/template/LineChartType.cxx:41 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/LineChartType.cxx:39:1) PROP_LINECHARTTYPE_CURVE_STYLE +chart2/source/model/template/LineChartType.cxx:42 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/LineChartType.cxx:39:1) PROP_LINECHARTTYPE_CURVE_RESOLUTION +chart2/source/model/template/LineChartType.cxx:43 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/LineChartType.cxx:39:1) PROP_LINECHARTTYPE_SPLINE_ORDER +chart2/source/model/template/LineChartTypeTemplate.cxx:49 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/LineChartTypeTemplate.cxx:47:1) PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE +chart2/source/model/template/LineChartTypeTemplate.cxx:50 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/LineChartTypeTemplate.cxx:47:1) PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION +chart2/source/model/template/LineChartTypeTemplate.cxx:51 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/LineChartTypeTemplate.cxx:47:1) PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER +chart2/source/model/template/PieChartType.cxx:41 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/PieChartType.cxx:39:1) PROP_PIECHARTTYPE_USE_RINGS +chart2/source/model/template/PieChartType.cxx:42 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/PieChartType.cxx:39:1) PROP_PIECHARTTYPE_3DRELATIVEHEIGHT +chart2/source/model/template/PieChartTypeTemplate.cxx:53 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/PieChartTypeTemplate.cxx:51:1) PROP_PIE_TEMPLATE_DEFAULT_OFFSET +chart2/source/model/template/PieChartTypeTemplate.cxx:54 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/PieChartTypeTemplate.cxx:51:1) PROP_PIE_TEMPLATE_OFFSET_MODE +chart2/source/model/template/PieChartTypeTemplate.cxx:55 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/PieChartTypeTemplate.cxx:51:1) PROP_PIE_TEMPLATE_DIMENSION +chart2/source/model/template/PieChartTypeTemplate.cxx:56 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/PieChartTypeTemplate.cxx:51:1) PROP_PIE_TEMPLATE_USE_RINGS +chart2/source/model/template/ScatterChartType.cxx:44 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/ScatterChartType.cxx:42:1) PROP_SCATTERCHARTTYPE_CURVE_STYLE +chart2/source/model/template/ScatterChartType.cxx:45 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/ScatterChartType.cxx:42:1) PROP_SCATTERCHARTTYPE_CURVE_RESOLUTION +chart2/source/model/template/ScatterChartType.cxx:46 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/ScatterChartType.cxx:42:1) PROP_SCATTERCHARTTYPE_SPLINE_ORDER +chart2/source/model/template/ScatterChartTypeTemplate.cxx:50 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/ScatterChartTypeTemplate.cxx:48:1) PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE +chart2/source/model/template/ScatterChartTypeTemplate.cxx:51 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/ScatterChartTypeTemplate.cxx:48:1) PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION +chart2/source/model/template/ScatterChartTypeTemplate.cxx:52 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/ScatterChartTypeTemplate.cxx:48:1) PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER +chart2/source/model/template/StockChartTypeTemplate.cxx:50 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/StockChartTypeTemplate.cxx:48:1) PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME +chart2/source/model/template/StockChartTypeTemplate.cxx:51 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/StockChartTypeTemplate.cxx:48:1) PROP_STOCKCHARTTYPE_TEMPLATE_OPEN +chart2/source/model/template/StockChartTypeTemplate.cxx:52 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/StockChartTypeTemplate.cxx:48:1) PROP_STOCKCHARTTYPE_TEMPLATE_LOW_HIGH +chart2/source/model/template/StockChartTypeTemplate.cxx:53 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/model/template/StockChartTypeTemplate.cxx:48:1) PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE +chart2/source/tools/CachedDataSequence.cxx:50 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/CachedDataSequence.cxx:47:1) PROP_NUMBERFORMAT_KEY +chart2/source/tools/CachedDataSequence.cxx:51 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/CachedDataSequence.cxx:47:1) PROP_PROPOSED_ROLE +chart2/source/tools/RegressionCurveModel.cxx:41 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionCurveModel.cxx:39:1) PROPERTY_DEGREE +chart2/source/tools/RegressionCurveModel.cxx:42 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionCurveModel.cxx:39:1) PROPERTY_PERIOD +chart2/source/tools/RegressionCurveModel.cxx:43 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionCurveModel.cxx:39:1) PROPERTY_EXTRAPOLATE_FORWARD +chart2/source/tools/RegressionCurveModel.cxx:44 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionCurveModel.cxx:39:1) PROPERTY_EXTRAPOLATE_BACKWARD +chart2/source/tools/RegressionCurveModel.cxx:45 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionCurveModel.cxx:39:1) PROPERTY_FORCE_INTERCEPT +chart2/source/tools/RegressionCurveModel.cxx:46 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionCurveModel.cxx:39:1) PROPERTY_INTERCEPT_VALUE +chart2/source/tools/RegressionCurveModel.cxx:47 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionCurveModel.cxx:39:1) PROPERTY_CURVE_NAME +chart2/source/tools/RegressionCurveModel.cxx:48 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionCurveModel.cxx:39:1) PROPERTY_MOVING_AVERAGE_TYPE +chart2/source/tools/RegressionEquation.cxx:53 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionEquation.cxx:51:1) PROP_EQUATION_SHOW +chart2/source/tools/RegressionEquation.cxx:54 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionEquation.cxx:51:1) PROP_EQUATION_XNAME +chart2/source/tools/RegressionEquation.cxx:55 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionEquation.cxx:51:1) PROP_EQUATION_YNAME +chart2/source/tools/RegressionEquation.cxx:56 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionEquation.cxx:51:1) PROP_EQUATION_SHOW_CORRELATION_COEFF +chart2/source/tools/RegressionEquation.cxx:57 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionEquation.cxx:51:1) PROP_EQUATION_REF_PAGE_SIZE +chart2/source/tools/RegressionEquation.cxx:58 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionEquation.cxx:51:1) PROP_EQUATION_REL_POS +chart2/source/tools/RegressionEquation.cxx:59 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/RegressionEquation.cxx:51:1) PROP_EQUATION_NUMBER_FORMAT +chart2/source/tools/UncachedDataSequence.cxx:48 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/UncachedDataSequence.cxx:46:1) PROP_NUMBERFORMAT_KEY +chart2/source/tools/UncachedDataSequence.cxx:49 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/UncachedDataSequence.cxx:46:1) PROP_PROPOSED_ROLE +chart2/source/tools/UncachedDataSequence.cxx:50 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/chart2/source/tools/UncachedDataSequence.cxx:46:1) PROP_XML_RANGE +chart2/source/view/axes/VAxisProperties.hxx:48 + enum chart::AxisLabelStaggering SideBySide +chart2/source/view/inc/LegendEntryProvider.hxx:42 + enum chart::LegendSymbolStyle Box +chart2/source/view/inc/ShapeFactory.hxx:64 + enum chart::SymbolEnum Symbol_COUNT +chart2/source/view/inc/ShapeFactory.hxx:76 + enum chart::ShapeFactory::StackPosition Top +codemaker/source/cppumaker/dependencies.hxx:48 + enum codemaker::cppumaker::Dependencies::Kind KIND_NORMAL +comphelper/source/misc/backupfilehelper.cxx:209 + enum (anonymous namespace)::PackageRepository BUNDLED +comphelper/source/misc/backupfilehelper.cxx:209 + enum (anonymous namespace)::PackageRepository SHARED +comphelper/source/misc/backupfilehelper.cxx:209 + enum (anonymous namespace)::PackageRepository USER +comphelper/source/misc/syntaxhighlight.cxx:35 + enum (anonymous namespace)::CharFlags StartNumber +comphelper/source/misc/syntaxhighlight.cxx:36 + enum (anonymous namespace)::CharFlags InNumber +comphelper/source/misc/syntaxhighlight.cxx:37 + enum (anonymous namespace)::CharFlags InHexNumber +comphelper/source/misc/syntaxhighlight.cxx:38 + enum (anonymous namespace)::CharFlags InOctNumber +comphelper/source/misc/syntaxhighlight.cxx:39 + enum (anonymous namespace)::CharFlags StartString +comphelper/source/misc/syntaxhighlight.cxx:40 + enum (anonymous namespace)::CharFlags Operator +comphelper/source/misc/syntaxhighlight.cxx:41 + enum (anonymous namespace)::CharFlags Space +comphelper/source/misc/syntaxhighlight.cxx:42 + enum (anonymous namespace)::CharFlags EOL +configmgr/source/access.hxx:442 + enum configmgr::Access::(anonymous at /home/noel/libo2/configmgr/source/access.hxx:441:5) IS_ANY +configmgr/source/partial.hxx:33 + enum configmgr::Partial::Containment CONTAINS_SUBNODES +connectivity/source/drivers/evoab2/EApi.h:74 + EBookQueryTest E_BOOK_QUERY_IS +connectivity/source/drivers/evoab2/EApi.h:75 + EBookQueryTest E_BOOK_QUERY_CONTAINS +connectivity/source/drivers/evoab2/EApi.h:76 + EBookQueryTest E_BOOK_QUERY_BEGINS_WITH +connectivity/source/drivers/evoab2/EApi.h:77 + EBookQueryTest E_BOOK_QUERY_ENDS_WITH +connectivity/source/inc/java/sql/ConnectionLog.hxx:66 + enum connectivity::java::sql::ConnectionLog::ObjectType CONNECTION +connectivity/source/inc/java/sql/ConnectionLog.hxx:67 + enum connectivity::java::sql::ConnectionLog::ObjectType STATEMENT +connectivity/source/inc/java/sql/ConnectionLog.hxx:68 + enum connectivity::java::sql::ConnectionLog::ObjectType RESULTSET +connectivity/source/inc/java/sql/ConnectionLog.hxx:70 + enum connectivity::java::sql::ConnectionLog::ObjectType ObjectTypeCount +connectivity/source/inc/TSortIndex.hxx:36 + enum connectivity::TAscendingOrder DESC +cppuhelper/source/servicemanager.hxx:119 + enum cppuhelper::ServiceManager::Data::Implementation::Status STATUS_WRAPPER +cui/source/dialogs/colorpicker.cxx:56 + enum (anonymous namespace)::UpdateFlags All +cui/source/dialogs/hangulhanjadlg.cxx:89 + enum svx::(anonymous namespace)::PseudoRubyText::RubyPosition eBelow +cui/source/inc/acccfg.hxx:72 + enum StartFileDialogType Open +cui/source/inc/cuitabarea.hxx:82 + enum PageType Area +cui/source/inc/cuitabarea.hxx:86 + enum PageType Shadow +cui/source/inc/cuitabarea.hxx:87 + enum PageType Transparence +cui/source/inc/hldoctp.hxx:51 + enum SvxHyperlinkDocTp::EPathType Invalid +cui/source/inc/scriptdlg.hxx:42 + enum InputDialogMode NEWLIB +cui/source/options/optcolor.cxx:47 + enum (anonymous namespace)::Group Group_General +cui/source/options/optcolor.cxx:52 + enum (anonymous namespace)::Group Group_Basic +cui/source/options/optfltr.cxx:28 + enum MSFltrPg2_CheckBoxEntries Math +cui/source/options/optfltr.cxx:29 + enum MSFltrPg2_CheckBoxEntries Writer +cui/source/options/optfltr.cxx:30 + enum MSFltrPg2_CheckBoxEntries Calc +cui/source/options/optfltr.cxx:31 + enum MSFltrPg2_CheckBoxEntries Impress +cui/source/options/optfltr.cxx:33 + enum MSFltrPg2_CheckBoxEntries Visio +cui/source/options/optgenrl.cxx:50 + enum (anonymous namespace)::RowType Row_Company +cui/source/options/optgenrl.cxx:51 + enum (anonymous namespace)::RowType Row_Name +cui/source/options/optgenrl.cxx:52 + enum (anonymous namespace)::RowType Row_Name_Russian +cui/source/options/optgenrl.cxx:53 + enum (anonymous namespace)::RowType Row_Name_Eastern +cui/source/options/optgenrl.cxx:54 + enum (anonymous namespace)::RowType Row_Street +cui/source/options/optgenrl.cxx:55 + enum (anonymous namespace)::RowType Row_Street_Russian +cui/source/options/optgenrl.cxx:56 + enum (anonymous namespace)::RowType Row_City +cui/source/options/optgenrl.cxx:57 + enum (anonymous namespace)::RowType Row_City_US +cui/source/options/optgenrl.cxx:58 + enum (anonymous namespace)::RowType Row_Country +cui/source/options/optgenrl.cxx:59 + enum (anonymous namespace)::RowType Row_TitlePos +cui/source/options/optgenrl.cxx:60 + enum (anonymous namespace)::RowType Row_Phone +cui/source/options/optgenrl.cxx:61 + enum (anonymous namespace)::RowType Row_FaxMail +cui/source/options/optlingu.cxx:185 + enum (anonymous namespace)::EID_OPTIONS EID_SPELL_AUTO +cui/source/options/optlingu.cxx:186 + enum (anonymous namespace)::EID_OPTIONS EID_GRAMMAR_AUTO +cui/source/options/optlingu.cxx:187 + enum (anonymous namespace)::EID_OPTIONS EID_CAPITAL_WORDS +cui/source/options/optlingu.cxx:188 + enum (anonymous namespace)::EID_OPTIONS EID_WORDS_WITH_DIGITS +cui/source/options/optlingu.cxx:189 + enum (anonymous namespace)::EID_OPTIONS EID_SPELL_SPECIAL +cui/source/options/optlingu.cxx:193 + enum (anonymous namespace)::EID_OPTIONS EID_HYPH_AUTO +cui/source/options/optlingu.cxx:194 + enum (anonymous namespace)::EID_OPTIONS EID_HYPH_SPECIAL +cui/source/tabpages/autocdlg.cxx:327 + enum (anonymous namespace)::OfaAutoFmtOptions USE_REPLACE_TABLE +cui/source/tabpages/autocdlg.cxx:328 + enum (anonymous namespace)::OfaAutoFmtOptions CORR_UPPER +cui/source/tabpages/autocdlg.cxx:329 + enum (anonymous namespace)::OfaAutoFmtOptions BEGIN_UPPER +cui/source/tabpages/autocdlg.cxx:330 + enum (anonymous namespace)::OfaAutoFmtOptions BOLD_UNDERLINE +cui/source/tabpages/autocdlg.cxx:331 + enum (anonymous namespace)::OfaAutoFmtOptions DETECT_URL +cui/source/tabpages/autocdlg.cxx:332 + enum (anonymous namespace)::OfaAutoFmtOptions REPLACE_DASHES +cui/source/tabpages/autocdlg.cxx:333 + enum (anonymous namespace)::OfaAutoFmtOptions DEL_SPACES_AT_STT_END +cui/source/tabpages/autocdlg.cxx:334 + enum (anonymous namespace)::OfaAutoFmtOptions DEL_SPACES_BETWEEN_LINES +cui/source/tabpages/autocdlg.cxx:335 + enum (anonymous namespace)::OfaAutoFmtOptions IGNORE_DBLSPACE +cui/source/tabpages/autocdlg.cxx:336 + enum (anonymous namespace)::OfaAutoFmtOptions CORRECT_CAPS_LOCK +cui/source/tabpages/autocdlg.cxx:338 + enum (anonymous namespace)::OfaAutoFmtOptions INSERT_BORDER +cui/source/tabpages/autocdlg.cxx:339 + enum (anonymous namespace)::OfaAutoFmtOptions CREATE_TABLE +cui/source/tabpages/autocdlg.cxx:340 + enum (anonymous namespace)::OfaAutoFmtOptions REPLACE_STYLES +cui/source/tabpages/autocdlg.cxx:341 + enum (anonymous namespace)::OfaAutoFmtOptions DEL_EMPTY_NODE +cui/source/tabpages/autocdlg.cxx:342 + enum (anonymous namespace)::OfaAutoFmtOptions REPLACE_USER_COLL +cui/source/tabpages/autocdlg.cxx:1528 + enum (anonymous namespace)::OfaQuoteOptions ADD_NONBRK_SPACE +cui/source/tabpages/autocdlg.cxx:1529 + enum (anonymous namespace)::OfaQuoteOptions REPLACE_1ST +cui/source/tabpages/autocdlg.cxx:1530 + enum (anonymous namespace)::OfaQuoteOptions TRANSLITERATE_RTL +cui/source/tabpages/autocdlg.cxx:1531 + enum (anonymous namespace)::OfaQuoteOptions REPLACE_ANGLE_QUOTES +cui/source/tabpages/swpossizetabpage.cxx:101 + enum (anonymous namespace)::LB RelPagePrintAreaBottom +cui/source/tabpages/swpossizetabpage.cxx:102 + enum (anonymous namespace)::LB RelPagePrintAreaTop +dbaccess/source/core/dataaccess/databasedocument.hxx:163 + enum dbaccess::ODatabaseDocument::InitState NotInitialized +dbaccess/source/core/dataaccess/databasedocument.hxx:641 + enum dbaccess::DocumentGuard::InitMethod_ InitMethod +dbaccess/source/core/dataaccess/databasedocument.hxx:647 + enum dbaccess::DocumentGuard::DefaultMethod_ DefaultMethod +dbaccess/source/core/dataaccess/databasedocument.hxx:653 + enum dbaccess::DocumentGuard::MethodUsedDuringInit_ MethodUsedDuringInit +dbaccess/source/core/dataaccess/databasedocument.hxx:659 + enum dbaccess::DocumentGuard::MethodWithoutInit_ MethodWithoutInit +dbaccess/source/core/inc/definitioncontainer.hxx:103 + enum dbaccess::ODefinitionContainer::ListenerType ContainerListemers +dbaccess/source/core/inc/ModelImpl.hxx:111 + enum dbaccess::ODatabaseModelImpl::EmbeddedMacros eDocumentWideMacros +dbaccess/source/core/inc/objectnameapproval.hxx:49 + enum dbaccess::ObjectNameApproval::ObjectType TypeTable +dbaccess/source/core/inc/SingleSelectQueryComposer.hxx:72 + enum dbaccess::OSingleSelectQueryComposer::EColumnType GroupByColumns +dbaccess/source/core/inc/SingleSelectQueryComposer.hxx:73 + enum dbaccess::OSingleSelectQueryComposer::EColumnType OrderColumns +dbaccess/source/filter/xml/xmlDataSource.hxx:32 + enum dbaxml::OXMLDataSource::UsedFor eDataSource +dbaccess/source/ui/app/AppView.hxx:72 + enum dbaui::OApplicationView::ChildFocusState PANELSWAP +dbaccess/source/ui/dlg/ConnectionHelper.hxx:32 + enum dbaui::IS_PATH_EXIST PATH_EXIST +dbaccess/source/ui/inc/dbadmin.hxx:104 + enum dbaui::ODbAdminDialog::ApplyResult AR_KEEP +dbaccess/source/ui/inc/dsmeta.hxx:40 + enum dbaui::AuthenticationMode AuthPwd +dbaccess/source/ui/inc/QEnumTypes.hxx:26 + enum dbaui::EOrderDir ORDER_ASC +dbaccess/source/ui/inc/QEnumTypes.hxx:27 + enum dbaui::EOrderDir ORDER_DESC +dbaccess/source/ui/inc/QEnumTypes.hxx:49 + enum dbaui::ETableFieldType TAB_NORMAL_FIELD +dbaccess/source/ui/inc/QEnumTypes.hxx:50 + enum dbaui::ETableFieldType TAB_PRIMARY_FIELD +dbaccess/source/ui/inc/QueryDesignView.hxx:48 + enum dbaui::SqlParseError eIllegalJoinCondition +dbaccess/source/ui/inc/QueryDesignView.hxx:61 + enum dbaui::OQueryDesignView::ChildFocusState TABLEVIEW +dbaccess/source/ui/inc/WCopyTable.hxx:224 + enum dbaui::OCopyTableWizard::Wizard_Button_Style WIZARD_PREV +dbaccess/source/ui/tabledesign/TableFieldDescWin.hxx:37 + enum dbaui::OTableFieldDescWin::ChildFocusState HELP +desktop/inc/app.hxx:65 + enum desktop::Desktop::BootstrapStatus BS_OK +desktop/source/app/officeipcthread.cxx:775 + enum PipeMode PIPEMODE_CONNECTED +desktop/source/app/officeipcthread.hxx:83 + enum desktop::RequestHandler::State Starting +desktop/source/app/userinstall.hxx:32 + enum desktop::userinstall::Status ERROR_OTHER +desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx:237 + enum dp_gui::ExtensionCmdQueue::Thread::Input START +desktop/source/deployment/inc/dp_update.hxx:47 + enum dp_misc::UPDATE_SOURCE UPDATE_SOURCE_ONLINE +desktop/source/deployment/registry/component/dp_component.cxx:111 + enum dp_registry::backend::component::(anonymous namespace)::BackendImpl::ComponentPackageImpl::Reg NotRegistered +desktop/source/deployment/registry/component/dp_component.cxx:243 + enum dp_registry::backend::component::(anonymous namespace)::BackendImpl::RcItem RCITEM_COMPONENTS +desktop/source/deployment/registry/inc/dp_backend.h:215 + enum dp_registry::backend::PackageRegistryBackend::Context Document +desktop/source/deployment/registry/inc/dp_backend.h:215 + enum dp_registry::backend::PackageRegistryBackend::Context Tmp +desktop/source/deployment/registry/inc/dp_backend.h:215 + enum dp_registry::backend::PackageRegistryBackend::Context Unknown +desktop/source/lib/init.cxx:4914 + enum (anonymous namespace)::UndoOrRedo REDO +desktop/source/lib/init.cxx:6150 + enum (anonymous at /home/noel/libo2/desktop/source/lib/init.cxx:6147:5) FULL_INIT +desktop/source/migration/services/oo3extensionmigration.hxx:62 + enum migration::OO3ExtensionMigration::ScanResult SCANRESULT_DONTMIGRATE_EXTENSION +desktop/unx/source/start.c:178 + int ProgressExit +desktop/unx/source/start.c:178 + int ProgressRestart +editeng/inc/editdoc.hxx:339 + enum AsianCompressionFlags Normal +editeng/source/editeng/impedit.hxx:1134 + enum ImpEditEngine::CallbackResult Continue +editeng/source/editeng/impedit.hxx:1151 + enum ImpEditEngine::IterFlag none +editeng/source/editeng/impedit.hxx:1152 + enum ImpEditEngine::IterFlag inclILS +editeng/source/items/paraitem.cxx:70 + enum (anonymous namespace)::SvxSpecialLineSpace User +editeng/source/items/paraitem.cxx:74 + enum (anonymous namespace)::SvxSpecialLineSpace End +editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx:24 + enum SvXMLAutoCorrectToken NAMESPACE +editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx:25 + enum SvXMLAutoCorrectToken ABBREVIATED_NAME +editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx:28 + enum SvXMLAutoCorrectToken NAME +emfio/inc/mtftools.hxx:50 + enum emfio::BkMode OPAQUE +emfio/inc/mtftools.hxx:80 + enum emfio::WMFRasterOp Black +emfio/inc/mtftools.hxx:84 + enum emfio::WMFRasterOp CopyPen +extensions/source/propctrlr/browserlistbox.cxx:126 + enum pcr::PropertyControlContext_Impl::NotificationMode eAsynchronously +extensions/source/propctrlr/eformshelper.hxx:180 + enum pcr::EFormsHelper::ModelElementType Binding +extensions/source/propctrlr/formcomponenthandler.hxx:46 + enum pcr::ComponentClassification eUnknown +extensions/source/propctrlr/formlinkdialog.cxx:76 + enum pcr::FieldLinkRow::LinkParticipant eMasterField +filter/source/config/cache/filtercache.hxx:139 + enum filter::config::FilterCache::EItemFlushState E_ITEM_UNCHANGED +filter/source/xmlfilteradaptor/XmlFilterAdaptor.hxx:34 + enum FilterType FILTER_IMPORT +filter/source/xsltdialog/typedetectionimport.hxx:47 + enum ImportState e_Unknown +forms/source/inc/FormComponent.hxx:556 + enum frm::OBoundControlModel::ValueChangeInstigator eOther +forms/source/richtext/rtattributes.hxx:39 + enum frm::AttributeCheckState eIndetermined +forms/source/solar/inc/navtoolbar.hxx:38 + enum frm::NavigationToolBar::ImageSize eSmall +forms/source/xforms/submission/submission.hxx:114 + enum CSubmission::SubmissionResult UNKNOWN_ERROR +fpicker/source/office/fpinteraction.hxx:46 + enum svt::OFilePickerInteractionHandler::EInterceptedInteractions E_NOINTERCEPTION +fpicker/source/office/fpsmartcontent.hxx:58 + enum svt::SmartContent::Type Document +fpicker/source/office/fpsmartcontent.hxx:96 + enum svt::SmartContent::InteractionHandlerType IHT_OWN +framework/inc/dispatch/closedispatcher.hxx:66 + enum framework::CloseDispatcher::EOperation E_CLOSE_WIN +framework/inc/jobs/jobdata.hxx:50 + enum framework::JobData::EMode E_UNKNOWN_MODE +framework/inc/jobs/jobdata.hxx:54 + enum framework::JobData::EMode E_SERVICE +framework/inc/jobs/jobdata.hxx:66 + enum framework::JobData::EEnvironment E_UNKNOWN_ENVIRONMENT +framework/inc/jobs/jobresult.hxx:52 + enum framework::JobResult::EParts E_NOPART +framework/inc/jobs/jobresult.hxx:53 + enum framework::JobResult::EParts E_ARGUMENTS +framework/inc/jobs/jobresult.hxx:54 + enum framework::JobResult::EParts E_DEACTIVATE +framework/inc/jobs/jobresult.hxx:55 + enum framework::JobResult::EParts E_DISPATCHRESULT +framework/inc/uielement/menubarmerger.hxx:47 + enum framework::RPResultInfo RP_POPUPMENU_NOT_FOUND +framework/inc/uielement/menubarmerger.hxx:48 + enum framework::RPResultInfo RP_MENUITEM_NOT_FOUND +framework/inc/uielement/togglebuttontoolbarcontroller.hxx:47 + enum framework::ToggleButtonToolbarController::Style ToggleDropDownButton +framework/inc/xml/imagesdocumenthandler.hxx:58 + enum framework::OReadImagesDocumentHandler::Image_XML_Namespace IMG_NS_XLINK +framework/inc/xml/statusbardocumenthandler.hxx:60 + enum framework::OReadStatusBarDocumentHandler::StatusBar_XML_Namespace SB_NS_XLINK +framework/inc/xml/toolboxdocumenthandler.hxx:59 + enum framework::OReadToolBoxDocumentHandler::ToolBox_XML_Namespace TB_NS_XLINK +framework/source/fwe/classes/addonsoptions.cxx:241 + enum framework::AddonsOptions_Impl::ImageSize IMGSIZE_SMALL +framework/source/fwe/classes/addonsoptions.cxx:242 + enum framework::AddonsOptions_Impl::ImageSize IMGSIZE_BIG +framework/source/inc/loadenv/loadenv.hxx:91 + enum framework::LoadEnv::EContentType E_CAN_BE_HANDLED +framework/source/inc/loadenv/loadenvexception.hxx:54 + enum framework::LoadEnvException::EIDs ID_INVALID_ENVIRONMENT +framework/source/inc/loadenv/loadenvexception.hxx:57 + enum framework::LoadEnvException::EIDs ID_NO_TARGET_FOUND +framework/source/inc/loadenv/loadenvexception.hxx:60 + enum framework::LoadEnvException::EIDs ID_COULD_NOT_REACTIVATE_CONTROLLER +framework/source/inc/loadenv/loadenvexception.hxx:65 + enum framework::LoadEnvException::EIDs ID_STILL_RUNNING +framework/source/inc/loadenv/loadenvexception.hxx:70 + enum framework::LoadEnvException::EIDs ID_GENERAL_ERROR +framework/source/layoutmanager/toolbarlayoutmanager.hxx:55 + enum framework::ToolbarLayoutManager::PreviewFrameDetection PREVIEWFRAME_NO +framework/source/services/autorecovery.cxx:169 + enum (anonymous namespace)::DocState Unknown +framework/source/services/autorecovery.cxx:177 + enum (anonymous namespace)::DocState TrySave +framework/source/services/autorecovery.cxx:188 + enum (anonymous namespace)::DocState Succeeded +framework/source/services/autorecovery.cxx:248 + enum (anonymous namespace)::AutoRecovery::EFailureSafeResult E_COPIED +framework/source/services/autorecovery.cxx:249 + enum (anonymous namespace)::AutoRecovery::EFailureSafeResult E_ORIGINAL_FILE_MISSING +framework/source/services/autorecovery.cxx:250 + enum (anonymous namespace)::AutoRecovery::EFailureSafeResult E_WRONG_TARGET_PATH +framework/source/services/substitutepathvars.cxx:54 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_INST +framework/source/services/substitutepathvars.cxx:55 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_PROG +framework/source/services/substitutepathvars.cxx:56 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_USER +framework/source/services/substitutepathvars.cxx:58 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_HOME +framework/source/services/substitutepathvars.cxx:59 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_TEMP +framework/source/services/substitutepathvars.cxx:61 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_USERNAME +framework/source/services/substitutepathvars.cxx:62 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_LANGID +framework/source/services/substitutepathvars.cxx:63 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_VLANG +framework/source/services/substitutepathvars.cxx:64 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_INSTPATH +framework/source/services/substitutepathvars.cxx:65 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_PROGPATH +framework/source/services/substitutepathvars.cxx:66 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_USERPATH +framework/source/services/substitutepathvars.cxx:67 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_INSTURL +framework/source/services/substitutepathvars.cxx:68 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_PROGURL +framework/source/services/substitutepathvars.cxx:69 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_USERURL +framework/source/services/substitutepathvars.cxx:72 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_BASEINSTURL +framework/source/services/substitutepathvars.cxx:73 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_USERDATAURL +framework/source/services/substitutepathvars.cxx:74 + enum (anonymous namespace)::PreDefVariable PREDEFVAR_BRANDBASEURL +framework/source/uiconfiguration/moduleuiconfigurationmanager.cxx:140 + enum (anonymous namespace)::ModuleUIConfigurationManager::Layer LAYER_DEFAULT +framework/source/uiconfiguration/moduleuiconfigurationmanager.cxx:142 + enum (anonymous namespace)::ModuleUIConfigurationManager::Layer LAYER_COUNT +framework/source/uiconfiguration/windowstateconfiguration.cxx:142 + enum (anonymous namespace)::ConfigurationAccess_WindowState::(anonymous at /home/noel/libo2/framework/source/uiconfiguration/windowstateconfiguration.cxx:140:9) WINDOWSTATE_MASK_DOCKINGAREA +framework/source/uiconfiguration/windowstateconfiguration.cxx:143 + enum (anonymous namespace)::ConfigurationAccess_WindowState::(anonymous at /home/noel/libo2/framework/source/uiconfiguration/windowstateconfiguration.cxx:140:9) WINDOWSTATE_MASK_POS +framework/source/uiconfiguration/windowstateconfiguration.cxx:144 + enum (anonymous namespace)::ConfigurationAccess_WindowState::(anonymous at /home/noel/libo2/framework/source/uiconfiguration/windowstateconfiguration.cxx:140:9) WINDOWSTATE_MASK_SIZE +framework/source/uiconfiguration/windowstateconfiguration.cxx:145 + enum (anonymous namespace)::ConfigurationAccess_WindowState::(anonymous at /home/noel/libo2/framework/source/uiconfiguration/windowstateconfiguration.cxx:140:9) WINDOWSTATE_MASK_UINAME +framework/source/uiconfiguration/windowstateconfiguration.cxx:146 + enum (anonymous namespace)::ConfigurationAccess_WindowState::(anonymous at /home/noel/libo2/framework/source/uiconfiguration/windowstateconfiguration.cxx:140:9) WINDOWSTATE_MASK_INTERNALSTATE +framework/source/uiconfiguration/windowstateconfiguration.cxx:147 + enum (anonymous namespace)::ConfigurationAccess_WindowState::(anonymous at /home/noel/libo2/framework/source/uiconfiguration/windowstateconfiguration.cxx:140:9) WINDOWSTATE_MASK_STYLE +framework/source/uiconfiguration/windowstateconfiguration.cxx:148 + enum (anonymous namespace)::ConfigurationAccess_WindowState::(anonymous at /home/noel/libo2/framework/source/uiconfiguration/windowstateconfiguration.cxx:140:9) WINDOWSTATE_MASK_DOCKPOS +framework/source/uiconfiguration/windowstateconfiguration.cxx:149 + enum (anonymous namespace)::ConfigurationAccess_WindowState::(anonymous at /home/noel/libo2/framework/source/uiconfiguration/windowstateconfiguration.cxx:140:9) WINDOWSTATE_MASK_DOCKSIZE +helpcompiler/inc/BasCodeTagger.hxx:36 + enum BasicCodeTagger::TaggerException NULL_DOCUMENT +helpcompiler/inc/HelpCompiler.hxx:51 + enum fs::convert native +i18nlangtag/source/languagetag/languagetag.cxx:348 + enum LanguageTagImpl::Extraction EXTRACTED_X +i18nlangtag/source/languagetag/languagetag.cxx:349 + enum LanguageTagImpl::Extraction EXTRACTED_X_JOKER +i18nlangtag/source/languagetag/languagetag.cxx:350 + enum LanguageTagImpl::Extraction EXTRACTED_KNOWN_BAD +i18npool/inc/cclass_unicode.hxx:38 + enum ParserFlags ILLEGAL +i18npool/inc/cclass_unicode.hxx:47 + enum ParserFlags WORD_SEP +idl/inc/types.hxx:51 + enum MetaTypeType Enum +idl/inc/types.hxx:51 + enum MetaTypeType Interface +idlc/inc/idlctypes.hxx:63 + enum ParseState PS_SingletonDeclSeen +idlc/inc/idlctypes.hxx:74 + enum ParseState PS_ServiceQsSeen +idlc/inc/idlctypes.hxx:80 + enum ParseState PS_SingletonSeen +idlc/inc/idlctypes.hxx:81 + enum ParseState PS_SingletonIDSeen +idlc/inc/idlctypes.hxx:82 + enum ParseState PS_SingletonSqSeen +idlc/inc/idlctypes.hxx:83 + enum ParseState PS_SingletonQsSeen +idlc/inc/idlctypes.hxx:84 + enum ParseState PS_SingletonBodySeen +include/avmedia/mediaitem.hxx:50 + enum AVMediaSetMask ALL +include/basegfx/DrawCommands.hxx:33 + enum gfx::DrawCommandType Root +include/basegfx/polygon/b2dpolygontools.hxx:48 + enum CutFlagValue DEFAULT +include/basegfx/utils/common.hxx:28 + enum basegfx::Axis2D Y +include/basic/basmgr.hxx:43 + enum BasicErrorReason OPENLIBSTORAGE +include/basic/basmgr.hxx:44 + enum BasicErrorReason OPENMGRSTREAM +include/basic/basmgr.hxx:45 + enum BasicErrorReason OPENLIBSTREAM +include/basic/basmgr.hxx:46 + enum BasicErrorReason LIBNOTFOUND +include/basic/basmgr.hxx:47 + enum BasicErrorReason STORAGENOTFOUND +include/basic/basmgr.hxx:48 + enum BasicErrorReason BASICLOADERROR +include/basic/basmgr.hxx:49 + enum BasicErrorReason STDLIB +include/basic/sbdef.hxx:50 + enum BasicDebugFlags Continue +include/codemaker/commoncpp.hxx:52 + enum codemaker::cpp::IdentifierTranslationMode NonGlobal +include/comphelper/componentbase.hxx:110 + enum comphelper::ComponentMethodGuard::MethodType Default +include/comphelper/configurationhelper.hxx:43 + enum comphelper::EConfigurationModes Standard +include/comphelper/docpasswordhelper.hxx:39 + enum comphelper::DocPasswordVerifierResult Abort +include/comphelper/lok.hxx:78 + enum comphelper::LibreOfficeKit::Compat none +include/comphelper/lok.hxx:79 + enum comphelper::LibreOfficeKit::Compat scNoGridBackground +include/comphelper/lok.hxx:80 + enum comphelper::LibreOfficeKit::Compat scPrintTwipsMsgs +include/connectivity/parameters.hxx:67 + enum dbtools::ParameterManager::ParameterClassification LinkedByParamName +include/connectivity/sqliterator.hxx:51 + enum connectivity::TraversalParts All +include/connectivity/sqlnode.hxx:223 + enum connectivity::OSQLParseNode::Rule null_predicate_part_2 +include/desktop/crashreport.hxx:47 + CrashReporter::tAddKeyHandling AddItem +include/desktop/crashreport.hxx:47 + CrashReporter::tAddKeyHandling Create +include/desktop/crashreport.hxx:47 + CrashReporter::tAddKeyHandling Write +include/desktop/exithelper.h:28 + enum EExitCodes EXITHELPER_FATAL_ERROR +include/desktop/exithelper.h:30 + enum EExitCodes EXITHELPER_CRASH_WITH_RESTART +include/desktop/exithelper.h:32 + enum EExitCodes EXITHELPER_NORMAL_RESTART +include/drawinglayer/primitive2d/helplineprimitive2d.hxx:39 + enum drawinglayer::primitive2d::HelplineStyle2D Point +include/drawinglayer/primitive2d/svggradientprimitive2d.hxx:76 + enum drawinglayer::primitive2d::SpreadMethod Repeat +include/drawinglayer/primitive2d/texthierarchyprimitive2d.hxx:113 + enum drawinglayer::primitive2d::FieldType FIELD_TYPE_COMMON +include/editeng/AccessibleContextBase.hxx:62 + enum accessibility::AccessibleContextBase::StringOrigin ManuallySet +include/editeng/AccessibleContextBase.hxx:63 + enum accessibility::AccessibleContextBase::StringOrigin FromShape +include/editeng/AccessibleContextBase.hxx:64 + enum accessibility::AccessibleContextBase::StringOrigin AutomaticallyCreated +include/editeng/boxitem.hxx:150 + enum SvxBoxInfoItemValidFlags VERT +include/editeng/boxitem.hxx:151 + enum SvxBoxInfoItemValidFlags DISTANCE +include/editeng/boxitem.hxx:152 + enum SvxBoxInfoItemValidFlags DISABLE +include/editeng/boxitem.hxx:153 + enum SvxBoxInfoItemValidFlags ALL +include/editeng/editdata.hxx:36 + enum EESelectionMode Std +include/editeng/editeng.hxx:129 + enum GetAttribsFlags ALL +include/editeng/editobj.hxx:55 + enum TextRotation BOTTOMTOTOP +include/editeng/editstat.hxx:43 + enum EEControlBits MARKFIELDS +include/editeng/editstat.hxx:119 + enum SpellCallbackCommand WORDLANGUAGE +include/editeng/editstat.hxx:120 + enum SpellCallbackCommand PARALANGUAGE +include/editeng/editview.hxx:86 + enum ScrollRangeCheck NoNegative +include/editeng/flditem.hxx:311 + enum SvxFileType Var +include/editeng/flditem.hxx:353 + enum SvxAuthorType Var +include/editeng/hangulhanja.hxx:84 + enum editeng::HangulHanjaConversion::ConversionDirection eHanjaToHangul +include/editeng/numitem.hxx:232 + enum SvxNumRuleFlags CHAR_STYLE +include/editeng/numitem.hxx:233 + enum SvxNumRuleFlags BULLET_REL_SIZE +include/editeng/numitem.hxx:234 + enum SvxNumRuleFlags BULLET_COLOR +include/editeng/numitem.hxx:235 + enum SvxNumRuleFlags NO_NUMBERS +include/editeng/numitem.hxx:236 + enum SvxNumRuleFlags ENABLE_LINKED_BMP +include/editeng/numitem.hxx:237 + enum SvxNumRuleFlags ENABLE_EMBEDDED_BMP +include/editeng/numitem.hxx:247 + enum SvxNumRuleType OUTLINE_NUMBERING +include/editeng/numitem.hxx:248 + enum SvxNumRuleType PRESENTATION_NUMBERING +include/editeng/outliner.hxx:99 + enum ParaFlag SETBULLETTEXT +include/editeng/outliner.hxx:190 + enum OutlinerView::MouseTarget Outside +include/editeng/svxrtf.hxx:207 + enum SvxRTFParser::RTF_CharTypeDef NOTDEF_CHARTYPE +include/filter/msfilter/msdffimp.hxx:376 + enum DffSeekToContentMode SEEK_FROM_CURRENT +include/filter/msfilter/ww8fields.hxx:30 + enum ww::eField eXE +include/filter/msfilter/ww8fields.hxx:32 + enum ww::eField eSET +include/filter/msfilter/ww8fields.hxx:35 + enum ww::eField eTC +include/filter/msfilter/ww8fields.hxx:36 + enum ww::eField eSTYLEREF +include/filter/msfilter/ww8fields.hxx:37 + enum ww::eField eRD +include/filter/msfilter/ww8fields.hxx:38 + enum ww::eField eSEQ +include/filter/msfilter/ww8fields.hxx:40 + enum ww::eField eINFO +include/filter/msfilter/ww8fields.hxx:41 + enum ww::eField eTITLE +include/filter/msfilter/ww8fields.hxx:42 + enum ww::eField eSUBJECT +include/filter/msfilter/ww8fields.hxx:43 + enum ww::eField eAUTHOR +include/filter/msfilter/ww8fields.hxx:44 + enum ww::eField eKEYWORDS +include/filter/msfilter/ww8fields.hxx:45 + enum ww::eField eCOMMENTS +include/filter/msfilter/ww8fields.hxx:46 + enum ww::eField eLASTSAVEDBY +include/filter/msfilter/ww8fields.hxx:50 + enum ww::eField eREVNUM +include/filter/msfilter/ww8fields.hxx:51 + enum ww::eField eEDITTIME +include/filter/msfilter/ww8fields.hxx:52 + enum ww::eField eNUMPAGES +include/filter/msfilter/ww8fields.hxx:53 + enum ww::eField eNUMWORDS +include/filter/msfilter/ww8fields.hxx:54 + enum ww::eField eNUMCHARS +include/filter/msfilter/ww8fields.hxx:55 + enum ww::eField eFILENAME +include/filter/msfilter/ww8fields.hxx:56 + enum ww::eField eTEMPLATE +include/filter/msfilter/ww8fields.hxx:61 + enum ww::eField eQUOTE +include/filter/msfilter/ww8fields.hxx:64 + enum ww::eField eASK +include/filter/msfilter/ww8fields.hxx:65 + enum ww::eField eFILLIN +include/filter/msfilter/ww8fields.hxx:66 + enum ww::eField eMERGEDATA +include/filter/msfilter/ww8fields.hxx:67 + enum ww::eField eNEXT +include/filter/msfilter/ww8fields.hxx:68 + enum ww::eField eNEXTIF +include/filter/msfilter/ww8fields.hxx:69 + enum ww::eField eSKIPIF +include/filter/msfilter/ww8fields.hxx:70 + enum ww::eField eMERGEREC +include/filter/msfilter/ww8fields.hxx:71 + enum ww::eField eDDEREF +include/filter/msfilter/ww8fields.hxx:72 + enum ww::eField eDDEAUTOREF +include/filter/msfilter/ww8fields.hxx:73 + enum ww::eField eGLOSSREF +include/filter/msfilter/ww8fields.hxx:74 + enum ww::eField ePRINT +include/filter/msfilter/ww8fields.hxx:76 + enum ww::eField eGOTOBUTTON +include/filter/msfilter/ww8fields.hxx:77 + enum ww::eField eMACROBUTTON +include/filter/msfilter/ww8fields.hxx:78 + enum ww::eField eAUTONUMOUT +include/filter/msfilter/ww8fields.hxx:79 + enum ww::eField eAUTONUMLGL +include/filter/msfilter/ww8fields.hxx:80 + enum ww::eField eAUTONUM +include/filter/msfilter/ww8fields.hxx:81 + enum ww::eField eINCLUDETIFF +include/filter/msfilter/ww8fields.hxx:82 + enum ww::eField eLINK +include/filter/msfilter/ww8fields.hxx:83 + enum ww::eField eSYMBOL +include/filter/msfilter/ww8fields.hxx:84 + enum ww::eField eEMBED +include/filter/msfilter/ww8fields.hxx:85 + enum ww::eField eMERGEFIELD +include/filter/msfilter/ww8fields.hxx:86 + enum ww::eField eUSERNAME +include/filter/msfilter/ww8fields.hxx:87 + enum ww::eField eUSERINITIALS +include/filter/msfilter/ww8fields.hxx:88 + enum ww::eField eUSERADDRESS +include/filter/msfilter/ww8fields.hxx:89 + enum ww::eField eBARCODE +include/filter/msfilter/ww8fields.hxx:90 + enum ww::eField eDOCVARIABLE +include/filter/msfilter/ww8fields.hxx:91 + enum ww::eField eSECTION +include/filter/msfilter/ww8fields.hxx:92 + enum ww::eField eSECTIONPAGES +include/filter/msfilter/ww8fields.hxx:93 + enum ww::eField eINCLUDEPICTURE +include/filter/msfilter/ww8fields.hxx:95 + enum ww::eField eFILESIZE +include/filter/msfilter/ww8fields.hxx:99 + enum ww::eField eTOA +include/filter/msfilter/ww8fields.hxx:100 + enum ww::eField eTA +include/filter/msfilter/ww8fields.hxx:101 + enum ww::eField eMERGESEQ +include/filter/msfilter/ww8fields.hxx:102 + enum ww::eField eMACRO +include/filter/msfilter/ww8fields.hxx:103 + enum ww::eField ePRIVATE +include/filter/msfilter/ww8fields.hxx:104 + enum ww::eField eDATABASE +include/filter/msfilter/ww8fields.hxx:106 + enum ww::eField eCOMPARE +include/filter/msfilter/ww8fields.hxx:107 + enum ww::eField ePLUGIN +include/filter/msfilter/ww8fields.hxx:108 + enum ww::eField eSUBSCRIBER +include/filter/msfilter/ww8fields.hxx:110 + enum ww::eField eADVANCE +include/filter/msfilter/ww8fields.hxx:111 + enum ww::eField eDOCPROPERTY +include/filter/msfilter/ww8fields.hxx:116 + enum ww::eField eLISTNUM +include/filter/msfilter/ww8fields.hxx:117 + enum ww::eField eHTMLCONTROL +include/filter/msfilter/ww8fields.hxx:118 + enum ww::eField eBIDIOUTLINE +include/filter/msfilter/ww8fields.hxx:119 + enum ww::eField eADDRESSBLOCK +include/filter/msfilter/ww8fields.hxx:120 + enum ww::eField eGREETINGLINE +include/formula/formula.hxx:45 + enum formula::FormulaDlgMode Edit +include/formula/tokenarray.hxx:62 + enum ScRecalcMode ONLOAD_MUST +include/formula/tokenarray.hxx:64 + enum ScRecalcMode ONLOAD_LENIENT +include/formula/tokenarray.hxx:166 + enum formula::FormulaTokenArrayReferencesIterator::Dummy Flag +include/formula/tokenarray.hxx:258 + enum formula::FormulaTokenArray::ReplaceMode CODE_ONLY +include/formula/vectortoken.hxx:42 + enum formula::VectorRefArray::InitInvalid Invalid +include/framework/desktop.hxx:59 + enum framework::ELoadState E_NOTSET +include/framework/desktop.hxx:60 + enum framework::ELoadState E_SUCCESSFUL +include/framework/desktop.hxx:61 + enum framework::ELoadState E_FAILED +include/framework/framelistanalyzer.hxx:44 + enum FrameAnalyzerFlags All +include/framework/transactionmanager.hxx:79 + enum framework::EExceptionMode E_SOFTEXCEPTIONS +include/i18nutil/casefolding.hxx:35 + enum MappingType ToUpper +include/i18nutil/casefolding.hxx:36 + enum MappingType ToLower +include/i18nutil/casefolding.hxx:37 + enum MappingType ToTitle +include/i18nutil/casefolding.hxx:38 + enum MappingType SimpleFolding +include/i18nutil/casefolding.hxx:39 + enum MappingType FullFolding +include/i18nutil/transliteration.hxx:37 + enum TransliterationFlags HALFWIDTH_FULLWIDTH +include/i18nutil/transliteration.hxx:39 + enum TransliterationFlags FULLWIDTH_HALFWIDTH +include/i18nutil/transliteration.hxx:41 + enum TransliterationFlags KATAKANA_HIRAGANA +include/i18nutil/transliteration.hxx:43 + enum TransliterationFlags HIRAGANA_KATAKANA +include/i18nutil/transliteration.hxx:75 + enum TransliterationFlags NON_IGNORE_MASK +include/i18nutil/transliteration.hxx:76 + enum TransliterationFlags IGNORE_MASK +include/i18nutil/transliteration.hxx:122 + enum TransliterationFlags IGNORE_DIACRITICS_CTL +include/i18nutil/transliteration.hxx:124 + enum TransliterationFlags IGNORE_KASHIDA_CTL +include/jvmfwk/framework.hxx:181 + enum javaFrameworkError JFW_E_ERROR +include/jvmfwk/framework.hxx:191 + enum javaFrameworkError JFW_E_CONFIGURATION +include/LibreOfficeKit/LibreOfficeKitEnums.h:55 + LibreOfficeKitSelectionType LOK_SELTYPE_TEXT +include/LibreOfficeKit/LibreOfficeKitEnums.h:57 + LibreOfficeKitSelectionType LOK_SELTYPE_COMPLEX +include/linguistic/misc.hxx:62 + enum linguistic::DictionaryError NOT_EXISTS +include/linguistic/misc.hxx:69 + enum linguistic::CapType NOCAP +include/o3tl/unit_conversion.hxx:27 + enum o3tl::Length mm100 +include/o3tl/unit_conversion.hxx:28 + enum o3tl::Length mm10 +include/o3tl/unit_conversion.hxx:29 + enum o3tl::Length mm +include/o3tl/unit_conversion.hxx:30 + enum o3tl::Length cm +include/o3tl/unit_conversion.hxx:31 + enum o3tl::Length m +include/o3tl/unit_conversion.hxx:32 + enum o3tl::Length km +include/o3tl/unit_conversion.hxx:33 + enum o3tl::Length emu +include/o3tl/unit_conversion.hxx:34 + enum o3tl::Length twip +include/o3tl/unit_conversion.hxx:35 + enum o3tl::Length pt +include/o3tl/unit_conversion.hxx:36 + enum o3tl::Length pc +include/o3tl/unit_conversion.hxx:37 + enum o3tl::Length in1000 +include/o3tl/unit_conversion.hxx:38 + enum o3tl::Length in100 +include/o3tl/unit_conversion.hxx:39 + enum o3tl::Length in10 +include/o3tl/unit_conversion.hxx:40 + enum o3tl::Length in +include/o3tl/unit_conversion.hxx:41 + enum o3tl::Length ft +include/o3tl/unit_conversion.hxx:42 + enum o3tl::Length mi +include/o3tl/unit_conversion.hxx:43 + enum o3tl::Length master +include/o3tl/unit_conversion.hxx:44 + enum o3tl::Length px +include/o3tl/unit_conversion.hxx:45 + enum o3tl::Length ch +include/o3tl/unit_conversion.hxx:46 + enum o3tl::Length line +include/oox/crypto/AgileEngine.hxx:73 + enum oox::crypto::AgileEncryptionPreset AES_256_SHA512 +include/oox/drawingml/shape.hxx:256 + enum oox::drawingml::Shape::FrameType FRAMETYPE_TABLE +include/oox/ole/axcontrol.hxx:164 + enum oox::ole::ApiControlType API_CONTROL_TABSTRIP +include/oox/ole/axcontrol.hxx:185 + enum oox::ole::ApiDefaultStateMode API_DEFAULTSTATE_SHORT +include/oox/ppt/pptfilterhelpers.hxx:40 + enum oox::ppt::AnimationAttributeEnum STYLEFONTFAMILY +include/oox/token/relationship.hxx:21 + enum oox::Relationship ACTIVEXCONTROLBINARY +include/oox/token/relationship.hxx:22 + enum oox::Relationship CHART +include/oox/token/relationship.hxx:23 + enum oox::Relationship CHARTUSERSHAPES +include/oox/token/relationship.hxx:24 + enum oox::Relationship COMMENTS +include/oox/token/relationship.hxx:25 + enum oox::Relationship COMMENTAUTHORS +include/oox/token/relationship.hxx:26 + enum oox::Relationship COMMENTSEXTENDED +include/oox/token/relationship.hxx:27 + enum oox::Relationship CONTROL +include/oox/token/relationship.hxx:28 + enum oox::Relationship CTRLPROP +include/oox/token/relationship.hxx:29 + enum oox::Relationship CUSTOMXML +include/oox/token/relationship.hxx:30 + enum oox::Relationship CUSTOMXMLPROPS +include/oox/token/relationship.hxx:31 + enum oox::Relationship DIAGRAMCOLORS +include/oox/token/relationship.hxx:32 + enum oox::Relationship DIAGRAMDATA +include/oox/token/relationship.hxx:33 + enum oox::Relationship DIAGRAMDRAWING +include/oox/token/relationship.hxx:34 + enum oox::Relationship DIAGRAMLAYOUT +include/oox/token/relationship.hxx:35 + enum oox::Relationship DIAGRAMQUICKSTYLE +include/oox/token/relationship.hxx:36 + enum oox::Relationship DRAWING +include/oox/token/relationship.hxx:37 + enum oox::Relationship ENDNOTES +include/oox/token/relationship.hxx:38 + enum oox::Relationship EXTERNALLINKPATH +include/oox/token/relationship.hxx:39 + enum oox::Relationship FONT +include/oox/token/relationship.hxx:40 + enum oox::Relationship FONTTABLE +include/oox/token/relationship.hxx:41 + enum oox::Relationship FOOTER +include/oox/token/relationship.hxx:42 + enum oox::Relationship FOOTNOTES +include/oox/token/relationship.hxx:43 + enum oox::Relationship GLOSSARYDOCUMENT +include/oox/token/relationship.hxx:44 + enum oox::Relationship HDPHOTO +include/oox/token/relationship.hxx:45 + enum oox::Relationship HEADER +include/oox/token/relationship.hxx:46 + enum oox::Relationship HYPERLINK +include/oox/token/relationship.hxx:47 + enum oox::Relationship IMAGE +include/oox/token/relationship.hxx:48 + enum oox::Relationship MEDIA +include/oox/token/relationship.hxx:49 + enum oox::Relationship NOTESMASTER +include/oox/token/relationship.hxx:50 + enum oox::Relationship NOTESSLIDE +include/oox/token/relationship.hxx:51 + enum oox::Relationship NUMBERING +include/oox/token/relationship.hxx:52 + enum oox::Relationship OFFICEDOCUMENT +include/oox/token/relationship.hxx:53 + enum oox::Relationship OLEOBJECT +include/oox/token/relationship.hxx:54 + enum oox::Relationship PACKAGE +include/oox/token/relationship.hxx:55 + enum oox::Relationship PRESPROPS +include/oox/token/relationship.hxx:56 + enum oox::Relationship SETTINGS +include/oox/token/relationship.hxx:57 + enum oox::Relationship SHAREDSTRINGS +include/oox/token/relationship.hxx:58 + enum oox::Relationship SLIDE +include/oox/token/relationship.hxx:59 + enum oox::Relationship SLIDELAYOUT +include/oox/token/relationship.hxx:60 + enum oox::Relationship SLIDEMASTER +include/oox/token/relationship.hxx:61 + enum oox::Relationship STYLES +include/oox/token/relationship.hxx:62 + enum oox::Relationship THEME +include/oox/token/relationship.hxx:63 + enum oox::Relationship VBAPROJECT +include/oox/token/relationship.hxx:65 + enum oox::Relationship AUDIO +include/oox/token/relationship.hxx:66 + enum oox::Relationship VMLDRAWING +include/oox/token/relationship.hxx:67 + enum oox::Relationship WORDVBADATA +include/oox/token/relationship.hxx:68 + enum oox::Relationship WORKSHEET +include/registry/regtype.h:44 + enum RegAccessMode READWRITE +include/registry/regtype.h:88 + enum RegError REGISTRY_NOT_OPEN +include/registry/regtype.h:92 + enum RegError REGISTRY_READONLY +include/registry/regtype.h:94 + enum RegError DESTROY_REGISTRY_FAILED +include/registry/regtype.h:98 + enum RegError CANNOT_OPEN_FOR_READWRITE +include/registry/regtype.h:105 + enum RegError KEY_NOT_OPEN +include/registry/regtype.h:109 + enum RegError CREATE_KEY_FAILED +include/registry/regtype.h:111 + enum RegError DELETE_KEY_FAILED +include/registry/regtype.h:117 + enum RegError INVALID_KEY +include/registry/regtype.h:122 + enum RegError SET_VALUE_FAILED +include/registry/regtype.h:124 + enum RegError DELETE_VALUE_FAILED +include/sfx2/AccessibilityIssue.hxx:23 + enum sfx::AccessibilityIssueID UNSPECIFIED +include/sfx2/AccessibilityIssue.hxx:24 + enum sfx::AccessibilityIssueID DOCUMENT_TITLE +include/sfx2/AccessibilityIssue.hxx:25 + enum sfx::AccessibilityIssueID DOCUMENT_LANGUAGE +include/sfx2/AccessibilityIssue.hxx:26 + enum sfx::AccessibilityIssueID STYLE_LANGUAGE +include/sfx2/AccessibilityIssue.hxx:27 + enum sfx::AccessibilityIssueID NO_ALT_OLE +include/sfx2/AccessibilityIssue.hxx:28 + enum sfx::AccessibilityIssueID NO_ALT_GRAPHIC +include/sfx2/AccessibilityIssue.hxx:29 + enum sfx::AccessibilityIssueID NO_ALT_SHAPE +include/sfx2/AccessibilityIssue.hxx:30 + enum sfx::AccessibilityIssueID TABLE_MERGE_SPLIT +include/sfx2/AccessibilityIssue.hxx:31 + enum sfx::AccessibilityIssueID TEXT_FORMATTING +include/sfx2/app.hxx:73 + enum SfxToolsModule Math +include/sfx2/app.hxx:74 + enum SfxToolsModule Calc +include/sfx2/app.hxx:75 + enum SfxToolsModule Draw +include/sfx2/app.hxx:76 + enum SfxToolsModule Writer +include/sfx2/app.hxx:77 + enum SfxToolsModule Basic +include/sfx2/docfile.hxx:169 + enum SfxMedium::LockFileResult Failed +include/sfx2/docfile.hxx:171 + enum SfxMedium::LockFileResult Succeeded +include/sfx2/docfile.hxx:300 + enum SfxMedium::ShowLockResult NoLock +include/sfx2/filedlghelper.hxx:81 + enum sfx2::FileDialogHelper::Context SW_INSERT_GRAPHIC +include/sfx2/frmdescr.hxx:42 + enum ScrollingMode No +include/sfx2/lnkbase.hxx:136 + enum sfx2::SvBaseLink::UpdateResult ERROR_GENERAL +include/sfx2/mailmodelapi.hxx:48 + enum SfxMailModel::SaveResult SAVE_ERROR +include/sfx2/mailmodelapi.hxx:72 + enum SfxMailModel::SendMailResult SEND_MAIL_CANCELLED +include/sfx2/msg.hxx:38 + enum SfxSlotMode TOGGLE +include/sfx2/msg.hxx:39 + enum SfxSlotMode AUTOUPDATE +include/sfx2/msg.hxx:40 + enum SfxSlotMode ASYNCHRON +include/sfx2/msg.hxx:42 + enum SfxSlotMode NORECORD +include/sfx2/msg.hxx:43 + enum SfxSlotMode RECORDPERITEM +include/sfx2/msg.hxx:44 + enum SfxSlotMode RECORDPERSET +include/sfx2/msg.hxx:45 + enum SfxSlotMode RECORDABSOLUTE +include/sfx2/msg.hxx:47 + enum SfxSlotMode METHOD +include/sfx2/msg.hxx:49 + enum SfxSlotMode FASTCALL +include/sfx2/msg.hxx:51 + enum SfxSlotMode MENUCONFIG +include/sfx2/msg.hxx:52 + enum SfxSlotMode TOOLBOXCONFIG +include/sfx2/msg.hxx:53 + enum SfxSlotMode ACCELCONFIG +include/sfx2/msg.hxx:55 + enum SfxSlotMode CONTAINER +include/sfx2/msg.hxx:88 + enum SfxSlotKind Standard +include/sfx2/objface.hxx:47 + enum StatusBarId GenericStatusBar +include/sfx2/objface.hxx:48 + enum StatusBarId WriterStatusBar +include/sfx2/objface.hxx:49 + enum StatusBarId MathStatusBar +include/sfx2/objface.hxx:50 + enum StatusBarId DrawStatusBar +include/sfx2/objface.hxx:51 + enum StatusBarId CalcStatusBar +include/sfx2/objface.hxx:52 + enum StatusBarId BasicIdeStatusBar +include/sfx2/objsh.hxx:193 + enum SfxObjectShell::TriState no +include/sfx2/passwd.hxx:36 + enum SfxShowExtras ALL +include/sfx2/StylePreviewRenderer.hxx:33 + enum sfx2::StylePreviewRenderer::RenderAlign TOP +include/sfx2/toolbarids.hxx:20 + enum ToolbarId FullScreenToolbox +include/sfx2/toolbarids.hxx:21 + enum ToolbarId EnvToolbox +include/sfx2/toolbarids.hxx:24 + enum ToolbarId Basicide_Objectbar +include/sfx2/toolbarids.hxx:25 + enum ToolbarId SvxTbx_Form_Navigation +include/sfx2/toolbarids.hxx:26 + enum ToolbarId SvxTbx_Form_Filter +include/sfx2/toolbarids.hxx:27 + enum ToolbarId SvxTbx_Text_Control_Attributes +include/sfx2/toolbarids.hxx:28 + enum ToolbarId SvxTbx_Controls +include/sfx2/toolbarids.hxx:29 + enum ToolbarId SvxTbx_FormDesign +include/sfx2/toolbarids.hxx:30 + enum ToolbarId Math_Toolbox +include/sfx2/toolbarids.hxx:31 + enum ToolbarId Webtools_Toolbox +include/sfx2/toolbarids.hxx:32 + enum ToolbarId Webtext_Toolbox +include/sfx2/toolbarids.hxx:33 + enum ToolbarId Webframe_Toolbox +include/sfx2/toolbarids.hxx:34 + enum ToolbarId Webgraphic_Toolbox +include/sfx2/toolbarids.hxx:35 + enum ToolbarId Webole_Toolbox +include/sfx2/toolbarids.hxx:36 + enum ToolbarId Draw_Toolbox_Sd +include/sfx2/toolbarids.hxx:37 + enum ToolbarId Slide_Toolbox +include/sfx2/toolbarids.hxx:38 + enum ToolbarId Draw_Obj_Toolbox +include/sfx2/toolbarids.hxx:39 + enum ToolbarId Slide_Obj_Toolbox +include/sfx2/toolbarids.hxx:42 + enum ToolbarId Outline_Toolbox +include/sfx2/toolbarids.hxx:44 + enum ToolbarId Gluepoints_Toolbox +include/sfx2/toolbarids.hxx:45 + enum ToolbarId Draw_Options_Toolbox +include/sfx2/toolbarids.hxx:46 + enum ToolbarId Draw_CommonTask_Toolbox +include/sfx2/toolbarids.hxx:48 + enum ToolbarId Draw_Viewer_Toolbox +include/sfx2/toolbarids.hxx:49 + enum ToolbarId Graphic_Obj_Toolbox +include/sfx2/toolbarids.hxx:52 + enum ToolbarId Text_Toolbox_Sw +include/sfx2/toolbarids.hxx:53 + enum ToolbarId Table_Toolbox +include/sfx2/toolbarids.hxx:54 + enum ToolbarId Frame_Toolbox +include/sfx2/toolbarids.hxx:55 + enum ToolbarId Grafik_Toolbox +include/sfx2/toolbarids.hxx:56 + enum ToolbarId Draw_Toolbox_Sw +include/sfx2/toolbarids.hxx:57 + enum ToolbarId Draw_Text_Toolbox_Sw +include/sfx2/toolbarids.hxx:58 + enum ToolbarId Num_Toolbox +include/sfx2/toolbarids.hxx:59 + enum ToolbarId Ole_Toolbox +include/sfx2/toolbarids.hxx:60 + enum ToolbarId Tools_Toolbox +include/sfx2/toolbarids.hxx:61 + enum ToolbarId PView_Toolbox +include/sfx2/toolbarids.hxx:62 + enum ToolbarId Bezier_Toolbox_Sw +include/sfx2/toolbarids.hxx:63 + enum ToolbarId Module_Toolbox +include/sfx2/toolbarids.hxx:64 + enum ToolbarId Media_Toolbox +include/sfx2/toolbarids.hxx:65 + enum ToolbarId Objectbar_App +include/sfx2/toolbarids.hxx:66 + enum ToolbarId Objectbar_Format +include/sfx2/toolbarids.hxx:67 + enum ToolbarId Text_Toolbox_Sc +include/sfx2/toolbarids.hxx:68 + enum ToolbarId Objectbar_Preview +include/sfx2/toolbarids.hxx:69 + enum ToolbarId Objectbar_Tools +include/sfx2/toolbarids.hxx:70 + enum ToolbarId Draw_Objectbar +include/sfx2/toolbarids.hxx:71 + enum ToolbarId Graphic_Objectbar +include/sfx2/toolbarids.hxx:72 + enum ToolbarId Media_Objectbar +include/sfx2/zoomitem.hxx:41 + enum SvxZoomEnableFlags N75 +include/sfx2/zoomitem.hxx:48 + enum SvxZoomEnableFlags ALL +include/sot/exchange.hxx:91 + enum SotExchangeDest CHARTDOC_OLEOBJ +include/sot/exchange.hxx:97 + enum SotExchangeDest DOC_IMAPREGION +include/sot/exchange.hxx:100 + enum SotExchangeDest DOC_URLFIELD +include/sot/exchange.hxx:103 + enum SotExchangeDest SCDOC_FREE_AREA +include/sot/exchange.hxx:104 + enum SotExchangeDest SDDOC_FREE_AREA +include/store/types.h:75 + storeError store_E_AccessViolation +include/store/types.h:77 + storeError store_E_CantSeek +include/store/types.h:78 + storeError store_E_CantRead +include/store/types.h:79 + storeError store_E_CantWrite +include/store/types.h:80 + storeError store_E_InvalidAccess +include/store/types.h:81 + storeError store_E_InvalidHandle +include/store/types.h:82 + storeError store_E_InvalidParameter +include/store/types.h:86 + storeError store_E_NotDirectory +include/store/types.h:87 + storeError store_E_NotFile +include/store/types.h:88 + storeError store_E_NoMoreFiles +include/store/types.h:89 + storeError store_E_NameTooLong +include/store/types.h:90 + storeError store_E_OutOfMemory +include/store/types.h:91 + storeError store_E_OutOfSpace +include/store/types.h:94 + storeError store_E_WrongVersion +include/store/types.h:95 + storeError store_E_Unknown +include/svl/IndexedStyleSheets.hxx:120 + enum svl::IndexedStyleSheets::SearchBehavior ReturnAll +include/svl/inettype.hxx:126 + enum INetContentType CONTENT_TYPE_APP_OCTSTREAM +include/svl/inettype.hxx:127 + enum INetContentType CONTENT_TYPE_APP_PDF +include/svl/inettype.hxx:128 + enum INetContentType CONTENT_TYPE_APP_RTF +include/svl/inettype.hxx:129 + enum INetContentType CONTENT_TYPE_APP_MSWORD +include/svl/inettype.hxx:130 + enum INetContentType CONTENT_TYPE_APP_MSWORD_TEMPL +include/svl/inettype.hxx:131 + enum INetContentType CONTENT_TYPE_APP_STARCALC +include/svl/inettype.hxx:132 + enum INetContentType CONTENT_TYPE_APP_STARCHART +include/svl/inettype.hxx:133 + enum INetContentType CONTENT_TYPE_APP_STARDRAW +include/svl/inettype.hxx:134 + enum INetContentType CONTENT_TYPE_APP_STARHELP +include/svl/inettype.hxx:135 + enum INetContentType CONTENT_TYPE_APP_STARIMAGE +include/svl/inettype.hxx:136 + enum INetContentType CONTENT_TYPE_APP_STARIMPRESS +include/svl/inettype.hxx:137 + enum INetContentType CONTENT_TYPE_APP_STARMATH +include/svl/inettype.hxx:138 + enum INetContentType CONTENT_TYPE_APP_STARWRITER +include/svl/inettype.hxx:139 + enum INetContentType CONTENT_TYPE_APP_ZIP +include/svl/inettype.hxx:140 + enum INetContentType CONTENT_TYPE_AUDIO_AIFF +include/svl/inettype.hxx:141 + enum INetContentType CONTENT_TYPE_AUDIO_BASIC +include/svl/inettype.hxx:142 + enum INetContentType CONTENT_TYPE_AUDIO_MIDI +include/svl/inettype.hxx:143 + enum INetContentType CONTENT_TYPE_AUDIO_VORBIS +include/svl/inettype.hxx:144 + enum INetContentType CONTENT_TYPE_AUDIO_WAV +include/svl/inettype.hxx:145 + enum INetContentType CONTENT_TYPE_AUDIO_WEBM +include/svl/inettype.hxx:146 + enum INetContentType CONTENT_TYPE_IMAGE_GIF +include/svl/inettype.hxx:147 + enum INetContentType CONTENT_TYPE_IMAGE_JPEG +include/svl/inettype.hxx:148 + enum INetContentType CONTENT_TYPE_IMAGE_PCX +include/svl/inettype.hxx:149 + enum INetContentType CONTENT_TYPE_IMAGE_PNG +include/svl/inettype.hxx:150 + enum INetContentType CONTENT_TYPE_IMAGE_TIFF +include/svl/inettype.hxx:151 + enum INetContentType CONTENT_TYPE_IMAGE_BMP +include/svl/inettype.hxx:152 + enum INetContentType CONTENT_TYPE_TEXT_HTML +include/svl/inettype.hxx:154 + enum INetContentType CONTENT_TYPE_TEXT_URL +include/svl/inettype.hxx:155 + enum INetContentType CONTENT_TYPE_TEXT_VCARD +include/svl/inettype.hxx:156 + enum INetContentType CONTENT_TYPE_VIDEO_MSVIDEO +include/svl/inettype.hxx:157 + enum INetContentType CONTENT_TYPE_VIDEO_THEORA +include/svl/inettype.hxx:158 + enum INetContentType CONTENT_TYPE_VIDEO_VDO +include/svl/inettype.hxx:159 + enum INetContentType CONTENT_TYPE_VIDEO_WEBM +include/svl/inettype.hxx:160 + enum INetContentType CONTENT_TYPE_X_CNT_FSYSBOX +include/svl/inettype.hxx:161 + enum INetContentType CONTENT_TYPE_X_CNT_FSYSFOLDER +include/svl/inettype.hxx:162 + enum INetContentType CONTENT_TYPE_X_STARMAIL +include/svl/inettype.hxx:163 + enum INetContentType CONTENT_TYPE_X_VRML +include/svl/inettype.hxx:164 + enum INetContentType CONTENT_TYPE_APP_GALLERY +include/svl/inettype.hxx:165 + enum INetContentType CONTENT_TYPE_APP_GALLERY_THEME +include/svl/inettype.hxx:166 + enum INetContentType CONTENT_TYPE_APP_STARWRITER_GLOB +include/svl/inettype.hxx:167 + enum INetContentType CONTENT_TYPE_APP_STARMAIL_SDM +include/svl/inettype.hxx:168 + enum INetContentType CONTENT_TYPE_APP_STARMAIL_SMD +include/svl/inettype.hxx:169 + enum INetContentType CONTENT_TYPE_APP_VND_CALC +include/svl/inettype.hxx:170 + enum INetContentType CONTENT_TYPE_APP_VND_CHART +include/svl/inettype.hxx:171 + enum INetContentType CONTENT_TYPE_APP_VND_DRAW +include/svl/inettype.hxx:172 + enum INetContentType CONTENT_TYPE_APP_VND_IMAGE +include/svl/inettype.hxx:173 + enum INetContentType CONTENT_TYPE_APP_VND_IMPRESS +include/svl/inettype.hxx:174 + enum INetContentType CONTENT_TYPE_APP_VND_MAIL +include/svl/inettype.hxx:175 + enum INetContentType CONTENT_TYPE_APP_VND_MATH +include/svl/inettype.hxx:176 + enum INetContentType CONTENT_TYPE_APP_VND_WRITER +include/svl/inettype.hxx:177 + enum INetContentType CONTENT_TYPE_APP_VND_WRITER_GLOBAL +include/svl/inettype.hxx:178 + enum INetContentType CONTENT_TYPE_APP_VND_WRITER_WEB +include/svl/inettype.hxx:179 + enum INetContentType CONTENT_TYPE_APP_FRAMESET +include/svl/inettype.hxx:180 + enum INetContentType CONTENT_TYPE_APP_MACRO +include/svl/inettype.hxx:181 + enum INetContentType CONTENT_TYPE_X_CNT_FSYSSPECIALFOLDER +include/svl/inettype.hxx:182 + enum INetContentType CONTENT_TYPE_APP_VND_TEMPLATE +include/svl/inettype.hxx:183 + enum INetContentType CONTENT_TYPE_IMAGE_GENERIC +include/svl/inettype.hxx:184 + enum INetContentType CONTENT_TYPE_APP_VND_NEWS +include/svl/inettype.hxx:185 + enum INetContentType CONTENT_TYPE_APP_VND_OUTTRAY +include/svl/inettype.hxx:186 + enum INetContentType CONTENT_TYPE_APP_MSEXCEL +include/svl/inettype.hxx:187 + enum INetContentType CONTENT_TYPE_APP_MSEXCEL_TEMPL +include/svl/inettype.hxx:188 + enum INetContentType CONTENT_TYPE_APP_MSPPOINT +include/svl/inettype.hxx:189 + enum INetContentType CONTENT_TYPE_APP_MSPPOINT_TEMPL +include/svl/inettype.hxx:190 + enum INetContentType CONTENT_TYPE_TEXT_VCALENDAR +include/svl/inettype.hxx:191 + enum INetContentType CONTENT_TYPE_TEXT_ICALENDAR +include/svl/inettype.hxx:192 + enum INetContentType CONTENT_TYPE_TEXT_XMLICALENDAR +include/svl/inettype.hxx:193 + enum INetContentType CONTENT_TYPE_APP_CDE_CALENDAR_APP +include/svl/inettype.hxx:194 + enum INetContentType CONTENT_TYPE_INET_MESSAGE_RFC822 +include/svl/inettype.hxx:195 + enum INetContentType CONTENT_TYPE_INET_MULTIPART_ALTERNATIVE +include/svl/inettype.hxx:196 + enum INetContentType CONTENT_TYPE_INET_MULTIPART_DIGEST +include/svl/inettype.hxx:197 + enum INetContentType CONTENT_TYPE_INET_MULTIPART_PARALLEL +include/svl/inettype.hxx:198 + enum INetContentType CONTENT_TYPE_INET_MULTIPART_RELATED +include/svl/inettype.hxx:199 + enum INetContentType CONTENT_TYPE_INET_MULTIPART_MIXED +include/svl/inettype.hxx:200 + enum INetContentType CONTENT_TYPE_APP_VND_IMPRESSPACKED +include/svl/inettype.hxx:201 + enum INetContentType CONTENT_TYPE_APP_JAR +include/svl/inettype.hxx:202 + enum INetContentType CONTENT_TYPE_APP_VND_SUN_XML_WRITER +include/svl/inettype.hxx:203 + enum INetContentType CONTENT_TYPE_APP_VND_SUN_XML_CALC +include/svl/inettype.hxx:204 + enum INetContentType CONTENT_TYPE_APP_VND_SUN_XML_IMPRESS +include/svl/inettype.hxx:205 + enum INetContentType CONTENT_TYPE_APP_VND_SUN_XML_DRAW +include/svl/inettype.hxx:206 + enum INetContentType CONTENT_TYPE_APP_VND_SUN_XML_CHART +include/svl/inettype.hxx:207 + enum INetContentType CONTENT_TYPE_APP_VND_SUN_XML_MATH +include/svl/inettype.hxx:208 + enum INetContentType CONTENT_TYPE_APP_VND_SUN_XML_WRITER_GLOBAL +include/svl/inettype.hxx:209 + enum INetContentType CONTENT_TYPE_APP_VND_SUN_XML_IMPRESSPACKED +include/svl/lstner.hxx:41 + enum DuplicateHandling Allow +include/svl/nfsymbol.hxx:48 + enum svt::NfSymbolType NF_SYMBOLTYPE_CURRDEL +include/svl/sigstruct.hxx:79 + enum svl::crypto::SignatureMethodAlgorithm RSA +include/svl/srchdefs.hxx:41 + enum SearchOptionFlags ALL +include/svl/style.hxx:57 + enum SfxStyleSearchBits ScStandard +include/svtools/borderline.hxx:45 + enum BorderWidthImplFlags FIXED +include/svtools/colorcfg.hxx:33 + enum svtools::ColorConfigEntry DOCBOUNDARIES +include/svtools/colorcfg.hxx:35 + enum svtools::ColorConfigEntry OBJECTBOUNDARIES +include/svtools/colorcfg.hxx:36 + enum svtools::ColorConfigEntry TABLEBOUNDARIES +include/svtools/colorcfg.hxx:40 + enum svtools::ColorConfigEntry SPELL +include/svtools/colorcfg.hxx:41 + enum svtools::ColorConfigEntry SMARTTAGS +include/svtools/colorcfg.hxx:42 + enum svtools::ColorConfigEntry SHADOWCOLOR +include/svtools/colorcfg.hxx:43 + enum svtools::ColorConfigEntry WRITERTEXTGRID +include/svtools/colorcfg.hxx:44 + enum svtools::ColorConfigEntry WRITERFIELDSHADINGS +include/svtools/colorcfg.hxx:45 + enum svtools::ColorConfigEntry WRITERIDXSHADINGS +include/svtools/colorcfg.hxx:46 + enum svtools::ColorConfigEntry WRITERDIRECTCURSOR +include/svtools/colorcfg.hxx:47 + enum svtools::ColorConfigEntry WRITERSCRIPTINDICATOR +include/svtools/colorcfg.hxx:48 + enum svtools::ColorConfigEntry WRITERSECTIONBOUNDARIES +include/svtools/colorcfg.hxx:49 + enum svtools::ColorConfigEntry WRITERHEADERFOOTERMARK +include/svtools/colorcfg.hxx:50 + enum svtools::ColorConfigEntry WRITERPAGEBREAKS +include/svtools/colorcfg.hxx:55 + enum svtools::ColorConfigEntry CALCGRID +include/svtools/colorcfg.hxx:56 + enum svtools::ColorConfigEntry CALCPAGEBREAK +include/svtools/colorcfg.hxx:57 + enum svtools::ColorConfigEntry CALCPAGEBREAKMANUAL +include/svtools/colorcfg.hxx:58 + enum svtools::ColorConfigEntry CALCPAGEBREAKAUTOMATIC +include/svtools/colorcfg.hxx:59 + enum svtools::ColorConfigEntry CALCDETECTIVE +include/svtools/colorcfg.hxx:60 + enum svtools::ColorConfigEntry CALCDETECTIVEERROR +include/svtools/colorcfg.hxx:61 + enum svtools::ColorConfigEntry CALCREFERENCE +include/svtools/colorcfg.hxx:62 + enum svtools::ColorConfigEntry CALCNOTESBACKGROUND +include/svtools/colorcfg.hxx:63 + enum svtools::ColorConfigEntry CALCVALUE +include/svtools/colorcfg.hxx:64 + enum svtools::ColorConfigEntry CALCFORMULA +include/svtools/colorcfg.hxx:65 + enum svtools::ColorConfigEntry CALCTEXT +include/svtools/colorcfg.hxx:66 + enum svtools::ColorConfigEntry CALCPROTECTEDBACKGROUND +include/svtools/colorcfg.hxx:67 + enum svtools::ColorConfigEntry DRAWGRID +include/svtools/colorcfg.hxx:68 + enum svtools::ColorConfigEntry BASICIDENTIFIER +include/svtools/colorcfg.hxx:69 + enum svtools::ColorConfigEntry BASICCOMMENT +include/svtools/colorcfg.hxx:70 + enum svtools::ColorConfigEntry BASICNUMBER +include/svtools/colorcfg.hxx:71 + enum svtools::ColorConfigEntry BASICSTRING +include/svtools/colorcfg.hxx:72 + enum svtools::ColorConfigEntry BASICOPERATOR +include/svtools/colorcfg.hxx:73 + enum svtools::ColorConfigEntry BASICKEYWORD +include/svtools/colorcfg.hxx:74 + enum svtools::ColorConfigEntry BASICERROR +include/svtools/colorcfg.hxx:75 + enum svtools::ColorConfigEntry SQLIDENTIFIER +include/svtools/colorcfg.hxx:76 + enum svtools::ColorConfigEntry SQLNUMBER +include/svtools/colorcfg.hxx:77 + enum svtools::ColorConfigEntry SQLSTRING +include/svtools/colorcfg.hxx:78 + enum svtools::ColorConfigEntry SQLOPERATOR +include/svtools/colorcfg.hxx:79 + enum svtools::ColorConfigEntry SQLKEYWORD +include/svtools/colorcfg.hxx:80 + enum svtools::ColorConfigEntry SQLPARAMETER +include/svtools/colorcfg.hxx:81 + enum svtools::ColorConfigEntry SQLCOMMENT +include/svtools/colrdlg.hxx:31 + enum svtools::ColorPickerMode Modify +include/svtools/colrdlg.hxx:31 + enum svtools::ColorPickerMode Select +include/svtools/editbrowsebox.hxx:820 + enum svt::EditBrowseBox::BrowseInfo COLCHANGE +include/svtools/imagemgr.hxx:29 + enum SvImageId START +include/svtools/parhtml.hxx:48 + enum HTMLTableFrame Void +include/svtools/parhtml.hxx:58 + enum HTMLInputType Range +include/svtools/parhtml.hxx:59 + enum HTMLInputType Scribble +include/svtools/parhtml.hxx:71 + enum HTMLScriptLanguage JavaScript +include/svtools/parhtml.hxx:72 + enum HTMLScriptLanguage Unknown +include/svtools/ruler.hxx:471 + enum RulerExtra DontKnow +include/svtools/ruler.hxx:518 + enum RulerIndentStyle Top +include/svtools/tabbar.hxx:301 + enum TabBarAllowRenamingReturnCode TABBAR_RENAMING_CANCEL +include/svx/dataaccessdescriptor.hxx:48 + enum svx::DataAccessDescriptorProperty Filter +include/svx/def3d.hxx:36 + enum E3dDragConstraint XYZ +include/svx/EnhancedCustomShape2d.hxx:55 + enum HandleFlags MIRRORED_X +include/svx/EnhancedCustomShape2d.hxx:56 + enum HandleFlags MIRRORED_Y +include/svx/flagsdef.hxx:31 + enum SwBorderModes FRAME +include/svx/flagsdef.hxx:95 + enum SvxModeType SVX_PAGE_MODE_STANDARD +include/svx/fmsrcimp.hxx:159 + enum FmSearchEngine::SearchFor NotNull +include/svx/frmsel.hxx:36 + enum FrameSelFlags Left +include/svx/frmsel.hxx:38 + enum FrameSelFlags Right +include/svx/frmsel.hxx:40 + enum FrameSelFlags Top +include/svx/frmsel.hxx:42 + enum FrameSelFlags Bottom +include/svx/frmsel.hxx:44 + enum FrameSelFlags InnerHorizontal +include/svx/frmsel.hxx:46 + enum FrameSelFlags InnerVertical +include/svx/frmsel.hxx:48 + enum FrameSelFlags DiagonalTLBR +include/svx/frmsel.hxx:50 + enum FrameSelFlags DiagonalBLTR +include/svx/frmsel.hxx:53 + enum FrameSelFlags Outer +include/svx/galmisc.hxx:71 + enum GalleryGraphicImportRet IMPORT_FILE +include/svx/grfflt.hxx:26 + enum SvxGraphicFilterResult UnsupportedGraphicType +include/svx/grfflt.hxx:26 + enum SvxGraphicFilterResult UnsupportedSlot +include/svx/gridctrl.hxx:56 + enum GridRowStatus Invalid +include/svx/gridctrl.hxx:121 + enum InitWindowFacet All +include/svx/numvset.hxx:46 + enum NumberingPageType BITMAP +include/svx/optgenrl.hxx:26 + enum EditPosition COMPANY +include/svx/optgenrl.hxx:27 + enum EditPosition FIRSTNAME +include/svx/optgenrl.hxx:28 + enum EditPosition LASTNAME +include/svx/optgenrl.hxx:29 + enum EditPosition STREET +include/svx/optgenrl.hxx:30 + enum EditPosition COUNTRY +include/svx/optgenrl.hxx:31 + enum EditPosition PLZ +include/svx/optgenrl.hxx:32 + enum EditPosition CITY +include/svx/optgenrl.hxx:33 + enum EditPosition STATE +include/svx/optgenrl.hxx:34 + enum EditPosition TITLE +include/svx/optgenrl.hxx:35 + enum EditPosition POSITION +include/svx/optgenrl.hxx:36 + enum EditPosition SHORTNAME +include/svx/optgenrl.hxx:37 + enum EditPosition TELPRIV +include/svx/optgenrl.hxx:38 + enum EditPosition TELCOMPANY +include/svx/optgenrl.hxx:39 + enum EditPosition FAX +include/svx/optgenrl.hxx:40 + enum EditPosition EMAIL +include/svx/papersizelistbox.hxx:30 + enum PaperSizeApp Draw +include/svx/ruler.hxx:53 + enum SvxRulerDragFlags OBJECT +include/svx/sdr/overlay/overlayselection.hxx:32 + enum sdr::overlay::OverlayType Solid +include/svx/shapeproperty.hxx:32 + enum svx::ShapeProperty Position +include/svx/shapeproperty.hxx:33 + enum svx::ShapeProperty Size +include/svx/shapeproperty.hxx:35 + enum svx::ShapeProperty TextDocAnchor +include/svx/ShapeTypeHandler.hxx:82 + enum accessibility::ShapeTypeHandler::(anonymous at /home/noel/libo2/include/svx/ShapeTypeHandler.hxx:82:5) UNKNOWN_SHAPE_TYPE +include/svx/sidebar/InspectorTextPanel.hxx:34 + enum svx::sidebar::TreeNode::(anonymous at /home/noel/libo2/include/svx/sidebar/InspectorTextPanel.hxx:31:5) ComplexProperty +include/svx/srchdlg.hxx:74 + enum SearchLabel Empty +include/svx/svddrgv.hxx:36 + enum SdrDragView::(anonymous at /home/noel/libo2/include/svx/svddrgv.hxx:35:5) eDragXorPolyLimit +include/svx/svddrgv.hxx:37 + enum SdrDragView::(anonymous at /home/noel/libo2/include/svx/svddrgv.hxx:35:5) eDragXorPointLimit +include/svx/svdedxv.hxx:51 + enum SdrEndTextEditKind Changed +include/svx/svdglue.hxx:45 + enum SdrEscapeDirection ALL +include/svx/svdglue.hxx:58 + enum SdrAlign HORZ_DONTCARE +include/svx/svdglue.hxx:62 + enum SdrAlign VERT_DONTCARE +include/svx/svditer.hxx:36 + enum SdrIterMode DeepWithGroups +include/svx/svdmrkv.hxx:48 + enum SdrSearchOptions PICKMARKABLE +include/svx/svdmrkv.hxx:49 + enum SdrSearchOptions PICKTEXTEDIT +include/svx/svdmrkv.hxx:50 + enum SdrSearchOptions PICKMACRO +include/svx/svdmrkv.hxx:60 + enum SdrHitKind Object +include/svx/svdoashp.hxx:58 + enum CustomShapeHandleModes ORTHO4 +include/svx/svdobj.hxx:104 + enum SdrInventor IMap +include/svx/svdobjkind.hxx:65 + enum SdrObjKind E3D_OBJECT_ID +include/svx/svdobjkind.hxx:99 + enum SdrObjKind OBJ_DLG_CONTROL +include/svx/svdobjkind.hxx:100 + enum SdrObjKind OBJ_DLG_DIALOG +include/svx/svdograf.hxx:52 + enum SdrGrafObjTransformsAttrs ALL +include/svx/svdotable.hxx:55 + enum sdr::table::TableHitKind HorizontalBorder +include/svx/svdotable.hxx:56 + enum sdr::table::TableHitKind VerticallBorder +include/svx/svdpntv.hxx:63 + enum SdrAnimationMode Disable +include/svx/svdsnpv.hxx:73 + enum SdrSnap NOTSNAPPED +include/svx/svdtypes.hxx:69 + enum SdrRepeatFunc Move +include/svx/svdtypes.hxx:70 + enum SdrRepeatFunc Resize +include/svx/svdtypes.hxx:71 + enum SdrRepeatFunc Rotate +include/svx/svdview.hxx:57 + enum SdrViewContext GluePointEdit +include/svx/svdview.hxx:92 + enum SdrMouseEventKind MOVE +include/svx/SvxShapeTypes.hxx:65 + enum accessibility::SvxShapeTypes DRAWING_END +include/svx/swframeposstrings.hxx:34 + enum SvxSwFramePosString::StringId LEFT +include/svx/swframeposstrings.hxx:35 + enum SvxSwFramePosString::StringId RIGHT +include/svx/swframeposstrings.hxx:37 + enum SvxSwFramePosString::StringId MIR_LEFT +include/svx/swframeposstrings.hxx:38 + enum SvxSwFramePosString::StringId MIR_RIGHT +include/svx/swframeposstrings.hxx:39 + enum SvxSwFramePosString::StringId MIR_FROMLEFT +include/svx/swframeposstrings.hxx:40 + enum SvxSwFramePosString::StringId FRAME +include/svx/swframeposstrings.hxx:41 + enum SvxSwFramePosString::StringId PRTAREA +include/svx/swframeposstrings.hxx:42 + enum SvxSwFramePosString::StringId REL_PG_LEFT +include/svx/swframeposstrings.hxx:43 + enum SvxSwFramePosString::StringId REL_PG_RIGHT +include/svx/swframeposstrings.hxx:44 + enum SvxSwFramePosString::StringId REL_FRM_LEFT +include/svx/swframeposstrings.hxx:45 + enum SvxSwFramePosString::StringId REL_FRM_RIGHT +include/svx/swframeposstrings.hxx:46 + enum SvxSwFramePosString::StringId MIR_REL_PG_LEFT +include/svx/swframeposstrings.hxx:47 + enum SvxSwFramePosString::StringId MIR_REL_PG_RIGHT +include/svx/swframeposstrings.hxx:48 + enum SvxSwFramePosString::StringId MIR_REL_FRM_LEFT +include/svx/swframeposstrings.hxx:49 + enum SvxSwFramePosString::StringId MIR_REL_FRM_RIGHT +include/svx/swframeposstrings.hxx:50 + enum SvxSwFramePosString::StringId REL_PG_FRAME +include/svx/swframeposstrings.hxx:51 + enum SvxSwFramePosString::StringId REL_PG_PRTAREA +include/svx/swframeposstrings.hxx:52 + enum SvxSwFramePosString::StringId REL_PG_PRTAREA_TOP +include/svx/swframeposstrings.hxx:53 + enum SvxSwFramePosString::StringId REL_PG_PRTAREA_BOTTOM +include/svx/swframeposstrings.hxx:54 + enum SvxSwFramePosString::StringId REL_BASE +include/svx/swframeposstrings.hxx:55 + enum SvxSwFramePosString::StringId REL_CHAR +include/svx/swframeposstrings.hxx:56 + enum SvxSwFramePosString::StringId REL_ROW +include/svx/swframeposstrings.hxx:57 + enum SvxSwFramePosString::StringId REL_BORDER +include/svx/swframeposstrings.hxx:58 + enum SvxSwFramePosString::StringId REL_PRTAREA +include/svx/swframeposstrings.hxx:59 + enum SvxSwFramePosString::StringId FLY_REL_PG_LEFT +include/svx/swframeposstrings.hxx:60 + enum SvxSwFramePosString::StringId FLY_REL_PG_RIGHT +include/svx/swframeposstrings.hxx:61 + enum SvxSwFramePosString::StringId FLY_REL_PG_FRAME +include/svx/swframeposstrings.hxx:62 + enum SvxSwFramePosString::StringId FLY_REL_PG_PRTAREA +include/svx/swframeposstrings.hxx:63 + enum SvxSwFramePosString::StringId FLY_MIR_REL_PG_LEFT +include/svx/swframeposstrings.hxx:64 + enum SvxSwFramePosString::StringId FLY_MIR_REL_PG_RIGHT +include/svx/swframeposstrings.hxx:65 + enum SvxSwFramePosString::StringId TOP +include/svx/swframeposstrings.hxx:66 + enum SvxSwFramePosString::StringId BOTTOM +include/svx/swframeposstrings.hxx:67 + enum SvxSwFramePosString::StringId CENTER_HORI +include/svx/swframeposstrings.hxx:68 + enum SvxSwFramePosString::StringId CENTER_VERT +include/svx/swframeposstrings.hxx:70 + enum SvxSwFramePosString::StringId FROMBOTTOM +include/svx/swframeposstrings.hxx:71 + enum SvxSwFramePosString::StringId BELOW +include/svx/swframeposstrings.hxx:72 + enum SvxSwFramePosString::StringId FROMRIGHT +include/svx/swframeposstrings.hxx:73 + enum SvxSwFramePosString::StringId REL_PG_TOP +include/svx/swframeposstrings.hxx:74 + enum SvxSwFramePosString::StringId REL_PG_BOTTOM +include/svx/swframeposstrings.hxx:75 + enum SvxSwFramePosString::StringId REL_FRM_TOP +include/svx/swframeposstrings.hxx:76 + enum SvxSwFramePosString::StringId REL_FRM_BOTTOM +include/svx/swframeposstrings.hxx:77 + enum SvxSwFramePosString::StringId REL_LINE +include/svx/xenum.hxx:26 + enum XFormTextShadow Slant +include/toolkit/controls/unocontrols.hxx:729 + enum UnoControlListBoxModel::ConstructorMode ConstructWithoutProperties +include/tools/color.hxx:45 + enum ColorTransparencyTag ColorTransparency +include/tools/color.hxx:46 + enum ColorAlphaTag ColorAlpha +include/tools/cpuid.hxx:23 + enum cpuid::InstructionSetFlags HYPER +include/tools/cpuid.hxx:24 + enum cpuid::InstructionSetFlags SSE2 +include/tools/cpuid.hxx:25 + enum cpuid::InstructionSetFlags SSSE3 +include/tools/cpuid.hxx:26 + enum cpuid::InstructionSetFlags SSE41 +include/tools/cpuid.hxx:27 + enum cpuid::InstructionSetFlags SSE42 +include/tools/cpuid.hxx:28 + enum cpuid::InstructionSetFlags AVX +include/tools/cpuid.hxx:29 + enum cpuid::InstructionSetFlags AVX2 +include/tools/date.hxx:63 + enum Date::DateInitSystem SYSTEM +include/tools/date.hxx:68 + enum Date::DateInitEmpty EMPTY +include/tools/datetime.hxx:34 + enum DateTime::DateTimeInitSystem SYSTEM +include/tools/datetime.hxx:39 + enum DateTime::DateTimeInitEmpty EMPTY +include/tools/stream.hxx:52 + enum StreamMode TEMPORARY +include/tools/stream.hxx:60 + enum StreamMode STD_READ +include/tools/stream.hxx:61 + enum StreamMode STD_WRITE +include/tools/stream.hxx:62 + enum StreamMode STD_READWRITE +include/tools/time.hxx:45 + enum tools::Time::TimeInitSystem SYSTEM +include/tools/time.hxx:51 + enum tools::Time::TimeInitEmpty EMPTY +include/tools/urlobj.hxx:173 + enum FSysStyle Detect +include/tools/urlobj.hxx:243 + enum INetURLObject::DecodeMechanism WithCharset +include/tools/urlobj.hxx:785 + enum INetURLObject::Part PART_USER_PASSWORD +include/tools/urlobj.hxx:786 + enum INetURLObject::Part PART_FPATH +include/tools/urlobj.hxx:787 + enum INetURLObject::Part PART_AUTHORITY +include/tools/urlobj.hxx:788 + enum INetURLObject::Part PART_REL_SEGMENT_EXTRA +include/tools/urlobj.hxx:789 + enum INetURLObject::Part PART_URIC +include/tools/urlobj.hxx:790 + enum INetURLObject::Part PART_HTTP_PATH +include/tools/urlobj.hxx:791 + enum INetURLObject::Part PART_MESSAGE_ID_PATH +include/tools/urlobj.hxx:792 + enum INetURLObject::Part PART_MAILTO +include/tools/urlobj.hxx:793 + enum INetURLObject::Part PART_PATH_BEFORE_QUERY +include/tools/urlobj.hxx:794 + enum INetURLObject::Part PART_PCHAR +include/tools/urlobj.hxx:795 + enum INetURLObject::Part PART_VISIBLE +include/tools/urlobj.hxx:796 + enum INetURLObject::Part PART_VISIBLE_NONSPECIAL +include/tools/urlobj.hxx:797 + enum INetURLObject::Part PART_UNO_PARAM_VALUE +include/tools/urlobj.hxx:798 + enum INetURLObject::Part PART_UNAMBIGUOUS +include/tools/urlobj.hxx:799 + enum INetURLObject::Part PART_URIC_NO_SLASH +include/tools/urlobj.hxx:800 + enum INetURLObject::Part PART_HTTP_QUERY +include/tools/wintypes.hxx:240 + enum SymbolAlign LEFT +include/tools/wintypes.hxx:253 + enum StandardButtonType More +include/tools/wintypes.hxx:254 + enum StandardButtonType Ignore +include/tools/wintypes.hxx:255 + enum StandardButtonType Abort +include/tools/wintypes.hxx:256 + enum StandardButtonType Less +include/tools/wintypes.hxx:257 + enum StandardButtonType Back +include/tools/wintypes.hxx:258 + enum StandardButtonType Next +include/tools/wintypes.hxx:259 + enum StandardButtonType Finish +include/tools/wintypes.hxx:260 + enum StandardButtonType Count +include/tools/zcodec.hxx:40 + enum ZCodec::State STATE_DECOMPRESS +include/ucbhelper/content.hxx:77 + enum ucbhelper::ResultSetInclude INCLUDE_FOLDERS_AND_DOCUMENTS +include/ucbhelper/simpleauthenticationrequest.hxx:73 + enum ucbhelper::SimpleAuthenticationRequest::EntityType ENTITY_FIXED +include/unotest/filters-test.hxx:26 + enum test::filterStatus fail +include/unotest/filters-test.hxx:27 + enum test::filterStatus pass +include/unotools/bootstrap.hxx:59 + enum utl::Bootstrap::PathStatus DATA_UNKNOWN +include/unotools/bootstrap.hxx:82 + enum utl::Bootstrap::Status MISSING_USER_INSTALL +include/unotools/bootstrap.hxx:83 + enum utl::Bootstrap::Status INVALID_USER_INSTALL +include/unotools/bootstrap.hxx:84 + enum utl::Bootstrap::Status INVALID_BASE_INSTALL +include/unotools/compatibility.hxx:68 + enum SvtCompatibilityEntry::Index AddTableLineSpacing +include/unotools/confignode.hxx:164 + enum utl::OConfigurationNode::NAMEORIGIN NO_CONFIGURATION +include/unotools/confignode.hxx:194 + enum utl::OConfigurationTreeRoot::CREATION_MODE CM_UPDATABLE +include/unotools/eventcfg.hxx:31 + enum GlobalEventId DOCCREATED +include/unotools/eventcfg.hxx:32 + enum GlobalEventId CREATEDOC +include/unotools/eventcfg.hxx:33 + enum GlobalEventId LOADFINISHED +include/unotools/eventcfg.hxx:34 + enum GlobalEventId OPENDOC +include/unotools/eventcfg.hxx:35 + enum GlobalEventId PREPARECLOSEDOC +include/unotools/eventcfg.hxx:36 + enum GlobalEventId CLOSEDOC +include/unotools/eventcfg.hxx:37 + enum GlobalEventId SAVEDOC +include/unotools/eventcfg.hxx:38 + enum GlobalEventId SAVEDOCDONE +include/unotools/eventcfg.hxx:39 + enum GlobalEventId SAVEDOCFAILED +include/unotools/eventcfg.hxx:40 + enum GlobalEventId SAVEASDOC +include/unotools/eventcfg.hxx:41 + enum GlobalEventId SAVEASDOCDONE +include/unotools/eventcfg.hxx:42 + enum GlobalEventId SAVEASDOCFAILED +include/unotools/eventcfg.hxx:43 + enum GlobalEventId SAVETODOC +include/unotools/eventcfg.hxx:44 + enum GlobalEventId SAVETODOCDONE +include/unotools/eventcfg.hxx:45 + enum GlobalEventId SAVETODOCFAILED +include/unotools/eventcfg.hxx:46 + enum GlobalEventId ACTIVATEDOC +include/unotools/eventcfg.hxx:47 + enum GlobalEventId DEACTIVATEDOC +include/unotools/eventcfg.hxx:48 + enum GlobalEventId PRINTDOC +include/unotools/eventcfg.hxx:49 + enum GlobalEventId VIEWCREATED +include/unotools/eventcfg.hxx:50 + enum GlobalEventId PREPARECLOSEVIEW +include/unotools/eventcfg.hxx:51 + enum GlobalEventId CLOSEVIEW +include/unotools/eventcfg.hxx:52 + enum GlobalEventId MODIFYCHANGED +include/unotools/eventcfg.hxx:53 + enum GlobalEventId TITLECHANGED +include/unotools/eventcfg.hxx:54 + enum GlobalEventId VISAREACHANGED +include/unotools/eventcfg.hxx:55 + enum GlobalEventId MODECHANGED +include/unotools/eventcfg.hxx:56 + enum GlobalEventId STORAGECHANGED +include/unotools/fontcfg.hxx:64 + enum ImplFontAttrs CJK_JP +include/unotools/fontcfg.hxx:65 + enum ImplFontAttrs CJK_SC +include/unotools/fontcfg.hxx:66 + enum ImplFontAttrs CJK_TC +include/unotools/fontcfg.hxx:67 + enum ImplFontAttrs CJK_KR +include/unotools/fontcfg.hxx:75 + enum ImplFontAttrs Script +include/unotools/fontcfg.hxx:76 + enum ImplFontAttrs Handwriting +include/unotools/fontcfg.hxx:77 + enum ImplFontAttrs Chancery +include/unotools/fontcfg.hxx:78 + enum ImplFontAttrs Comic +include/unotools/fontcvt.hxx:30 + enum FontToSubsFontFlags EXPORT +include/unotools/options.hxx:34 + enum ConfigurationHints UiLocale +include/unotools/options.hxx:37 + enum ConfigurationHints IgnoreLang +include/unotools/options.hxx:38 + enum ConfigurationHints CtlSettingsChanged +include/unotools/sharedunocomponent.hxx:149 + enum utl::SharedUNOComponent::AssignmentMode NoTakeOwnership +include/unotools/sharedunocomponent.hxx:149 + enum utl::SharedUNOComponent::AssignmentMode NoTakeOwnership +include/unotools/sharedunocomponent.hxx:149 + enum utl::SharedUNOComponent::AssignmentMode NoTakeOwnership +include/unotools/sharedunocomponent.hxx:149 + enum utl::SharedUNOComponent::AssignmentMode NoTakeOwnership +include/unotools/useroptions.hxx:32 + enum UserOptToken City +include/unotools/useroptions.hxx:33 + enum UserOptToken Company +include/unotools/useroptions.hxx:34 + enum UserOptToken Country +include/unotools/useroptions.hxx:35 + enum UserOptToken Email +include/unotools/useroptions.hxx:36 + enum UserOptToken Fax +include/unotools/useroptions.hxx:37 + enum UserOptToken FirstName +include/unotools/useroptions.hxx:38 + enum UserOptToken LastName +include/unotools/useroptions.hxx:39 + enum UserOptToken Position +include/unotools/useroptions.hxx:40 + enum UserOptToken State +include/unotools/useroptions.hxx:41 + enum UserOptToken Street +include/unotools/useroptions.hxx:42 + enum UserOptToken TelephoneHome +include/unotools/useroptions.hxx:43 + enum UserOptToken TelephoneWork +include/unotools/useroptions.hxx:44 + enum UserOptToken Title +include/unotools/useroptions.hxx:46 + enum UserOptToken Zip +include/unotools/useroptions.hxx:47 + enum UserOptToken FathersName +include/unotools/useroptions.hxx:48 + enum UserOptToken Apartment +include/unotools/useroptions.hxx:49 + enum UserOptToken SigningKey +include/unotools/useroptions.hxx:50 + enum UserOptToken EncryptionKey +include/unotools/useroptions.hxx:51 + enum UserOptToken EncryptToSelf +include/vcl/decoview.hxx:49 + enum DrawHighlightFrameStyle Out +include/vcl/EnumContext.hxx:41 + enum vcl::EnumContext::Application Chart +include/vcl/EnumContext.hxx:56 + enum vcl::EnumContext::Application Any +include/vcl/EnumContext.hxx:68 + enum vcl::EnumContext::Context Auditing +include/vcl/EnumContext.hxx:69 + enum vcl::EnumContext::Context Axis +include/vcl/EnumContext.hxx:72 + enum vcl::EnumContext::Context ChartElements +include/vcl/EnumContext.hxx:74 + enum vcl::EnumContext::Context DrawFontwork +include/vcl/EnumContext.hxx:76 + enum vcl::EnumContext::Context DrawPage +include/vcl/EnumContext.hxx:79 + enum vcl::EnumContext::Context ErrorBar +include/vcl/EnumContext.hxx:81 + enum vcl::EnumContext::Context Frame +include/vcl/EnumContext.hxx:84 + enum vcl::EnumContext::Context HandoutPage +include/vcl/EnumContext.hxx:85 + enum vcl::EnumContext::Context MasterPage +include/vcl/EnumContext.hxx:88 + enum vcl::EnumContext::Context NotesPage +include/vcl/EnumContext.hxx:92 + enum vcl::EnumContext::Context Printpreview +include/vcl/EnumContext.hxx:93 + enum vcl::EnumContext::Context Series +include/vcl/EnumContext.hxx:94 + enum vcl::EnumContext::Context SlidesorterPage +include/vcl/EnumContext.hxx:98 + enum vcl::EnumContext::Context Trendline +include/vcl/errcode.hxx:61 + enum WarningFlag Yes +include/vcl/event.hxx:84 + enum MouseEventModifiers DRAGMOVE +include/vcl/event.hxx:85 + enum MouseEventModifiers DRAGCOPY +include/vcl/filter/pdfdocument.hxx:294 + enum vcl::filter::TokenizeMode END_OF_STREAM +include/vcl/filter/pdfdocument.hxx:300 + enum vcl::filter::TokenizeMode STORED_OBJECT +include/vcl/fntstyle.hxx:31 + enum FontKerning FontSpecific +include/vcl/font/Feature.hxx:29 + enum vcl::font::FeatureParameterType BOOL +include/vcl/font/Feature.hxx:35 + enum vcl::font::FeatureType OpenType +include/vcl/font/Feature.hxx:36 + enum vcl::font::FeatureType Graphite +include/vcl/formatter.hxx:82 + enum FORMAT_CHANGE_TYPE CURRENCY_SYMBOL +include/vcl/formatter.hxx:83 + enum FORMAT_CHANGE_TYPE CURRSYM_POSITION +include/vcl/formatter.hxx:120 + enum Formatter::valueState valueDirty +include/vcl/gdimtf.hxx:48 + enum MtfConversion N8BitGreys +include/vcl/GestureEvent.hxx:25 + enum PanningOrientation Horizontal +include/vcl/GestureEvent.hxx:26 + enum PanningOrientation Vertical +include/vcl/GraphicObject.hxx:40 + enum GraphicAdjustmentFlags ALL +include/vcl/graphictools.hxx:214 + enum SvtGraphicFill::FillRule fillNonZero +include/vcl/graphictools.hxx:239 + enum SvtGraphicFill::HatchType hatchSingle +include/vcl/graphictools.hxx:241 + enum SvtGraphicFill::HatchType hatchDouble +include/vcl/graphictools.hxx:246 + enum SvtGraphicFill::HatchType hatchTriple +include/vcl/graphictools.hxx:249 + enum SvtGraphicFill::GradientType Rectangular +include/vcl/graphictools.hxx:251 + enum SvtGraphicFill::(anonymous at /home/noel/libo2/include/vcl/graphictools.hxx:251:5) gradientStepsInfinite +include/vcl/headbar.hxx:183 + enum HeaderBarItemBits LEFT +include/vcl/headbar.hxx:192 + enum HeaderBarItemBits STDSTYLE +include/vcl/help.hxx:36 + enum QuickHelpFlags Center +include/vcl/help.hxx:39 + enum QuickHelpFlags VCenter +include/vcl/image.hxx:37 + enum StockImage Yes +include/vcl/inputctx.hxx:32 + enum InputContextFlags ExtText +include/vcl/inputtypes.hxx:27 + enum VclInputFlags MOUSE +include/vcl/inputtypes.hxx:28 + enum VclInputFlags KEYBOARD +include/vcl/inputtypes.hxx:29 + enum VclInputFlags PAINT +include/vcl/inputtypes.hxx:32 + enum VclInputFlags APPEVENT +include/vcl/keycodes.hxx:168 + enum ModKeyFlags LeftMod1 +include/vcl/keycodes.hxx:169 + enum ModKeyFlags RightMod1 +include/vcl/keycodes.hxx:170 + enum ModKeyFlags LeftMod2 +include/vcl/keycodes.hxx:171 + enum ModKeyFlags RightMod2 +include/vcl/keycodes.hxx:172 + enum ModKeyFlags LeftMod3 +include/vcl/keycodes.hxx:173 + enum ModKeyFlags RightMod3 +include/vcl/keycodes.hxx:188 + enum KeyIndicatorState NUMLOCK +include/vcl/outdev.hxx:138 + enum OutDevViewType DontKnow +include/vcl/outdev.hxx:138 + enum OutDevViewType SlideShow +include/vcl/pdf/PDFAnnotationMarker.hxx:58 + enum vcl::pdf::PDFTextMarkerType Highlight +include/vcl/pdf/PDFAnnotationSubType.hxx:33 + enum vcl::pdf::PDFAnnotationSubType Popup +include/vcl/pdfwriter.hxx:537 + enum vcl::PDFWriter::ColorMode DrawColor +include/vcl/rendercontext/AddFontSubstituteFlags.hxx:28 + enum AddFontSubstituteFlags ScreenOnly +include/vcl/rendercontext/DrawModeFlags.hxx:26 + enum DrawModeFlags Default +include/vcl/salgtype.hxx:30 + enum DeviceFormat DEFAULT +include/vcl/salnativewidgets.hxx:131 + enum ControlPart TrackHorzLeft +include/vcl/salnativewidgets.hxx:132 + enum ControlPart TrackVertUpper +include/vcl/salnativewidgets.hxx:133 + enum ControlPart TrackHorzRight +include/vcl/salnativewidgets.hxx:134 + enum ControlPart TrackVertLower +include/vcl/salnativewidgets.hxx:196 + enum ControlPart BackgroundWindow +include/vcl/salnativewidgets.hxx:197 + enum ControlPart BackgroundDialog +include/vcl/salnativewidgets.hxx:236 + enum ButtonValue DontKnow +include/vcl/sysdata.hxx:53 + enum SystemEnvData::Toolkit Gen +include/vcl/sysdata.hxx:53 + enum SystemEnvData::Toolkit Qt5 +include/vcl/sysdata.hxx:65 + enum SystemEnvData::Platform Xcb +include/vcl/syswin.hxx:51 + enum MenuBarMode Normal +include/vcl/task.hxx:29 + enum TaskPriority HIGHEST +include/vcl/task.hxx:30 + enum TaskPriority DEFAULT +include/vcl/task.hxx:33 + enum TaskPriority RESIZE +include/vcl/task.hxx:34 + enum TaskPriority REPAINT +include/vcl/task.hxx:35 + enum TaskPriority POST_PAINT +include/vcl/toolbox.hxx:52 + enum ToolBoxMenuType ClippedItems +include/vcl/toolbox.hxx:62 + enum ToolBoxLayoutMode Normal +include/vcl/toolbox.hxx:69 + enum ToolBoxTextPosition Bottom +include/vcl/toolkit/dialog.hxx:46 + enum Dialog::InitFlag Default +include/vcl/toolkit/floatwin.hxx:49 + enum FloatWinTitleType Unknown +include/vcl/toolkit/ivctrl.hxx:52 + enum SvxIconChoiceCtrlTextMode Short +include/vcl/toolkit/ivctrl.hxx:57 + enum SvxIconChoiceCtrlPositionMode Free +include/vcl/toolkit/svlbitm.hxx:40 + enum SvBmp CHECKED +include/vcl/toolkit/svlbitm.hxx:41 + enum SvBmp TRISTATE +include/vcl/toolkit/svlbitm.hxx:42 + enum SvBmp HIUNCHECKED +include/vcl/toolkit/svlbitm.hxx:43 + enum SvBmp HICHECKED +include/vcl/toolkit/svlbitm.hxx:44 + enum SvBmp HITRISTATE +include/vcl/toolkit/svtabbx.hxx:39 + enum SvTabJustify AdjustCenter +include/vcl/toolkit/treelistbox.hxx:67 + enum SvLBoxTabFlags ADJUST_LEFT +include/vcl/vclenum.hxx:38 + enum MenuItemBits HELP +include/vcl/vclenum.hxx:57 + enum ToolBoxItemBits AUTOSIZE +include/vcl/vclenum.hxx:69 + enum ToolBoxItemType DONTKNOW +include/vcl/vclenum.hxx:71 + enum ButtonType SYMBOLTEXT +include/vcl/vclenum.hxx:101 + enum SymbolType MENU +include/vcl/vclenum.hxx:109 + enum WindowBorderStyle NORMAL +include/vcl/vclenum.hxx:134 + enum WindowStateMask All +include/vcl/vclenum.hxx:143 + enum TimeFormat Hour24 +include/vcl/vclenum.hxx:314 + enum WindowStateState SystemMask +include/vcl/vclenum.hxx:331 + enum vcl::ImageType Small +include/vcl/vclenum.hxx:353 + enum DrawFrameFlags BorderWindowBorder +include/vcl/vclenum.hxx:407 + enum TrackingEventFlags Key +include/vcl/vclevent.hxx:92 + enum VclEventId ScrollbarEndScroll +include/vcl/vectorgraphicdata.hxx:111 + enum VectorGraphicData::State PARSED +include/vcl/VectorGraphicSearch.hxx:24 + enum SearchStartPosition Begin +include/vcl/virdev.hxx:44 + enum VirtualDevice::RefDevMode Custom +include/vcl/weld.hxx:831 + enum weld::ColumnToggleType Check +include/vcl/window.hxx:134 + enum PosSizeFlags PosSize +include/vcl/window.hxx:135 + enum PosSizeFlags All +include/vcl/window.hxx:249 + enum ShowTrackFlags Small +include/vcl/window.hxx:253 + enum ShowTrackFlags StyleMask +include/vcl/window.hxx:266 + enum StartTrackingFlags KeyMod +include/vcl/window.hxx:305 + enum StateChangedType Layout +include/vcl/window.hxx:320 + enum GetFocusFlags Around +include/vcl/window.hxx:323 + enum GetFocusFlags FloatWinPopupModeEndCancel +include/vcl/window.hxx:360 + enum EndExtTextInputFlags Complete +include/xmloff/families.hxx:75 + enum XmlStyleFamily TABLE_TEMPLATE_ID +include/xmloff/families.hxx:83 + enum XmlStyleFamily SD_PAGEMASTERCONTEXT_ID +include/xmloff/families.hxx:84 + enum XmlStyleFamily SD_PAGEMASTERSTYLECONTEXT_ID +include/xmloff/families.hxx:85 + enum XmlStyleFamily SD_PRESENTATIONPAGELAYOUT_ID +include/xmloff/families.hxx:91 + enum XmlStyleFamily SD_GRADIENT_ID +include/xmloff/families.hxx:92 + enum XmlStyleFamily SD_HATCH_ID +include/xmloff/families.hxx:93 + enum XmlStyleFamily SD_FILL_IMAGE_ID +include/xmloff/families.hxx:94 + enum XmlStyleFamily SD_MARKER_ID +include/xmloff/families.hxx:95 + enum XmlStyleFamily SD_STROKE_DASH_ID +include/xmloff/namespacemap.hxx:107 + enum SvXMLNamespaceMap::QNameMode AttrValue +include/xmloff/shapeexport.hxx:56 + enum XMLShapeExportFlags SIZE +include/xmloff/txtimp.hxx:76 + enum XMLTextType Footnote +include/xmloff/txtparae.hxx:73 + enum TextPNS ODF +include/xmloff/txtparae.hxx:118 + enum XMLTextParagraphExport::FieldmarkType CHECK +include/xmloff/xmlerror.hxx:82 + enum SvXMLErrorFlags WARNING_OCCURRED +include/xmloff/xmlexp.hxx:104 + enum SvXMLExportFlags ALL +include/xmloff/xmlnumfi.hxx:53 + enum SvXMLDateElementAttributes XML_DEA_SHORT +include/xmloff/xmlnumfi.hxx:54 + enum SvXMLDateElementAttributes XML_DEA_LONG +include/xmloff/xmlnumfi.hxx:55 + enum SvXMLDateElementAttributes XML_DEA_TEXTSHORT +include/xmloff/xmlnumfi.hxx:56 + enum SvXMLDateElementAttributes XML_DEA_TEXTLONG +include/xmloff/xmlnumfi.hxx:124 + enum SvXMLNumFormatContext::ImplicitCalendar DEFAULT_FROM_OTHER +include/xmlreader/xmlreader.hxx:42 + enum xmlreader::XmlReader::(anonymous at /home/noel/libo2/include/xmlreader/xmlreader.hxx:42:5) NAMESPACE_UNKNOWN +include/xmlreader/xmlreader.hxx:44 + enum xmlreader::XmlReader::Text Normalized +include/xmlreader/xmlreader.hxx:125 + enum xmlreader::XmlReader::State Done +jvmfwk/inc/vendorplugin.hxx:57 + enum javaPluginError InvalidArg +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:62 + enum jfw_plugin::SunVersion::PreRelease Rel_INTERNAL +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:63 + enum jfw_plugin::SunVersion::PreRelease Rel_EA +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:64 + enum jfw_plugin::SunVersion::PreRelease Rel_EA1 +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:65 + enum jfw_plugin::SunVersion::PreRelease Rel_EA2 +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:66 + enum jfw_plugin::SunVersion::PreRelease Rel_EA3 +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:67 + enum jfw_plugin::SunVersion::PreRelease Rel_BETA +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:68 + enum jfw_plugin::SunVersion::PreRelease Rel_BETA1 +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:69 + enum jfw_plugin::SunVersion::PreRelease Rel_BETA2 +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:70 + enum jfw_plugin::SunVersion::PreRelease Rel_BETA3 +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:71 + enum jfw_plugin::SunVersion::PreRelease Rel_RC +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:72 + enum jfw_plugin::SunVersion::PreRelease Rel_RC1 +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:73 + enum jfw_plugin::SunVersion::PreRelease Rel_RC2 +jvmfwk/plugins/sunmajor/pluginlib/sunversion.hxx:74 + enum jfw_plugin::SunVersion::PreRelease Rel_RC3 +jvmfwk/plugins/sunmajor/pluginlib/util.cxx:190 + enum jfw_plugin::(anonymous namespace)::FileHandleReader::Result RESULT_EOF +jvmfwk/plugins/sunmajor/pluginlib/util.cxx:200 + enum jfw_plugin::(anonymous namespace)::FileHandleReader::(anonymous at /home/noel/libo2/jvmfwk/plugins/sunmajor/pluginlib/util.cxx:200:5) BUFFER_SIZE +libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx:75 + enum (anonymous at /home/noel/libo2/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx:68:1) PROP_LAST +libreofficekit/source/gtk/lokdocview.cxx:271 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) LOAD_CHANGED +libreofficekit/source/gtk/lokdocview.cxx:272 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) EDIT_CHANGED +libreofficekit/source/gtk/lokdocview.cxx:273 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) COMMAND_CHANGED +libreofficekit/source/gtk/lokdocview.cxx:274 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) SEARCH_NOT_FOUND +libreofficekit/source/gtk/lokdocview.cxx:275 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) PART_CHANGED +libreofficekit/source/gtk/lokdocview.cxx:276 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) SIZE_CHANGED +libreofficekit/source/gtk/lokdocview.cxx:277 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) HYPERLINK_CLICKED +libreofficekit/source/gtk/lokdocview.cxx:278 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) CURSOR_CHANGED +libreofficekit/source/gtk/lokdocview.cxx:279 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) SEARCH_RESULT_COUNT +libreofficekit/source/gtk/lokdocview.cxx:280 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) COMMAND_RESULT +libreofficekit/source/gtk/lokdocview.cxx:281 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) ADDRESS_CHANGED +libreofficekit/source/gtk/lokdocview.cxx:282 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) FORMULA_CHANGED +libreofficekit/source/gtk/lokdocview.cxx:283 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) TEXT_SELECTION +libreofficekit/source/gtk/lokdocview.cxx:284 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) PASSWORD_REQUIRED +libreofficekit/source/gtk/lokdocview.cxx:285 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) COMMENT +libreofficekit/source/gtk/lokdocview.cxx:286 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) RULER +libreofficekit/source/gtk/lokdocview.cxx:287 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) WINDOW +libreofficekit/source/gtk/lokdocview.cxx:288 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) INVALIDATE_HEADER +libreofficekit/source/gtk/lokdocview.cxx:290 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:269:1) LAST_SIGNAL +libreofficekit/source/gtk/lokdocview.cxx:316 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/lokdocview.cxx:293:1) PROP_LAST +libreofficekit/source/gtk/tilebuffer.hxx:174 + enum (anonymous at /home/noel/libo2/libreofficekit/source/gtk/tilebuffer.hxx:171:1) LOK_TILEBUFFER_MEMORY +oox/inc/drawingml/chart/objectformatter.hxx:39 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_CHARTTITLE +oox/inc/drawingml/chart/objectformatter.hxx:40 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_LEGEND +oox/inc/drawingml/chart/objectformatter.hxx:41 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_PLOTAREA2D +oox/inc/drawingml/chart/objectformatter.hxx:42 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_PLOTAREA3D +oox/inc/drawingml/chart/objectformatter.hxx:45 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_AXIS +oox/inc/drawingml/chart/objectformatter.hxx:46 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_AXISTITLE +oox/inc/drawingml/chart/objectformatter.hxx:47 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_AXISUNIT +oox/inc/drawingml/chart/objectformatter.hxx:48 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_MAJORGRIDLINE +oox/inc/drawingml/chart/objectformatter.hxx:49 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_MINORGRIDLINE +oox/inc/drawingml/chart/objectformatter.hxx:50 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_LINEARSERIES2D +oox/inc/drawingml/chart/objectformatter.hxx:51 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_FILLEDSERIES2D +oox/inc/drawingml/chart/objectformatter.hxx:52 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_FILLEDSERIES3D +oox/inc/drawingml/chart/objectformatter.hxx:53 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_DATALABEL +oox/inc/drawingml/chart/objectformatter.hxx:54 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_TRENDLINE +oox/inc/drawingml/chart/objectformatter.hxx:55 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_TRENDLINELABEL +oox/inc/drawingml/chart/objectformatter.hxx:56 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_ERRORBAR +oox/inc/drawingml/chart/objectformatter.hxx:57 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_SERLINE +oox/inc/drawingml/chart/objectformatter.hxx:58 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_LEADERLINE +oox/inc/drawingml/chart/objectformatter.hxx:59 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_DROPLINE +oox/inc/drawingml/chart/objectformatter.hxx:60 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_HILOLINE +oox/inc/drawingml/chart/objectformatter.hxx:61 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_UPBAR +oox/inc/drawingml/chart/objectformatter.hxx:62 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_DOWNBAR +oox/inc/drawingml/chart/objectformatter.hxx:63 + enum oox::drawingml::chart::ObjectType OBJECTTYPE_DATATABLE +oox/inc/drawingml/chart/seriesmodel.hxx:172 + enum oox::drawingml::chart::SeriesModel::SourceType CATEGORIES +oox/inc/drawingml/chart/seriesmodel.hxx:173 + enum oox::drawingml::chart::SeriesModel::SourceType VALUES +oox/inc/drawingml/chart/seriesmodel.hxx:174 + enum oox::drawingml::chart::SeriesModel::SourceType POINTS +oox/inc/drawingml/chart/typegroupconverter.hxx:58 + enum oox::drawingml::chart::TypeCategory TYPECATEGORY_LINE +oox/inc/drawingml/chart/typegroupconverter.hxx:61 + enum oox::drawingml::chart::TypeCategory TYPECATEGORY_SCATTER +oox/inc/drawingml/chart/typegroupconverter.hxx:62 + enum oox::drawingml::chart::TypeCategory TYPECATEGORY_SURFACE +oox/inc/drawingml/textspacing.hxx:35 + enum oox::drawingml::TextSpacing::Unit Points +oox/source/export/shapes.cxx:2001 + enum (anonymous at /home/noel/libo2/oox/source/export/shapes.cxx:2001:5) OTHER +pyuno/inc/pyuno.hxx:65 + enum pyuno::NotNull NOT_NULL +pyuno/inc/pyuno.hxx:153 + enum pyuno::ConversionMode REJECT_UNO_ANY +reportdesign/inc/RptObject.hxx:40 + enum rptui::DlgEdHintKind RPTUI_HINT_WINDOWSCROLLED +reportdesign/source/filter/xml/xmlEnums.hxx:28 + enum rptxml::XMLReportToken XML_TOK_REPORT_HEADER +reportdesign/source/filter/xml/xmlEnums.hxx:29 + enum rptxml::XMLReportToken XML_TOK_PAGE_HEADER +reportdesign/source/filter/xml/xmlEnums.hxx:30 + enum rptxml::XMLReportToken XML_TOK_GROUP +reportdesign/source/filter/xml/xmlEnums.hxx:31 + enum rptxml::XMLReportToken XML_TOK_DETAIL +reportdesign/source/filter/xml/xmlEnums.hxx:32 + enum rptxml::XMLReportToken XML_TOK_PAGE_FOOTER +reportdesign/source/filter/xml/xmlEnums.hxx:33 + enum rptxml::XMLReportToken XML_TOK_REPORT_FOOTER +reportdesign/source/filter/xml/xmlEnums.hxx:34 + enum rptxml::XMLReportToken XML_TOK_HEADER_ON_NEW_PAGE +reportdesign/source/filter/xml/xmlEnums.hxx:35 + enum rptxml::XMLReportToken XML_TOK_FOOTER_ON_NEW_PAGE +reportdesign/source/filter/xml/xmlEnums.hxx:39 + enum rptxml::XMLReportToken XML_TOK_CAPTION +reportdesign/source/filter/xml/xmlEnums.hxx:41 + enum rptxml::XMLReportToken XML_TOK_REPORT_FUNCTION +reportdesign/source/filter/xml/xmlEnums.hxx:43 + enum rptxml::XMLReportToken XML_TOK_REPORT_MIMETYPE +reportdesign/source/filter/xml/xmlEnums.hxx:44 + enum rptxml::XMLReportToken XML_TOK_REPORT_NAME +reportdesign/source/filter/xml/xmlEnums.hxx:45 + enum rptxml::XMLReportToken XML_TOK_MASTER_DETAIL_FIELDS +reportdesign/source/filter/xml/xmlEnums.hxx:46 + enum rptxml::XMLReportToken XML_TOK_SUB_FRAME +reportdesign/source/filter/xml/xmlEnums.hxx:47 + enum rptxml::XMLReportToken XML_TOK_SUB_BODY +reportdesign/source/filter/xml/xmlEnums.hxx:52 + enum rptxml::XMLSubDocument XML_TOK_MASTER_DETAIL_FIELD +sal/osl/all/log.cxx:393 + enum Sense NEGATIVE +sal/rtl/bootstrap.cxx:87 + enum (anonymous namespace)::LookupMode LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION +sal/rtl/rtl_process.cxx:44 + enum (anonymous namespace)::Id::(anonymous at /home/noel/libo2/sal/rtl/rtl_process.cxx:44:5) UUID_SIZE +sal/rtl/ustring.cxx:881 + enum (anonymous namespace)::StrLifecycle CANNOT_RETURN +sal/rtl/ustring.cxx:882 + enum (anonymous namespace)::StrLifecycle CAN_RETURN +sc/inc/address.hxx:159 + enum ScRefFlags BITS +sc/inc/address.hxx:169 + enum ScRefFlags TAB_ABS_3D +sc/inc/address.hxx:171 + enum ScRefFlags ADDR_ABS +sc/inc/address.hxx:173 + enum ScRefFlags RANGE_ABS +sc/inc/address.hxx:175 + enum ScRefFlags ADDR_ABS_3D +sc/inc/address.hxx:176 + enum ScRefFlags RANGE_ABS_3D +sc/inc/address.hxx:207 + enum ScAddress::Uninitialized UNINITIALIZED +sc/inc/address.hxx:208 + enum ScAddress::InitializeInvalid INITIALIZE_INVALID +sc/inc/attrib.hxx:43 + enum ScMF DpTable +sc/inc/chartpos.hxx:95 + enum ScChartGlue Cols +sc/inc/chartpos.hxx:97 + enum ScChartGlue Both +sc/inc/chgtrack.hxx:595 + enum ScChangeActionContentCellType SC_CACCT_NORMAL +sc/inc/colorscale.hxx:190 + enum ScIconSetType IconSet_3Arrows +sc/inc/colorscale.hxx:191 + enum ScIconSetType IconSet_3ArrowsGray +sc/inc/colorscale.hxx:192 + enum ScIconSetType IconSet_3Flags +sc/inc/colorscale.hxx:193 + enum ScIconSetType IconSet_3TrafficLights1 +sc/inc/colorscale.hxx:194 + enum ScIconSetType IconSet_3TrafficLights2 +sc/inc/colorscale.hxx:195 + enum ScIconSetType IconSet_3Signs +sc/inc/colorscale.hxx:196 + enum ScIconSetType IconSet_3Symbols +sc/inc/colorscale.hxx:197 + enum ScIconSetType IconSet_3Symbols2 +sc/inc/colorscale.hxx:202 + enum ScIconSetType IconSet_4Arrows +sc/inc/colorscale.hxx:203 + enum ScIconSetType IconSet_4ArrowsGray +sc/inc/colorscale.hxx:204 + enum ScIconSetType IconSet_4RedToBlack +sc/inc/colorscale.hxx:205 + enum ScIconSetType IconSet_4Rating +sc/inc/colorscale.hxx:206 + enum ScIconSetType IconSet_4TrafficLights +sc/inc/colorscale.hxx:207 + enum ScIconSetType IconSet_5Arrows +sc/inc/colorscale.hxx:208 + enum ScIconSetType IconSet_5ArrowsGray +sc/inc/colorscale.hxx:209 + enum ScIconSetType IconSet_5Ratings +sc/inc/colorscale.hxx:210 + enum ScIconSetType IconSet_5Quarters +sc/inc/compiler.hxx:51 + enum ScCharFlags Illegal +sc/inc/compiler.hxx:54 + enum ScCharFlags CharWord +sc/inc/compiler.hxx:67 + enum ScCharFlags NameSep +sc/inc/compiler.hxx:74 + enum ScCharFlags CharName +sc/inc/compiler.hxx:75 + enum ScCharFlags Name +sc/inc/datastreamgettime.hxx:30 + enum sc::DebugTime Render +sc/inc/detfunc.hxx:45 + enum ScDetectiveObjType SC_DETOBJ_RECTANGLE +sc/inc/dociter.hxx:255 + enum ScQueryCellIterator::StopOnMismatchBits nStopOnMismatchDisabled +sc/inc/dociter.hxx:256 + enum ScQueryCellIterator::StopOnMismatchBits nStopOnMismatchEnabled +sc/inc/dociter.hxx:257 + enum ScQueryCellIterator::StopOnMismatchBits nStopOnMismatchOccurred +sc/inc/dociter.hxx:263 + enum ScQueryCellIterator::TestEqualConditionBits nTestEqualConditionDisabled +sc/inc/dociter.hxx:264 + enum ScQueryCellIterator::TestEqualConditionBits nTestEqualConditionEnabled +sc/inc/dociter.hxx:265 + enum ScQueryCellIterator::TestEqualConditionBits nTestEqualConditionMatched +sc/inc/document.hxx:254 + enum CommentCaptionState ALLSHOWN +sc/inc/document.hxx:262 + enum RangeNameScope SHEET +sc/inc/document.hxx:307 + enum ScMutationGuardFlags CORE +sc/inc/document.hxx:349 + enum ScDocument::HardRecalcState TEMPORARY +sc/inc/dpglobal.hxx:46 + enum ScDPValue::Type Value +sc/inc/formulacell.hxx:173 + enum ScFormulaCell::CompareState EqualRelativeRef +sc/inc/formulacell.hxx:272 + enum ScFormulaCell::RelNameRef SINGLE +sc/inc/importfilterdata.hxx:33 + enum sc::ImportPostProcessData::DataStream::InsertPos InsertBottom +sc/inc/lookupcache.hxx:55 + enum ScLookupCache::QueryOp LESS_EQUAL +sc/inc/lookupcache.hxx:56 + enum ScLookupCache::QueryOp GREATER_EQUAL +sc/inc/patattr.hxx:46 + enum ScAutoFontColorMode SC_AUTOCOL_DISPLAY +sc/inc/PivotTableDataSequence.hxx:35 + enum sc::ValueType Empty +sc/inc/rangenam.hxx:50 + enum ScRangeData::Type Name +sc/inc/rangenam.hxx:51 + enum ScRangeData::Type Database +sc/inc/rangenam.hxx:53 + enum ScRangeData::Type PrintArea +sc/inc/rangenam.hxx:54 + enum ScRangeData::Type ColHeader +sc/inc/rangenam.hxx:55 + enum ScRangeData::Type RowHeader +sc/inc/sheetevents.hxx:28 + enum ScSheetEventId CALCULATE +sc/inc/sheetevents.hxx:28 + enum ScSheetEventId CHANGE +sc/inc/sheetevents.hxx:28 + enum ScSheetEventId DOUBLECLICK +sc/inc/sheetevents.hxx:28 + enum ScSheetEventId FOCUS +sc/inc/sheetevents.hxx:28 + enum ScSheetEventId RIGHTCLICK +sc/inc/sheetevents.hxx:28 + enum ScSheetEventId SELECT +sc/inc/sheetevents.hxx:28 + enum ScSheetEventId UNFOCUS +sc/inc/stlsheet.hxx:38 + enum ScStyleSheet::Usage NOTUSED +sc/inc/stringutil.hxx:57 + enum ScSetStringParam::TextFormatPolicy Keep +sc/inc/tabprotection.hxx:100 + enum ScDocProtection::Option STRUCTURE +sc/inc/tabprotection.hxx:101 + enum ScDocProtection::Option WINDOWS +sc/inc/tabprotection.hxx:171 + enum ScTableProtection::Option AUTOFILTER +sc/inc/tabprotection.hxx:172 + enum ScTableProtection::Option DELETE_COLUMNS +sc/inc/tabprotection.hxx:173 + enum ScTableProtection::Option DELETE_ROWS +sc/inc/tabprotection.hxx:174 + enum ScTableProtection::Option FORMAT_CELLS +sc/inc/tabprotection.hxx:175 + enum ScTableProtection::Option FORMAT_COLUMNS +sc/inc/tabprotection.hxx:176 + enum ScTableProtection::Option FORMAT_ROWS +sc/inc/tabprotection.hxx:177 + enum ScTableProtection::Option INSERT_COLUMNS +sc/inc/tabprotection.hxx:178 + enum ScTableProtection::Option INSERT_HYPERLINKS +sc/inc/tabprotection.hxx:179 + enum ScTableProtection::Option INSERT_ROWS +sc/inc/tabprotection.hxx:180 + enum ScTableProtection::Option OBJECTS +sc/inc/tabprotection.hxx:181 + enum ScTableProtection::Option PIVOT_TABLES +sc/inc/tabprotection.hxx:182 + enum ScTableProtection::Option SCENARIOS +sc/inc/tabprotection.hxx:183 + enum ScTableProtection::Option SELECT_LOCKED_CELLS +sc/inc/tabprotection.hxx:184 + enum ScTableProtection::Option SELECT_UNLOCKED_CELLS +sc/inc/tabprotection.hxx:185 + enum ScTableProtection::Option SORT +sc/inc/typedstrdata.hxx:21 + enum ScTypedStrData::StringType Standard +sc/inc/typedstrdata.hxx:22 + enum ScTypedStrData::StringType Name +sc/inc/typedstrdata.hxx:23 + enum ScTypedStrData::StringType DbName +sc/inc/typedstrdata.hxx:24 + enum ScTypedStrData::StringType Header +sc/inc/types.hxx:78 + enum sc::GroupCalcState GroupCalcEnabled +sc/inc/types.hxx:99 + enum sc::MultiDataCellState::StateType Invalid +sc/inc/viewopti.hxx:32 + enum ScViewOption VOPT_FORMULAS +sc/inc/viewopti.hxx:33 + enum ScViewOption VOPT_NULLVALS +sc/inc/viewopti.hxx:34 + enum ScViewOption VOPT_SYNTAX +sc/inc/viewopti.hxx:35 + enum ScViewOption VOPT_NOTES +sc/inc/viewopti.hxx:36 + enum ScViewOption VOPT_VSCROLL +sc/inc/viewopti.hxx:37 + enum ScViewOption VOPT_HSCROLL +sc/inc/viewopti.hxx:38 + enum ScViewOption VOPT_TABCONTROLS +sc/inc/viewopti.hxx:39 + enum ScViewOption VOPT_OUTLINER +sc/inc/viewopti.hxx:40 + enum ScViewOption VOPT_HEADER +sc/inc/viewopti.hxx:41 + enum ScViewOption VOPT_GRID +sc/inc/viewopti.hxx:42 + enum ScViewOption VOPT_GRID_ONTOP +sc/inc/viewopti.hxx:43 + enum ScViewOption VOPT_HELPLINES +sc/inc/viewopti.hxx:44 + enum ScViewOption VOPT_ANCHOR +sc/inc/viewopti.hxx:45 + enum ScViewOption VOPT_PAGEBREAKS +sc/inc/viewopti.hxx:46 + enum ScViewOption VOPT_SUMMARY +sc/inc/viewopti.hxx:47 + enum ScViewOption VOPT_THEMEDCURSOR +sc/inc/viewopti.hxx:53 + enum ScVObjType VOBJ_TYPE_OLE +sc/inc/viewopti.hxx:54 + enum ScVObjType VOBJ_TYPE_CHART +sc/inc/xmlwrap.hxx:49 + enum ImportFlags All +sc/source/core/data/document10.cxx:647 + enum (anonymous namespace)::MightReferenceSheet CODE +sc/source/core/inc/refupdat.hxx:32 + enum ScRefUpdateRes UR_UPDATED +sc/source/core/inc/refupdat.hxx:34 + enum ScRefUpdateRes UR_STICKY +sc/source/core/opencl/op_statistical.cxx:7653 + enum sc::opencl::(anonymous namespace)::MixDoubleString svDoubleVectorRefNULL +sc/source/core/opencl/op_statistical.cxx:7657 + enum sc::opencl::(anonymous namespace)::MixDoubleString svSingleVectorRefNULL +sc/source/core/tool/cellkeytranslator.cxx:39 + enum (anonymous namespace)::LocaleMatch LOCALE_MATCH_LANG +sc/source/core/tool/cellkeytranslator.cxx:40 + enum (anonymous namespace)::LocaleMatch LOCALE_MATCH_LANG_SCRIPT +sc/source/core/tool/cellkeytranslator.cxx:41 + enum (anonymous namespace)::LocaleMatch LOCALE_MATCH_LANG_SCRIPT_COUNTRY +sc/source/core/tool/token.cxx:2764 + enum (anonymous namespace)::ShrinkResult UNMODIFIED +sc/source/filter/excel/xeformula.cxx:227 + enum (anonymous namespace)::XclExpFmlaClassType EXC_CLASSTYPE_ARRAY +sc/source/filter/excel/xestyle.cxx:1615 + enum CalcLineIndex Idx_DashDot +sc/source/filter/excel/xestyle.cxx:1615 + enum CalcLineIndex Idx_DashDotDot +sc/source/filter/excel/xestyle.cxx:1615 + enum CalcLineIndex Idx_Dashed +sc/source/filter/excel/xestyle.cxx:1615 + enum CalcLineIndex Idx_Dotted +sc/source/filter/excel/xestyle.cxx:1615 + enum CalcLineIndex Idx_DoubleThin +sc/source/filter/excel/xestyle.cxx:1615 + enum CalcLineIndex Idx_FineDashed +sc/source/filter/excel/xestyle.cxx:1615 + enum CalcLineIndex Idx_Last +sc/source/filter/excel/xestyle.cxx:1615 + enum CalcLineIndex Idx_Solid +sc/source/filter/excel/xestyle.cxx:1616 + enum ExcelWidthIndex Width_Hair +sc/source/filter/excel/xestyle.cxx:1616 + enum ExcelWidthIndex Width_Last +sc/source/filter/excel/xestyle.cxx:1616 + enum ExcelWidthIndex Width_Medium +sc/source/filter/excel/xestyle.cxx:1616 + enum ExcelWidthIndex Width_Thick +sc/source/filter/excel/xestyle.cxx:1616 + enum ExcelWidthIndex Width_Thin +sc/source/filter/excel/xiescher.cxx:473 + enum (anonymous at /home/noel/libo2/sc/source/filter/excel/xiescher.cxx:473:17) eCreateFromMSOCXControl +sc/source/filter/excel/xiescher.cxx:473 + enum (anonymous at /home/noel/libo2/sc/source/filter/excel/xiescher.cxx:473:17) eCreateFromMSTBXControl +sc/source/filter/inc/colrowst.hxx:30 + enum ExcColRowFlags Hidden +sc/source/filter/inc/decl.h:23 + enum WKTYP eWK_UNKNOWN +sc/source/filter/inc/externallinkbuffer.hxx:148 + enum oox::xls::LinkSheetRange::LinkSheetRangeType LINKSHEETRANGE_INTERNAL +sc/source/filter/inc/formel.hxx:48 + enum FORMULA_TYPE FT_CellFormula +sc/source/filter/inc/formulabase.hxx:370 + enum oox::xls::FuncParamValidity Regular +sc/source/filter/inc/formulabase.hxx:467 + enum oox::xls::FunctionLibraryType FUNCLIB_EUROTOOL +sc/source/filter/inc/htmlpars.hxx:223 + enum ScHTMLOrient tdRow +sc/source/filter/inc/orcusinterface.hxx:232 + enum ScOrcusFormula::ResultType Empty +sc/source/filter/inc/orcusinterface.hxx:232 + enum ScOrcusFormula::ResultType NotSet +sc/source/filter/inc/xeextlst.hxx:21 + enum XclExpExtType XclExpExtDataBarType +sc/source/filter/inc/xeextlst.hxx:22 + enum XclExpExtType XclExpExtDataFooType +sc/source/filter/inc/xelink.hxx:47 + enum ExcTabBufFlags Ignore +sc/source/filter/inc/xelink.hxx:48 + enum ExcTabBufFlags Extern +sc/source/filter/inc/xelink.hxx:49 + enum ExcTabBufFlags SkipMask +sc/source/filter/inc/xelink.hxx:50 + enum ExcTabBufFlags Visible +sc/source/filter/inc/xelink.hxx:51 + enum ExcTabBufFlags Selected +sc/source/filter/inc/xelink.hxx:52 + enum ExcTabBufFlags Mirrored +sc/source/filter/inc/xicontent.hxx:216 + enum XclImpWebQuery::XclImpWebQueryMode xlWQDocument +sc/source/filter/inc/xihelper.hxx:186 + enum XclImpHFConverter::XclImpHFPortion EXC_HF_PORTION_COUNT +sc/source/filter/inc/xistyle.hxx:643 + enum XclImpXFRangeBuffer::XclImpXFInsertMode xlXFModeCell +sc/source/filter/inc/xlchart.hxx:1112 + enum XclChObjectType EXC_CHOBJTYPE_BACKGROUND +sc/source/filter/inc/xlchart.hxx:1113 + enum XclChObjectType EXC_CHOBJTYPE_PLOTFRAME +sc/source/filter/inc/xlchart.hxx:1116 + enum XclChObjectType EXC_CHOBJTYPE_TEXT +sc/source/filter/inc/xlchart.hxx:1117 + enum XclChObjectType EXC_CHOBJTYPE_LEGEND +sc/source/filter/inc/xlchart.hxx:1120 + enum XclChObjectType EXC_CHOBJTYPE_AXISLINE +sc/source/filter/inc/xlchart.hxx:1121 + enum XclChObjectType EXC_CHOBJTYPE_GRIDLINE +sc/source/filter/inc/xlchart.hxx:1122 + enum XclChObjectType EXC_CHOBJTYPE_TRENDLINE +sc/source/filter/inc/xlchart.hxx:1123 + enum XclChObjectType EXC_CHOBJTYPE_ERRORBAR +sc/source/filter/inc/xlchart.hxx:1124 + enum XclChObjectType EXC_CHOBJTYPE_CONNECTLINE +sc/source/filter/inc/xlchart.hxx:1125 + enum XclChObjectType EXC_CHOBJTYPE_HILOLINE +sc/source/filter/inc/xlchart.hxx:1126 + enum XclChObjectType EXC_CHOBJTYPE_WHITEDROPBAR +sc/source/filter/inc/xlchart.hxx:1127 + enum XclChObjectType EXC_CHOBJTYPE_BLACKDROPBAR +sc/source/filter/inc/xlchart.hxx:1170 + enum XclChTypeId EXC_CHTYPEID_BAR +sc/source/filter/inc/xlchart.hxx:1171 + enum XclChTypeId EXC_CHTYPEID_HORBAR +sc/source/filter/inc/xlchart.hxx:1172 + enum XclChTypeId EXC_CHTYPEID_LINE +sc/source/filter/inc/xlchart.hxx:1173 + enum XclChTypeId EXC_CHTYPEID_AREA +sc/source/filter/inc/xlchart.hxx:1175 + enum XclChTypeId EXC_CHTYPEID_RADARLINE +sc/source/filter/inc/xlchart.hxx:1176 + enum XclChTypeId EXC_CHTYPEID_RADARAREA +sc/source/filter/inc/xlchart.hxx:1177 + enum XclChTypeId EXC_CHTYPEID_PIE +sc/source/filter/inc/xlchart.hxx:1180 + enum XclChTypeId EXC_CHTYPEID_SCATTER +sc/source/filter/inc/xlchart.hxx:1194 + enum XclChTypeCateg EXC_CHTYPECATEG_SURFACE +sc/source/filter/inc/xlescher.hxx:407 + enum XclTbxEventType EXC_TBX_EVENT_ACTION +sc/source/filter/inc/xlescher.hxx:408 + enum XclTbxEventType EXC_TBX_EVENT_MOUSE +sc/source/filter/inc/xlescher.hxx:409 + enum XclTbxEventType EXC_TBX_EVENT_TEXT +sc/source/filter/inc/xlescher.hxx:410 + enum XclTbxEventType EXC_TBX_EVENT_VALUE +sc/source/filter/inc/xlescher.hxx:411 + enum XclTbxEventType EXC_TBX_EVENT_CHANGE +sc/source/filter/inc/xlformula.hxx:165 + enum XclFormulaType EXC_FMLATYPE_DATAVAL +sc/source/filter/inc/xlformula.hxx:166 + enum XclFormulaType EXC_FMLATYPE_NAME +sc/source/filter/inc/xlformula.hxx:168 + enum XclFormulaType EXC_FMLATYPE_CONTROL +sc/source/filter/inc/xlformula.hxx:169 + enum XclFormulaType EXC_FMLATYPE_WQUERY +sc/source/filter/inc/xlformula.hxx:170 + enum XclFormulaType EXC_FMLATYPE_LISTVAL +sc/source/filter/inc/xlformula.hxx:179 + enum XclFuncParamValidity EXC_PARAM_REGULAR +sc/source/filter/inc/xlstyle.hxx:390 + enum XclFontItemType Editeng +sc/source/filter/oox/formulabase.cxx:62 + enum (anonymous namespace)::FuncFlags MACROCALL_NEW +sc/source/filter/oox/pagesettings.cxx:354 + enum oox::xls::(anonymous namespace)::HFPortionId HF_COUNT +sc/source/filter/oox/revisionfragment.cxx:44 + enum oox::xls::(anonymous namespace)::RevisionType REV_UNKNOWN +sc/source/filter/xml/XMLConverter.hxx:101 + enum ScXMLConditionToken XML_COND_INVALID +sc/source/ui/dbgui/scuiasciiopt.cxx:60 + enum (anonymous namespace)::CSVImportOptionsIndex CSVIO_Text2ColSkipEmptyCells +sc/source/ui/inc/AccessibleEditObject.hxx:51 + enum ScAccessibleEditObject::EditObjectType EditLine +sc/source/ui/inc/anyrefdg.hxx:142 + enum ScRefHdlrControllerImpl::(anonymous at /home/noel/libo2/sc/source/ui/inc/anyrefdg.hxx:142:5) UNKNOWN_SLOTID +sc/source/ui/inc/anyrefdg.hxx:142 + enum ScRefHdlrControllerImpl::(anonymous at /home/noel/libo2/sc/source/ui/inc/anyrefdg.hxx:142:5) UNKNOWN_SLOTID +sc/source/ui/inc/anyrefdg.hxx:142 + enum ScRefHdlrControllerImpl::(anonymous at /home/noel/libo2/sc/source/ui/inc/anyrefdg.hxx:142:5) UNKNOWN_SLOTID +sc/source/ui/inc/checklistmenu.hxx:31 + enum ScCheckListMember::DatePartType YEAR +sc/source/ui/inc/checklistmenu.hxx:32 + enum ScCheckListMember::DatePartType MONTH +sc/source/ui/inc/csvcontrol.hxx:92 + enum ScCsvDiff HeaderWidth +sc/source/ui/inc/csvcontrol.hxx:93 + enum ScCsvDiff CharWidth +sc/source/ui/inc/csvcontrol.hxx:94 + enum ScCsvDiff LineCount +sc/source/ui/inc/csvcontrol.hxx:96 + enum ScCsvDiff HeaderHeight +sc/source/ui/inc/csvcontrol.hxx:97 + enum ScCsvDiff LineHeight +sc/source/ui/inc/csvcontrol.hxx:99 + enum ScCsvDiff GridCursor +sc/source/ui/inc/csvcontrol.hxx:102 + enum ScCsvDiff VerticalMask +sc/source/ui/inc/datastream.hxx:65 + enum sc::DataStream::(anonymous at /home/noel/libo2/sc/source/ui/inc/datastream.hxx:65:5) VALUES_IN_LINE +sc/source/ui/inc/olinewin.hxx:28 + enum ScOutlineMode SC_OUTLINE_VER +sc/source/ui/inc/pfuncache.hxx:35 + enum ScPrintSelectionMode SC_PRINTSEL_INVALID +sc/source/ui/inc/pfuncache.hxx:36 + enum ScPrintSelectionMode SC_PRINTSEL_DOCUMENT +sc/source/ui/inc/pfuncache.hxx:37 + enum ScPrintSelectionMode SC_PRINTSEL_CURSOR +sc/source/ui/inc/PivotLayoutTreeListBase.hxx:38 + enum ScPivotLayoutTreeListBase::SvPivotTreeListType UNDEFINED +sc/source/ui/inc/selectionstate.hxx:30 + enum ScSelectionType SC_SELECTTYPE_EDITCELL +sc/source/ui/inc/StatisticsInputOutputDialog.hxx:22 + enum ScStatisticsInputOutputDialog::GroupedBy BY_ROW +sc/source/ui/inc/StatisticsTwoVariableDialog.hxx:22 + enum ScStatisticsTwoVariableDialog::GroupedBy BY_ROW +sc/source/ui/inc/tabview.hxx:119 + enum ScTabView::BlockMode Normal +sc/source/ui/inc/undobase.hxx:75 + enum ScBlockUndoMode SC_UNDO_MANUALHEIGHT +sc/source/ui/inc/undobase.hxx:75 + enum ScBlockUndoMode SC_UNDO_SIMPLE +sc/source/ui/inc/validate.hxx:221 + enum ScValidationDlg::(anonymous at /home/noel/libo2/sc/source/ui/inc/validate.hxx:221:5) SLOTID +sc/source/ui/inc/viewdata.hxx:66 + enum ScMarkType SC_MARK_FILTERED +sc/source/ui/inc/viewdata.hxx:92 + enum ScDragSrc Undefined +sc/source/ui/pagedlg/areasdlg.cxx:41 + enum (anonymous at /home/noel/libo2/sc/source/ui/pagedlg/areasdlg.cxx:39:1) SC_AREASDLG_PR_USER +sc/source/ui/pagedlg/areasdlg.cxx:42 + enum (anonymous at /home/noel/libo2/sc/source/ui/pagedlg/areasdlg.cxx:39:1) SC_AREASDLG_PR_SELECT +sc/source/ui/pagedlg/areasdlg.cxx:48 + enum (anonymous at /home/noel/libo2/sc/source/ui/pagedlg/areasdlg.cxx:46:1) SC_AREASDLG_RR_USER +sc/source/ui/pagedlg/areasdlg.cxx:49 + enum (anonymous at /home/noel/libo2/sc/source/ui/pagedlg/areasdlg.cxx:46:1) SC_AREASDLG_RR_OFFSET +sc/source/ui/unoobj/cellsuno.cxx:9097 + enum (anonymous namespace)::ScUniqueFormatsEntry::EntryState STATE_COMPLEX +sc/source/ui/unoobj/chart2uno.cxx:449 + enum (anonymous namespace)::Chart2Positioner::GlueType GLUETYPE_COLS +sc/source/ui/unoobj/chart2uno.cxx:450 + enum (anonymous namespace)::Chart2Positioner::GlueType GLUETYPE_ROWS +sc/source/ui/unoobj/chart2uno.cxx:451 + enum (anonymous namespace)::Chart2Positioner::GlueType GLUETYPE_BOTH +sc/source/ui/unoobj/chart2uno.cxx:601 + enum (anonymous namespace)::State Glue +sc/source/ui/unoobj/fielduno.cxx:155 + enum (anonymous namespace)::ScUnoCollectMode SC_UNO_COLLECT_COUNT +sc/source/ui/view/prevloc.cxx:38 + enum (anonymous namespace)::ScPreviewLocationType SC_PLOC_NOTEMARK +sc/source/ui/view/prevloc.cxx:39 + enum (anonymous namespace)::ScPreviewLocationType SC_PLOC_NOTETEXT +sc/source/ui/view/tabview3.cxx:1467 + enum (anonymous at /home/noel/libo2/sc/source/ui/view/tabview3.cxx:1467:5) MOD_BOTH +sc/source/ui/view/viewfun2.cxx:254 + enum (anonymous namespace)::ScAutoSum ScAutoSumAverage +sc/source/ui/view/viewfun2.cxx:255 + enum (anonymous namespace)::ScAutoSum ScAutoSumMax +sc/source/ui/view/viewfun2.cxx:256 + enum (anonymous namespace)::ScAutoSum ScAutoSumMin +scaddins/source/analysis/analysishelper.hxx:493 + enum sca::analysis::ConvertDataClass CDC_Energy +scaddins/source/analysis/analysishelper.hxx:493 + enum sca::analysis::ConvertDataClass CDC_Force +scaddins/source/analysis/analysishelper.hxx:493 + enum sca::analysis::ConvertDataClass CDC_Length +scaddins/source/analysis/analysishelper.hxx:493 + enum sca::analysis::ConvertDataClass CDC_Magnetism +scaddins/source/analysis/analysishelper.hxx:493 + enum sca::analysis::ConvertDataClass CDC_Mass +scaddins/source/analysis/analysishelper.hxx:493 + enum sca::analysis::ConvertDataClass CDC_Power +scaddins/source/analysis/analysishelper.hxx:493 + enum sca::analysis::ConvertDataClass CDC_Pressure +scaddins/source/analysis/analysishelper.hxx:493 + enum sca::analysis::ConvertDataClass CDC_Time +scaddins/source/analysis/analysishelper.hxx:494 + enum sca::analysis::ConvertDataClass CDC_Area +scaddins/source/analysis/analysishelper.hxx:494 + enum sca::analysis::ConvertDataClass CDC_Speed +scaddins/source/analysis/analysishelper.hxx:494 + enum sca::analysis::ConvertDataClass CDC_Temperature +scaddins/source/analysis/analysishelper.hxx:494 + enum sca::analysis::ConvertDataClass CDC_Volume +sd/inc/diadef.h:26 + enum PresChange SemiAuto +sd/inc/sdenumdef.hxx:28 + enum SnapKind Point +sd/inc/sdmod.hxx:54 + enum SdOptionStreamMode Load +sd/inc/sdxmlwrp.hxx:30 + enum SdXMLFilterMode Normal +sd/source/filter/eppt/pptx-epptooxml.cxx:181 + enum (anonymous namespace)::PPTXLayout LAYOUT_BLANK +sd/source/filter/eppt/pptx-epptooxml.cxx:182 + enum (anonymous namespace)::PPTXLayout LAYOUT_TITLE_SLIDE +sd/source/filter/eppt/pptx-epptooxml.cxx:183 + enum (anonymous namespace)::PPTXLayout LAYOUT_TITLE_CONTENT +sd/source/filter/eppt/pptx-epptooxml.cxx:184 + enum (anonymous namespace)::PPTXLayout LAYOUT_TITLE_2CONTENT +sd/source/filter/eppt/pptx-epptooxml.cxx:185 + enum (anonymous namespace)::PPTXLayout LAYOUT_TITLE +sd/source/filter/eppt/pptx-epptooxml.cxx:186 + enum (anonymous namespace)::PPTXLayout LAYOUT_CENTERED_TEXT +sd/source/filter/eppt/pptx-epptooxml.cxx:187 + enum (anonymous namespace)::PPTXLayout LAYOUT_TITLE_2CONTENT_CONTENT +sd/source/filter/eppt/pptx-epptooxml.cxx:188 + enum (anonymous namespace)::PPTXLayout LAYOUT_TITLE_CONTENT_2CONTENT +sd/source/filter/eppt/pptx-epptooxml.cxx:189 + enum (anonymous namespace)::PPTXLayout LAYOUT_TITLE_2CONTENT_OVER_CONTENT +sd/source/filter/eppt/pptx-epptooxml.cxx:190 + enum (anonymous namespace)::PPTXLayout LAYOUT_TITLE_CONTENT_OVER_CONTENT +sd/source/filter/eppt/pptx-epptooxml.cxx:191 + enum (anonymous namespace)::PPTXLayout LAYOUT_TITLE_4CONTENT +sd/source/filter/eppt/pptx-epptooxml.cxx:192 + enum (anonymous namespace)::PPTXLayout LAYOUT_TITLE_6CONTENT +sd/source/ui/inc/DrawController.hxx:93 + enum sd::DrawController::PropertyHandle PROPERTY_UPDATEACC +sd/source/ui/inc/DrawController.hxx:94 + enum sd::DrawController::PropertyHandle PROPERTY_PAGE_CHANGE +sd/source/ui/inc/TableDesignPane.hxx:42 + enum sd::TableCheckBox CB_HEADER_ROW +sd/source/ui/inc/TableDesignPane.hxx:43 + enum sd::TableCheckBox CB_TOTAL_ROW +sd/source/ui/inc/TableDesignPane.hxx:44 + enum sd::TableCheckBox CB_BANDED_ROWS +sd/source/ui/inc/TableDesignPane.hxx:45 + enum sd::TableCheckBox CB_FIRST_COLUMN +sd/source/ui/inc/TableDesignPane.hxx:46 + enum sd::TableCheckBox CB_LAST_COLUMN +sd/source/ui/inc/TableDesignPane.hxx:48 + enum sd::TableCheckBox CB_COUNT +sd/source/ui/inc/ToolBarManager.hxx:130 + enum sd::ToolBarManager::ToolBarGroup Permanent +sd/source/ui/inc/ToolBarManager.hxx:131 + enum sd::ToolBarManager::ToolBarGroup Function +sd/source/ui/inc/ToolBarManager.hxx:132 + enum sd::ToolBarManager::ToolBarGroup CommonTask +sd/source/ui/inc/ToolBarManager.hxx:133 + enum sd::ToolBarManager::ToolBarGroup MasterMode +sd/source/ui/inc/tools/ConfigurationAccess.hxx:43 + enum sd::tools::ConfigurationAccess::WriteMode READ_WRITE +sd/source/ui/inc/tools/IdleDetection.hxx:34 + enum sd::tools::IdleState SystemEventPending +sd/source/ui/inc/tools/IdleDetection.hxx:44 + enum sd::tools::IdleState WindowShowActive +sd/source/ui/inc/tools/IdleDetection.hxx:48 + enum sd::tools::IdleState WindowPainting +sd/source/ui/remotecontrol/BluetoothServer.cxx:98 + enum sd::BluetoothServer::Impl::BluezVersion BLUEZ4 +sd/source/ui/remotecontrol/BluetoothServer.hxx:47 + enum sd::BluetoothServer::(anonymous at /home/noel/libo2/sd/source/ui/remotecontrol/BluetoothServer.hxx:47:9) DISCOVERABLE +sd/source/ui/sidebar/MasterPageContainer.cxx:121 + enum sd::sidebar::MasterPageContainer::Implementation::InitializationState Initialized +sd/source/ui/sidebar/MasterPageContainer.cxx:121 + enum sd::sidebar::MasterPageContainer::Implementation::InitializationState Initializing +sd/source/ui/sidebar/MasterPageContainer.hxx:63 + enum sd::sidebar::MasterPageContainer::PreviewSize LARGE +sd/source/ui/slidesorter/cache/SlsRequestPriorityClass.hxx:33 + enum sd::slidesorter::cache::RequestPriorityClass VISIBLE_NO_PREVIEW +sd/source/ui/slidesorter/cache/SlsRequestPriorityClass.hxx:35 + enum sd::slidesorter::cache::RequestPriorityClass VISIBLE_OUTDATED_PREVIEW +sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx:45 + enum sd::slidesorter::controller::Animator::AnimationMode AM_Immediate +sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx:45 + enum sd::slidesorter::controller::InsertionIndicatorHandler::Mode MoveMode +sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx:79 + enum sd::slidesorter::view::PageObjectLayouter::CoordinateSystem ModelCoordinateSystem +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:69 + enum sd::slidesorter::view::Theme::ColorType ColorType_Size_ +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:74 + enum sd::slidesorter::view::Theme::GradientColorType Gradient_NormalPage +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:75 + enum sd::slidesorter::view::Theme::GradientColorType Gradient_SelectedPage +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:76 + enum sd::slidesorter::view::Theme::GradientColorType Gradient_SelectedAndFocusedPage +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:77 + enum sd::slidesorter::view::Theme::GradientColorType Gradient_MouseOverPage +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:78 + enum sd::slidesorter::view::Theme::GradientColorType Gradient_MouseOverSelected +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:79 + enum sd::slidesorter::view::Theme::GradientColorType Gradient_MouseOverSelectedAndFocusedPage +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:80 + enum sd::slidesorter::view::Theme::GradientColorType Gradient_FocusedPage +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:81 + enum sd::slidesorter::view::Theme::GradientColorType GradientColorType_Size_ +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:104 + enum sd::slidesorter::view::Theme::IconType Icon_RawShadow +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:105 + enum sd::slidesorter::view::Theme::IconType Icon_RawInsertShadow +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:106 + enum sd::slidesorter::view::Theme::IconType Icon_HideSlideOverlay +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:107 + enum sd::slidesorter::view::Theme::IconType Icon_FocusBorder +sd/source/ui/slidesorter/inc/view/SlsTheme.hxx:108 + enum sd::slidesorter::view::Theme::IconType IconType_Size_ +sdext/source/minimizer/pppoptimizertoken.hxx:50 + enum PPPOptimizerTokenEnum TK_FileSizeDestination +sdext/source/minimizer/pppoptimizertoken.hxx:51 + enum PPPOptimizerTokenEnum TK_FileSizeSource +sdext/source/minimizer/pppoptimizertoken.hxx:56 + enum PPPOptimizerTokenEnum TK_Progress +sdext/source/minimizer/pppoptimizertoken.hxx:78 + enum PPPOptimizerTokenEnum TK_Status +sdext/source/minimizer/pppoptimizertoken.hxx:79 + enum PPPOptimizerTokenEnum TK_Pages +sdext/source/minimizer/pppoptimizertoken.hxx:81 + enum PPPOptimizerTokenEnum STR_SUN_OPTIMIZATION_WIZARD2 +sdext/source/minimizer/pppoptimizertoken.hxx:82 + enum PPPOptimizerTokenEnum STR_STEPS +sdext/source/minimizer/pppoptimizertoken.hxx:83 + enum PPPOptimizerTokenEnum STR_BACK +sdext/source/minimizer/pppoptimizertoken.hxx:84 + enum PPPOptimizerTokenEnum STR_NEXT +sdext/source/minimizer/pppoptimizertoken.hxx:85 + enum PPPOptimizerTokenEnum STR_FINISH +sdext/source/minimizer/pppoptimizertoken.hxx:86 + enum PPPOptimizerTokenEnum STR_CANCEL +sdext/source/minimizer/pppoptimizertoken.hxx:87 + enum PPPOptimizerTokenEnum STR_INTRODUCTION +sdext/source/minimizer/pppoptimizertoken.hxx:88 + enum PPPOptimizerTokenEnum STR_INTRODUCTION_T +sdext/source/minimizer/pppoptimizertoken.hxx:89 + enum PPPOptimizerTokenEnum STR_CHOSE_SETTINGS +sdext/source/minimizer/pppoptimizertoken.hxx:90 + enum PPPOptimizerTokenEnum STR_REMOVE +sdext/source/minimizer/pppoptimizertoken.hxx:91 + enum PPPOptimizerTokenEnum STR_GRAPHIC_OPTIMIZATION +sdext/source/minimizer/pppoptimizertoken.hxx:92 + enum PPPOptimizerTokenEnum STR_IMAGE_OPTIMIZATION +sdext/source/minimizer/pppoptimizertoken.hxx:93 + enum PPPOptimizerTokenEnum STR_LOSSLESS_COMPRESSION +sdext/source/minimizer/pppoptimizertoken.hxx:94 + enum PPPOptimizerTokenEnum STR_JPEG_COMPRESSION +sdext/source/minimizer/pppoptimizertoken.hxx:95 + enum PPPOptimizerTokenEnum STR_QUALITY +sdext/source/minimizer/pppoptimizertoken.hxx:96 + enum PPPOptimizerTokenEnum STR_REMOVE_CROP_AREA +sdext/source/minimizer/pppoptimizertoken.hxx:97 + enum PPPOptimizerTokenEnum STR_IMAGE_RESOLUTION +sdext/source/minimizer/pppoptimizertoken.hxx:98 + enum PPPOptimizerTokenEnum STR_IMAGE_RESOLUTION_0 +sdext/source/minimizer/pppoptimizertoken.hxx:99 + enum PPPOptimizerTokenEnum STR_IMAGE_RESOLUTION_1 +sdext/source/minimizer/pppoptimizertoken.hxx:100 + enum PPPOptimizerTokenEnum STR_IMAGE_RESOLUTION_2 +sdext/source/minimizer/pppoptimizertoken.hxx:102 + enum PPPOptimizerTokenEnum STR_EMBED_LINKED_GRAPHICS +sdext/source/minimizer/pppoptimizertoken.hxx:103 + enum PPPOptimizerTokenEnum STR_OLE_OBJECTS +sdext/source/minimizer/pppoptimizertoken.hxx:104 + enum PPPOptimizerTokenEnum STR_OLE_OPTIMIZATION +sdext/source/minimizer/pppoptimizertoken.hxx:105 + enum PPPOptimizerTokenEnum STR_OLE_REPLACE +sdext/source/minimizer/pppoptimizertoken.hxx:106 + enum PPPOptimizerTokenEnum STR_ALL_OLE_OBJECTS +sdext/source/minimizer/pppoptimizertoken.hxx:107 + enum PPPOptimizerTokenEnum STR_ALIEN_OLE_OBJECTS_ONLY +sdext/source/minimizer/pppoptimizertoken.hxx:108 + enum PPPOptimizerTokenEnum STR_OLE_OBJECTS_DESC +sdext/source/minimizer/pppoptimizertoken.hxx:109 + enum PPPOptimizerTokenEnum STR_NO_OLE_OBJECTS_DESC +sdext/source/minimizer/pppoptimizertoken.hxx:110 + enum PPPOptimizerTokenEnum STR_SLIDES +sdext/source/minimizer/pppoptimizertoken.hxx:111 + enum PPPOptimizerTokenEnum STR_CHOOSE_SLIDES +sdext/source/minimizer/pppoptimizertoken.hxx:112 + enum PPPOptimizerTokenEnum STR_DELETE_MASTER_PAGES +sdext/source/minimizer/pppoptimizertoken.hxx:113 + enum PPPOptimizerTokenEnum STR_DELETE_NOTES_PAGES +sdext/source/minimizer/pppoptimizertoken.hxx:114 + enum PPPOptimizerTokenEnum STR_DELETE_HIDDEN_SLIDES +sdext/source/minimizer/pppoptimizertoken.hxx:115 + enum PPPOptimizerTokenEnum STR_CUSTOM_SHOW +sdext/source/minimizer/pppoptimizertoken.hxx:116 + enum PPPOptimizerTokenEnum STR_SUMMARY +sdext/source/minimizer/pppoptimizertoken.hxx:117 + enum PPPOptimizerTokenEnum STR_SUMMARY_TITLE +sdext/source/minimizer/pppoptimizertoken.hxx:118 + enum PPPOptimizerTokenEnum STR_APPLY_TO_CURRENT +sdext/source/minimizer/pppoptimizertoken.hxx:119 + enum PPPOptimizerTokenEnum STR_AUTOMATICALLY_OPEN +sdext/source/minimizer/pppoptimizertoken.hxx:120 + enum PPPOptimizerTokenEnum STR_SAVE_SETTINGS +sdext/source/minimizer/pppoptimizertoken.hxx:121 + enum PPPOptimizerTokenEnum STR_SAVE_AS +sdext/source/minimizer/pppoptimizertoken.hxx:122 + enum PPPOptimizerTokenEnum STR_DELETE_SLIDES +sdext/source/minimizer/pppoptimizertoken.hxx:123 + enum PPPOptimizerTokenEnum STR_OPTIMIZE_IMAGES +sdext/source/minimizer/pppoptimizertoken.hxx:124 + enum PPPOptimizerTokenEnum STR_CREATE_REPLACEMENT +sdext/source/minimizer/pppoptimizertoken.hxx:125 + enum PPPOptimizerTokenEnum STR_CURRENT_FILESIZE +sdext/source/minimizer/pppoptimizertoken.hxx:126 + enum PPPOptimizerTokenEnum STR_ESTIMATED_FILESIZE +sdext/source/minimizer/pppoptimizertoken.hxx:127 + enum PPPOptimizerTokenEnum STR_MY_SETTINGS +sdext/source/minimizer/pppoptimizertoken.hxx:128 + enum PPPOptimizerTokenEnum STR_OK +sdext/source/minimizer/pppoptimizertoken.hxx:129 + enum PPPOptimizerTokenEnum STR_INFO_1 +sdext/source/minimizer/pppoptimizertoken.hxx:130 + enum PPPOptimizerTokenEnum STR_INFO_2 +sdext/source/minimizer/pppoptimizertoken.hxx:131 + enum PPPOptimizerTokenEnum STR_INFO_3 +sdext/source/minimizer/pppoptimizertoken.hxx:132 + enum PPPOptimizerTokenEnum STR_INFO_4 +sdext/source/minimizer/pppoptimizertoken.hxx:133 + enum PPPOptimizerTokenEnum STR_DUPLICATING_PRESENTATION +sdext/source/minimizer/pppoptimizertoken.hxx:134 + enum PPPOptimizerTokenEnum STR_DELETING_SLIDES +sdext/source/minimizer/pppoptimizertoken.hxx:135 + enum PPPOptimizerTokenEnum STR_OPTIMIZING_GRAPHICS +sdext/source/minimizer/pppoptimizertoken.hxx:136 + enum PPPOptimizerTokenEnum STR_CREATING_OLE_REPLACEMENTS +sdext/source/minimizer/pppoptimizertoken.hxx:137 + enum PPPOptimizerTokenEnum STR_FILESIZESEPARATOR +sdext/source/minimizer/pppoptimizertoken.hxx:138 + enum PPPOptimizerTokenEnum STR_FILENAME_SUFFIX +sdext/source/minimizer/pppoptimizertoken.hxx:139 + enum PPPOptimizerTokenEnum STR_WARN_UNSAVED_PRESENTATION +sdext/source/minimizer/pppoptimizertoken.hxx:140 + enum PPPOptimizerTokenEnum TK_NotFound +sdext/source/pdfimport/inc/genericelements.hxx:202 + enum pdfi::ParagraphElement::ParagraphType Normal +sdext/source/pdfimport/tree/drawtreevisiting.hxx:98 + enum pdfi::DrawXmlEmitter::DocType IMPRESS_DOC +sdext/source/pdfimport/wrapper/wrapper.cxx:94 + enum pdfi::(anonymous namespace)::parseKey HYPERLINK +sdext/source/pdfimport/wrapper/wrapper.cxx:95 + enum pdfi::(anonymous namespace)::parseKey INTERSECTCLIP +sdext/source/pdfimport/wrapper/wrapper.cxx:96 + enum pdfi::(anonymous namespace)::parseKey INTERSECTEOCLIP +sdext/source/pdfimport/wrapper/wrapper.cxx:97 + enum pdfi::(anonymous namespace)::parseKey POPSTATE +sdext/source/pdfimport/wrapper/wrapper.cxx:98 + enum pdfi::(anonymous namespace)::parseKey PUSHSTATE +sdext/source/pdfimport/wrapper/wrapper.cxx:101 + enum pdfi::(anonymous namespace)::parseKey SETBLENDMODE +sdext/source/pdfimport/wrapper/wrapper.cxx:102 + enum pdfi::(anonymous namespace)::parseKey SETFILLCOLOR +sdext/source/pdfimport/wrapper/wrapper.cxx:103 + enum pdfi::(anonymous namespace)::parseKey SETFONT +sdext/source/pdfimport/wrapper/wrapper.cxx:104 + enum pdfi::(anonymous namespace)::parseKey SETLINECAP +sdext/source/pdfimport/wrapper/wrapper.cxx:105 + enum pdfi::(anonymous namespace)::parseKey SETLINEDASH +sdext/source/pdfimport/wrapper/wrapper.cxx:106 + enum pdfi::(anonymous namespace)::parseKey SETLINEJOIN +sdext/source/pdfimport/wrapper/wrapper.cxx:107 + enum pdfi::(anonymous namespace)::parseKey SETLINEWIDTH +sdext/source/pdfimport/wrapper/wrapper.cxx:108 + enum pdfi::(anonymous namespace)::parseKey SETMITERLIMIT +sdext/source/pdfimport/wrapper/wrapper.cxx:110 + enum pdfi::(anonymous namespace)::parseKey SETSTROKECOLOR +sdext/source/pdfimport/wrapper/wrapper.cxx:112 + enum pdfi::(anonymous namespace)::parseKey SETTRANSFORMATION +sdext/source/pdfimport/wrapper/wrapper.cxx:115 + enum pdfi::(anonymous namespace)::parseKey UPDATEBLENDMODE +sdext/source/pdfimport/wrapper/wrapper.cxx:118 + enum pdfi::(anonymous namespace)::parseKey UPDATEFILLOPACITY +sdext/source/presenter/PresenterBitmapContainer.hxx:67 + enum sdext::presenter::PresenterBitmapContainer::BitmapDescriptor::TexturingMode Once +sdext/source/presenter/PresenterConfigurationAccess.hxx:51 + enum sdext::presenter::PresenterConfigurationAccess::WriteMode READ_WRITE +sdext/source/presenter/PresenterPaneBorderPainter.cxx:80 + enum sdext::presenter::(anonymous namespace)::RendererPaneStyle::Anchor Center +sdext/source/presenter/PresenterScrollBar.hxx:145 + enum sdext::presenter::PresenterScrollBar::Area Pager +sdext/source/presenter/PresenterScrollBar.hxx:145 + enum sdext::presenter::PresenterScrollBar::Area Total +sdext/source/presenter/PresenterWindowManager.hxx:88 + enum sdext::presenter::PresenterWindowManager::LayoutMode LM_Generic +sfx2/source/control/unoctitm.cxx:90 + enum (anonymous namespace)::URLTypeId URLType_BOOL +sfx2/source/control/unoctitm.cxx:91 + enum (anonymous namespace)::URLTypeId URLType_BYTE +sfx2/source/control/unoctitm.cxx:92 + enum (anonymous namespace)::URLTypeId URLType_SHORT +sfx2/source/control/unoctitm.cxx:93 + enum (anonymous namespace)::URLTypeId URLType_LONG +sfx2/source/control/unoctitm.cxx:94 + enum (anonymous namespace)::URLTypeId URLType_HYPER +sfx2/source/control/unoctitm.cxx:95 + enum (anonymous namespace)::URLTypeId URLType_STRING +sfx2/source/control/unoctitm.cxx:96 + enum (anonymous namespace)::URLTypeId URLType_FLOAT +sfx2/source/control/unoctitm.cxx:97 + enum (anonymous namespace)::URLTypeId URLType_DOUBLE +sfx2/source/control/unoctitm.cxx:98 + enum (anonymous namespace)::URLTypeId URLType_COUNT +sfx2/source/dialog/filedlghelper.cxx:805 + enum sfx2::(anonymous namespace)::open_or_save_t SAVE +sfx2/source/dialog/filedlghelper.cxx:805 + enum sfx2::(anonymous namespace)::open_or_save_t UNDEFINED +sfx2/source/dialog/securitypage.cxx:45 + enum (anonymous namespace)::RedliningMode RL_CALC +sfx2/source/doc/docmacromode.cxx:162 + enum AutoConfirmation eAutoConfirmReject +sfx2/source/inc/docundomanager.hxx:70 + enum SfxModelGuard::AllowedModelState E_FULLY_ALIVE +sfx2/source/inc/workwin.hxx:69 + enum SfxChildVisibility NOT_VISIBLE +sfx2/source/inc/workwin.hxx:72 + enum SfxChildVisibility FITS_IN +shell/source/backends/kf5be/kf5access.cxx:67 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:67:30) Size +shell/source/backends/kf5be/kf5access.cxx:112 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:112:56) Size +shell/source/backends/kf5be/kf5access.cxx:121 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:121:26) Size +shell/source/backends/kf5be/kf5access.cxx:139 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:139:56) Size +shell/source/backends/kf5be/kf5access.cxx:148 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:148:26) Size +shell/source/backends/kf5be/kf5access.cxx:166 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:166:57) Size +shell/source/backends/kf5be/kf5access.cxx:175 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:175:26) Size +shell/source/backends/kf5be/kf5access.cxx:193 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:193:57) Size +shell/source/backends/kf5be/kf5access.cxx:202 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:202:26) Size +shell/source/backends/kf5be/kf5access.cxx:220 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:220:58) Size +shell/source/backends/kf5be/kf5access.cxx:229 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:229:26) Size +shell/source/backends/kf5be/kf5access.cxx:247 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:247:58) Size +shell/source/backends/kf5be/kf5access.cxx:256 + enum (anonymous at /home/noel/libo2/shell/source/backends/kf5be/kf5access.cxx:256:26) Size +slideshow/source/engine/shapes/viewshape.hxx:41 + enum UpdateFlags Transformation +slideshow/source/engine/shapes/viewshape.hxx:44 + enum UpdateFlags Position +slideshow/source/engine/slide/layer.hxx:207 + enum slideshow::internal::Layer::Dummy BackgroundLayer +slideshow/source/engine/slide/slideimpl.cxx:171 + enum slideshow::internal::(anonymous namespace)::SlideImpl::SlideAnimationState CONSTRUCTING_STATE +slideshow/source/engine/slide/slideimpl.cxx:172 + enum slideshow::internal::(anonymous namespace)::SlideImpl::SlideAnimationState INITIAL_STATE +slideshow/source/engine/slide/slideimpl.cxx:173 + enum slideshow::internal::(anonymous namespace)::SlideImpl::SlideAnimationState SHOWING_STATE +slideshow/source/engine/slide/slideimpl.cxx:175 + enum slideshow::internal::(anonymous namespace)::SlideImpl::SlideAnimationState SlideAnimationState_NUM_ENTRIES +soltools/cpp/_lex.c:60 + int COM1 +soltools/cpp/_lex.c:60 + int COM2 +soltools/cpp/_lex.c:60 + int COM3 +soltools/cpp/_lex.c:60 + int COM4 +soltools/cpp/_lex.c:60 + int ID1 +soltools/cpp/_lex.c:60 + int NUM1 +soltools/cpp/_lex.c:60 + int NUM2 +soltools/cpp/_lex.c:60 + int NUM3 +soltools/cpp/_lex.c:60 + int ST1 +soltools/cpp/_lex.c:60 + int ST2 +soltools/cpp/_lex.c:60 + int ST3 +soltools/cpp/_lex.c:61 + int CC1 +soltools/cpp/_lex.c:61 + int CC2 +soltools/cpp/_lex.c:61 + int MINUS1 +soltools/cpp/_lex.c:61 + int PCT1 +soltools/cpp/_lex.c:61 + int PLUS1 +soltools/cpp/_lex.c:61 + int SHARP1 +soltools/cpp/_lex.c:61 + int STAR1 +soltools/cpp/_lex.c:61 + int WS1 +soltools/cpp/_lex.c:62 + int AND1 +soltools/cpp/_lex.c:62 + int ASG1 +soltools/cpp/_lex.c:62 + int CIRC1 +soltools/cpp/_lex.c:62 + int DOTS1 +soltools/cpp/_lex.c:62 + int GT1 +soltools/cpp/_lex.c:62 + int GT2 +soltools/cpp/_lex.c:62 + int LT1 +soltools/cpp/_lex.c:62 + int LT2 +soltools/cpp/_lex.c:62 + int NOT1 +soltools/cpp/_lex.c:62 + int OR1 +soltools/cpp/cpp.h:43 + int MMINUS +soltools/cpp/cpp.h:43 + int PPLUS +soltools/cpp/cpp.h:44 + int ARROW +soltools/cpp/cpp.h:44 + int DOT +soltools/cpp/cpp.h:44 + int SBRA +soltools/cpp/cpp.h:44 + int SKET +soltools/cpp/cpp.h:46 + int CBRA +soltools/cpp/cpp.h:46 + int CKET +soltools/cpp/cpp.h:46 + int SEMIC +soltools/cpp/cpp.h:47 + int ASCIRC +soltools/cpp/cpp.h:47 + int ASLSH +soltools/cpp/cpp.h:47 + int ASMINUS +soltools/cpp/cpp.h:47 + int ASPCT +soltools/cpp/cpp.h:47 + int ASPLUS +soltools/cpp/cpp.h:47 + int ASSLASH +soltools/cpp/cpp.h:47 + int ASSTAR +soltools/cpp/cpp.h:48 + int ASAND +soltools/cpp/cpp.h:48 + int ASOR +soltools/cpp/cpp.h:48 + int ASRSH +soltools/cpp/cpp.h:48 + int ELLIPS +soltools/cpp/cpp.h:50 + int COMMENT +soltools/cpp/cpp.h:57 + int KSTDC +soltools/cpp/cpp.h:137 + int ERROR +soltools/cpp/cpp.h:137 + int INFO +sot/source/sdstor/stgio.hxx:33 + enum FatError WrongLength +sot/source/sdstor/stgio.hxx:34 + enum FatError UnrefChain +sot/source/sdstor/stgio.hxx:35 + enum FatError OutOfBounds +sot/source/sdstor/stgio.hxx:37 + enum FatError InMemoryError +sot/source/sdstor/stgio.hxx:38 + enum FatError OnFileError +sot/source/sdstor/stgio.hxx:39 + enum FatError BothError +starmath/inc/mathml/def.hxx:28 + enum SmLengthUnit MlEm +starmath/inc/mathml/def.hxx:36 + enum SmLengthUnit MlP +starmath/inc/mathml/def.hxx:103 + enum SmMlAttributeValueAccent MlFalse +starmath/inc/mathml/def.hxx:109 + enum SmMlAttributeValueDir MlLtr +starmath/inc/mathml/def.hxx:115 + enum SmMlAttributeValueDisplaystyle MlFalse +starmath/inc/mathml/def.hxx:121 + enum SmMlAttributeValueFence MlFalse +starmath/inc/mathml/def.hxx:127 + enum SmMlAttributeValueHref NMlEmpty +starmath/inc/mathml/def.hxx:138 + enum SmMlAttributeValueMathbackground MlTransparent +starmath/inc/mathml/def.hxx:144 + enum SmMlAttributeValueMathcolor MlDefault +starmath/inc/mathml/def.hxx:155 + enum SmMlAttributeValueMathvariant normal +starmath/inc/mathml/def.hxx:178 + enum SmMlAttributeValueMaxsize MlInfinity +starmath/inc/mathml/def.hxx:184 + enum SmMlAttributeValueMinsize MlInfinity +starmath/inc/mathml/def.hxx:194 + enum SmMlAttributeValueMovablelimits MlFalse +starmath/inc/mathml/def.hxx:205 + enum SmMlAttributeValueSeparator MlFalse +starmath/inc/mathml/def.hxx:211 + enum SmMlAttributeValueStretchy MlFalse +starmath/inc/mathml/def.hxx:217 + enum SmMlAttributeValueSymmetric MlFalse +starmath/inc/mathml/mathmlattr.hxx:27 + enum MathMLLengthUnit Ex +starmath/inc/mathml/mathmlattr.hxx:28 + enum MathMLLengthUnit Px +starmath/inc/mathml/mathmlattr.hxx:29 + enum MathMLLengthUnit In +starmath/inc/mathml/mathmlattr.hxx:30 + enum MathMLLengthUnit Cm +starmath/inc/mathml/mathmlattr.hxx:31 + enum MathMLLengthUnit Mm +starmath/inc/mathml/mathmlattr.hxx:32 + enum MathMLLengthUnit Pt +starmath/inc/mathml/mathmlattr.hxx:33 + enum MathMLLengthUnit Pc +starmath/inc/mathml/mathmlattr.hxx:34 + enum MathMLLengthUnit Percent +starmath/inc/mathml/mathmlMo.hxx:37 + enum moOpDP nonedp +starmath/inc/mathml/mathmlMo.hxx:38 + enum moOpDP accent +starmath/inc/mathml/mathmlMo.hxx:39 + enum moOpDP fence +starmath/inc/mathml/mathmlMo.hxx:40 + enum moOpDP stretchy +starmath/inc/mathml/mathmlMo.hxx:41 + enum moOpDP symmetric +starmath/inc/mathml/mathmlMo.hxx:42 + enum moOpDP separator +starmath/inc/mathml/mathmlMo.hxx:43 + enum moOpDP linebreakstyleAfter +starmath/inc/mathml/mathmlMo.hxx:44 + enum moOpDP largeop +starmath/inc/mathml/mathmlMo.hxx:48 + enum moOpDP stretchyfence +starmath/inc/mathml/mathmlMo.hxx:49 + enum moOpDP movablelargeop +starmath/inc/mathml/mathmlMo.hxx:55 + enum moOpDF prefix +starmath/inc/mathml/mathmlMo.hxx:56 + enum moOpDF infix +starmath/inc/mathml/mathmlMo.hxx:57 + enum moOpDF postfix +starmath/inc/mathml/mathmlMo.hxx:58 + enum moOpDF prepostfix +starmath/inc/nodetype.hxx:52 + enum SmNodeType Rectangle +starmath/inc/parsebase.hxx:36 + enum SmParseError UnexpectedChar +starmath/inc/parsebase.hxx:37 + enum SmParseError UnexpectedToken +starmath/inc/parsebase.hxx:38 + enum SmParseError PoundExpected +starmath/inc/parsebase.hxx:39 + enum SmParseError ColorExpected +starmath/inc/parsebase.hxx:40 + enum SmParseError LgroupExpected +starmath/inc/parsebase.hxx:41 + enum SmParseError RgroupExpected +starmath/inc/parsebase.hxx:42 + enum SmParseError LbraceExpected +starmath/inc/parsebase.hxx:43 + enum SmParseError RbraceExpected +starmath/inc/parsebase.hxx:44 + enum SmParseError ParentMismatch +starmath/inc/parsebase.hxx:45 + enum SmParseError RightExpected +starmath/inc/parsebase.hxx:46 + enum SmParseError FontExpected +starmath/inc/parsebase.hxx:47 + enum SmParseError SizeExpected +starmath/inc/parsebase.hxx:48 + enum SmParseError DoubleAlign +starmath/inc/parsebase.hxx:49 + enum SmParseError DoubleSubsupscript +starmath/inc/parsebase.hxx:50 + enum SmParseError NumberExpected +starmath/inc/token.hxx:54 + enum TG Attribute +starmath/inc/token.hxx:55 + enum TG Align +starmath/inc/token.hxx:57 + enum TG Blank +starmath/inc/token.hxx:60 + enum TG Color +starmath/inc/token.hxx:61 + enum TG Font +starmath/inc/token.hxx:62 + enum TG Standalone +starmath/inc/token.hxx:64 + enum TG FontAttr +starmath/inc/token.hxx:85 + enum SmTokenType TGE +starmath/inc/token.hxx:85 + enum SmTokenType TGT +starmath/inc/token.hxx:85 + enum SmTokenType TLE +starmath/inc/token.hxx:85 + enum SmTokenType TLT +starmath/inc/token.hxx:86 + enum SmTokenType TASSIGN +starmath/inc/token.hxx:86 + enum SmTokenType TGG +starmath/inc/token.hxx:86 + enum SmTokenType TLL +starmath/inc/token.hxx:86 + enum SmTokenType TNEQ +starmath/inc/token.hxx:87 + enum SmTokenType TEQUIV +starmath/inc/token.hxx:87 + enum SmTokenType TORTHO +starmath/inc/token.hxx:87 + enum SmTokenType TPARALLEL +starmath/inc/token.hxx:90 + enum SmTokenType TSIM +starmath/inc/token.hxx:90 + enum SmTokenType TSIMEQ +starmath/inc/token.hxx:92 + enum SmTokenType TDIV +starmath/inc/token.hxx:92 + enum SmTokenType TTIMES +starmath/inc/token.hxx:93 + enum SmTokenType TBACKSLASH +starmath/inc/token.hxx:93 + enum SmTokenType TSLASH +starmath/inc/token.hxx:94 + enum SmTokenType TIT +starmath/inc/token.hxx:98 + enum SmTokenType TAND +starmath/inc/token.hxx:98 + enum SmTokenType TOR +starmath/inc/token.hxx:99 + enum SmTokenType TNOTPRECEDES +starmath/inc/token.hxx:99 + enum SmTokenType TNOTSUCCEEDS +starmath/inc/token.hxx:99 + enum SmTokenType TPRECEDES +starmath/inc/token.hxx:99 + enum SmTokenType TSUCCEEDS +starmath/inc/token.hxx:100 + enum SmTokenType TPRECEDESEQUAL +starmath/inc/token.hxx:100 + enum SmTokenType TPRECEDESEQUIV +starmath/inc/token.hxx:100 + enum SmTokenType TSUCCEEDSEQUAL +starmath/inc/token.hxx:100 + enum SmTokenType TSUCCEEDSEQUIV +starmath/inc/token.hxx:102 + enum SmTokenType TDEF +starmath/inc/token.hxx:103 + enum SmTokenType TAPPROX +starmath/inc/token.hxx:103 + enum SmTokenType TDIVIDES +starmath/inc/token.hxx:103 + enum SmTokenType TNDIVIDES +starmath/inc/token.hxx:103 + enum SmTokenType TPROP +starmath/inc/token.hxx:104 + enum SmTokenType TGESLANT +starmath/inc/token.hxx:104 + enum SmTokenType TLESLANT +starmath/inc/token.hxx:104 + enum SmTokenType TTRANSL +starmath/inc/token.hxx:104 + enum SmTokenType TTRANSR +starmath/inc/token.hxx:106 + enum SmTokenType TODIVIDE +starmath/inc/token.hxx:106 + enum SmTokenType TODOT +starmath/inc/token.hxx:106 + enum SmTokenType TOMINUS +starmath/inc/token.hxx:106 + enum SmTokenType TOPLUS +starmath/inc/token.hxx:106 + enum SmTokenType TOTIMES +starmath/inc/token.hxx:113 + enum SmTokenType TIN +starmath/inc/token.hxx:113 + enum SmTokenType TNI +starmath/inc/token.hxx:113 + enum SmTokenType TNOTIN +starmath/inc/token.hxx:114 + enum SmTokenType TSUBSET +starmath/inc/token.hxx:114 + enum SmTokenType TSUBSETEQ +starmath/inc/token.hxx:114 + enum SmTokenType TSUPSET +starmath/inc/token.hxx:114 + enum SmTokenType TSUPSETEQ +starmath/inc/token.hxx:115 + enum SmTokenType TNSUBSET +starmath/inc/token.hxx:115 + enum SmTokenType TNSUBSETEQ +starmath/inc/token.hxx:115 + enum SmTokenType TNSUPSET +starmath/inc/token.hxx:115 + enum SmTokenType TNSUPSETEQ +starmath/inc/token.hxx:116 + enum SmTokenType TINTERSECT +starmath/inc/token.hxx:116 + enum SmTokenType TSETMINUS +starmath/inc/token.hxx:116 + enum SmTokenType TSETQUOTIENT +starmath/inc/token.hxx:116 + enum SmTokenType TUNION +starmath/inc/token.hxx:127 + enum SmTokenType THARPOON +starmath/inc/token.hxx:144 + enum SmTokenType TEXP +starmath/inc/token.hxx:144 + enum SmTokenType TLN +starmath/inc/token.hxx:144 + enum SmTokenType TLOG +starmath/inc/token.hxx:145 + enum SmTokenType TCOS +starmath/inc/token.hxx:145 + enum SmTokenType TCOT +starmath/inc/token.hxx:145 + enum SmTokenType TSIN +starmath/inc/token.hxx:145 + enum SmTokenType TTAN +starmath/inc/token.hxx:146 + enum SmTokenType TCOSH +starmath/inc/token.hxx:146 + enum SmTokenType TCOTH +starmath/inc/token.hxx:146 + enum SmTokenType TSINH +starmath/inc/token.hxx:146 + enum SmTokenType TTANH +starmath/inc/token.hxx:147 + enum SmTokenType TACOS +starmath/inc/token.hxx:147 + enum SmTokenType TACOT +starmath/inc/token.hxx:147 + enum SmTokenType TASIN +starmath/inc/token.hxx:147 + enum SmTokenType TATAN +starmath/inc/token.hxx:148 + enum SmTokenType TACOSH +starmath/inc/token.hxx:148 + enum SmTokenType TACOTH +starmath/inc/token.hxx:148 + enum SmTokenType TASINH +starmath/inc/token.hxx:148 + enum SmTokenType TATANH +starmath/source/ooxmlimport.cxx:388 + enum operation_t noBar +stoc/source/inspect/introspection.cxx:1829 + enum MethodType GETSET_METHOD +stoc/source/inspect/introspection.cxx:1831 + enum MethodType REMOVE_LISTENER_METHOD +stoc/source/security/permissions.h:37 + enum stoc_sec::Permission::t_type ALL +store/source/stordata.hxx:572 + enum store::OStoreDirectoryPageData::ChunkScope SCOPE_UNKNOWN +svgio/inc/svgmarkernode.hxx:34 + enum svgio::svgreader::SvgMarkerNode::MarkerUnits userSpaceOnUse +svgio/inc/svgnode.hxx:46 + enum svgio::svgreader::XmlSpace Preserve +svgio/inc/svgnode.hxx:52 + enum svgio::svgreader::Display Inline +svgio/inc/svgnode.hxx:53 + enum svgio::svgreader::Display Block +svgio/inc/svgnode.hxx:54 + enum svgio::svgreader::Display ListItem +svgio/inc/svgnode.hxx:55 + enum svgio::svgreader::Display RunIn +svgio/inc/svgnode.hxx:56 + enum svgio::svgreader::Display Compact +svgio/inc/svgnode.hxx:57 + enum svgio::svgreader::Display Marker +svgio/inc/svgnode.hxx:58 + enum svgio::svgreader::Display Table +svgio/inc/svgnode.hxx:59 + enum svgio::svgreader::Display InlineTable +svgio/inc/svgnode.hxx:60 + enum svgio::svgreader::Display TableRowGroup +svgio/inc/svgnode.hxx:61 + enum svgio::svgreader::Display TableHeaderGroup +svgio/inc/svgnode.hxx:62 + enum svgio::svgreader::Display TableFooterGroup +svgio/inc/svgnode.hxx:63 + enum svgio::svgreader::Display TableRow +svgio/inc/svgnode.hxx:64 + enum svgio::svgreader::Display TableColumnGroup +svgio/inc/svgnode.hxx:65 + enum svgio::svgreader::Display TableColumn +svgio/inc/svgnode.hxx:66 + enum svgio::svgreader::Display TableCell +svgio/inc/svgnode.hxx:67 + enum svgio::svgreader::Display TableCaption +svgio/inc/svgnode.hxx:69 + enum svgio::svgreader::Display Inherit +svgio/inc/SvgNumber.hxx:35 + enum svgio::svgreader::NumberType length +svgio/inc/svgstyleattributes.hxx:45 + enum svgio::svgreader::StrokeLinecap butt +svgio/inc/svgstyleattributes.hxx:53 + enum svgio::svgreader::StrokeLinejoin miter +svgio/inc/svgstyleattributes.hxx:95 + enum svgio::svgreader::FontStyle normal +svgio/inc/svgstyleattributes.hxx:132 + enum svgio::svgreader::TextDecoration none +svgio/inc/svgstyleattributes.hxx:136 + enum svgio::svgreader::TextDecoration blink +svgio/inc/svgstyleattributes.hxx:151 + enum svgio::svgreader::FillRule evenodd +svgio/inc/svgstyleattributes.hxx:156 + enum svgio::svgreader::BaselineShift Baseline +svgio/inc/svgstyleattributes.hxx:168 + enum svgio::svgreader::Visibility collapse +svgio/inc/svgtoken.hxx:41 + enum svgio::svgreader::SVGToken Xmlns +svgio/inc/svgtools.hxx:53 + enum svgio::svgreader::SvgAlign xMinYMin +svgio/source/svgreader/svgtools.cxx:415 + enum DegreeType rad +svl/source/misc/adrparse.cxx:26 + enum (anonymous namespace)::ElementType ELEMENT_START +svl/source/misc/strmadpt.cxx:40 + enum SvDataPipe_Impl::SeekResult SEEK_BEFORE_MARKED +svl/source/misc/strmadpt.cxx:40 + enum SvDataPipe_Impl::SeekResult SEEK_PAST_END +svl/source/numbers/zforscan.hxx:47 + enum ImpSvNumberformatScan::KeywordLocalization LocaleLegacy +svtools/inc/table/tablecontrolinterface.hxx:78 + enum svt::table::TableCellArea CellContent +svtools/inc/table/tablemodel.hxx:68 + enum svt::table::ScrollbarVisibility ScrollbarShowSmart +svtools/inc/table/tablesort.hxx:34 + enum svt::table::ColumnSortDirection ColumnSortDescending +svtools/source/config/miscopt.cxx:119 + enum SvtMiscOptions_Impl::SetModifiedFlag DONT_SET +svtools/source/control/ctrltool.cxx:97 + enum (anonymous namespace)::FontListFontNameType SCREEN +svtools/source/control/valueset.cxx:62 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/svtools/source/control/valueset.cxx:60:1) ITEM_OFFSET +svtools/source/control/valueset.cxx:63 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/svtools/source/control/valueset.cxx:60:1) ITEM_OFFSET_DOUBLE +svtools/source/control/valueset.cxx:64 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/svtools/source/control/valueset.cxx:60:1) NAME_LINE_OFF_X +svtools/source/control/valueset.cxx:65 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/svtools/source/control/valueset.cxx:60:1) NAME_LINE_OFF_Y +svtools/source/control/valueset.cxx:66 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/svtools/source/control/valueset.cxx:60:1) NAME_LINE_HEIGHT +svtools/source/control/valueset.cxx:67 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/svtools/source/control/valueset.cxx:60:1) NAME_OFFSET +svtools/source/svhtml/parhtml.cxx:1887 + enum (anonymous namespace)::HtmlMeta Generator +svtools/source/svhtml/parhtml.cxx:1888 + enum (anonymous namespace)::HtmlMeta SDFootnote +svtools/source/svhtml/parhtml.cxx:1889 + enum (anonymous namespace)::HtmlMeta SDEndnote +svx/inc/sdr/overlay/overlaytools.hxx:204 + enum drawinglayer::primitive2d::HelplineStyle HELPLINESTYLE_POINT +svx/inc/sxmkitm.hxx:25 + enum SdrMeasureKind SDRMEASURE_STD +svx/source/dialog/srchdlg.cxx:100 + enum ModifyFlags Formulas +svx/source/dialog/srchdlg.cxx:101 + enum ModifyFlags Values +svx/source/dialog/srchdlg.cxx:102 + enum ModifyFlags CalcNotes +svx/source/fmcomp/fmgridcl.cxx:815 + enum (anonymous namespace)::InspectorAction eOpenInspector +svx/source/inc/datanavi.hxx:71 + enum svxform::DataItemType DITElement +svx/source/inc/docrecovery.hxx:75 + enum EDocStates Unknown +svx/source/inc/fmdocumentclassification.hxx:31 + enum svxform::DocumentType eTextDocument +svx/source/inc/fmdocumentclassification.hxx:32 + enum svxform::DocumentType eWebDocument +svx/source/inc/fmdocumentclassification.hxx:33 + enum svxform::DocumentType eSpreadsheetDocument +svx/source/inc/fmdocumentclassification.hxx:34 + enum svxform::DocumentType eDrawingDocument +svx/source/inc/fmdocumentclassification.hxx:35 + enum svxform::DocumentType ePresentationDocument +svx/source/inc/fmdocumentclassification.hxx:37 + enum svxform::DocumentType eDatabaseForm +svx/source/inc/fmdocumentclassification.hxx:38 + enum svxform::DocumentType eDatabaseReport +svx/source/inc/fmexpl.hxx:380 + enum svxform::NavigatorTree::SELDATA_ITEMS SDI_ALL +svx/source/inc/fmshimp.hxx:82 + enum LoadFormsFlags Load +svx/source/inc/fmshimp.hxx:83 + enum LoadFormsFlags Sync +svx/source/inc/fmtextcontrolshell.hxx:146 + enum svx::FmTextControlShell::AttributeSet eParaAttribs +svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx:534 + enum sdr::contact::ViewObjectContactOfUnoControl_Impl::ViewControlMode eAlive +svx/source/stbctrls/modctrl.cxx:45 + enum SvxModifyControl::ImplData::ModificationState MODIFICATION_STATE_NO +svx/source/stbctrls/modctrl.cxx:47 + enum SvxModifyControl::ImplData::ModificationState MODIFICATION_STATE_FEEDBACK +svx/source/stbctrls/modctrl.cxx:48 + enum SvxModifyControl::ImplData::ModificationState MODIFICATION_STATE_SIZE +svx/source/svdraw/svdocapt.cxx:58 + enum (anonymous namespace)::EscDir UNT +svx/source/table/tablehandles.hxx:28 + enum sdr::table::TableEdgeState Empty +svx/source/table/tablehandles.hxx:28 + enum sdr::table::TableEdgeState Invisible +svx/source/tbxctrls/tbcontrl.cxx:2208 + enum (anonymous namespace)::FrmValidFlags AllMask +svx/source/tbxctrls/tbunosearchcontrollers.cxx:706 + enum (anonymous namespace)::UpDownSearchToolboxController::Type DOWN +svx/source/unodraw/recoveryui.cxx:49 + enum (anonymous namespace)::RecoveryUI::EJob E_JOB_UNKNOWN +sw/inc/calbck.hxx:122 + enum sw::IteratorMode Exact +sw/inc/chpfld.hxx:31 + enum SwChapterFormat CF_BEGIN +sw/inc/crstate.hxx:57 + enum MultiPortionType TWOLINE +sw/inc/crstate.hxx:126 + enum CursorMoveState LeftMargin +sw/inc/dbmgr.hxx:98 + enum SwDBSelect QUERY +sw/inc/doc.hxx:322 + enum SwDoc::MissingDictionary False +sw/inc/doc.hxx:392 + enum SwDoc::DocumentType DOCTYPE_NATIVE +sw/inc/doc.hxx:1197 + enum SwDoc::RowColMode DeleteRow +sw/inc/docary.hxx:72 + enum SwVectorModifyBase::DestructorPolicy KeepElements +sw/inc/docary.hxx:72 + enum SwVectorModifyBase::DestructorPolicy KeepElements +sw/inc/docary.hxx:72 + enum SwVectorModifyBase::DestructorPolicy KeepElements +sw/inc/docstyle.hxx:68 + enum SwDocStyleSheet::FillStyleType FillOnlyName +sw/inc/docufld.hxx:43 + enum SwAuthorFormat AF_BEGIN +sw/inc/docufld.hxx:52 + enum SwDocStatSubType DS_BEGIN +sw/inc/docufld.hxx:123 + enum SwJumpEditFormat JE_FMT_TEXT +sw/inc/fesh.hxx:64 + enum FrameTypeFlags PAGE +sw/inc/fesh.hxx:96 + enum GotoObjFlags Any +sw/inc/fesh.hxx:111 + enum FlyProtectFlags Fixed +sw/inc/fesh.hxx:131 + enum ObjCntType OBJCNT_DONTCARE +sw/inc/fesh.hxx:140 + enum CurRectType Frame +sw/inc/flyenum.hxx:36 + enum SwChainRet NOT_EMPTY +sw/inc/flyenum.hxx:37 + enum SwChainRet IS_IN_CHAIN +sw/inc/flyenum.hxx:38 + enum SwChainRet WRONG_AREA +sw/inc/flyenum.hxx:40 + enum SwChainRet NOT_FOUND +sw/inc/flyenum.hxx:41 + enum SwChainRet SOURCE_CHAINED +sw/inc/flyenum.hxx:42 + enum SwChainRet SELF +sw/inc/fmtcol.hxx:189 + enum Master_CollCondition PARA_IN_LIST +sw/inc/fmtcol.hxx:190 + enum Master_CollCondition PARA_IN_OUTLINE +sw/inc/fmtcol.hxx:191 + enum Master_CollCondition PARA_IN_FRAME +sw/inc/fmtcol.hxx:194 + enum Master_CollCondition PARA_IN_SECTION +sw/inc/fmtcol.hxx:195 + enum Master_CollCondition PARA_IN_FOOTNOTE +sw/inc/fmtcol.hxx:198 + enum Master_CollCondition PARA_IN_ENDNOTE +sw/inc/fmtftntx.hxx:34 + enum SwFootnoteEndPosEnum FTNEND_ATTXTEND_END +sw/inc/IDocumentContentOperations.hxx:48 + enum SwMoveFlags DEFAULT +sw/inc/IDocumentContentOperations.hxx:62 + enum SwInsertFlags DEFAULT +sw/inc/IDocumentContentOperations.hxx:74 + enum SwCopyFlags Default +sw/inc/IDocumentExternalData.hxx:28 + enum sw::tExternalDataType FIB +sw/inc/IDocumentExternalData.hxx:28 + enum sw::tExternalDataType STTBF_ASSOC +sw/inc/IDocumentRedlineAccess.hxx:136 + enum IDocumentRedlineAccess::AppendResult MERGED +sw/inc/IMark.hxx:34 + enum sw::mark::InsertMode CopyText +sw/inc/istyleaccess.hxx:35 + enum IStyleAccess::SwAutoStyleFamily AUTO_STYLE_NOTXT +sw/inc/itabenum.hxx:31 + enum SwInsertTableFlags HeadlineNoBorder +sw/inc/itabenum.hxx:32 + enum SwInsertTableFlags All +sw/inc/ndhints.hxx:33 + enum CopyOrNewType New +sw/inc/ndtxt.hxx:177 + enum SwTextNode::WrongState PENDING +sw/inc/pagedesc.hxx:130 + enum UseOnPage NoHeaderShare +sw/inc/pagedesc.hxx:131 + enum UseOnPage NoFooterShare +sw/inc/pagedesc.hxx:132 + enum UseOnPage NoFirstShare +sw/inc/redline.hxx:236 + enum SwRangeRedline::Invalidation Remove +sw/inc/reffld.hxx:47 + enum REFERENCEMARK REF_BEGIN +sw/inc/sortopt.hxx:28 + enum SwSortOrder Descending +sw/inc/sortopt.hxx:29 + enum SwSortDirection Columns +sw/inc/SwAppletImpl.hxx:31 + enum SwHtmlOptType IGNORE +sw/inc/swmodule.hxx:64 + enum SvViewOpt DestView +sw/inc/swtypes.hxx:139 + enum SetAttrMode DEFAULT +sw/inc/swtypes.hxx:202 + enum PrepareHint FixSizeChanged +sw/inc/swtypes.hxx:203 + enum PrepareHint FollowFollows +sw/inc/swtypes.hxx:205 + enum PrepareHint FlyFrameSizeChanged +sw/inc/swtypes.hxx:214 + enum PrepareHint ULSpaceChanged +sw/inc/swundo.hxx:32 + enum SwUndoId STD_BEGIN +sw/inc/ToxTabStopTokenHandler.hxx:56 + enum sw::DefaultToxTabStopTokenHandler::TabStopReferencePolicy TABSTOPS_RELATIVE_TO_PAGE +sw/inc/undobj.hxx:138 + enum DelContentType AllMask +sw/inc/unobaseclass.hxx:50 + enum CursorType All +sw/inc/unocoll.hxx:126 + enum SwServiceType FieldTypeDummy1 +sw/inc/unocoll.hxx:127 + enum SwServiceType FieldTypeDummy2 +sw/inc/unocoll.hxx:128 + enum SwServiceType FieldTypeDummy3 +sw/inc/unocrsrhelper.hxx:57 + enum SwGetPropertyStatesCaller SW_PROPERTY_STATE_CALLER_DEFAULT +sw/inc/unostyle.hxx:248 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) FIRST_ROW_STYLE +sw/inc/unostyle.hxx:249 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) LAST_ROW_STYLE +sw/inc/unostyle.hxx:250 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) FIRST_COLUMN_STYLE +sw/inc/unostyle.hxx:251 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) LAST_COLUMN_STYLE +sw/inc/unostyle.hxx:252 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) EVEN_ROWS_STYLE +sw/inc/unostyle.hxx:253 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) ODD_ROWS_STYLE +sw/inc/unostyle.hxx:254 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) EVEN_COLUMNS_STYLE +sw/inc/unostyle.hxx:255 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) ODD_COLUMNS_STYLE +sw/inc/unostyle.hxx:256 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) BODY_STYLE +sw/inc/unostyle.hxx:257 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) BACKGROUND_STYLE +sw/inc/unostyle.hxx:259 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) FIRST_ROW_START_COLUMN_STYLE +sw/inc/unostyle.hxx:260 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) FIRST_ROW_END_COLUMN_STYLE +sw/inc/unostyle.hxx:261 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) LAST_ROW_START_COLUMN_STYLE +sw/inc/unostyle.hxx:262 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) LAST_ROW_END_COLUMN_STYLE +sw/inc/unostyle.hxx:263 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) FIRST_ROW_EVEN_COLUMN_STYLE +sw/inc/unostyle.hxx:264 + enum SwXTextTableStyle::(anonymous at /home/noel/libo2/sw/inc/unostyle.hxx:247:5) LAST_ROW_EVEN_COLUMN_STYLE +sw/inc/unotextrange.hxx:59 + enum sw::TextRangeMode RequireTextNode +sw/inc/unotextrange.hxx:101 + enum SwXTextRange::RangePosition RANGE_IN_TEXT +sw/inc/view.hxx:98 + enum ShellMode Media +sw/inc/view.hxx:99 + enum ShellMode ExtrudedCustomShape +sw/inc/view.hxx:100 + enum ShellMode FontWork +sw/inc/view.hxx:101 + enum ShellMode PostIt +sw/inc/view.hxx:666 + enum SwView::CachedStringID OldGrfCat +sw/inc/view.hxx:667 + enum SwView::CachedStringID OldTabCat +sw/inc/view.hxx:668 + enum SwView::CachedStringID OldFrameCat +sw/inc/view.hxx:669 + enum SwView::CachedStringID OldDrwCat +sw/inc/view.hxx:670 + enum SwView::CachedStringID CachedStrings +sw/inc/viewopt.hxx:45 + enum ViewOptFlags1 Pagebreak +sw/inc/viewopt.hxx:46 + enum ViewOptFlags1 Columnbreak +sw/inc/viewopt.hxx:49 + enum ViewOptFlags1 Ref +sw/inc/viewopt.hxx:93 + enum ViewOptFlags2 Modified +sw/inc/viewopt.hxx:115 + enum ViewOptFlags DocBoundaries +sw/inc/viewopt.hxx:116 + enum ViewOptFlags ObjectBoundaries +sw/inc/viewopt.hxx:117 + enum ViewOptFlags TableBoundaries +sw/inc/viewopt.hxx:118 + enum ViewOptFlags IndexShadings +sw/inc/viewopt.hxx:119 + enum ViewOptFlags Links +sw/inc/viewopt.hxx:120 + enum ViewOptFlags VisitedLinks +sw/inc/viewopt.hxx:121 + enum ViewOptFlags FieldShadings +sw/inc/viewopt.hxx:122 + enum ViewOptFlags SectionBoundaries +sw/inc/viewopt.hxx:123 + enum ViewOptFlags Shadow +sw/source/core/access/accfrmobjmap.hxx:36 + enum SwAccessibleChildMapKey::LayerId CONTROLS +sw/source/core/access/accfrmobjmap.hxx:36 + enum SwAccessibleChildMapKey::LayerId HEAVEN +sw/source/core/access/accfrmobjmap.hxx:36 + enum SwAccessibleChildMapKey::LayerId HELL +sw/source/core/access/accfrmobjmap.hxx:36 + enum SwAccessibleChildMapKey::LayerId INVALID +sw/source/core/access/accfrmobjmap.hxx:36 + enum SwAccessibleChildMapKey::LayerId TEXT +sw/source/core/access/accfrmobjmap.hxx:36 + enum SwAccessibleChildMapKey::LayerId XWINDOW +sw/source/core/fields/cellfml.cxx:58 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/sw/source/core/fields/cellfml.cxx:56:1) cMAXSTACKSIZE +sw/source/core/inc/ascharanchoredobjectposition.hxx:51 + enum sw::LineAlign TOP +sw/source/core/inc/dbg_lay.hxx:56 + enum DbgAction NextSect +sw/source/core/inc/dbg_lay.hxx:56 + enum DbgAction PrevSect +sw/source/core/inc/frame.hxx:489 + enum SwFrame::InvalidationType INVALID_LINENUM +sw/source/core/inc/frame.hxx:489 + enum SwFrame::InvalidationType INVALID_PRTAREA +sw/source/core/inc/frame.hxx:489 + enum SwFrame::InvalidationType INVALID_SIZE +sw/source/core/inc/mvsave.hxx:72 + enum sw::mark::RestoreMode All +sw/source/core/inc/rolbck.hxx:60 + enum HISTORY_HINT HSTRY_SETFMTHNT +sw/source/core/inc/rolbck.hxx:61 + enum HISTORY_HINT HSTRY_RESETFMTHNT +sw/source/core/inc/rolbck.hxx:62 + enum HISTORY_HINT HSTRY_SETTXTHNT +sw/source/core/inc/rolbck.hxx:63 + enum HISTORY_HINT HSTRY_SETTXTFLDHNT +sw/source/core/inc/rolbck.hxx:64 + enum HISTORY_HINT HSTRY_SETREFMARKHNT +sw/source/core/inc/rolbck.hxx:67 + enum HISTORY_HINT HSTRY_SETFTNHNT +sw/source/core/inc/rolbck.hxx:68 + enum HISTORY_HINT HSTRY_CHGFMTCOLL +sw/source/core/inc/rolbck.hxx:70 + enum HISTORY_HINT HSTRY_BOOKMARK +sw/source/core/inc/rolbck.hxx:71 + enum HISTORY_HINT HSTRY_SETATTRSET +sw/source/core/inc/rolbck.hxx:72 + enum HISTORY_HINT HSTRY_CHGFLYANCHOR +sw/source/core/inc/rolbck.hxx:73 + enum HISTORY_HINT HSTRY_CHGFLYCHAIN +sw/source/core/inc/rolbck.hxx:74 + enum HISTORY_HINT HSTRY_CHGCHARFMT +sw/source/core/inc/rolbck.hxx:75 + enum HISTORY_HINT HSTRY_NOTEXTFIELDMARK +sw/source/core/inc/rolbck.hxx:76 + enum HISTORY_HINT HSTRY_TEXTFIELDMARK +sw/source/core/inc/rootfrm.hxx:72 + enum SwRemoveResult Prev +sw/source/core/inc/sectfrm.hxx:33 + enum SwFindMode LastCnt +sw/source/core/inc/SwXMLBlockImport.hxx:102 + enum SwXMLBlockListToken ABBREVIATED_NAME +sw/source/core/inc/SwXMLBlockImport.hxx:105 + enum SwXMLBlockListToken LIST_NAME +sw/source/core/inc/SwXMLBlockImport.hxx:106 + enum SwXMLBlockListToken NAME +sw/source/core/inc/SwXMLBlockImport.hxx:107 + enum SwXMLBlockListToken PACKAGE_NAME +sw/source/core/inc/SwXMLBlockImport.hxx:108 + enum SwXMLBlockListToken UNFORMATTED_TEXT +sw/source/core/inc/txmsrt.hxx:43 + enum TOXSortType TOX_SORT_AUTHORITY +sw/source/core/inc/txtfrm.hxx:103 + enum sw::FrameMode New +sw/source/core/inc/txtfrm.hxx:128 + enum sw::Recreate ThisNode +sw/source/core/inc/UndoManager.hxx:120 + enum sw::UndoManager::UndoOrRedoType Redo +sw/source/core/inc/wrong.hxx:62 + enum WrongListType WRONGLIST_CHANGETRACKING +sw/source/core/layout/paintfrm.cxx:2245 + enum (anonymous namespace)::SwLineEntry::OverlapType NO_OVERLAP +sw/source/core/text/pormulti.hxx:40 + enum SwMultiCreatorId Double +sw/source/core/text/pormulti.hxx:46 + enum RubyPosition BELOW +sw/source/filter/html/css1atr.cxx:107 + enum (anonymous namespace)::Css1Background Attr +sw/source/filter/html/css1atr.cxx:111 + enum (anonymous namespace)::Css1Background Section +sw/source/filter/html/css1atr.cxx:117 + enum (anonymous namespace)::Css1FrameSize MinHeight +sw/source/filter/html/css1atr.cxx:118 + enum (anonymous namespace)::Css1FrameSize FixHeight +sw/source/filter/html/htmlatr.cxx:1061 + enum (anonymous namespace)::HTMLOnOffState HTML_NOT_SUPPORTED +sw/source/filter/html/htmlfly.hxx:36 + enum SwHTMLFrameType HTML_FRMTYPE_TABLE +sw/source/filter/html/htmlfly.hxx:37 + enum SwHTMLFrameType HTML_FRMTYPE_TABLE_CAP +sw/source/filter/html/htmlfly.hxx:38 + enum SwHTMLFrameType HTML_FRMTYPE_MULTICOL +sw/source/filter/html/htmlfly.hxx:39 + enum SwHTMLFrameType HTML_FRMTYPE_EMPTY +sw/source/filter/html/htmlfly.hxx:40 + enum SwHTMLFrameType HTML_FRMTYPE_TEXT +sw/source/filter/html/htmlfly.hxx:41 + enum SwHTMLFrameType HTML_FRMTYPE_GRF +sw/source/filter/html/htmlfly.hxx:42 + enum SwHTMLFrameType HTML_FRMTYPE_PLUGIN +sw/source/filter/html/htmlfly.hxx:43 + enum SwHTMLFrameType HTML_FRMTYPE_APPLET +sw/source/filter/html/htmlfly.hxx:44 + enum SwHTMLFrameType HTML_FRMTYPE_IFRAME +sw/source/filter/html/htmlfly.hxx:45 + enum SwHTMLFrameType HTML_FRMTYPE_OLE +sw/source/filter/html/htmlfly.hxx:46 + enum SwHTMLFrameType HTML_FRMTYPE_MARQUEE +sw/source/filter/html/htmlfly.hxx:47 + enum SwHTMLFrameType HTML_FRMTYPE_CONTROL +sw/source/filter/html/htmlfly.hxx:48 + enum SwHTMLFrameType HTML_FRMTYPE_DRAW +sw/source/filter/html/htmlfly.hxx:49 + enum SwHTMLFrameType HTML_FRMTYPE_END +sw/source/filter/html/htmlfly.hxx:68 + enum HtmlPosition Prefix +sw/source/filter/html/htmlfly.hxx:69 + enum HtmlPosition Before +sw/source/filter/html/htmlform.cxx:110 + enum (anonymous namespace)::HTMLWordWrapMode HTML_WM_SOFT +sw/source/filter/html/htmlforw.cxx:698 + enum Tag TAG_INPUT +sw/source/filter/html/htmlforw.cxx:704 + enum Type TYPE_PASSWORD +sw/source/filter/html/htmlforw.cxx:705 + enum Type TYPE_BUTTON +sw/source/filter/html/htmlforw.cxx:705 + enum Type TYPE_RESET +sw/source/filter/html/htmlforw.cxx:705 + enum Type TYPE_SUBMIT +sw/source/filter/html/parcss1.hxx:66 + enum CSS1ParserState CSS1_PAR_ACCEPTED +sw/source/filter/html/svxcss1.hxx:42 + enum SvxCSS1Position SVX_CSS1_POS_STATIC +sw/source/filter/html/svxcss1.hxx:44 + enum SvxCSS1Position SVX_CSS1_POS_RELATIVE +sw/source/filter/html/svxcss1.hxx:50 + enum SvxCSS1LengthType SVX_CSS1_LTYPE_AUTO +sw/source/filter/html/svxcss1.hxx:59 + enum SvxCSS1SizeType SVX_CSS1_STYPE_AUTO +sw/source/filter/html/swhtml.hxx:198 + enum SwHTMLAppendMode AM_NORMAL +sw/source/filter/html/swhtml.hxx:318 + enum HtmlContextFlags MultiColMask +sw/source/filter/html/wrthtml.hxx:108 + enum HtmlFrmOpts GenImgAllMask +sw/source/filter/html/wrthtml.hxx:109 + enum HtmlFrmOpts GenImgMask +sw/source/filter/inc/fltshell.hxx:100 + enum SwFltStackEntry::RegionMode NoCheck +sw/source/filter/inc/fltshell.hxx:128 + enum SwFltControlStack::MoveAttrsMode DEFAULT +sw/source/filter/inc/fltshell.hxx:132 + enum SwFltControlStack::Flags HYPO +sw/source/filter/inc/fltshell.hxx:133 + enum SwFltControlStack::Flags TAGS_DO_ID +sw/source/filter/inc/fltshell.hxx:134 + enum SwFltControlStack::Flags TAGS_VISIBLE +sw/source/filter/inc/fltshell.hxx:135 + enum SwFltControlStack::Flags BOOK_TO_VAR_REF +sw/source/filter/inc/fltshell.hxx:136 + enum SwFltControlStack::Flags BOOK_AND_REF +sw/source/filter/inc/fltshell.hxx:137 + enum SwFltControlStack::Flags TAGS_IN_TEXT +sw/source/filter/inc/fltshell.hxx:138 + enum SwFltControlStack::Flags ALLOW_FLD_CR +sw/source/filter/inc/wrt_fn.hxx:42 + enum RES_NODE RES_NODE_BEGIN +sw/source/filter/inc/wrt_fn.hxx:43 + enum RES_NODE RES_TXTNODE +sw/source/filter/inc/wrt_fn.hxx:44 + enum RES_NODE RES_GRFNODE +sw/source/filter/inc/wrt_fn.hxx:45 + enum RES_NODE RES_OLENODE +sw/source/filter/inc/wrt_fn.hxx:46 + enum RES_NODE RES_NODE_END +sw/source/filter/ww8/docxattributeoutput.hxx:1033 + enum DocxAttributeOutput::hasResolved no +sw/source/filter/ww8/sprmids.hxx:244 + enum NS_sprm::SGC paragraph +sw/source/filter/ww8/sprmids.hxx:245 + enum NS_sprm::SGC character +sw/source/filter/ww8/sprmids.hxx:246 + enum NS_sprm::SGC picture +sw/source/filter/ww8/sprmids.hxx:247 + enum NS_sprm::SGC section +sw/source/filter/ww8/sprmids.hxx:248 + enum NS_sprm::SGC table +sw/source/filter/ww8/sprmids.hxx:252 + enum NS_sprm::SPRA operand_toggle_1b_0 +sw/source/filter/ww8/sprmids.hxx:253 + enum NS_sprm::SPRA operand_1b_1 +sw/source/filter/ww8/sprmids.hxx:254 + enum NS_sprm::SPRA operand_2b_2 +sw/source/filter/ww8/sprmids.hxx:255 + enum NS_sprm::SPRA operand_4b_3 +sw/source/filter/ww8/sprmids.hxx:256 + enum NS_sprm::SPRA operand_2b_4 +sw/source/filter/ww8/sprmids.hxx:257 + enum NS_sprm::SPRA operand_2b_5 +sw/source/filter/ww8/sprmids.hxx:259 + enum NS_sprm::SPRA operand_3b_7 +sw/source/filter/ww8/wrtww8.hxx:819 + enum MSWordExportBase::ExportFormat DOC +sw/source/filter/ww8/ww8par2.cxx:1639 + enum (anonymous namespace)::wwTableSprm sprmNil +sw/source/filter/ww8/ww8par2.hxx:292 + enum WW8LvlType WW8_Sequence +sw/source/filter/ww8/ww8par.cxx:5728 + enum (anonymous at /home/noel/libo2/sw/source/filter/ww8/ww8par.cxx:5728:5) Other +sw/source/filter/ww8/ww8par.hxx:155 + enum WW8ListManager::ListLevel nMinLevel +sw/source/filter/ww8/ww8scan.hxx:385 + enum ePLCFT PLCF_END +sw/source/filter/ww8/ww8scan.hxx:388 + enum eExtSprm eATNBKN +sw/source/filter/ww8/ww8scan.hxx:388 + enum eExtSprm eBKN +sw/source/filter/ww8/ww8scan.hxx:388 + enum eExtSprm eFACTOIDBKN +sw/source/filter/ww8/ww8scan.hxx:747 + enum eBookStatus BOOK_NORMAL +sw/source/filter/ww8/ww8scan.hxx:867 + enum ManMaskTypes MAN_MASK_NEW_SEP +sw/source/filter/ww8/ww8scan.hxx:935 + enum WW8PLCFMan::WW8PLCFManLimits MAN_PLCF_COUNT +sw/source/filter/ww8/ww8struc.hxx:358 + enum BRC_Sides WW8_BETW +sw/source/filter/ww8/ww8struc.hxx:950 + enum WW8_FSPA::FSPAOrient RelPageBorder +sw/source/filter/xml/xmlitemi.cxx:75 + enum (anonymous namespace)::SwXMLImportTableItemMapper_Impl::(anonymous at /home/noel/libo2/sw/source/filter/xml/xmlitemi.cxx:75:5) BOTTOM +sw/source/filter/xml/xmlitemi.cxx:75 + enum (anonymous namespace)::SwXMLImportTableItemMapper_Impl::(anonymous at /home/noel/libo2/sw/source/filter/xml/xmlitemi.cxx:75:5) LEFT +sw/source/filter/xml/xmlitemi.cxx:75 + enum (anonymous namespace)::SwXMLImportTableItemMapper_Impl::(anonymous at /home/noel/libo2/sw/source/filter/xml/xmlitemi.cxx:75:5) RIGHT +sw/source/filter/xml/xmlitemi.cxx:75 + enum (anonymous namespace)::SwXMLImportTableItemMapper_Impl::(anonymous at /home/noel/libo2/sw/source/filter/xml/xmlitemi.cxx:75:5) TOP +sw/source/filter/xml/xmlmeta.cxx:72 + enum (anonymous namespace)::SvXMLTokenMapAttrs XML_TOK_META_STAT_TABLE +sw/source/filter/xml/xmlmeta.cxx:73 + enum (anonymous namespace)::SvXMLTokenMapAttrs XML_TOK_META_STAT_IMAGE +sw/source/filter/xml/xmlmeta.cxx:74 + enum (anonymous namespace)::SvXMLTokenMapAttrs XML_TOK_META_STAT_OLE +sw/source/filter/xml/xmlmeta.cxx:77 + enum (anonymous namespace)::SvXMLTokenMapAttrs XML_TOK_META_STAT_WORD +sw/source/filter/xml/xmlmeta.cxx:78 + enum (anonymous namespace)::SvXMLTokenMapAttrs XML_TOK_META_STAT_CHAR +sw/source/filter/xml/xmlmeta.cxx:79 + enum (anonymous namespace)::SvXMLTokenMapAttrs XML_TOK_META_STAT_NON_WHITE_SPACE_CHAR +sw/source/filter/xml/xmlmeta.cxx:80 + enum (anonymous namespace)::SvXMLTokenMapAttrs XML_TOK_META_STAT_END +sw/source/ui/fldui/fldref.cxx:739 + enum (anonymous namespace)::FMT_REF_IDX FMT_REF_PAGE_PGDSC_IDX +sw/source/ui/fldui/fldref.cxx:742 + enum (anonymous namespace)::FMT_REF_IDX FMT_REF_ONLYSEQNO_IDX +sw/source/ui/fldui/fldref.cxx:743 + enum (anonymous namespace)::FMT_REF_IDX FMT_REF_NUMBER_IDX +sw/source/ui/fldui/fldref.cxx:744 + enum (anonymous namespace)::FMT_REF_IDX FMT_REF_NUMBER_NO_CONTEXT_IDX +sw/source/ui/fldui/fldref.cxx:745 + enum (anonymous namespace)::FMT_REF_IDX FMT_REF_NUMBER_FULL_CONTEXT_IDX +sw/source/ui/frmdlg/frmpage.cxx:100 + enum (anonymous namespace)::LB Frame +sw/source/ui/frmdlg/frmpage.cxx:101 + enum (anonymous namespace)::LB PrintArea +sw/source/ui/frmdlg/frmpage.cxx:102 + enum (anonymous namespace)::LB VertFrame +sw/source/ui/frmdlg/frmpage.cxx:103 + enum (anonymous namespace)::LB VertPrintArea +sw/source/ui/frmdlg/frmpage.cxx:104 + enum (anonymous namespace)::LB RelFrameLeft +sw/source/ui/frmdlg/frmpage.cxx:105 + enum (anonymous namespace)::LB RelFrameRight +sw/source/ui/frmdlg/frmpage.cxx:107 + enum (anonymous namespace)::LB RelPageLeft +sw/source/ui/frmdlg/frmpage.cxx:108 + enum (anonymous namespace)::LB RelPageRight +sw/source/ui/frmdlg/frmpage.cxx:109 + enum (anonymous namespace)::LB RelPageFrame +sw/source/ui/frmdlg/frmpage.cxx:110 + enum (anonymous namespace)::LB RelPagePrintArea +sw/source/ui/frmdlg/frmpage.cxx:112 + enum (anonymous namespace)::LB FlyRelPageLeft +sw/source/ui/frmdlg/frmpage.cxx:113 + enum (anonymous namespace)::LB FlyRelPageRight +sw/source/ui/frmdlg/frmpage.cxx:114 + enum (anonymous namespace)::LB FlyRelPageFrame +sw/source/ui/frmdlg/frmpage.cxx:115 + enum (anonymous namespace)::LB FlyRelPagePrintArea +sw/source/ui/frmdlg/frmpage.cxx:117 + enum (anonymous namespace)::LB RelBase +sw/source/ui/frmdlg/frmpage.cxx:119 + enum (anonymous namespace)::LB RelRow +sw/source/ui/frmdlg/frmpage.cxx:121 + enum (anonymous namespace)::LB FlyVertFrame +sw/source/ui/frmdlg/frmpage.cxx:122 + enum (anonymous namespace)::LB FlyVertPrintArea +sw/source/ui/frmdlg/frmpage.cxx:124 + enum (anonymous namespace)::LB VertLine +sw/source/uibase/dbui/dbmgr.cxx:151 + enum (anonymous namespace)::WorkingDocType COPY +sw/source/uibase/docvw/edtwin.cxx:1587 + enum SwKeyState NumOrNoNum +sw/source/uibase/docvw/edtwin.cxx:6079 + enum Capitalization CASE_OTHER +sw/source/uibase/fldui/fldmgr.cxx:86 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:84:1) GRP_DOC_BEGIN +sw/source/uibase/fldui/fldmgr.cxx:87 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:84:1) GRP_DOC_END +sw/source/uibase/fldui/fldmgr.cxx:89 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:84:1) GRP_FKT_BEGIN +sw/source/uibase/fldui/fldmgr.cxx:90 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:84:1) GRP_FKT_END +sw/source/uibase/fldui/fldmgr.cxx:92 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:84:1) GRP_REF_BEGIN +sw/source/uibase/fldui/fldmgr.cxx:93 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:84:1) GRP_REF_END +sw/source/uibase/fldui/fldmgr.cxx:95 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:84:1) GRP_REG_BEGIN +sw/source/uibase/fldui/fldmgr.cxx:96 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:84:1) GRP_REG_END +sw/source/uibase/fldui/fldmgr.cxx:98 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:84:1) GRP_DB_BEGIN +sw/source/uibase/fldui/fldmgr.cxx:99 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:84:1) GRP_DB_END +sw/source/uibase/fldui/fldmgr.cxx:101 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:84:1) GRP_VAR_BEGIN +sw/source/uibase/fldui/fldmgr.cxx:102 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:84:1) GRP_VAR_END +sw/source/uibase/fldui/fldmgr.cxx:107 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:105:1) GRP_WEB_DOC_BEGIN +sw/source/uibase/fldui/fldmgr.cxx:108 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:105:1) GRP_WEB_DOC_END +sw/source/uibase/fldui/fldmgr.cxx:110 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:105:1) GRP_WEB_FKT_BEGIN +sw/source/uibase/fldui/fldmgr.cxx:111 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:105:1) GRP_WEB_FKT_END +sw/source/uibase/fldui/fldmgr.cxx:113 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:105:1) GRP_WEB_REF_BEGIN +sw/source/uibase/fldui/fldmgr.cxx:114 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:105:1) GRP_WEB_REF_END +sw/source/uibase/fldui/fldmgr.cxx:116 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:105:1) GRP_WEB_REG_BEGIN +sw/source/uibase/fldui/fldmgr.cxx:117 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:105:1) GRP_WEB_REG_END +sw/source/uibase/fldui/fldmgr.cxx:119 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:105:1) GRP_WEB_DB_BEGIN +sw/source/uibase/fldui/fldmgr.cxx:120 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:105:1) GRP_WEB_DB_END +sw/source/uibase/fldui/fldmgr.cxx:122 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:105:1) GRP_WEB_VAR_BEGIN +sw/source/uibase/fldui/fldmgr.cxx:123 + enum (anonymous at /home/noel/libo2/sw/source/uibase/fldui/fldmgr.cxx:105:1) GRP_WEB_VAR_END +sw/source/uibase/inc/chrdlgmodes.hxx:15 + enum SwCharDlgMode Env +sw/source/uibase/inc/frmmgr.hxx:47 + enum Frmmgr_Type ENVELP +sw/source/uibase/inc/pview.hxx:123 + enum SwPagePreviewWin::MoveMode MV_SPECIFIC_PAGE +sw/source/uibase/inc/swdtflvr.hxx:61 + enum TransferBufferType Drawing +sw/source/uibase/inc/swdtflvr.hxx:69 + enum PasteTableType PASTE_DEFAULT +sw/source/uibase/inc/wrtsh.hxx:82 + enum SelectionType All +sw/source/uibase/inc/wrtsh.hxx:357 + enum SwWrtShell::GetStyle GETSTYLE_CREATESOME +sw/source/uibase/inc/wrtsh.hxx:527 + enum SwWrtShell::PageMove MV_PAGE_UP +sw/source/uibase/inc/wrtsh.hxx:528 + enum SwWrtShell::PageMove MV_PAGE_DOWN +sw/source/uibase/ribbar/workctrl.cxx:976 + enum (anonymous namespace)::PrevNextScrollToolboxController::Type NEXT +sw/source/uibase/uno/unomailmerge.cxx:89 + enum (anonymous namespace)::CloseResult eSuccess +sw/source/uibase/uno/unomailmerge.cxx:91 + enum (anonymous namespace)::CloseResult eFailed +sw/source/uibase/utlui/content.cxx:1017 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_HYPERLINK +sw/source/uibase/utlui/content.cxx:1021 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_ACTIVE_VIEW +sw/source/uibase/utlui/content.cxx:1022 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_HIDDEN +sw/source/uibase/utlui/content.cxx:1023 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_ACTIVE +sw/source/uibase/utlui/content.cxx:1028 + enum (anonymous namespace)::STR_CONTEXT_IDX IDX_STR_OUTLINE_TRACKING +sw/source/uibase/utlui/glbltree.cxx:96 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_INSERT_TEXT +sw/source/uibase/utlui/glbltree.cxx:102 + enum (anonymous namespace)::GLOBAL_CONTEXT_IDX IDX_STR_BROKEN_LINK +sw/source/uibase/utlui/navipi.cxx:461 + enum (anonymous namespace)::StatusIndex IDX_STR_HIDDEN +sw/source/uibase/utlui/navipi.cxx:462 + enum (anonymous namespace)::StatusIndex IDX_STR_ACTIVE +sw/source/uibase/utlui/navipi.cxx:463 + enum (anonymous namespace)::StatusIndex IDX_STR_INACTIVE +toolkit/inc/helper/msgbox.hxx:33 + enum MessBoxStyle DefaultOk +toolkit/source/helper/vclunohelper.cxx:355 + enum (anonymous namespace)::UnitConversionDirection MeasurementUnitToFieldUnit +tools/source/fsys/urlobj.cxx:307 + enum INetURLObject::PrefixInfo::Kind Official +tools/source/fsys/urlobj.cxx:439 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PA +tools/source/fsys/urlobj.cxx:440 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PD +tools/source/fsys/urlobj.cxx:441 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PE +tools/source/fsys/urlobj.cxx:442 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PF +tools/source/fsys/urlobj.cxx:443 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PG +tools/source/fsys/urlobj.cxx:444 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PH +tools/source/fsys/urlobj.cxx:445 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PI +tools/source/fsys/urlobj.cxx:446 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PJ +tools/source/fsys/urlobj.cxx:447 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PK +tools/source/fsys/urlobj.cxx:448 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PL +tools/source/fsys/urlobj.cxx:449 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PM +tools/source/fsys/urlobj.cxx:450 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PN +tools/source/fsys/urlobj.cxx:451 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PO +tools/source/fsys/urlobj.cxx:452 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PP +tools/source/fsys/urlobj.cxx:453 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PQ +tools/source/fsys/urlobj.cxx:454 + enum (anonymous namespace)::(anonymous at /home/noel/libo2/tools/source/fsys/urlobj.cxx:437:1) PR +tools/source/fsys/urlobj.cxx:1616 + enum State STATE_DONE +ucb/source/ucp/ext/ucpext_content.hxx:42 + enum ucb::ucp::ext::ExtensionContentType E_UNKNOWN +ucb/source/ucp/ftp/ftpdirp.hxx:65 + enum ftp::FTPDirentryMode INETCOREFTP_FILEMODE_READ +ucb/source/ucp/ftp/ftpdirp.hxx:68 + enum ftp::FTPDirentryMode INETCOREFTP_FILEMODE_ISLINK +ucb/source/ucp/hierarchy/hierarchycontent.hxx:102 + enum hierarchy_ucp::HierarchyContent::ContentState DEAD +ucb/source/ucp/package/pkgcontent.hxx:92 + enum package_ucp::Content::ContentState TRANSIENT +ucb/source/ucp/package/pkgcontent.hxx:95 + enum package_ucp::Content::ContentState DEAD +ucb/source/ucp/tdoc/tdoc_content.hxx:89 + enum tdoc_ucp::Content::ContentState DEAD +ucb/source/ucp/tdoc/tdoc_uri.hxx:33 + enum tdoc_ucp::Uri::State INVALID +ucb/source/ucp/webdav-neon/DAVException.hxx:130 + enum webdav_ucp::DAVException::ExceptionCode DAV_HTTP_FAILED +ucb/source/ucp/webdav-neon/DAVException.hxx:136 + enum webdav_ucp::DAVException::ExceptionCode DAV_SESSION_CREATE +ucb/source/ucp/webdav-neon/DAVTypes.hxx:191 + enum webdav_ucp::Depth DAVONE +ucb/source/ucp/webdav-neon/DAVTypes.hxx:191 + enum webdav_ucp::Depth DAVZERO +ucb/source/ucp/webdav-neon/DAVTypes.hxx:193 + enum webdav_ucp::ProppatchOperation PROPREMOVE +unoidl/source/sourceprovider-parser-requires.hxx:27 + enum unoidl::detail::SourceProviderAccessDecls ACCESS_DECL_GET +unoidl/source/sourceprovider-parser-requires.hxx:27 + enum unoidl::detail::SourceProviderAccessDecls ACCESS_DECL_SET +unoidl/source/unoidl-read.cxx:139 + enum (anonymous namespace)::Entity::Written DECLARATION +unoidl/source/unoidlprovider.cxx:467 + enum unoidl::detail::(anonymous namespace)::Compare COMPARE_EQUAL +unotools/source/config/fltrcfg.cxx:41 + enum (anonymous namespace)::ConfigFlags MathLoad +unotools/source/config/fltrcfg.cxx:42 + enum (anonymous namespace)::ConfigFlags MathSave +unotools/source/config/fltrcfg.cxx:43 + enum (anonymous namespace)::ConfigFlags WriterLoad +unotools/source/config/fltrcfg.cxx:44 + enum (anonymous namespace)::ConfigFlags WriterSave +unotools/source/config/fltrcfg.cxx:45 + enum (anonymous namespace)::ConfigFlags CalcLoad +unotools/source/config/fltrcfg.cxx:46 + enum (anonymous namespace)::ConfigFlags CalcSave +unotools/source/config/fltrcfg.cxx:47 + enum (anonymous namespace)::ConfigFlags ImpressLoad +unotools/source/config/fltrcfg.cxx:48 + enum (anonymous namespace)::ConfigFlags ImpressSave +unotools/source/config/fltrcfg.cxx:50 + enum (anonymous namespace)::ConfigFlags EnablePowerPointPreview +unotools/source/config/fltrcfg.cxx:51 + enum (anonymous namespace)::ConfigFlags EnableExcelPreview +unotools/source/config/fltrcfg.cxx:52 + enum (anonymous namespace)::ConfigFlags EnableWordPreview +unotools/source/config/fltrcfg.cxx:53 + enum (anonymous namespace)::ConfigFlags UseEnhancedFields +unotools/source/config/fltrcfg.cxx:55 + enum (anonymous namespace)::ConfigFlags SmartArtShapeLoad +unotools/source/config/fltrcfg.cxx:56 + enum (anonymous namespace)::ConfigFlags CharBackgroundToHighlighting +unotools/source/config/fltrcfg.cxx:57 + enum (anonymous namespace)::ConfigFlags CreateMSOLockFiles +unotools/source/config/fltrcfg.cxx:58 + enum (anonymous namespace)::ConfigFlags VisioLoad +unotools/source/config/viewoptions.cxx:85 + enum SvtViewOptionsBase_Impl::State STATE_FALSE +unotools/source/misc/fontcvt.cxx:1018 + enum (anonymous namespace)::SymbolFont MonotypeSorts +unotools/source/misc/fontcvt.cxx:1018 + enum (anonymous namespace)::SymbolFont Symbol +unotools/source/misc/fontcvt.cxx:1018 + enum (anonymous namespace)::SymbolFont Webdings +unotools/source/misc/fontcvt.cxx:1018 + enum (anonymous namespace)::SymbolFont Wingdings +unotools/source/misc/fontcvt.cxx:1018 + enum (anonymous namespace)::SymbolFont Wingdings2 +unotools/source/misc/fontcvt.cxx:1019 + enum (anonymous namespace)::SymbolFont MTExtra +unotools/source/misc/fontcvt.cxx:1019 + enum (anonymous namespace)::SymbolFont TimesNewRoman +unotools/source/misc/fontcvt.cxx:1019 + enum (anonymous namespace)::SymbolFont Wingdings3 +unotools/source/ucbhelper/ucblockbytes.cxx:210 + enum utl::(anonymous namespace)::Moderator::ResultType GENERAL +uui/source/iahndl-errorhandler.cxx:147 + enum Source SOURCE_DEFAULT +uui/source/iahndl-errorhandler.cxx:147 + enum Source SOURCE_SVX +uui/source/iahndl-errorhandler.cxx:147 + enum Source SOURCE_UUI +vcl/inc/driverblocklist.hxx:59 + enum DriverBlocklist::OperatingSystem DRIVER_OS_UNKNOWN +vcl/inc/driverblocklist.hxx:61 + enum DriverBlocklist::OperatingSystem DRIVER_OS_WINDOWS_7 +vcl/inc/driverblocklist.hxx:62 + enum DriverBlocklist::OperatingSystem DRIVER_OS_WINDOWS_8 +vcl/inc/driverblocklist.hxx:63 + enum DriverBlocklist::OperatingSystem DRIVER_OS_WINDOWS_8_1 +vcl/inc/driverblocklist.hxx:64 + enum DriverBlocklist::OperatingSystem DRIVER_OS_WINDOWS_10 +vcl/inc/driverblocklist.hxx:67 + enum DriverBlocklist::OperatingSystem DRIVER_OS_LINUX +vcl/inc/driverblocklist.hxx:69 + enum DriverBlocklist::OperatingSystem DRIVER_OS_OSX_10_5 +vcl/inc/driverblocklist.hxx:70 + enum DriverBlocklist::OperatingSystem DRIVER_OS_OSX_10_6 +vcl/inc/driverblocklist.hxx:71 + enum DriverBlocklist::OperatingSystem DRIVER_OS_OSX_10_7 +vcl/inc/driverblocklist.hxx:72 + enum DriverBlocklist::OperatingSystem DRIVER_OS_OSX_10_8 +vcl/inc/driverblocklist.hxx:75 + enum DriverBlocklist::OperatingSystem DRIVER_OS_ANDROID +vcl/inc/headless/svpgdi.hxx:77 + enum PaintMode Over +vcl/inc/headless/svpinst.hxx:61 + enum SvpRequest MainThreadDispatchOneEvent +vcl/inc/ppdparser.hxx:42 + enum psp::PPDValueType eQuoted +vcl/inc/ppdparser.hxx:42 + enum psp::PPDValueType eString +vcl/inc/ppdparser.hxx:42 + enum psp::PPDValueType eSymbol +vcl/inc/ppdparser.hxx:77 + enum psp::PPDKey::SetupType ExitServer +vcl/inc/ppdparser.hxx:77 + enum psp::PPDKey::SetupType JCLSetup +vcl/inc/ppdparser.hxx:77 + enum psp::PPDKey::SetupType Prolog +vcl/inc/qt5/Qt5Graphics_Controls.hxx:86 + enum Qt5Graphics_Controls::Round Floor +vcl/inc/qt5/Qt5Widget.hxx:45 + enum Qt5Widget::ButtonKeyState Released +vcl/inc/regband.hxx:45 + enum LineType Ascending +vcl/inc/regband.hxx:45 + enum LineType Descending +vcl/inc/salframe.hxx:72 + enum SalFrameStyleFlags NOSHADOW +vcl/inc/salptype.hxx:32 + enum JobSetFlags ALL +vcl/inc/svimpbox.hxx:108 + enum SvImpLBox::ImageType NodeExpanded +vcl/inc/svimpbox.hxx:109 + enum SvImpLBox::ImageType NodeCollapsed +vcl/inc/svimpbox.hxx:110 + enum SvImpLBox::ImageType NodeDontKnow +vcl/inc/svimpbox.hxx:111 + enum SvImpLBox::ImageType EntryDefExpanded +vcl/inc/svimpbox.hxx:112 + enum SvImpLBox::ImageType EntryDefCollapsed +vcl/inc/unx/desktops.hxx:30 + enum DesktopType DESKTOP_UNKNOWN +vcl/inc/unx/gtk/gtkinst.hxx:246 + enum SelectionType SELECTION_PRIMARY +vcl/inc/unx/i18n_cb.hxx:69 + enum PreeditStatus DontKnow +vcl/inc/unx/printergfx.hxx:47 + enum psp::PrinterColor::ColorSpace eRGB +vcl/inc/unx/printergfx.hxx:235 + enum psp::PrinterGfx::pspath_t moveto +vcl/inc/unx/saldisp.hxx:64 + srv_vendor_t vendor_unknown +vcl/inc/unx/saldisp.hxx:71 + enum SalRGB RBG +vcl/inc/unx/saldisp.hxx:72 + enum SalRGB GBR +vcl/inc/unx/saldisp.hxx:72 + enum SalRGB GRB +vcl/inc/unx/saldisp.hxx:73 + enum SalRGB BRG +vcl/inc/unx/salframe.h:55 + enum WMWindowType Normal +vcl/inc/unx/wmadaptor.hxx:42 + enum vcl_sal::WMAdaptor::WMAtom UTF8_STRING +vcl/inc/unx/wmadaptor.hxx:45 + enum vcl_sal::WMAdaptor::WMAtom NET_ACTIVE_WINDOW +vcl/inc/unx/wmadaptor.hxx:46 + enum vcl_sal::WMAdaptor::WMAtom NET_SUPPORTED +vcl/inc/unx/wmadaptor.hxx:47 + enum vcl_sal::WMAdaptor::WMAtom NET_SUPPORTING_WM_CHECK +vcl/inc/unx/wmadaptor.hxx:48 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_NAME +vcl/inc/unx/wmadaptor.hxx:49 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_DESKTOP +vcl/inc/unx/wmadaptor.hxx:50 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_ICON_NAME +vcl/inc/unx/wmadaptor.hxx:51 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_PID +vcl/inc/unx/wmadaptor.hxx:52 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_PING +vcl/inc/unx/wmadaptor.hxx:53 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_STATE +vcl/inc/unx/wmadaptor.hxx:54 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_STATE_MAXIMIZED_HORZ +vcl/inc/unx/wmadaptor.hxx:55 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_STATE_MAXIMIZED_VERT +vcl/inc/unx/wmadaptor.hxx:56 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_STATE_MODAL +vcl/inc/unx/wmadaptor.hxx:57 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_STATE_SKIP_PAGER +vcl/inc/unx/wmadaptor.hxx:58 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_STATE_SKIP_TASKBAR +vcl/inc/unx/wmadaptor.hxx:60 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_STATE_STICKY +vcl/inc/unx/wmadaptor.hxx:61 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_STATE_FULLSCREEN +vcl/inc/unx/wmadaptor.hxx:62 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_STRUT +vcl/inc/unx/wmadaptor.hxx:63 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_STRUT_PARTIAL +vcl/inc/unx/wmadaptor.hxx:64 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_USER_TIME +vcl/inc/unx/wmadaptor.hxx:65 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_WINDOW_TYPE +vcl/inc/unx/wmadaptor.hxx:66 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_WINDOW_TYPE_DESKTOP +vcl/inc/unx/wmadaptor.hxx:67 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_WINDOW_TYPE_DIALOG +vcl/inc/unx/wmadaptor.hxx:68 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_WINDOW_TYPE_DOCK +vcl/inc/unx/wmadaptor.hxx:69 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_WINDOW_TYPE_MENU +vcl/inc/unx/wmadaptor.hxx:70 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_WINDOW_TYPE_NORMAL +vcl/inc/unx/wmadaptor.hxx:71 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_WINDOW_TYPE_TOOLBAR +vcl/inc/unx/wmadaptor.hxx:72 + enum vcl_sal::WMAdaptor::WMAtom KDE_NET_WM_WINDOW_TYPE_OVERRIDE +vcl/inc/unx/wmadaptor.hxx:73 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_WINDOW_TYPE_SPLASH +vcl/inc/unx/wmadaptor.hxx:74 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_WINDOW_TYPE_UTILITY +vcl/inc/unx/wmadaptor.hxx:75 + enum vcl_sal::WMAdaptor::WMAtom NET_NUMBER_OF_DESKTOPS +vcl/inc/unx/wmadaptor.hxx:76 + enum vcl_sal::WMAdaptor::WMAtom NET_CURRENT_DESKTOP +vcl/inc/unx/wmadaptor.hxx:77 + enum vcl_sal::WMAdaptor::WMAtom NET_WORKAREA +vcl/inc/unx/wmadaptor.hxx:78 + enum vcl_sal::WMAdaptor::WMAtom NET_WM_ICON +vcl/inc/unx/wmadaptor.hxx:81 + enum vcl_sal::WMAdaptor::WMAtom WIN_SUPPORTING_WM_CHECK +vcl/inc/unx/wmadaptor.hxx:82 + enum vcl_sal::WMAdaptor::WMAtom WIN_PROTOCOLS +vcl/inc/unx/wmadaptor.hxx:83 + enum vcl_sal::WMAdaptor::WMAtom WIN_WORKSPACE_COUNT +vcl/inc/unx/wmadaptor.hxx:84 + enum vcl_sal::WMAdaptor::WMAtom WIN_WORKSPACE +vcl/inc/unx/wmadaptor.hxx:86 + enum vcl_sal::WMAdaptor::WMAtom WIN_STATE +vcl/inc/unx/wmadaptor.hxx:87 + enum vcl_sal::WMAdaptor::WMAtom WIN_HINTS +vcl/inc/unx/wmadaptor.hxx:88 + enum vcl_sal::WMAdaptor::WMAtom WIN_APP_STATE +vcl/inc/unx/wmadaptor.hxx:89 + enum vcl_sal::WMAdaptor::WMAtom WIN_EXPANDED_SIZE +vcl/inc/unx/wmadaptor.hxx:90 + enum vcl_sal::WMAdaptor::WMAtom WIN_ICONS +vcl/inc/unx/wmadaptor.hxx:91 + enum vcl_sal::WMAdaptor::WMAtom WIN_CLIENT_LIST +vcl/inc/unx/wmadaptor.hxx:94 + enum vcl_sal::WMAdaptor::WMAtom WM_STATE +vcl/inc/unx/wmadaptor.hxx:95 + enum vcl_sal::WMAdaptor::WMAtom MOTIF_WM_HINTS +vcl/inc/unx/wmadaptor.hxx:96 + enum vcl_sal::WMAdaptor::WMAtom WM_PROTOCOLS +vcl/inc/unx/wmadaptor.hxx:97 + enum vcl_sal::WMAdaptor::WMAtom WM_DELETE_WINDOW +vcl/inc/unx/wmadaptor.hxx:98 + enum vcl_sal::WMAdaptor::WMAtom WM_TAKE_FOCUS +vcl/inc/unx/wmadaptor.hxx:99 + enum vcl_sal::WMAdaptor::WMAtom WM_CLIENT_LEADER +vcl/inc/unx/wmadaptor.hxx:100 + enum vcl_sal::WMAdaptor::WMAtom WM_COMMAND +vcl/inc/unx/wmadaptor.hxx:101 + enum vcl_sal::WMAdaptor::WMAtom WM_LOCALE_NAME +vcl/inc/unx/wmadaptor.hxx:102 + enum vcl_sal::WMAdaptor::WMAtom WM_TRANSIENT_FOR +vcl/inc/unx/wmadaptor.hxx:105 + enum vcl_sal::WMAdaptor::WMAtom SAL_QUITEVENT +vcl/inc/unx/wmadaptor.hxx:106 + enum vcl_sal::WMAdaptor::WMAtom SAL_USEREVENT +vcl/inc/unx/wmadaptor.hxx:107 + enum vcl_sal::WMAdaptor::WMAtom SAL_EXTTEXTEVENT +vcl/inc/unx/wmadaptor.hxx:108 + enum vcl_sal::WMAdaptor::WMAtom SAL_GETTIMEEVENT +vcl/inc/unx/wmadaptor.hxx:109 + enum vcl_sal::WMAdaptor::WMAtom VCL_SYSTEM_SETTINGS +vcl/inc/unx/wmadaptor.hxx:110 + enum vcl_sal::WMAdaptor::WMAtom XSETTINGS +vcl/inc/unx/wmadaptor.hxx:111 + enum vcl_sal::WMAdaptor::WMAtom XEMBED +vcl/inc/unx/wmadaptor.hxx:112 + enum vcl_sal::WMAdaptor::WMAtom XEMBED_INFO +vcl/inc/unx/wmadaptor.hxx:113 + enum vcl_sal::WMAdaptor::WMAtom NetAtomMax +vcl/qt5/Qt5FilePicker.cxx:323 + enum (anonymous at /home/noel/libo2/vcl/qt5/Qt5FilePicker.cxx:323:27) Size +vcl/qt5/Qt5Instance.cxx:262 + enum (anonymous at /home/noel/libo2/vcl/qt5/Qt5Instance.cxx:262:45) Size +vcl/qt5/Qt5Transferable.cxx:78 + enum (anonymous at /home/noel/libo2/vcl/qt5/Qt5Transferable.cxx:78:26) Size +vcl/qt5/Qt5Transferable.cxx:138 + enum (anonymous at /home/noel/libo2/vcl/qt5/Qt5Transferable.cxx:138:52) Size +vcl/qt5/Qt5Transferable.cxx:269 + enum (anonymous at /home/noel/libo2/vcl/qt5/Qt5Transferable.cxx:269:22) Size +vcl/qt5/Qt5Transferable.cxx:271 + enum (anonymous at /home/noel/libo2/vcl/qt5/Qt5Transferable.cxx:271:22) Size +vcl/source/control/imivctl.hxx:88 + enum IcnViewFieldType Image +vcl/source/filter/ipict/ipict.cxx:73 + enum PictReaderInternal::(anonymous namespace)::Pattern::PenStyle PEN_DASH +vcl/source/filter/ipict/ipict.cxx:73 + enum PictReaderInternal::(anonymous namespace)::Pattern::PenStyle PEN_DASHDOT +vcl/source/filter/ipict/ipict.cxx:73 + enum PictReaderInternal::(anonymous namespace)::Pattern::PenStyle PEN_DOT +vcl/source/filter/ipict/ipict.cxx:73 + enum PictReaderInternal::(anonymous namespace)::Pattern::PenStyle PEN_NULL +vcl/source/filter/ipict/ipict.cxx:73 + enum PictReaderInternal::(anonymous namespace)::Pattern::PenStyle PEN_SOLID +vcl/source/filter/ipict/ipict.cxx:74 + enum PictReaderInternal::(anonymous namespace)::Pattern::BrushStyle BRUSH_HORZ +vcl/source/filter/ipict/ipict.cxx:74 + enum PictReaderInternal::(anonymous namespace)::Pattern::BrushStyle BRUSH_SOLID +vcl/source/filter/ipict/ipict.cxx:74 + enum PictReaderInternal::(anonymous namespace)::Pattern::BrushStyle BRUSH_VERT +vcl/source/filter/ipict/ipict.cxx:75 + enum PictReaderInternal::(anonymous namespace)::Pattern::BrushStyle BRUSH_CROSS +vcl/source/filter/ipict/ipict.cxx:75 + enum PictReaderInternal::(anonymous namespace)::Pattern::BrushStyle BRUSH_DIAGCROSS +vcl/source/filter/ipict/ipict.cxx:75 + enum PictReaderInternal::(anonymous namespace)::Pattern::BrushStyle BRUSH_DOWNDIAG +vcl/source/filter/ipict/ipict.cxx:75 + enum PictReaderInternal::(anonymous namespace)::Pattern::BrushStyle BRUSH_UPDIAG +vcl/source/filter/ipict/ipict.cxx:76 + enum PictReaderInternal::(anonymous namespace)::Pattern::BrushStyle BRUSH_25 +vcl/source/filter/ipict/ipict.cxx:76 + enum PictReaderInternal::(anonymous namespace)::Pattern::BrushStyle BRUSH_50 +vcl/source/filter/ipict/ipict.cxx:76 + enum PictReaderInternal::(anonymous namespace)::Pattern::BrushStyle BRUSH_75 +vcl/source/filter/ipict/ipict.cxx:148 + enum (anonymous namespace)::PictDrawingMethod UNDEFINED +vcl/source/filter/ixbm/xbmread.cxx:36 + enum (anonymous namespace)::XBMFormat XBM11 +vcl/source/filter/ixbm/xbmread.cxx:41 + enum (anonymous namespace)::ReadState XBMREAD_OK +vcl/source/filter/ixpm/xpmread.cxx:54 + enum (anonymous namespace)::ReadState XPMREAD_OK +vcl/source/filter/jpeg/Exif.hxx:29 + enum exif::Orientation TOP_RIGHT +vcl/source/filter/jpeg/Exif.hxx:31 + enum exif::Orientation BOTTOM_LEFT +vcl/source/filter/jpeg/Exif.hxx:32 + enum exif::Orientation LEFT_TOP +vcl/source/filter/jpeg/Exif.hxx:34 + enum exif::Orientation RIGHT_BOTTOM +vcl/source/filter/jpeg/JpegReader.hxx:33 + enum ReadState JPEGREAD_OK +vcl/source/filter/wmf/emfwr.cxx:100 + enum EmfPlusRecordType Header +vcl/source/filter/wmf/emfwr.cxx:101 + enum EmfPlusRecordType EndOfFile +vcl/source/filter/wmf/emfwr.cxx:102 + enum EmfPlusRecordType GetDC +vcl/source/filter/wmf/emfwr.cxx:103 + enum EmfPlusRecordType FillPolygon +vcl/source/filter/wmf/emfwr.cxx:104 + enum EmfPlusRecordType SetAntiAliasMode +vcl/source/filter/wmf/emfwr.cxx:105 + enum EmfPlusRecordType SetInterpolationMode +vcl/source/filter/wmf/emfwr.cxx:106 + enum EmfPlusRecordType SetPixelOffsetMode +vcl/source/filter/wmf/emfwr.cxx:107 + enum EmfPlusRecordType SetCompositingQuality +vcl/source/fontsubset/ttcr.hxx:49 + enum vcl::TTCRErrCodes TTCR_OK +vcl/source/fontsubset/ttcr.hxx:50 + enum vcl::TTCRErrCodes TTCR_ZEROGLYPHS +vcl/source/fontsubset/ttcr.hxx:51 + enum vcl::TTCRErrCodes TTCR_UNKNOWN +vcl/source/fontsubset/ttcr.hxx:52 + enum vcl::TTCRErrCodes TTCR_NONAMES +vcl/source/fontsubset/ttcr.hxx:53 + enum vcl::TTCRErrCodes TTCR_NAMETOOLONG +vcl/source/fontsubset/ttcr.hxx:54 + enum vcl::TTCRErrCodes TTCR_POSTFORMAT +vcl/source/gdi/pdfwriter_impl.hxx:91 + enum vcl::pdf::GraphicsStateUpdateFlags All +vcl/source/gdi/pdfwriter_impl.hxx:624 + enum vcl::pdf::Mode DEFAULT +vcl/source/gdi/region.cxx:1538 + enum RegionType REGION_COMPLEX +vcl/source/gdi/region.cxx:1538 + enum RegionType REGION_RECTANGLE +vcl/source/gdi/regionband.cxx:199 + enum (anonymous namespace)::StreamEntryType STREAMENTRY_SEPARATION +vcl/source/opengl/OpenGLHelper.cxx:806 + enum (anonymous namespace)::CrashWatchdogTimingMode NORMAL +vcl/source/opengl/x11/X11DeviceInfo.cxx:128 + enum (anonymous at /home/noel/libo2/vcl/source/opengl/x11/X11DeviceInfo.cxx:128:5) buf_size +vcl/unx/generic/app/sm.cxx:188 + enum (anonymous at /home/noel/libo2/vcl/unx/generic/app/sm.cxx:188:1) eCloneCommand +vcl/unx/generic/app/sm.cxx:188 + enum (anonymous at /home/noel/libo2/vcl/unx/generic/app/sm.cxx:188:1) eProgram +vcl/unx/generic/app/sm.cxx:188 + enum (anonymous at /home/noel/libo2/vcl/unx/generic/app/sm.cxx:188:1) eRestartCommand +vcl/unx/generic/app/sm.cxx:188 + enum (anonymous at /home/noel/libo2/vcl/unx/generic/app/sm.cxx:188:1) eRestartStyleHint +vcl/unx/generic/app/sm.cxx:188 + enum (anonymous at /home/noel/libo2/vcl/unx/generic/app/sm.cxx:188:1) eUserId +vcl/unx/generic/app/sm.cxx:189 + enum (anonymous at /home/noel/libo2/vcl/unx/generic/app/sm.cxx:189:1) eDiscardCommand +vcl/unx/generic/dtrans/X11_selection.hxx:178 + enum x11::SelectionManager::Selection::State Inactive +vcl/unx/glxtest.cxx:90 + enum (anonymous at /home/noel/libo2/vcl/unx/glxtest.cxx:90:3) bufsize +vcl/unx/gtk3/a11y/atktextattributes.cxx:82 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_CASEMAP +vcl/unx/gtk3/a11y/atktextattributes.cxx:84 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_CONTOURED +vcl/unx/gtk3/a11y/atktextattributes.cxx:85 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_CHAR_ESCAPEMENT +vcl/unx/gtk3/a11y/atktextattributes.cxx:86 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_BLINKING +vcl/unx/gtk3/a11y/atktextattributes.cxx:87 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_FONT_NAME +vcl/unx/gtk3/a11y/atktextattributes.cxx:88 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_HEIGHT +vcl/unx/gtk3/a11y/atktextattributes.cxx:89 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_HIDDEN +vcl/unx/gtk3/a11y/atktextattributes.cxx:90 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_KERNING +vcl/unx/gtk3/a11y/atktextattributes.cxx:91 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_LOCALE +vcl/unx/gtk3/a11y/atktextattributes.cxx:92 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_POSTURE +vcl/unx/gtk3/a11y/atktextattributes.cxx:93 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_RELIEF +vcl/unx/gtk3/a11y/atktextattributes.cxx:94 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_ROTATION +vcl/unx/gtk3/a11y/atktextattributes.cxx:95 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_SCALE +vcl/unx/gtk3/a11y/atktextattributes.cxx:96 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_SHADOWED +vcl/unx/gtk3/a11y/atktextattributes.cxx:97 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_STRIKETHROUGH +vcl/unx/gtk3/a11y/atktextattributes.cxx:98 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_UNDERLINE +vcl/unx/gtk3/a11y/atktextattributes.cxx:99 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_WEIGHT +vcl/unx/gtk3/a11y/atktextattributes.cxx:101 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO +vcl/unx/gtk3/a11y/atktextattributes.cxx:102 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_JUSTIFICATION +vcl/unx/gtk3/a11y/atktextattributes.cxx:103 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_BOTTOM_MARGIN +vcl/unx/gtk3/a11y/atktextattributes.cxx:104 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_FIRST_LINE_INDENT +vcl/unx/gtk3/a11y/atktextattributes.cxx:105 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_LEFT_MARGIN +vcl/unx/gtk3/a11y/atktextattributes.cxx:106 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_LINE_SPACING +vcl/unx/gtk3/a11y/atktextattributes.cxx:107 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_RIGHT_MARGIN +vcl/unx/gtk3/a11y/atktextattributes.cxx:108 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_STYLE_NAME +vcl/unx/gtk3/a11y/atktextattributes.cxx:109 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_TAB_STOPS +vcl/unx/gtk3/a11y/atktextattributes.cxx:110 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_TOP_MARGIN +vcl/unx/gtk3/a11y/atktextattributes.cxx:111 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_WRITING_MODE +vcl/unx/gtk3/a11y/atktextattributes.cxx:112 + enum (anonymous namespace)::ExportedAttribute TEXT_ATTRIBUTE_LAST +vcl/unx/gtk3/a11y/atktextattributes.cxx:770 + enum (anonymous at /home/noel/libo2/vcl/unx/gtk3/a11y/atktextattributes.cxx:767:1) DECORATION_BLINK +vcl/unx/gtk3/a11y/atktextattributes.cxx:771 + enum (anonymous at /home/noel/libo2/vcl/unx/gtk3/a11y/atktextattributes.cxx:767:1) DECORATION_UNDERLINE +vcl/unx/gtk3/a11y/atktextattributes.cxx:772 + enum (anonymous at /home/noel/libo2/vcl/unx/gtk3/a11y/atktextattributes.cxx:767:1) DECORATION_LINE_THROUGH +vcl/unx/gtk3/fpicker/SalGtkFilePicker.hxx:172 + enum SalGtkFilePicker::(anonymous at /home/noel/libo2/vcl/unx/gtk3/fpicker/SalGtkFilePicker.hxx:171:9) PLAY +vcl/unx/kf5/KF5FilePicker.cxx:63 + enum (anonymous at /home/noel/libo2/vcl/unx/kf5/KF5FilePicker.cxx:63:33) Size +vcl/unx/kf5/KF5FilePicker.cxx:63 + enum (anonymous at /home/noel/libo2/vcl/unx/kf5/KF5FilePicker.cxx:63:56) Size +vcl/unx/kf5/KF5FilePicker.cxx:63 + enum (anonymous at /home/noel/libo2/vcl/unx/kf5/KF5FilePicker.cxx:63:9) Size +vcl/unx/kf5/KF5FilePicker.cxx:64 + enum (anonymous at /home/noel/libo2/vcl/unx/kf5/KF5FilePicker.cxx:64:34) Size +vcl/unx/kf5/KF5FilePicker.cxx:64 + enum (anonymous at /home/noel/libo2/vcl/unx/kf5/KF5FilePicker.cxx:64:60) Size +vcl/unx/kf5/KF5FilePicker.cxx:64 + enum (anonymous at /home/noel/libo2/vcl/unx/kf5/KF5FilePicker.cxx:64:9) Size +vcl/unx/kf5/KF5FilePicker.cxx:65 + enum (anonymous at /home/noel/libo2/vcl/unx/kf5/KF5FilePicker.cxx:65:9) Size +vcl/unx/kf5/KF5FilePicker.cxx:66 + enum (anonymous at /home/noel/libo2/vcl/unx/kf5/KF5FilePicker.cxx:66:9) Size +writerfilter/source/dmapper/BorderHandler.hxx:37 + enum writerfilter::dmapper::BorderHandler::BorderPosition Top +writerfilter/source/dmapper/BorderHandler.hxx:38 + enum writerfilter::dmapper::BorderHandler::BorderPosition Left +writerfilter/source/dmapper/BorderHandler.hxx:39 + enum writerfilter::dmapper::BorderHandler::BorderPosition Bottom +writerfilter/source/dmapper/BorderHandler.hxx:40 + enum writerfilter::dmapper::BorderHandler::BorderPosition Right +writerfilter/source/dmapper/BorderHandler.hxx:41 + enum writerfilter::dmapper::BorderHandler::BorderPosition Horizontal +writerfilter/source/dmapper/BorderHandler.hxx:42 + enum writerfilter::dmapper::BorderHandler::BorderPosition Vertical +writerfilter/source/dmapper/DomainMapper_Impl.hxx:104 + enum writerfilter::dmapper::ContextType CONTEXT_LIST +writerfilter/source/dmapper/DomainMapper_Impl.hxx:125 + enum writerfilter::dmapper::SkipFootnoteSeparator OFF +writerfilter/source/dmapper/DomainMapper_Impl.hxx:133 + enum writerfilter::dmapper::StoredRedlines FRAME +writerfilter/source/dmapper/DomainMapper_Impl.hxx:134 + enum writerfilter::dmapper::StoredRedlines FOOTNOTE +writerfilter/source/dmapper/DomainMapper_Impl.hxx:135 + enum writerfilter::dmapper::StoredRedlines ENDNOTE +writerfilter/source/dmapper/DomainMapper_Impl.hxx:538 + enum writerfilter::dmapper::DomainMapper_Impl::HeaderFooterImportState header +writerfilter/source/dmapper/DomainMapper_Impl.hxx:539 + enum writerfilter::dmapper::DomainMapper_Impl::HeaderFooterImportState footer +writerfilter/source/dmapper/PropertyIds.hxx:27 + enum writerfilter::dmapper::PropertyIds PROP_ID_START +writerfilter/source/dmapper/PropertyMap.hxx:66 + enum writerfilter::dmapper::BorderPosition BORDER_LEFT +writerfilter/source/dmapper/PropertyMap.hxx:67 + enum writerfilter::dmapper::BorderPosition BORDER_RIGHT +writerfilter/source/dmapper/PropertyMap.hxx:68 + enum writerfilter::dmapper::BorderPosition BORDER_TOP +writerfilter/source/dmapper/PropertyMap.hxx:69 + enum writerfilter::dmapper::BorderPosition BORDER_BOTTOM +writerfilter/source/dmapper/PropertyMap.hxx:74 + enum writerfilter::dmapper::GrabBagType NO_GRAB_BAG +writerfilter/source/dmapper/PropertyMap.hxx:214 + enum writerfilter::dmapper::SectionPropertyMap::BorderOffsetFrom Text +writerfilter/source/dmapper/PropertyMap.hxx:558 + enum writerfilter::dmapper::TablePropertyMap::TablePropertyMapTarget TablePropertyMapTarget_START +writerfilter/source/dmapper/PropertyMap.hxx:559 + enum writerfilter::dmapper::TablePropertyMap::TablePropertyMapTarget CELL_MAR_LEFT +writerfilter/source/dmapper/PropertyMap.hxx:560 + enum writerfilter::dmapper::TablePropertyMap::TablePropertyMapTarget CELL_MAR_RIGHT +writerfilter/source/dmapper/PropertyMap.hxx:561 + enum writerfilter::dmapper::TablePropertyMap::TablePropertyMapTarget CELL_MAR_TOP +writerfilter/source/dmapper/PropertyMap.hxx:562 + enum writerfilter::dmapper::TablePropertyMap::TablePropertyMapTarget CELL_MAR_BOTTOM +writerfilter/source/dmapper/PropertyMap.hxx:563 + enum writerfilter::dmapper::TablePropertyMap::TablePropertyMapTarget TABLE_WIDTH +writerfilter/source/dmapper/PropertyMap.hxx:564 + enum writerfilter::dmapper::TablePropertyMap::TablePropertyMapTarget TABLE_WIDTH_TYPE +writerfilter/source/dmapper/PropertyMap.hxx:565 + enum writerfilter::dmapper::TablePropertyMap::TablePropertyMapTarget GAP_HALF +writerfilter/source/dmapper/PropertyMap.hxx:566 + enum writerfilter::dmapper::TablePropertyMap::TablePropertyMapTarget LEFT_MARGIN +writerfilter/source/dmapper/PropertyMap.hxx:567 + enum writerfilter::dmapper::TablePropertyMap::TablePropertyMapTarget HORI_ORIENT +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:40 + enum writerfilter::ooxml::OOXMLFastContextHandler::ResourceEnum_t PROPERTIES +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:40 + enum writerfilter::ooxml::OOXMLFastContextHandler::ResourceEnum_t SHAPE +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:40 + enum writerfilter::ooxml::OOXMLFastContextHandler::ResourceEnum_t TABLE +writerfilter/source/rtftok/rtfdocumentimpl.hxx:96 + enum writerfilter::rtftok::RTFFormFieldType TEXT +writerfilter/source/rtftok/rtfdocumentimpl.hxx:104 + enum writerfilter::rtftok::RTFBmpStyle PNG +writerfilter/source/rtftok/rtfdocumentimpl.hxx:105 + enum writerfilter::rtftok::RTFBmpStyle JPEG +writerfilter/source/rtftok/rtfdocumentimpl.hxx:113 + enum writerfilter::rtftok::RTFFieldStatus RESULT +writerperfect/source/writer/exp/xmlimp.hxx:60 + enum writerperfect::exp::PopupState Consumed +xmlhelp/source/cxxhelp/inc/tvread.hxx:43 + enum treeview::ConfigData::(anonymous at /home/noel/libo2/xmlhelp/source/cxxhelp/inc/tvread.hxx:42:9) PRODUCTNAME +xmlhelp/source/cxxhelp/inc/tvread.hxx:43 + enum treeview::ConfigData::(anonymous at /home/noel/libo2/xmlhelp/source/cxxhelp/inc/tvread.hxx:42:9) PRODUCTVERSION +xmlhelp/source/cxxhelp/inc/tvread.hxx:43 + enum treeview::ConfigData::(anonymous at /home/noel/libo2/xmlhelp/source/cxxhelp/inc/tvread.hxx:42:9) VENDORNAME +xmlhelp/source/cxxhelp/inc/tvread.hxx:43 + enum treeview::ConfigData::(anonymous at /home/noel/libo2/xmlhelp/source/cxxhelp/inc/tvread.hxx:42:9) VENDORVERSION +xmlhelp/source/cxxhelp/inc/tvread.hxx:44 + enum treeview::ConfigData::(anonymous at /home/noel/libo2/xmlhelp/source/cxxhelp/inc/tvread.hxx:42:9) VENDORSHORT +xmlhelp/source/cxxhelp/provider/databases.hxx:232 + enum chelp::Databases::(anonymous at /home/noel/libo2/xmlhelp/source/cxxhelp/provider/databases.hxx:231:9) PRODUCTNAME +xmlhelp/source/cxxhelp/provider/databases.hxx:233 + enum chelp::Databases::(anonymous at /home/noel/libo2/xmlhelp/source/cxxhelp/provider/databases.hxx:231:9) PRODUCTVERSION +xmlhelp/source/cxxhelp/provider/databases.hxx:234 + enum chelp::Databases::(anonymous at /home/noel/libo2/xmlhelp/source/cxxhelp/provider/databases.hxx:231:9) VENDORNAME +xmlhelp/source/cxxhelp/provider/databases.hxx:235 + enum chelp::Databases::(anonymous at /home/noel/libo2/xmlhelp/source/cxxhelp/provider/databases.hxx:231:9) VENDORVERSION +xmlhelp/source/cxxhelp/provider/databases.hxx:236 + enum chelp::Databases::(anonymous at /home/noel/libo2/xmlhelp/source/cxxhelp/provider/databases.hxx:231:9) VENDORSHORT +xmlhelp/source/cxxhelp/provider/databases.hxx:237 + enum chelp::Databases::(anonymous at /home/noel/libo2/xmlhelp/source/cxxhelp/provider/databases.hxx:231:9) NEWPRODUCTNAME +xmlhelp/source/cxxhelp/provider/databases.hxx:238 + enum chelp::Databases::(anonymous at /home/noel/libo2/xmlhelp/source/cxxhelp/provider/databases.hxx:231:9) NEWPRODUCTVERSION +xmlhelp/source/treeview/tvread.cxx:80 + enum treeview::TVDom::Kind tree_node +xmlhelp/source/treeview/tvread.cxx:82 + enum treeview::TVDom::Kind other +xmloff/inc/EnhancedCustomShapeToken.hxx:88 + enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum EAS_CustomShapeEngine +xmloff/inc/EnhancedCustomShapeToken.hxx:89 + enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum EAS_CustomShapeData +xmloff/inc/EnhancedCustomShapeToken.hxx:101 + enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum EAS_Equation +xmloff/inc/EnhancedCustomShapeToken.hxx:105 + enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum EAS_Handle +xmloff/inc/EnhancedCustomShapeToken.hxx:142 + enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum EAS_GluePointLeavingDirections +xmloff/inc/EnhancedCustomShapeToken.hxx:152 + enum xmloff::EnhancedCustomShapeToken::EnhancedCustomShapeTokenEnum EAS_NotFound +xmloff/inc/forms/property_ids.hxx:37 + enum xmloff::PropertyId PID_INVALID +xmloff/source/chart/SchXMLPlotAreaContext.hxx:230 + enum SchXMLWallFloorContext::ContextType CONTEXT_TYPE_FLOOR +xmloff/source/chart/SchXMLTools.hxx:55 + enum SchXMLTools::SchXMLChartTypeEnum XML_CHART_CLASS_LINE +xmloff/source/chart/SchXMLTools.hxx:56 + enum SchXMLTools::SchXMLChartTypeEnum XML_CHART_CLASS_AREA +xmloff/source/chart/SchXMLTools.hxx:57 + enum SchXMLTools::SchXMLChartTypeEnum XML_CHART_CLASS_CIRCLE +xmloff/source/chart/SchXMLTools.hxx:58 + enum SchXMLTools::SchXMLChartTypeEnum XML_CHART_CLASS_RING +xmloff/source/chart/SchXMLTools.hxx:59 + enum SchXMLTools::SchXMLChartTypeEnum XML_CHART_CLASS_SCATTER +xmloff/source/chart/SchXMLTools.hxx:60 + enum SchXMLTools::SchXMLChartTypeEnum XML_CHART_CLASS_RADAR +xmloff/source/chart/SchXMLTools.hxx:61 + enum SchXMLTools::SchXMLChartTypeEnum XML_CHART_CLASS_FILLED_RADAR +xmloff/source/chart/SchXMLTools.hxx:62 + enum SchXMLTools::SchXMLChartTypeEnum XML_CHART_CLASS_BAR +xmloff/source/chart/SchXMLTools.hxx:64 + enum SchXMLTools::SchXMLChartTypeEnum XML_CHART_CLASS_BUBBLE +xmloff/source/chart/SchXMLTools.hxx:65 + enum SchXMLTools::SchXMLChartTypeEnum XML_CHART_CLASS_ADDIN +xmloff/source/chart/transporttypes.hxx:30 + enum SchXMLCellType SCH_CELL_TYPE_UNKNOWN +xmloff/source/core/xmlenums.hxx:24 + enum XMLForbiddenCharactersEnum XML_FORBIDDEN_CHARACTER_LANGUAGE +xmloff/source/core/xmlenums.hxx:25 + enum XMLForbiddenCharactersEnum XML_FORBIDDEN_CHARACTER_COUNTRY +xmloff/source/core/xmlenums.hxx:26 + enum XMLForbiddenCharactersEnum XML_FORBIDDEN_CHARACTER_VARIANT +xmloff/source/core/xmlenums.hxx:27 + enum XMLForbiddenCharactersEnum XML_FORBIDDEN_CHARACTER_BEGIN_LINE +xmloff/source/core/xmlenums.hxx:28 + enum XMLForbiddenCharactersEnum XML_FORBIDDEN_CHARACTER_END_LINE +xmloff/source/core/xmlenums.hxx:34 + enum XMLSymbolDescriptorsEnum XML_SYMBOL_DESCRIPTOR_NAME +xmloff/source/core/xmlenums.hxx:35 + enum XMLSymbolDescriptorsEnum XML_SYMBOL_DESCRIPTOR_EXPORT_NAME +xmloff/source/core/xmlenums.hxx:36 + enum XMLSymbolDescriptorsEnum XML_SYMBOL_DESCRIPTOR_SYMBOL_SET +xmloff/source/core/xmlenums.hxx:37 + enum XMLSymbolDescriptorsEnum XML_SYMBOL_DESCRIPTOR_CHARACTER +xmloff/source/core/xmlenums.hxx:38 + enum XMLSymbolDescriptorsEnum XML_SYMBOL_DESCRIPTOR_FONT_NAME +xmloff/source/core/xmlenums.hxx:39 + enum XMLSymbolDescriptorsEnum XML_SYMBOL_DESCRIPTOR_CHAR_SET +xmloff/source/core/xmlenums.hxx:40 + enum XMLSymbolDescriptorsEnum XML_SYMBOL_DESCRIPTOR_FAMILY +xmloff/source/core/xmlenums.hxx:41 + enum XMLSymbolDescriptorsEnum XML_SYMBOL_DESCRIPTOR_PITCH +xmloff/source/core/xmlenums.hxx:42 + enum XMLSymbolDescriptorsEnum XML_SYMBOL_DESCRIPTOR_WEIGHT +xmloff/source/core/xmlenums.hxx:43 + enum XMLSymbolDescriptorsEnum XML_SYMBOL_DESCRIPTOR_ITALIC +xmloff/source/draw/XMLNumberStyles.cxx:75 + enum DataStyleNumber Day +xmloff/source/draw/XMLNumberStyles.cxx:76 + enum DataStyleNumber DayLong +xmloff/source/draw/XMLNumberStyles.cxx:77 + enum DataStyleNumber MonthLong +xmloff/source/draw/XMLNumberStyles.cxx:78 + enum DataStyleNumber MonthText +xmloff/source/draw/XMLNumberStyles.cxx:79 + enum DataStyleNumber MonthLongText +xmloff/source/draw/XMLNumberStyles.cxx:80 + enum DataStyleNumber Year +xmloff/source/draw/XMLNumberStyles.cxx:81 + enum DataStyleNumber YearLong +xmloff/source/draw/XMLNumberStyles.cxx:82 + enum DataStyleNumber DayOfWeek +xmloff/source/draw/XMLNumberStyles.cxx:83 + enum DataStyleNumber DayOfWeekLong +xmloff/source/draw/XMLNumberStyles.cxx:84 + enum DataStyleNumber TextPoint +xmloff/source/draw/XMLNumberStyles.cxx:86 + enum DataStyleNumber TextCommaSpace +xmloff/source/draw/XMLNumberStyles.cxx:87 + enum DataStyleNumber TextPointSpace +xmloff/source/draw/XMLNumberStyles.cxx:88 + enum DataStyleNumber Hours +xmloff/source/draw/XMLNumberStyles.cxx:89 + enum DataStyleNumber Minutes +xmloff/source/draw/XMLNumberStyles.cxx:90 + enum DataStyleNumber TextColon +xmloff/source/draw/XMLNumberStyles.cxx:91 + enum DataStyleNumber AmPm +xmloff/source/draw/XMLNumberStyles.cxx:92 + enum DataStyleNumber Seconds +xmloff/source/draw/XMLNumberStyles.cxx:93 + enum DataStyleNumber Seconds_02 +xmloff/source/forms/controlelement.hxx:52 + enum xmloff::OControlElement::ElementType GENERIC_CONTROL +xmloff/source/forms/formattributes.hxx:100 + enum EAFlags ControlEvents +xmloff/source/forms/formattributes.hxx:101 + enum EAFlags OnChange +xmloff/source/forms/formattributes.hxx:102 + enum EAFlags OnClick +xmloff/source/forms/formattributes.hxx:103 + enum EAFlags OnDoubleClick +xmloff/source/forms/formattributes.hxx:104 + enum EAFlags OnSelect +xmloff/source/forms/propertyexport.hxx:35 + enum BoolAttrFlags DefaultFalse +xmloff/source/style/PagePropertySetContext.hxx:26 + enum PageContextType Page +xmloff/source/text/txtparae.cxx:341 + enum (anonymous namespace)::eParagraphPropertyNamesEnumAuto NUMBERING_RULES_AUTO +xmloff/source/text/txtparae.cxx:342 + enum (anonymous namespace)::eParagraphPropertyNamesEnumAuto PARA_CONDITIONAL_STYLE_NAME_AUTO +xmloff/source/text/txtparae.cxx:343 + enum (anonymous namespace)::eParagraphPropertyNamesEnumAuto PARA_STYLE_NAME_AUTO +xmloff/source/text/txtparae.cxx:364 + enum (anonymous namespace)::eParagraphPropertyNamesEnum NUMBERING_IS_NUMBER +xmloff/source/text/txtparae.cxx:365 + enum (anonymous namespace)::eParagraphPropertyNamesEnum PARA_NUMBERING_STYLENAME +xmloff/source/text/txtparae.cxx:366 + enum (anonymous namespace)::eParagraphPropertyNamesEnum PARA_OUTLINE_LEVEL +xmloff/source/text/txtparae.cxx:367 + enum (anonymous namespace)::eParagraphPropertyNamesEnum PARA_CONDITIONAL_STYLE_NAME +xmloff/source/text/txtparae.cxx:368 + enum (anonymous namespace)::eParagraphPropertyNamesEnum PARA_STYLE_NAME +xmloff/source/text/txtparae.cxx:369 + enum (anonymous namespace)::eParagraphPropertyNamesEnum TEXT_SECTION +xmloff/source/text/txtparae.cxx:370 + enum (anonymous namespace)::eParagraphPropertyNamesEnum PARA_OUTLINE_CONTENT_VISIBLE +xmloff/source/text/XMLIndexTOCContext.hxx:42 + enum IndexTypeEnum TEXT_INDEX_UNKNOWN +xmloff/source/text/XMLSectionExport.cxx:1056 + enum (anonymous namespace)::TemplateTypeEnum TOK_TTYPE_INVALID +xmloff/source/text/XMLSectionExport.hxx:57 + enum SectionTypeEnum TEXT_SECTION_TYPE_UNKNOWN +xmloff/source/transform/AttrTransformerAction.hxx:26 + enum XMLAttrTransformerAction XML_ATACTION_EOT +xmloff/source/transform/AttrTransformerAction.hxx:123 + enum XMLAttrTransformerAction XML_ATACTION_USER_DEFINED +xmloff/source/transform/ElemTransformerAction.hxx:26 + enum XMLElemTransformerAction XML_ETACTION_EOT +xmloff/source/transform/FamilyType.hxx:25 + enum XMLFamilyType XML_FAMILY_TYPE_PRESENTATION +xmloff/source/transform/FamilyType.hxx:26 + enum XMLFamilyType XML_FAMILY_TYPE_DRAWING_PAGE +xmloff/source/transform/FamilyType.hxx:27 + enum XMLFamilyType XML_FAMILY_TYPE_MASTER_PAGE +xmloff/source/transform/FamilyType.hxx:28 + enum XMLFamilyType XML_FAMILY_TYPE_PAGE_LAYOUT +xmloff/source/transform/FamilyType.hxx:29 + enum XMLFamilyType XML_FAMILY_TYPE_HEADER_FOOTER +xmloff/source/transform/FamilyType.hxx:30 + enum XMLFamilyType XML_FAMILY_TYPE_TEXT +xmloff/source/transform/FamilyType.hxx:31 + enum XMLFamilyType XML_FAMILY_TYPE_PARAGRAPH +xmloff/source/transform/FamilyType.hxx:32 + enum XMLFamilyType XML_FAMILY_TYPE_RUBY +xmloff/source/transform/FamilyType.hxx:33 + enum XMLFamilyType XML_FAMILY_TYPE_SECTION +xmloff/source/transform/FamilyType.hxx:34 + enum XMLFamilyType XML_FAMILY_TYPE_TABLE +xmloff/source/transform/FamilyType.hxx:35 + enum XMLFamilyType XML_FAMILY_TYPE_TABLE_COLUMN +xmloff/source/transform/FamilyType.hxx:36 + enum XMLFamilyType XML_FAMILY_TYPE_TABLE_ROW +xmloff/source/transform/FamilyType.hxx:37 + enum XMLFamilyType XML_FAMILY_TYPE_TABLE_CELL +xmloff/source/transform/FamilyType.hxx:38 + enum XMLFamilyType XML_FAMILY_TYPE_LIST +xmloff/source/transform/FamilyType.hxx:39 + enum XMLFamilyType XML_FAMILY_TYPE_CHART +xmloff/source/transform/FamilyType.hxx:40 + enum XMLFamilyType XML_FAMILY_TYPE_DATA +xmloff/source/transform/FamilyType.hxx:41 + enum XMLFamilyType XML_FAMILY_TYPE_GRADIENT +xmloff/source/transform/FamilyType.hxx:42 + enum XMLFamilyType XML_FAMILY_TYPE_HATCH +xmloff/source/transform/FamilyType.hxx:43 + enum XMLFamilyType XML_FAMILY_TYPE_FILL_IMAGE +xmloff/source/transform/FamilyType.hxx:44 + enum XMLFamilyType XML_FAMILY_TYPE_STROKE_DASH +xmloff/source/transform/FamilyType.hxx:45 + enum XMLFamilyType XML_FAMILY_TYPE_MARKER +xmloff/source/transform/PropType.hxx:24 + enum XMLPropType XML_PROP_TYPE_GRAPHIC +xmloff/source/transform/PropType.hxx:25 + enum XMLPropType XML_PROP_TYPE_DRAWING_PAGE +xmloff/source/transform/PropType.hxx:26 + enum XMLPropType XML_PROP_TYPE_PAGE_LAYOUT +xmloff/source/transform/PropType.hxx:27 + enum XMLPropType XML_PROP_TYPE_HEADER_FOOTER +xmloff/source/transform/PropType.hxx:28 + enum XMLPropType XML_PROP_TYPE_TEXT +xmloff/source/transform/PropType.hxx:29 + enum XMLPropType XML_PROP_TYPE_PARAGRAPH +xmloff/source/transform/PropType.hxx:30 + enum XMLPropType XML_PROP_TYPE_RUBY +xmloff/source/transform/PropType.hxx:31 + enum XMLPropType XML_PROP_TYPE_SECTION +xmloff/source/transform/PropType.hxx:32 + enum XMLPropType XML_PROP_TYPE_TABLE +xmloff/source/transform/PropType.hxx:33 + enum XMLPropType XML_PROP_TYPE_TABLE_COLUMN +xmloff/source/transform/PropType.hxx:34 + enum XMLPropType XML_PROP_TYPE_TABLE_ROW +xmloff/source/transform/PropType.hxx:35 + enum XMLPropType XML_PROP_TYPE_TABLE_CELL +xmloff/source/transform/PropType.hxx:36 + enum XMLPropType XML_PROP_TYPE_LIST_LEVEL +xmloff/source/transform/PropType.hxx:37 + enum XMLPropType XML_PROP_TYPE_CHART +xmlsecurity/inc/documentsignaturehelper.hxx:45 + enum DocumentSignatureAlgorithm OOo3_0 +xmlsecurity/inc/xsecctl.hxx:192 + enum XSecController::InitializationState FAILTOINITIALIZED diff --git a/compilerplugins/clang/unusedfields.cxx b/compilerplugins/clang/unusedfields.cxx new file mode 100644 index 000000000..24045483f --- /dev/null +++ b/compilerplugins/clang/unusedfields.cxx @@ -0,0 +1,1235 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if !defined _WIN32 //TODO, #include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config_clang.h" + +#include "plugin.hxx" +#include "compat.hxx" +#include "check.hxx" + +#include "clang/AST/ParentMapContext.h" + +/** +This performs two analyses: + (1) look for unused fields + (2) look for fields that are write-only + +We dmp a list of calls to methods, and a list of field definitions. +Then we will post-process the 2 lists and find the set of unused methods. + +Be warned that it produces around 5G of log file. + +The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='unusedfields' check + $ ./compilerplugins/clang/unusedfields.py + +and then + $ for dir in *; do make FORCE_COMPILE=all UPDATE_FILES=$dir COMPILER_PLUGIN_TOOL='unusedfieldsremove' $dir; done +to auto-remove the method declarations + +Note that the actual process may involve a fair amount of undoing, hand editing, and general messing around +to get it to work :-) + +*/ + +namespace { + +struct MyFieldInfo +{ + const RecordDecl* parentRecord; + std::string parentClass; + std::string fieldName; + std::string fieldType; + std::string sourceLocation; + std::string access; +}; +bool operator < (const MyFieldInfo &lhs, const MyFieldInfo &rhs) +{ + return std::tie(lhs.parentClass, lhs.fieldName) + < std::tie(rhs.parentClass, rhs.fieldName); +} + + +// try to limit the voluminous output a little +static std::set touchedFromInsideSet; +static std::set touchedFromOutsideSet; +static std::set touchedFromOutsideConstructorSet; +static std::set readFromSet; +static std::set writeToSet; +static std::set definitionSet; + +/** + * Wrap the different kinds of callable and callee objects in the clang AST so I can define methods that handle everything. + */ +class CallerWrapper +{ + const CallExpr * m_callExpr; + const CXXConstructExpr * m_cxxConstructExpr; +public: + CallerWrapper(const CallExpr * callExpr) : m_callExpr(callExpr), m_cxxConstructExpr(nullptr) {} + CallerWrapper(const CXXConstructExpr * cxxConstructExpr) : m_callExpr(nullptr), m_cxxConstructExpr(cxxConstructExpr) {} + unsigned getNumArgs () const + { return m_callExpr ? m_callExpr->getNumArgs() : m_cxxConstructExpr->getNumArgs(); } + const Expr * getArg (unsigned i) const + { return m_callExpr ? m_callExpr->getArg(i) : m_cxxConstructExpr->getArg(i); } +}; +class CalleeWrapper +{ + const FunctionDecl * m_calleeFunctionDecl = nullptr; + const CXXConstructorDecl * m_cxxConstructorDecl = nullptr; + const FunctionProtoType * m_functionPrototype = nullptr; +public: + explicit CalleeWrapper(const FunctionDecl * calleeFunctionDecl) : m_calleeFunctionDecl(calleeFunctionDecl) {} + explicit CalleeWrapper(const CXXConstructExpr * cxxConstructExpr) : m_cxxConstructorDecl(cxxConstructExpr->getConstructor()) {} + explicit CalleeWrapper(const FunctionProtoType * functionPrototype) : m_functionPrototype(functionPrototype) {} + unsigned getNumParams() const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getNumParams(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getNumParams(); + else if (m_functionPrototype->param_type_begin() == m_functionPrototype->param_type_end()) + // FunctionProtoType will assert if we call getParamTypes() and it has no params + return 0; + else + return m_functionPrototype->getParamTypes().size(); + } + const QualType getParamType(unsigned i) const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getParamDecl(i)->getType(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getParamDecl(i)->getType(); + else + return m_functionPrototype->getParamTypes()[i]; + } + std::string getNameAsString() const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getNameAsString(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getNameAsString(); + else + return ""; + } + CXXMethodDecl const * getAsCXXMethodDecl() const + { + if (m_calleeFunctionDecl) + return dyn_cast(m_calleeFunctionDecl); + return nullptr; + } +}; + +class UnusedFields: + public loplugin::FilteringPlugin +{ +public: + explicit UnusedFields(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override; + + bool shouldVisitTemplateInstantiations () const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitFieldDecl( const FieldDecl* ); + bool VisitMemberExpr( const MemberExpr* ); + bool VisitDeclRefExpr( const DeclRefExpr* ); + bool VisitCXXConstructorDecl( const CXXConstructorDecl* ); + bool VisitInitListExpr( const InitListExpr* ); + bool TraverseCXXConstructorDecl( CXXConstructorDecl* ); + bool TraverseCXXMethodDecl( CXXMethodDecl* ); + bool TraverseFunctionDecl( FunctionDecl* ); + bool TraverseIfStmt( IfStmt* ); + +private: + MyFieldInfo niceName(const FieldDecl*); + bool ignoreLocation(SourceLocation loc); + bool checkIgnoreLocation(SourceLocation loc); + void checkTouchedFromOutside(const FieldDecl* fieldDecl, const Expr* memberExpr); + void checkIfReadFrom(const FieldDecl* fieldDecl, const Expr* memberExpr); + void checkIfWrittenTo(const FieldDecl* fieldDecl, const Expr* memberExpr); + bool isSomeKindOfZero(const Expr* arg); + bool checkForWriteWhenUsingCollectionType(const CXXMethodDecl * calleeMethodDecl); + bool IsPassedByNonConst(const FieldDecl* fieldDecl, const Stmt * child, CallerWrapper callExpr, + CalleeWrapper calleeFunctionDecl); + llvm::Optional getCallee(CallExpr const *); + + RecordDecl * insideMoveOrCopyOrCloneDeclParent = nullptr; + RecordDecl * insideStreamOutputOperator = nullptr; + // For reasons I do not understand, parentFunctionDecl() is not reliable, so + // we store the parent function on the way down the AST. + FunctionDecl * insideFunctionDecl = nullptr; + std::vector insideConditionalCheckOfMemberSet; +}; + +void UnusedFields::run() +{ + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + if (!isUnitTestMode()) + { + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + std::string output; + for (const MyFieldInfo & s : touchedFromInsideSet) + output += "inside:\t" + s.parentClass + "\t" + s.fieldName + "\n"; + for (const MyFieldInfo & s : touchedFromOutsideSet) + output += "outside:\t" + s.parentClass + "\t" + s.fieldName + "\n"; + for (const MyFieldInfo & s : touchedFromOutsideConstructorSet) + output += "outside-constructor:\t" + s.parentClass + "\t" + s.fieldName + "\n"; + for (const MyFieldInfo & s : readFromSet) + output += "read:\t" + s.parentClass + "\t" + s.fieldName + "\n"; + for (const MyFieldInfo & s : writeToSet) + output += "write:\t" + s.parentClass + "\t" + s.fieldName + "\n"; + for (const MyFieldInfo & s : definitionSet) + output += "definition:\t" + s.access + "\t" + s.parentClass + "\t" + s.fieldName + "\t" + s.fieldType + "\t" + s.sourceLocation + "\n"; + std::ofstream myfile; + myfile.open( WORKDIR "/loplugin.unusedfields.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + else + { + for (const MyFieldInfo & s : readFromSet) + report( + DiagnosticsEngine::Warning, + "read %0", + s.parentRecord->getBeginLoc()) + << s.fieldName; + for (const MyFieldInfo & s : writeToSet) + report( + DiagnosticsEngine::Warning, + "write %0", + s.parentRecord->getBeginLoc()) + << s.fieldName; + for (const MyFieldInfo & s : touchedFromOutsideConstructorSet) + report( + DiagnosticsEngine::Warning, + "outside-constructor %0", + s.parentRecord->getBeginLoc()) + << s.fieldName; + for (const MyFieldInfo & s : touchedFromOutsideSet) + report( + DiagnosticsEngine::Warning, + "outside %0", + s.parentRecord->getBeginLoc()) + << s.fieldName; + } +} + + +MyFieldInfo UnusedFields::niceName(const FieldDecl* fieldDecl) +{ + MyFieldInfo aInfo; + + const RecordDecl* recordDecl = fieldDecl->getParent(); + + if (const CXXRecordDecl* cxxRecordDecl = dyn_cast(recordDecl)) + { + if (cxxRecordDecl->getTemplateInstantiationPattern()) + cxxRecordDecl = cxxRecordDecl->getTemplateInstantiationPattern(); + aInfo.parentRecord = cxxRecordDecl; + aInfo.parentClass = cxxRecordDecl->getQualifiedNameAsString(); + } + else + { + aInfo.parentRecord = recordDecl; + aInfo.parentClass = recordDecl->getQualifiedNameAsString(); + } + + aInfo.fieldName = fieldDecl->getNameAsString(); + // sometimes the name (if it's an anonymous thing) contains the full path of the build folder, which we don't need + size_t idx = aInfo.fieldName.find(SRCDIR); + if (idx != std::string::npos) { + aInfo.fieldName = aInfo.fieldName.replace(idx, strlen(SRCDIR), ""); + } + aInfo.fieldType = fieldDecl->getType().getAsString(); + + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( fieldDecl->getLocation() ); + StringRef name = getFilenameOfLocation(expansionLoc); + aInfo.sourceLocation = std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(aInfo.sourceLocation); + + switch (fieldDecl->getAccess()) + { + case AS_public: aInfo.access = "public"; break; + case AS_private: aInfo.access = "private"; break; + case AS_protected: aInfo.access = "protected"; break; + default: aInfo.access = "unknown"; break; + } + + return aInfo; +} + +/** + * Our need to see everything conflicts with the PCH code in pluginhandler::ignoreLocation, + * so we have to do this ourselves. + */ +bool UnusedFields::ignoreLocation(SourceLocation loc) +{ + static std::unordered_map checkedMap; + auto it = checkedMap.find(loc); + if (it != checkedMap.end()) + return it->second; + bool ignore = checkIgnoreLocation(loc); + checkedMap.emplace(loc, ignore); + return ignore; +} + +bool UnusedFields::checkIgnoreLocation(SourceLocation loc) +{ + // simplified form of the code in PluginHandler::checkIgnoreLocation + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( loc ); + if( compiler.getSourceManager().isInSystemHeader( expansionLoc )) + return true; + PresumedLoc presumedLoc = compiler.getSourceManager().getPresumedLoc( expansionLoc ); + if( presumedLoc.isInvalid()) + return true; + const char* bufferName = presumedLoc.getFilename(); + if (bufferName == NULL + || loplugin::hasPathnamePrefix(bufferName, SRCDIR "/external/") + || loplugin::hasPathnamePrefix(bufferName, WORKDIR "/")) + return true; + if( loplugin::hasPathnamePrefix(bufferName, BUILDDIR "/") + || loplugin::hasPathnamePrefix(bufferName, SRCDIR "/") ) + return false; // ok + return true; +} + + +bool UnusedFields::VisitFieldDecl( const FieldDecl* fieldDecl ) +{ + fieldDecl = fieldDecl->getCanonicalDecl(); + if (ignoreLocation( fieldDecl->getBeginLoc() )) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocation()))) { + return true; + } + + if (fieldDecl->getInClassInitializer() && !isSomeKindOfZero(fieldDecl->getInClassInitializer())) { + writeToSet.insert(niceName(fieldDecl)); + } + + definitionSet.insert(niceName(fieldDecl)); + return true; +} + +/** + Does the expression being used to initialise a field value evaluate to + the same as a default value? + */ +bool UnusedFields::isSomeKindOfZero(const Expr* arg) +{ + assert(arg); + arg = arg->IgnoreParenCasts(); + if (isa(arg)) { + arg = dyn_cast(arg)->getExpr(); + } + arg = arg->IgnoreParenCasts(); + // ignore this, it seems to trigger an infinite recursion + if (isa(arg)) { + return false; + } + if (auto cxxConstructExpr = dyn_cast(arg)) { + return cxxConstructExpr->getConstructor()->isDefaultConstructor(); + } + APSInt x1; + if (compat::EvaluateAsInt(arg, x1, compiler.getASTContext())) + { + return x1 == 0; + } + if (isa(arg)) { + return true; + } + if (isa(arg)) + { + const CXXBindTemporaryExpr* strippedArg = dyn_cast_or_null(arg->IgnoreParenCasts()); + if (strippedArg) + { + auto temp = dyn_cast(strippedArg->getSubExpr()); + if (temp->getNumArgs() == 0) + { + if (loplugin::TypeCheck(temp->getType()).Class("OUString").Namespace("rtl").GlobalNamespace()) { + return true; + } + if (loplugin::TypeCheck(temp->getType()).Class("OString").Namespace("rtl").GlobalNamespace()) { + return true; + } + return false; + } + } + } + + // Get the expression contents. + // This helps us find params which are always initialised with something like "OUString()". + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = arg->getBeginLoc(); + SourceLocation endLoc = arg->getEndLoc(); + const char *p1 = SM.getCharacterData( startLoc ); + const char *p2 = SM.getCharacterData( endLoc ); + if (!p1 || !p2 || (p2 - p1) < 0 || (p2 - p1) > 40) { + return false; + } + unsigned n = Lexer::MeasureTokenLength( endLoc, SM, compiler.getLangOpts()); + std::string s( p1, p2 - p1 + n); + // strip linefeed and tab characters so they don't interfere with the parsing of the log file + std::replace( s.begin(), s.end(), '\r', ' '); + std::replace( s.begin(), s.end(), '\n', ' '); + std::replace( s.begin(), s.end(), '\t', ' '); + + // now normalize the value. For some params, like OUString, we can pass it as OUString() or "" and they are the same thing + if (s == "OUString()") + return true; + else if (s == "OString()") + return true; + return false; +} + +static char easytolower(char in) +{ + if (in<='Z' && in>='A') + return in-('Z'-'z'); + return in; +} + +bool startswith(const std::string& rStr, const char* pSubStr) +{ + return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; +} + +bool UnusedFields::TraverseCXXConstructorDecl(CXXConstructorDecl* cxxConstructorDecl) +{ + auto copy = insideMoveOrCopyOrCloneDeclParent; + if (!ignoreLocation(cxxConstructorDecl->getBeginLoc()) && cxxConstructorDecl->isThisDeclarationADefinition()) + { + if (cxxConstructorDecl->isCopyOrMoveConstructor()) + insideMoveOrCopyOrCloneDeclParent = cxxConstructorDecl->getParent(); + } + bool ret = RecursiveASTVisitor::TraverseCXXConstructorDecl(cxxConstructorDecl); + insideMoveOrCopyOrCloneDeclParent = copy; + return ret; +} + +bool UnusedFields::TraverseCXXMethodDecl(CXXMethodDecl* cxxMethodDecl) +{ + auto copy1 = insideMoveOrCopyOrCloneDeclParent; + auto copy2 = insideFunctionDecl; + if (!ignoreLocation(cxxMethodDecl->getBeginLoc()) && cxxMethodDecl->isThisDeclarationADefinition()) + { + if (cxxMethodDecl->isCopyAssignmentOperator() + || cxxMethodDecl->isMoveAssignmentOperator() + || (cxxMethodDecl->getIdentifier() + && (cxxMethodDecl->getName().startswith("Clone") + || cxxMethodDecl->getName().startswith("clone") + || cxxMethodDecl->getName().startswith("createClone")))) + insideMoveOrCopyOrCloneDeclParent = cxxMethodDecl->getParent(); + // these are similar in that they tend to simply enumerate all the fields of an object without putting + // them to some useful purpose + auto op = cxxMethodDecl->getOverloadedOperator(); + if (op == OO_EqualEqual || op == OO_ExclaimEqual) + insideMoveOrCopyOrCloneDeclParent = cxxMethodDecl->getParent(); + } + insideFunctionDecl = cxxMethodDecl; + bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl); + insideMoveOrCopyOrCloneDeclParent = copy1; + insideFunctionDecl = copy2; + return ret; +} + +bool UnusedFields::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + auto copy1 = insideStreamOutputOperator; + auto copy2 = insideFunctionDecl; + auto copy3 = insideMoveOrCopyOrCloneDeclParent; + if (functionDecl->getLocation().isValid() && !ignoreLocation(functionDecl->getBeginLoc()) && functionDecl->isThisDeclarationADefinition()) + { + auto op = functionDecl->getOverloadedOperator(); + if (op == OO_LessLess + && functionDecl->getNumParams() == 2) + { + QualType qt = functionDecl->getParamDecl(1)->getType(); + insideStreamOutputOperator = qt.getNonReferenceType().getUnqualifiedType()->getAsCXXRecordDecl(); + } + // these are similar in that they tend to simply enumerate all the fields of an object without putting + // them to some useful purpose + if (op == OO_EqualEqual || op == OO_ExclaimEqual) + { + QualType qt = functionDecl->getParamDecl(1)->getType(); + insideMoveOrCopyOrCloneDeclParent = qt.getNonReferenceType().getUnqualifiedType()->getAsCXXRecordDecl(); + } + } + insideFunctionDecl = functionDecl; + bool ret = RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); + insideStreamOutputOperator = copy1; + insideFunctionDecl = copy2; + insideMoveOrCopyOrCloneDeclParent = copy3; + return ret; +} + +bool UnusedFields::TraverseIfStmt(IfStmt* ifStmt) +{ + FieldDecl const * memberFieldDecl = nullptr; + Expr const * cond = ifStmt->getCond()->IgnoreParenImpCasts(); + + if (auto memberCallExpr = dyn_cast(cond)) + { + if (auto cxxConvert = dyn_cast_or_null(memberCallExpr->getMethodDecl())) + { + if (cxxConvert->getConversionType()->isBooleanType()) + if (auto memberExpr = dyn_cast(memberCallExpr->getImplicitObjectArgument()->IgnoreParenImpCasts())) + if ((memberFieldDecl = dyn_cast(memberExpr->getMemberDecl()))) + insideConditionalCheckOfMemberSet.push_back(memberFieldDecl); + } + else if (auto cxxMethod = memberCallExpr->getMethodDecl()) + { + if (cxxMethod->getIdentifier() && cxxMethod->getName() == "get" && memberCallExpr->getNumArgs()==0) + if (auto memberExpr = dyn_cast(memberCallExpr->getImplicitObjectArgument()->IgnoreParenImpCasts())) + if ((memberFieldDecl = dyn_cast(memberExpr->getMemberDecl()))) + insideConditionalCheckOfMemberSet.push_back(memberFieldDecl); + } + } + else if (auto memberExpr = dyn_cast(cond)) + { + if ((memberFieldDecl = dyn_cast(memberExpr->getMemberDecl()))) + insideConditionalCheckOfMemberSet.push_back(memberFieldDecl); + } + + bool ret = RecursiveASTVisitor::TraverseIfStmt(ifStmt); + if (memberFieldDecl) + insideConditionalCheckOfMemberSet.pop_back(); + return ret; +} + +bool UnusedFields::VisitMemberExpr( const MemberExpr* memberExpr ) +{ + const ValueDecl* decl = memberExpr->getMemberDecl(); + const FieldDecl* fieldDecl = dyn_cast(decl); + if (!fieldDecl) { + return true; + } + fieldDecl = fieldDecl->getCanonicalDecl(); + if (ignoreLocation(fieldDecl->getBeginLoc())) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocation()))) { + return true; + } + + checkTouchedFromOutside(fieldDecl, memberExpr); + + checkIfReadFrom(fieldDecl, memberExpr); + + checkIfWrittenTo(fieldDecl, memberExpr); + + return true; +} + +void UnusedFields::checkIfReadFrom(const FieldDecl* fieldDecl, const Expr* memberExpr) +{ + if (insideMoveOrCopyOrCloneDeclParent || insideStreamOutputOperator) + { + RecordDecl const * cxxRecordDecl1 = fieldDecl->getParent(); + // we don't care about reads from a field when inside the copy/move constructor/operator= for that field + if (cxxRecordDecl1 && (cxxRecordDecl1 == insideMoveOrCopyOrCloneDeclParent)) + return; + // we don't care about reads when the field is being used in an output operator, this is normally + // debug stuff + if (cxxRecordDecl1 && (cxxRecordDecl1 == insideStreamOutputOperator)) + return; + } + + auto parentsRange = compiler.getASTContext().getParents(*memberExpr); + const Stmt* child = memberExpr; + const Stmt* parent = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get(); + // walk up the tree until we find something interesting + bool bPotentiallyReadFrom = false; + bool bDump = false; + auto walkUp = [&]() { + child = parent; + auto parentsRange = compiler.getASTContext().getParents(*parent); + parent = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get(); + }; + do + { + if (!parent) + { + // check if we're inside a CXXCtorInitializer or a VarDecl + auto parentsRange = compiler.getASTContext().getParents(*child); + if ( parentsRange.begin() != parentsRange.end()) + { + const Decl* decl = parentsRange.begin()->get(); + if (decl && (isa(decl) || isa(decl))) + bPotentiallyReadFrom = true; + } + if (!bPotentiallyReadFrom) + return; + break; + } + if (isa(parent)) + { + // once we see one of these, there is not much useful we can know + bPotentiallyReadFrom = true; + break; + } + else if (isa(parent) || isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent)) + { + walkUp(); + } + else if (auto unaryOperator = dyn_cast(parent)) + { + UnaryOperator::Opcode op = unaryOperator->getOpcode(); + if (memberExpr->getType()->isArrayType() && op == UO_Deref) + { + // ignore, deref'ing an array does not count as a read + } + else if (op == UO_AddrOf || op == UO_Deref + || op == UO_Plus || op == UO_Minus + || op == UO_Not || op == UO_LNot) + { + bPotentiallyReadFrom = true; + break; + } + /* The following are technically reads, but from a code-sense they're more of a write/modify, so + ignore them to find interesting fields that only modified, not usefully read: + UO_PreInc / UO_PostInc / UO_PreDec / UO_PostDec + But we still walk up in case the result of the expression is used in a read sense. + */ + walkUp(); + } + else if (auto caseStmt = dyn_cast(parent)) + { + bPotentiallyReadFrom = caseStmt->getLHS() == child || caseStmt->getRHS() == child; + break; + } + else if (auto ifStmt = dyn_cast(parent)) + { + bPotentiallyReadFrom = ifStmt->getCond() == child; + break; + } + else if (auto doStmt = dyn_cast(parent)) + { + bPotentiallyReadFrom = doStmt->getCond() == child; + break; + } + else if (auto arraySubscriptExpr = dyn_cast(parent)) + { + if (arraySubscriptExpr->getIdx() == child) + { + bPotentiallyReadFrom = true; + break; + } + walkUp(); + } + else if (auto binaryOp = dyn_cast(parent)) + { + BinaryOperator::Opcode op = binaryOp->getOpcode(); + const bool assignmentOp = op == BO_Assign || op == BO_MulAssign + || op == BO_DivAssign || op == BO_RemAssign || op == BO_AddAssign + || op == BO_SubAssign || op == BO_ShlAssign || op == BO_ShrAssign + || op == BO_AndAssign || op == BO_XorAssign || op == BO_OrAssign; + if (binaryOp->getLHS() == child && assignmentOp) + break; + else + { + bPotentiallyReadFrom = true; + break; + } + } + else if (auto operatorCallExpr = dyn_cast(parent)) + { + auto op = operatorCallExpr->getOperator(); + const bool assignmentOp = op == OO_Equal || op == OO_StarEqual || + op == OO_SlashEqual || op == OO_PercentEqual || + op == OO_PlusEqual || op == OO_MinusEqual || + op == OO_LessLessEqual || + op == OO_AmpEqual || op == OO_CaretEqual || + op == OO_PipeEqual; + if (operatorCallExpr->getArg(0) == child && assignmentOp) + break; + else if (op == OO_GreaterGreaterEqual && operatorCallExpr->getArg(1) == child) + break; // this is a write-only call + else + { + bPotentiallyReadFrom = true; + break; + } + } + else if (auto cxxMemberCallExpr = dyn_cast(parent)) + { + bool bWriteOnlyCall = false; + const CXXMethodDecl * callee = cxxMemberCallExpr->getMethodDecl(); + if (callee) + { + const Expr* tmp = dyn_cast(child); + if (tmp->isBoundMemberFunction(compiler.getASTContext())) { + tmp = dyn_cast(tmp)->getBase(); + } + if (cxxMemberCallExpr->getImplicitObjectArgument() == tmp) + { + // FIXME perhaps a better solution here would be some kind of SAL_PARAM_WRITEONLY attribute + // which we could scatter around. + std::string name = callee->getNameAsString(); + std::transform(name.begin(), name.end(), name.begin(), easytolower); + if (startswith(name, "emplace") || name == "insert" + || name == "erase" || name == "remove" || name == "remove_if" || name == "sort" + || name == "push_back" || name == "pop_back" + || name == "push_front" || name == "pop_front" + || name == "reserve" || name == "resize" || name == "reset" + || name == "clear" || name == "fill") + // write-only modifications to collections + bWriteOnlyCall = true; + else if (name == "dispose" || name == "disposeAndClear" || name == "swap") + // we're abusing the write-only analysis here to look for fields which don't have anything useful + // being done to them, so we're ignoring things like std::vector::clear, std::vector::swap, + // and VclPtr::disposeAndClear + bWriteOnlyCall = true; + } + } + if (!bWriteOnlyCall) + bPotentiallyReadFrom = true; + break; + } + else if (auto callExpr = dyn_cast(parent)) + { + bool bWriteOnlyCall = false; + // check for calls to ReadXXX(foo) type methods, where foo is write-only + auto callee = getCallee(callExpr); + if (callee) + { + // FIXME perhaps a better solution here would be some kind of SAL_PARAM_WRITEONLY attribute + // which we could scatter around. + std::string name = callee->getNameAsString(); + std::transform(name.begin(), name.end(), name.begin(), easytolower); + if (startswith(name, "read")) + // this is a write-only call + bWriteOnlyCall = true; + } + if (!bWriteOnlyCall) + bPotentiallyReadFrom = true; + break; + } + else if (isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent)) + { + bPotentiallyReadFrom = true; + break; + } + else if (isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent)) + { + break; + } + else + { + bPotentiallyReadFrom = true; + bDump = true; + break; + } + } while (true); + + if (bDump) + { + report( + DiagnosticsEngine::Warning, + "oh dear, what can the matter be?", + memberExpr->getBeginLoc()) + << memberExpr->getSourceRange(); + report( + DiagnosticsEngine::Note, + "parent over here", + parent->getBeginLoc()) + << parent->getSourceRange(); + parent->dump(); + memberExpr->dump(); + } + + MyFieldInfo fieldInfo = niceName(fieldDecl); + if (bPotentiallyReadFrom) + { + readFromSet.insert(fieldInfo); + } +} + +void UnusedFields::checkIfWrittenTo(const FieldDecl* fieldDecl, const Expr* memberExpr) +{ + if (insideMoveOrCopyOrCloneDeclParent) + { + RecordDecl const * cxxRecordDecl1 = fieldDecl->getParent(); + // we don't care about writes to a field when inside the copy/move constructor/operator= for that field + if (cxxRecordDecl1 && (cxxRecordDecl1 == insideMoveOrCopyOrCloneDeclParent)) + { + return; + } + } + + // if we're inside a block that looks like + // if (fieldDecl) + // ... + // then writes to this field don't matter, because unless we find another write to this field, this field is dead + if (std::find(insideConditionalCheckOfMemberSet.begin(), insideConditionalCheckOfMemberSet.end(), fieldDecl) != insideConditionalCheckOfMemberSet.end()) + return; + + auto parentsRange = compiler.getASTContext().getParents(*memberExpr); + const Stmt* child = memberExpr; + const Stmt* parent = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get(); + // walk up the tree until we find something interesting + bool bPotentiallyWrittenTo = false; + bool bDump = false; + auto walkUp = [&]() { + child = parent; + auto parentsRange = compiler.getASTContext().getParents(*parent); + parent = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get(); + }; + do + { + if (!parent) + { + // check if we have an expression like + // int& r = m_field; + auto parentsRange = compiler.getASTContext().getParents(*child); + if (parentsRange.begin() != parentsRange.end()) + { + auto varDecl = dyn_cast_or_null(parentsRange.begin()->get()); + // The isImplicit() call is to avoid triggering when we see the vardecl which is part of a for-range statement, + // which is of type 'T&&' and also an l-value-ref ? + if (varDecl && !varDecl->isImplicit() && loplugin::TypeCheck(varDecl->getType()).LvalueReference().NonConst()) + { + bPotentiallyWrittenTo = true; + } + } + break; + } + if (isa(parent)) + { + // once we see one of these, there is not much useful we can know + bPotentiallyWrittenTo = true; + break; + } + else if (isa(parent) || isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent)) + { + walkUp(); + } + else if (auto unaryOperator = dyn_cast(parent)) + { + UnaryOperator::Opcode op = unaryOperator->getOpcode(); + if (op == UO_AddrOf || op == UO_PostInc || op == UO_PostDec || op == UO_PreInc || op == UO_PreDec) + { + bPotentiallyWrittenTo = true; + } + break; + } + else if (auto arraySubscriptExpr = dyn_cast(parent)) + { + if (arraySubscriptExpr->getIdx() == child) + break; + walkUp(); + } + else if (auto operatorCallExpr = dyn_cast(parent)) + { + auto callee = getCallee(operatorCallExpr); + if (callee) + { + // if calling a non-const operator on the field + auto calleeMethodDecl = callee->getAsCXXMethodDecl(); + if (calleeMethodDecl && operatorCallExpr->getArg(0) == child) + { + if (!calleeMethodDecl->isConst()) + bPotentiallyWrittenTo = checkForWriteWhenUsingCollectionType(calleeMethodDecl); + } + else if (IsPassedByNonConst(fieldDecl, child, operatorCallExpr, *callee)) + { + bPotentiallyWrittenTo = true; + } + } + else + bPotentiallyWrittenTo = true; // conservative, could improve + break; + } + else if (auto cxxMemberCallExpr = dyn_cast(parent)) + { + const CXXMethodDecl * calleeMethodDecl = cxxMemberCallExpr->getMethodDecl(); + if (calleeMethodDecl) + { + // if calling a non-const method on the field + const Expr* tmp = dyn_cast(child); + if (tmp->isBoundMemberFunction(compiler.getASTContext())) { + tmp = dyn_cast(tmp)->getBase(); + } + if (cxxMemberCallExpr->getImplicitObjectArgument() == tmp) + { + if (!calleeMethodDecl->isConst()) + bPotentiallyWrittenTo = checkForWriteWhenUsingCollectionType(calleeMethodDecl); + break; + } + else if (IsPassedByNonConst(fieldDecl, child, cxxMemberCallExpr, CalleeWrapper(calleeMethodDecl))) + bPotentiallyWrittenTo = true; + } + else + bPotentiallyWrittenTo = true; // can happen in templates + break; + } + else if (auto cxxConstructExpr = dyn_cast(parent)) + { + if (IsPassedByNonConst(fieldDecl, child, cxxConstructExpr, CalleeWrapper(cxxConstructExpr))) + bPotentiallyWrittenTo = true; + break; + } + else if (auto callExpr = dyn_cast(parent)) + { + auto callee = getCallee(callExpr); + if (callee) { + if (IsPassedByNonConst(fieldDecl, child, callExpr, *callee)) + bPotentiallyWrittenTo = true; + } else + bPotentiallyWrittenTo = true; // conservative, could improve + break; + } + else if (auto binaryOp = dyn_cast(parent)) + { + BinaryOperator::Opcode op = binaryOp->getOpcode(); + const bool assignmentOp = op == BO_Assign || op == BO_MulAssign + || op == BO_DivAssign || op == BO_RemAssign || op == BO_AddAssign + || op == BO_SubAssign || op == BO_ShlAssign || op == BO_ShrAssign + || op == BO_AndAssign || op == BO_XorAssign || op == BO_OrAssign; + if (assignmentOp) + { + if (binaryOp->getLHS() == child) + bPotentiallyWrittenTo = true; + else if (loplugin::TypeCheck(binaryOp->getLHS()->getType()).LvalueReference().NonConst()) + // if the LHS is a non-const reference, we could write to the field later on + bPotentiallyWrittenTo = true; + } + break; + } + else if (isa(parent)) + { + if (insideFunctionDecl) + { + auto tc = loplugin::TypeCheck(insideFunctionDecl->getReturnType()); + if (tc.LvalueReference().NonConst()) + bPotentiallyWrittenTo = true; + } + break; + } + else if (isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent) + || isa(parent)) + { + break; + } + else + { + bPotentiallyWrittenTo = true; + bDump = true; + break; + } + } while (true); + + if (bDump) + { + report( + DiagnosticsEngine::Warning, + "oh dear, what can the matter be? writtenTo=%0", + memberExpr->getBeginLoc()) + << bPotentiallyWrittenTo + << memberExpr->getSourceRange(); + if (parent) + { + report( + DiagnosticsEngine::Note, + "parent over here", + parent->getBeginLoc()) + << parent->getSourceRange(); + parent->dump(); + } + memberExpr->dump(); + fieldDecl->getType()->dump(); + } + + MyFieldInfo fieldInfo = niceName(fieldDecl); + if (bPotentiallyWrittenTo) + { + writeToSet.insert(fieldInfo); + } +} + +// return true if this not a collection type, or if it is a collection type, and we might be writing to it +bool UnusedFields::checkForWriteWhenUsingCollectionType(const CXXMethodDecl * calleeMethodDecl) +{ + auto const tc = loplugin::TypeCheck(calleeMethodDecl->getParent()); + bool listLike = false, setLike = false, mapLike = false, cssSequence = false; + if (tc.Class("deque").StdNamespace() + || tc.Class("list").StdNamespace() + || tc.Class("queue").StdNamespace() + || tc.Class("vector").StdNamespace()) + { + listLike = true; + } + else if (tc.Class("set").StdNamespace() + || tc.Class("unordered_set").StdNamespace()) + { + setLike = true; + } + else if (tc.Class("map").StdNamespace() + || tc.Class("unordered_map").StdNamespace()) + { + mapLike = true; + } + else if (tc.Class("Sequence").Namespace("uno").Namespace("star").Namespace("sun").Namespace("com").GlobalNamespace()) + { + cssSequence = true; + } + else + return true; + + if (calleeMethodDecl->isOverloadedOperator()) + { + auto oo = calleeMethodDecl->getOverloadedOperator(); + if (oo == OO_Equal) + return true; + // This is operator[]. We only care about things that add elements to the collection. + // if nothing modifies the size of the collection, then nothing useful + // is stored in it. + if (listLike) + return false; + return true; + } + + auto name = calleeMethodDecl->getName(); + if (listLike || setLike || mapLike) + { + if (name == "reserve" || name == "shrink_to_fit" || name == "clear" + || name == "erase" || name == "pop_back" || name == "pop_front" + || name == "front" || name == "back" || name == "data" + || name == "remove" || name == "remove_if" + || name == "unique" || name == "sort" + || name == "begin" || name == "end" + || name == "rbegin" || name == "rend" + || name == "at" || name == "find" || name == "equal_range" + || name == "lower_bound" || name == "upper_bound") + return false; + } + if (cssSequence) + { + if (name == "getArray" || name == "begin" || name == "end") + return false; + } + + return true; +} + +bool UnusedFields::IsPassedByNonConst(const FieldDecl* fieldDecl, const Stmt * child, CallerWrapper callExpr, + CalleeWrapper calleeFunctionDecl) +{ + unsigned len = std::min(callExpr.getNumArgs(), + calleeFunctionDecl.getNumParams()); + // if it's an array, passing it by value to a method typically means the + // callee takes a pointer and can modify the array + if (fieldDecl->getType()->isConstantArrayType()) + { + for (unsigned i = 0; i < len; ++i) + if (callExpr.getArg(i) == child) + if (loplugin::TypeCheck(calleeFunctionDecl.getParamType(i)).Pointer().NonConst()) + return true; + } + else + { + for (unsigned i = 0; i < len; ++i) + if (callExpr.getArg(i) == child) + if (loplugin::TypeCheck(calleeFunctionDecl.getParamType(i)).LvalueReference().NonConst()) + return true; + } + return false; +} + +// fields that are assigned via member initialisers do not get visited in VisitDeclRef, so +// have to do it here +bool UnusedFields::VisitCXXConstructorDecl( const CXXConstructorDecl* cxxConstructorDecl ) +{ + if (ignoreLocation( cxxConstructorDecl->getBeginLoc() )) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(cxxConstructorDecl->getLocation()))) { + return true; + } + + // templates make EvaluateAsInt crash inside clang + if (cxxConstructorDecl->isDependentContext()) + return true; + + // we don't care about writes to a field when inside the copy/move constructor/operator= for that field + if (insideMoveOrCopyOrCloneDeclParent && cxxConstructorDecl->getParent() == insideMoveOrCopyOrCloneDeclParent) + return true; + + for(auto it = cxxConstructorDecl->init_begin(); it != cxxConstructorDecl->init_end(); ++it) + { + const CXXCtorInitializer* init = *it; + const FieldDecl* fieldDecl = init->getMember(); + if (fieldDecl && init->getInit() && !isSomeKindOfZero(init->getInit())) + { + MyFieldInfo fieldInfo = niceName(fieldDecl); + writeToSet.insert(fieldInfo); + } + } + return true; +} + +// Fields that are assigned via init-list-expr do not get visited in VisitDeclRef, so +// have to do it here. +bool UnusedFields::VisitInitListExpr( const InitListExpr* initListExpr) +{ + if (ignoreLocation( initListExpr->getBeginLoc() )) + return true; + + QualType varType = initListExpr->getType().getDesugaredType(compiler.getASTContext()); + auto recordType = varType->getAs(); + if (!recordType) + return true; + + auto recordDecl = recordType->getDecl(); + for (auto it = recordDecl->field_begin(); it != recordDecl->field_end(); ++it) + { + MyFieldInfo fieldInfo = niceName(*it); + writeToSet.insert(fieldInfo); + } + + return true; +} + +bool UnusedFields::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) +{ + const Decl* decl = declRefExpr->getDecl(); + const FieldDecl* fieldDecl = dyn_cast(decl); + if (!fieldDecl) { + return true; + } + fieldDecl = fieldDecl->getCanonicalDecl(); + if (ignoreLocation(fieldDecl->getBeginLoc())) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocation()))) { + return true; + } + checkTouchedFromOutside(fieldDecl, declRefExpr); + return true; +} + +void UnusedFields::checkTouchedFromOutside(const FieldDecl* fieldDecl, const Expr* memberExpr) { + const FunctionDecl* memberExprParentFunction = getParentFunctionDecl(memberExpr); + const CXXMethodDecl* methodDecl = dyn_cast_or_null(memberExprParentFunction); + + MyFieldInfo fieldInfo = niceName(fieldDecl); + + // it's touched from somewhere outside a class + if (!methodDecl) { + touchedFromOutsideSet.insert(fieldInfo); + return; + } + + auto constructorDecl = dyn_cast(methodDecl); + if (methodDecl->isCopyAssignmentOperator() || methodDecl->isMoveAssignmentOperator()) { + // ignore move/copy operator, it's self->self + } else if (constructorDecl && (constructorDecl->isCopyConstructor() || constructorDecl->isMoveConstructor())) { + // ignore move/copy constructor, it's self->self + } else { + if (memberExprParentFunction->getParent() == fieldDecl->getParent()) { + touchedFromInsideSet.insert(fieldInfo); + if (!constructorDecl) + touchedFromOutsideConstructorSet.insert(fieldInfo); + } else { + if (fieldDecl->getName() == "m_pShell") + { + if (memberExprParentFunction) + memberExprParentFunction->dump(); + memberExpr->dump(); + std::cout << "site2" << std::endl; + } + touchedFromOutsideSet.insert(fieldInfo); + } + } +} + +llvm::Optional UnusedFields::getCallee(CallExpr const * callExpr) +{ + FunctionDecl const * functionDecl = callExpr->getDirectCallee(); + if (functionDecl) + return CalleeWrapper(functionDecl); + + // Extract the functionprototype from a type + clang::Type const * calleeType = callExpr->getCallee()->getType().getTypePtr(); + if (auto pointerType = calleeType->getUnqualifiedDesugaredType()->getAs()) { + if (auto prototype = pointerType->getPointeeType()->getUnqualifiedDesugaredType()->getAs()) { + return CalleeWrapper(prototype); + } + } + + return llvm::Optional(); +} + +loplugin::Plugin::Registration< UnusedFields > X("unusedfields", false); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unusedfields.only-used-in-constructor.results b/compilerplugins/clang/unusedfields.only-used-in-constructor.results new file mode 100644 index 000000000..196a586da --- /dev/null +++ b/compilerplugins/clang/unusedfields.only-used-in-constructor.results @@ -0,0 +1,980 @@ +basegfx/source/polygon/b2dpolygontriangulator.cxx:112 + basegfx::(anonymous namespace)::Triangulator maStartEntries basegfx::(anonymous namespace)::EdgeEntries +basegfx/source/polygon/b2dtrapezoid.cxx:205 + basegfx::trapezoidhelper::(anonymous namespace)::PointBlockAllocator maFirstStackBlock class basegfx::B2DPoint[32] +basegfx/source/polygon/b2dtrapezoid.cxx:256 + basegfx::trapezoidhelper::(anonymous namespace)::TrapezoidSubdivider maPoints std::vector +basic/qa/cppunit/basictest.hxx:27 + MacroSnippet maDll class BasicDLL +basic/qa/cppunit/test_global_array.cxx:25 + (anonymous namespace)::GlobalArrayTest lib class BasicDLL +basic/qa/cppunit/test_global_as_new.cxx:25 + (anonymous namespace)::GlobalAsNewTest lib class BasicDLL +binaryurp/source/unmarshal.hxx:86 + binaryurp::Unmarshal buffer_ com::sun::star::uno::Sequence +binaryurp/source/writer.hxx:136 + binaryurp::Writer state_ struct binaryurp::WriterState +canvas/source/tools/surfaceproxy.hxx:104 + canvas::SurfaceProxy mpPageManager canvas::PageManagerSharedPtr +canvas/source/vcl/impltools.hxx:114 + vclcanvas::tools::LocalGuard aSolarGuard class SolarMutexGuard +chart2/source/controller/accessibility/AccessibleChartShape.hxx:78 + chart::AccessibleChartShape m_aShapeTreeInfo ::accessibility::AccessibleShapeTreeInfo +chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx:71 + chart::ThreeD_SceneIllumination_TabPage m_aModelChangeListener class chart::ModifyListenerCallBack +chart2/source/controller/inc/dlg_View3D.hxx:46 + chart::View3DDialog m_aControllerLocker class chart::ControllerLockHelper +chart2/source/controller/inc/RangeSelectionListener.hxx:65 + chart::RangeSelectionListener m_aControllerLockGuard class chart::ControllerLockGuardUNO +connectivity/source/commontools/RowFunctionParser.cxx:372 + connectivity::(anonymous namespace)::ExpressionGrammar::definition unaryFunction ::boost::spirit::classic::rule +connectivity/source/commontools/RowFunctionParser.cxx:373 + connectivity::(anonymous namespace)::ExpressionGrammar::definition assignment ::boost::spirit::classic::rule +connectivity/source/commontools/RowFunctionParser.cxx:374 + connectivity::(anonymous namespace)::ExpressionGrammar::definition argument ::boost::spirit::classic::rule +connectivity/source/commontools/RowFunctionParser.cxx:374 + connectivity::(anonymous namespace)::ExpressionGrammar::definition integer ::boost::spirit::classic::rule +connectivity/source/commontools/RowFunctionParser.cxx:375 + connectivity::(anonymous namespace)::ExpressionGrammar::definition andExpression ::boost::spirit::classic::rule +connectivity/source/commontools/RowFunctionParser.cxx:375 + connectivity::(anonymous namespace)::ExpressionGrammar::definition orExpression ::boost::spirit::classic::rule +connectivity/source/drivers/evoab2/EApi.h:121 + (anonymous) address_format char * +connectivity/source/drivers/evoab2/EApi.h:125 + (anonymous) ext char * +connectivity/source/drivers/firebird/Driver.hxx:48 + connectivity::firebird::FirebirdDriver m_firebirdTMPDirectory ::utl::TempFile +connectivity/source/drivers/firebird/Driver.hxx:49 + connectivity::firebird::FirebirdDriver m_firebirdLockDirectory ::utl::TempFile +connectivity/source/drivers/postgresql/pq_statics.hxx:104 + pq_sdbc_driver::ImplementationStatics types css::uno::Sequence +connectivity/source/inc/component/CResultSet.hxx:41 + connectivity::component::OComponentResultSet m_bBookmarkable _Bool +connectivity/source/inc/dbase/DResultSet.hxx:40 + connectivity::dbase::ODbaseResultSet m_bBookmarkable _Bool +connectivity/source/inc/file/FStatement.hxx:84 + connectivity::file::OStatement_Base m_aCursorName rtl::OUString +connectivity/source/inc/file/FStatement.hxx:85 + connectivity::file::OStatement_Base m_nMaxFieldSize sal_Int32 +connectivity/source/inc/file/FStatement.hxx:86 + connectivity::file::OStatement_Base m_nMaxRows sal_Int32 +connectivity/source/inc/file/FStatement.hxx:87 + connectivity::file::OStatement_Base m_nQueryTimeOut sal_Int32 +connectivity/source/inc/file/FStatement.hxx:88 + connectivity::file::OStatement_Base m_nFetchSize sal_Int32 +connectivity/source/inc/file/FStatement.hxx:89 + connectivity::file::OStatement_Base m_nResultSetType sal_Int32 +connectivity/source/inc/file/FStatement.hxx:90 + connectivity::file::OStatement_Base m_nFetchDirection sal_Int32 +connectivity/source/inc/file/FStatement.hxx:91 + connectivity::file::OStatement_Base m_nResultSetConcurrency sal_Int32 +connectivity/source/inc/file/FStatement.hxx:92 + connectivity::file::OStatement_Base m_bEscapeProcessing _Bool +connectivity/source/inc/flat/EResultSet.hxx:39 + connectivity::flat::OFlatResultSet m_bBookmarkable _Bool +connectivity/source/inc/java/lang/Object.hxx:37 + connectivity::SDBThreadAttach m_aGuard jvmaccess::class VirtualMachine::AttachGuard +cppcanvas/source/mtfrenderer/textaction.cxx:806 + cppcanvas::internal::(anonymous namespace)::EffectTextAction maTextLineInfo const tools::TextLineInfo +cppcanvas/source/mtfrenderer/textaction.cxx:1627 + cppcanvas::internal::(anonymous namespace)::OutlineAction maTextLineInfo const tools::TextLineInfo +cppu/source/threadpool/threadpool.cxx:352 + _uno_ThreadPool dummy sal_Int32 +cppu/source/typelib/typelib.cxx:56 + (anonymous namespace)::AlignSize_Impl nInt16 sal_Int16 +cppu/source/uno/check.cxx:38 + (anonymous namespace)::C1 n1 sal_Int16 +cppu/source/uno/check.cxx:67 + (anonymous namespace)::D d sal_Int16 +cppu/source/uno/check.cxx:68 + (anonymous namespace)::D e sal_Int32 +cppu/source/uno/check.cxx:72 + (anonymous namespace)::E a sal_Bool +cppu/source/uno/check.cxx:73 + (anonymous namespace)::E b sal_Bool +cppu/source/uno/check.cxx:74 + (anonymous namespace)::E c sal_Bool +cppu/source/uno/check.cxx:75 + (anonymous namespace)::E d sal_Int16 +cppu/source/uno/check.cxx:76 + (anonymous namespace)::E e sal_Int32 +cppu/source/uno/check.cxx:81 + (anonymous namespace)::M n sal_Int32 +cppu/source/uno/check.cxx:82 + (anonymous namespace)::M o sal_Int16 +cppu/source/uno/check.cxx:91 + (anonymous namespace)::N2 m struct (anonymous namespace)::M +cppu/source/uno/check.cxx:92 + (anonymous namespace)::N2 p sal_Int16 +cppu/source/uno/check.cxx:97 + (anonymous namespace)::O p double +cppu/source/uno/check.cxx:98 + (anonymous namespace)::O q sal_Int16 +cppu/source/uno/check.cxx:107 + (anonymous namespace)::P p2 double +cppu/source/uno/check.cxx:115 + (anonymous namespace)::second a int +cppu/source/uno/check.cxx:126 + (anonymous namespace)::Char1 c1 char +cppu/source/uno/check.cxx:130 + (anonymous namespace)::Char2 c2 char +cppu/source/uno/check.cxx:134 + (anonymous namespace)::Char3 c3 char +cppu/source/uno/check.cxx:258 + (anonymous namespace)::Char4 chars struct (anonymous namespace)::Char3 +cui/source/dialogs/colorpicker.cxx:740 + cui::(anonymous namespace)::ColorPickerDialog m_aColorPrevious class cui::(anonymous namespace)::ColorPreviewControl +cui/source/factory/dlgfact.cxx:1226 + (anonymous namespace)::SvxMacroAssignDialog_Impl m_aItems class SfxItemSet +cui/source/inc/AdditionsDialog.hxx:47 + AdditionInfo sReleaseVersion rtl::OUString +cui/source/inc/AdditionsDialog.hxx:84 + AdditionsDialog m_sTag rtl::OUString +cui/source/inc/cfgutil.hxx:241 + SvxScriptSelectorDialog m_aStylesInfo struct SfxStylesInfo_Impl +cui/source/inc/cuitabarea.hxx:223 + SvxAreaTabPage maFixed_ChangeType enum ChangeType +cui/source/inc/cuitabarea.hxx:231 + SvxAreaTabPage m_aXFillAttr class XFillAttrSetItem +cui/source/inc/tabstpge.hxx:84 + SvxTabulatorTabPage m_aLeftWin class TabWin_Impl +cui/source/inc/tabstpge.hxx:85 + SvxTabulatorTabPage m_aRightWin class TabWin_Impl +cui/source/inc/tabstpge.hxx:86 + SvxTabulatorTabPage m_aCenterWin class TabWin_Impl +cui/source/inc/tabstpge.hxx:87 + SvxTabulatorTabPage m_aDezWin class TabWin_Impl +cui/source/options/optcolor.cxx:240 + (anonymous namespace)::ColorConfigWindow_Impl::Entry m_aDefaultColor class Color +dbaccess/source/core/api/RowSet.hxx:108 + dbaccess::ORowSet m_aURL rtl::OUString +dbaccess/source/core/api/RowSet.hxx:123 + dbaccess::ORowSet m_nMaxFieldSize sal_Int32 +dbaccess/source/core/api/RowSet.hxx:125 + dbaccess::ORowSet m_nQueryTimeOut sal_Int32 +dbaccess/source/core/api/RowSet.hxx:127 + dbaccess::ORowSet m_nTransactionIsolation sal_Int32 +dbaccess/source/core/api/RowSet.hxx:139 + dbaccess::ORowSet m_bIsBookmarkable _Bool +dbaccess/source/core/api/RowSet.hxx:141 + dbaccess::ORowSet m_bCanUpdateInsertedRows _Bool +dbaccess/source/core/api/RowSet.hxx:457 + dbaccess::ORowSetClone m_nFetchDirection sal_Int32 +dbaccess/source/core/api/RowSet.hxx:458 + dbaccess::ORowSetClone m_nFetchSize sal_Int32 +dbaccess/source/core/api/RowSet.hxx:459 + dbaccess::ORowSetClone m_bIsBookmarkable _Bool +dbaccess/source/core/dataaccess/connection.hxx:101 + dbaccess::OConnection m_nInAppend std::atomic +dbaccess/source/core/inc/databasecontext.hxx:84 + dbaccess::ODatabaseContext m_aBasicDLL class BasicDLL +drawinglayer/inc/texture/texture3d.hxx:54 + drawinglayer::texture::GeoTexSvxBitmapEx maBitmapEx class BitmapEx +drawinglayer/inc/texture/texture3d.hxx:55 + drawinglayer::texture::GeoTexSvxBitmapEx maBitmap class Bitmap +drawinglayer/inc/texture/texture3d.hxx:57 + drawinglayer::texture::GeoTexSvxBitmapEx maTransparence class Bitmap +drawinglayer/source/tools/emfphelperdata.hxx:197 + emfplushelper::EmfPlusHelperData mnFrameRight sal_Int32 +drawinglayer/source/tools/emfphelperdata.hxx:198 + emfplushelper::EmfPlusHelperData mnFrameBottom sal_Int32 +editeng/source/editeng/impedit.hxx:527 + ImpEditEngine aSelFuncSet class EditSelFunctionSet +embeddedobj/source/msole/olecomponent.hxx:51 + OleComponent m_pInterfaceContainer comphelper::OMultiTypeInterfaceContainerHelper2 * +embeddedobj/source/msole/olecomponent.hxx:53 + OleComponent m_bDisposed _Bool +embeddedobj/source/msole/olecomponent.hxx:54 + OleComponent m_bModified _Bool +embeddedobj/source/msole/olecomponent.hxx:55 + OleComponent m_pNativeImpl struct OleComponentNative_Impl * +embeddedobj/source/msole/olecomponent.hxx:57 + OleComponent m_pUnoOleObject class OleEmbeddedObject * +embeddedobj/source/msole/olecomponent.hxx:58 + OleComponent m_pOleWrapClientSite class OleWrapperClientSite * +embeddedobj/source/msole/olecomponent.hxx:59 + OleComponent m_pImplAdviseSink class OleWrapperAdviseSink * +embeddedobj/source/msole/olecomponent.hxx:61 + OleComponent m_nOLEMiscFlags sal_Int32 +embeddedobj/source/msole/olecomponent.hxx:62 + OleComponent m_nAdvConn sal_Int32 +embeddedobj/source/msole/olecomponent.hxx:64 + OleComponent m_aVerbList css::uno::Sequence +embeddedobj/source/msole/olecomponent.hxx:65 + OleComponent m_aDataFlavors css::uno::Sequence +embeddedobj/source/msole/olecomponent.hxx:69 + OleComponent m_bOleInitialized _Bool +extensions/source/bibliography/datman.cxx:410 + (anonymous namespace)::DBChangeDialog_Impl aConfig class DBChangeDialogConfig_Impl +filter/source/graphicfilter/icgm/chart.hxx:48 + DataNode nBoxX1 sal_Int16 +filter/source/graphicfilter/icgm/chart.hxx:49 + DataNode nBoxY1 sal_Int16 +filter/source/graphicfilter/icgm/chart.hxx:50 + DataNode nBoxX2 sal_Int16 +filter/source/graphicfilter/icgm/chart.hxx:51 + DataNode nBoxY2 sal_Int16 +helpcompiler/inc/HelpCompiler.hxx:201 + HelpCompiler lang const std::string +include/basic/basmgr.hxx:57 + BasicError nReason enum BasicErrorReason +include/drawinglayer/primitive2d/textlayoutdevice.hxx:64 + drawinglayer::primitive2d::TextLayouterDevice maSolarGuard class SolarMutexGuard +include/filter/msfilter/svdfppt.hxx:889 + ImplPPTParaPropSet nDontKnow1 sal_uInt32 +include/filter/msfilter/svdfppt.hxx:890 + ImplPPTParaPropSet nDontKnow2 sal_uInt32 +include/filter/msfilter/svdfppt.hxx:891 + ImplPPTParaPropSet nDontKnow2bit06 sal_uInt16 +include/LibreOfficeKit/LibreOfficeKitGtk.h:33 + _LOKDocView aDrawingArea GtkDrawingArea +include/LibreOfficeKit/LibreOfficeKitGtk.h:38 + _LOKDocViewClass parent_class GtkDrawingAreaClass +include/oox/export/shapes.hxx:104 + oox::drawingml::ShapeExport maShapeMap oox::drawingml::ShapeExport::ShapeHashMap +include/registry/registry.hxx:34 + Registry_Api acquire void (*)(RegHandle) +include/sfx2/classificationhelper.hxx:134 + sfx::ClassificationKeyCreator m_ePolicyType const enum SfxClassificationPolicyType +include/sfx2/msg.hxx:117 + SfxType0 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:119 + SfxType0 nAttribs sal_uInt16 +include/sfx2/msg.hxx:132 + SfxType1 aAttrib struct SfxTypeAttrib[1] +include/sfx2/msg.hxx:132 + SfxType1 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:132 + SfxType1 nAttribs sal_uInt16 +include/sfx2/msg.hxx:132 + SfxType1 pType const std::type_info * +include/sfx2/msg.hxx:133 + SfxType2 aAttrib struct SfxTypeAttrib[2] +include/sfx2/msg.hxx:133 + SfxType2 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:133 + SfxType2 nAttribs sal_uInt16 +include/sfx2/msg.hxx:133 + SfxType2 pType const std::type_info * +include/sfx2/msg.hxx:134 + SfxType3 aAttrib struct SfxTypeAttrib[3] +include/sfx2/msg.hxx:134 + SfxType3 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:134 + SfxType3 nAttribs sal_uInt16 +include/sfx2/msg.hxx:134 + SfxType3 pType const std::type_info * +include/sfx2/msg.hxx:135 + SfxType4 aAttrib struct SfxTypeAttrib[4] +include/sfx2/msg.hxx:135 + SfxType4 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:135 + SfxType4 nAttribs sal_uInt16 +include/sfx2/msg.hxx:135 + SfxType4 pType const std::type_info * +include/sfx2/msg.hxx:136 + SfxType5 aAttrib struct SfxTypeAttrib[5] +include/sfx2/msg.hxx:136 + SfxType5 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:136 + SfxType5 nAttribs sal_uInt16 +include/sfx2/msg.hxx:136 + SfxType5 pType const std::type_info * +include/sfx2/msg.hxx:137 + SfxType6 aAttrib struct SfxTypeAttrib[6] +include/sfx2/msg.hxx:137 + SfxType6 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:137 + SfxType6 nAttribs sal_uInt16 +include/sfx2/msg.hxx:137 + SfxType6 pType const std::type_info * +include/sfx2/msg.hxx:138 + SfxType7 aAttrib struct SfxTypeAttrib[7] +include/sfx2/msg.hxx:138 + SfxType7 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:138 + SfxType7 nAttribs sal_uInt16 +include/sfx2/msg.hxx:138 + SfxType7 pType const std::type_info * +include/sfx2/msg.hxx:139 + SfxType8 aAttrib struct SfxTypeAttrib[8] +include/sfx2/msg.hxx:139 + SfxType8 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:139 + SfxType8 nAttribs sal_uInt16 +include/sfx2/msg.hxx:139 + SfxType8 pType const std::type_info * +include/sfx2/msg.hxx:140 + SfxType10 aAttrib struct SfxTypeAttrib[10] +include/sfx2/msg.hxx:140 + SfxType10 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:140 + SfxType10 nAttribs sal_uInt16 +include/sfx2/msg.hxx:140 + SfxType10 pType const std::type_info * +include/sfx2/msg.hxx:141 + SfxType11 aAttrib struct SfxTypeAttrib[11] +include/sfx2/msg.hxx:141 + SfxType11 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:141 + SfxType11 nAttribs sal_uInt16 +include/sfx2/msg.hxx:141 + SfxType11 pType const std::type_info * +include/sfx2/msg.hxx:143 + SfxType13 aAttrib struct SfxTypeAttrib[13] +include/sfx2/msg.hxx:143 + SfxType13 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:143 + SfxType13 nAttribs sal_uInt16 +include/sfx2/msg.hxx:143 + SfxType13 pType const std::type_info * +include/sfx2/msg.hxx:144 + SfxType14 aAttrib struct SfxTypeAttrib[14] +include/sfx2/msg.hxx:144 + SfxType14 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:144 + SfxType14 nAttribs sal_uInt16 +include/sfx2/msg.hxx:144 + SfxType14 pType const std::type_info * +include/sfx2/msg.hxx:145 + SfxType16 aAttrib struct SfxTypeAttrib[16] +include/sfx2/msg.hxx:145 + SfxType16 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:145 + SfxType16 nAttribs sal_uInt16 +include/sfx2/msg.hxx:145 + SfxType16 pType const std::type_info * +include/sfx2/msg.hxx:146 + SfxType17 aAttrib struct SfxTypeAttrib[17] +include/sfx2/msg.hxx:146 + SfxType17 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:146 + SfxType17 nAttribs sal_uInt16 +include/sfx2/msg.hxx:146 + SfxType17 pType const std::type_info * +include/sfx2/msg.hxx:147 + SfxType23 aAttrib struct SfxTypeAttrib[23] +include/sfx2/msg.hxx:147 + SfxType23 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:147 + SfxType23 nAttribs sal_uInt16 +include/sfx2/msg.hxx:147 + SfxType23 pType const std::type_info * +include/svl/itemset.hxx:274 + SfxItemSetFixed m_aItems const class SfxPoolItem *[NITEMS] +include/svx/ClassificationDialog.hxx:35 + svx::ClassificationDialog maInternationalHelper class SfxClassificationHelper +include/svx/ClassificationDialog.hxx:37 + svx::ClassificationDialog m_bPerParagraph const _Bool +include/svx/imapdlg.hxx:91 + SvxIMapDlg aIMapItem class SvxIMapDlgItem +include/vcl/commandevent.hxx:310 + CommandGestureData mfX const double +include/vcl/commandevent.hxx:311 + CommandGestureData mfY const double +include/vcl/commandevent.hxx:314 + CommandGestureData meOrientation const enum PanningOrientation +include/vcl/pdf/PDFAnnotationMarker.hxx:67 + vcl::pdf::PDFAnnotationMarkerHighlight meTextMarkerType enum vcl::pdf::PDFTextMarkerType +include/xmloff/shapeimport.hxx:57 + SdXML3DLightContext mbSpecular _Bool +libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx:51 + GtvApplicationWindow parent_instance GtkApplicationWindow +libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx:55 + GtvApplicationWindow doctype LibreOfficeKitDocumentType +libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx:74 + GtvApplicationWindowClass parentClass GtkApplicationWindowClass +libreofficekit/qa/gtktiledviewer/gtv-application.hxx:26 + GtvApplication parent GtkApplication +libreofficekit/qa/gtktiledviewer/gtv-application.hxx:31 + GtvApplicationClass parentClass GtkApplicationClass +libreofficekit/qa/gtktiledviewer/gtv-calc-header-bar.hxx:28 + GtvCalcHeaderBar parent GtkDrawingArea +libreofficekit/qa/gtktiledviewer/gtv-calc-header-bar.hxx:37 + GtvCalcHeaderBarClass parentClass GtkDrawingAreaClass +libreofficekit/qa/gtktiledviewer/gtv-comments-sidebar.hxx:26 + GtvCommentsSidebar parent GtkBox +libreofficekit/qa/gtktiledviewer/gtv-comments-sidebar.hxx:35 + GtvCommentsSidebarClass parentClass GtkBoxClass +libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx:28 + GtvLokDialog parent GtkDialog +libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx:33 + GtvLokDialogClass parentClass GtkDialogClass +libreofficekit/qa/gtktiledviewer/gtv-main-toolbar.hxx:28 + GtvMainToolbar parent GtkBox +libreofficekit/qa/gtktiledviewer/gtv-main-toolbar.hxx:36 + GtvMainToolbarClass parentClass GtkBoxClass +lingucomponent/source/languageguessing/simpleguesser.cxx:75 + (anonymous namespace)::textcat_t maxsize uint4 +lingucomponent/source/languageguessing/simpleguesser.cxx:77 + (anonymous namespace)::textcat_t output char[1024] +lotuswordpro/source/filter/bento.hxx:351 + OpenStormBento::CBenNamedObject cNameListElmt class OpenStormBento::CBenNamedObjectListElmt +lotuswordpro/source/filter/clone.hxx:23 + detail::has_clone::(anonymous) a char[2] +oox/source/drawingml/diagram/layoutnodecontext.cxx:93 + oox::drawingml::(anonymous namespace)::AlgorithmContext mnRevision sal_Int32 +oox/source/drawingml/diagram/layoutnodecontext.cxx:135 + oox::drawingml::(anonymous namespace)::ChooseContext msName rtl::OUString +oox/source/ppt/timenodelistcontext.cxx:205 + oox::ppt::(anonymous namespace)::MediaNodeContext mbFullScrn _Bool +oox/source/ppt/timenodelistcontext.cxx:400 + oox::ppt::(anonymous namespace)::SequenceTimeNodeContext mbConcurrent _Bool +oox/source/ppt/timenodelistcontext.cxx:401 + oox::ppt::(anonymous namespace)::SequenceTimeNodeContext mnNextAc sal_Int32 +oox/source/ppt/timenodelistcontext.cxx:401 + oox::ppt::(anonymous namespace)::SequenceTimeNodeContext mnPrevAc sal_Int32 +oox/source/ppt/timenodelistcontext.cxx:639 + oox::ppt::(anonymous namespace)::AnimContext mnValueType sal_Int32 +oox/source/ppt/timenodelistcontext.cxx:721 + oox::ppt::(anonymous namespace)::AnimScaleContext mbZoomContents _Bool +oox/source/ppt/timenodelistcontext.cxx:861 + oox::ppt::(anonymous namespace)::AnimMotionContext msPtsTypes rtl::OUString +oox/source/ppt/timenodelistcontext.cxx:862 + oox::ppt::(anonymous namespace)::AnimMotionContext mnPathEditMode sal_Int32 +oox/source/ppt/timenodelistcontext.cxx:863 + oox::ppt::(anonymous namespace)::AnimMotionContext mnAngle sal_Int32 +pyuno/source/module/pyuno_callable.cxx:45 + pyuno::(anonymous namespace)::PyUNO_callable ob_base PyObject +pyuno/source/module/pyuno_impl.hxx:138 + pyuno::(anonymous) ob_base PyObject +pyuno/source/module/pyuno_impl.hxx:238 + pyuno::stRuntimeImpl ob_base PyObject +reportdesign/source/core/api/ReportDefinition.cxx:239 + reportdesign::(anonymous namespace)::OStyle m_aSize awt::Size +sal/qa/osl/condition/osl_Condition.cxx:72 + osl_Condition::ctors bRes1 _Bool +sal/qa/osl/condition/osl_Condition.cxx:202 + osl_Condition::wait bRes2 _Bool +sal/qa/osl/condition/osl_Condition.cxx:273 + osl_Condition::check bRes2 _Bool +sal/qa/osl/file/osl_File.cxx:1387 + osl_FileStatus::isValid rItem_link class osl::DirectoryItem +sal/qa/osl/file/osl_File.cxx:1564 + osl_FileStatus::getFileType m_aFifoItem class osl::DirectoryItem +sal/qa/osl/file/osl_File.cxx:1564 + osl_FileStatus::getFileType m_aVolumeItem class osl::DirectoryItem +sal/qa/osl/file/osl_File.cxx:1565 + osl_FileStatus::getFileType m_aLinkItem class osl::DirectoryItem +sal/qa/osl/file/osl_File.cxx:1565 + osl_FileStatus::getFileType m_aSocketItem class osl::DirectoryItem +sal/qa/osl/file/osl_File.cxx:1565 + osl_FileStatus::getFileType m_aSpecialItem class osl::DirectoryItem +sal/qa/osl/file/osl_File.cxx:2039 + osl_FileStatus::getLinkTargetURL rItem class osl::DirectoryItem +sal/qa/osl/module/osl_Module.cxx:70 + osl_Module::ctors bRes1 _Bool +sal/qa/osl/module/osl_Module.cxx:114 + osl_Module::getUrlFromAddress bRes1 _Bool +sal/qa/osl/module/osl_Module.cxx:174 + osl_Module::load bRes1 _Bool +sal/qa/osl/module/osl_Module.cxx:201 + osl_Module::unload bRes1 _Bool +sal/qa/osl/module/osl_Module.cxx:342 + osl_Module::getFunctionSymbol bRes1 _Bool +sal/qa/osl/pipe/osl_Pipe.cxx:358 + osl_Pipe::clear bRes1 _Bool +sal/qa/osl/pipe/osl_Pipe.cxx:523 + osl_Pipe::getError bRes _Bool +sal/qa/osl/pipe/osl_Pipe.cxx:523 + osl_Pipe::getError bRes1 _Bool +sal/qa/osl/pipe/osl_Pipe.cxx:561 + osl_Pipe::getHandle bRes1 _Bool +sal/qa/osl/pipe/osl_Pipe.cxx:848 + osl_StreamPipe::recv bRes _Bool +sal/qa/osl/pipe/osl_Pipe.cxx:848 + osl_StreamPipe::recv bRes1 _Bool +sal/qa/osl/process/osl_process.cxx:151 + Test_osl_executeProcess env_param_ const rtl::OUString +sal/qa/osl/security/osl_Security.cxx:59 + osl_Security::ctors bRes _Bool +sal/qa/osl/security/osl_Security.cxx:59 + osl_Security::ctors bRes1 _Bool +sal/qa/osl/security/osl_Security.cxx:124 + osl_Security::getUserIdent bRes1 _Bool +sal/qa/osl/security/osl_Security.cxx:154 + osl_Security::getUserName bRes1 _Bool +sal/qa/osl/security/osl_Security.cxx:188 + osl_Security::getConfigDir bRes1 _Bool +sal/textenc/textenc.cxx:405 + (anonymous namespace)::FullTextEncodingData module_ osl::Module +sc/inc/compiler.hxx:266 + ScCompiler::AddInMap pODFF const char * +sc/inc/compiler.hxx:267 + ScCompiler::AddInMap pEnglish const char * +sc/inc/compiler.hxx:269 + ScCompiler::AddInMap pUpper const char * +sc/inc/editutil.hxx:113 + ScEnginePoolHelper bDeleteEnginePool _Bool +sc/inc/queryevaluator.hxx:61 + ScQueryEvaluator mnEntryCount const SCSIZE +sc/inc/queryevaluator.hxx:65 + ScQueryEvaluator maBool _Bool[32] +sc/inc/queryevaluator.hxx:66 + ScQueryEvaluator maTest _Bool[32] +sc/inc/token.hxx:402 + SingleDoubleRefModifier aDub struct ScComplexRefData +sc/source/core/data/document.cxx:1236 + (anonymous namespace)::BroadcastRecalcOnRefMoveGuard aSwitch sc::AutoCalcSwitch +sc/source/core/data/document.cxx:1237 + (anonymous namespace)::BroadcastRecalcOnRefMoveGuard aBulk class ScBulkBroadcast +sc/source/core/data/table2.cxx:802 + (anonymous namespace)::TransClipHandler mnEndRow size_t +sc/source/filter/inc/htmlpars.hxx:626 + ScHTMLQueryParser mnUnusedId ScHTMLTableId +sc/source/filter/inc/sheetdatacontext.hxx:50 + oox::xls::SheetDataContext aReleaser class SolarMutexReleaser +sc/source/filter/inc/XclImpChangeTrack.hxx:55 + XclImpChangeTrack xInStrm tools::SvRef +sc/source/filter/inc/xetable.hxx:1016 + XclExpCellTable maArrayBfr class XclExpArrayBuffer +sc/source/filter/inc/xetable.hxx:1017 + XclExpCellTable maShrfmlaBfr class XclExpShrfmlaBuffer +sc/source/filter/inc/xiescher.hxx:1205 + XclImpDffPropSet maDummyStrm class SvMemoryStream +sc/source/filter/inc/xihelper.hxx:327 + XclImpCachedValue mxTokArr XclImpCachedValue::ScTokenArrayPtr +sc/source/filter/inc/xistream.hxx:171 + XclImpBiff8StdDecrypter maCodec ::msfilter::MSCodec_Std97 +sc/source/filter/inc/xistream.hxx:193 + XclImpBiff8CryptoAPIDecrypter maCodec ::msfilter::MSCodec_CryptoAPI +sc/source/filter/oox/worksheethelper.cxx:388 + oox::xls::WorksheetGlobals mxProgressBar oox::ISegmentProgressBarRef +sc/source/filter/xml/xmldrani.hxx:71 + ScXMLDatabaseRangeContext bIsSelection _Bool +sc/source/filter/xml/xmlexternaltabi.hxx:110 + ScXMLExternalRefCellContext mnCellType sal_Int16 +sc/source/filter/xml/xmltransformationi.hxx:154 + ScXMLDateTimeContext aType rtl::OUString +sc/source/ui/inc/acredlin.hxx:51 + ScAcceptChgDlg aReOpenIdle class Idle +sc/source/ui/inc/msgpool.hxx:34 + ScMessagePool aGlobalStringItem class SfxStringItem +sc/source/ui/inc/msgpool.hxx:35 + ScMessagePool aGlobalSearchItem class SvxSearchItem +sc/source/ui/inc/msgpool.hxx:36 + ScMessagePool aGlobalSortItem class ScSortItem +sc/source/ui/inc/msgpool.hxx:37 + ScMessagePool aGlobalQueryItem class ScQueryItem +sc/source/ui/inc/msgpool.hxx:38 + ScMessagePool aGlobalSubTotalItem class ScSubTotalItem +sc/source/ui/inc/msgpool.hxx:39 + ScMessagePool aGlobalConsolidateItem class ScConsolidateItem +sc/source/ui/inc/msgpool.hxx:40 + ScMessagePool aGlobalPivotItem class ScPivotItem +sc/source/ui/inc/msgpool.hxx:41 + ScMessagePool aGlobalSolveItem class ScSolveItem +sc/source/ui/inc/msgpool.hxx:42 + ScMessagePool aGlobalUserListItem class ScUserListItem +sc/source/ui/inc/msgpool.hxx:43 + ScMessagePool aCondFormatDlgItem class ScCondFormatDlgItem +sc/source/ui/inc/notemark.hxx:45 + ScNoteMarker m_aTimer class Timer +sc/source/ui/inc/PivotLayoutTreeListBase.hxx:47 + ScPivotLayoutTreeListBase maDropTargetHelper class ScPivotLayoutTreeDropTarget +sc/source/ui/inc/xmlsourcedlg.hxx:60 + ScXMLSourceDlg maCustomCompare struct CustomCompare +sccomp/source/solver/DifferentialEvolution.hxx:34 + DifferentialEvolutionAlgorithm maRandomDevice std::random_device +sccomp/source/solver/ParticelSwarmOptimization.hxx:55 + ParticleSwarmOptimizationAlgorithm maRandomDevice std::random_device +scripting/source/stringresource/stringresource.cxx:1254 + stringresource::(anonymous namespace)::BinaryInput m_aData Sequence +sd/inc/anminfo.hxx:51 + SdAnimationInfo maSecondSoundFile rtl::OUString +sd/source/filter/eppt/epptbase.hxx:347 + PPTWriterBase maFraction class Fraction +sd/source/filter/ppt/pptin.hxx:81 + SdPPTImport maParam struct PowerPointImportParam +sd/source/ui/inc/AccessibleDocumentViewBase.hxx:258 + accessibility::AccessibleDocumentViewBase maViewForwarder class accessibility::AccessibleViewForwarder +sd/source/ui/inc/CustomAnimationList.hxx:127 + sd::CustomAnimationList maDropTargetHelper class sd::CustomAnimationListDropTarget +sd/source/ui/inc/OutlineBulletDlg.hxx:43 + sd::OutlineBulletDlg m_aInputSet class SfxItemSet +sd/source/ui/remotecontrol/Receiver.hxx:34 + sd::Receiver pTransmitter class sd::Transmitter * +sd/source/ui/remotecontrol/ZeroconfService.hxx:32 + sd::ZeroconfService port uint +sd/source/ui/view/DocumentRenderer.cxx:1317 + sd::DocumentRenderer::Implementation mxObjectShell SfxObjectShellRef +sd/source/ui/view/viewshel.cxx:1157 + sd::(anonymous namespace)::KeepSlideSorterInSyncWithPageChanges m_aDrawLock sd::slidesorter::view::class SlideSorterView::DrawLock +sd/source/ui/view/viewshel.cxx:1158 + sd::(anonymous namespace)::KeepSlideSorterInSyncWithPageChanges m_aModelLock sd::slidesorter::controller::class SlideSorterController::ModelChangeLock +sd/source/ui/view/viewshel.cxx:1159 + sd::(anonymous namespace)::KeepSlideSorterInSyncWithPageChanges m_aUpdateLock sd::slidesorter::controller::class PageSelector::UpdateLock +sd/source/ui/view/viewshel.cxx:1160 + sd::(anonymous namespace)::KeepSlideSorterInSyncWithPageChanges m_aContext sd::slidesorter::controller::class SelectionObserver::Context +sdext/source/pdfimport/pdfparse/pdfparse.cxx:265 + (anonymous namespace)::PDFGrammar::definition boolean rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:265 + (anonymous namespace)::PDFGrammar::definition comment rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:265 + (anonymous namespace)::PDFGrammar::definition name rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:265 + (anonymous namespace)::PDFGrammar::definition null_object rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:265 + (anonymous namespace)::PDFGrammar::definition simple_type rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:265 + (anonymous namespace)::PDFGrammar::definition stream rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:265 + (anonymous namespace)::PDFGrammar::definition stringtype rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:266 + (anonymous namespace)::PDFGrammar::definition array rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:266 + (anonymous namespace)::PDFGrammar::definition dict_begin rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:266 + (anonymous namespace)::PDFGrammar::definition dict_element rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:266 + (anonymous namespace)::PDFGrammar::definition dict_end rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:266 + (anonymous namespace)::PDFGrammar::definition objectref rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:266 + (anonymous namespace)::PDFGrammar::definition value rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:267 + (anonymous namespace)::PDFGrammar::definition array_begin rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:267 + (anonymous namespace)::PDFGrammar::definition array_end rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:267 + (anonymous namespace)::PDFGrammar::definition object rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:267 + (anonymous namespace)::PDFGrammar::definition object_begin rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:267 + (anonymous namespace)::PDFGrammar::definition object_end rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:268 + (anonymous namespace)::PDFGrammar::definition trailer rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:268 + (anonymous namespace)::PDFGrammar::definition xref rule +sfx2/inc/autoredactdialog.hxx:99 + SfxAutoRedactDialog m_xDocShell class SfxObjectShellLock +sfx2/source/dialog/basedlgs.cxx:46 + SfxModelessDialog_Impl aMoveIdle class Idle +sfx2/source/doc/doctempl.cxx:105 + DocTempl::(anonymous namespace)::DocTempl_EntryData_Impl mxObjShell class SfxObjectShellLock +sfx2/source/inc/templdgi.hxx:93 + SfxCommonTemplateDialog_Impl m_aStyleListUpdateFamily Link +slideshow/source/engine/animationnodes/animationbasenode.hxx:88 + slideshow::internal::AnimationBaseNode mpSubsetManager slideshow::internal::SubsettableShapeManagerSharedPtr +slideshow/source/engine/opengl/TransitionImpl.cxx:1991 + (anonymous namespace)::ThreeFloats x GLfloat +slideshow/source/engine/opengl/TransitionImpl.cxx:1991 + (anonymous namespace)::ThreeFloats y GLfloat +slideshow/source/engine/opengl/TransitionImpl.cxx:1991 + (anonymous namespace)::ThreeFloats z GLfloat +slideshow/source/engine/opengl/TransitionImpl.hxx:297 + Vertex normal glm::vec3 +slideshow/source/engine/opengl/TransitionImpl.hxx:298 + Vertex texcoord glm::vec2 +slideshow/source/engine/slide/slideimpl.cxx:199 + slideshow::internal::(anonymous namespace)::SlideImpl mpBox2DWorld box2d::utils::Box2DWorldSharedPtr +slideshow/source/engine/smilfunctionparser.cxx:493 + slideshow::internal::(anonymous namespace)::ExpressionGrammar::definition multiplicativeExpression ::boost::spirit::classic::rule +slideshow/source/engine/smilfunctionparser.cxx:494 + slideshow::internal::(anonymous namespace)::ExpressionGrammar::definition unaryExpression ::boost::spirit::classic::rule +slideshow/source/engine/smilfunctionparser.cxx:495 + slideshow::internal::(anonymous namespace)::ExpressionGrammar::definition basicExpression ::boost::spirit::classic::rule +slideshow/source/engine/smilfunctionparser.cxx:496 + slideshow::internal::(anonymous namespace)::ExpressionGrammar::definition unaryFunction ::boost::spirit::classic::rule +slideshow/source/engine/smilfunctionparser.cxx:497 + slideshow::internal::(anonymous namespace)::ExpressionGrammar::definition binaryFunction ::boost::spirit::classic::rule +slideshow/source/engine/smilfunctionparser.cxx:498 + slideshow::internal::(anonymous namespace)::ExpressionGrammar::definition identifier ::boost::spirit::classic::rule +starmath/inc/mathml/mathmlMo.hxx:63 + moOperatorData m_motxt rtl::OUString +starmath/inc/mathml/mathmlMo.hxx:64 + moOperatorData m_form enum moOpDF +starmath/inc/mathml/mathmlMo.hxx:65 + moOperatorData m_priority sal_uInt16 +starmath/inc/mathml/mathmlMo.hxx:66 + moOperatorData m_lspace sal_uInt16 +starmath/inc/mathml/mathmlMo.hxx:67 + moOperatorData m_rspace sal_uInt16 +starmath/inc/mathml/mathmlMo.hxx:68 + moOperatorData m_properties enum moOpDP +starmath/inc/view.hxx:246 + SmViewShell maGraphicController class SmGraphicController +svgio/inc/svgcharacternode.hxx:84 + svgio::svgreader::SvgTextPosition maY ::std::vector +svl/source/crypto/cryptosign.cxx:108 + (anonymous namespace)::Extension extnID SECItem +svl/source/crypto/cryptosign.cxx:109 + (anonymous namespace)::Extension critical SECItem +svl/source/crypto/cryptosign.cxx:110 + (anonymous namespace)::Extension extnValue SECItem +svl/source/crypto/cryptosign.cxx:268 + (anonymous namespace)::PKIStatusInfo statusString SECItem +svl/source/crypto/cryptosign.cxx:269 + (anonymous namespace)::PKIStatusInfo failInfo SECItem +svx/inc/GalleryControl.hxx:43 + svx::sidebar::GalleryControl mpGallery class Gallery * +svx/source/customshapes/EnhancedCustomShapeFunctionParser.cxx:1087 + (anonymous namespace)::ExpressionGrammar::definition multiplicativeExpression ::boost::spirit::classic::rule +svx/source/customshapes/EnhancedCustomShapeFunctionParser.cxx:1088 + (anonymous namespace)::ExpressionGrammar::definition unaryExpression ::boost::spirit::classic::rule +svx/source/customshapes/EnhancedCustomShapeFunctionParser.cxx:1089 + (anonymous namespace)::ExpressionGrammar::definition basicExpression ::boost::spirit::classic::rule +svx/source/customshapes/EnhancedCustomShapeFunctionParser.cxx:1090 + (anonymous namespace)::ExpressionGrammar::definition unaryFunction ::boost::spirit::classic::rule +svx/source/customshapes/EnhancedCustomShapeFunctionParser.cxx:1091 + (anonymous namespace)::ExpressionGrammar::definition binaryFunction ::boost::spirit::classic::rule +svx/source/customshapes/EnhancedCustomShapeFunctionParser.cxx:1092 + (anonymous namespace)::ExpressionGrammar::definition ternaryFunction ::boost::spirit::classic::rule +svx/source/customshapes/EnhancedCustomShapeFunctionParser.cxx:1093 + (anonymous namespace)::ExpressionGrammar::definition funcRef_decl ::boost::spirit::classic::rule +svx/source/customshapes/EnhancedCustomShapeFunctionParser.cxx:1094 + (anonymous namespace)::ExpressionGrammar::definition functionReference ::boost::spirit::classic::rule +svx/source/customshapes/EnhancedCustomShapeFunctionParser.cxx:1095 + (anonymous namespace)::ExpressionGrammar::definition modRef_decl ::boost::spirit::classic::rule +svx/source/customshapes/EnhancedCustomShapeFunctionParser.cxx:1096 + (anonymous namespace)::ExpressionGrammar::definition modifierReference ::boost::spirit::classic::rule +svx/source/customshapes/EnhancedCustomShapeFunctionParser.cxx:1097 + (anonymous namespace)::ExpressionGrammar::definition identifier ::boost::spirit::classic::rule +svx/source/dialog/contimp.hxx:75 + SvxSuperContourDlg aContourItem class SvxContourDlgItem +svx/source/dialog/framelinkarray.cxx:455 + svx::frame::(anonymous namespace)::MergedCellIterator mnFirstRow sal_Int32 +svx/source/dialog/imapwnd.hxx:87 + IMapWindow maItemInfos struct SfxItemInfo[1] +svx/source/dialog/weldeditview.cxx:458 + (anonymous namespace)::WeldEditSource m_rEditAcc class WeldEditAccessible & +svx/source/inc/datanavi.hxx:190 + svxform::XFormsPage m_aDropHelper class svxform::DataTreeDropTarget +svx/source/svdraw/svdcrtv.cxx:48 + ImplConnectMarkerOverlay maObjects sdr::overlay::OverlayObjectList +svx/source/svdraw/svdmrkv.cxx:135 + MarkingSubSelectionOverlay maObjects sdr::overlay::OverlayObjectList +svx/source/tbxctrls/extrusioncontrols.hxx:66 + svx::ExtrusionDirectionWindow maImgDirection class Image[9] +svx/source/xml/xmleohlp.cxx:71 + OutputStorageWrapper_Impl aTempFile class utl::TempFile +svx/source/xml/xmlgrhlp.cxx:93 + (anonymous namespace)::GraphicInputStream maTempFile utl::TempFile +sw/inc/unosett.hxx:146 + SwXNumberingRules m_pImpl ::sw::UnoImplPtr +sw/qa/core/test_ToxTextGenerator.cxx:140 + (anonymous namespace)::ToxTextGeneratorWithMockedChapterField mChapterFieldType class SwChapterFieldType +sw/qa/extras/tiledrendering/tiledrendering.cxx:876 + (anonymous namespace)::ViewCallback m_callbackWrapper class TestLokCallbackWrapper +sw/qa/extras/uiwriter/uiwriter7.cxx:2258 + (anonymous namespace)::IdleTask maIdle class Idle +sw/source/core/crsr/crbm.cxx:62 + (anonymous namespace)::CursorStateHelper m_aSaveState class SwCursorSaveState +sw/source/core/inc/ftnboss.hxx:34 + SwSaveFootnoteHeight aGuard class SwFrameDeleteGuard +sw/source/core/inc/swfont.hxx:980 + SvStatistics nGetStretchTextSize sal_uInt16 +sw/source/core/layout/dbg_lay.cxx:179 + SwImplEnterLeave m_nAction enum DbgAction +sw/source/core/text/inftxt.cxx:533 + (anonymous namespace)::SwTransparentTextGuard m_aContentVDev ScopedVclPtrInstance +sw/source/core/text/inftxt.hxx:675 + SwTextSlot aText rtl::OUString +sw/source/core/text/porfld.cxx:142 + (anonymous namespace)::SwFieldSlot aText rtl::OUString +sw/source/core/text/redlnitr.hxx:78 + SwRedlineItr m_nNdIdx const SwNodeOffset +sw/source/core/unocore/unolinebreak.cxx:43 + SwXLineBreak::Impl m_rThis class SwXLineBreak & +sw/source/uibase/docvw/romenu.hxx:34 + SwReadOnlyPopup m_aBuilder class VclBuilder +sw/source/uibase/docvw/romenu.hxx:46 + SwReadOnlyPopup m_nReadonlyGraphictogallery sal_uInt16 +sw/source/uibase/docvw/romenu.hxx:50 + SwReadOnlyPopup m_nReadonlyBackgroundtogallery sal_uInt16 +sw/source/uibase/inc/condedit.hxx:43 + ConditionEdit m_aDropTargetHelper class ConditionEditDropTarget +sw/source/uibase/inc/conttree.hxx:296 + SwGlobalTree m_aDropTargetHelper class SwGlobalTreeDropTarget +sw/source/uibase/inc/olmenu.hxx:77 + SwSpellPopup m_aBuilder class VclBuilder +sw/source/uibase/inc/swuicnttab.hxx:241 + SwTokenWindow m_aAdjustPositionsIdle class Idle +sw/source/uibase/inc/tmpdlg.hxx:35 + SwTemplateDlgController bNewStyle _Bool +sw/source/uibase/inc/uivwimp.hxx:93 + SwView_Impl m_xTmpSelDocShell class SfxObjectShellLock +sw/source/uibase/inc/unodispatch.hxx:45 + SwXDispatchProviderInterceptor::DispatchMutexLock_Impl aGuard class SolarMutexGuard +toolkit/source/awt/stylesettings.cxx:74 + toolkit::(anonymous namespace)::StyleMethodGuard m_aGuard class SolarMutexGuard +ucb/source/ucp/gio/gio_mount.hxx:73 + OOoMountOperationClass parent_class GMountOperationClass +ucb/source/ucp/gio/gio_mount.hxx:76 + OOoMountOperationClass _gtk_reserved1 void (*)(void) +ucb/source/ucp/gio/gio_mount.hxx:77 + OOoMountOperationClass _gtk_reserved2 void (*)(void) +ucb/source/ucp/gio/gio_mount.hxx:78 + OOoMountOperationClass _gtk_reserved3 void (*)(void) +ucb/source/ucp/gio/gio_mount.hxx:79 + OOoMountOperationClass _gtk_reserved4 void (*)(void) +vcl/inc/graphic/Manager.hxx:41 + vcl::graphic::Manager maSwapOutTimer class Timer +vcl/inc/headless/BitmapHelper.hxx:32 + BitmapHelper aTmpBmp class SvpSalBitmap +vcl/inc/pdf/pdfbuildin_fonts.hxx:34 + vcl::pdf::BuildinFont m_nAscent const int +vcl/inc/pdf/pdfbuildin_fonts.hxx:35 + vcl::pdf::BuildinFont m_nDescent const int +vcl/inc/pdf/pdfbuildin_fonts.hxx:42 + vcl::pdf::BuildinFont m_aWidths const int[256] +vcl/inc/qt5/QtAccessibleWidget.hxx:156 + QtAccessibleWidget m_pObject class QObject * +vcl/inc/qt5/QtClipboard.hxx:39 + QtClipboard m_aClipboardName const rtl::OUString +vcl/inc/qt5/QtClipboard.hxx:40 + QtClipboard m_aClipboardMode const class QClipboard::Mode +vcl/inc/qt5/QtClipboard.hxx:43 + QtClipboard m_bOwnClipboardChange _Bool +vcl/inc/qt5/QtClipboard.hxx:45 + QtClipboard m_bDoClear _Bool +vcl/inc/qt5/QtFilePicker.hxx:70 + QtFilePicker m_aNamedFilterList class QStringList +vcl/inc/qt5/QtFilePicker.hxx:71 + QtFilePicker m_aTitleToFilterMap QHash +vcl/inc/qt5/QtFilePicker.hxx:73 + QtFilePicker m_aNamedFilterToExtensionMap QHash +vcl/inc/qt5/QtFilePicker.hxx:74 + QtFilePicker m_aCurrentFilter class QString +vcl/inc/qt5/QtFilePicker.hxx:77 + QtFilePicker m_aCustomWidgetsMap QHash +vcl/inc/qt5/QtFilePicker.hxx:79 + QtFilePicker m_bIsFolderPicker const _Bool +vcl/inc/qt5/QtFilePicker.hxx:81 + QtFilePicker m_pParentWidget class QWidget * +vcl/inc/qt5/QtFrame.hxx:85 + QtFrame m_bGraphicsInUse _Bool +vcl/inc/qt5/QtFrame.hxx:87 + QtFrame m_pParent class QtFrame * +vcl/inc/qt5/QtFrame.hxx:88 + QtFrame m_ePointerStyle enum PointerStyle +vcl/inc/qt5/QtFrame.hxx:92 + QtFrame m_pDragSource class QtDragSource * +vcl/inc/qt5/QtFrame.hxx:93 + QtFrame m_pDropTarget class QtDropTarget * +vcl/inc/qt5/QtFrame.hxx:94 + QtFrame m_bInDrag _Bool +vcl/inc/qt5/QtFrame.hxx:96 + QtFrame m_bDefaultSize _Bool +vcl/inc/qt5/QtFrame.hxx:97 + QtFrame m_bDefaultPos _Bool +vcl/inc/qt5/QtFrame.hxx:98 + QtFrame m_bFullScreen _Bool +vcl/inc/qt5/QtFrame.hxx:99 + QtFrame m_bFullScreenSpanAll _Bool +vcl/inc/qt5/QtFrame.hxx:100 + QtFrame m_nRestoreScreen sal_uInt32 +vcl/inc/qt5/QtFrame.hxx:101 + QtFrame m_aRestoreGeometry class QRect +vcl/inc/qt5/QtFrame.hxx:104 + QtFrame m_ScreenSaverInhibitor class ScreenSaverInhibitor +vcl/inc/qt5/QtFrame.hxx:110 + QtFrame m_nInputLanguage LanguageType +vcl/inc/qt5/QtInstance.hxx:56 + QtInstance m_aWaitingYieldCond osl::Condition +vcl/inc/qt5/QtInstance.hxx:58 + QtInstance m_pTimer class QtTimer * +vcl/inc/qt5/QtInstance.hxx:59 + QtInstance m_bSleeping _Bool +vcl/inc/qt5/QtInstance.hxx:63 + QtInstance m_pFakeArgvFreeable std::vector +vcl/inc/qt5/QtInstance.hxx:67 + QtInstance m_aUpdateStyleTimer class Timer +vcl/inc/qt5/QtInstance.hxx:68 + QtInstance m_bUpdateFonts _Bool +vcl/inc/qt5/QtMainWindow.hxx:31 + QtMainWindow m_rFrame class QtFrame & +vcl/inc/qt5/QtMenu.hxx:44 + QtMenu mpParentSalMenu class QtMenu * +vcl/inc/qt5/QtMenu.hxx:45 + QtMenu mpFrame class QtFrame * +vcl/inc/qt5/QtMenu.hxx:46 + QtMenu mbMenuBar _Bool +vcl/inc/qt5/QtMenu.hxx:47 + QtMenu mpQMenuBar class QMenuBar * +vcl/inc/qt5/QtMenu.hxx:51 + QtMenu mpQMenu class QMenu * +vcl/inc/qt5/QtMenu.hxx:52 + QtMenu mpCloseButton class QPushButton * +vcl/inc/qt5/QtMenu.hxx:53 + QtMenu maCloseButtonConnection struct QMetaObject::Connection +vcl/inc/qt5/QtMenu.hxx:110 + QtMenuItem mpParentMenu class QtMenu * +vcl/inc/qt5/QtMenu.hxx:111 + QtMenuItem mpSubMenu class QtMenu * +vcl/inc/qt5/QtMenu.hxx:115 + QtMenuItem mnId sal_uInt16 +vcl/inc/qt5/QtMenu.hxx:116 + QtMenuItem mnType enum MenuItemType +vcl/inc/qt5/QtMenu.hxx:117 + QtMenuItem mbVisible _Bool +vcl/inc/qt5/QtMenu.hxx:118 + QtMenuItem mbEnabled _Bool +vcl/inc/qt5/QtMenu.hxx:119 + QtMenuItem maImage class Image +vcl/inc/qt5/QtObject.hxx:40 + QtObject m_pRegion class QRegion +vcl/inc/qt5/QtObject.hxx:67 + QtObjectWindow m_rParent class QtObject & +vcl/inc/qt5/QtWidget.hxx:38 + QtWidget m_bNonEmptyIMPreeditSeen _Bool +vcl/inc/qt5/QtWidget.hxx:39 + QtWidget m_nDeltaX int +vcl/inc/qt5/QtWidget.hxx:40 + QtWidget m_nDeltaY int +vcl/inc/salvtables.hxx:556 + SalInstanceEntry m_aTextFilter class WeldTextFilter +vcl/inc/salvtables.hxx:941 + SalInstanceComboBoxWithEdit m_aTextFilter class WeldTextFilter +vcl/inc/svimpbox.hxx:120 + SvImpLBox m_aFctSet class ImpLBSelEng +vcl/inc/unx/i18n_ic.hxx:40 + SalI18N_InputContext maPreeditStartCallback XIMCallback +vcl/inc/unx/i18n_ic.hxx:41 + SalI18N_InputContext maPreeditDoneCallback XIMCallback +vcl/inc/unx/i18n_ic.hxx:42 + SalI18N_InputContext maPreeditDrawCallback XIMCallback +vcl/inc/unx/i18n_ic.hxx:43 + SalI18N_InputContext maPreeditCaretCallback XIMCallback +vcl/inc/unx/i18n_ic.hxx:44 + SalI18N_InputContext maCommitStringCallback XIMCallback +vcl/inc/unx/i18n_ic.hxx:45 + SalI18N_InputContext maSwitchIMCallback XIMCallback +vcl/inc/unx/i18n_ic.hxx:46 + SalI18N_InputContext maDestroyCallback XIMCallback +vcl/source/gdi/jobset.cxx:36 + (anonymous namespace)::ImplOldJobSetupData cDeviceName char[32] +vcl/source/gdi/jobset.cxx:37 + (anonymous namespace)::ImplOldJobSetupData cPortName char[32] +vcl/source/pdf/PDFiumLibrary.cxx:389 + vcl::pdf::(anonymous namespace)::PDFiumDocumentImpl m_aFormCallbacks FPDF_FORMFILLINFO +vcl/unx/gtk3/a11y/atkhypertext.cxx:31 + (anonymous namespace)::HyperLink atk_hyper_link const AtkHyperlink +vcl/unx/gtk3/a11y/atkwrapper.hxx:50 + AtkObjectWrapper aParent AtkObject +vcl/unx/gtk3/a11y/atkwrapper.hxx:79 + AtkObjectWrapperClass aParentClass GtkWidgetAccessibleClass +vcl/unx/gtk3/customcellrenderer.hxx:19 + _CustomCellRenderer parent GtkCellRendererText +vcl/unx/gtk3/customcellrenderer.hxx:29 + (anonymous) parent_class GtkCellRendererTextClass +vcl/unx/gtk3/gloactiongroup.cxx:27 + (anonymous namespace)::GLOAction parent_instance GObject +vcl/unx/gtk3/glomenu.cxx:14 + GLOMenu parent_instance const GMenuModel +vcl/unx/gtk3/gtkinst.cxx:7169 + (anonymous namespace)::GtkInstanceAssistant m_pButtonBox GtkButtonBox * +vcl/unx/gtk3/gtkinst.cxx:10599 + (anonymous namespace)::GtkInstanceMenuToggleButton m_pContainer GtkBox * +vcl/unx/gtk3/gtkinst.cxx:10601 + (anonymous namespace)::GtkInstanceMenuToggleButton m_pMenuButton GtkMenuButton * +vcl/unx/gtk3/gtkinst.cxx:19869 + (anonymous namespace)::GtkInstanceComboBox m_pOverlay GtkOverlay * +vcl/unx/gtk3/gtkinst.cxx:19875 + (anonymous namespace)::GtkInstanceComboBox m_pMenuTextRenderer GtkCellRenderer * +writerfilter/source/dmapper/PropertyMap.hxx:219 + writerfilter::dmapper::SectionPropertyMap m_nDebugSectionNumber sal_Int32 +xmloff/source/text/XMLTextListBlockContext.hxx:34 + XMLTextListBlockContext msListStyleName rtl::OUString +xmloff/source/text/XMLTextListBlockContext.hxx:40 + XMLTextListBlockContext mbSetDefaults _Bool diff --git a/compilerplugins/clang/unusedfields.py b/compilerplugins/clang/unusedfields.py new file mode 100755 index 000000000..b0018de21 --- /dev/null +++ b/compilerplugins/clang/unusedfields.py @@ -0,0 +1,290 @@ +#!/usr/bin/python3 + +import sys +import re +import io + +definitionSet = set() +protectedAndPublicDefinitionSet = set() # set of tuple(type, name) +definitionToSourceLocationMap = dict() +definitionToTypeMap = dict() +touchedFromInsideSet = set() +touchedFromOutsideSet = set() +touchedFromOutsideConstructorSet = set() +readFromSet = set() +writeToSet = set() +sourceLocationSet = set() + +# clang does not always use exactly the same numbers in the type-parameter vars it generates +# so I need to substitute them to ensure we can match correctly. +normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") +def normalizeTypeParams( line ): + return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) + +def parseFieldInfo( tokens ): + if len(tokens) == 3: + return (normalizeTypeParams(tokens[1]), tokens[2]) + else: + return (normalizeTypeParams(tokens[1]), "") + +with io.open("workdir/loplugin.unusedfields.log", "r", buffering=1024*1024) as txt: + for line in txt: + tokens = line.strip().split("\t") + if tokens[0] == "definition:": + access = tokens[1] + fieldInfo = (normalizeTypeParams(tokens[2]), tokens[3]) + srcLoc = tokens[5] + # ignore external source code + if (srcLoc.startswith("external/")): + continue + # ignore build folder + if (srcLoc.startswith("workdir/")): + continue + definitionSet.add(fieldInfo) + definitionToTypeMap[fieldInfo] = tokens[4] + if access == "protected" or access == "public": + protectedAndPublicDefinitionSet.add(fieldInfo) + definitionToSourceLocationMap[fieldInfo] = tokens[5] + elif tokens[0] == "inside:": + touchedFromInsideSet.add(parseFieldInfo(tokens)) + elif tokens[0] == "outside:": + touchedFromOutsideSet.add(parseFieldInfo(tokens)) + elif tokens[0] == "outside-constructor:": + touchedFromOutsideConstructorSet.add(parseFieldInfo(tokens)) + elif tokens[0] == "read:": + readFromSet.add(parseFieldInfo(tokens)) + elif tokens[0] == "write:": + writeToSet.add(parseFieldInfo(tokens)) + else: + print( "unknown line: " + line) + +# Calculate untouched +untouchedSet = set() +untouchedSetD = set() +for d in definitionSet: + if d in touchedFromOutsideSet or d in touchedFromInsideSet: + continue + srcLoc = definitionToSourceLocationMap[d]; + # this is all representations of on-disk data structures + if (srcLoc.startswith("sc/source/filter/inc/scflt.hxx") + or srcLoc.startswith("sw/source/filter/ww8/") + or srcLoc.startswith("vcl/source/filter/sgvmain.hxx") + or srcLoc.startswith("vcl/source/filter/sgfbram.hxx") + or srcLoc.startswith("vcl/inc/unx/gtk/gloactiongroup.h") + or srcLoc.startswith("include/svl/svdde.hxx") + or srcLoc.startswith("lotuswordpro/source/filter/lwpsdwdrawheader.hxx") + or srcLoc.startswith("hwpfilter/") + or srcLoc.startswith("embeddedobj/source/inc/") + or srcLoc.startswith("svtools/source/dialogs/insdlg.cxx") + or srcLoc.startswith("bridges/")): + continue + if d[0] in set([ "AtkObjectWrapperClass", "AtkObjectWrapper", "GLOMenu", "GLOAction", "_XRegion", "SalMenuButtonItem", "Vertex", + "OOoMountOperationClass", "SwCSS1ItemIds", "ScCompiler::AddInMap", "MemoryByteGrabber", "textcat_t", "fp_t", "ngram_t", + "ImplPPTParaPropSet", "DataNode"]): + continue + # unit testing code + if srcLoc.startswith("cppu/source/uno/check.cxx"): + continue + fieldType = definitionToTypeMap[d] + if "ModuleClient" in fieldType: + continue + # leave the weld stuff alone until Caolan is finished + if "weld::" in fieldType: + continue + if "::sfx2::sidebar::ControllerItem" in fieldType: + continue + untouchedSet.add((d[0] + " " + d[1] + " " + fieldType, srcLoc)) + untouchedSetD.add(d) + +# Calculate only-touched-in-constructor set +onlyUsedInConstructorSet = set() +for d in definitionSet: + if d in touchedFromOutsideSet or d in touchedFromOutsideConstructorSet: + continue + srcLoc = definitionToSourceLocationMap[d]; + # this is all representations of on-disk data structures + if (srcLoc.startswith("sc/source/filter/inc/scflt.hxx") + or srcLoc.startswith("sw/source/filter/ww8/") + or srcLoc.startswith("vcl/source/filter/sgvmain.hxx") + or srcLoc.startswith("vcl/source/filter/sgfbram.hxx") + or srcLoc.startswith("vcl/inc/unx/gtk/gloactiongroup.h") + or srcLoc.startswith("include/svl/svdde.hxx") + or srcLoc.startswith("lotuswordpro/source/filter/lwpsdwdrawheader.hxx") + or srcLoc.startswith("hwpfilter/") + or srcLoc.startswith("embeddedobj/source/inc/") + or srcLoc.startswith("svtools/source/dialogs/insdlg.cxx") + or srcLoc.startswith("bridges/")): + continue + fieldType = definitionToTypeMap[d] + if "std::unique_ptr" in fieldType: + continue + if "std::shared_ptr" in fieldType: + continue + if "Reference<" in fieldType: + continue + if "VclPtr<" in fieldType: + continue + # leave the weld stuff alone until Caolan is finished + if "weld::" in fieldType: + continue + if "osl::Mutex" in fieldType: + continue + if "::sfx2::sidebar::ControllerItem" in fieldType: + continue + onlyUsedInConstructorSet.add((d[0] + " " + d[1] + " " + fieldType, srcLoc)) + +writeonlySet = set() +for d in definitionSet: + parentClazz = d[0]; + if d in readFromSet or d in untouchedSetD: + continue + srcLoc = definitionToSourceLocationMap[d]; + # this is all representations of on-disk data structures + if (srcLoc.startswith("sc/source/filter/inc/scflt.hxx") + or srcLoc.startswith("sw/source/filter/ww8/") + or srcLoc.startswith("vcl/source/filter/sgvmain.hxx") + or srcLoc.startswith("vcl/source/filter/sgfbram.hxx") + or srcLoc.startswith("vcl/inc/unx/gtk/gloactiongroup.h") + or srcLoc.startswith("include/svl/svdde.hxx") + or srcLoc.startswith("lotuswordpro/source/filter/lwpsdwdrawheader.hxx") + or srcLoc.startswith("svtools/source/dialogs/insdlg.cxx")): + continue + fieldType = definitionToTypeMap[d] + if "ModuleClient" in fieldType: + continue + if "::sfx2::sidebar::ControllerItem" in fieldType: + continue + # ignore reference fields, because writing to them actually writes to another field somewhere else + if fieldType.endswith("&"): + continue + # ignore the import/export data model stuff + if srcLoc.startswith("sc/source/filter/inc/") and "Model" in fieldType: + continue + if srcLoc.startswith("sc/source/filter/inc/") and (parentClazz.startswith("Xcl") or parentClazz.startswith("oox::xls::")): + continue + # implement some kind of registration of errors + if fieldType == "class SfxErrorHandler *": + continue + # mutex locking + if "Guard" in fieldType: + continue + # leave the weld stuff alone until Caolan is finished + if "weld::" in fieldType: + continue + # these are just all model classes + if (srcLoc.startswith("oox/") + or srcLoc.startswith("lotuswordpro/") + or srcLoc.startswith("include/oox/") + or srcLoc.startswith("include/filter/") + or srcLoc.startswith("hwpfilter/") + or srcLoc.startswith("filter/") + or srcLoc.startswith("vcl/source/filter/")): + continue + + writeonlySet.add((d[0] + " " + d[1] + " " + definitionToTypeMap[d], srcLoc)) + + +readonlySet = set() +for d in definitionSet: + parentClazz = d[0]; + if d in writeToSet or d in untouchedSetD: + continue + fieldType = definitionToTypeMap[d] + srcLoc = definitionToSourceLocationMap[d]; + if "ModuleClient" in fieldType: + continue + # this is all representations of on-disk data structures + if (srcLoc.startswith("sc/source/filter/inc/scflt.hxx") + or srcLoc.startswith("sw/source/filter/ww8/") + or srcLoc.startswith("vcl/source/filter/sgvmain.hxx") + or srcLoc.startswith("vcl/source/filter/sgfbram.hxx") + or srcLoc.startswith("vcl/inc/unx/gtk/gloactiongroup.h") + or srcLoc.startswith("include/svl/svdde.hxx")): + continue + # I really don't care about these ancient file formats + if (srcLoc.startswith("hwpfilter/") + or srcLoc.startswith("lotuswordpro/")): + continue + # leave the weld stuff alone until Caolan is finished + if "weld::" in fieldType: + continue + readonlySet.add((d[0] + " " + d[1] + " " + definitionToTypeMap[d], srcLoc)) + + +canBePrivateSet = set() +for d in protectedAndPublicDefinitionSet: + clazz = d[0] + " " + d[1] + if d in touchedFromOutsideSet: + continue + srcLoc = definitionToSourceLocationMap[d]; + + canBePrivateSet.add((clazz + " " + definitionToTypeMap[d], srcLoc)) + + +# -------------------------------------------------------------------------------------------- +# "all fields in class can be made private" analysis +# -------------------------------------------------------------------------------------------- + +potentialClasses = set() +excludedClasses = set() +potentialClassesSourceLocationMap = dict() +matchClassName = re.compile(r"(\w+)::") +for d in protectedAndPublicDefinitionSet: + clazz = d[0] + if d in touchedFromOutsideSet: + excludedClasses.add(clazz) + else: + potentialClasses.add(clazz) + potentialClassesSourceLocationMap[clazz] = definitionToSourceLocationMap[d] +allFieldsCanBePrivateSet = set() +for d in (potentialClasses - excludedClasses): + sourceLoc = potentialClassesSourceLocationMap[d] + # when the class is inside a compile unit, assume that the compiler can figure this out for itself, much less interesting to me + if not ".cxx" in sourceLoc: + allFieldsCanBePrivateSet.add((d, sourceLoc)) + +# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[1]) + [v[0]] + +# sort results by name and line number +tmp1list = sorted(untouchedSet, key=lambda v: v_sort_key(v)) +tmp2list = sorted(writeonlySet, key=lambda v: v_sort_key(v)) +tmp3list = sorted(canBePrivateSet, key=lambda v: v_sort_key(v)) +tmp4list = sorted(readonlySet, key=lambda v: v_sort_key(v)) +tmp5list = sorted(onlyUsedInConstructorSet, key=lambda v: v_sort_key(v)) +tmp6list = sorted(allFieldsCanBePrivateSet, key=lambda v: v_sort_key(v)) + +# print out the results +with open("compilerplugins/clang/unusedfields.untouched.results", "wt") as f: + for t in tmp1list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) +with open("compilerplugins/clang/unusedfields.writeonly.results", "wt") as f: + for t in tmp2list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) +# this one is not checked in yet because I haven't actually done anything with it +with open("loplugin.unusedfields.report-can-be-private", "wt") as f: + for t in tmp3list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) +with open("compilerplugins/clang/unusedfields.readonly.results", "wt") as f: + for t in tmp4list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) +with open("compilerplugins/clang/unusedfields.only-used-in-constructor.results", "wt") as f: + for t in tmp5list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) +with open("compilerplugins/clang/unusedfields.report-all-can-be-private", "wt") as f: + for t in tmp6list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) + + diff --git a/compilerplugins/clang/unusedfields.readonly.results b/compilerplugins/clang/unusedfields.readonly.results new file mode 100644 index 000000000..0c31aec65 --- /dev/null +++ b/compilerplugins/clang/unusedfields.readonly.results @@ -0,0 +1,824 @@ +basegfx/source/polygon/b2dtrapezoid.cxx:205 + basegfx::trapezoidhelper::(anonymous namespace)::PointBlockAllocator maFirstStackBlock class basegfx::B2DPoint[32] +basic/source/inc/expr.hxx:92 + SbiExprNode::(anonymous) nTypeStrId sal_uInt16 +bridges/source/cpp_uno/gcc3_linux_x86-64/callvirtualmethod.cxx:63 + Data rdx sal_uInt64 +bridges/source/cpp_uno/gcc3_linux_x86-64/callvirtualmethod.cxx:64 + Data xmm0 double +bridges/source/cpp_uno/gcc3_linux_x86-64/callvirtualmethod.cxx:65 + Data xmm1 double +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:128 + __cxxabiv1::__cxa_exception exceptionType std::type_info * +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:129 + __cxxabiv1::__cxa_exception exceptionDestructor void (*)(void *) +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:130 + __cxxabiv1::__cxa_exception unexpectedHandler void (*)(void) +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:131 + __cxxabiv1::__cxa_exception terminateHandler std::terminate_handler +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:132 + __cxxabiv1::__cxa_exception nextException struct __cxxabiv1::__cxa_exception * +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:133 + __cxxabiv1::__cxa_exception handlerCount int +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:134 + __cxxabiv1::__cxa_exception handlerSwitchValue int +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:135 + __cxxabiv1::__cxa_exception actionRecord const char * +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:136 + __cxxabiv1::__cxa_exception languageSpecificData const char * +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:137 + __cxxabiv1::__cxa_exception catchTemp void * +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:138 + __cxxabiv1::__cxa_exception adjustedPtr void * +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:139 + __cxxabiv1::__cxa_exception unwindHeader _Unwind_Exception +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:148 + __cxxabiv1::__cxa_eh_globals caughtExceptions struct __cxxabiv1::__cxa_exception * +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:149 + __cxxabiv1::__cxa_eh_globals uncaughtExceptions unsigned int +bridges/source/jni_uno/jni_info.h:67 + jni_uno::JNI_type_info m_td ::com::sun::star::uno::TypeDescription +bridges/source/jni_uno/jni_java2uno.cxx:151 + jni_uno::(anonymous namespace)::largest n sal_Int64 +bridges/source/jni_uno/jni_java2uno.cxx:152 + jni_uno::(anonymous namespace)::largest d double +bridges/source/jni_uno/jni_java2uno.cxx:153 + jni_uno::(anonymous namespace)::largest p void * +bridges/source/jni_uno/jni_java2uno.cxx:154 + jni_uno::(anonymous namespace)::largest a uno_Any +chart2/source/model/main/DataPoint.hxx:106 + chart::DataPoint m_bNoParentPropAllowed _Bool +codemaker/source/javamaker/classfile.cxx:508 + uint32Bytes sal_uInt32 +codemaker/source/javamaker/classfile.cxx:540 + uint64Bytes sal_uInt64 +connectivity/inc/sdbcx/VCatalog.hxx:66 + connectivity::sdbcx::OCatalog m_pGroups std::unique_ptr +connectivity/inc/sdbcx/VGroup.hxx:52 + connectivity::sdbcx::OGroup m_pUsers std::unique_ptr +connectivity/inc/sdbcx/VKey.hxx:69 + connectivity::sdbcx::OKey m_pColumns std::unique_ptr +connectivity/inc/sdbcx/VUser.hxx:52 + connectivity::sdbcx::OUser m_pGroups std::unique_ptr +connectivity/qa/connectivity/resource/sharedresources_test.cxx:53 + connectivity_test::SharedResourcesTest m_aResource ::connectivity::SharedResources +connectivity/source/drivers/evoab2/EApi.h:124 + (anonymous) po char * +connectivity/source/drivers/evoab2/EApi.h:126 + (anonymous) street char * +connectivity/source/drivers/evoab2/EApi.h:127 + (anonymous) locality char * +connectivity/source/drivers/evoab2/EApi.h:128 + (anonymous) region char * +connectivity/source/drivers/evoab2/EApi.h:129 + (anonymous) code char * +connectivity/source/drivers/evoab2/EApi.h:130 + (anonymous) country char * +connectivity/source/inc/dbase/DIndexIter.hxx:33 + connectivity::dbase::OIndexIterator m_pOperator file::OBoolOperator * +connectivity/source/inc/dbase/DIndexIter.hxx:34 + connectivity::dbase::OIndexIterator m_pOperand const file::OOperand * +connectivity/source/inc/FDatabaseMetaDataResultSet.hxx:109 + connectivity::ODatabaseMetaDataResultSet m_aEmptyValue class connectivity::ORowSetValue +connectivity/source/inc/OColumn.hxx:40 + connectivity::OColumn m_AutoIncrement _Bool +connectivity/source/inc/OColumn.hxx:41 + connectivity::OColumn m_CaseSensitive _Bool +connectivity/source/inc/OColumn.hxx:43 + connectivity::OColumn m_Currency _Bool +connectivity/source/inc/OColumn.hxx:44 + connectivity::OColumn m_Signed _Bool +connectivity/source/inc/OColumn.hxx:46 + connectivity::OColumn m_Writable _Bool +connectivity/source/inc/OColumn.hxx:47 + connectivity::OColumn m_DefinitelyWritable _Bool +connectivity/source/inc/TConnection.hxx:54 + connectivity::OMetaConnection m_aResources class connectivity::SharedResources +connectivity/source/inc/writer/WTable.hxx:43 + connectivity::writer::OWriterTable m_nStartCol sal_Int32 +cppcanvas/source/mtfrenderer/textaction.cxx:1635 + cppcanvas::internal::(anonymous namespace)::OutlineAction maTextFillColor const ::Color +cppu/source/helper/purpenv/helper_purpenv_Mapping.cxx:36 + (anonymous namespace)::Mapping m_from uno::Environment +cppu/source/helper/purpenv/helper_purpenv_Mapping.cxx:37 + (anonymous namespace)::Mapping m_to uno::Environment +cppu/source/helper/purpenv/Proxy.hxx:35 + Proxy m_from css::uno::Environment +cppu/source/helper/purpenv/Proxy.hxx:36 + Proxy m_to css::uno::Environment +cppu/source/uno/cascade_mapping.cxx:42 + (anonymous namespace)::MediatorMapping m_from uno::Environment +cppu/source/uno/cascade_mapping.cxx:43 + (anonymous namespace)::MediatorMapping m_interm uno::Environment +cppu/source/uno/cascade_mapping.cxx:44 + (anonymous namespace)::MediatorMapping m_to uno::Environment +cppu/source/uno/check.cxx:38 + (anonymous namespace)::C1 n1 sal_Int16 +cppu/source/uno/check.cxx:67 + (anonymous namespace)::D d sal_Int16 +cppu/source/uno/check.cxx:68 + (anonymous namespace)::D e sal_Int32 +cppu/source/uno/check.cxx:72 + (anonymous namespace)::E a sal_Bool +cppu/source/uno/check.cxx:73 + (anonymous namespace)::E b sal_Bool +cppu/source/uno/check.cxx:74 + (anonymous namespace)::E c sal_Bool +cppu/source/uno/check.cxx:75 + (anonymous namespace)::E d sal_Int16 +cppu/source/uno/check.cxx:76 + (anonymous namespace)::E e sal_Int32 +cppu/source/uno/check.cxx:81 + (anonymous namespace)::M n sal_Int32 +cppu/source/uno/check.cxx:82 + (anonymous namespace)::M o sal_Int16 +cppu/source/uno/check.cxx:91 + (anonymous namespace)::N2 m struct (anonymous namespace)::M +cppu/source/uno/check.cxx:92 + (anonymous namespace)::N2 p sal_Int16 +cppu/source/uno/check.cxx:97 + (anonymous namespace)::O p double +cppu/source/uno/check.cxx:98 + (anonymous namespace)::O q sal_Int16 +cppu/source/uno/check.cxx:107 + (anonymous namespace)::P p2 double +cppu/source/uno/check.cxx:115 + (anonymous namespace)::second a int +cppu/source/uno/check.cxx:126 + (anonymous namespace)::Char1 c1 char +cppu/source/uno/check.cxx:130 + (anonymous namespace)::Char2 c2 char +cppu/source/uno/check.cxx:134 + (anonymous namespace)::Char3 c3 char +cppu/source/uno/check.cxx:258 + (anonymous namespace)::Char4 chars struct (anonymous namespace)::Char3 +cui/source/options/optcolor.cxx:259 + (anonymous namespace)::ColorConfigWindow_Impl aModuleOptions class SvtModuleOptions +dbaccess/source/core/api/RowSetBase.hxx:84 + dbaccess::ORowSetBase m_aEmptyValue connectivity::ORowSetValue +dbaccess/source/core/api/RowSetBase.hxx:95 + dbaccess::ORowSetBase m_aErrors ::connectivity::SQLError +dbaccess/source/core/dataaccess/documentcontainer.cxx:67 + dbaccess::(anonymous namespace)::LocalNameApproval m_aErrors ::connectivity::SQLError +dbaccess/source/core/inc/ContentHelper.hxx:103 + dbaccess::OContentHelper m_aErrorHelper const ::connectivity::SQLError +dbaccess/source/filter/hsqldb/parseschema.hxx:34 + dbahsql::SchemaParser m_PrimaryKeys std::map > +dbaccess/source/ui/control/tabletree.cxx:127 + dbaui::(anonymous namespace)::OViewSetter m_aEqualFunctor ::comphelper::UStringMixEqual +dbaccess/source/ui/inc/charsetlistbox.hxx:43 + dbaui::CharSetListBox m_aCharSets class dbaui::OCharsetDisplay +dbaccess/source/ui/inc/sqledit.hxx:41 + dbaui::SQLEditView m_aColorConfig const svtools::ColorConfig +dbaccess/source/ui/inc/WCopyTable.hxx:258 + dbaui::OCopyTableWizard m_aLocale css::lang::Locale +editeng/source/editeng/impedit.hxx:516 + ImpEditEngine maColorConfig svtools::ColorConfig +embeddedobj/source/inc/commonembobj.hxx:110 + OCommonEmbeddedObject m_aClassName rtl::OUString +embeddedobj/source/inc/oleembobj.hxx:125 + OleEmbeddedObject m_pOleComponent rtl::Reference +embeddedobj/source/inc/oleembobj.hxx:145 + OleEmbeddedObject m_xClosePreventer css::uno::Reference +embeddedobj/source/inc/oleembobj.hxx:167 + OleEmbeddedObject m_bHasSizeToSet _Bool +embeddedobj/source/inc/oleembobj.hxx:168 + OleEmbeddedObject m_aSizeToSet css::awt::Size +embeddedobj/source/inc/oleembobj.hxx:169 + OleEmbeddedObject m_nAspectToSet sal_Int64 +embeddedobj/source/inc/oleembobj.hxx:174 + OleEmbeddedObject m_bGotStatus _Bool +embeddedobj/source/inc/oleembobj.hxx:175 + OleEmbeddedObject m_nStatus sal_Int64 +embeddedobj/source/inc/oleembobj.hxx:176 + OleEmbeddedObject m_nStatusAspect sal_Int64 +embeddedobj/source/inc/oleembobj.hxx:184 + OleEmbeddedObject m_aLinkURL rtl::OUString +embeddedobj/source/inc/oleembobj.hxx:190 + OleEmbeddedObject m_bFromClipboard _Bool +embeddedobj/source/msole/olecomponent.hxx:73 + OleComponent m_bWorkaroundActive _Bool +extensions/source/propctrlr/eformshelper.hxx:60 + pcr::EFormsHelper m_aSubmissionUINames pcr::MapStringToPropertySet +extensions/source/propctrlr/eformshelper.hxx:62 + pcr::EFormsHelper m_aBindingUINames pcr::MapStringToPropertySet +filter/source/graphicfilter/icgm/chart.hxx:48 + DataNode nBoxX1 sal_Int16 +filter/source/graphicfilter/icgm/chart.hxx:49 + DataNode nBoxY1 sal_Int16 +filter/source/graphicfilter/icgm/chart.hxx:50 + DataNode nBoxX2 sal_Int16 +filter/source/graphicfilter/icgm/chart.hxx:51 + DataNode nBoxY2 sal_Int16 +filter/source/xsltdialog/xmlfiltersettingsdialog.hxx:85 + XMLFilterSettingsDialog maModuleOpt class SvtModuleOptions +framework/inc/dispatch/dispatchprovider.hxx:76 + framework::DispatchProvider m_aProtocolHandlerCache class framework::HandlerCache +framework/inc/helper/uiconfigelementwrapperbase.hxx:128 + framework::UIConfigElementWrapperBase m_bConfigListening _Bool +framework/inc/xml/menudocumenthandler.hxx:186 + framework::OReadMenuPopupHandler m_bMenuMode _Bool +framework/source/fwe/classes/addonsoptions.cxx:349 + framework::AddonsOptions_Impl m_aEmptyAddonToolBar Sequence > +framework/source/fwe/classes/addonsoptions.cxx:350 + framework::AddonsOptions_Impl m_aEmptyAddonNotebookBar Sequence > +i18npool/inc/textconversion.hxx:78 + i18npool::(anonymous) code sal_Unicode +i18npool/inc/textconversion.hxx:79 + i18npool::(anonymous) address sal_Int16 +i18npool/inc/textconversion.hxx:80 + i18npool::(anonymous) count sal_Int16 +include/basic/sbstar.hxx:50 + StarBASIC aErrorHdl Link +include/basic/sbstar.hxx:51 + StarBASIC aBreakHdl Link +include/comphelper/guarding.hxx:40 + comphelper::ORelease m_rMutex MUTEX & +include/comphelper/parallelsort.hxx:164 + comphelper::(anonymous namespace)::Binner maLabels uint8_t[51200] +include/comphelper/servicedecl.hxx:130 + comphelper::service_decl::ServiceDecl m_createFunc const detail::CreateFuncF +include/comphelper/servicedecl.hxx:131 + comphelper::service_decl::ServiceDecl m_pImplName const char *const +include/comphelper/servicedecl.hxx:132 + comphelper::service_decl::ServiceDecl m_pServiceNames const char *const +include/comphelper/stl_types.hxx:113 + comphelper::mem_fun1_t M_f const comphelper::mem_fun1_t::_fun_type +include/connectivity/DriversConfig.hxx:76 + connectivity::DriversConfig m_aNode connectivity::DriversConfig::OSharedConfigNode +include/connectivity/sdbcx/VDescriptor.hxx:51 + connectivity::sdbcx::ODescriptor m_aCase comphelper::UStringMixEqual +include/connectivity/sdbcx/VTable.hxx:77 + connectivity::sdbcx::OTable m_xColumns std::unique_ptr +include/connectivity/sdbcx/VTable.hxx:78 + connectivity::sdbcx::OTable m_xIndexes std::unique_ptr +include/connectivity/sqlparse.hxx:104 + connectivity::OSQLParser_Data aErrors ::connectivity::SQLError +include/filter/msfilter/svdfppt.hxx:718 + PPTExtParaSheet aExtParaLevel struct PPTExtParaLevel[10] +include/filter/msfilter/svdfppt.hxx:889 + ImplPPTParaPropSet nDontKnow1 sal_uInt32 +include/filter/msfilter/svdfppt.hxx:890 + ImplPPTParaPropSet nDontKnow2 sal_uInt32 +include/filter/msfilter/svdfppt.hxx:891 + ImplPPTParaPropSet nDontKnow2bit06 sal_uInt16 +include/oox/core/contexthandler2.hxx:231 + oox::core::ContextHandler2Helper mnRootStackSize size_t +include/oox/helper/containerhelper.hxx:130 + oox::Matrix maData oox::Matrix::container_type +include/oox/ole/axbinarywriter.hxx:150 + oox::ole::AxBinaryPropertyWriter maStreamProps oox::ole::AxBinaryPropertyWriter::ComplexPropVector +include/registry/refltype.hxx:65 + RTUik m_Data1 sal_uInt32 +include/registry/refltype.hxx:66 + RTUik m_Data2 sal_uInt16 +include/registry/refltype.hxx:67 + RTUik m_Data3 sal_uInt16 +include/registry/refltype.hxx:68 + RTUik m_Data4 sal_uInt32 +include/registry/refltype.hxx:69 + RTUik m_Data5 sal_uInt32 +include/sfx2/lokhelper.hxx:32 + LokMouseEventData maLogicPosition std::optional +include/sfx2/msg.hxx:95 + SfxTypeAttrib nAID sal_uInt16 +include/sfx2/msg.hxx:96 + SfxTypeAttrib pName const char * +include/sfx2/msg.hxx:105 + SfxType createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:106 + SfxType pType const std::type_info * +include/sfx2/msg.hxx:107 + SfxType nAttribs sal_uInt16 +include/sfx2/msg.hxx:108 + SfxType aAttrib struct SfxTypeAttrib[1] +include/sfx2/msg.hxx:118 + SfxType0 pType const std::type_info * +include/svl/ondemand.hxx:55 + OnDemandLocaleDataWrapper aSysLocale class SvtSysLocale +include/svx/graphctl.hxx:52 + GraphCtrl xVD ScopedVclPtrInstance +include/svx/sdr/overlay/overlayanimatedbitmapex.hxx:49 + sdr::overlay::OverlayAnimatedBitmapEx mbOverlayState _Bool +include/svx/svdmark.hxx:141 + SdrMarkList maPointName rtl::OUString +include/svx/svdmark.hxx:142 + SdrMarkList maGluePointName rtl::OUString +include/svx/svdoedge.hxx:160 + SdrEdgeObj mbBoundRectCalculationRunning _Bool +include/unoidl/unoidl.hxx:444 + unoidl::ConstantValue union unoidl::ConstantValue::(anonymous at /home/noel/libo2/include/unoidl/unoidl.hxx:444:5) +include/unoidl/unoidl.hxx:445 + unoidl::ConstantValue::(anonymous) booleanValue _Bool +include/unoidl/unoidl.hxx:446 + unoidl::ConstantValue::(anonymous) byteValue sal_Int8 +include/unoidl/unoidl.hxx:447 + unoidl::ConstantValue::(anonymous) shortValue sal_Int16 +include/unoidl/unoidl.hxx:448 + unoidl::ConstantValue::(anonymous) unsignedShortValue sal_uInt16 +include/unoidl/unoidl.hxx:449 + unoidl::ConstantValue::(anonymous) longValue sal_Int32 +include/unoidl/unoidl.hxx:450 + unoidl::ConstantValue::(anonymous) unsignedLongValue sal_uInt32 +include/unoidl/unoidl.hxx:451 + unoidl::ConstantValue::(anonymous) hyperValue sal_Int64 +include/unoidl/unoidl.hxx:452 + unoidl::ConstantValue::(anonymous) unsignedHyperValue sal_uInt64 +include/unoidl/unoidl.hxx:453 + unoidl::ConstantValue::(anonymous) floatValue float +include/unoidl/unoidl.hxx:454 + unoidl::ConstantValue::(anonymous) doubleValue double +include/unotest/bootstrapfixturebase.hxx:52 + test::BootstrapFixtureBase m_directories class test::Directories +include/vcl/formatter.hxx:127 + Formatter m_aStaticFormatter class Formatter::StaticFormatter +include/vcl/toolkit/field.hxx:399 + DateFormatter maStaticFormatter class Formatter::StaticFormatter +io/source/stm/odata.cxx:559 + io_stm::(anonymous namespace)::ODataOutputStream::writeDouble(double)::(anonymous union)::(anonymous) n1 sal_uInt32 +io/source/stm/odata.cxx:559 + io_stm::(anonymous namespace)::ODataOutputStream::writeDouble(double)::(anonymous union)::(anonymous) n2 sal_uInt32 +libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx:48 + (anonymous namespace)::GtvLokDialogPrivate m_nChildKeyModifier guint32 +libreofficekit/source/gtk/lokdocview.cxx:85 + (anonymous namespace)::LOKDocViewPrivateImpl m_bIsLoading _Bool +lingucomponent/source/languageguessing/simpleguesser.cxx:72 + (anonymous namespace)::textcat_t fprint void ** +lingucomponent/source/languageguessing/simpleguesser.cxx:74 + (anonymous namespace)::textcat_t size uint4 +linguistic/source/dlistimp.hxx:56 + DicList aOpt class LinguOptions +oox/inc/drawingml/table/tablecell.hxx:85 + oox::drawingml::table::TableCell maLinePropertiesInsideH oox::drawingml::LineProperties +oox/inc/drawingml/table/tablecell.hxx:86 + oox::drawingml::table::TableCell maLinePropertiesInsideV oox::drawingml::LineProperties +oox/qa/token/tokenmap-test.cxx:33 + oox::TokenmapTest tokenMap class oox::TokenMap +oox/qa/unit/vba_compression.cxx:70 + TestVbaCompression m_directories test::Directories +oox/source/drawingml/chart/objectformatter.cxx:717 + oox::drawingml::chart::ObjectFormatterData maFromLocale struct com::sun::star::lang::Locale +registry/source/reflwrit.cxx:140 + writeDouble(sal_uInt8 *, double)::(anonymous union)::(anonymous) b1 sal_uInt32 +registry/source/reflwrit.cxx:141 + writeDouble(sal_uInt8 *, double)::(anonymous union)::(anonymous) b2 sal_uInt32 +registry/source/reflwrit.cxx:181 + (anonymous namespace)::CPInfo::(anonymous) aUik struct RTUik * +reportdesign/source/ui/inc/ColorListener.hxx:35 + rptui::OColorListener m_aColorConfig svtools::ColorConfig +sal/osl/unx/process.cxx:827 + (anonymous namespace)::osl_procStat signal char[24] +sal/osl/unx/process.cxx:828 + (anonymous namespace)::osl_procStat blocked char[24] +sal/osl/unx/process.cxx:829 + (anonymous namespace)::osl_procStat sigignore char[24] +sal/osl/unx/process.cxx:830 + (anonymous namespace)::osl_procStat sigcatch char[24] +sal/qa/OStringBuffer/rtl_OStringBuffer.cxx:1675 + rtl_OStringBuffer::append_001 empty rtl::OString +sal/rtl/alloc_arena.hxx:100 + rtl_arena_st m_hash_table_0 struct rtl_arena_segment_type *[64] +sal/rtl/digest.cxx:188 + (anonymous namespace)::DigestContextMD2 m_state sal_uInt32[16] +sal/rtl/digest.cxx:189 + (anonymous namespace)::DigestContextMD2 m_chksum sal_uInt32[16] +sal/rtl/uuid.cxx:66 + (anonymous namespace)::UUID clock_seq_low sal_uInt8 +sal/rtl/uuid.cxx:67 + (anonymous namespace)::UUID node sal_uInt8[6] +sc/inc/attarray.hxx:69 + ScMergePatternState pItemSet std::optional +sc/inc/compiler.hxx:132 + ScRawToken::(anonymous union)::(anonymous) eItem class ScTableRefToken::Item +sc/inc/compiler.hxx:133 + ScRawToken::(anonymous) table struct (unnamed struct at /home/noel/libo2/sc/inc/compiler.hxx:130:9) +sc/inc/compiler.hxx:138 + ScRawToken::(anonymous) pMat class ScMatrix * +sc/inc/formulagroup.hxx:38 + sc::FormulaGroupEntry::(anonymous) mpCells class ScFormulaCell ** +sc/inc/reordermap.hxx:20 + sc::ColRowReorderMapType maData sc::ColRowReorderMapType::DataType +sc/source/core/inc/adiasync.hxx:41 + ScAddInAsync::(anonymous) pStr rtl::OUString * +sc/source/core/inc/interpre.hxx:99 + ScTokenStack pPointer const formula::FormulaToken *[512] +sc/source/filter/excel/xltoolbar.cxx:30 + (anonymous namespace)::MSOExcelCommandConvertor msoToOOcmd IdToString +sc/source/filter/excel/xltoolbar.cxx:31 + (anonymous namespace)::MSOExcelCommandConvertor tcidToOOcmd IdToString +sc/source/filter/inc/commentsbuffer.hxx:40 + oox::xls::CommentModel maAnchor css::awt::Rectangle +sc/source/filter/inc/htmlexp.hxx:117 + ScHTMLExport pFileNameMap ScHTMLExport::FileNameMapPtr +sc/source/filter/inc/htmlpars.hxx:57 + ScHTMLStyles maEmpty const rtl::OUString +sc/source/filter/inc/namebuff.hxx:79 + RangeNameBufferWK3::Entry nAbsInd sal_uInt16 +sc/source/filter/inc/qproform.hxx:54 + QProToSc mnAddToken struct TokenId +sc/source/filter/inc/stylesbuffer.hxx:674 + oox::xls::Dxf mxAlignment std::shared_ptr +sc/source/filter/inc/stylesbuffer.hxx:676 + oox::xls::Dxf mxProtection std::shared_ptr +sc/source/filter/inc/stylesbuffer.hxx:765 + oox::xls::CellStyleBuffer maBuiltinStyles oox::xls::CellStyleBuffer::CellStyleVector +sc/source/filter/inc/stylesbuffer.hxx:766 + oox::xls::CellStyleBuffer maUserStyles oox::xls::CellStyleBuffer::CellStyleVector +sc/source/filter/inc/XclExpChangeTrack.hxx:347 + XclExpChTrAction pAddAction std::unique_ptr +sc/source/filter/inc/xepage.hxx:121 + XclExpChartPageSettings maData struct XclPageData +sc/source/filter/inc/xistyle.hxx:517 + XclImpXFBuffer maBuiltinStyles XclImpXFBuffer::XclImpStyleList +sc/source/filter/inc/xistyle.hxx:518 + XclImpXFBuffer maUserStyles XclImpXFBuffer::XclImpStyleList +sc/source/filter/inc/xltracer.hxx:81 + XclTracer mbEnabled _Bool +sc/source/filter/xml/xmlcelli.hxx:94 + ScXMLTableRowCellContext mbEditEngineHasText _Bool +sc/source/ui/inc/csvruler.hxx:37 + ScCsvRuler maBackgrDev ScopedVclPtrInstance +sc/source/ui/inc/csvruler.hxx:38 + ScCsvRuler maRulerDev ScopedVclPtrInstance +sc/source/ui/inc/inputhdl.hxx:66 + ScInputHandler pColumnData std::unique_ptr +sc/source/ui/inc/inputhdl.hxx:67 + ScInputHandler pFormulaData std::unique_ptr +sc/source/ui/inc/inputhdl.hxx:68 + ScInputHandler pFormulaDataPara std::unique_ptr +sc/source/ui/inc/tabcont.hxx:37 + ScTabControl bErrorShown _Bool +sc/source/ui/vba/vbaformatconditions.hxx:36 + ScVbaFormatConditions mxSheetConditionalEntries css::uno::Reference +sc/source/ui/vba/vbaformatconditions.hxx:37 + ScVbaFormatConditions mxStyles css::uno::Reference +sc/source/ui/vba/vbaformatconditions.hxx:38 + ScVbaFormatConditions mxRangeParent css::uno::Reference +sc/source/ui/vba/vbaformatconditions.hxx:39 + ScVbaFormatConditions mxParentRangePropertySet css::uno::Reference +sc/source/ui/vba/vbaworksheet.hxx:49 + ScVbaWorksheet mxButtons ::rtl::Reference[2] +sd/inc/Outliner.hxx:288 + SdOutliner mpFirstObj class SdrObject * +sd/inc/sdmod.hxx:120 + SdModule gImplImpressPropertySetInfoCache SdExtPropertySetInfoCache +sd/inc/sdmod.hxx:121 + SdModule gImplDrawPropertySetInfoCache SdExtPropertySetInfoCache +sd/source/core/CustomAnimationCloner.cxx:70 + sd::(anonymous namespace)::CustomAnimationClonerImpl maSourceNodeVector std::vector > +sd/source/core/CustomAnimationCloner.cxx:71 + sd::(anonymous namespace)::CustomAnimationClonerImpl maCloneNodeVector std::vector > +sd/source/ui/inc/unopage.hxx:164 + SdDrawPage maTypeSequence css::uno::Sequence +sd/source/ui/inc/unopage.hxx:224 + SdMasterPage maTypeSequence css::uno::Sequence +sd/source/ui/sidebar/MasterPageContainer.cxx:141 + sd::sidebar::MasterPageContainer::Implementation maLargePreviewBeingCreated class Image +sd/source/ui/sidebar/MasterPageContainer.cxx:142 + sd::sidebar::MasterPageContainer::Implementation maSmallPreviewBeingCreated class Image +sd/source/ui/sidebar/MasterPageContainer.cxx:147 + sd::sidebar::MasterPageContainer::Implementation maLargePreviewNotAvailable class Image +sd/source/ui/sidebar/MasterPageContainer.cxx:148 + sd::sidebar::MasterPageContainer::Implementation maSmallPreviewNotAvailable class Image +sd/source/ui/slideshow/showwindow.hxx:98 + sd::ShowWindow mbMouseCursorHidden _Bool +sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx:141 + sd::slidesorter::cache::PageCacheManager::RecentlyUsedPageCaches maMap std::map +sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx:96 + sd::slidesorter::controller::Animator maElapsedTime ::canvas::tools::ElapsedTime +sdext/source/pdfimport/inc/pdfihelper.hxx:100 + pdfi::GraphicsContext BlendMode sal_Int8 +sdext/source/pdfimport/tree/style.hxx:44 + pdfi::StyleContainer::Style Contents rtl::OUString +sfx2/source/appl/lnkbase2.cxx:81 + sfx2::(anonymous namespace)::ImplDdeItem pLink class sfx2::SvBaseLink * +slideshow/source/engine/slideshowimpl.cxx:139 + (anonymous namespace)::FrameSynchronization maTimer canvas::tools::ElapsedTime +sot/source/sdstor/ucbstorage.cxx:406 + UCBStorageStream_Impl m_aKey rtl::OString +store/source/storbios.cxx:59 + (anonymous namespace)::OStoreSuperBlock m_aMarked (anonymous namespace)::OStoreSuperBlock::L +svl/source/crypto/cryptosign.cxx:267 + (anonymous namespace)::PKIStatusInfo status SECItem +svl/source/crypto/cryptosign.cxx:287 + (anonymous namespace)::TimeStampResp status struct (anonymous namespace)::PKIStatusInfo +svl/source/crypto/cryptosign.cxx:288 + (anonymous namespace)::TimeStampResp timeStampToken SECItem +svl/source/misc/strmadpt.cxx:51 + SvDataPipe_Impl::Page m_aBuffer sal_Int8[1] +svl/source/uno/pathservice.cxx:37 + (anonymous namespace)::PathService m_aOptions class SvtPathOptions +svtools/source/control/tabbar.cxx:209 + ImplTabBarItem maHelpId rtl::OString +svtools/source/dialogs/insdlg.cxx:54 + (anonymous namespace)::OleObjectDescriptor cbSize sal_uInt32 +svtools/source/dialogs/insdlg.cxx:55 + (anonymous namespace)::OleObjectDescriptor clsid ClsId +svtools/source/dialogs/insdlg.cxx:56 + (anonymous namespace)::OleObjectDescriptor dwDrawAspect sal_uInt32 +svtools/source/dialogs/insdlg.cxx:57 + (anonymous namespace)::OleObjectDescriptor sizel SIZEL +svtools/source/dialogs/insdlg.cxx:58 + (anonymous namespace)::OleObjectDescriptor pointl POINTL +svtools/source/dialogs/insdlg.cxx:59 + (anonymous namespace)::OleObjectDescriptor dwStatus sal_uInt32 +svtools/source/dialogs/insdlg.cxx:60 + (anonymous namespace)::OleObjectDescriptor dwFullUserTypeName sal_uInt32 +svtools/source/dialogs/insdlg.cxx:61 + (anonymous namespace)::OleObjectDescriptor dwSrcOfCopy sal_uInt32 +svtools/source/table/gridtablerenderer.cxx:71 + svt::table::(anonymous namespace)::CachedSortIndicator m_sortAscending class BitmapEx +svtools/source/table/gridtablerenderer.cxx:72 + svt::table::(anonymous namespace)::CachedSortIndicator m_sortDescending class BitmapEx +svx/inc/sdr/overlay/overlayrectangle.hxx:41 + sdr::overlay::OverlayRectangle mbOverlayState _Bool +svx/source/inc/datanavi.hxx:182 + svxform::XFormsPage m_aMethodString class svxform::MethodString +svx/source/inc/datanavi.hxx:183 + svxform::XFormsPage m_aReplaceString class svxform::ReplaceString +svx/source/inc/datanavi.hxx:488 + svxform::AddSubmissionDialog m_aMethodString class svxform::MethodString +svx/source/inc/datanavi.hxx:489 + svxform::AddSubmissionDialog m_aReplaceString class svxform::ReplaceString +svx/source/inc/gridcell.hxx:514 + DbPatternField m_pValueFormatter ::std::unique_ptr< ::dbtools::FormattedColumnValue> +svx/source/inc/gridcell.hxx:515 + DbPatternField m_pPaintFormatter ::std::unique_ptr< ::dbtools::FormattedColumnValue> +svx/source/inc/StylesPreviewWindow.hxx:63 + StyleItemController m_GlyphsCache class SalLayoutGlyphsCache +svx/source/inc/svdpdf.hxx:61 + ImpSdrPdfImport maDash class XDash +sw/inc/acmplwrd.hxx:42 + SwAutoCompleteWord m_LookupTree editeng::Trie +sw/inc/breakit.hxx:38 + SwBreakIt m_xLanguageTag std::unique_ptr +sw/inc/dpage.hxx:35 + SwDPage m_pGridLst std::unique_ptr +sw/inc/hints.hxx:290 + SwAttrSetChg m_bDelSet _Bool +sw/inc/shellio.hxx:152 + SwReader mpStg tools::SvRef +sw/inc/swevent.hxx:71 + SwCallMouseEvent::(anonymous union)::(anonymous) pFormat const class SwFrameFormat * +sw/source/core/access/accfrmobjmap.hxx:100 + SwAccessibleChildMap maMap std::map +sw/source/core/access/acchypertextdata.hxx:40 + SwAccessibleHyperTextData maMap std::map +sw/source/core/access/accmap.cxx:95 + SwAccessibleContextMap_Impl maMap std::map +sw/source/core/access/accmap.cxx:263 + SwAccessibleShapeMap_Impl maMap std::map +sw/source/core/access/accmap.cxx:619 + SwAccessibleEventMap_Impl maMap std::map +sw/source/core/access/accmap.cxx:663 + SwAccessibleSelectedParas_Impl maMap std::map +sw/source/core/doc/swstylemanager.cxx:60 + (anonymous namespace)::SwStyleManager m_aAutoCharPool class StylePool +sw/source/core/doc/swstylemanager.cxx:61 + (anonymous namespace)::SwStyleManager m_aAutoParaPool class StylePool +sw/source/core/inc/swblocks.hxx:69 + SwImpBlocks m_bInPutMuchBlocks _Bool +sw/source/core/text/atrhndl.hxx:47 + SwAttrHandler m_oFnt std::optional +sw/source/core/text/inftxt.cxx:533 + (anonymous namespace)::SwTransparentTextGuard m_aContentVDev ScopedVclPtrInstance +sw/source/core/text/redlnitr.hxx:75 + SwRedlineItr m_pSet std::unique_ptr +sw/source/filter/html/htmltab.cxx:2839 + CellSaveStruct m_xCnts std::shared_ptr +sw/source/filter/inc/rtf.hxx:33 + RTFSurround::(anonymous) nVal sal_uInt8 +sw/source/ui/dbui/dbinsdlg.cxx:103 + DB_Column::(anonymous) pText rtl::OUString * +sw/source/ui/dbui/dbinsdlg.cxx:105 + DB_Column::(anonymous) nFormat sal_uInt32 +sw/source/uibase/dbui/mmconfigitem.cxx:113 + SwMailMergeConfigItem_Impl m_aFemaleGreetingLines std::vector +sw/source/uibase/dbui/mmconfigitem.cxx:115 + SwMailMergeConfigItem_Impl m_aMaleGreetingLines std::vector +sw/source/uibase/dbui/mmconfigitem.cxx:117 + SwMailMergeConfigItem_Impl m_aNeutralGreetingLines std::vector +sw/source/uibase/inc/fldmgr.hxx:78 + SwInsertField_Data m_aDBDataSource css::uno::Any +toolkit/source/awt/vclxtoolkit.cxx:438 + (anonymous namespace)::VCLXToolkit mxSelection css::uno::Reference +ucb/source/ucp/gio/gio_mount.hxx:73 + OOoMountOperationClass parent_class GMountOperationClass +ucb/source/ucp/gio/gio_mount.hxx:76 + OOoMountOperationClass _gtk_reserved1 void (*)(void) +ucb/source/ucp/gio/gio_mount.hxx:77 + OOoMountOperationClass _gtk_reserved2 void (*)(void) +ucb/source/ucp/gio/gio_mount.hxx:78 + OOoMountOperationClass _gtk_reserved3 void (*)(void) +ucb/source/ucp/gio/gio_mount.hxx:79 + OOoMountOperationClass _gtk_reserved4 void (*)(void) +ucb/source/ucp/package/pkgprovider.hxx:50 + package_ucp::ContentProvider m_pPackages std::unique_ptr +ucb/source/ucp/webdav-curl/CurlSession.cxx:127 + (anonymous namespace)::CurlOption::(anonymous) pValue const void *const +ucbhelper/source/client/proxydecider.cxx:131 + ucbhelper::proxydecider_impl::InternetProxyDecider_Impl m_aEmptyProxy const struct ucbhelper::InternetProxyServer +ucbhelper/source/provider/propertyvalueset.cxx:88 + ucbhelper_impl::PropertyValue aString rtl::OUString +ucbhelper/source/provider/propertyvalueset.cxx:89 + ucbhelper_impl::PropertyValue bBoolean _Bool +ucbhelper/source/provider/propertyvalueset.cxx:90 + ucbhelper_impl::PropertyValue nByte sal_Int8 +ucbhelper/source/provider/propertyvalueset.cxx:91 + ucbhelper_impl::PropertyValue nShort sal_Int16 +ucbhelper/source/provider/propertyvalueset.cxx:92 + ucbhelper_impl::PropertyValue nInt sal_Int32 +ucbhelper/source/provider/propertyvalueset.cxx:93 + ucbhelper_impl::PropertyValue nLong sal_Int64 +ucbhelper/source/provider/propertyvalueset.cxx:97 + ucbhelper_impl::PropertyValue aBytes Sequence +ucbhelper/source/provider/propertyvalueset.cxx:98 + ucbhelper_impl::PropertyValue aDate struct com::sun::star::util::Date +ucbhelper/source/provider/propertyvalueset.cxx:99 + ucbhelper_impl::PropertyValue aTime struct com::sun::star::util::Time +ucbhelper/source/provider/propertyvalueset.cxx:100 + ucbhelper_impl::PropertyValue aTimestamp struct com::sun::star::util::DateTime +ucbhelper/source/provider/propertyvalueset.cxx:101 + ucbhelper_impl::PropertyValue xBinaryStream Reference +ucbhelper/source/provider/propertyvalueset.cxx:102 + ucbhelper_impl::PropertyValue xCharacterStream Reference +ucbhelper/source/provider/propertyvalueset.cxx:103 + ucbhelper_impl::PropertyValue xRef Reference +ucbhelper/source/provider/propertyvalueset.cxx:104 + ucbhelper_impl::PropertyValue xBlob Reference +ucbhelper/source/provider/propertyvalueset.cxx:105 + ucbhelper_impl::PropertyValue xClob Reference +ucbhelper/source/provider/propertyvalueset.cxx:106 + ucbhelper_impl::PropertyValue xArray Reference +unoidl/source/sourceprovider-scanner.hxx:146 + unoidl::detail::SourceProviderInterfaceTypeEntityPad directMandatoryBases std::vector +unoidl/source/sourceprovider-scanner.hxx:147 + unoidl::detail::SourceProviderInterfaceTypeEntityPad directOptionalBases std::vector +unoidl/source/unoidl-read.cxx:148 + (anonymous namespace)::Entity dependencies std::set +unoidl/source/unoidl-read.cxx:149 + (anonymous namespace)::Entity interfaceDependencies std::set +unoidl/source/unoidlprovider.cxx:87 + unoidl::detail::(anonymous namespace)::Memory16 byte unsigned char[2] +unoidl/source/unoidlprovider.cxx:97 + unoidl::detail::(anonymous namespace)::Memory32 byte unsigned char[4] +unoidl/source/unoidlprovider.cxx:128 + unoidl::detail::(anonymous namespace)::Memory64 byte unsigned char[8] +unoidl/source/unoidlprovider.cxx:456 + unoidl::detail::MapEntry name struct unoidl::detail::(anonymous namespace)::Memory32 +unoidl/source/unoidlprovider.cxx:457 + unoidl::detail::MapEntry data struct unoidl::detail::(anonymous namespace)::Memory32 +unotools/source/config/pathoptions.cxx:84 + SvtPathOptions_Impl m_aEmptyString rtl::OUString +vcl/inc/bitmap/BitmapFastScaleFilter.hxx:31 + BitmapFastScaleFilter maSize class Size +vcl/inc/ppdparser.hxx:131 + psp::PPDParser::PPDConstraint m_pKey1 const class psp::PPDKey * +vcl/inc/printerinfomanager.hxx:75 + psp::PrinterInfoManager::SystemPrintQueue m_aComment rtl::OUString +vcl/inc/qt5/QtFrame.hxx:73 + QtFrame m_pQWidget class QWidget * +vcl/inc/qt5/QtFrame.hxx:74 + QtFrame m_pTopLevel class QtMainWindow * +vcl/inc/qt5/QtFrame.hxx:78 + QtFrame m_pQtGraphics std::unique_ptr +vcl/inc/qt5/QtFrame.hxx:80 + QtFrame m_pSvpGraphics std::unique_ptr +vcl/inc/qt5/QtFrame.hxx:82 + QtFrame m_aRegion class QRegion +vcl/inc/qt5/QtFrame.hxx:86 + QtFrame m_nStyle enum SalFrameStyleFlags +vcl/inc/qt5/QtMenu.hxx:42 + QtMenu maItems std::vector +vcl/inc/qt5/QtObject.hxx:38 + QtObject m_pQWidget class QWidget * +vcl/inc/qt5/QtObject.hxx:39 + QtObject m_pQWindow class QWindow * +vcl/inc/qt5/QtTimer.hxx:29 + QtTimer m_aTimer class QTimer +vcl/inc/salinst.hxx:83 + SalInstance m_bSupportsBitmap32 _Bool +vcl/inc/salwtype.hxx:164 + SalWheelMouseEvent mbDeltaIsPixel _Bool +vcl/inc/salwtype.hxx:217 + SalQueryCharPositionEvent mnCharPos sal_uLong +vcl/inc/svdata.hxx:323 + ImplSVNWFData mbMenuBarDockingAreaCommonBG _Bool +vcl/inc/toolbox.h:108 + vcl::ToolBoxLayoutData m_aLineItemIds std::vector +vcl/inc/unx/saldisp.hxx:282 + SalDisplay m_aInvalidScreenData struct SalDisplay::ScreenData +vcl/inc/widgetdraw/WidgetDefinition.hxx:226 + vcl::WidgetDefinitionStyle maDefaultButtonTextColor class Color +vcl/inc/widgetdraw/WidgetDefinition.hxx:230 + vcl::WidgetDefinitionStyle maFlatButtonTextColor class Color +vcl/inc/widgetdraw/WidgetDefinition.hxx:231 + vcl::WidgetDefinitionStyle maDefaultButtonRolloverTextColor class Color +vcl/inc/widgetdraw/WidgetDefinition.hxx:233 + vcl::WidgetDefinitionStyle maDefaultActionButtonRolloverTextColor class Color +vcl/inc/widgetdraw/WidgetDefinition.hxx:235 + vcl::WidgetDefinitionStyle maFlatButtonRolloverTextColor class Color +vcl/inc/widgetdraw/WidgetDefinition.hxx:236 + vcl::WidgetDefinitionStyle maDefaultButtonPressedRolloverTextColor class Color +vcl/inc/widgetdraw/WidgetDefinition.hxx:237 + vcl::WidgetDefinitionStyle maButtonPressedRolloverTextColor class Color +vcl/inc/widgetdraw/WidgetDefinition.hxx:238 + vcl::WidgetDefinitionStyle maDefaultActionButtonPressedRolloverTextColor class Color +vcl/inc/widgetdraw/WidgetDefinition.hxx:239 + vcl::WidgetDefinitionStyle maActionButtonPressedRolloverTextColor class Color +vcl/inc/widgetdraw/WidgetDefinition.hxx:240 + vcl::WidgetDefinitionStyle maFlatButtonPressedRolloverTextColor class Color +vcl/source/app/settings.cxx:195 + ImplStyleData maDialogStyle struct DialogStyle +vcl/source/bitmap/dibtools.cxx:52 + (anonymous namespace)::CIEXYZ aXyzX FXPT2DOT30 +vcl/source/bitmap/dibtools.cxx:53 + (anonymous namespace)::CIEXYZ aXyzY FXPT2DOT30 +vcl/source/bitmap/dibtools.cxx:54 + (anonymous namespace)::CIEXYZ aXyzZ FXPT2DOT30 +vcl/source/bitmap/dibtools.cxx:65 + (anonymous namespace)::CIEXYZTriple aXyzRed struct (anonymous namespace)::CIEXYZ +vcl/source/bitmap/dibtools.cxx:66 + (anonymous namespace)::CIEXYZTriple aXyzGreen struct (anonymous namespace)::CIEXYZ +vcl/source/bitmap/dibtools.cxx:67 + (anonymous namespace)::CIEXYZTriple aXyzBlue struct (anonymous namespace)::CIEXYZ +vcl/source/bitmap/dibtools.cxx:107 + (anonymous namespace)::DIBV5Header nV5AlphaMask sal_uInt32 +vcl/source/bitmap/dibtools.cxx:109 + (anonymous namespace)::DIBV5Header aV5Endpoints struct (anonymous namespace)::CIEXYZTriple +vcl/source/bitmap/dibtools.cxx:110 + (anonymous namespace)::DIBV5Header nV5GammaRed sal_uInt32 +vcl/source/bitmap/dibtools.cxx:111 + (anonymous namespace)::DIBV5Header nV5GammaGreen sal_uInt32 +vcl/source/bitmap/dibtools.cxx:112 + (anonymous namespace)::DIBV5Header nV5GammaBlue sal_uInt32 +vcl/source/bitmap/dibtools.cxx:114 + (anonymous namespace)::DIBV5Header nV5ProfileData sal_uInt32 +vcl/source/bitmap/dibtools.cxx:115 + (anonymous namespace)::DIBV5Header nV5ProfileSize sal_uInt32 +vcl/source/bitmap/dibtools.cxx:116 + (anonymous namespace)::DIBV5Header nV5Reserved sal_uInt32 +vcl/source/control/roadmapwizard.cxx:63 + vcl::RoadmapWizardImpl aStateDescriptors vcl::(anonymous namespace)::StateDescriptions +vcl/source/control/tabctrl.cxx:81 + ImplTabCtrlData maLayoutPageIdToLine std::unordered_map +vcl/source/filter/eps/eps.cxx:115 + (anonymous namespace)::PSWriter pVDev ScopedVclPtrInstance +vcl/source/filter/idxf/dxf2mtf.hxx:54 + DXF2GDIMetaFile aDefaultLineInfo const class LineInfo +vcl/source/filter/idxf/dxfreprd.hxx:75 + DXFRepresentation aPalette class DXFPalette +vcl/source/filter/iras/iras.cxx:56 + (anonymous namespace)::RASReader mnRepCount sal_uInt8 +vcl/source/filter/itga/itga.cxx:55 + (anonymous namespace)::TGAFileFooter nSignature sal_uInt32[4] +vcl/source/filter/jpeg/Exif.hxx:54 + Exif::ExifIFD tag sal_uInt8[2] +vcl/source/filter/jpeg/Exif.hxx:55 + Exif::ExifIFD type sal_uInt8[2] +vcl/source/filter/jpeg/Exif.hxx:56 + Exif::ExifIFD count sal_uInt8[4] +vcl/source/filter/jpeg/Exif.hxx:61 + Exif::TiffHeader byteOrder sal_uInt16 +vcl/source/filter/jpeg/transupp.h:132 + (anonymous) slow_hflip boolean +vcl/source/filter/jpeg/transupp.h:144 + (anonymous) crop_width_set JCROP_CODE +vcl/source/filter/jpeg/transupp.h:146 + (anonymous) crop_height_set JCROP_CODE +vcl/source/filter/jpeg/transupp.h:148 + (anonymous) crop_xoffset_set JCROP_CODE +vcl/source/filter/jpeg/transupp.h:150 + (anonymous) crop_yoffset_set JCROP_CODE +vcl/source/treelist/headbar.cxx:41 + ImplHeadItem maHelpId rtl::OString +vcl/source/treelist/headbar.cxx:42 + ImplHeadItem maImage class Image +vcl/unx/gtk3/a11y/atkwrapper.hxx:50 + AtkObjectWrapper aParent AtkObject +vcl/unx/gtk3/a11y/atkwrapper.hxx:79 + AtkObjectWrapperClass aParentClass GtkWidgetAccessibleClass +vcl/unx/gtk3/glomenu.cxx:14 + GLOMenu parent_instance const GMenuModel +writerfilter/source/ooxml/OOXMLFactory.hxx:57 + writerfilter::ooxml::AttributeInfo m_nToken writerfilter::Token_t +writerfilter/source/ooxml/OOXMLFactory.hxx:58 + writerfilter::ooxml::AttributeInfo m_nResource enum writerfilter::ooxml::ResourceType +writerfilter/source/ooxml/OOXMLFactory.hxx:59 + writerfilter::ooxml::AttributeInfo m_nRef Id +xmloff/inc/MultiPropertySetHelper.hxx:85 + MultiPropertySetHelper aEmptyAny css::uno::Any +xmloff/source/chart/SchXMLChartContext.cxx:443 + (anonymous namespace)::NewDonutSeries msStyleName rtl::OUString +xmloff/source/chart/SchXMLChartContext.hxx:51 + SeriesDefaultsAndStyles maErrorIndicatorDefault css::uno::Any +xmloff/source/chart/SchXMLChartContext.hxx:52 + SeriesDefaultsAndStyles maErrorCategoryDefault css::uno::Any +xmloff/source/chart/SchXMLChartContext.hxx:53 + SeriesDefaultsAndStyles maConstantErrorLowDefault css::uno::Any +xmloff/source/chart/SchXMLChartContext.hxx:54 + SeriesDefaultsAndStyles maConstantErrorHighDefault css::uno::Any +xmloff/source/chart/SchXMLChartContext.hxx:55 + SeriesDefaultsAndStyles maPercentageErrorDefault css::uno::Any +xmloff/source/chart/SchXMLChartContext.hxx:56 + SeriesDefaultsAndStyles maErrorMarginDefault css::uno::Any diff --git a/compilerplugins/clang/unusedfields.untouched.results b/compilerplugins/clang/unusedfields.untouched.results new file mode 100644 index 000000000..ad337c610 --- /dev/null +++ b/compilerplugins/clang/unusedfields.untouched.results @@ -0,0 +1,626 @@ +basctl/source/inc/dlged.hxx:121 + basctl::DlgEditor pObjFac std::unique_ptr > +basic/qa/cppunit/basictest.hxx:27 + MacroSnippet maDll class BasicDLL +basic/qa/cppunit/test_global_array.cxx:25 + (anonymous namespace)::GlobalArrayTest lib class BasicDLL +basic/qa/cppunit/test_global_as_new.cxx:25 + (anonymous namespace)::GlobalAsNewTest lib class BasicDLL +canvas/source/vcl/canvasbitmap.hxx:113 + vclcanvas::CanvasBitmap mxDevice css::uno::Reference +canvas/source/vcl/impltools.hxx:114 + vclcanvas::tools::LocalGuard aSolarGuard class SolarMutexGuard +chart2/source/controller/inc/dlg_DataEditor.hxx:55 + chart::DataEditor m_xContext css::uno::Reference +chart2/source/controller/inc/RangeSelectionListener.hxx:65 + chart::RangeSelectionListener m_aControllerLockGuard class chart::ControllerLockGuardUNO +chart2/source/inc/ModifyListenerCallBack.hxx:52 + chart::ModifyListenerCallBack m_xModifyListener css::uno::Reference +comphelper/source/container/enumerablemap.cxx:297 + comphelper::(anonymous namespace)::MapEnumeration m_xKeepMapAlive Reference +connectivity/source/drivers/evoab2/EApi.h:121 + (anonymous) address_format char * +connectivity/source/drivers/evoab2/EApi.h:125 + (anonymous) ext char * +connectivity/source/drivers/mysqlc/mysqlc_user.hxx:22 + connectivity::mysqlc::User m_xConnection css::uno::Reference +connectivity/source/drivers/mysqlc/mysqlc_view.hxx:65 + connectivity::mysqlc::View m_xConnection css::uno::Reference +connectivity/source/drivers/postgresql/pq_statics.hxx:104 + pq_sdbc_driver::ImplementationStatics types css::uno::Sequence +cppu/source/threadpool/threadpool.cxx:352 + _uno_ThreadPool dummy sal_Int32 +cppu/source/typelib/typelib.cxx:56 + (anonymous namespace)::AlignSize_Impl nInt16 sal_Int16 +cui/source/inc/AdditionsDialog.hxx:47 + AdditionInfo sReleaseVersion rtl::OUString +cui/source/inc/cuitabarea.hxx:645 + SvxColorTabPage m_context css::uno::Reference +dbaccess/source/core/inc/databasecontext.hxx:84 + dbaccess::ODatabaseContext m_aBasicDLL class BasicDLL +dbaccess/source/sdbtools/inc/connectiondependent.hxx:115 + sdbtools::ConnectionDependentComponent::EntryGuard m_aMutexGuard ::osl::MutexGuard +embeddedobj/source/msole/olecomponent.hxx:50 + OleComponent m_aMutex ::osl::Mutex +embeddedobj/source/msole/olecomponent.hxx:51 + OleComponent m_pInterfaceContainer comphelper::OMultiTypeInterfaceContainerHelper2 * +embeddedobj/source/msole/olecomponent.hxx:53 + OleComponent m_bDisposed _Bool +embeddedobj/source/msole/olecomponent.hxx:54 + OleComponent m_bModified _Bool +embeddedobj/source/msole/olecomponent.hxx:55 + OleComponent m_pNativeImpl struct OleComponentNative_Impl * +embeddedobj/source/msole/olecomponent.hxx:57 + OleComponent m_pUnoOleObject class OleEmbeddedObject * +embeddedobj/source/msole/olecomponent.hxx:58 + OleComponent m_pOleWrapClientSite class OleWrapperClientSite * +embeddedobj/source/msole/olecomponent.hxx:59 + OleComponent m_pImplAdviseSink class OleWrapperAdviseSink * +embeddedobj/source/msole/olecomponent.hxx:61 + OleComponent m_nOLEMiscFlags sal_Int32 +embeddedobj/source/msole/olecomponent.hxx:62 + OleComponent m_nAdvConn sal_Int32 +embeddedobj/source/msole/olecomponent.hxx:64 + OleComponent m_aVerbList css::uno::Sequence +embeddedobj/source/msole/olecomponent.hxx:65 + OleComponent m_aDataFlavors css::uno::Sequence +embeddedobj/source/msole/olecomponent.hxx:67 + OleComponent m_xContext css::uno::Reference +embeddedobj/source/msole/olecomponent.hxx:69 + OleComponent m_bOleInitialized _Bool +emfio/source/emfuno/xemfparser.cxx:48 + emfio::emfreader::(anonymous namespace)::XEmfParser context_ uno::Reference +extensions/source/scanner/scanner.hxx:43 + ScannerManager maProtector osl::Mutex +helpcompiler/inc/HelpCompiler.hxx:201 + HelpCompiler lang const std::string +include/basegfx/DrawCommands.hxx:142 + gfx::DrawPath mpFillGradient std::shared_ptr +include/comphelper/interfacecontainer3.hxx:328 + const css::uno::Reference & +include/cui/cuicharmap.hxx:90 + SvxCharacterMap mxContext uno::Reference +include/drawinglayer/primitive2d/textlayoutdevice.hxx:64 + drawinglayer::primitive2d::TextLayouterDevice maSolarGuard class SolarMutexGuard +include/editeng/unotext.hxx:608 + SvxUnoTextRangeEnumeration mxParentText css::uno::Reference +include/LibreOfficeKit/LibreOfficeKitGtk.h:33 + _LOKDocView aDrawingArea GtkDrawingArea +include/LibreOfficeKit/LibreOfficeKitGtk.h:38 + _LOKDocViewClass parent_class GtkDrawingAreaClass +include/oox/vml/vmlshapecontext.hxx:115 + oox::vml::ShapeTypeContext m_pShapeType std::shared_ptr +include/registry/registry.hxx:34 + Registry_Api acquire void (*)(RegHandle) +include/sfx2/msg.hxx:117 + SfxType0 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:119 + SfxType0 nAttribs sal_uInt16 +include/sfx2/msg.hxx:132 + SfxType1 aAttrib struct SfxTypeAttrib[1] +include/sfx2/msg.hxx:132 + SfxType1 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:132 + SfxType1 nAttribs sal_uInt16 +include/sfx2/msg.hxx:132 + SfxType1 pType const std::type_info * +include/sfx2/msg.hxx:133 + SfxType2 aAttrib struct SfxTypeAttrib[2] +include/sfx2/msg.hxx:133 + SfxType2 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:133 + SfxType2 nAttribs sal_uInt16 +include/sfx2/msg.hxx:133 + SfxType2 pType const std::type_info * +include/sfx2/msg.hxx:134 + SfxType3 aAttrib struct SfxTypeAttrib[3] +include/sfx2/msg.hxx:134 + SfxType3 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:134 + SfxType3 nAttribs sal_uInt16 +include/sfx2/msg.hxx:134 + SfxType3 pType const std::type_info * +include/sfx2/msg.hxx:135 + SfxType4 aAttrib struct SfxTypeAttrib[4] +include/sfx2/msg.hxx:135 + SfxType4 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:135 + SfxType4 nAttribs sal_uInt16 +include/sfx2/msg.hxx:135 + SfxType4 pType const std::type_info * +include/sfx2/msg.hxx:136 + SfxType5 aAttrib struct SfxTypeAttrib[5] +include/sfx2/msg.hxx:136 + SfxType5 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:136 + SfxType5 nAttribs sal_uInt16 +include/sfx2/msg.hxx:136 + SfxType5 pType const std::type_info * +include/sfx2/msg.hxx:137 + SfxType6 aAttrib struct SfxTypeAttrib[6] +include/sfx2/msg.hxx:137 + SfxType6 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:137 + SfxType6 nAttribs sal_uInt16 +include/sfx2/msg.hxx:137 + SfxType6 pType const std::type_info * +include/sfx2/msg.hxx:138 + SfxType7 aAttrib struct SfxTypeAttrib[7] +include/sfx2/msg.hxx:138 + SfxType7 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:138 + SfxType7 nAttribs sal_uInt16 +include/sfx2/msg.hxx:138 + SfxType7 pType const std::type_info * +include/sfx2/msg.hxx:139 + SfxType8 aAttrib struct SfxTypeAttrib[8] +include/sfx2/msg.hxx:139 + SfxType8 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:139 + SfxType8 nAttribs sal_uInt16 +include/sfx2/msg.hxx:139 + SfxType8 pType const std::type_info * +include/sfx2/msg.hxx:140 + SfxType10 aAttrib struct SfxTypeAttrib[10] +include/sfx2/msg.hxx:140 + SfxType10 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:140 + SfxType10 nAttribs sal_uInt16 +include/sfx2/msg.hxx:140 + SfxType10 pType const std::type_info * +include/sfx2/msg.hxx:141 + SfxType11 aAttrib struct SfxTypeAttrib[11] +include/sfx2/msg.hxx:141 + SfxType11 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:141 + SfxType11 nAttribs sal_uInt16 +include/sfx2/msg.hxx:141 + SfxType11 pType const std::type_info * +include/sfx2/msg.hxx:143 + SfxType13 aAttrib struct SfxTypeAttrib[13] +include/sfx2/msg.hxx:143 + SfxType13 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:143 + SfxType13 nAttribs sal_uInt16 +include/sfx2/msg.hxx:143 + SfxType13 pType const std::type_info * +include/sfx2/msg.hxx:144 + SfxType14 aAttrib struct SfxTypeAttrib[14] +include/sfx2/msg.hxx:144 + SfxType14 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:144 + SfxType14 nAttribs sal_uInt16 +include/sfx2/msg.hxx:144 + SfxType14 pType const std::type_info * +include/sfx2/msg.hxx:145 + SfxType16 aAttrib struct SfxTypeAttrib[16] +include/sfx2/msg.hxx:145 + SfxType16 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:145 + SfxType16 nAttribs sal_uInt16 +include/sfx2/msg.hxx:145 + SfxType16 pType const std::type_info * +include/sfx2/msg.hxx:146 + SfxType17 aAttrib struct SfxTypeAttrib[17] +include/sfx2/msg.hxx:146 + SfxType17 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:146 + SfxType17 nAttribs sal_uInt16 +include/sfx2/msg.hxx:146 + SfxType17 pType const std::type_info * +include/sfx2/msg.hxx:147 + SfxType23 aAttrib struct SfxTypeAttrib[23] +include/sfx2/msg.hxx:147 + SfxType23 createSfxPoolItemFunc std::function +include/sfx2/msg.hxx:147 + SfxType23 nAttribs sal_uInt16 +include/sfx2/msg.hxx:147 + SfxType23 pType const std::type_info * +include/sfx2/templdlg.hxx:41 + SfxTemplatePanelControl pImpl std::unique_ptr +include/svtools/genericunodialog.hxx:154 + svt::UnoDialogEntryGuard m_aGuard ::osl::MutexGuard +include/svtools/unoevent.hxx:162 + SvEventDescriptor xParentRef css::uno::Reference +include/svx/imapdlg.hxx:91 + SvxIMapDlg aIMapItem class SvxIMapDlgItem +include/unotest/macros_test.hxx:104 + unotest::MacrosTest mpDll std::unique_ptr +include/vcl/commandevent.hxx:310 + CommandGestureData mfX const double +include/vcl/commandevent.hxx:311 + CommandGestureData mfY const double +include/vcl/commandevent.hxx:314 + CommandGestureData meOrientation const enum PanningOrientation +include/vcl/filter/PngImageReader.hxx:35 + vcl::PngImageReader mxStatusIndicator css::uno::Reference +include/vcl/pdf/PDFAnnotationMarker.hxx:67 + vcl::pdf::PDFAnnotationMarkerHighlight meTextMarkerType enum vcl::pdf::PDFTextMarkerType +include/vcl/uitest/uiobject.hxx:287 + TabPageUIObject mxTabPage VclPtr +include/xmloff/formlayerexport.hxx:172 + xmloff::OOfficeFormsExport m_pImpl std::unique_ptr +libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx:51 + GtvApplicationWindow parent_instance GtkApplicationWindow +libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx:55 + GtvApplicationWindow doctype LibreOfficeKitDocumentType +libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx:74 + GtvApplicationWindowClass parentClass GtkApplicationWindowClass +libreofficekit/qa/gtktiledviewer/gtv-application.hxx:26 + GtvApplication parent GtkApplication +libreofficekit/qa/gtktiledviewer/gtv-application.hxx:31 + GtvApplicationClass parentClass GtkApplicationClass +libreofficekit/qa/gtktiledviewer/gtv-calc-header-bar.hxx:28 + GtvCalcHeaderBar parent GtkDrawingArea +libreofficekit/qa/gtktiledviewer/gtv-calc-header-bar.hxx:37 + GtvCalcHeaderBarClass parentClass GtkDrawingAreaClass +libreofficekit/qa/gtktiledviewer/gtv-comments-sidebar.hxx:26 + GtvCommentsSidebar parent GtkBox +libreofficekit/qa/gtktiledviewer/gtv-comments-sidebar.hxx:35 + GtvCommentsSidebarClass parentClass GtkBoxClass +libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx:28 + GtvLokDialog parent GtkDialog +libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx:33 + GtvLokDialogClass parentClass GtkDialogClass +libreofficekit/qa/gtktiledviewer/gtv-main-toolbar.hxx:28 + GtvMainToolbar parent GtkBox +libreofficekit/qa/gtktiledviewer/gtv-main-toolbar.hxx:36 + GtvMainToolbarClass parentClass GtkBoxClass +lingucomponent/source/languageguessing/simpleguesser.cxx:75 + (anonymous namespace)::textcat_t maxsize uint4 +lingucomponent/source/languageguessing/simpleguesser.cxx:77 + (anonymous namespace)::textcat_t output char[1024] +lotuswordpro/source/filter/clone.hxx:23 + detail::has_clone::(anonymous) a char[2] +pyuno/source/module/pyuno_callable.cxx:45 + pyuno::(anonymous namespace)::PyUNO_callable ob_base PyObject +pyuno/source/module/pyuno_impl.hxx:138 + pyuno::(anonymous) ob_base PyObject +pyuno/source/module/pyuno_impl.hxx:238 + pyuno::stRuntimeImpl ob_base PyObject +reportdesign/source/ui/inc/ReportWindow.hxx:52 + rptui::OReportWindow m_pObjFac std::unique_ptr > +sal/qa/osl/condition/osl_Condition.cxx:72 + osl_Condition::ctors bRes1 _Bool +sal/qa/osl/condition/osl_Condition.cxx:202 + osl_Condition::wait bRes2 _Bool +sal/qa/osl/condition/osl_Condition.cxx:273 + osl_Condition::check bRes2 _Bool +sal/qa/osl/file/osl_File.cxx:1387 + osl_FileStatus::isValid rItem_link class osl::DirectoryItem +sal/qa/osl/file/osl_File.cxx:1564 + osl_FileStatus::getFileType m_aFifoItem class osl::DirectoryItem +sal/qa/osl/file/osl_File.cxx:1564 + osl_FileStatus::getFileType m_aVolumeItem class osl::DirectoryItem +sal/qa/osl/file/osl_File.cxx:1565 + osl_FileStatus::getFileType m_aLinkItem class osl::DirectoryItem +sal/qa/osl/file/osl_File.cxx:1565 + osl_FileStatus::getFileType m_aSocketItem class osl::DirectoryItem +sal/qa/osl/file/osl_File.cxx:1565 + osl_FileStatus::getFileType m_aSpecialItem class osl::DirectoryItem +sal/qa/osl/file/osl_File.cxx:2039 + osl_FileStatus::getLinkTargetURL rItem class osl::DirectoryItem +sal/qa/osl/module/osl_Module.cxx:70 + osl_Module::ctors bRes1 _Bool +sal/qa/osl/module/osl_Module.cxx:114 + osl_Module::getUrlFromAddress bRes1 _Bool +sal/qa/osl/module/osl_Module.cxx:174 + osl_Module::load bRes1 _Bool +sal/qa/osl/module/osl_Module.cxx:201 + osl_Module::unload bRes1 _Bool +sal/qa/osl/module/osl_Module.cxx:342 + osl_Module::getFunctionSymbol bRes1 _Bool +sal/qa/osl/pipe/osl_Pipe.cxx:358 + osl_Pipe::clear bRes1 _Bool +sal/qa/osl/pipe/osl_Pipe.cxx:523 + osl_Pipe::getError bRes _Bool +sal/qa/osl/pipe/osl_Pipe.cxx:523 + osl_Pipe::getError bRes1 _Bool +sal/qa/osl/pipe/osl_Pipe.cxx:561 + osl_Pipe::getHandle bRes1 _Bool +sal/qa/osl/pipe/osl_Pipe.cxx:848 + osl_StreamPipe::recv bRes _Bool +sal/qa/osl/pipe/osl_Pipe.cxx:848 + osl_StreamPipe::recv bRes1 _Bool +sal/qa/osl/security/osl_Security.cxx:59 + osl_Security::ctors bRes _Bool +sal/qa/osl/security/osl_Security.cxx:59 + osl_Security::ctors bRes1 _Bool +sal/qa/osl/security/osl_Security.cxx:124 + osl_Security::getUserIdent bRes1 _Bool +sal/qa/osl/security/osl_Security.cxx:154 + osl_Security::getUserName bRes1 _Bool +sal/qa/osl/security/osl_Security.cxx:188 + osl_Security::getConfigDir bRes1 _Bool +sc/inc/editutil.hxx:111 + ScEnginePoolHelper pEnginePool rtl::Reference +sc/inc/editutil.hxx:113 + ScEnginePoolHelper bDeleteEnginePool _Bool +sc/qa/extras/scpdfexport.cxx:44 + ScPDFExportTest xTargetFrame Reference +sc/source/core/data/document.cxx:1236 + (anonymous namespace)::BroadcastRecalcOnRefMoveGuard aSwitch sc::AutoCalcSwitch +sc/source/core/data/document.cxx:1237 + (anonymous namespace)::BroadcastRecalcOnRefMoveGuard aBulk class ScBulkBroadcast +sc/source/filter/inc/sheetdatacontext.hxx:50 + oox::xls::SheetDataContext aReleaser class SolarMutexReleaser +sc/source/ui/inc/docsh.hxx:459 + ScDocShellModificator mpProtector std::unique_ptr +sc/source/ui/inc/PivotLayoutTreeListBase.hxx:47 + ScPivotLayoutTreeListBase maDropTargetHelper class ScPivotLayoutTreeDropTarget +sd/source/ui/inc/CustomAnimationList.hxx:127 + sd::CustomAnimationList maDropTargetHelper class sd::CustomAnimationListDropTarget +sd/source/ui/inc/sdtreelb.hxx:72 + SdPageObjsTLV m_xDropTargetHelper std::unique_ptr +sd/source/ui/inc/TableDesignPane.hxx:101 + sd::TableDesignPane m_xImpl std::unique_ptr +sd/source/ui/remotecontrol/ZeroconfService.hxx:32 + sd::ZeroconfService port uint +sd/source/ui/slidesorter/view/SlsLayouter.cxx:62 + sd::slidesorter::view::Layouter::Implementation mpTheme std::shared_ptr +sd/source/ui/view/DocumentRenderer.cxx:1317 + sd::DocumentRenderer::Implementation mxObjectShell SfxObjectShellRef +sd/source/ui/view/viewshel.cxx:1157 + sd::(anonymous namespace)::KeepSlideSorterInSyncWithPageChanges m_aDrawLock sd::slidesorter::view::class SlideSorterView::DrawLock +sd/source/ui/view/viewshel.cxx:1158 + sd::(anonymous namespace)::KeepSlideSorterInSyncWithPageChanges m_aModelLock sd::slidesorter::controller::class SlideSorterController::ModelChangeLock +sd/source/ui/view/viewshel.cxx:1159 + sd::(anonymous namespace)::KeepSlideSorterInSyncWithPageChanges m_aUpdateLock sd::slidesorter::controller::class PageSelector::UpdateLock +sd/source/ui/view/viewshel.cxx:1160 + sd::(anonymous namespace)::KeepSlideSorterInSyncWithPageChanges m_aContext sd::slidesorter::controller::class SelectionObserver::Context +sd/source/ui/view/ViewShellBase.cxx:188 + sd::ViewShellBase::Implementation mpPageCacheManager std::shared_ptr +sdext/source/pdfimport/pdfparse/pdfparse.cxx:266 + (anonymous namespace)::PDFGrammar::definition array rule +sdext/source/pdfimport/pdfparse/pdfparse.cxx:266 + (anonymous namespace)::PDFGrammar::definition value rule +sfx2/inc/autoredactdialog.hxx:99 + SfxAutoRedactDialog m_xDocShell class SfxObjectShellLock +sfx2/source/dialog/basedlgs.cxx:46 + SfxModelessDialog_Impl aMoveIdle class Idle +sfx2/source/doc/doctempl.cxx:105 + DocTempl::(anonymous namespace)::DocTempl_EntryData_Impl mxObjShell class SfxObjectShellLock +sfx2/source/inc/sfxpicklist.hxx:33 + SfxPickList mxImpl std::unique_ptr +sfx2/source/inc/templdgi.hxx:93 + SfxCommonTemplateDialog_Impl m_aStyleListUpdateFamily Link +slideshow/source/engine/opengl/TransitionImpl.cxx:1991 + (anonymous namespace)::ThreeFloats x GLfloat +slideshow/source/engine/opengl/TransitionImpl.cxx:1991 + (anonymous namespace)::ThreeFloats y GLfloat +slideshow/source/engine/opengl/TransitionImpl.cxx:1991 + (anonymous namespace)::ThreeFloats z GLfloat +starmath/inc/mathml/mathmlMo.hxx:63 + moOperatorData m_motxt rtl::OUString +starmath/inc/mathml/mathmlMo.hxx:64 + moOperatorData m_form enum moOpDF +starmath/inc/mathml/mathmlMo.hxx:65 + moOperatorData m_priority sal_uInt16 +starmath/inc/mathml/mathmlMo.hxx:66 + moOperatorData m_lspace sal_uInt16 +starmath/inc/mathml/mathmlMo.hxx:67 + moOperatorData m_rspace sal_uInt16 +starmath/inc/mathml/mathmlMo.hxx:68 + moOperatorData m_properties enum moOpDP +starmath/inc/smmod.hxx:67 + SmModule mpLocSymbolData std::unique_ptr +starmath/inc/view.hxx:246 + SmViewShell maGraphicController class SmGraphicController +svl/source/crypto/cryptosign.cxx:108 + (anonymous namespace)::Extension extnID SECItem +svl/source/crypto/cryptosign.cxx:109 + (anonymous namespace)::Extension critical SECItem +svl/source/crypto/cryptosign.cxx:110 + (anonymous namespace)::Extension extnValue SECItem +svl/source/crypto/cryptosign.cxx:268 + (anonymous namespace)::PKIStatusInfo statusString SECItem +svl/source/crypto/cryptosign.cxx:269 + (anonymous namespace)::PKIStatusInfo failInfo SECItem +svx/source/dialog/contimp.hxx:75 + SvxSuperContourDlg aContourItem class SvxContourDlgItem +svx/source/dialog/weldeditview.cxx:458 + (anonymous namespace)::WeldEditSource m_rEditAcc class WeldEditAccessible & +svx/source/inc/datanavi.hxx:190 + svxform::XFormsPage m_aDropHelper class svxform::DataTreeDropTarget +svx/source/sidebar/fontwork/FontworkPropertyPanel.hxx:41 + svx::sidebar::FontworkPropertyPanel m_xToolbar std::unique_ptr +svx/source/tbxctrls/layctrl.cxx:432 + (anonymous namespace)::ColumnsWindow mxControl rtl::Reference +sw/source/core/crsr/crbm.cxx:62 + (anonymous namespace)::CursorStateHelper m_aSaveState class SwCursorSaveState +sw/source/core/frmedt/fetab.cxx:78 + (anonymous namespace)::TableWait m_pWait const std::unique_ptr +sw/source/core/inc/ftnboss.hxx:34 + SwSaveFootnoteHeight aGuard class SwFrameDeleteGuard +sw/source/core/layout/dbg_lay.cxx:179 + SwImplEnterLeave m_nAction enum DbgAction +sw/source/core/unocore/unolinebreak.cxx:43 + SwXLineBreak::Impl m_rThis class SwXLineBreak & +sw/source/uibase/inc/condedit.hxx:43 + ConditionEdit m_aDropTargetHelper class ConditionEditDropTarget +sw/source/uibase/inc/conttree.hxx:296 + SwGlobalTree m_aDropTargetHelper class SwGlobalTreeDropTarget +sw/source/uibase/inc/swuicnttab.hxx:241 + SwTokenWindow m_aAdjustPositionsIdle class Idle +sw/source/uibase/inc/uivwimp.hxx:93 + SwView_Impl m_xTmpSelDocShell class SfxObjectShellLock +sw/source/uibase/inc/unodispatch.hxx:45 + SwXDispatchProviderInterceptor::DispatchMutexLock_Impl aGuard class SolarMutexGuard +toolkit/source/awt/stylesettings.cxx:74 + toolkit::(anonymous namespace)::StyleMethodGuard m_aGuard class SolarMutexGuard +unoidl/source/unoidlprovider.cxx:673 + unoidl::detail::(anonymous namespace)::UnoidlCursor reference1_ rtl::Reference +unoidl/source/unoidlprovider.cxx:674 + unoidl::detail::(anonymous namespace)::UnoidlCursor reference2_ rtl::Reference +vcl/inc/pdf/pdfbuildin_fonts.hxx:34 + vcl::pdf::BuildinFont m_nAscent const int +vcl/inc/pdf/pdfbuildin_fonts.hxx:35 + vcl::pdf::BuildinFont m_nDescent const int +vcl/inc/pdf/pdfbuildin_fonts.hxx:42 + vcl::pdf::BuildinFont m_aWidths const int[256] +vcl/inc/qt5/QtAccessibleEventListener.hxx:34 + QtAccessibleEventListener m_xAccessible css::uno::Reference +vcl/inc/qt5/QtAccessibleWidget.hxx:153 + QtAccessibleWidget m_xAccessible css::uno::Reference +vcl/inc/qt5/QtAccessibleWidget.hxx:156 + QtAccessibleWidget m_pObject class QObject * +vcl/inc/qt5/QtClipboard.hxx:38 + QtClipboard m_aMutex osl::Mutex +vcl/inc/qt5/QtClipboard.hxx:39 + QtClipboard m_aClipboardName const rtl::OUString +vcl/inc/qt5/QtClipboard.hxx:40 + QtClipboard m_aClipboardMode const class QClipboard::Mode +vcl/inc/qt5/QtClipboard.hxx:43 + QtClipboard m_bOwnClipboardChange _Bool +vcl/inc/qt5/QtClipboard.hxx:45 + QtClipboard m_bDoClear _Bool +vcl/inc/qt5/QtClipboard.hxx:48 + QtClipboard m_aContents css::uno::Reference +vcl/inc/qt5/QtClipboard.hxx:50 + QtClipboard m_aOwner css::uno::Reference +vcl/inc/qt5/QtClipboard.hxx:51 + QtClipboard m_aListeners std::vector > +vcl/inc/qt5/QtFilePicker.hxx:63 + QtFilePicker m_context css::uno::Reference +vcl/inc/qt5/QtFilePicker.hxx:65 + QtFilePicker m_xListener css::uno::Reference +vcl/inc/qt5/QtFilePicker.hxx:66 + QtFilePicker m_xClosedListener css::uno::Reference +vcl/inc/qt5/QtFilePicker.hxx:68 + QtFilePicker m_aHelperMutex osl::Mutex +vcl/inc/qt5/QtFilePicker.hxx:70 + QtFilePicker m_aNamedFilterList class QStringList +vcl/inc/qt5/QtFilePicker.hxx:71 + QtFilePicker m_aTitleToFilterMap QHash +vcl/inc/qt5/QtFilePicker.hxx:73 + QtFilePicker m_aNamedFilterToExtensionMap QHash +vcl/inc/qt5/QtFilePicker.hxx:74 + QtFilePicker m_aCurrentFilter class QString +vcl/inc/qt5/QtFilePicker.hxx:77 + QtFilePicker m_aCustomWidgetsMap QHash +vcl/inc/qt5/QtFilePicker.hxx:79 + QtFilePicker m_bIsFolderPicker const _Bool +vcl/inc/qt5/QtFilePicker.hxx:81 + QtFilePicker m_pParentWidget class QWidget * +vcl/inc/qt5/QtFrame.hxx:85 + QtFrame m_bGraphicsInUse _Bool +vcl/inc/qt5/QtFrame.hxx:87 + QtFrame m_pParent class QtFrame * +vcl/inc/qt5/QtFrame.hxx:88 + QtFrame m_ePointerStyle enum PointerStyle +vcl/inc/qt5/QtFrame.hxx:92 + QtFrame m_pDragSource class QtDragSource * +vcl/inc/qt5/QtFrame.hxx:93 + QtFrame m_pDropTarget class QtDropTarget * +vcl/inc/qt5/QtFrame.hxx:94 + QtFrame m_bInDrag _Bool +vcl/inc/qt5/QtFrame.hxx:96 + QtFrame m_bDefaultSize _Bool +vcl/inc/qt5/QtFrame.hxx:97 + QtFrame m_bDefaultPos _Bool +vcl/inc/qt5/QtFrame.hxx:98 + QtFrame m_bFullScreen _Bool +vcl/inc/qt5/QtFrame.hxx:99 + QtFrame m_bFullScreenSpanAll _Bool +vcl/inc/qt5/QtFrame.hxx:100 + QtFrame m_nRestoreScreen sal_uInt32 +vcl/inc/qt5/QtFrame.hxx:101 + QtFrame m_aRestoreGeometry class QRect +vcl/inc/qt5/QtFrame.hxx:104 + QtFrame m_ScreenSaverInhibitor class ScreenSaverInhibitor +vcl/inc/qt5/QtFrame.hxx:110 + QtFrame m_nInputLanguage LanguageType +vcl/inc/qt5/QtInstance.hxx:56 + QtInstance m_aWaitingYieldCond osl::Condition +vcl/inc/qt5/QtInstance.hxx:58 + QtInstance m_pTimer class QtTimer * +vcl/inc/qt5/QtInstance.hxx:59 + QtInstance m_bSleeping _Bool +vcl/inc/qt5/QtInstance.hxx:60 + QtInstance m_aClipboards std::unordered_map > +vcl/inc/qt5/QtInstance.hxx:62 + QtInstance m_pQApplication std::unique_ptr +vcl/inc/qt5/QtInstance.hxx:63 + QtInstance m_pFakeArgvFreeable std::vector +vcl/inc/qt5/QtInstance.hxx:64 + QtInstance m_pFakeArgv std::unique_ptr +vcl/inc/qt5/QtInstance.hxx:65 + QtInstance m_pFakeArgc std::unique_ptr +vcl/inc/qt5/QtInstance.hxx:67 + QtInstance m_aUpdateStyleTimer class Timer +vcl/inc/qt5/QtInstance.hxx:68 + QtInstance m_bUpdateFonts _Bool +vcl/inc/qt5/QtMainWindow.hxx:31 + QtMainWindow m_rFrame class QtFrame & +vcl/inc/qt5/QtMenu.hxx:44 + QtMenu mpParentSalMenu class QtMenu * +vcl/inc/qt5/QtMenu.hxx:45 + QtMenu mpFrame class QtFrame * +vcl/inc/qt5/QtMenu.hxx:46 + QtMenu mbMenuBar _Bool +vcl/inc/qt5/QtMenu.hxx:47 + QtMenu mpQMenuBar class QMenuBar * +vcl/inc/qt5/QtMenu.hxx:49 + QtMenu mpOwnedQMenu std::unique_ptr +vcl/inc/qt5/QtMenu.hxx:51 + QtMenu mpQMenu class QMenu * +vcl/inc/qt5/QtMenu.hxx:52 + QtMenu mpCloseButton class QPushButton * +vcl/inc/qt5/QtMenu.hxx:53 + QtMenu maCloseButtonConnection struct QMetaObject::Connection +vcl/inc/qt5/QtMenu.hxx:110 + QtMenuItem mpParentMenu class QtMenu * +vcl/inc/qt5/QtMenu.hxx:111 + QtMenuItem mpSubMenu class QtMenu * +vcl/inc/qt5/QtMenu.hxx:112 + QtMenuItem mpAction std::unique_ptr +vcl/inc/qt5/QtMenu.hxx:113 + QtMenuItem mpMenu std::unique_ptr +vcl/inc/qt5/QtMenu.hxx:114 + QtMenuItem mpActionGroup std::shared_ptr +vcl/inc/qt5/QtMenu.hxx:115 + QtMenuItem mnId sal_uInt16 +vcl/inc/qt5/QtMenu.hxx:116 + QtMenuItem mnType enum MenuItemType +vcl/inc/qt5/QtMenu.hxx:117 + QtMenuItem mbVisible _Bool +vcl/inc/qt5/QtMenu.hxx:118 + QtMenuItem mbEnabled _Bool +vcl/inc/qt5/QtMenu.hxx:119 + QtMenuItem maImage class Image +vcl/inc/qt5/QtObject.hxx:40 + QtObject m_pRegion class QRegion +vcl/inc/qt5/QtObject.hxx:67 + QtObjectWindow m_rParent class QtObject & +vcl/inc/qt5/QtWidget.hxx:38 + QtWidget m_bNonEmptyIMPreeditSeen _Bool +vcl/inc/qt5/QtWidget.hxx:39 + QtWidget m_nDeltaX int +vcl/inc/qt5/QtWidget.hxx:40 + QtWidget m_nDeltaY int +vcl/inc/salprn.hxx:45 + SalPrinterQueueInfo mpPortName std::unique_ptr +vcl/source/gdi/jobset.cxx:36 + (anonymous namespace)::ImplOldJobSetupData cDeviceName char[32] +vcl/source/gdi/jobset.cxx:37 + (anonymous namespace)::ImplOldJobSetupData cPortName char[32] +vcl/source/uitest/uno/uitest_uno.cxx:35 + (anonymous namespace)::UITestUnoObj mpUITest std::unique_ptr +vcl/unx/gtk3/a11y/atkhypertext.cxx:31 + (anonymous namespace)::HyperLink atk_hyper_link const AtkHyperlink +vcl/unx/gtk3/customcellrenderer.hxx:19 + _CustomCellRenderer parent GtkCellRendererText +vcl/unx/gtk3/customcellrenderer.hxx:29 + (anonymous) parent_class GtkCellRendererTextClass +vcl/unx/gtk3/gloactiongroup.cxx:27 + (anonymous namespace)::GLOAction parent_instance GObject +vcl/unx/kf5/KF5FilePicker.hxx:33 + KF5FilePicker _layout std::unique_ptr +writerfilter/source/ooxml/OOXMLStreamImpl.hxx:41 + writerfilter::ooxml::OOXMLStreamImpl mxFastParser css::uno::Reference +xmlscript/source/xmldlg_imexp/imp_share.hxx:535 + xmlscript::BulletinBoardElement mxDialogImport rtl::Reference +xmlsecurity/qa/unit/signing/signing2.cxx:42 + SigningTest2 mxSEInitializer uno::Reference +xmlsecurity/qa/unit/signing/signing2.cxx:43 + SigningTest2 mxSecurityContext uno::Reference diff --git a/compilerplugins/clang/unusedfields.writeonly.results b/compilerplugins/clang/unusedfields.writeonly.results new file mode 100644 index 000000000..e61d5edbb --- /dev/null +++ b/compilerplugins/clang/unusedfields.writeonly.results @@ -0,0 +1,1108 @@ +basctl/source/basicide/moduldlg.hxx:134 + basctl::ObjectPage m_xDropTarget std::unique_ptr +basctl/source/inc/basidesh.hxx:87 + basctl::Shell m_aNotifier class basctl::DocumentEventNotifier +basctl/source/inc/bastype2.hxx:182 + basctl::SbTreeListBox m_aNotifier class basctl::DocumentEventNotifier +basctl/source/inc/IDEComboBox.hxx:113 + basctl::DocListenerBox maNotifier class basctl::DocumentEventNotifier +basegfx/source/polygon/b2dpolygontriangulator.cxx:113 + basegfx::(anonymous namespace)::Triangulator maNewEdgeEntries std::vector > +basic/qa/cppunit/test_scanner.cxx:24 + (anonymous namespace)::Symbol line sal_uInt16 +basic/qa/cppunit/test_scanner.cxx:25 + (anonymous namespace)::Symbol col1 sal_uInt16 +basic/source/inc/runtime.hxx:255 + SbiRuntime aRefSaved std::vector +bridges/source/cpp_uno/gcc3_linux_x86-64/callvirtualmethod.cxx:56 + Data pMethod sal_uInt64 +bridges/source/cpp_uno/gcc3_linux_x86-64/callvirtualmethod.cxx:57 + Data pStack sal_uInt64 * +bridges/source/cpp_uno/gcc3_linux_x86-64/callvirtualmethod.cxx:58 + Data nStack sal_uInt32 +bridges/source/cpp_uno/gcc3_linux_x86-64/callvirtualmethod.cxx:59 + Data pGPR sal_uInt64 * +bridges/source/cpp_uno/gcc3_linux_x86-64/callvirtualmethod.cxx:60 + Data pFPR double * +bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx:448 + bridges::cpp_uno::shared::VtableFactory::Slot fn void * +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:130 + __cxxabiv1::__cxa_exception unexpectedHandler void (*)(void) +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:131 + __cxxabiv1::__cxa_exception terminateHandler std::terminate_handler +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:132 + __cxxabiv1::__cxa_exception nextException struct __cxxabiv1::__cxa_exception * +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:133 + __cxxabiv1::__cxa_exception handlerCount int +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:134 + __cxxabiv1::__cxa_exception handlerSwitchValue int +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:135 + __cxxabiv1::__cxa_exception actionRecord const char * +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:136 + __cxxabiv1::__cxa_exception languageSpecificData const char * +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:137 + __cxxabiv1::__cxa_exception catchTemp void * +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:139 + __cxxabiv1::__cxa_exception unwindHeader _Unwind_Exception +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:149 + __cxxabiv1::__cxa_eh_globals uncaughtExceptions unsigned int +bridges/source/jni_uno/jni_java2uno.cxx:151 + jni_uno::(anonymous namespace)::largest n sal_Int64 +bridges/source/jni_uno/jni_java2uno.cxx:152 + jni_uno::(anonymous namespace)::largest d double +bridges/source/jni_uno/jni_java2uno.cxx:153 + jni_uno::(anonymous namespace)::largest p void * +bridges/source/jni_uno/jni_java2uno.cxx:154 + jni_uno::(anonymous namespace)::largest a uno_Any +canvas/inc/rendering/irendermodule.hxx:35 + canvas::Vertex a float +canvas/inc/rendering/irendermodule.hxx:35 + canvas::Vertex b float +canvas/inc/rendering/irendermodule.hxx:35 + canvas::Vertex g float +canvas/inc/rendering/irendermodule.hxx:35 + canvas::Vertex r float +canvas/inc/rendering/irendermodule.hxx:36 + canvas::Vertex u float +canvas/inc/rendering/irendermodule.hxx:36 + canvas::Vertex v float +canvas/inc/rendering/irendermodule.hxx:37 + canvas::Vertex x float +canvas/inc/rendering/irendermodule.hxx:37 + canvas::Vertex y float +canvas/inc/rendering/irendermodule.hxx:37 + canvas::Vertex z float +canvas/source/cairo/cairo_canvasbitmap.hxx:119 + cairocanvas::CanvasBitmap mpBufferCairo ::cairo::CairoSharedPtr +canvas/source/cairo/cairo_spritedevicehelper.hxx:73 + cairocanvas::SpriteDeviceHelper mbFullScreen _Bool +canvas/source/cairo/cairo_spritehelper.hxx:98 + cairocanvas::SpriteHelper mbTextureDirty _Bool +chart2/inc/ChartModel.hxx:149 + chart::ChartModel m_aGraphicObjectVector std::vector +chart2/inc/ChartModel.hxx:480 + chart::ChartModel mnStart sal_Int32 +chart2/inc/ChartModel.hxx:481 + chart::ChartModel mnEnd sal_Int32 +chart2/source/controller/dialogs/DialogModel.cxx:184 + (anonymous namespace)::lcl_RolesWithRangeAppend m_rDestCnt (anonymous namespace)::lcl_RolesWithRangeAppend::tContainerType * +chart2/source/controller/inc/ChartController.hxx:414 + chart::ChartController m_apDropTargetHelper std::unique_ptr +chart2/source/controller/inc/dlg_ChartType_UNO.hxx:62 + chart::ChartTypeUnoDlg m_xChartModel rtl::Reference< ::chart::ChartModel> +chart2/source/controller/inc/dlg_View3D.hxx:53 + chart::View3DDialog m_xIllumination std::unique_ptr +chart2/source/controller/main/ElementSelector.hxx:38 + chart::ListBoxEntryData nHierarchyDepth sal_Int32 +chart2/source/inc/MediaDescriptorHelper.hxx:71 + apphelper::MediaDescriptorHelper ReadOnly _Bool +chart2/source/view/charttypes/PieChart.hxx:127 + chart::PieChart::PieLabelInfo fValue double +codemaker/source/cppumaker/dependencies.hxx:108 + codemaker::cppumaker::Dependencies m_voidDependency _Bool +codemaker/source/javamaker/classfile.cxx:508 + floatBytes float +codemaker/source/javamaker/classfile.cxx:540 + doubleBytes double +comphelper/qa/unit/parallelsorttest.cxx:44 + ParallelSortTest mnThreads size_t +comphelper/source/misc/asyncnotification.cxx:69 + comphelper::EventNotifierImpl pKeepThisAlive std::shared_ptr +configmgr/source/components.cxx:162 + configmgr::Components::WriteThread reference_ rtl::Reference * +connectivity/source/drivers/postgresql/pq_statics.hxx:141 + pq_sdbc_driver::Statics NO_NULLS rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:142 + pq_sdbc_driver::Statics NULABLE rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:143 + pq_sdbc_driver::Statics NULLABLE_UNKNOWN rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:144 + pq_sdbc_driver::Statics SELECT rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:145 + pq_sdbc_driver::Statics UPDATE rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:146 + pq_sdbc_driver::Statics INSERT rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:147 + pq_sdbc_driver::Statics DELETE rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:148 + pq_sdbc_driver::Statics RULE rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:149 + pq_sdbc_driver::Statics REFERENCES rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:150 + pq_sdbc_driver::Statics TRIGGER rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:151 + pq_sdbc_driver::Statics EXECUTE rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:152 + pq_sdbc_driver::Statics USAGE rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:153 + pq_sdbc_driver::Statics CREATE rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:154 + pq_sdbc_driver::Statics TEMPORARY rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:187 + pq_sdbc_driver::Statics KEY_COLUMN rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:193 + pq_sdbc_driver::Statics CURSOR_NAME rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:194 + pq_sdbc_driver::Statics ESCAPE_PROCESSING rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:195 + pq_sdbc_driver::Statics FETCH_DIRECTION rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:196 + pq_sdbc_driver::Statics FETCH_SIZE rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:197 + pq_sdbc_driver::Statics IS_BOOKMARKABLE rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:199 + pq_sdbc_driver::Statics RESULT_SET_TYPE rtl::OUString +connectivity/source/drivers/postgresql/pq_statics.hxx:211 + pq_sdbc_driver::Statics HELP_TEXT rtl::OUString +connectivity/source/inc/calc/CConnection.hxx:51 + connectivity::calc::OCalcConnection::CloseVetoButTerminateListener m_pCloseListener std::unique_ptr +connectivity/source/inc/odbc/OConnection.hxx:53 + connectivity::odbc::OConnection m_sUser rtl::OUString +connectivity/source/inc/odbc/ODatabaseMetaDataResultSet.hxx:70 + connectivity::odbc::ODatabaseMetaDataResultSet m_aStatement css::uno::WeakReferenceHelper +connectivity/source/inc/OTypeInfo.hxx:30 + connectivity::OTypeInfo aTypeName rtl::OUString +connectivity/source/inc/OTypeInfo.hxx:31 + connectivity::OTypeInfo aLocalTypeName rtl::OUString +connectivity/source/inc/OTypeInfo.hxx:33 + connectivity::OTypeInfo nPrecision sal_Int32 +connectivity/source/inc/OTypeInfo.hxx:35 + connectivity::OTypeInfo nMaximumScale sal_Int16 +connectivity/source/inc/OTypeInfo.hxx:37 + connectivity::OTypeInfo nType sal_Int16 +connectivity/source/inc/writer/WConnection.hxx:54 + connectivity::writer::OWriterConnection::CloseVetoButTerminateListener m_pCloseListener std::unique_ptr +cppcanvas/source/inc/implrenderer.hxx:208 + cppcanvas::internal::ImplRenderer aBaseTransform struct cppcanvas::internal::XForm +cppu/source/uno/check.cxx:38 + (anonymous namespace)::C1 n1 sal_Int16 +cppu/source/uno/check.cxx:67 + (anonymous namespace)::D d sal_Int16 +cppu/source/uno/check.cxx:68 + (anonymous namespace)::D e sal_Int32 +cppu/source/uno/check.cxx:72 + (anonymous namespace)::E a sal_Bool +cppu/source/uno/check.cxx:73 + (anonymous namespace)::E b sal_Bool +cppu/source/uno/check.cxx:74 + (anonymous namespace)::E c sal_Bool +cppu/source/uno/check.cxx:75 + (anonymous namespace)::E d sal_Int16 +cppu/source/uno/check.cxx:76 + (anonymous namespace)::E e sal_Int32 +cppu/source/uno/check.cxx:81 + (anonymous namespace)::M n sal_Int32 +cppu/source/uno/check.cxx:82 + (anonymous namespace)::M o sal_Int16 +cppu/source/uno/check.cxx:91 + (anonymous namespace)::N2 m struct (anonymous namespace)::M +cppu/source/uno/check.cxx:92 + (anonymous namespace)::N2 p sal_Int16 +cppu/source/uno/check.cxx:97 + (anonymous namespace)::O p double +cppu/source/uno/check.cxx:98 + (anonymous namespace)::O q sal_Int16 +cppu/source/uno/check.cxx:107 + (anonymous namespace)::P p2 double +cppu/source/uno/check.cxx:115 + (anonymous namespace)::second a int +cppu/source/uno/check.cxx:126 + (anonymous namespace)::Char1 c1 char +cppu/source/uno/check.cxx:130 + (anonymous namespace)::Char2 c2 char +cppu/source/uno/check.cxx:134 + (anonymous namespace)::Char3 c3 char +cppu/source/uno/check.cxx:258 + (anonymous namespace)::Char4 chars struct (anonymous namespace)::Char3 +cppu/source/uno/copy.hxx:38 + cppu::(anonymous namespace)::SequencePrefix nRefCount sal_Int32 +cppu/source/uno/copy.hxx:39 + cppu::(anonymous namespace)::SequencePrefix nElements sal_Int32 +cppuhelper/qa/ifcontainer/cppu_ifcontainer.cxx:45 + (anonymous namespace)::ContainerListener m_pStats struct (anonymous namespace)::ContainerStats * +cppuhelper/source/access_control.cxx:79 + cppu::(anonymous namespace)::permission m_str1 rtl_uString * +cppuhelper/source/access_control.cxx:80 + cppu::(anonymous namespace)::permission m_str2 rtl_uString * +cppuhelper/source/typemanager.cxx:844 + (anonymous namespace)::BaseOffset set_ std::set +cui/source/inc/cfg.hxx:404 + SvxConfigPage m_xDropTargetHelper std::unique_ptr +cui/source/inc/cuihyperdlg.hxx:46 + SvxHlinkCtrl aRdOnlyForwarder class SfxStatusForwarder +cui/source/inc/cuihyperdlg.hxx:77 + SvxHpLinkDlg maCtrl class SvxHlinkCtrl +cui/source/inc/GraphicsTestsDialog.hxx:42 + GraphicsTestsDialog m_xGraphicTestEntries std::vector > +cui/source/inc/screenshotannotationdlg.hxx:29 + ScreenshotAnnotationDlg m_pImpl std::unique_ptr +dbaccess/source/core/dataaccess/databasedocument.hxx:177 + dbaccess::ODatabaseDocument m_pEventExecutor ::rtl::Reference +dbaccess/source/core/dataaccess/documentdefinition.cxx:291 + dbaccess::(anonymous namespace)::LifetimeCoupler m_xClient Reference +dbaccess/source/core/inc/SingleSelectQueryComposer.hxx:83 + dbaccess::OSingleSelectQueryComposer m_aColumnsCollection std::vector > +dbaccess/source/core/inc/SingleSelectQueryComposer.hxx:85 + dbaccess::OSingleSelectQueryComposer m_aTablesCollection std::vector > +dbaccess/source/core/inc/TableDeco.hxx:65 + dbaccess::ODBTableDecorator m_xColumnMediator css::uno::Reference +dbaccess/source/filter/xml/dbloader2.cxx:200 + dbaxml::(anonymous namespace)::DBContentLoader m_xMySelf Reference +dbaccess/source/ui/app/AppDetailView.hxx:107 + dbaui::OApplicationDetailView m_aExternalMnemonics class MnemonicGenerator +dbaccess/source/ui/browser/dbloader.cxx:59 + (anonymous namespace)::DBContentLoader m_xListener Reference +desktop/qa/desktop_lib/test_desktop_lib.cxx:307 + DesktopLOKTest m_bModified _Bool +desktop/source/app/app.cxx:1230 + desktop::(anonymous namespace)::ExecuteGlobals pCTLLanguageOptions std::unique_ptr +desktop/source/app/app.cxx:1231 + desktop::(anonymous namespace)::ExecuteGlobals pPathOptions std::unique_ptr +desktop/source/deployment/gui/dp_gui_extlistbox.hxx:137 + dp_gui::ExtensionBox_Impl m_vRemovedEntries std::vector +desktop/source/deployment/gui/dp_gui_updatedialog.hxx:148 + dp_gui::UpdateDialog m_xExtensionManager css::uno::Reference +desktop/source/deployment/gui/dp_gui_updateinstalldialog.cxx:101 + dp_gui::UpdateCommandEnv m_installThread ::rtl::Reference +desktop/source/deployment/manager/dp_managerfac.cxx:44 + dp_manager::factory::(anonymous namespace)::PackageManagerFactoryImpl m_xUserMgr Reference +desktop/source/deployment/manager/dp_managerfac.cxx:45 + dp_manager::factory::(anonymous namespace)::PackageManagerFactoryImpl m_xSharedMgr Reference +desktop/source/deployment/manager/dp_managerfac.cxx:46 + dp_manager::factory::(anonymous namespace)::PackageManagerFactoryImpl m_xBundledMgr Reference +desktop/source/deployment/manager/dp_managerfac.cxx:47 + dp_manager::factory::(anonymous namespace)::PackageManagerFactoryImpl m_xTmpMgr Reference +desktop/source/deployment/manager/dp_managerfac.cxx:48 + dp_manager::factory::(anonymous namespace)::PackageManagerFactoryImpl m_xBakMgr Reference +desktop/unx/source/splashx.c:371 + decorations unsigned long +desktop/unx/source/splashx.c:371 + flags unsigned long +desktop/unx/source/splashx.c:371 + functions unsigned long +desktop/unx/source/splashx.c:372 + input_mode long +drawinglayer/inc/texture/texture.hxx:58 + drawinglayer::texture::GeoTexSvxGradient maDefinitionRange basegfx::B2DRange +drawinglayer/inc/texture/texture.hxx:61 + drawinglayer::texture::GeoTexSvxGradient mfBorder double +drawinglayer/inc/texture/texture.hxx:210 + drawinglayer::texture::GeoTexSvxHatch mfAngle double +drawinglayer/source/attribute/sdrfillgraphicattribute.cxx:44 + drawinglayer::attribute::ImpSdrFillGraphicAttribute mbLogSize _Bool +drawinglayer/source/attribute/sdrsceneattribute3d.cxx:29 + drawinglayer::attribute::ImpSdrSceneAttribute mfDistance double +embeddedobj/source/inc/oleembobj.hxx:133 + OleEmbeddedObject m_nTargetState sal_Int32 +embeddedobj/source/inc/oleembobj.hxx:145 + OleEmbeddedObject m_xClosePreventer css::uno::Reference +embeddedobj/source/inc/oleembobj.hxx:167 + OleEmbeddedObject m_bHasSizeToSet _Bool +embeddedobj/source/inc/oleembobj.hxx:168 + OleEmbeddedObject m_aSizeToSet css::awt::Size +embeddedobj/source/inc/oleembobj.hxx:169 + OleEmbeddedObject m_nAspectToSet sal_Int64 +embeddedobj/source/inc/oleembobj.hxx:174 + OleEmbeddedObject m_bGotStatus _Bool +embeddedobj/source/inc/oleembobj.hxx:175 + OleEmbeddedObject m_nStatus sal_Int64 +embeddedobj/source/inc/oleembobj.hxx:176 + OleEmbeddedObject m_nStatusAspect sal_Int64 +embeddedobj/source/inc/oleembobj.hxx:190 + OleEmbeddedObject m_bFromClipboard _Bool +emfio/inc/mtftools.hxx:621 + emfio::MtfTools mrclBounds tools::Rectangle +extensions/source/propctrlr/genericpropertyhandler.hxx:65 + pcr::GenericPropertyHandler m_xComponentIntrospectionAccess css::uno::Reference +extensions/source/scanner/scanner.hxx:45 + ScannerManager mpData void * +framework/inc/services/layoutmanager.hxx:247 + framework::LayoutManager m_bGlobalSettings _Bool +framework/inc/services/layoutmanager.hxx:261 + framework::LayoutManager m_pGlobalSettings std::unique_ptr +framework/inc/uielement/langselectionmenucontroller.hxx:69 + framework::LanguageSelectionMenuController m_xMenuDispatch_Lang css::uno::Reference +framework/inc/uielement/langselectionmenucontroller.hxx:71 + framework::LanguageSelectionMenuController m_xMenuDispatch_Font css::uno::Reference +framework/inc/uielement/langselectionmenucontroller.hxx:73 + framework::LanguageSelectionMenuController m_xMenuDispatch_CharDlgForParagraph css::uno::Reference +framework/inc/xml/imagesdocumenthandler.hxx:124 + framework::OWriteImagesDocumentHandler m_xEmptyList css::uno::Reference +framework/inc/xml/statusbardocumenthandler.hxx:125 + framework::OWriteStatusBarDocumentHandler m_xEmptyList css::uno::Reference +framework/source/layoutmanager/toolbarlayoutmanager.hxx:271 + framework::ToolbarLayoutManager m_pGlobalSettings std::unique_ptr +framework/source/layoutmanager/toolbarlayoutmanager.hxx:275 + framework::ToolbarLayoutManager m_bGlobalSettings _Bool +i18nutil/source/utility/paper.cxx:314 + paperword string char * +include/basegfx/DrawCommands.hxx:81 + gfx::LinearGradientInfo maMatrix basegfx::B2DHomMatrix +include/basic/basmgr.hxx:57 + BasicError nReason enum BasicErrorReason +include/basic/sbxvar.hxx:75 + SbxValues::(anonymous) pData void * +include/basic/sbxvar.hxx:247 + SbxVariable m_xComListener css::uno::Reference +include/basic/sbxvar.hxx:248 + SbxVariable m_pComListenerParentBasic class StarBASIC * +include/comphelper/parallelsort.hxx:88 + comphelper::(anonymous namespace)::ProfileZone mbDummy _Bool +include/comphelper/unique_disposing_ptr.hxx:30 + comphelper::unique_disposing_ptr m_xTerminateListener css::uno::Reference +include/drawinglayer/attribute/sdrallattribute3d.hxx:42 + drawinglayer::attribute::SdrLineFillShadowAttribute3D maLineStartEnd const class drawinglayer::attribute::SdrLineStartEndAttribute +include/drawinglayer/primitive2d/mediaprimitive2d.hxx:48 + drawinglayer::primitive2d::MediaPrimitive2D maURL rtl::OUString +include/editeng/adjustitem.hxx:37 + SvxAdjustItem bLeft _Bool +include/editeng/outlobj.hxx:44 + OutlinerParaObjData mbIsEditDoc _Bool +include/editeng/unotext.hxx:420 + SvxUnoTextBase xParentText css::uno::Reference +include/editeng/unotext.hxx:589 + SvxUnoTextContentEnumeration mxParentText css::uno::Reference +include/framework/addonsoptions.hxx:75 + framework::MergeNotebookBarInstruction aMergePoint rtl::OUString +include/framework/addonsoptions.hxx:76 + framework::MergeNotebookBarInstruction aMergeCommand rtl::OUString +include/framework/addonsoptions.hxx:77 + framework::MergeNotebookBarInstruction aMergeCommandParameter rtl::OUString +include/framework/addonsoptions.hxx:78 + framework::MergeNotebookBarInstruction aMergeFallback rtl::OUString +include/framework/addonsoptions.hxx:79 + framework::MergeNotebookBarInstruction aMergeContext rtl::OUString +include/framework/dispatchhelper.hxx:73 + framework::DispatchHelper m_xBroadcaster css::uno::Reference +include/framework/framelistanalyzer.hxx:122 + framework::FrameListAnalyzer m_xHelp css::uno::Reference +include/LibreOfficeKit/LibreOfficeKit.h:334 + _LibreOfficeKitDocumentClass getPartInfo char *(*)(LibreOfficeKitDocument *, int) +include/LibreOfficeKit/LibreOfficeKit.h:339 + _LibreOfficeKitDocumentClass paintWindowDPI void (*)(LibreOfficeKitDocument *, unsigned int, unsigned char *, const int, const int, const int, const int, const double) +include/opencl/openclwrapper.hxx:34 + openclwrapper::KernelEnv mpkProgram cl_program +include/opencl/openclwrapper.hxx:50 + openclwrapper::GPUEnv mbNeedsTDRAvoidance _Bool +include/opencl/platforminfo.hxx:29 + OpenCLDeviceInfo mnMemory size_t +include/opencl/platforminfo.hxx:30 + OpenCLDeviceInfo mnComputeUnits size_t +include/opencl/platforminfo.hxx:31 + OpenCLDeviceInfo mnFrequency size_t +include/sfx2/minfitem.hxx:38 + SfxMacroInfoItem aCommentText rtl::OUString +include/svl/sigstruct.hxx:127 + SignatureInformation hasInconsistentSigningTime _Bool +include/svtools/brwbox.hxx:326 + BrowseBox::CursorMoveAttempt m_nCol sal_Int32 +include/svtools/brwbox.hxx:327 + BrowseBox::CursorMoveAttempt m_nRow sal_Int32 +include/svtools/brwbox.hxx:328 + BrowseBox::CursorMoveAttempt m_bScrolledToReachCell _Bool +include/svtools/ctrltool.hxx:147 + FontList mpDev VclPtr +include/svtools/ctrltool.hxx:148 + FontList mpDev2 VclPtr +include/svx/AccessibilityCheckDialog.hxx:44 + svx::AccessibilityCheckDialog m_aAccessibilityCheckEntries std::vector > +include/svx/bmpmask.hxx:127 + SvxBmpMask aSelItem class SvxBmpMaskSelectItem +include/svx/fillctrl.hxx:83 + FillControl mxColorDispatch std::unique_ptr +include/svx/float3d.hxx:202 + Svx3DWin pControllerItem std::unique_ptr +include/svx/fmtools.hxx:135 + FmXDisposeListener m_pAdapter rtl::Reference +include/svx/galctrl.hxx:38 + GalleryPreview mxDragDropTargetHelper std::unique_ptr +include/svx/galctrl.hxx:91 + GalleryIconView mxDragDropTargetHelper std::unique_ptr +include/svx/GenericCheckDialog.hxx:91 + svx::GenericCheckDialog m_aCheckEntries std::vector > +include/svx/gridctrl.hxx:258 + DbGridControl m_pCursorDisposeListener std::unique_ptr +include/svx/ofaitem.hxx:44 + OfaXColorListItem mxRef rtl::Reference +include/svx/srchdlg.hxx:166 + SvxSearchDialog pSearchController std::unique_ptr +include/svx/srchdlg.hxx:167 + SvxSearchDialog pOptionsController std::unique_ptr +include/svx/svdmrkv.hxx:99 + SdrMarkView mpMarkingSubSelectionOverlay std::unique_ptr +include/svx/viewpt3d.hxx:62 + Viewport3D::(anonymous) H double +include/svx/viewpt3d.hxx:62 + Viewport3D::(anonymous) X double +include/svx/viewpt3d.hxx:62 + Viewport3D::(anonymous) Y double +include/test/beans/xpropertyset.hxx:56 + apitest::XPropertySet::PropsToTest constrained std::vector +include/unotools/fontcfg.hxx:157 + utl::FontSubstConfiguration maSubstHash utl::FontSubstConfiguration::UniqueSubstHash +include/vcl/notebookbar/NotebookBarAddonsMerger.hxx:43 + AddonNotebookBarItem sTarget rtl::OUString +include/vcl/notebookbar/NotebookBarAddonsMerger.hxx:44 + AddonNotebookBarItem sContext rtl::OUString +include/vcl/notebookbar/NotebookBarAddonsMerger.hxx:45 + AddonNotebookBarItem sControlType rtl::OUString +include/vcl/notebookbar/NotebookBarAddonsMerger.hxx:46 + AddonNotebookBarItem nWidth sal_uInt16 +include/vcl/opengl/OpenGLContext.hxx:27 + GLWindow bMultiSampleSupported _Bool +include/vcl/pdfextoutdevdata.hxx:82 + vcl::PDFExtOutDevData mbSinglePageSheets _Bool +include/vcl/salnativewidgets.hxx:467 + ToolbarValue mbIsTopDockingArea _Bool +include/vcl/salnativewidgets.hxx:533 + PushButtonValue mbBevelButton _Bool +include/vcl/salnativewidgets.hxx:534 + PushButtonValue mbSingleLine _Bool +include/vcl/sysdata.hxx:68 + SystemEnvData pSalFrame class SalFrame * +include/vcl/textrectinfo.hxx:35 + TextRectInfo mnLineCount sal_uInt16 +include/vcl/vclenum.hxx:199 + ItalicMatrix xx double +include/vcl/vclenum.hxx:199 + ItalicMatrix xy double +include/vcl/vclenum.hxx:199 + ItalicMatrix yx double +include/vcl/vclenum.hxx:199 + ItalicMatrix yy double +include/xmloff/shapeimport.hxx:95 + SdXML3DSceneAttributesHelper mbVRPUsed _Bool +io/source/stm/odata.cxx:243 + io_stm::(anonymous namespace)::ODataInputStream::readDouble()::(anonymous union)::(anonymous) n1 sal_uInt32 +io/source/stm/odata.cxx:243 + io_stm::(anonymous namespace)::ODataInputStream::readDouble()::(anonymous union)::(anonymous) n2 sal_uInt32 +jvmfwk/inc/vendorbase.hxx:171 + jfw_plugin::VendorBase m_sArch rtl::OUString +l10ntools/inc/common.hxx:32 + common::HandledArgs m_bUTF8BOM _Bool +libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx:28 + GtvRenderingArgs m_aBackgroundColor std::string +libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx:62 + GtvApplicationWindow statusbar GtkWidget * +libreofficekit/qa/gtktiledviewer/gtv-main-toolbar.cxx:37 + (anonymous namespace)::GtvMainToolbarPrivateImpl m_pPartModeSelector GtkWidget * +package/inc/ByteChucker.hxx:33 + ByteChucker p2Sequence sal_Int8 *const +package/inc/ByteChucker.hxx:33 + ByteChucker p4Sequence sal_Int8 *const +registry/source/reflread.cxx:477 + (anonymous namespace)::ConstantPool::readDoubleConstant(sal_uInt16)::(anonymous union)::(anonymous) b1 sal_uInt32 +registry/source/reflread.cxx:478 + (anonymous namespace)::ConstantPool::readDoubleConstant(sal_uInt16)::(anonymous union)::(anonymous) b2 sal_uInt32 +reportdesign/inc/RptObject.hxx:69 + rptui::OObjectBase m_xKeepShapeAlive css::uno::Reference +sal/rtl/alloc_arena.hxx:35 + rtl_arena_stat_type m_mem_total sal_Size +sal/rtl/alloc_arena.hxx:36 + rtl_arena_stat_type m_mem_alloc sal_Size +sal/textenc/tcvtutf7.cxx:98 + (anonymous namespace)::ImplUTF7ToUCContextData mbShifted _Bool +sal/textenc/tcvtutf7.cxx:99 + (anonymous namespace)::ImplUTF7ToUCContextData mbFirst _Bool +sal/textenc/tcvtutf7.cxx:100 + (anonymous namespace)::ImplUTF7ToUCContextData mbWroteOne _Bool +sal/textenc/tcvtutf7.cxx:101 + (anonymous namespace)::ImplUTF7ToUCContextData mnBitBuffer sal_uInt32 +sal/textenc/tcvtutf7.cxx:102 + (anonymous namespace)::ImplUTF7ToUCContextData mnBufferBits sal_uInt32 +sal/textenc/tcvtutf7.cxx:421 + (anonymous namespace)::ImplUTF7FromUCContextData mbShifted _Bool +sal/textenc/tcvtutf7.cxx:422 + (anonymous namespace)::ImplUTF7FromUCContextData mnBitBuffer sal_uInt32 +sal/textenc/tcvtutf7.cxx:423 + (anonymous namespace)::ImplUTF7FromUCContextData mnBufferBits sal_uInt32 +sc/inc/compiler.hxx:266 + ScCompiler::AddInMap pODFF const char * +sc/inc/compiler.hxx:267 + ScCompiler::AddInMap pEnglish const char * +sc/inc/compiler.hxx:269 + ScCompiler::AddInMap pUpper const char * +sc/inc/compressedarray.hxx:68 + ScCompressedArray::RangeData mnRow2 A +sc/inc/fillinfo.hxx:280 + ScTableInfo mDataBarInfos std::vector > +sc/inc/fillinfo.hxx:281 + ScTableInfo mIconSetInfos std::vector > +sc/inc/pivot.hxx:75 + ScDPLabelData mnFlags sal_Int32 +sc/inc/pivot.hxx:78 + ScDPLabelData mbIsValue _Bool +sc/inc/scmatrix.hxx:117 + ScMatrix mbCloneIfConst _Bool +sc/inc/scmod.hxx:100 + ScModule m_pErrorHdl std::unique_ptr +sc/inc/SparklineGroup.hxx:79 + sc::SparklineGroup m_sUID rtl::OUString +sc/inc/tabopparams.hxx:37 + ScInterpreterTableOpParams bValid _Bool +sc/source/core/data/column4.cxx:1386 + (anonymous namespace)::StartListeningFormulaCellsHandler mnStartRow SCROW +sc/source/core/data/column.cxx:1319 + (anonymous namespace)::CopyByCloneHandler meListenType sc::StartListeningType +sc/source/core/data/column.cxx:1320 + (anonymous namespace)::CopyByCloneHandler mnFormulaCellCloneFlags enum ScCloneFlags +sc/source/core/data/table2.cxx:3970 + (anonymous namespace)::OutlineArrayFinder mpArray class ScOutlineArray * +sc/source/filter/excel/xltoolbar.hxx:24 + TBCCmd A _Bool +sc/source/filter/excel/xltoolbar.hxx:25 + TBCCmd B _Bool +sc/source/filter/excel/xltoolbar.hxx:26 + TBCCmd cmdType sal_uInt16 +sc/source/filter/excel/xltoolbar.hxx:27 + TBCCmd C _Bool +sc/source/filter/excel/xltoolbar.hxx:28 + TBCCmd reserved3 sal_uInt16 +sc/source/filter/excel/xltoolbar.hxx:53 + ScCTB rVisualData std::vector +sc/source/filter/excel/xltools.cxx:102 + smD union sal_math_Double +sc/source/filter/inc/exp_op.hxx:47 + ExportBiff5 pExcRoot struct RootData * +sc/source/filter/inc/imp_op.hxx:83 + ImportExcel::LastFormula mpCell class ScFormulaCell * +sc/source/filter/inc/namebuff.hxx:36 + StringHashEntry aString rtl::OUString +sc/source/filter/inc/namebuff.hxx:37 + StringHashEntry nHash sal_uInt32 +sc/source/filter/inc/orcusinterface.hxx:377 + ScOrcusStyles::fill maBgColor std::optional +sc/source/filter/inc/orcusinterface.hxx:432 + ScOrcusStyles::xf mnStyleXf size_t +sc/source/filter/inc/orcusinterface.hxx:452 + ScOrcusStyles::cell_style mnBuiltInId size_t +sc/source/filter/inc/tokstack.hxx:141 + TokenPool pP_Err TokenPoolPool +sc/source/filter/lotus/lotfilter.hxx:53 + LotusContext eActType enum Lotus123Typ +sc/source/filter/xml/xmlcondformat.hxx:110 + ScXMLIconSetFormatContext mpFormatData struct ScIconSetFormatData * +sc/source/filter/xml/XMLDetectiveContext.hxx:96 + ScXMLDetectiveHighlightedContext pDetectiveObjVec ScMyImpDetectiveObjVec * +sc/source/filter/xml/xmldpimp.hxx:247 + ScXMLDataPilotFieldContext mbHasHiddenMember _Bool +sc/source/filter/xml/xmldrani.hxx:71 + ScXMLDatabaseRangeContext bIsSelection _Bool +sc/source/filter/xml/xmlexternaltabi.hxx:110 + ScXMLExternalRefCellContext mnCellType sal_Int16 +sc/source/ui/inc/AccessibleText.hxx:197 + ScAccessiblePreviewHeaderCellTextData mbRowHeader _Bool +sc/source/ui/inc/datastream.hxx:104 + sc::DataStream mnSettings sal_uInt32 +sc/source/ui/inc/drawview.hxx:41 + ScDrawView pDropMarker std::unique_ptr +sc/source/ui/inc/drwtrans.hxx:44 + ScDrawTransferObj m_aDrawPersistRef SfxObjectShellRef +sc/source/ui/inc/dwfunctr.hxx:52 + ScFunctionWin xConfigChange std::unique_ptr +sc/source/ui/inc/filtdlg.hxx:193 + ScSpecialFilterDlg pOptionsMgr std::unique_ptr +sc/source/ui/inc/instbdlg.hxx:57 + ScInsertTableDlg aDocShTablesRef SfxObjectShellRef +sc/source/ui/inc/linkarea.hxx:36 + ScLinkedAreaDlg aSourceRef SfxObjectShellRef +sc/source/ui/inc/pfuncache.hxx:48 + ScPrintSelectionStatus aRanges class ScRangeList +sc/source/ui/inc/PivotLayoutTreeList.hxx:20 + ScPivotLayoutTreeList maItemValues std::vector > +sc/source/ui/inc/PivotLayoutTreeListData.hxx:37 + ScPivotLayoutTreeListData maDataItemValues std::vector > +sc/source/ui/inc/preview.hxx:46 + ScPreview nTabPage tools::Long +sc/source/ui/inc/tabvwsh.hxx:122 + ScTabViewShell xDisProvInterceptor css::uno::Reference +sc/source/ui/inc/transobj.hxx:46 + ScTransferObj m_aDrawPersistRef SfxObjectShellRef +sc/source/ui/inc/uiitems.hxx:46 + ScInputStatusItem aStartPos class ScAddress +sc/source/ui/inc/uiitems.hxx:47 + ScInputStatusItem aEndPos class ScAddress +sc/source/ui/sidebar/AlignmentPropertyPanel.hxx:76 + sc::sidebar::AlignmentPropertyPanel mxHorizontalAlignDispatch std::unique_ptr +sc/source/ui/sidebar/AlignmentPropertyPanel.hxx:79 + sc::sidebar::AlignmentPropertyPanel mxVertAlignDispatch std::unique_ptr +sc/source/ui/sidebar/AlignmentPropertyPanel.hxx:82 + sc::sidebar::AlignmentPropertyPanel mxWriteDirectionDispatch std::unique_ptr +sc/source/ui/sidebar/AlignmentPropertyPanel.hxx:85 + sc::sidebar::AlignmentPropertyPanel mxIndentButtonsDispatch std::unique_ptr +sc/source/ui/sidebar/CellAppearancePropertyPanel.hxx:75 + sc::sidebar::CellAppearancePropertyPanel mxBackColorDispatch std::unique_ptr +sc/source/ui/sidebar/CellAppearancePropertyPanel.hxx:79 + sc::sidebar::CellAppearancePropertyPanel mxLineColorDispatch std::unique_ptr +sc/source/ui/sidebar/NumberFormatPropertyPanel.hxx:65 + sc::sidebar::NumberFormatPropertyPanel mxCategoryDispatch std::unique_ptr +sc/source/ui/vba/vbachartobject.hxx:43 + ScVbaChartObject oShapeHelper std::unique_ptr +sd/inc/sdmod.hxx:134 + SdModule mpErrorHdl std::unique_ptr +sd/qa/unit/tiledrendering/tiledrendering.cxx:212 + SdTiledRenderingTest m_bFound _Bool +sd/qa/unit/tiledrendering/tiledrendering.cxx:213 + SdTiledRenderingTest m_nPart sal_Int32 +sd/qa/unit/tiledrendering/tiledrendering.cxx:215 + SdTiledRenderingTest m_aSearchResultPart std::vector +sd/qa/unit/tiledrendering/tiledrendering.cxx:216 + SdTiledRenderingTest m_nSelectionBeforeSearchResult int +sd/qa/unit/tiledrendering/tiledrendering.cxx:217 + SdTiledRenderingTest m_nSelectionAfterSearchResult int +sd/source/ui/dlg/RemoteDialogClientBox.hxx:66 + sd::ClientBox m_vEntries std::vector +sd/source/ui/framework/module/ToolBarModule.hxx:72 + sd::framework::ToolBarModule mpToolBarManagerLock std::unique_ptr > +sd/source/ui/inc/animobjs.hxx:122 + sd::AnimationWindow pControllerItem std::unique_ptr +sd/source/ui/inc/custsdlg.hxx:62 + SdDefineCustomShowDlg bModified _Bool +sd/source/ui/inc/fudspord.hxx:50 + sd::FuDisplayOrder mpOverlay std::unique_ptr +sd/source/ui/inc/navigatr.hxx:143 + SdNavigatorWin mpNavigatorCtrlItem std::unique_ptr +sd/source/ui/inc/navigatr.hxx:144 + SdNavigatorWin mpPageNameCtrlItem std::unique_ptr +sd/source/ui/inc/tools/TimerBasedTaskExecution.hxx:72 + sd::tools::TimerBasedTaskExecution mpSelf std::shared_ptr +sd/source/ui/inc/unopage.hxx:277 + SdPageLinkTargets mxPage css::uno::Reference +sd/source/ui/inc/ViewShellImplementation.hxx:78 + sd::ViewShell::Implementation::ToolBarManagerLock mpLock ::std::unique_ptr > +sd/source/ui/inc/ViewShellImplementation.hxx:89 + sd::ViewShell::Implementation::ToolBarManagerLock mpSelf std::shared_ptr +sd/source/ui/remotecontrol/Receiver.hxx:34 + sd::Receiver pTransmitter class sd::Transmitter * +sd/source/ui/sidebar/MasterPageContainerProviders.hxx:144 + sd::sidebar::TemplatePreviewProvider msURL rtl::OUString +sd/source/ui/slideshow/slideshowimpl.hxx:331 + sd::SlideshowImpl mpPaneHider ::std::unique_ptr +sd/source/ui/slideshow/SlideShowRestarter.hxx:73 + sd::SlideShowRestarter mpSelf ::std::shared_ptr +sd/source/ui/slidesorter/controller/SlsListener.hxx:140 + sd::slidesorter::controller::Listener mpModelChangeLock std::shared_ptr +sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx:114 + sd::slidesorter::controller::Clipboard mxUndoContext std::unique_ptr +sd/source/ui/view/ToolBarManager.cxx:317 + sd::ToolBarManager::Implementation mpAsynchronousLayouterLock ::std::unique_ptr +sdext/source/presenter/PresenterTimer.cxx:104 + sdext::presenter::(anonymous namespace)::TimerScheduler mpLateDestroy std::shared_ptr +sfx2/inc/commandpopup/CommandPopup.hxx:107 + CommandPopupHandler mpListBox std::unique_ptr +sfx2/inc/notebookbar/NotebookbarTabControl.hxx:42 + NotebookbarTabControl m_pListener css::uno::Reference +sfx2/source/appl/fileobj.hxx:40 + SvFileObject mxDelMed tools::SvRef +sfx2/source/doc/sfxbasemodel.cxx:450 + (anonymous namespace)::SfxSaveGuard m_pFramesLock std::unique_ptr +sfx2/source/inc/appdata.hxx:69 + SfxAppData_Impl pDocTopics std::unique_ptr +sfx2/source/inc/appdata.hxx:70 + SfxAppData_Impl pTriggerTopic std::unique_ptr +sfx2/source/inc/appdata.hxx:71 + SfxAppData_Impl pDdeService2 std::unique_ptr +sfx2/source/inc/appdata.hxx:79 + SfxAppData_Impl m_pToolsErrorHdl std::optional +sfx2/source/inc/appdata.hxx:80 + SfxAppData_Impl m_pSoErrorHdl std::optional +sfx2/source/inc/appdata.hxx:82 + SfxAppData_Impl m_pSbxErrorHdl std::optional +sfx2/source/inc/appdata.hxx:85 + SfxAppData_Impl mxAppPickList std::optional +sfx2/source/inc/splitwin.hxx:52 + SfxSplitWindow pActive VclPtr +sfx2/source/inc/StyleList.hxx:226 + StyleList m_xTreeView1DropTargetHelper std::unique_ptr +sfx2/source/inc/StyleList.hxx:227 + StyleList m_xTreeView2DropTargetHelper std::unique_ptr +sfx2/source/inc/templdgi.hxx:207 + SfxTemplateDialog_Impl m_xToolbarDropTargetHelper std::unique_ptr +sfx2/source/view/classificationcontroller.cxx:73 + sfx2::(anonymous namespace)::ClassificationCategoriesController m_aPropertyListener class sfx2::(anonymous namespace)::ClassificationPropertyListener +slideshow/source/engine/opengl/TransitionImpl.hxx:297 + Vertex normal glm::vec3 +slideshow/source/engine/opengl/TransitionImpl.hxx:298 + Vertex texcoord glm::vec2 +slideshow/source/engine/slideshowimpl.cxx:1047 + (anonymous namespace)::SlideShowImpl::PrefetchPropertiesFunc mpSlideShowImpl class (anonymous namespace)::SlideShowImpl *const +slideshow/test/testview.cxx:50 + (anonymous namespace)::ImplTestView maCreatedSprites std::vector > +slideshow/test/testview.cxx:53 + (anonymous namespace)::ImplTestView maPriority basegfx::B1DRange +soltools/cpp/cpp.h:143 + macroValidator pMacro Nlist * +starmath/inc/mathml/mathmlimport.hxx:45 + SmXMLImportWrapper m_bUseHTMLMLEntities _Bool +starmath/inc/view.hxx:186 + SmCmdBoxWindow aController class SmEditController +stoc/source/servicemanager/servicemanager.cxx:388 + (anonymous namespace)::OServiceManager m_SetLoadedFactories (anonymous namespace)::HashSet_Ref +store/source/storbios.cxx:58 + (anonymous namespace)::OStoreSuperBlock m_nMarked sal_uInt32 +store/source/storbios.cxx:59 + (anonymous namespace)::OStoreSuperBlock m_aMarked (anonymous namespace)::OStoreSuperBlock::L +svgio/inc/svgcharacternode.hxx:84 + svgio::svgreader::SvgTextPosition maY ::std::vector +svgio/inc/svgsvgnode.hxx:41 + svgio::svgreader::SvgSvgNode maVersion class svgio::svgreader::SvgNumber +svgio/inc/svgsymbolnode.hxx:32 + svgio::svgreader::SvgSymbolNode maSvgAspectRatio class svgio::svgreader::SvgAspectRatio +svgio/inc/svgusenode.hxx:40 + svgio::svgreader::SvgUseNode maWidth class svgio::svgreader::SvgNumber +svgio/inc/svgusenode.hxx:41 + svgio::svgreader::SvgUseNode maHeight class svgio::svgreader::SvgNumber +svl/source/crypto/cryptosign.cxx:97 + (anonymous namespace)::MessageImprint hashedMessage SECItem +svl/source/crypto/cryptosign.cxx:132 + (anonymous namespace)::TimeStampReq version SECItem +svl/source/crypto/cryptosign.cxx:134 + (anonymous namespace)::TimeStampReq reqPolicy SECItem +svl/source/crypto/cryptosign.cxx:135 + (anonymous namespace)::TimeStampReq nonce SECItem +svl/source/crypto/cryptosign.cxx:136 + (anonymous namespace)::TimeStampReq certReq SECItem +svl/source/crypto/cryptosign.cxx:137 + (anonymous namespace)::TimeStampReq extensions struct (anonymous namespace)::Extension * +svl/source/crypto/cryptosign.cxx:145 + (anonymous namespace)::GeneralName name CERTName +svl/source/crypto/cryptosign.cxx:153 + (anonymous namespace)::GeneralNames names struct (anonymous namespace)::GeneralName +svl/source/crypto/cryptosign.cxx:161 + (anonymous namespace)::IssuerSerial issuer struct (anonymous namespace)::GeneralNames +svl/source/crypto/cryptosign.cxx:162 + (anonymous namespace)::IssuerSerial serialNumber SECItem +svl/source/crypto/cryptosign.cxx:172 + (anonymous namespace)::ESSCertIDv2 certHash SECItem +svl/source/crypto/cryptosign.cxx:173 + (anonymous namespace)::ESSCertIDv2 issuerSerial struct (anonymous namespace)::IssuerSerial +svl/source/crypto/cryptosign.cxx:181 + (anonymous namespace)::SigningCertificateV2 certs struct (anonymous namespace)::ESSCertIDv2 ** +svl/source/misc/inethist.cxx:45 + INetURLHistory_Impl::head_entry m_nMagic sal_uInt32 +svl/source/undo/undo.cxx:310 + svl::undo::impl::UndoManagerGuard m_aUndoActionsCleanup ::std::vector > +svx/inc/galbrws2.hxx:82 + GalleryBrowser2 mxDragDropTargetHelper std::unique_ptr +svx/inc/sdr/overlay/overlaytools.hxx:41 + drawinglayer::primitive2d::OverlayStaticRectanglePrimitive mfRotation double +svx/inc/sdr/primitive2d/sdrolecontentprimitive2d.hxx:44 + drawinglayer::primitive2d::SdrOleContentPrimitive2D mnGraphicVersion sal_uInt32 +svx/source/form/dataaccessdescriptor.cxx:39 + svx::ODADescriptorImpl m_bSetOutOfDate _Bool +svx/source/form/formcontroller.cxx:208 + svxform::(anonymous namespace)::ColumnInfo nNullable sal_Int32 +svx/source/inc/datanavi.hxx:319 + svxform::DataNavigator m_xDataWin std::unique_ptr +svx/source/inc/docrecovery.hxx:131 + svx::DocRecovery::TURLInfo Module rtl::OUString +svx/source/inc/StylesPreviewToolBoxControl.hxx:33 + StylesPreviewToolBoxControl m_xWeldBox std::unique_ptr +svx/source/inc/StylesPreviewWindow.hxx:107 + StylesPreviewWindow_Base m_pStylePoolChangeListener std::unique_ptr +svx/source/sdr/attribute/sdrformtextattribute.cxx:152 + drawinglayer::attribute::ImpSdrFormTextAttribute mnFormTextShdwTransp sal_uInt16 +svx/source/sdr/attribute/sdrtextattribute.cxx:48 + drawinglayer::attribute::ImpSdrTextAttribute maPropertiesVersion sal_uInt32 +svx/source/sdr/attribute/sdrtextattribute.cxx:62 + drawinglayer::attribute::ImpSdrTextAttribute mbWrongSpell _Bool +svx/source/sidebar/effect/EffectPropertyPanel.hxx:35 + svx::sidebar::EffectPropertyPanel maGlowColorController sfx2::sidebar::ControllerItem +svx/source/sidebar/effect/EffectPropertyPanel.hxx:36 + svx::sidebar::EffectPropertyPanel maGlowRadiusController sfx2::sidebar::ControllerItem +svx/source/sidebar/effect/EffectPropertyPanel.hxx:37 + svx::sidebar::EffectPropertyPanel maGlowTransparencyController sfx2::sidebar::ControllerItem +svx/source/sidebar/effect/EffectPropertyPanel.hxx:39 + svx::sidebar::EffectPropertyPanel maSoftEdgeRadiusController sfx2::sidebar::ControllerItem +svx/source/sidebar/line/LinePropertyPanel.hxx:81 + svx::sidebar::LinePropertyPanel maStyleControl sfx2::sidebar::ControllerItem +svx/source/sidebar/line/LinePropertyPanel.hxx:82 + svx::sidebar::LinePropertyPanel maDashControl sfx2::sidebar::ControllerItem +svx/source/sidebar/line/LinePropertyPanel.hxx:84 + svx::sidebar::LinePropertyPanel maTransControl sfx2::sidebar::ControllerItem +svx/source/sidebar/line/LinePropertyPanel.hxx:85 + svx::sidebar::LinePropertyPanel maEdgeStyle sfx2::sidebar::ControllerItem +svx/source/sidebar/line/LinePropertyPanel.hxx:86 + svx::sidebar::LinePropertyPanel maCapStyle sfx2::sidebar::ControllerItem +svx/source/sidebar/lists/ListsPropertyPanel.hxx:41 + svx::sidebar::ListsPropertyPanel mxNumBulletDispatcher std::unique_ptr +svx/source/sidebar/lists/ListsPropertyPanel.hxx:43 + svx::sidebar::ListsPropertyPanel mxOutlineDispatcher std::unique_ptr +svx/source/sidebar/paragraph/ParaPropertyPanel.hxx:77 + svx::sidebar::ParaPropertyPanel mxHorzAlignDispatch std::unique_ptr +svx/source/sidebar/paragraph/ParaPropertyPanel.hxx:79 + svx::sidebar::ParaPropertyPanel mxVertAlignDispatch std::unique_ptr +svx/source/sidebar/paragraph/ParaPropertyPanel.hxx:82 + svx::sidebar::ParaPropertyPanel mxNumBulletDispatch std::unique_ptr +svx/source/sidebar/paragraph/ParaPropertyPanel.hxx:84 + svx::sidebar::ParaPropertyPanel mxBackColorDispatch std::unique_ptr +svx/source/sidebar/paragraph/ParaPropertyPanel.hxx:87 + svx::sidebar::ParaPropertyPanel mxWriteDirectionDispatch std::unique_ptr +svx/source/sidebar/paragraph/ParaPropertyPanel.hxx:89 + svx::sidebar::ParaPropertyPanel mxParaSpacingDispatch std::unique_ptr +svx/source/sidebar/paragraph/ParaPropertyPanel.hxx:91 + svx::sidebar::ParaPropertyPanel mxLineSpacingDispatch std::unique_ptr +svx/source/sidebar/paragraph/ParaPropertyPanel.hxx:93 + svx::sidebar::ParaPropertyPanel mxIndentDispatch std::unique_ptr +svx/source/sidebar/possize/PosSizePropertyPanel.hxx:105 + svx::sidebar::PosSizePropertyPanel mxFlipDispatch std::unique_ptr +svx/source/sidebar/possize/PosSizePropertyPanel.hxx:108 + svx::sidebar::PosSizePropertyPanel mxArrangeDispatch std::unique_ptr +svx/source/sidebar/possize/PosSizePropertyPanel.hxx:110 + svx::sidebar::PosSizePropertyPanel mxArrangeDispatch2 std::unique_ptr +svx/source/sidebar/possize/PosSizePropertyPanel.hxx:113 + svx::sidebar::PosSizePropertyPanel mxAlignDispatch std::unique_ptr +svx/source/sidebar/possize/PosSizePropertyPanel.hxx:115 + svx::sidebar::PosSizePropertyPanel mxAlignDispatch2 std::unique_ptr +svx/source/sidebar/styles/StylesPropertyPanel.hxx:20 + svx::sidebar::StylesPropertyPanel m_xFontStyleDispatch std::unique_ptr +svx/source/sidebar/styles/StylesPropertyPanel.hxx:23 + svx::sidebar::StylesPropertyPanel m_xStyleDispatch std::unique_ptr +svx/source/sidebar/text/TextPropertyPanel.hxx:49 + svx::sidebar::TextPropertyPanel mxFontDispatch std::unique_ptr +svx/source/sidebar/text/TextPropertyPanel.hxx:51 + svx::sidebar::TextPropertyPanel mxFontHeightDispatch std::unique_ptr +svx/source/sidebar/text/TextPropertyPanel.hxx:53 + svx::sidebar::TextPropertyPanel mxFontEffectsDispatch std::unique_ptr +svx/source/sidebar/text/TextPropertyPanel.hxx:55 + svx::sidebar::TextPropertyPanel mxFontAdjustDispatch std::unique_ptr +svx/source/sidebar/text/TextPropertyPanel.hxx:57 + svx::sidebar::TextPropertyPanel mxToolBoxFontColorSwDispatch std::unique_ptr +svx/source/sidebar/text/TextPropertyPanel.hxx:59 + svx::sidebar::TextPropertyPanel mxToolBoxFontColorDispatch std::unique_ptr +svx/source/sidebar/text/TextPropertyPanel.hxx:61 + svx::sidebar::TextPropertyPanel mxToolBoxBackgroundColorDispatch std::unique_ptr +svx/source/sidebar/text/TextPropertyPanel.hxx:63 + svx::sidebar::TextPropertyPanel mxResetBarDispatch std::unique_ptr +svx/source/sidebar/text/TextPropertyPanel.hxx:65 + svx::sidebar::TextPropertyPanel mxDefaultBarDispatch std::unique_ptr +svx/source/sidebar/text/TextPropertyPanel.hxx:67 + svx::sidebar::TextPropertyPanel mxPositionBarDispatch std::unique_ptr +svx/source/sidebar/text/TextPropertyPanel.hxx:69 + svx::sidebar::TextPropertyPanel mxSpacingBarDispatch std::unique_ptr +svx/source/sidebar/textcolumns/TextColumnsPropertyPanel.hxx:40 + svx::sidebar::TextColumnsPropertyPanel maColumnsNumberController sfx2::sidebar::ControllerItem +svx/source/sidebar/textcolumns/TextColumnsPropertyPanel.hxx:41 + svx::sidebar::TextColumnsPropertyPanel maColumnsSpacingController sfx2::sidebar::ControllerItem +svx/source/tbxctrls/tbcontrl.cxx:313 + (anonymous namespace)::SvxFontNameBox_Base m_aOwnFontList ::std::unique_ptr +sw/inc/accmap.hxx:96 + SwAccessibleMap mvShapes SwShapeList_Impl +sw/inc/swmodule.hxx:95 + SwModule m_pErrorHandler std::unique_ptr +sw/inc/swmodule.hxx:108 + SwModule m_xLinguServiceEventListener css::uno::Reference +sw/inc/swwait.hxx:45 + SwWait mpLockedDispatchers o3tl::sorted_vector +sw/inc/unoframe.hxx:311 + SwXOLEListener m_xOLEModel css::uno::Reference +sw/inc/view.hxx:194 + SwView m_xGlueDocShell std::unique_ptr +sw/source/core/inc/swfont.hxx:978 + SvStatistics nGetTextSize sal_uInt16 +sw/source/core/inc/swfont.hxx:979 + SvStatistics nDrawText sal_uInt16 +sw/source/core/inc/swfont.hxx:980 + SvStatistics nGetStretchTextSize sal_uInt16 +sw/source/core/inc/swfont.hxx:981 + SvStatistics nDrawStretchText sal_uInt16 +sw/source/core/inc/swfont.hxx:982 + SvStatistics nChangeFont sal_uInt16 +sw/source/core/inc/unoflatpara.hxx:135 + SwXFlatParagraphIterator m_aFlatParaList std::set > +sw/source/core/layout/dbg_lay.cxx:133 + SwImplProtocol m_aVars std::vector +sw/source/core/table/swtable.cxx:2791 + SwTableCellInfo::Impl m_HandledTableBoxes SwTableCellInfo::Impl::TableBoxes_t +sw/source/core/text/porfld.hxx:65 + SwFieldPortion m_nAttrFieldType sal_uInt16 +sw/source/core/unocore/unolinebreak.cxx:44 + SwXLineBreak::Impl m_wThis uno::WeakReference +sw/source/filter/html/swhtml.hxx:384 + SwHTMLParser m_aOrphanedTableBoxes std::vector > +sw/source/filter/inc/rtf.hxx:29 + RTFSurround::(anonymous union)::(anonymous) nGoldCut sal_uInt8 +sw/source/filter/inc/rtf.hxx:30 + RTFSurround::(anonymous union)::(anonymous) nOrder sal_uInt8 +sw/source/filter/inc/rtf.hxx:31 + RTFSurround::(anonymous union)::(anonymous) nJunk sal_uInt8 +sw/source/filter/inc/rtf.hxx:32 + RTFSurround::(anonymous) Flags struct (unnamed struct at /home/noel/libo2/sw/source/filter/inc/rtf.hxx:27:9) +sw/source/uibase/inc/glossary.hxx:63 + SwGlossaryDlg m_xGroupData std::vector > +sw/source/uibase/inc/maildispatcher.hxx:143 + MailDispatcher m_aListenerVector std::vector< ::rtl::Reference > +sw/source/uibase/inc/maildispatcher.hxx:149 + MailDispatcher m_xSelfReference ::rtl::Reference +sw/source/uibase/inc/navipi.hxx:59 + SwNavigationPI m_xContent2Dispatch std::unique_ptr +sw/source/uibase/inc/navipi.hxx:60 + SwNavigationPI m_xContent3Dispatch std::unique_ptr +sw/source/uibase/inc/redlndlg.hxx:64 + SwRedlineAcceptDlg m_RedlinData std::vector > +sw/source/uibase/inc/redlndlg.hxx:65 + SwRedlineAcceptDlg m_aUsedSeqNo class SwRedlineDataParentSortArr +sw/source/uibase/sidebar/TableEditPanel.hxx:48 + sw::sidebar::TableEditPanel m_xInsertDispatch std::unique_ptr +sw/source/uibase/sidebar/TableEditPanel.hxx:50 + sw::sidebar::TableEditPanel m_xSelectDispatch std::unique_ptr +sw/source/uibase/sidebar/TableEditPanel.hxx:52 + sw::sidebar::TableEditPanel m_xRowSizingDispatch std::unique_ptr +sw/source/uibase/sidebar/TableEditPanel.hxx:54 + sw::sidebar::TableEditPanel m_xColumnSizingDispatch std::unique_ptr +sw/source/uibase/sidebar/TableEditPanel.hxx:56 + sw::sidebar::TableEditPanel m_xDeleteDispatch std::unique_ptr +sw/source/uibase/sidebar/TableEditPanel.hxx:58 + sw::sidebar::TableEditPanel m_xSplitMergeDispatch std::unique_ptr +sw/source/uibase/sidebar/TableEditPanel.hxx:60 + sw::sidebar::TableEditPanel m_xMiscDispatch std::unique_ptr +sw/source/uibase/sidebar/WrapPropertyPanel.hxx:73 + sw::sidebar::WrapPropertyPanel mxWrapOptionsDispatch std::unique_ptr +testtools/source/bridgetest/cppobj.cxx:154 + bridge_object::(anonymous namespace)::Test_Impl _arStruct Sequence +ucb/source/ucp/gio/gio_mount.hxx:73 + OOoMountOperationClass parent_class GMountOperationClass +ucb/source/ucp/gio/gio_mount.hxx:76 + OOoMountOperationClass _gtk_reserved1 void (*)(void) +ucb/source/ucp/gio/gio_mount.hxx:77 + OOoMountOperationClass _gtk_reserved2 void (*)(void) +ucb/source/ucp/gio/gio_mount.hxx:78 + OOoMountOperationClass _gtk_reserved3 void (*)(void) +ucb/source/ucp/gio/gio_mount.hxx:79 + OOoMountOperationClass _gtk_reserved4 void (*)(void) +unoidl/source/unoidl.cxx:83 + unoidl::(anonymous namespace)::AggregatingCursor seen_ std::set +unoxml/source/rdf/librdf_repository.cxx:470 + (anonymous namespace)::librdf_GraphResult m_pQuery const std::shared_ptr +unoxml/source/rdf/librdf_repository.cxx:623 + (anonymous namespace)::librdf_QuerySelectResult m_pQuery const std::shared_ptr +unoxml/source/xpath/nodelist.hxx:51 + XPath::CNodeList m_pXPathObj std::shared_ptr +vbahelper/source/vbahelper/vbafillformat.hxx:36 + ScVbaFillFormat m_nForeColor sal_Int32 +vcl/inc/accel.hxx:39 + ImplAccelEntry mpAutoAccel class Accelerator * +vcl/inc/driverblocklist.hxx:114 + DriverBlocklist::DriverInfo maMsg rtl::OUString +vcl/inc/font/FontSelectPattern.hxx:65 + vcl::font::FontSelectPattern mfExactHeight float +vcl/inc/pdf/BitmapID.hxx:23 + vcl::pdf::BitmapID m_nChecksum BitmapChecksum +vcl/inc/pdf/BitmapID.hxx:24 + vcl::pdf::BitmapID m_nMaskChecksum BitmapChecksum +vcl/inc/qt5/QtFilePicker.hxx:76 + QtFilePicker m_pLayout class QGridLayout * +vcl/inc/salmenu.hxx:33 + SalItemParams pMenu VclPtr +vcl/inc/salmenu.hxx:34 + SalItemParams aText rtl::OUString +vcl/inc/salmenu.hxx:37 + SalItemParams nBits enum MenuItemBits +vcl/inc/salwtype.hxx:206 + SalSurroundingTextRequestEvent mnEnd sal_uLong +vcl/inc/salwtype.hxx:218 + SalQueryCharPositionEvent mnCursorBoundX tools::Long +vcl/inc/salwtype.hxx:219 + SalQueryCharPositionEvent mnCursorBoundY tools::Long +vcl/inc/salwtype.hxx:220 + SalQueryCharPositionEvent mnCursorBoundWidth tools::Long +vcl/inc/salwtype.hxx:221 + SalQueryCharPositionEvent mnCursorBoundHeight tools::Long +vcl/inc/salwtype.hxx:222 + SalQueryCharPositionEvent mbValid _Bool +vcl/inc/salwtype.hxx:223 + SalQueryCharPositionEvent mbVertical _Bool +vcl/inc/salwtype.hxx:250 + SalInputContext mpFont rtl::Reference +vcl/inc/salwtype.hxx:257 + SalSwipeEvent mnVelocityY double +vcl/inc/scanlinewriter.hxx:35 + vcl::ScanlineWriter mpCurrentScanline sal_uInt8 * +vcl/inc/svdata.hxx:462 + ImplSVEvent mpInstanceRef VclPtr +vcl/inc/unx/gtk/gtkdata.hxx:224 + DocumentFocusListener m_aRefList o3tl::sorted_vector > +vcl/inc/unx/gtk/gtkframe.hxx:81 + GtkSalFrame::IMHandler::PreviousKeyPress window GdkWindow * +vcl/inc/unx/gtk/gtkframe.hxx:82 + GtkSalFrame::IMHandler::PreviousKeyPress send_event gint8 +vcl/inc/unx/gtk/gtkframe.hxx:83 + GtkSalFrame::IMHandler::PreviousKeyPress time guint32 +vcl/qa/cppunit/pdfexport/pdfexport.cxx:71 + (anonymous namespace)::PdfExportTest mpPDFium std::shared_ptr +vcl/source/components/dtranscomp.cxx:214 + vcl::(anonymous namespace)::GenericDragSource m_xTrans css::uno::Reference +vcl/source/fontsubset/sft.cxx:98 + vcl::(anonymous namespace)::TTGlyphMetrics lsb sal_Int16 +vcl/source/fontsubset/ttcr.cxx:350 + vcl::(anonymous namespace)::tdata_post ptr void * +vcl/unx/generic/app/wmadaptor.cxx:1266 + _mwmhints deco unsigned long +vcl/unx/generic/app/wmadaptor.cxx:1266 + _mwmhints flags unsigned long +vcl/unx/generic/app/wmadaptor.cxx:1266 + _mwmhints func unsigned long +vcl/unx/generic/app/wmadaptor.cxx:1267 + _mwmhints input_mode tools::Long +vcl/unx/generic/app/wmadaptor.cxx:1268 + _mwmhints status unsigned long +vcl/unx/generic/gdi/cairotextrender.cxx:44 + (anonymous namespace)::CairoFontsCache::CacheId maFace (anonymous namespace)::FT_Face +vcl/unx/generic/gdi/cairotextrender.cxx:46 + (anonymous namespace)::CairoFontsCache::CacheId mbEmbolden _Bool +vcl/unx/generic/gdi/cairotextrender.cxx:47 + (anonymous namespace)::CairoFontsCache::CacheId mbVerticalMetrics _Bool +vcl/unx/gtk3/a11y/atkwrapper.hxx:50 + AtkObjectWrapper aParent AtkObject +vcl/unx/gtk3/a11y/atkwrapper.hxx:79 + AtkObjectWrapperClass aParentClass GtkWidgetAccessibleClass +vcl/unx/gtk3/glomenu.cxx:14 + GLOMenu parent_instance const GMenuModel +vcl/unx/gtk3/gtkinst.cxx:19880 + (anonymous namespace)::GtkInstanceComboBox m_xCustomMenuButtonHelper std::unique_ptr +vcl/unx/gtk3/hudawareness.cxx:18 + (anonymous namespace)::HudAwarenessHandle connection gpointer +vcl/unx/gtk3/hudawareness.cxx:21 + (anonymous namespace)::HudAwarenessHandle notify GDestroyNotify +vcl/workben/vcldemo.cxx:1740 + (anonymous namespace)::DemoWin mxThread rtl::Reference +writerfilter/source/dmapper/DocumentProtection.hxx:50 + writerfilter::dmapper::DocumentProtection m_sRedlineProtectionKey rtl::OUString +writerfilter/source/dmapper/DomainMapperTableHandler.cxx:240 + writerfilter::dmapper::TableInfo aTablePropertyIds std::vector +writerfilter/source/dmapper/PropertyMap.hxx:219 + writerfilter::dmapper::SectionPropertyMap m_nDebugSectionNumber sal_Int32 +writerfilter/source/dmapper/SdtHelper.hxx:76 + writerfilter::dmapper::SdtHelper m_sDataBindingStoreItemID rtl::OUString +writerfilter/source/dmapper/WriteProtection.hxx:36 + writerfilter::dmapper::WriteProtection m_nCryptProviderType sal_Int32 +xmlhelp/source/cxxhelp/provider/databases.hxx:249 + chelp::Databases m_aDatabases chelp::Databases::DatabasesTable +xmlhelp/source/cxxhelp/provider/databases.hxx:255 + chelp::Databases m_aModInfo chelp::Databases::ModInfoTable +xmlhelp/source/cxxhelp/provider/databases.hxx:258 + chelp::Databases m_aKeywordInfo chelp::Databases::KeywordInfoTable +xmlhelp/source/cxxhelp/provider/databases.hxx:264 + chelp::Databases m_aZipFileTable chelp::Databases::ZipFileTable +xmlhelp/source/cxxhelp/provider/databases.hxx:270 + chelp::Databases m_aCollatorTable chelp::Databases::CollatorTable +xmloff/source/draw/ximpstyl.hxx:215 + SdXMLMasterStylesContext maMasterPageList std::vector > +xmloff/source/forms/elementexport.hxx:46 + xmloff::OElementExport m_pXMLElement std::unique_ptr +xmloff/source/forms/elementexport.hxx:103 + xmloff::OControlExport m_pOuterElement std::unique_ptr +xmloff/source/forms/officeforms.hxx:68 + xmloff::OFormsRootExport m_pImplElement std::unique_ptr +xmloff/source/text/txtimp.cxx:105 + XMLTextImportHelper::Impl m_xFrameImpPrMap rtl::Reference +xmlsecurity/inc/certificatechooser.hxx:53 + CertificateChooser mvUserData std::vector > +xmlsecurity/inc/certificateviewer.hxx:50 + CertificateViewer mxGeneralPage std::unique_ptr +xmlsecurity/inc/certificateviewer.hxx:51 + CertificateViewer mxDetailsPage std::unique_ptr +xmlsecurity/source/helper/pdfsignaturehelper.cxx:237 + (anonymous namespace)::PageChecksum m_nPageContent BitmapChecksum +xmlsecurity/source/helper/pdfsignaturehelper.cxx:238 + (anonymous namespace)::PageChecksum m_aAnnotations std::vector diff --git a/compilerplugins/clang/unusedfieldsremove.cxx b/compilerplugins/clang/unusedfieldsremove.cxx new file mode 100644 index 000000000..61df036f2 --- /dev/null +++ b/compilerplugins/clang/unusedfieldsremove.cxx @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if !defined _WIN32 //TODO, #include + +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" +#include +#include +#include +#include +#include +#include +#include + +/** + This is intended to be run as the second stage of the "unusedfields" clang plugin. +*/ + +namespace { + +class UnusedFieldsRemove: + public loplugin::FilteringRewritePlugin +{ +public: + explicit UnusedFieldsRemove(loplugin::InstantiationData const & data); + ~UnusedFieldsRemove(); + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitFieldDecl( const FieldDecl* var ); +private: + // I use a brute-force approach - mmap the results file and do a linear search on it + // It works surprisingly well, because the file is small enough to fit into L2 cache on modern CPU's + size_t mmapFilesize; + int mmapFD; + char* mmappedData; +}; + +size_t getFilesize(const char* filename) +{ + struct stat st; + stat(filename, &st); + return st.st_size; +} + +UnusedFieldsRemove::UnusedFieldsRemove(loplugin::InstantiationData const & data): FilteringRewritePlugin(data) +{ + static const char sInputFile[] = SRCDIR "/result.txt"; + mmapFilesize = getFilesize(sInputFile); + //Open file + mmapFD = open(sInputFile, O_RDONLY, 0); + assert(mmapFD != -1); + //Execute mmap + mmappedData = static_cast(mmap(NULL, mmapFilesize, PROT_READ, MAP_PRIVATE, mmapFD, 0)); + assert(mmappedData != NULL); +} + +UnusedFieldsRemove::~UnusedFieldsRemove() +{ + //Cleanup + int rc = munmap(mmappedData, mmapFilesize); + assert(rc == 0); + (void)rc; + close(mmapFD); +} + +std::string niceName(const FieldDecl* fieldDecl) +{ + return fieldDecl->getParent()->getQualifiedNameAsString() + " " + + fieldDecl->getNameAsString(); +} + +bool UnusedFieldsRemove::VisitFieldDecl( const FieldDecl* fieldDecl ) +{ + if (rewriter == nullptr) { + return true; + } + if (ignoreLocation(fieldDecl)) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( + fieldDecl->getCanonicalDecl()->getLocation()))) { + return true; + } + + // don't mess with templates +/* if (isa(fieldDecl->getParent())) { + if (dyn_cast(fieldDecl->getParent())->getDescribedClassTemplate() != nullptr) { + return true; + } + } +*/ + std::string aNiceName = " " + niceName(fieldDecl) + "\n"; + const char *aNiceNameStr = aNiceName.c_str(); + char* found = std::search(mmappedData, mmappedData + mmapFilesize, aNiceNameStr, aNiceNameStr + strlen(aNiceNameStr)); + if(!(found < mmappedData + mmapFilesize)) { + return true; + } + SourceRange replaceRange(fieldDecl->getSourceRange()); + // sometimes the declaration has a semicolon just after it, and it's much neater to remove that too. + if (rewriter->getRewrittenText(SourceRange(replaceRange.getEnd(), replaceRange.getEnd().getLocWithOffset(1))) == ";") { + replaceRange.setEnd(replaceRange.getEnd().getLocWithOffset(1)); + } + // remove leading spaces + while (rewriter->getRewrittenText(SourceRange(replaceRange.getBegin().getLocWithOffset(-1), replaceRange.getBegin())) == " ") + { + replaceRange.setBegin(replaceRange.getBegin().getLocWithOffset(-1)); + } + if (!replaceText(replaceRange, "")) { + report( + DiagnosticsEngine::Warning, + "Could not remove unused field (" + niceName(fieldDecl) + ")", + fieldDecl->getBeginLoc()) + << fieldDecl->getSourceRange(); + } + return true; +} + + +loplugin::Plugin::Registration< UnusedFieldsRemove > X("unusedfieldsremove", false); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unusedindex.cxx b/compilerplugins/clang/unusedindex.cxx new file mode 100644 index 000000000..63b9d4dca --- /dev/null +++ b/compilerplugins/clang/unusedindex.cxx @@ -0,0 +1,87 @@ + +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +/* + Mike Kaganski found a bug where the code was looping over a block and + not using the index var, and the loop was unnecessary. + So he wanted to have a look for other places like that. +*/ +namespace +{ +class UnusedIndex : public loplugin::FilteringPlugin +{ +public: + explicit UnusedIndex(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool TraverseForStmt(ForStmt* stmt); + bool VisitDeclRefExpr(DeclRefExpr const* stmt); + +private: + std::vector mLoopVarDecls; + std::unordered_set mFoundSet; +}; + +bool UnusedIndex::TraverseForStmt(ForStmt* stmt) +{ + if (ignoreLocation(stmt)) + return true; + + VarDecl const* loopVarDecl = nullptr; + if (stmt->getInit()) + { + auto declStmt = dyn_cast(stmt->getInit()); + if (declStmt && declStmt->isSingleDecl()) + { + loopVarDecl = dyn_cast(declStmt->getSingleDecl()); + } + } + if (loopVarDecl) + mLoopVarDecls.push_back(loopVarDecl); + + // deliberately ignore the other parts of the for stmt, except for the body + auto ret = RecursiveASTVisitor::TraverseStmt(stmt->getBody()); + + if (loopVarDecl && mFoundSet.erase(loopVarDecl) == 0) + report(DiagnosticsEngine::Warning, "loop variable not used", loopVarDecl->getBeginLoc()) + << loopVarDecl->getSourceRange(); + + if (loopVarDecl) + mLoopVarDecls.pop_back(); + return ret; +} + +bool UnusedIndex::VisitDeclRefExpr(DeclRefExpr const* stmt) +{ + auto varDecl = dyn_cast(stmt->getDecl()); + if (!varDecl) + return true; + if (std::find(mLoopVarDecls.begin(), mLoopVarDecls.end(), varDecl) != mLoopVarDecls.end()) + mFoundSet.insert(varDecl); + return true; +} + +loplugin::Plugin::Registration X("unusedindex", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unusedmember.cxx b/compilerplugins/clang/unusedmember.cxx new file mode 100644 index 000000000..7ee433ca2 --- /dev/null +++ b/compilerplugins/clang/unusedmember.cxx @@ -0,0 +1,441 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// A more aggressive check for unused C struct/C++ class members than what plain Clang offers. On +// the one hand, unlike -Wunused-private-field, it warns about all members regardless of access +// specifiers, if all code that can use a class has been seen. On the other hand, it warns about +// all kinds of members. But it uses some heuristics (the type showing up in sizeof, alignof, +// offsetof, certain casts) to determine that seemingly unused data members are probably used after +// all; the used heuristics were enough to not require any explicit [[maybe_unused]] decorations +// across the existing code base. + +#include +#include + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" + +namespace +{ +// Whether the CXXRecordDecl itself or one of its enclosing classes is a template: +bool isTemplated(CXXRecordDecl const* decl) +{ + if (decl->getDescribedClassTemplate() != nullptr) + { + return true; + } + if (auto const d = dyn_cast(decl->getParent())) + { + return isTemplated(d); + } + return false; +} + +bool isWarnUnusedType(QualType type) +{ + if (auto const t = type->getAs()) + { + if (t->getDecl()->hasAttr()) + { + return true; + } + } + return loplugin::isExtraWarnUnusedType(type); +} + +class UnusedMember final : public loplugin::FilteringPlugin +{ +public: + explicit UnusedMember(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool VisitDeclaratorDecl(DeclaratorDecl const* decl) + { + // For declarations like + // + // enum E { ... } e; + // + // it may be that the declaration of E is not marked as referenced even though the + // declaration of e clearly references it: + if (auto const t = decl->getType()->getAs()) + { + deferred_.erase(t->getDecl()); + } + return true; + } + + bool VisitCXXRecordDecl(CXXRecordDecl const* decl) //TODO: non-CXX RecordDecl? + { + if (ignoreLocation(decl)) + { + return true; + } + if (!decl->isThisDeclarationADefinition()) + { + return true; + } + if (!handler.isAllRelevantCodeDefined(decl)) + { + return true; + } + if (!compiler.getSourceManager().isInMainFile(decl->getLocation())) + { + // include/rtl/instance.hxx declares entities in an unnamed namespace + return true; + } + if (isTemplated(decl) || isa(decl)) + { + return true; + } + if (decl->isUnion() && decl->getIdentifier() == nullptr) + { + return true; //TODO + } + for (auto i = decl->decls_begin(); i != decl->decls_end(); ++i) + { + auto const d = *i; + if (d->isImplicit() || isa(d) || isa(d)) + { + //TODO: only filter out UsingDecls that are actually used (if only to silence + // -Woverloaded-virtual) + continue; + } + if (isa(d) || isa(d)) + { + //TODO: only filter out ones that are not instantiated at all + continue; + } + if (auto const d1 = dyn_cast(d)) + { + //TODO: determine whether the friendship is actually required + auto const d2 = d1->getFriendDecl(); + if (d2 == nullptr) + { // happens for "friend class C;" + continue; + } + if (auto const d3 = dyn_cast(d2)) + { +#if 0 //TODO: friend function definitions are not marked as referenced even if used? + if (!d3->isThisDeclarationADefinition()) //TODO: do this check for all kinds? +#endif + { + continue; + } + } + } + if (d->isReferenced()) + { + continue; + } + if (d->hasAttr()) + { + continue; + } + // Check individual members instead of the whole CXXRecordDecl for coming from a macro, + // as CppUnit's CPPUNIT_TEST_SUITE_END (cppunit/extensions/HelperMacros.h) contains a + // partial member list ending in + // + // private: /* dummy typedef so that the macro can still end with ';'*/ + // typedef int CppUnitDummyTypedefForSemiColonEnding__ + // + if (compiler.getSourceManager().isMacroBodyExpansion(d->getLocation())) + { + return true; + } + if (auto const d1 = dyn_cast(d)) + { + if (d1->isUnnamedBitfield()) + { + continue; + } + if (!isWarnWhenUnusedType(d1->getType())) + { + continue; + } + deferred_.insert(d1); + continue; + } + if (auto const d1 = dyn_cast(d)) + { + if (d1->isDeletedAsWritten()) // TODO: just isDeleted? + { + continue; + } + if (d1->isExplicitlyDefaulted()) + { + continue; + } + } + else if (auto const d2 = dyn_cast(d)) + { + if (d2->getIdentifier() == nullptr) + { + continue; + } + if (isa(d2)) + { + deferred_.insert(d2); + continue; + } + } + else if (auto const d3 = dyn_cast(d)) + { + // Some types, like (specializations of) std::iterator_traits, have specific + // requirements on their members; only covers std::iterator_traits for now (TODO: + // check that at least some member is actually used) + // (isa(decl) is already filtered out + // above): + if (isa(decl) + && loplugin::DeclCheck(decl).Struct("iterator_traits").StdNamespace()) + { + auto const id = d3->getIdentifier(); + assert(id != nullptr); + auto const n = id->getName(); + if (n == "difference_type" || n == "iterator_category" || n == "pointer" + || n == "reference" || n == "value_type") + { + continue; + } + } + } + report(DiagnosticsEngine::Warning, "unused class member", d->getLocation()) + << d->getSourceRange(); + } + return true; + } + + bool VisitOffsetOfExpr(OffsetOfExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const t1 = expr->getTypeSourceInfo()->getType(); + RecordDecl const* d; + if (auto const t2 = t1->getAs()) + { + d = t2->getDecl(); + } + else + { + d = t1->castAs()->getDecl(); + } + recordRecordDeclAndBases(d); + return true; + } + + bool VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + switch (expr->getKind()) + { + case UETT_SizeOf: + case UETT_AlignOf: + case UETT_PreferredAlignOf: + break; + default: + return true; + } + if (!expr->isArgumentType()) + { + return true; + } + auto t = expr->getArgumentType(); + if (auto const t1 = t->getAs()) + { + t = t1->getPointeeType(); + } + if (auto const t1 = t->getAsArrayTypeUnsafe()) + { + t = compiler.getASTContext().getBaseElementType(t1); + } + if (auto const t1 = t->getAs()) + { + recordRecordDeclAndBases(t1->getDecl()); + } + return true; + } + + // Handling implicit, C-style, static and reinterpret casts between void* and record types + // (though reinterpret_cast would be ruled out by loplugin:redundantcast): + bool VisitCastExpr(CastExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const t1 = expr->getType(); + auto const t2 = compat::getSubExprAsWritten(expr)->getType(); + if (loplugin::TypeCheck(t1).Pointer().Void()) + { + recordCastedRecordDecl(t2); + } + else if (loplugin::TypeCheck(t2).Pointer().Void()) + { + recordCastedRecordDecl(t1); + } + return true; + } + + bool VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + recordCastedRecordDecl(expr->getTypeAsWritten()); + recordCastedRecordDecl(expr->getSubExprAsWritten()->getType()); + return true; + } + + bool VisitElaboratedTypeLoc(ElaboratedTypeLoc tloc) + { + if (ignoreLocation(tloc)) + { + return true; + } + auto const tl = tloc.getNamedTypeLoc().getAs(); + if (tl.isNull()) + { + return true; + } + if (tl.isDefinition()) + { + return true; + } + if (auto const d = dyn_cast(tl.getDecl())) + { + // For some reason, using an elaborated type specifier in (at least) a FieldDecl, as in + // + // enum E { ... }; + // enum E e; + // + // doesn't cause the EnumDecl to be marked as referenced. (This should fix it, but note + // the warning at : + // "[...] a type written 'struct foo' should be represented as an ElaboratedTypeLoc. We + // currently only do that when C++ is enabled [...]" + deferred_.erase(d->getCanonicalDecl()); + } + return true; + } + + void postRun() override + { + for (auto const d : deferred_) + { + if (auto const d1 = dyn_cast(d)) + { + bool layout = false; + for (auto d2 = d1->getParent();;) + { + if (layout_.find(d2->getCanonicalDecl()) != layout_.end()) + { + layout = true; + break; + } + // Heuristic to recursively check parent RecordDecl if given RecordDecl is + // unnamed and either an anonymous struct (or union, but which are already + // filtered out anyway), or defined in a non-static data member declaration + // (TODO: which is erroneously approximated here with getTypedefNameForAnonDecl + // for now, which fails to filter out RecordDecls in static data member + // declarations): + if (!(d2->getDeclName().isEmpty() + && (d2->isAnonymousStructOrUnion() + || d2->getTypedefNameForAnonDecl() == nullptr))) + { + break; + } + d2 = dyn_cast(d2->getParent()); + if (d2 == nullptr) + { + break; + } + } + if (layout) + { + continue; + } + } + report(DiagnosticsEngine::Warning, "unused class member", d->getLocation()) + << d->getSourceRange(); + } + } + +private: + void run() override + { + if (TraverseDecl(compiler.getASTContext().getTranslationUnitDecl())) + { + postRun(); + } + } + + bool isWarnWhenUnusedType(QualType type) + { + auto t = type; + if (auto const t1 = t->getAs()) + { + t = t1->getPointeeType(); + } + return t.isTrivialType(compiler.getASTContext()) || isWarnUnusedType(t); + } + + void recordRecordDeclAndBases(RecordDecl const* decl) + { + if (!layout_.insert(decl->getCanonicalDecl()).second) + { + return; + } + if (auto const d2 = dyn_cast_or_null(decl->getDefinition())) + { + for (auto i = d2->bases_begin(); i != d2->bases_end(); ++i) + { + recordRecordDeclAndBases(i->getType()->castAs()->getDecl()); + } + //TODO: doesn't iterate vbases, but presence of such would run counter to the layout + // heuristic anyway + } + } + + void recordCastedRecordDecl(QualType type) + { + for (auto t = type;;) + { + if (auto const t1 = t->getAs()) + { + t = t1->getPointeeType(); + continue; + } + if (auto const t1 = t->getAs()) + { + recordRecordDeclAndBases(t1->getDecl()); + } + break; + } + } + + // RecordDecls whose layout (i.e., contained FieldDecls) must presumably not be changed: + std::set layout_; + + std::set deferred_; +}; + +loplugin::Plugin::Registration unusedmember("unusedmember"); +} + +// Cannot be shared, uses TraverseStmt(). + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/unusedmethods.cxx b/compilerplugins/clang/unusedmethods.cxx new file mode 100644 index 000000000..41b1317d4 --- /dev/null +++ b/compilerplugins/clang/unusedmethods.cxx @@ -0,0 +1,464 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include + + +#include "clang/AST/Attr.h" + +#include "config_clang.h" + +#include "plugin.hxx" + +/** +This plugin performs 3 different analyses: + +(1) Find unused methods +(2) Find methods whose return types are never evaluated +(3) Find methods which are public, but are never called from outside the class i.e. they can be private + +It does so, by dumping various call/definition/use info to a log file. +Then we will post-process the various lists and find the set of unused methods. + +Be warned that it produces around 15G of log file. + +The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='unusedmethods' check + $ ./compilerplugins/clang/unusedmethods.py + +and then + $ for dir in *; do make FORCE_COMPILE=all UPDATE_FILES=$dir COMPILER_PLUGIN_TOOL='unusedmethodsremove' $dir; done +to auto-remove the method declarations + +Note that the actual process may involve a fair amount of undoing, hand editing, and general messing around +to get it to work :-) + +*/ + +namespace { + +struct MyFuncInfo +{ + std::string access; + std::string returnType; + std::string nameAndParams; + std::string sourceLocation; + std::string virtualness; + +}; +bool operator < (const MyFuncInfo &lhs, const MyFuncInfo &rhs) +{ + return std::tie(lhs.returnType, lhs.nameAndParams) + < std::tie(rhs.returnType, rhs.nameAndParams); +} + +// try to limit the voluminous output a little + +// for the "unused method" analysis +static std::set callSet; +static std::set definitionSet; +// for the "unused return type" analysis +static std::set usedReturnSet; +// for the "can be private" analysis +static std::set calledFromOutsideSet; + + +class UnusedMethods: + public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit UnusedMethods(loplugin::InstantiationData const & data): + Plugin(data) {} + + virtual void run() override + { + StringRef fn(handler.getMainFileName()); + // ignore external code, makes this run faster + if (fn.contains("UnpackedTarball")) + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + + std::string output; + for (const MyFuncInfo & s : definitionSet) + { + output += "definition:\t" + s.access + "\t" + s.returnType + "\t" + s.nameAndParams + + "\t" + s.sourceLocation + "\t" + s.virtualness + "\n"; + } + // for the "unused method" analysis + for (const MyFuncInfo & s : callSet) + output += "call:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; + // for the "unused return type" analysis + for (const MyFuncInfo & s : usedReturnSet) + output += "usedReturn:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; + // for the "method can be private" analysis + for (const MyFuncInfo & s : calledFromOutsideSet) + output += "outside:\t" + s.returnType + "\t" + s.nameAndParams + "\n"; + std::ofstream myfile; + myfile.open( WORKDIR "/loplugin.unusedmethods.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + + bool shouldVisitTemplateInstantiations () const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitCallExpr(CallExpr* ); + bool VisitFunctionDecl( const FunctionDecl* decl ); + bool VisitDeclRefExpr( const DeclRefExpr* ); + bool VisitCXXConstructExpr( const CXXConstructExpr* ); + bool TraverseCXXRecordDecl( CXXRecordDecl* ); + bool TraverseFunctionDecl( FunctionDecl* ); + bool TraverseCXXMethodDecl( CXXMethodDecl* ); + bool TraverseCXXConversionDecl( CXXConversionDecl* ); + bool TraverseCXXDeductionGuideDecl( CXXDeductionGuideDecl* ); + +private: + void logCallToRootMethods(const FunctionDecl* functionDecl, std::set& funcSet); + MyFuncInfo niceName(const FunctionDecl* functionDecl); + std::string toString(SourceLocation loc); + void functionTouchedFromExpr( const FunctionDecl* calleeFunctionDecl, const Expr* expr ); + bool ignoreLocation(SourceLocation loc); + bool checkIgnoreLocation(SourceLocation loc); + + CXXRecordDecl const * currentCxxRecordDecl = nullptr; + FunctionDecl const * currentFunctionDecl = nullptr; +}; + +MyFuncInfo UnusedMethods::niceName(const FunctionDecl* functionDecl) +{ + for(;;) + { + if (functionDecl->getInstantiatedFromMemberFunction()) + functionDecl = functionDecl->getInstantiatedFromMemberFunction(); + else if (functionDecl->getTemplateInstantiationPattern()) + functionDecl = functionDecl->getTemplateInstantiationPattern(); + else + break; + } + + MyFuncInfo aInfo; + switch (functionDecl->getAccess()) + { + case AS_public: aInfo.access = "public"; break; + case AS_private: aInfo.access = "private"; break; + case AS_protected: aInfo.access = "protected"; break; + default: aInfo.access = "unknown"; break; + } + if (!isa(functionDecl)) { + aInfo.returnType = functionDecl->getReturnType().getCanonicalType().getAsString(); + } else { + aInfo.returnType = ""; + } + + if (auto methodDecl = dyn_cast(functionDecl)) { + const CXXRecordDecl* recordDecl = methodDecl->getParent(); + aInfo.nameAndParams = recordDecl->getQualifiedNameAsString() + + "::" + + functionDecl->getNameAsString() + + "("; + if (methodDecl->isVirtual()) + aInfo.virtualness = "virtual"; + } + else + { + aInfo.nameAndParams = functionDecl->getQualifiedNameAsString() + "("; + } + bool bFirst = true; + for (const ParmVarDecl *pParmVarDecl : functionDecl->parameters()) { + if (bFirst) + bFirst = false; + else + aInfo.nameAndParams += ","; + aInfo.nameAndParams += pParmVarDecl->getType().getCanonicalType().getAsString(); + } + aInfo.nameAndParams += ")"; + if (isa(functionDecl) && dyn_cast(functionDecl)->isConst()) { + aInfo.nameAndParams += " const"; + } + + aInfo.sourceLocation = toString( functionDecl->getLocation() ); + + return aInfo; +} + +/** + * Our need to see everything conflicts with the PCH code in pluginhandler::ignoreLocation, + * so we have to do this ourselves. + */ +bool UnusedMethods::ignoreLocation(SourceLocation loc) +{ + static std::unordered_map checkedMap; + auto it = checkedMap.find(loc); + if (it != checkedMap.end()) + return it->second; + bool ignore = checkIgnoreLocation(loc); + checkedMap.emplace(loc, ignore); + return ignore; +} + +bool UnusedMethods::checkIgnoreLocation(SourceLocation loc) +{ + // simplified form of the code in PluginHandler::checkIgnoreLocation + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( loc ); + if( compiler.getSourceManager().isInSystemHeader( expansionLoc )) + return true; + PresumedLoc presumedLoc = compiler.getSourceManager().getPresumedLoc( expansionLoc ); + if( presumedLoc.isInvalid()) + return true; + const char* bufferName = presumedLoc.getFilename(); + if (bufferName == NULL + || loplugin::hasPathnamePrefix(bufferName, SRCDIR "/external/") + || loplugin::hasPathnamePrefix(bufferName, WORKDIR "/")) + return true; + if( loplugin::hasPathnamePrefix(bufferName, BUILDDIR "/") + || loplugin::hasPathnamePrefix(bufferName, SRCDIR "/") ) + return false; // ok + return true; +} + +std::string UnusedMethods::toString(SourceLocation loc) +{ + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc( loc ); + StringRef name = getFilenameOfLocation(expansionLoc); + std::string sourceLocation = std::string(name.substr(strlen(SRCDIR)+1)) + ":" + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(sourceLocation); + return sourceLocation; +} + +// For virtual/overriding methods, we need to pretend we called the root method(s), +// so that they get marked as used. +void UnusedMethods::logCallToRootMethods(const FunctionDecl* functionDecl, std::set& funcSet) +{ + functionDecl = functionDecl->getCanonicalDecl(); + bool bCalledSuperMethod = false; + if (isa(functionDecl)) { + const CXXMethodDecl* methodDecl = dyn_cast(functionDecl); + for(CXXMethodDecl::method_iterator it = methodDecl->begin_overridden_methods(); + it != methodDecl->end_overridden_methods(); ++it) + { + logCallToRootMethods(*it, funcSet); + bCalledSuperMethod = true; + } + } + if (!bCalledSuperMethod) + { + while (functionDecl->getTemplateInstantiationPattern()) + functionDecl = functionDecl->getTemplateInstantiationPattern(); + if (functionDecl->getLocation().isValid() && !ignoreLocation( functionDecl->getBeginLoc() ) + && !functionDecl->isExternC()) + funcSet.insert(niceName(functionDecl)); + } +} + +bool UnusedMethods::VisitCallExpr(CallExpr* expr) +{ + // Note that I don't ignore ANYTHING here, because I want to get calls to my code that result + // from template instantiation deep inside the STL and other external code + + FunctionDecl* calleeFunctionDecl = expr->getDirectCallee(); + if (calleeFunctionDecl == nullptr) { + Expr* callee = expr->getCallee()->IgnoreParenImpCasts(); + DeclRefExpr* dr = dyn_cast(callee); + if (dr) { + calleeFunctionDecl = dyn_cast(dr->getDecl()); + if (calleeFunctionDecl) + goto gotfunc; + } + return true; + } + +gotfunc: + + + if (currentFunctionDecl == calleeFunctionDecl) + ; // for "unused method" analysis, ignore recursive calls + else if (currentFunctionDecl + && currentFunctionDecl->getIdentifier() + && currentFunctionDecl->getName() == "Clone" + && currentFunctionDecl->getParent() == calleeFunctionDecl->getParent() + && isa(calleeFunctionDecl)) + ; // if we are inside Clone(), ignore calls to the same class's constructor + else + logCallToRootMethods(calleeFunctionDecl, callSet); + + const Stmt* parent = getParentStmt(expr); + + // Now do the checks necessary for the "can be private" analysis + CXXMethodDecl* calleeMethodDecl = dyn_cast(calleeFunctionDecl); + if (calleeMethodDecl && calleeMethodDecl->getAccess() != AS_private) + { + const FunctionDecl* parentFunctionOfCallSite = getParentFunctionDecl(expr); + if (parentFunctionOfCallSite != calleeFunctionDecl) { + if (!parentFunctionOfCallSite || !ignoreLocation(parentFunctionOfCallSite->getBeginLoc())) { + calledFromOutsideSet.insert(niceName(calleeFunctionDecl)); + } + } + } + + // Now do the checks necessary for the "unused return value" analysis + if (calleeFunctionDecl->getReturnType()->isVoidType()) { + return true; + } + if (!parent) { + // we will get null parent if it's under a CXXConstructExpr node + logCallToRootMethods(calleeFunctionDecl, usedReturnSet); + return true; + } + if (isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent)) + { + logCallToRootMethods(calleeFunctionDecl, usedReturnSet); + return true; + } + if (isa(parent) || isa(parent) || isa(parent) + || isa(parent)) + { + return true; + } + parent->dump(); + return true; +} + +bool UnusedMethods::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr ) +{ + // Note that I don't ignore ANYTHING here, because I want to get calls to my code that result + // from template instantiation deep inside the STL and other external code + + const CXXConstructorDecl* constructorDecl = constructExpr->getConstructor(); + constructorDecl = constructorDecl->getCanonicalDecl(); + + if (!constructorDecl->getLocation().isValid() || ignoreLocation(constructorDecl->getBeginLoc())) { + return true; + } + + logCallToRootMethods(constructorDecl, callSet); + + // Now do the checks necessary for the "can be private" analysis + if (constructorDecl->getParent() != currentCxxRecordDecl) + calledFromOutsideSet.insert(niceName(constructorDecl)); + + return true; +} + +bool UnusedMethods::VisitFunctionDecl( const FunctionDecl* functionDecl ) +{ + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) { + return true; + } + const FunctionDecl* canonicalFunctionDecl = functionDecl->getCanonicalDecl(); + if (isa(functionDecl)) { + return true; + } + if (functionDecl->isDeleted() || functionDecl->isDefaulted()) { + return true; + } + if (isa(functionDecl) + && dyn_cast(functionDecl)->isCopyOrMoveConstructor()) + { + return true; + } + if (!canonicalFunctionDecl->getLocation().isValid() || ignoreLocation(canonicalFunctionDecl->getBeginLoc())) { + return true; + } + // ignore method overrides, since the call will show up as being directed to the root method + const CXXMethodDecl* methodDecl = dyn_cast(functionDecl); + if (methodDecl && (methodDecl->size_overridden_methods() != 0 || methodDecl->hasAttr())) { + return true; + } + if (!functionDecl->isExternC()) { + MyFuncInfo funcInfo = niceName(canonicalFunctionDecl); + definitionSet.insert(funcInfo); + } + return true; +} + +bool UnusedMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) +{ + const FunctionDecl* functionDecl = dyn_cast(declRefExpr->getDecl()); + if (!functionDecl) { + return true; + } + logCallToRootMethods(functionDecl->getCanonicalDecl(), callSet); + logCallToRootMethods(functionDecl->getCanonicalDecl(), usedReturnSet); + + // Now do the checks necessary for the "can be private" analysis + const CXXMethodDecl* methodDecl = dyn_cast(functionDecl); + if (methodDecl && methodDecl->getAccess() != AS_private) + { + const FunctionDecl* parentFunctionOfCallSite = getParentFunctionDecl(declRefExpr); + if (parentFunctionOfCallSite != functionDecl) { + if (!parentFunctionOfCallSite || !ignoreLocation(parentFunctionOfCallSite->getBeginLoc())) { + calledFromOutsideSet.insert(niceName(functionDecl)); + } + } + } + + return true; +} + +bool UnusedMethods::TraverseCXXRecordDecl(CXXRecordDecl* cxxRecordDecl) +{ + auto copy = currentCxxRecordDecl; + currentCxxRecordDecl = cxxRecordDecl; + bool ret = RecursiveASTVisitor::TraverseCXXRecordDecl(cxxRecordDecl); + currentCxxRecordDecl = copy; + return ret; +} + +bool UnusedMethods::TraverseFunctionDecl(FunctionDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseFunctionDecl(f); + currentFunctionDecl = copy; + return ret; +} +bool UnusedMethods::TraverseCXXMethodDecl(CXXMethodDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(f); + currentFunctionDecl = copy; + return ret; +} +bool UnusedMethods::TraverseCXXConversionDecl(CXXConversionDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseCXXConversionDecl(f); + currentFunctionDecl = copy; + return ret; +} +bool UnusedMethods::TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseCXXDeductionGuideDecl(f); + currentFunctionDecl = copy; + return ret; +} + +loplugin::Plugin::Registration< UnusedMethods > X("unusedmethods", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unusedmethods.py b/compilerplugins/clang/unusedmethods.py new file mode 100755 index 000000000..1a04e8180 --- /dev/null +++ b/compilerplugins/clang/unusedmethods.py @@ -0,0 +1,309 @@ +#!/usr/bin/python3 + +import sys +import re +import io + +# -------------------------------------------------------------------------------------------- +# globals +# -------------------------------------------------------------------------------------------- + +definitionSet = set() # set of tuple(return_type, name_and_params) +definitionToSourceLocationMap = dict() + +# for the "unused methods" analysis +callSet = set() # set of tuple(return_type, name_and_params) + +# for the "method can be private" analysis +publicDefinitionSet = set() # set of tuple(return_type, name_and_params) +protectedDefinitionSet = set() # set of tuple(return_type, name_and_params) +calledFromOutsideSet = set() # set of tuple(return_type, name_and_params) +virtualSet = set() # set of tuple(return_type, name_and_params) + +# for the "unused return types" analysis +usedReturnSet = set() # set of tuple(return_type, name_and_params) + +# clang does not always use exactly the same numbers in the type-parameter vars it generates +# so I need to substitute them to ensure we can match correctly. +normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") +def normalizeTypeParams( line ): + return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) + +# -------------------------------------------------------------------------------------------- +# primary input loop +# -------------------------------------------------------------------------------------------- + +with io.open("workdir/loplugin.unusedmethods.log", "r", buffering=16*1024*1024) as txt: + for line in txt: + tokens = line.strip().split("\t") + if tokens[0] == "definition:": + access = tokens[1] + returnType = tokens[2] + nameAndParams = tokens[3] + sourceLocation = tokens[4] + virtual = "" + if len(tokens)>=6: virtual = tokens[5] + funcInfo = (normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams)) + definitionSet.add(funcInfo) + if access == "public": + publicDefinitionSet.add(funcInfo) + elif access == "protected": + protectedDefinitionSet.add(funcInfo) + definitionToSourceLocationMap[funcInfo] = sourceLocation + if virtual == "virtual": + virtualSet.add(funcInfo) + elif tokens[0] == "call:": + returnType = tokens[1] + nameAndParams = tokens[2] + callSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))) + elif tokens[0] == "usedReturn:": + returnType = tokens[1] + nameAndParams = tokens[2] + usedReturnSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))) + elif tokens[0] == "outside:": + returnType = tokens[1] + nameAndParams = tokens[2] + calledFromOutsideSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))) + else: + print( "unknown line: " + line) + +# Invert the definitionToSourceLocationMap. +sourceLocationToDefinitionMap = {} +for k, v in definitionToSourceLocationMap.items(): + sourceLocationToDefinitionMap[v] = sourceLocationToDefinitionMap.get(v, []) + sourceLocationToDefinitionMap[v].append(k) + +def isOtherConstness( d, callSet ): + method = d[0] + " " + d[1] + # if this method is const, and there is a non-const variant of it, and the non-const variant is in use, then leave it alone + if d[0].startswith("const ") and d[1].endswith(" const"): + if ((d[0][6:],d[1][:-6]) in callSet): + return True + elif method.endswith(" const"): + method2 = method[:len(method)-6] # strip off " const" + if ((d[0],method2) in callSet): + return True + if method.endswith(" const") and ("::iterator" in method): + method2 = method[:len(method)-6] # strip off " const" + method2 = method2.replace("::const_iterator", "::iterator") + if ((d[0],method2) in callSet): + return True + # if this method is non-const, and there is a const variant of it, and the const variant is in use, then leave it alone + if (not method.endswith(" const")) and ((d[0],"const " + method + " const") in callSet): + return True + if (not method.endswith(" const")) and ("::iterator" in method): + method2 = method.replace("::iterator", "::const_iterator") + " const" + if ((d[0],method2) in callSet): + return True + return False + +# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[1]) + [v[0]] +def sort_set_by_natural_key(s): + return sorted(s, key=lambda v: v_sort_key(v)) + + +# -------------------------------------------------------------------------------------------- +# "unused methods" analysis +# -------------------------------------------------------------------------------------------- + +tmp1set = set() # set of tuple(method, source_location) +unusedSet = set() # set of tuple(return_type, name_and_params) +for d in definitionSet: + method = d[0] + " " + d[1] + if d in callSet: + continue + if isOtherConstness(d, callSet): + continue + # exclude assignment operators, if we remove them, the compiler creates a default one, which can have odd consequences + if "::operator=(" in d[1]: + continue + # these are only invoked implicitly, so the plugin does not see the calls + if "::operator new(" in d[1] or "::operator delete(" in d[1]: + continue + # just ignore iterators, they normally occur in pairs, and we typically want to leave one constness version alone + # alone if the other one is in use. + if d[1] == "begin() const" or d[1] == "begin()" or d[1] == "end()" or d[1] == "end() const": + continue + # used by Windows build + if any(x in d[1] for x in ["DdeTopic::", "DdeData::", "DdeService::", "DdeTransaction::", "DdeConnection::", "DdeLink::", "DdeItem::", "DdeGetPutItem::"]): + continue + if method == "class tools::SvRef FontCharMap::GetDefaultMap(_Bool)": + continue + # these are loaded by dlopen() from somewhere + if "get_implementation" in d[1]: + continue + if "component_getFactory" in d[1]: + continue + if d[0]=="_Bool" and "_supportsService(const class rtl::OUString &)" in d[1]: + continue + if (d[0]=="class com::sun::star::uno::Reference" + and "Instance(const class com::sun::star::uno::Reference &)" in d[1]): + continue + # ignore the Java symbols, loaded from the JavaVM + if d[1].startswith("Java_"): + continue + # ignore the VCL_BUILDER_DECL_FACTORY stuff + if d[0]=="void" and d[1].startswith("make") and ("(class VclPtr &" in d[1]): + continue + # ignore methods used to dump objects to stream - normally used for debugging + if d[0] == "class std::basic_ostream &" and d[1].startswith("operator<<(class std::basic_ostream &"): + continue + if d[0] == "basic_ostream &" and d[1].startswith("operator<<(basic_ostream>" in d[1] + or "operator++" in d[1] or "operator--" in d[1]): + continue + # ignore UNO constructor functions + if (d[0] == "class com::sun::star::uno::Reference" and + d[1].endswith("_createInstance(const class com::sun::star::uno::Reference &)")): + continue + if (d[0] == "class com::sun::star::uno::Reference" and + d[1].endswith("_CreateInstance(const class com::sun::star::uno::Reference &)")): + continue + # debug code + if d[1] == "writerfilter::ooxml::OOXMLPropertySet::toString()": + continue + # ignore lambdas + if "::__invoke(" in d[1]: + continue; + if "::operator " in d[1] and "(*)(" in d[1]: + continue; + location = definitionToSourceLocationMap[d]; + # windows only + if location.startswith("include/svl/svdde.hxx"): continue + # fluent API (return ref to self) + if location.startswith("include/tools/stream.hxx"): continue + if location.startswith("include/oox/helper/refvector.hxx"): continue + if location.startswith("include/oox/drawingml/chart/modelbase.hxx"): continue + # templates + if location.startswith("include/vcl/vclptr.hxx"): continue + # external API + if location.startswith("include/LibreOfficeKit/LibreOfficeKit.hxx"): continue + tmp2set.add((method, location)) + +#Disable this for now, not really using it +# print output, sorted by name and line number +with open("compilerplugins/clang/unusedmethods.unused-returns.results", "wt") as f: + for t in sort_set_by_natural_key(tmp2set): + f.write(t[1] + "\n") + f.write(" " + t[0] + "\n") + + +# -------------------------------------------------------------------------------------------- +# "method can be private" analysis +# -------------------------------------------------------------------------------------------- + +tmp3set = set() +for d in publicDefinitionSet: + method = d[0] + " " + d[1] + if d in calledFromOutsideSet: + continue + if d in virtualSet: + continue + # TODO ignore constructors for now, my called-from-outside analysis doesn't work here + if d[0] == "": + continue + if isOtherConstness(d, calledFromOutsideSet): + continue + tmp3set.add((method, definitionToSourceLocationMap[d])) + +# print output, sorted by name and line number +with open("loplugin.unusedmethods.report-can-be-private", "wt") as f: + for t in sort_set_by_natural_key(tmp3set): + f.write(t[1] + "\n") + f.write(" " + t[0] + "\n") + + + +# -------------------------------------------------------------------------------------------- +# "all protected methods in class can be made private" analysis +# -------------------------------------------------------------------------------------------- + +potentialClasses = set() +excludedClasses = set() +potentialClassesSourceLocationMap = dict() +matchClassName = re.compile(r"(\w+)::") +for d in protectedDefinitionSet: + m = matchClassName.match(d[1]) + if not m: continue + clazz = m.group(1) + if d in calledFromOutsideSet: + excludedClasses.add(clazz) + else: + potentialClasses.add(clazz) + potentialClassesSourceLocationMap[clazz] = definitionToSourceLocationMap[d] + +tmp4set = set() +for d in (potentialClasses - excludedClasses): + tmp4set.add((d, potentialClassesSourceLocationMap[d])) + +# print output, sorted by name and line number +with open("loplugin.unusedmethods.report-all-protected-can-be-private", "wt") as f: + for t in sort_set_by_natural_key(tmp4set): + f.write(t[1] + "\n") + f.write(" " + t[0] + "\n") + diff --git a/compilerplugins/clang/unusedmethods.results b/compilerplugins/clang/unusedmethods.results new file mode 100644 index 000000000..2e63c737f --- /dev/null +++ b/compilerplugins/clang/unusedmethods.results @@ -0,0 +1,2344 @@ +basegfx/source/range/b2drangeclipper.cxx:687 + type-parameter-?-? basegfx::(anonymous namespace)::eraseFromList(type-parameter-?-? &,const type-parameter-?-? &) +basic/source/inc/buffer.hxx:40 + void SbiBuffer::operator+=(signed char) +basic/source/inc/buffer.hxx:41 + void SbiBuffer::operator+=(short) +basic/source/inc/buffer.hxx:45 + void SbiBuffer::operator+=(int) +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:185 + void CPPU_CURRENT_NAMESPACE::raiseException(struct _uno_Any *,struct _uno_Mapping *) +bridges/source/cpp_uno/gcc3_linux_x86-64/share.hxx:188 + void CPPU_CURRENT_NAMESPACE::fillUnoException(struct _uno_Any *,struct _uno_Mapping *) +canvas/inc/rendering/icolorbuffer.hxx:47 + unsigned char * canvas::IColorBuffer::lock() const +canvas/inc/rendering/icolorbuffer.hxx:51 + void canvas::IColorBuffer::unlock() const +canvas/inc/rendering/icolorbuffer.hxx:66 + unsigned int canvas::IColorBuffer::getStride() const +canvas/inc/rendering/icolorbuffer.hxx:70 + enum canvas::IColorBuffer::Format canvas::IColorBuffer::getFormat() const +canvas/inc/rendering/isurfaceproxy.hxx:38 + void canvas::ISurfaceProxy::setColorBufferDirty() +canvas/inc/rendering/isurfaceproxy.hxx:51 + _Bool canvas::ISurfaceProxy::draw(double,const class basegfx::B2DPoint &,const class basegfx::B2DHomMatrix &) +canvas/inc/rendering/isurfaceproxy.hxx:71 + _Bool canvas::ISurfaceProxy::draw(double,const class basegfx::B2DPoint &,const class basegfx::B2DRange &,const class basegfx::B2DHomMatrix &) +canvas/inc/rendering/isurfaceproxy.hxx:91 + _Bool canvas::ISurfaceProxy::draw(double,const class basegfx::B2DPoint &,const class basegfx::B2DPolyPolygon &,const class basegfx::B2DHomMatrix &) +canvas/inc/rendering/isurfaceproxymanager.hxx:57 + class std::shared_ptr canvas::ISurfaceProxyManager::createSurfaceProxy(const class std::shared_ptr &) const +canvas/inc/rendering/isurfaceproxymanager.hxx:63 + class std::shared_ptr canvas::createSurfaceProxyManager(const class std::shared_ptr &) +canvas/inc/vclwrapper.hxx:66 + canvas::vcltools::VCLObject::VCLObject(unique_ptr >) +canvas/inc/vclwrapper.hxx:135 + type-parameter-?-? & canvas::vcltools::VCLObject::get() +canvas/inc/vclwrapper.hxx:136 + const type-parameter-?-? & canvas::vcltools::VCLObject::get() const +canvas/inc/vclwrapper.hxx:138 + void canvas::vcltools::VCLObject::swap(VCLObject &) +canvas/source/vcl/impltools.hxx:102 + vclcanvas::tools::LocalGuard::LocalGuard() +connectivity/inc/sdbcx/VGroup.hxx:61 + connectivity::sdbcx::OGroup::OGroup(_Bool) +connectivity/inc/sdbcx/VGroup.hxx:62 + connectivity::sdbcx::OGroup::OGroup(const class rtl::OUString &,_Bool) +connectivity/source/drivers/evoab2/NResultSet.hxx:60 + class rtl::OString connectivity::evoab::OEvoabVersionHelper::getUserName(void *) +connectivity/source/drivers/evoab2/NResultSetMetaData.hxx:49 + class com::sun::star::uno::Reference connectivity::evoab::OEvoabResultSetMetaData::operator Reference() +connectivity/source/drivers/firebird/Driver.hxx:61 + const class com::sun::star::uno::Reference & connectivity::firebird::FirebirdDriver::getContext() const +connectivity/source/drivers/firebird/Util.hxx:65 + connectivity::firebird::ColumnTypeInfo::ColumnTypeInfo(short,const class rtl::OUString &) +connectivity/source/drivers/firebird/Util.hxx:70 + short connectivity::firebird::ColumnTypeInfo::getType() const +connectivity/source/drivers/firebird/Util.hxx:71 + short connectivity::firebird::ColumnTypeInfo::getSubType() const +connectivity/source/drivers/firebird/Util.hxx:73 + const class rtl::OUString & connectivity::firebird::ColumnTypeInfo::getCharacterSet() const +connectivity/source/drivers/mysqlc/mysqlc_connection.hxx:176 + class rtl::OUString connectivity::mysqlc::OConnection::transFormPreparedStatement(const class rtl::OUString &) +connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.hxx:93 + type-parameter-?-? connectivity::mysqlc::OPreparedResultSet::safelyRetrieveValue(const int) +connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.hxx:94 + type-parameter-?-? connectivity::mysqlc::OPreparedResultSet::retrieveValue(const int) +connectivity/source/inc/dbase/dindexnode.hxx:64 + _Bool connectivity::dbase::ONDXKey::operator<(const class connectivity::dbase::ONDXKey &) const +connectivity/source/inc/java/sql/Connection.hxx:60 + class rtl::OUString connectivity::java_sql_Connection::transFormPreparedStatement(const class rtl::OUString &) +connectivity/source/inc/OColumn.hxx:102 + _Bool connectivity::OColumn::isReadOnly() const +connectivity/source/inc/OColumn.hxx:103 + _Bool connectivity::OColumn::isWritable() const +connectivity/source/inc/OColumn.hxx:104 + _Bool connectivity::OColumn::isDefinitelyWritable() const +connectivity/source/inc/odbc/OConnection.hxx:117 + class connectivity::odbc::ODBCDriver * connectivity::odbc::OConnection::getDriver() const +connectivity/source/inc/odbc/ODriver.hxx:71 + const class com::sun::star::uno::Reference & connectivity::odbc::ODBCDriver::getContext() const +connectivity/source/inc/odbc/OPreparedStatement.hxx:70 + void connectivity::odbc::OPreparedStatement::setScalarParameter(int,int,unsigned long,const type-parameter-?-?) +connectivity/source/inc/odbc/OPreparedStatement.hxx:71 + void connectivity::odbc::OPreparedStatement::setScalarParameter(int,int,unsigned long,int,const type-parameter-?-?) +connectivity/source/inc/OTypeInfo.hxx:45 + _Bool connectivity::OTypeInfo::operator==(const struct connectivity::OTypeInfo &) const +connectivity/source/inc/OTypeInfo.hxx:46 + _Bool connectivity::OTypeInfo::operator!=(const struct connectivity::OTypeInfo &) const +cui/source/dialogs/SpellAttrib.hxx:72 + _Bool svx::SpellErrorDescription::operator==(const struct svx::SpellErrorDescription &) const +cui/source/inc/cuihyperdlg.hxx:110 + _Bool SvxHpLinkDlg::AskApply(_Bool) +cui/source/inc/CustomNotebookbarGenerator.hxx:30 + CustomNotebookbarGenerator::CustomNotebookbarGenerator() +cui/source/inc/fileextcheckdlg.hxx:32 + void FileExtCheckDialog::LinkStubOnOkClick(void *,class weld::Button &) +cui/source/inc/fileextcheckdlg.hxx:32 + void FileExtCheckDialog::OnOkClick(class weld::Button &) +cui/source/inc/fileextcheckdlg.hxx:35 + FileExtCheckDialog::FileExtCheckDialog(class weld::Window *,const class rtl::OUString &,const class rtl::OUString &) +cui/source/inc/GraphicsTestsDialog.hxx:52 + void GraphicsTestsDialog::HandleResultViewRequest(class weld::Button &) +cui/source/inc/GraphicsTestsDialog.hxx:52 + void GraphicsTestsDialog::LinkStubHandleResultViewRequest(void *,class weld::Button &) +cui/source/inc/SvxNotebookbarConfigPage.hxx:40 + void SvxNotebookbarConfigPage::SetElement() +dbaccess/source/filter/hsqldb/fbalterparser.hxx:19 + void dbahsql::FbAlterStmtParser::ensureProperTableLengths() const +dbaccess/source/filter/hsqldb/parseschema.hxx:80 + const class std::map > & dbahsql::SchemaParser::getPrimaryKeys() const +dbaccess/source/ui/inc/dsmeta.hxx:88 + class __gnu_debug::_Safe_iterator, class std::set, struct std::bidirectional_iterator_tag> dbaui::FeatureSet::begin() const +dbaccess/source/ui/inc/dsmeta.hxx:89 + class __gnu_debug::_Safe_iterator, class std::set, struct std::bidirectional_iterator_tag> dbaui::FeatureSet::end() const +dbaccess/source/ui/inc/FieldControls.hxx:68 + class rtl::OUString dbaui::OPropNumericEditCtrl::get_text() const +dbaccess/source/ui/inc/FieldControls.hxx:73 + void dbaui::OPropNumericEditCtrl::set_min(int) +dbaccess/source/ui/inc/indexcollection.hxx:52 + class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag> dbaui::OIndexCollection::begin() const +dbaccess/source/ui/inc/indexcollection.hxx:56 + class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag> dbaui::OIndexCollection::end() const +dbaccess/source/ui/inc/indexcollection.hxx:61 + class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag> dbaui::OIndexCollection::find(const class rtl::OUString &) const +dbaccess/source/ui/inc/indexcollection.hxx:63 + class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag> dbaui::OIndexCollection::findOriginal(const class rtl::OUString &) const +dbaccess/source/ui/inc/sbamultiplex.hxx:281 + class comphelper::OInterfaceContainerHelper3 * dbaui::SbaXVetoableChangeMultiplexer::getContainer(const class rtl::OUString &) +dbaccess/source/ui/inc/unodatbr.hxx:315 + _Bool dbaui::SbaTableQueryBrowser::implCopyObject(class ODataClipboard &,const class weld::TreeIter &,int) +desktop/source/lib/lokclipboard.hxx:95 + LOKClipboardFactory::LOKClipboardFactory() +drawinglayer/inc/texture/texture.hxx:39 + _Bool drawinglayer::texture::GeoTexSvx::operator!=(const class drawinglayer::texture::GeoTexSvx &) const +drawinglayer/source/tools/emfpcustomlinecap.hxx:37 + void emfplushelper::EMFPCustomLineCap::SetAttributes(struct com::sun::star::rendering::StrokeAttributes &) +drawinglayer/source/tools/emfpstringformat.hxx:93 + _Bool emfplushelper::EMFPStringFormat::NoFitBlackBox() const +drawinglayer/source/tools/emfpstringformat.hxx:94 + _Bool emfplushelper::EMFPStringFormat::DisplayFormatControl() const +drawinglayer/source/tools/emfpstringformat.hxx:95 + _Bool emfplushelper::EMFPStringFormat::NoFontFallback() const +drawinglayer/source/tools/emfpstringformat.hxx:96 + _Bool emfplushelper::EMFPStringFormat::MeasureTrailingSpaces() const +drawinglayer/source/tools/emfpstringformat.hxx:97 + _Bool emfplushelper::EMFPStringFormat::NoWrap() const +drawinglayer/source/tools/emfpstringformat.hxx:98 + _Bool emfplushelper::EMFPStringFormat::LineLimit() const +drawinglayer/source/tools/emfpstringformat.hxx:99 + _Bool emfplushelper::EMFPStringFormat::NoClip() const +drawinglayer/source/tools/emfpstringformat.hxx:100 + _Bool emfplushelper::EMFPStringFormat::BypassGDI() const +editeng/inc/editdoc.hxx:523 + _Bool EditLine::IsInvalid() const +editeng/inc/editdoc.hxx:524 + _Bool EditLine::IsValid() const +editeng/inc/edtspell.hxx:103 + class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag> WrongList::begin() const +editeng/inc/edtspell.hxx:104 + class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag> WrongList::end() const +editeng/source/editeng/impedit.hxx:235 + class tools::Rectangle LOKSpecialPositioning::GetWindowPos(const class tools::Rectangle &,enum MapUnit) const +embeddedobj/source/msole/olecomponent.hxx:75 + _Bool OleComponent::InitializeObject_Impl() +embeddedobj/source/msole/olecomponent.hxx:77 + void OleComponent::CreateNewIStorage_Impl() +embeddedobj/source/msole/olecomponent.hxx:78 + void OleComponent::RetrieveObjectDataFlavors_Impl() +embeddedobj/source/msole/olecomponent.hxx:79 + void OleComponent::Dispose() +embeddedobj/source/msole/olecomponent.hxx:83 + OleComponent::OleComponent(const class com::sun::star::uno::Reference &,class OleEmbeddedObject *) +embeddedobj/source/msole/olecomponent.hxx:88 + class OleComponent * OleComponent::createEmbeddedCopyOfLink() +embeddedobj/source/msole/olecomponent.hxx:90 + void OleComponent::disconnectEmbeddedObject() +embeddedobj/source/msole/olecomponent.hxx:92 + struct com::sun::star::awt::Size OleComponent::CalculateWithFactor(const struct com::sun::star::awt::Size &,const struct com::sun::star::awt::Size &,const struct com::sun::star::awt::Size &) +embeddedobj/source/msole/olecomponent.hxx:96 + struct com::sun::star::awt::Size OleComponent::CalculateTheRealSize(const struct com::sun::star::awt::Size &,_Bool) +embeddedobj/source/msole/olecomponent.hxx:99 + void OleComponent::LoadEmbeddedObject(const class rtl::OUString &) +embeddedobj/source/msole/olecomponent.hxx:100 + void OleComponent::CreateObjectFromClipboard() +embeddedobj/source/msole/olecomponent.hxx:101 + void OleComponent::CreateNewEmbeddedObject(const class com::sun::star::uno::Sequence &) +embeddedobj/source/msole/olecomponent.hxx:102 + void OleComponent::CreateObjectFromData(const class com::sun::star::uno::Reference &) +embeddedobj/source/msole/olecomponent.hxx:104 + void OleComponent::CreateObjectFromFile(const class rtl::OUString &) +embeddedobj/source/msole/olecomponent.hxx:105 + void OleComponent::CreateLinkFromFile(const class rtl::OUString &) +embeddedobj/source/msole/olecomponent.hxx:106 + void OleComponent::InitEmbeddedCopyOfLink(const class rtl::Reference &) +embeddedobj/source/msole/olecomponent.hxx:109 + void OleComponent::RunObject() +embeddedobj/source/msole/olecomponent.hxx:110 + void OleComponent::CloseObject() +embeddedobj/source/msole/olecomponent.hxx:112 + class com::sun::star::uno::Sequence OleComponent::GetVerbList() +embeddedobj/source/msole/olecomponent.hxx:114 + void OleComponent::ExecuteVerb(int) +embeddedobj/source/msole/olecomponent.hxx:115 + void OleComponent::SetHostName(const class rtl::OUString &) +embeddedobj/source/msole/olecomponent.hxx:116 + void OleComponent::SetExtent(const struct com::sun::star::awt::Size &,long) +embeddedobj/source/msole/olecomponent.hxx:118 + struct com::sun::star::awt::Size OleComponent::GetExtent(long) +embeddedobj/source/msole/olecomponent.hxx:119 + struct com::sun::star::awt::Size OleComponent::GetCachedExtent(long) +embeddedobj/source/msole/olecomponent.hxx:120 + struct com::sun::star::awt::Size OleComponent::GetRecommendedExtent(long) +embeddedobj/source/msole/olecomponent.hxx:122 + long OleComponent::GetMiscStatus(long) +embeddedobj/source/msole/olecomponent.hxx:124 + class com::sun::star::uno::Sequence OleComponent::GetCLSID() +embeddedobj/source/msole/olecomponent.hxx:126 + _Bool OleComponent::IsWorkaroundActive() const +embeddedobj/source/msole/olecomponent.hxx:127 + _Bool OleComponent::IsDirty() +embeddedobj/source/msole/olecomponent.hxx:129 + void OleComponent::StoreOwnTmpIfNecessary() +embeddedobj/source/msole/olecomponent.hxx:131 + _Bool OleComponent::SaveObject_Impl() +embeddedobj/source/msole/olecomponent.hxx:132 + _Bool OleComponent::OnShowWindow_Impl(_Bool) +embeddedobj/source/msole/olecomponent.hxx:133 + void OleComponent::OnViewChange_Impl(unsigned int) +embeddedobj/source/msole/olecomponent.hxx:134 + void OleComponent::OnClose_Impl() +extensions/source/scanner/scanner.hxx:79 + void ScannerManager::SetData(void *) +hwpfilter/source/hiodev.h:63 + unsigned long HIODev::read4b(void *,unsigned long) +hwpfilter/source/mzstring.h:100 + class MzString & MzString::operator<<(unsigned char) +hwpfilter/source/mzstring.h:102 + class MzString & MzString::operator<<(long) +hwpfilter/source/mzstring.h:103 + class MzString & MzString::operator<<(short) +idl/source/prj/svidl.cxx:105 + int main(int,char **) +include/basegfx/curve/b2dcubicbezier.hxx:51 + _Bool basegfx::B2DCubicBezier::operator==(const class basegfx::B2DCubicBezier &) const +include/basegfx/curve/b2dcubicbezier.hxx:52 + _Bool basegfx::B2DCubicBezier::operator!=(const class basegfx::B2DCubicBezier &) const +include/basegfx/curve/b2dcubicbezier.hxx:192 + void basegfx::B2DCubicBezier::transform(const class basegfx::B2DHomMatrix &) +include/basegfx/curve/b2dcubicbezier.hxx:195 + void basegfx::B2DCubicBezier::fround() +include/basegfx/matrix/b2dhommatrix.hxx:106 + void basegfx::B2DHomMatrix::scale(const class basegfx::B2DTuple &) +include/basegfx/matrix/b2dhommatrix.hxx:112 + class basegfx::B2DHomMatrix & basegfx::B2DHomMatrix::operator+=(const class basegfx::B2DHomMatrix &) +include/basegfx/matrix/b2dhommatrix.hxx:113 + class basegfx::B2DHomMatrix & basegfx::B2DHomMatrix::operator-=(const class basegfx::B2DHomMatrix &) +include/basegfx/matrix/b2dhommatrix.hxx:118 + class basegfx::B2DHomMatrix & basegfx::B2DHomMatrix::operator*=(double) +include/basegfx/matrix/b2dhommatrix.hxx:119 + class basegfx::B2DHomMatrix & basegfx::B2DHomMatrix::operator/=(double) +include/basegfx/matrix/b2dhommatrixtools.hxx:131 + class basegfx::B2DHomMatrix basegfx::utils::createRotateAroundCenterKeepAspectRatioStayInsideRange(const class basegfx::B2DRange &,double) +include/basegfx/matrix/b2dhommatrixtools.hxx:213 + double basegfx::utils::B2DHomMatrixBufferedOnDemandDecompose::getShearX() const +include/basegfx/matrix/b3dhommatrix.hxx:66 + void basegfx::B3DHomMatrix::rotate(const class basegfx::B3DTuple &) +include/basegfx/matrix/b3dhommatrix.hxx:70 + void basegfx::B3DHomMatrix::translate(const class basegfx::B3DTuple &) +include/basegfx/matrix/b3dhommatrix.hxx:74 + void basegfx::B3DHomMatrix::scale(const class basegfx::B3DTuple &) +include/basegfx/matrix/b3dhommatrix.hxx:97 + class basegfx::B3DHomMatrix & basegfx::B3DHomMatrix::operator+=(const class basegfx::B3DHomMatrix &) +include/basegfx/matrix/b3dhommatrix.hxx:98 + class basegfx::B3DHomMatrix & basegfx::B3DHomMatrix::operator-=(const class basegfx::B3DHomMatrix &) +include/basegfx/matrix/b3dhommatrix.hxx:105 + class basegfx::B3DHomMatrix & basegfx::B3DHomMatrix::operator*=(double) +include/basegfx/matrix/b3dhommatrix.hxx:106 + class basegfx::B3DHomMatrix & basegfx::B3DHomMatrix::operator/=(double) +include/basegfx/numeric/ftools.hxx:112 + double basegfx::snapToRange(double,double,double) +include/basegfx/numeric/ftools.hxx:116 + double basegfx::copySign(double,double) +include/basegfx/pixel/bpixel.hxx:53 + basegfx::BPixel::BPixel(unsigned char,unsigned char,unsigned char,unsigned char) +include/basegfx/pixel/bpixel.hxx:84 + _Bool basegfx::BPixel::operator==(const class basegfx::BPixel &) const +include/basegfx/pixel/bpixel.hxx:89 + _Bool basegfx::BPixel::operator!=(const class basegfx::BPixel &) const +include/basegfx/point/b2ipoint.hxx:69 + class basegfx::B2IPoint & basegfx::B2IPoint::operator*=(const class basegfx::B2IPoint &) +include/basegfx/point/b2ipoint.hxx:78 + class basegfx::B2IPoint & basegfx::B2IPoint::operator*=(int) +include/basegfx/point/b2ipoint.hxx:95 + class basegfx::B2IPoint & basegfx::B2IPoint::operator*=(const class basegfx::B2DHomMatrix &) +include/basegfx/point/b3dpoint.hxx:74 + class basegfx::B3DPoint & basegfx::B3DPoint::operator*=(const class basegfx::B3DPoint &) +include/basegfx/point/b3dpoint.hxx:84 + class basegfx::B3DPoint & basegfx::B3DPoint::operator*=(double) +include/basegfx/polygon/b2dtrapezoid.hxx:70 + class basegfx::B2DPolygon basegfx::B2DTrapezoid::getB2DPolygon() const +include/basegfx/polygon/b2dtrapezoid.hxx:102 + void basegfx::utils::createLineTrapezoidFromB2DPolygon(class std::vector &,const class basegfx::B2DPolygon &,double) +include/basegfx/polygon/b3dpolypolygon.hxx:88 + void basegfx::B3DPolyPolygon::remove(unsigned int,unsigned int) +include/basegfx/polygon/b3dpolypolygon.hxx:108 + class basegfx::B3DPolygon * basegfx::B3DPolyPolygon::begin() +include/basegfx/polygon/b3dpolypolygon.hxx:109 + class basegfx::B3DPolygon * basegfx::B3DPolyPolygon::end() +include/basegfx/range/b1drange.hxx:50 + basegfx::B1DRange::B1DRange(double) +include/basegfx/range/b1drange.hxx:72 + _Bool basegfx::B1DRange::operator==(const class basegfx::B1DRange &) const +include/basegfx/range/b1drange.hxx:143 + double basegfx::B1DRange::clamp(double) const +include/basegfx/range/b2dpolyrange.hxx:64 + _Bool basegfx::B2DPolyRange::operator!=(const class basegfx::B2DPolyRange &) const +include/basegfx/range/b2drange.hxx:277 + class basegfx::B2DTuple basegfx::B2DRange::clamp(const class basegfx::B2DTuple &) const +include/basegfx/range/b2drange.hxx:297 + const class basegfx::B2DRange & basegfx::B2DRange::getUnitB2DRange() +include/basegfx/range/b2drange.hxx:308 + class basegfx::B2DRange basegfx::operator*(const class basegfx::B2DHomMatrix &,const class basegfx::B2DRange &) +include/basegfx/range/b2ibox.hxx:61 + basegfx::B2IBox::B2IBox() +include/basegfx/range/b2ibox.hxx:64 + basegfx::B2IBox::B2IBox(const class basegfx::B2ITuple &) +include/basegfx/range/b2ibox.hxx:83 + basegfx::B2IBox::B2IBox(const class basegfx::B2ITuple &,const class basegfx::B2ITuple &) +include/basegfx/range/b2ibox.hxx:101 + _Bool basegfx::B2IBox::operator==(const class basegfx::B2IBox &) const +include/basegfx/range/b2ibox.hxx:107 + _Bool basegfx::B2IBox::operator!=(const class basegfx::B2IBox &) const +include/basegfx/range/b2ibox.hxx:150 + _Bool basegfx::B2IBox::isInside(const class basegfx::B2ITuple &) const +include/basegfx/range/b2ibox.hxx:166 + void basegfx::B2IBox::intersect(const class basegfx::B2IBox &) +include/basegfx/range/b2irange.hxx:196 + void basegfx::B2IRange::expand(const class basegfx::B2IRange &) +include/basegfx/range/b2irange.hxx:209 + class basegfx::B2ITuple basegfx::B2IRange::clamp(const class basegfx::B2ITuple &) const +include/basegfx/range/b3drange.hxx:97 + _Bool basegfx::B3DRange::operator!=(const class basegfx::B3DRange &) const +include/basegfx/range/b3drange.hxx:198 + class basegfx::B3DTuple basegfx::B3DRange::clamp(const class basegfx::B3DTuple &) const +include/basegfx/range/b3drange.hxx:218 + const class basegfx::B3DRange & basegfx::B3DRange::getUnitB3DRange() +include/basegfx/range/b3drange.hxx:223 + class basegfx::B3DRange basegfx::operator*(const class basegfx::B3DHomMatrix &,const class basegfx::B3DRange &) +include/basegfx/tuple/b3ituple.hxx:43 + basegfx::B3ITuple::B3ITuple() +include/basegfx/tuple/b3ituple.hxx:66 + const int & basegfx::B3ITuple::operator[](int) const +include/basegfx/tuple/b3ituple.hxx:75 + int & basegfx::B3ITuple::operator[](int) +include/basegfx/tuple/Tuple2D.hxx:77 + _Bool basegfx::Tuple2D::equal(const class basegfx::Tuple2D &) const +include/basegfx/tuple/Tuple2D.hxx:77 + _Bool basegfx::Tuple2D::equal(const class basegfx::Tuple2D &) const +include/basegfx/tuple/Tuple2D.hxx:77 + _Bool basegfx::Tuple2D::equal(const class basegfx::Tuple2D &) const +include/basegfx/utils/b2dclipstate.hxx:72 + _Bool basegfx::utils::B2DClipState::operator!=(const class basegfx::utils::B2DClipState &) const +include/basegfx/utils/canvastools.hxx:109 + struct com::sun::star::geometry::AffineMatrix3D & basegfx::unotools::affineMatrixFromHomMatrix3D(struct com::sun::star::geometry::AffineMatrix3D &,const class basegfx::B3DHomMatrix &) +include/basegfx/utils/canvastools.hxx:129 + class basegfx::B3DRange basegfx::unotools::b3DRectangleFromRealRectangle3D(const struct com::sun::star::geometry::RealRectangle3D &) +include/basegfx/utils/unopolypolygon.hxx:86 + const class basegfx::B2DPolyPolygon & basegfx::unotools::UnoPolyPolygon::getPolyPolygonUnsafe() const +include/basegfx/vector/b2ivector.hxx:72 + class basegfx::B2IVector & basegfx::B2IVector::operator*=(const class basegfx::B2IVector &) +include/basegfx/vector/b2ivector.hxx:81 + class basegfx::B2IVector & basegfx::B2IVector::operator*=(int) +include/basegfx/vector/b2ivector.hxx:115 + class basegfx::B2IVector & basegfx::B2IVector::operator*=(const class basegfx::B2DHomMatrix &) +include/basegfx/vector/b3dvector.hxx:74 + class basegfx::B3DVector & basegfx::B3DVector::operator*=(const class basegfx::B3DVector &) +include/basic/sbxvar.hxx:138 + struct SbxValues * SbxValue::data() +include/codemaker/commoncpp.hxx:47 + class rtl::OString codemaker::cpp::translateUnoToCppType(enum codemaker::UnoType::Sort,class std::basic_string_view) +include/codemaker/global.hxx:53 + class FileStream & operator<<(class FileStream &,const class rtl::OString *) +include/codemaker/global.hxx:55 + class FileStream & operator<<(class FileStream &,const class rtl::OStringBuffer *) +include/codemaker/global.hxx:56 + class FileStream & operator<<(class FileStream &,const class rtl::OStringBuffer &) +include/comphelper/automationinvokedzone.hxx:26 + comphelper::Automation::AutomationInvokedZone::AutomationInvokedZone() +include/comphelper/basicio.hxx:52 + const class com::sun::star::uno::Reference & comphelper::operator>>(const class com::sun::star::uno::Reference &,unsigned int &) +include/comphelper/basicio.hxx:53 + const class com::sun::star::uno::Reference & comphelper::operator<<(const class com::sun::star::uno::Reference &,unsigned int) +include/comphelper/configuration.hxx:250 + type-parameter-?-? comphelper::ConfigurationLocalizedProperty::get(const class com::sun::star::uno::Reference &) +include/comphelper/configuration.hxx:266 + void comphelper::ConfigurationLocalizedProperty::set(const type-parameter-?-? &,const class std::shared_ptr &) +include/comphelper/configuration.hxx:302 + class com::sun::star::uno::Reference comphelper::ConfigurationGroup::get(const class std::shared_ptr &) +include/comphelper/flagguard.hxx:33 + ValueRestorationGuard_Impl comphelper::(ValueRestorationGuard_Impl) +include/comphelper/flagguard.hxx:37 + ValueRestorationGuard_Impl comphelper::(type-parameter-?-? &) +include/comphelper/flagguard.hxx:46 + ValueRestorationGuard comphelper::(ValueRestorationGuard) +include/comphelper/flagguard.hxx:50 + comphelper::ValueRestorationGuard::ValueRestorationGuard(_Bool &,type-parameter-?-? &&) +include/comphelper/flagguard.hxx:50 + comphelper::ValueRestorationGuard::ValueRestorationGuard(long &,type-parameter-?-? &&) +include/comphelper/flagguard.hxx:50 + comphelper::ValueRestorationGuard::ValueRestorationGuard(unsigned char &,type-parameter-?-? &&) +include/comphelper/flagguard.hxx:50 + ValueRestorationGuard comphelper::(type-parameter-?-? &,type-parameter-?-? &&) +include/comphelper/interfacecontainer3.hxx:48 + OInterfaceIteratorHelper3 comphelper::(OInterfaceIteratorHelper3) +include/comphelper/interfacecontainer3.hxx:63 + OInterfaceIteratorHelper3 comphelper::(OInterfaceContainerHelper3 &) +include/comphelper/interfacecontainer3.hxx:91 + OInterfaceIteratorHelper3 comphelper::(const OInterfaceIteratorHelper3 &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XActionListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XAdjustmentListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XDockableWindowListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XFocusListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XItemListListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XItemListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XKeyHandler::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XKeyListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XMenuListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XMouseClickHandler::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XMouseListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XMouseMotionListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XPaintListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XSpinListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XStyleChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XTabListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XTextListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XTopWindowListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XVclContainerListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XWindowListener2::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::XWindowListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::grid::XGridSelectionListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::tab::XTabPageContainerListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::tree::XTreeEditListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::awt::tree::XTreeExpansionListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::beans::XPropertiesChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::beans::XPropertyChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::beans::XPropertySetInfoChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::beans::XVetoableChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::container::XContainerListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::document::XDocumentEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::document::XEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::document::XStorageChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::document::XUndoManagerListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::drawing::XShape::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::XApproveActionListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::XChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::XConfirmDeleteListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::XDatabaseParameterListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::XFormControllerListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::XGridControlListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::XLoadListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::XResetListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::XSubmitListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::XUpdateListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::binding::XListEntryListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::runtime::XFilterControllerListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::submission::XSubmissionVetoListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::form::validation::XFormComponentValidityListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::frame::XStatusListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::lang::XEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::linguistic2::XDictionaryEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::linguistic2::XDictionaryListEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::linguistic2::XLinguServiceEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::presentation::XShapeEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::presentation::XSlideShowListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::script::XScriptListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::script::vba::XVBAScriptListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::sdb::XDatabaseRegistrationsListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::sdb::XRowSetApproveListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::sdb::XRowSetChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::sdb::XRowsChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::sdb::XSQLErrorListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::sdb::application::XCopyTableListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::sdbc::XRowSetListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::text::XPasteListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::ucb::XContentEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::ui::XContextMenuInterceptor::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::util::XChangesListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::util::XCloseListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::util::XFlushListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::util::XModeChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::util::XModifyListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::util::XRefreshListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer3.hxx:215 + void comphelper::OInterfaceContainerHelper3::notifyEach(void (class com::sun::star::view::XSelectionChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:45 + OInterfaceIteratorHelper4 comphelper::(OInterfaceIteratorHelper4) +include/comphelper/interfacecontainer4.hxx:60 + OInterfaceIteratorHelper4 comphelper::(OInterfaceContainerHelper4 &) +include/comphelper/interfacecontainer4.hxx:86 + OInterfaceIteratorHelper4 comphelper::(const OInterfaceIteratorHelper4 &) +include/comphelper/interfacecontainer4.hxx:165 + void comphelper::OInterfaceContainerHelper4::clear() +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::accessibility::XAccessibleEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::awt::XFocusListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::awt::XKeyListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::awt::XMouseListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::awt::XMouseMotionListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::awt::XPaintListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::awt::XWindowListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::awt::grid::XGridColumnListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::beans::XPropertyChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::chart::XChartDataChangeEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::document::XDocumentEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::document::XEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::lang::XEventListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::ui::XContextMenuInterceptor::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::ui::XUIConfigurationListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::util::XModifyListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::util::XRefreshListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/interfacecontainer4.hxx:200 + void comphelper::OInterfaceContainerHelper4::notifyEach(void (class com::sun::star::view::XSelectionChangeListener::*)(const type-parameter-?-? &),const type-parameter-?-? &) +include/comphelper/logging.hxx:58 + class rtl::OUString comphelper::log::convert::convertLogArgToString(char16_t) +include/comphelper/logging.hxx:225 + void comphelper::EventLogger::log(const int,const char *,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:246 + void comphelper::EventLogger::log(const int,const char *,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:258 + void comphelper::EventLogger::log(const int,const char *,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:271 + void comphelper::EventLogger::log(const int,const char *,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:295 + void comphelper::EventLogger::logp(const int,const char *,const char *,const class rtl::OUString &,type-parameter-?-?) const +include/comphelper/logging.hxx:304 + void comphelper::EventLogger::logp(const int,const char *,const char *,const class rtl::OUString &,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:314 + void comphelper::EventLogger::logp(const int,const char *,const char *,const class rtl::OUString &,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:325 + void comphelper::EventLogger::logp(const int,const char *,const char *,const class rtl::OUString &,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:337 + void comphelper::EventLogger::logp(const int,const char *,const char *,const class rtl::OUString &,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:350 + void comphelper::EventLogger::logp(const int,const char *,const char *,const class rtl::OUString &,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:374 + void comphelper::EventLogger::logp(const int,const char *,const char *,const char *,type-parameter-?-?) const +include/comphelper/logging.hxx:383 + void comphelper::EventLogger::logp(const int,const char *,const char *,const char *,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:393 + void comphelper::EventLogger::logp(const int,const char *,const char *,const char *,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:404 + void comphelper::EventLogger::logp(const int,const char *,const char *,const char *,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:416 + void comphelper::EventLogger::logp(const int,const char *,const char *,const char *,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/logging.hxx:429 + void comphelper::EventLogger::logp(const int,const char *,const char *,const char *,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?,type-parameter-?-?) const +include/comphelper/lok.hxx:49 + _Bool comphelper::LibreOfficeKit::isLocalRendering() +include/comphelper/lok.hxx:112 + void comphelper::LibreOfficeKit::setBlockedCommandList(const char *) +include/comphelper/multicontainer2.hxx:112 + void comphelper::OMultiTypeInterfaceContainerHelper2::clear() +include/comphelper/multiinterfacecontainer3.hxx:179 + void comphelper::OMultiTypeInterfaceContainerHelperVar3::clear() +include/comphelper/multiinterfacecontainer4.hxx:46 + vector > comphelper::OMultiTypeInterfaceContainerHelperVar4::getContainedTypes() const +include/comphelper/multiinterfacecontainer4.hxx:57 + _Bool comphelper::OMultiTypeInterfaceContainerHelperVar4::hasContainedTypes() const +include/comphelper/multiinterfacecontainer4.hxx:160 + void comphelper::OMultiTypeInterfaceContainerHelperVar4::clear() +include/comphelper/profilezone.hxx:56 + comphelper::ProfileZone::ProfileZone(const char *,const class std::map &) +include/comphelper/propagg.hxx:60 + _Bool comphelper::internal::OPropertyAccessor::operator==(const struct comphelper::internal::OPropertyAccessor &) const +include/comphelper/propagg.hxx:61 + _Bool comphelper::internal::OPropertyAccessor::operator<(const struct comphelper::internal::OPropertyAccessor &) const +include/comphelper/proparrhlp.hxx:83 + class cppu::IPropertyArrayHelper * comphelper::OAggregationArrayUsageHelper::createArrayHelper() const +include/comphelper/PropertyInfoHash.hxx:36 + comphelper::PropertyInfo::PropertyInfo(const class rtl::OUString &,int,const class com::sun::star::uno::Type &,short) +include/comphelper/scopeguard.hxx:54 + ScopeGuard comphelper::(ScopeGuard) +include/comphelper/scopeguard.hxx:59 + ScopeGuard comphelper::(type-parameter-?-? &&) +include/comphelper/scopeguard.hxx:75 + ScopeGuard comphelper::(const ScopeGuard &) +include/comphelper/sequence.hxx:207 + Sequence comphelper::containerToSequence(const type-parameter-?-? (&)[N]) +include/comphelper/sequence.hxx:207 + Sequence comphelper::containerToSequence(const type-parameter-?-? (&)[S]) +include/comphelper/sequence.hxx:207 + Sequence comphelper::containerToSequence(const type-parameter-?-? (&)[SrcSize]) +include/comphelper/sequence.hxx:207 + Sequence comphelper::containerToSequence(const type-parameter-?-? (&)[_Bound]) +include/comphelper/sequence.hxx:207 + Sequence comphelper::containerToSequence(const type-parameter-?-? (&)[_Nm]) +include/comphelper/servicedecl.hxx:107 + comphelper::service_decl::ServiceDecl::ServiceDecl(const type-parameter-?-? &,const char *,const char *) +include/comphelper/traceevent.hxx:214 + void comphelper::AsyncEvent::finish() +include/comphelper/unique_disposing_ptr.hxx:46 + type-parameter-?-? & comphelper::unique_disposing_ptr::operator*() const +include/comphelper/unwrapargs.hxx:51 + void comphelper::detail::unwrapArgs(const class com::sun::star::uno::Sequence &,int,const class com::sun::star::uno::Reference &) +include/connectivity/dbcharset.hxx:137 + const class dbtools::OCharsetMap::CharsetIterator & dbtools::OCharsetMap::CharsetIterator::operator--() +include/connectivity/FValue.hxx:345 + unsigned char connectivity::ORowSetValue::getUInt8() const +include/connectivity/FValue.hxx:427 + connectivity::TSetBound::TSetBound(_Bool) +include/connectivity/FValue.hxx:428 + void connectivity::TSetBound::operator()(class connectivity::ORowSetValue &) const +include/connectivity/sqlparse.hxx:186 + class rtl::OUString connectivity::OSQLParser::RuleIDToStr(unsigned int) +include/desktop/crashreport.hxx:104 + class rtl::OUString CrashReporter::getActiveSfxObjectName() +include/desktop/crashreport.hxx:109 + class rtl::OUString CrashReporter::getLoggedUnoCommands() +include/drawinglayer/geometry/viewinformation2d.hxx:119 + _Bool drawinglayer::geometry::ViewInformation2D::operator!=(const class drawinglayer::geometry::ViewInformation2D &) const +include/drawinglayer/primitive2d/baseprimitive2d.hxx:135 + _Bool drawinglayer::primitive2d::BasePrimitive2D::operator!=(const class drawinglayer::primitive2d::BasePrimitive2D &) const +include/drawinglayer/primitive2d/baseprimitive2d.hxx:187 + class basegfx::B2DRange drawinglayer::primitive2d::UnoPrimitive2D::getB2DRange(const class drawinglayer::geometry::ViewInformation2D &) const +include/drawinglayer/primitive2d/baseprimitive2d.hxx:192 + unsigned int drawinglayer::primitive2d::UnoPrimitive2D::getPrimitive2DID() const +include/drawinglayer/primitive2d/baseprimitive2d.hxx:195 + void drawinglayer::primitive2d::UnoPrimitive2D::get2DDecomposition(class drawinglayer::primitive2d::Primitive2DDecompositionVisitor &,const class drawinglayer::geometry::ViewInformation2D &) const +include/drawinglayer/primitive2d/Primitive2DContainer.hxx:61 + drawinglayer::primitive2d::Primitive2DContainer::Primitive2DContainer(const class std::deque > &) +include/drawinglayer/primitive2d/Primitive2DContainer.hxx:70 + drawinglayer::primitive2d::Primitive2DContainer::Primitive2DContainer(type-parameter-?-?,type-parameter-?-?) +include/drawinglayer/primitive2d/Primitive2DContainer.hxx:85 + void drawinglayer::primitive2d::Primitive2DContainer::append(const class com::sun::star::uno::Sequence > &) +include/drawinglayer/primitive2d/softedgeprimitive2d.hxx:39 + void drawinglayer::primitive2d::SoftEdgePrimitive2D::setMaskGeneration(_Bool) const +include/drawinglayer/primitive3d/baseprimitive3d.hxx:65 + drawinglayer::primitive3d::Primitive3DContainer::Primitive3DContainer(type-parameter-?-?,type-parameter-?-?) +include/drawinglayer/primitive3d/baseprimitive3d.hxx:112 + _Bool drawinglayer::primitive3d::BasePrimitive3D::operator!=(const class drawinglayer::primitive3d::BasePrimitive3D &) const +include/drawinglayer/tools/primitive2dxmldump.hxx:45 + void drawinglayer::Primitive2dXmlDump::dump(const class drawinglayer::primitive2d::Primitive2DContainer &,const class rtl::OUString &) +include/editeng/colritem.hxx:76 + short SvxColorItem::GetTintOrShade() const +include/editeng/colritem.hxx:81 + void SvxColorItem::SetTintOrShade(short) +include/editeng/editeng.hxx:244 + _Bool EditEngine::GetVertical() const +include/editeng/editeng.hxx:246 + enum TextRotation EditEngine::GetRotation() const +include/editeng/editeng.hxx:475 + _Bool EditEngine::(anonymous)::__invoke(const class SvxFieldData *) +include/editeng/hyphenzoneitem.hxx:64 + _Bool SvxHyphenZoneItem::IsPageEnd() const +include/editeng/outliner.hxx:891 + _Bool Outliner::(anonymous)::__invoke(const class SvxFieldData *) +include/editeng/outlobj.hxx:146 + std::optional::optional(struct std::in_place_t,type-parameter-?-? &&...) +include/editeng/outlobj.hxx:165 + _Bool std::optional::has_value() const +include/editeng/outlobj.hxx:169 + class OutlinerParaObject & std::optional::value() +include/filter/msfilter/mstoolbar.hxx:103 + Indent::Indent(_Bool) +include/formula/opcode.hxx:523 + class std::basic_string OpCodeEnumToString(enum OpCode) +include/formula/tokenarray.hxx:182 + class formula::FormulaTokenArrayReferencesIterator formula::FormulaTokenArrayReferencesIterator::operator++(int) +include/formula/tokenarray.hxx:580 + basic_ostream & formula::operator<<(basic_ostream &,const class formula::FormulaTokenArray &) +include/framework/addonsoptions.hxx:195 + class rtl::OUString framework::AddonsOptions::GetAddonsNotebookBarResourceName(unsigned int) const +include/framework/addonsoptions.hxx:220 + _Bool framework::AddonsOptions::GetMergeNotebookBarInstructions(const class rtl::OUString &,class std::vector &) const +include/i18nlangtag/languagetag.hxx:270 + enum LanguageTag::ScriptType LanguageTag::getScriptType() const +include/o3tl/any.hxx:155 + class std::optional o3tl::tryAccess(const class com::sun::star::uno::Any &) +include/o3tl/cow_wrapper.hxx:333 + type-parameter-?-? * o3tl::cow_wrapper::get() +include/o3tl/enumarray.hxx:105 + typename type-parameter-?-?::value_type * o3tl::enumarray_iterator::operator->() const +include/o3tl/enumarray.hxx:130 + const typename type-parameter-?-?::value_type * o3tl::enumarray_const_iterator::operator->() const +include/o3tl/enumarray.hxx:133 + _Bool o3tl::enumarray_const_iterator::operator==(const enumarray_const_iterator &) const +include/o3tl/hash_combine.hxx:19 + typename enable_if<(sizeof(N) == 4), void>::type o3tl::hash_combine(type-parameter-?-? &,const type-parameter-?-? *,unsigned long) +include/o3tl/hash_combine.hxx:30 + typename enable_if<(sizeof(N) == 4), void>::type o3tl::hash_combine(type-parameter-?-? &,const type-parameter-?-? &) +include/o3tl/sorted_vector.hxx:37 + sorted_vector o3tl::(sorted_vector) +include/o3tl/sorted_vector.hxx:50 + sorted_vector o3tl::(initializer_list) +include/o3tl/sorted_vector.hxx:55 + sorted_vector o3tl::() +include/o3tl/sorted_vector.hxx:56 + sorted_vector o3tl::(const sorted_vector &) +include/o3tl/sorted_vector.hxx:57 + sorted_vector o3tl::(sorted_vector &&) +include/o3tl/sorted_vector.hxx:225 + _Bool o3tl::sorted_vector::operator!=(const sorted_vector &) const +include/o3tl/span.hxx:36 + span o3tl::(span) +include/o3tl/span.hxx:50 + span o3tl::() +include/o3tl/span.hxx:53 + o3tl::span::span(const int (&)[N]) +include/o3tl/span.hxx:53 + o3tl::span::span(const struct XMLPropertyState (&)[N]) +include/o3tl/span.hxx:53 + o3tl::span::span(const unsigned short (&)[N]) +include/o3tl/span.hxx:53 + o3tl::span::span(int (&)[N]) +include/o3tl/span.hxx:53 + o3tl::span::span(struct XMLPropertyState (&)[N]) +include/o3tl/span.hxx:53 + o3tl::span::span(unsigned short (&)[N]) +include/o3tl/span.hxx:53 + span o3tl::(type-parameter-?-? (&)[_Size]) +include/o3tl/span.hxx:55 + span o3tl::(type-parameter-?-? *,unsigned long) +include/o3tl/span.hxx:63 + o3tl::span::span(const vector > &) +include/o3tl/span.hxx:63 + span o3tl::(const vector > &) +include/o3tl/span.hxx:67 + span o3tl::(const span::type> &) +include/o3tl/strong_int.hxx:86 + o3tl::strong_int::strong_int(type-parameter-?-?,typename enable_if::value, int>::type) +include/o3tl/strong_int.hxx:132 + _Bool o3tl::strong_int::anyOf(struct o3tl::strong_int >,type-parameter-?-?...) const +include/o3tl/strong_int.hxx:132 + _Bool o3tl::strong_int::anyOf(struct o3tl::strong_int,type-parameter-?-?...) const +include/o3tl/strong_int.hxx:132 + _Bool o3tl::strong_int::anyOf(struct o3tl::strong_int,type-parameter-?-?...) const +include/o3tl/strong_int.hxx:132 + _Bool o3tl::strong_int::anyOf(struct o3tl::strong_int,type-parameter-?-?...) const +include/o3tl/strong_int.hxx:132 + _Bool o3tl::strong_int::anyOf(struct o3tl::strong_int,type-parameter-?-?...) const +include/o3tl/strong_int.hxx:132 + _Bool o3tl::strong_int::anyOf(struct o3tl::strong_int >,type-parameter-?-?...) const +include/o3tl/strong_int.hxx:132 + _Bool o3tl::strong_int::anyOf(struct o3tl::strong_int,type-parameter-?-?...) const +include/o3tl/strong_int.hxx:132 + _Bool o3tl::strong_int::anyOf(struct o3tl::strong_int,type-parameter-?-?...) const +include/o3tl/strong_int.hxx:132 + _Bool o3tl::strong_int::anyOf(struct o3tl::strong_int,type-parameter-?-?...) const +include/o3tl/strong_int.hxx:132 + _Bool o3tl::strong_int::anyOf(struct o3tl::strong_int,type-parameter-?-?...) const +include/o3tl/typed_flags_set.hxx:113 + typename typed_flags::Wrap operator~(typename typed_flags::Wrap) +include/o3tl/typed_flags_set.hxx:146 + typename typed_flags::Wrap operator^(typename typed_flags::Wrap,type-parameter-?-?) +include/o3tl/typed_flags_set.hxx:313 + typename typed_flags::Self operator^=(type-parameter-?-? &,typename typed_flags::Wrap) +include/o3tl/vector_pool.hxx:83 + o3tl::detail::struct_from_value::type::type() +include/oox/export/DMLPresetShapeExport.hxx:100 + _Bool oox::drawingml::DMLPresetShapeExporter::HasHandleValue() const +include/oox/export/DMLPresetShapeExport.hxx:129 + class com::sun::star::uno::Any oox::drawingml::DMLPresetShapeExporter::FindHandleValue(class com::sun::star::uno::Sequence,class std::basic_string_view) +include/oox/helper/containerhelper.hxx:51 + _Bool oox::ValueRange::operator!=(const struct oox::ValueRange &) const +include/oox/helper/containerhelper.hxx:99 + oox::Matrix::Matrix(typename vector >::size_type,typename vector >::size_type,typename vector >::const_reference) +include/oox/helper/containerhelper.hxx:110 + typename vector >::iterator oox::Matrix::at(typename vector >::size_type,typename vector >::size_type) +include/oox/helper/containerhelper.hxx:113 + typename vector >::reference oox::Matrix::operator()(typename vector >::size_type,typename vector >::size_type) +include/oox/helper/containerhelper.hxx:117 + typename vector >::const_iterator oox::Matrix::begin() const +include/oox/helper/containerhelper.hxx:119 + typename vector >::const_iterator oox::Matrix::end() const +include/oox/helper/containerhelper.hxx:121 + typename vector >::iterator oox::Matrix::row_begin(typename vector >::size_type) +include/oox/helper/containerhelper.hxx:123 + typename vector >::iterator oox::Matrix::row_end(typename vector >::size_type) +include/oox/helper/containerhelper.hxx:126 + typename vector >::reference oox::Matrix::row_front(typename vector >::size_type) +include/oox/helper/propertymap.hxx:112 + void oox::PropertyMap::dumpCode(const class com::sun::star::uno::Reference &) +include/oox/helper/propertymap.hxx:113 + void oox::PropertyMap::dumpData(const class com::sun::star::uno::Reference &) +include/opencl/openclconfig.hxx:57 + _Bool OpenCLConfig::ImplMatcher::operator!=(const struct OpenCLConfig::ImplMatcher &) const +include/sax/fshelper.hxx:126 + void sax_fastparser::FastSerializerHelper::singleElementNS(int,int,const class rtl::Reference &) +include/sax/fshelper.hxx:130 + void sax_fastparser::FastSerializerHelper::startElementNS(int,int,const class rtl::Reference &) +include/sax/tools/converter.hxx:198 + _Bool sax::Converter::convertAngle(short &,class std::basic_string_view,_Bool) +include/sfx2/childwin.hxx:120 + void SfxChildWindow::ClearController() +include/sfx2/docfilt.hxx:81 + _Bool SfxFilter::GetGpgEncryption() const +include/sfx2/evntconf.hxx:60 + struct SfxEventName & SfxEventNamesList::at(unsigned long) +include/sfx2/infobar.hxx:104 + void SfxInfoBarWindow::SetCommandHandler(class weld::Button &,const class rtl::OUString &) +include/sfx2/lokcharthelper.hxx:43 + void LokChartHelper::Invalidate() +include/sfx2/msg.hxx:120 + const class std::type_info * SfxType0::Type() const +include/sfx2/viewsh.hxx:397 + enum LOKDeviceFormFactor SfxViewShell::GetLOKDeviceFormFactor() const +include/sfx2/viewsh.hxx:399 + _Bool SfxViewShell::isLOKDesktop() const +include/svl/itemiter.hxx:45 + _Bool SfxItemIter::IsAtEnd() const +include/svl/itempool.hxx:103 + enum MapUnit SfxItemPool::GetDefaultMetric() const +include/svl/itempool.hxx:158 + const type-parameter-?-? * SfxItemPool::GetItem2Default(TypedWhichId) const +include/svl/itempool.hxx:196 + void SfxItemPool::dumpAsXml(struct _xmlTextWriter *) const +include/svl/lockfilecommon.hxx:60 + void svt::LockFileCommon::SetURL(const class rtl::OUString &) +include/svl/ondemand.hxx:346 + const class CharClass & OnDemandCharClass::operator*() const +include/svl/poolitem.hxx:168 + type-parameter-?-? * SfxPoolItem::DynamicWhichCast(TypedWhichId) +include/svl/whichranges.hxx:52 + void svl::Items_t::fill(struct std::pair *) +include/svtools/DocumentToGraphicRenderer.hxx:105 + _Bool DocumentToGraphicRenderer::isImpress() const +include/svtools/HtmlWriter.hxx:46 + void HtmlWriter::writeAttribute(class SvStream &,class std::basic_string_view,int) +include/svx/autoformathelper.hxx:145 + _Bool AutoFormatBase::operator==(const class AutoFormatBase &) const +include/svx/ClassificationDialog.hxx:86 + void svx::ClassificationDialog::(anonymous)::__invoke() +include/svx/ClassificationField.hxx:47 + const class rtl::OUString & svx::ClassificationResult::getDisplayText() const +include/svx/ClassificationField.hxx:52 + _Bool svx::ClassificationResult::operator==(const class svx::ClassificationResult &) const +include/svx/ColorSets.hxx:85 + void svx::Theme::SetName(const class rtl::OUString &) +include/svx/DiagramDataInterface.hxx:33 + class rtl::OUString DiagramDataInterface::getString() const +include/svx/dlgctrl.hxx:265 + void SvxLineEndLB::set_active_text(const class rtl::OUString &) +include/svx/framelink.hxx:168 + _Bool svx::frame::operator>(const class svx::frame::Style &,const class svx::frame::Style &) +include/svx/gallery1.hxx:56 + const class std::unique_ptr & GalleryThemeEntry::getGalleryStorageEngineEntry() const +include/svx/gallerybinaryengine.hxx:59 + const class INetURLObject & GalleryBinaryEngine::GetStrURL() const +include/svx/sidebar/InspectorTextPanel.hxx:49 + class std::unique_ptr svx::sidebar::InspectorTextPanel::Create(class weld::Widget *) +include/svx/svdlayer.hxx:74 + _Bool SdrLayer::operator==(const class SdrLayer &) const +include/svx/svdpntv.hxx:444 + _Bool SdrPaintView::IsSwapAsynchron() const +include/svx/svdtrans.hxx:242 + _Bool IsMetric(enum MapUnit) +include/svx/txencbox.hxx:92 + void SvxTextEncodingBox::grab_focus() +include/svx/txencbox.hxx:146 + void SvxTextEncodingTreeView::connect_changed(const class Link &) +include/svx/xpoly.hxx:83 + _Bool XPolygon::operator==(const class XPolygon &) const +include/tools/bigint.hxx:76 + BigInt::BigInt(unsigned int) +include/tools/bigint.hxx:82 + unsigned short BigInt::operator unsigned short() const +include/tools/bigint.hxx:84 + unsigned int BigInt::operator unsigned int() const +include/tools/bigint.hxx:109 + class BigInt operator-(const class BigInt &,const class BigInt &) +include/tools/bigint.hxx:112 + class BigInt operator%(const class BigInt &,const class BigInt &) +include/tools/bigint.hxx:115 + _Bool operator!=(const class BigInt &,const class BigInt &) +include/tools/bigint.hxx:118 + _Bool operator<=(const class BigInt &,const class BigInt &) +include/tools/color.hxx:32 + unsigned int color::extractRGB(unsigned int) +include/tools/color.hxx:92 + Color::Color(enum ColorAlphaTag,unsigned int) +include/tools/color.hxx:247 + _Bool Color::operator>(const class Color &) const +include/tools/cpuid.hxx:72 + _Bool cpuid::hasSSSE3() +include/tools/cpuid.hxx:86 + _Bool cpuid::hasAVX2() +include/tools/date.hxx:218 + _Bool Date::operator>=(const class Date &) const +include/tools/datetime.hxx:47 + DateTime::DateTime(const class tools::Time &) +include/tools/datetime.hxx:88 + class DateTime operator-(const class DateTime &,int) +include/tools/datetime.hxx:90 + class DateTime operator-(const class DateTime &,double) +include/tools/datetime.hxx:92 + class DateTime operator+(const class DateTime &,const class tools::Time &) +include/tools/datetime.hxx:93 + class DateTime operator-(const class DateTime &,const class tools::Time &) +include/tools/degree.hxx:25 + char (&)[N] NofDegree(strong_int >) +include/tools/fract.hxx:41 + Fraction::Fraction(double,double) +include/tools/fract.hxx:68 + class Fraction & Fraction::operator+=(double) +include/tools/fract.hxx:69 + class Fraction & Fraction::operator-=(double) +include/tools/fract.hxx:85 + _Bool operator>=(const class Fraction &,const class Fraction &) +include/tools/fract.hxx:101 + class Fraction operator+(const class Fraction &,double) +include/tools/fract.hxx:102 + class Fraction operator-(const class Fraction &,double) +include/tools/fract.hxx:104 + class Fraction operator/(const class Fraction &,double) +include/tools/gen.hxx:236 + class Size & Size::operator+=(const class Size &) +include/tools/gen.hxx:237 + class Size & Size::operator-=(const class Size &) +include/tools/gen.hxx:239 + class Size & Size::operator/=(const long) +include/tools/gen.hxx:241 + class Size operator+(const class Size &,const class Size &) +include/tools/gen.hxx:242 + class Size operator-(const class Size &,const class Size &) +include/tools/gen.hxx:362 + class Pair & Range::toPair() +include/tools/gen.hxx:429 + class Pair & Selection::toPair() +include/tools/link.hxx:134 + const char * Link::getSourceFilename() const +include/tools/link.hxx:135 + int Link::getSourceLineNumber() const +include/tools/link.hxx:136 + const char * Link::getTargetName() const +include/tools/poly.hxx:161 + _Bool tools::Polygon::operator!=(const class tools::Polygon &) const +include/tools/poly.hxx:249 + _Bool tools::PolyPolygon::operator!=(const class tools::PolyPolygon &) const +include/tools/simd.hxx:16 + _Bool simd::isAligned(const type-parameter-?-? *) +include/tools/simd.hxx:21 + type-parameter-?-? simd::roundDown(type-parameter-?-?,unsigned int) +include/tools/stream.hxx:512 + class rtl::OString read_uInt32_lenPrefixed_uInt8s_ToOString(class SvStream &) +include/tools/urlobj.hxx:448 + _Bool INetURLObject::SetHost(class std::basic_string_view) +include/tools/urlobj.hxx:947 + int INetURLObject::SubString::set(class rtl::OUString &,class std::basic_string_view) +include/tools/weakbase.h:110 + _Bool tools::WeakReference::operator==(const type-parameter-?-? *) const +include/tools/weakbase.h:119 + _Bool tools::WeakReference::operator<(const WeakReference &) const +include/tools/weakbase.h:122 + _Bool tools::WeakReference::operator>(const WeakReference &) const +include/tools/XmlWriter.hxx:61 + void tools::XmlWriter::element(const class rtl::OString &) +include/unotest/directories.hxx:46 + class rtl::OUString test::Directories::getPathFromWorkdir(class std::basic_string_view) const +include/unotools/localedatawrapper.hxx:239 + const class rtl::OUString & LocaleDataWrapper::getLongDateYearSep() const +include/unotools/moduleoptions.hxx:165 + _Bool SvtModuleOptions::IsDataBase() const +include/unotools/resmgr.hxx:53 + TranslateNId::TranslateNId() +include/unotools/resmgr.hxx:58 + _Bool TranslateNId::operator bool() const +include/unotools/resmgr.hxx:61 + _Bool TranslateNId::operator!=(const struct TranslateNId &) const +include/unotools/securityoptions.hxx:57 + _Bool SvtSecurityOptions::Certificate::operator==(const struct SvtSecurityOptions::Certificate &) const +include/unotools/textsearch.hxx:121 + basic_ostream & utl::operator<<(basic_ostream &,const enum utl::SearchParam::SearchType &) +include/unotools/weakref.hxx:66 + unotools::WeakReference::WeakReference(const Reference &) +include/unotools/weakref.hxx:75 + unotools::WeakReference::WeakReference(type-parameter-?-? &) +include/unotools/weakref.hxx:127 + Reference unotools::WeakReference::operator Reference() const +include/vcl/alpha.hxx:46 + _Bool AlphaMask::operator==(const class AlphaMask &) const +include/vcl/alpha.hxx:47 + _Bool AlphaMask::operator!=(const class AlphaMask &) const +include/vcl/animate/Animation.hxx:41 + _Bool Animation::operator!=(const class Animation &) const +include/vcl/animate/AnimationBitmap.hxx:68 + _Bool AnimationBitmap::operator!=(const struct AnimationBitmap &) const +include/vcl/BitmapBasicMorphologyFilter.hxx:63 + BitmapDilateFilter::BitmapDilateFilter(int,unsigned char) +include/vcl/BitmapReadAccess.hxx:87 + class BitmapColor BitmapReadAccess::GetPixel(const class Point &) const +include/vcl/BitmapReadAccess.hxx:107 + unsigned char BitmapReadAccess::GetPixelIndex(const class Point &) const +include/vcl/builder.hxx:105 + const class rtl::OString & VclBuilder::getUIFile() const +include/vcl/builder.hxx:331 + void VclBuilder::connectNumericFormatterAdjustment(const class rtl::OString &,const class rtl::OUString &) +include/vcl/builderpage.hxx:36 + void BuilderPage::SetHelpId(const class rtl::OString &) +include/vcl/ColorMask.hxx:110 + void ColorMask::GetColorFor16BitMSB(class BitmapColor &,const unsigned char *) const +include/vcl/ColorMask.hxx:111 + void ColorMask::SetColorFor16BitMSB(const class BitmapColor &,unsigned char *) const +include/vcl/ColorMask.hxx:113 + void ColorMask::SetColorFor16BitLSB(const class BitmapColor &,unsigned char *) const +include/vcl/commandevent.hxx:249 + CommandMediaData::CommandMediaData(enum MediaCommand) +include/vcl/commandevent.hxx:256 + _Bool CommandMediaData::GetPassThroughToOS() const +include/vcl/commandevent.hxx:276 + CommandSwipeData::CommandSwipeData() +include/vcl/commandevent.hxx:293 + CommandLongPressData::CommandLongPressData() +include/vcl/cursor.hxx:96 + _Bool vcl::Cursor::operator!=(const class vcl::Cursor &) const +include/vcl/customweld.hxx:45 + class rtl::OUString weld::CustomWidgetController::GetHelpText() const +include/vcl/customweld.hxx:86 + class Point weld::CustomWidgetController::GetPointerPosPixel() const +include/vcl/customweld.hxx:166 + void weld::CustomWeld::queue_draw_area(int,int,int,int) +include/vcl/customweld.hxx:181 + void weld::CustomWeld::set_visible(_Bool) +include/vcl/customweld.hxx:185 + void weld::CustomWeld::set_tooltip_text(const class rtl::OUString &) +include/vcl/errcode.hxx:86 + _Bool ErrCode::operator<(const class ErrCode &) const +include/vcl/errcode.hxx:87 + _Bool ErrCode::operator<=(const class ErrCode &) const +include/vcl/errcode.hxx:88 + _Bool ErrCode::operator>(const class ErrCode &) const +include/vcl/errcode.hxx:89 + _Bool ErrCode::operator>=(const class ErrCode &) const +include/vcl/fieldvalues.hxx:53 + double vcl::ConvertDoubleValue(long,long,unsigned short,enum FieldUnit,enum FieldUnit) +include/vcl/filter/pdfdocument.hxx:119 + const class std::vector & vcl::filter::PDFObjectElement::GetDictionaryReferences() const +include/vcl/filter/pdfdocument.hxx:128 + unsigned long vcl::filter::PDFObjectElement::GetArrayLength() const +include/vcl/filter/pdfdocument.hxx:188 + class vcl::filter::PDFNumberElement & vcl::filter::PDFReferenceElement::GetObjectElement() const +include/vcl/filter/PDFiumLibrary.hxx:56 + const class rtl::OUString & vcl::pdf::PDFium::getLastError() const +include/vcl/filter/PDFiumLibrary.hxx:91 + class std::unique_ptr vcl::pdf::PDFiumAnnotation::getObject(int) +include/vcl/filter/PDFiumLibrary.hxx:97 + class basegfx::B2DVector vcl::pdf::PDFiumAnnotation::getBorderCornerRadius() +include/vcl/gdimtf.hxx:108 + _Bool GDIMetaFile::operator!=(const class GDIMetaFile &) const +include/vcl/gradient.hxx:84 + _Bool Gradient::operator!=(const class Gradient &) const +include/vcl/hatch.hxx:57 + _Bool Hatch::operator!=(const class Hatch &) const +include/vcl/inputctx.hxx:62 + _Bool InputContext::operator!=(const class InputContext &) const +include/vcl/ITiledRenderable.hxx:217 + enum PointerStyle vcl::ITiledRenderable::getPointer() +include/vcl/jsdialog/executor.hxx:46 + void LOKTrigger::trigger_clicked(class weld::Button &) +include/vcl/lazydelete.hxx:76 + vcl::DeleteOnDeinit::DeleteOnDeinit(type-parameter-?-? &&...) +include/vcl/lazydelete.hxx:92 + class std::optional vcl::DeleteOnDeinit::set(type-parameter-?-? &&...) +include/vcl/lazydelete.hxx:92 + class std::optional vcl::DeleteOnDeinit::set(type-parameter-?-? &&...) +include/vcl/lazydelete.hxx:92 + class std::optional vcl::DeleteOnDeinit::set(type-parameter-?-? &&...) +include/vcl/lazydelete.hxx:92 + class std::optional > vcl::DeleteOnDeinit::set(type-parameter-?-? &&...) +include/vcl/lazydelete.hxx:92 + class std::optional vcl::DeleteOnDeinit::set(type-parameter-?-? &&...) +include/vcl/lazydelete.hxx:92 + class std::optional vcl::DeleteOnDeinit::set(type-parameter-?-? &&...) +include/vcl/lazydelete.hxx:92 + class std::optional > vcl::DeleteOnDeinit::set(type-parameter-?-? &&...) +include/vcl/lazydelete.hxx:92 + class std::optional > > vcl::DeleteOnDeinit::set(type-parameter-?-? &&...) +include/vcl/lazydelete.hxx:92 + class std::optional vcl::DeleteOnDeinit::set(type-parameter-?-? &&...) +include/vcl/lok.hxx:22 + void vcl::lok::unregisterPollCallbacks() +include/vcl/menubarupdateicon.hxx:68 + MenuBarUpdateIconManager::MenuBarUpdateIconManager() +include/vcl/menubarupdateicon.hxx:71 + void MenuBarUpdateIconManager::SetShowMenuIcon(_Bool) +include/vcl/menubarupdateicon.hxx:72 + void MenuBarUpdateIconManager::SetShowBubble(_Bool) +include/vcl/menubarupdateicon.hxx:73 + void MenuBarUpdateIconManager::SetBubbleImage(const class Image &) +include/vcl/menubarupdateicon.hxx:74 + void MenuBarUpdateIconManager::SetBubbleTitle(const class rtl::OUString &) +include/vcl/menubarupdateicon.hxx:75 + void MenuBarUpdateIconManager::SetBubbleText(const class rtl::OUString &) +include/vcl/menubarupdateicon.hxx:77 + void MenuBarUpdateIconManager::SetClickHdl(const class Link &) +include/vcl/menubarupdateicon.hxx:79 + _Bool MenuBarUpdateIconManager::GetShowMenuIcon() const +include/vcl/menubarupdateicon.hxx:80 + _Bool MenuBarUpdateIconManager::GetShowBubble() const +include/vcl/menubarupdateicon.hxx:81 + const class rtl::OUString & MenuBarUpdateIconManager::GetBubbleTitle() const +include/vcl/menubarupdateicon.hxx:82 + const class rtl::OUString & MenuBarUpdateIconManager::GetBubbleText() const +include/vcl/opengl/OpenGLHelper.hxx:51 + class rtl::OString OpenGLHelper::GetDigest(const class rtl::OUString &,const class rtl::OUString &,class std::basic_string_view) +include/vcl/opengl/OpenGLHelper.hxx:68 + void OpenGLHelper::renderToFile(long,long,const class rtl::OUString &) +include/vcl/opengl/OpenGLHelper.hxx:101 + void OpenGLHelper::debugMsgStreamWarn(const class std::basic_ostringstream &) +include/vcl/outdev.hxx:1535 + void OutputDevice::DrawMask(const class Point &,const class Size &,const class Point &,const class Size &,const class Bitmap &,const class Color &) +include/vcl/outdev.hxx:1625 + class basegfx::B2DPolyPolygon OutputDevice::LogicToPixel(const class basegfx::B2DPolyPolygon &,const class MapMode &) const +include/vcl/outdev.hxx:1643 + class basegfx::B2DPolyPolygon OutputDevice::PixelToLogic(const class basegfx::B2DPolyPolygon &,const class MapMode &) const +include/vcl/salnativewidgets.hxx:408 + _Bool TabitemValue::isBothAligned() const +include/vcl/salnativewidgets.hxx:409 + _Bool TabitemValue::isNotAligned() const +include/vcl/settings.hxx:423 + void StyleSettings::SetUseFlatBorders(_Bool) +include/vcl/settings.hxx:426 + void StyleSettings::SetUseFlatMenus(_Bool) +include/vcl/settings.hxx:438 + void StyleSettings::SetHideDisabledMenuItems(_Bool) +include/vcl/settings.hxx:503 + void StyleSettings::SetSpinSize(int) +include/vcl/settings.hxx:539 + class Size StyleSettings::GetToolbarIconSizePixel() const +include/vcl/settings.hxx:655 + _Bool HelpSettings::operator!=(const class HelpSettings &) const +include/vcl/settings.hxx:716 + _Bool AllSettings::operator!=(const class AllSettings &) const +include/vcl/split.hxx:92 + void Splitter::SetHorizontal(_Bool) +include/vcl/svapp.hxx:164 + ApplicationEvent::ApplicationEvent(enum ApplicationEvent::Type,class std::vector &&) +include/vcl/svapp.hxx:802 + void Application::AppEvent(const class ApplicationEvent &) +include/vcl/TaskStopwatch.hxx:92 + void TaskStopwatch::reset() +include/vcl/TaskStopwatch.hxx:103 + void TaskStopwatch::setInputStop(enum VclInputFlags) +include/vcl/TaskStopwatch.hxx:104 + enum VclInputFlags TaskStopwatch::inputStop() const +include/vcl/TaskStopwatch.hxx:112 + unsigned int TaskStopwatch::timeSlice() +include/vcl/TaskStopwatch.hxx:113 + void TaskStopwatch::setTimeSlice(unsigned int) +include/vcl/textrectinfo.hxx:48 + _Bool TextRectInfo::operator!=(const class TextRectInfo &) const +include/vcl/toolkit/longcurr.hxx:47 + class BigInt LongCurrencyFormatter::GetValue() const +include/vcl/toolkit/treelist.hxx:170 + const class SvTreeListEntry * SvTreeList::GetParent(const class SvTreeListEntry *) const +include/vcl/toolkit/treelistbox.hxx:372 + void SvTreeListBox::RemoveSelection() +include/vcl/txtattr.hxx:56 + _Bool TextAttrib::operator!=(const class TextAttrib &) const +include/vcl/uitest/uiobject.hxx:134 + class std::unique_ptr WindowUIObject::get_visible_child(const class rtl::OUString &) +include/vcl/uitest/uiobject.hxx:289 + TabPageUIObject::TabPageUIObject(const class VclPtr &) +include/vcl/uitest/uiobject.hxx:297 + class std::unique_ptr TabPageUIObject::create(class vcl::Window *) +include/vcl/uitest/uiobject.hxx:360 + SpinUIObject::SpinUIObject(const class VclPtr &) +include/vcl/uitest/uiobject.hxx:368 + class std::unique_ptr SpinUIObject::create(class vcl::Window *) +include/vcl/weld.hxx:183 + _Bool weld::Widget::get_hexpand() const +include/vcl/weld.hxx:185 + _Bool weld::Widget::get_vexpand() const +include/vcl/weld.hxx:192 + int weld::Widget::get_margin_top() const +include/vcl/weld.hxx:193 + int weld::Widget::get_margin_bottom() const +include/vcl/weld.hxx:412 + void weld::ScrolledWindow::hadjustment_set_step_increment(int) +include/vcl/weld.hxx:545 + struct SystemEnvData weld::Window::get_system_data() const +include/vcl/weld.hxx:629 + class rtl::OString weld::Assistant::get_current_page_ident() const +include/vcl/weld.hxx:635 + class rtl::OUString weld::Assistant::get_page_title(const class rtl::OString &) const +include/vcl/weld.hxx:1118 + void weld::TreeView::set_text_align(const class weld::TreeIter &,double,int) +include/vcl/weld.hxx:1288 + const class rtl::OUString & weld::TreeView::get_saved_value() const +include/vcl/weld.hxx:1382 + _Bool weld::IconView::get_cursor(class weld::TreeIter *) const +include/vcl/weld.hxx:1392 + void weld::IconView::select_all() +include/vcl/weld.hxx:1398 + void weld::IconView::save_value() +include/vcl/weld.hxx:1399 + const class rtl::OUString & weld::IconView::get_saved_value() const +include/vcl/weld.hxx:1400 + _Bool weld::IconView::get_value_changed_from_saved() const +include/vcl/weld.hxx:1526 + void weld::MenuButton::append_item_radio(const class rtl::OUString &,const class rtl::OUString &) +include/vcl/weld.hxx:1534 + void weld::MenuButton::append_item(const class rtl::OUString &,const class rtl::OUString &,class VirtualDevice &) +include/vcl/weld.hxx:1615 + class rtl::OUString weld::ProgressBar::get_text() const +include/vcl/weld.hxx:1825 + void weld::EntryTreeView::EntryModifyHdl(const class weld::Entry &) +include/vcl/weld.hxx:2061 + class Size weld::MetricSpinButton::get_size_request() const +include/vcl/weld.hxx:2073 + void weld::MetricSpinButton::set_position(int) +include/vcl/weld.hxx:2177 + int weld::TextView::vadjustment_get_lower() const +include/vcl/weld.hxx:2399 + class rtl::OUString weld::Toolbar::get_item_label(const class rtl::OString &) const +include/vcl/weldutils.hxx:198 + const class com::sun::star::uno::Reference & weld::WidgetStatusListener::getFrame() const +include/vcl/weldutils.hxx:350 + void weld::DateFormatter::CursorChangedHdl(class weld::Entry &) +include/vcl/weldutils.hxx:350 + void weld::DateFormatter::LinkStubCursorChangedHdl(void *,class weld::Entry &) +include/vcl/weldutils.hxx:379 + void weld::PatternFormatter::connect_focus_in(const class Link &) +include/vcl/window.hxx:375 + const char * ImplDbgCheckWindow(const void *) +include/xmloff/txtimp.hxx:115 + class XMLPropertyBackpatcher & XMLTextImportHelper::GetFootnoteBP() +include/xmloff/txtimp.hxx:116 + class XMLPropertyBackpatcher & XMLTextImportHelper::GetSequenceIdBP() +include/xmloff/txtimp.hxx:117 + class XMLPropertyBackpatcher & XMLTextImportHelper::GetSequenceNameBP() +include/xmloff/xmluconv.hxx:190 + _Bool SvXMLUnitConverter::convertEnum(type-parameter-?-? &,class std::basic_string_view,const SvXMLEnumStringMapEntry *) +include/xmlreader/pad.hxx:38 + void xmlreader::Pad::add(const char (&)[size_]) +include/xmlreader/span.hxx:44 + xmlreader::Span::Span(const char (&)[size_]) +include/xmlreader/span.hxx:71 + _Bool xmlreader::Span::operator!=(const char (&)[N]) const +libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx:72 + void ::operator()(struct _GtkBuilder *) const +libreofficekit/qa/gtktiledviewer/gtv-comments-sidebar.cxx:31 + void * gtv_comments_sidebar_get_instance_private(struct GtvCommentsSidebar *) +libreofficekit/qa/gtktiledviewer/gtv-helpers.cxx:80 + void ::operator()(struct _GtkTargetList *) const +libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx:184 + void ::operator()(struct _GList *) const +libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.hxx:35 + void openLokDialog(struct _GtkWidget *,void *) +lotuswordpro/source/filter/clone.hxx:28 + detail::has_clone::no & detail::has_clone::check_sig() +lotuswordpro/source/filter/clone.hxx:28 + detail::has_clone::no & detail::has_clone::check_sig() +lotuswordpro/source/filter/clone.hxx:28 + detail::has_clone::no & detail::has_clone::check_sig() +lotuswordpro/source/filter/clone.hxx:28 + detail::has_clone::no & detail::has_clone::check_sig() +lotuswordpro/source/filter/clone.hxx:28 + detail::has_clone::no & detail::has_clone::check_sig() +lotuswordpro/source/filter/clone.hxx:28 + detail::has_clone::no & detail::has_clone::check_sig() +o3tl/qa/cow_wrapper_clients.hxx:140 + _Bool o3tltests::cow_wrapper_client4::operator==(const class o3tltests::cow_wrapper_client4 &) const +o3tl/qa/cow_wrapper_clients.hxx:141 + _Bool o3tltests::cow_wrapper_client4::operator!=(const class o3tltests::cow_wrapper_client4 &) const +o3tl/qa/cow_wrapper_clients.hxx:142 + _Bool o3tltests::cow_wrapper_client4::operator<(const class o3tltests::cow_wrapper_client4 &) const +o3tl/qa/cow_wrapper_clients.hxx:193 + _Bool o3tltests::cow_wrapper_client5::operator!=(const class o3tltests::cow_wrapper_client5 &) const +oox/inc/drawingml/textliststyle.hxx:62 + void oox::drawingml::TextListStyle::dump() const +oox/inc/drawingml/textparagraphproperties.hxx:96 + void oox::drawingml::TextParagraphProperties::setLineSpacing(const class oox::drawingml::TextSpacing &) +oox/source/drawingml/diagram/diagramlayoutatoms.hxx:330 + const class std::vector > & oox::drawingml::LayoutNode::getNodeShapes() const +oox/source/drawingml/diagram/diagramlayoutatoms.hxx:339 + const class oox::drawingml::LayoutNode * oox::drawingml::LayoutNode::getParentLayoutNode() const +sal/osl/unx/uunxapi.hxx:39 + int mkdir_c(const class rtl::OString &,unsigned int) +sal/osl/unx/uunxapi.hxx:74 + int osl::lstat(const class rtl::OUString &,struct stat &) +sal/rtl/strtmpl.hxx:917 + int rtl::str::toInt32_WithLength(const type-parameter-?-? *,short,int) +sc/inc/address.hxx:665 + _Bool ScRange::operator<=(const class ScRange &) const +sc/inc/bigrange.hxx:72 + _Bool ScBigAddress::operator!=(const class ScBigAddress &) const +sc/inc/column.hxx:223 + _Bool ScColumn::HasDataAt(struct sc::ColumnBlockPosition &,int,struct ScDataAreaExtras *) +sc/inc/columniterator.hxx:81 + int sc::ColumnIterator::getType() const +sc/inc/datamapper.hxx:75 + void sc::ExternalDataSource::setUpdateFrequency(double) +sc/inc/datamapper.hxx:78 + void sc::ExternalDataSource::setURL(const class rtl::OUString &) +sc/inc/datamapper.hxx:79 + void sc::ExternalDataSource::setProvider(const class rtl::OUString &) +sc/inc/document.hxx:587 + void ScDocument::SetImagePreferredDPI(int) +sc/inc/document.hxx:588 + int ScDocument::GetImagePreferredDPI() +sc/inc/dpfilteredcache.hxx:148 + void ScDPFilteredCache::dump() const +sc/inc/formulacell.hxx:508 + void ScFormulaCell::Dump() const +sc/inc/kahan.hxx:33 + KahanSum::KahanSum(double,double) +sc/inc/kahan.hxx:83 + class KahanSum KahanSum::operator-() const +sc/inc/kahan.hxx:173 + _Bool KahanSum::operator<(const class KahanSum &) const +sc/inc/kahan.hxx:177 + _Bool KahanSum::operator>(const class KahanSum &) const +sc/inc/kahan.hxx:179 + _Bool KahanSum::operator>(double) const +sc/inc/kahan.hxx:181 + _Bool KahanSum::operator<=(const class KahanSum &) const +sc/inc/kahan.hxx:183 + _Bool KahanSum::operator<=(double) const +sc/inc/kahan.hxx:185 + _Bool KahanSum::operator>=(const class KahanSum &) const +sc/inc/kahan.hxx:199 + double * KahanSum::getSum() +sc/inc/kahan.hxx:200 + double * KahanSum::getError() +sc/inc/miscuno.hxx:189 + void ScUnoHelpFunctions::SetOptionalPropertyValue(const class com::sun::star::uno::Reference &,const class rtl::OUString &,const type-parameter-?-? &) +sc/inc/mtvcellfunc.hxx:40 + class mdds::mtv::soa::detail::iterator_base, struct mdds::mtv::noncopyable_managed_element_block<53, class EditTextObject>, struct mdds::mtv::noncopyable_managed_element_block<54, class ScFormulaCell> >, struct sc::CellStoreTrait>::iterator_trait> sc::ProcessFormula(const class mdds::mtv::soa::detail::iterator_base, struct mdds::mtv::noncopyable_managed_element_block<53, class EditTextObject>, struct mdds::mtv::noncopyable_managed_element_block<54, class ScFormulaCell> >, struct sc::CellStoreTrait>::iterator_trait> &,class mdds::mtv::soa::multi_type_vector, struct mdds::mtv::noncopyable_managed_element_block<53, class EditTextObject>, struct mdds::mtv::noncopyable_managed_element_block<54, class ScFormulaCell> >, struct sc::CellStoreTrait> &,int,int,class std::function) +sc/inc/mtvelements.hxx:72 + class mdds::mtv::base_element_block * sc::mdds_mtv_create_new_block(const struct sc::CellTextAttr &,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:72 + void sc::mdds_mtv_insert_values(class mdds::mtv::base_element_block &,unsigned long,const struct sc::CellTextAttr &,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:76 + class mdds::mtv::base_element_block * mdds_mtv_create_new_block(const class ScPostIt *,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:76 + void mdds_mtv_insert_values(class mdds::mtv::base_element_block &,unsigned long,const class ScPostIt *,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:77 + class mdds::mtv::base_element_block * mdds_mtv_create_new_block(const class SvtBroadcaster *,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:77 + void mdds_mtv_append_values(class mdds::mtv::base_element_block &,const class SvtBroadcaster *,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:77 + void mdds_mtv_assign_values(class mdds::mtv::base_element_block &,const class SvtBroadcaster *,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:77 + void mdds_mtv_insert_values(class mdds::mtv::base_element_block &,unsigned long,const class SvtBroadcaster *,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:77 + void mdds_mtv_prepend_values(class mdds::mtv::base_element_block &,const class SvtBroadcaster *,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:77 + void mdds_mtv_set_values(class mdds::mtv::base_element_block &,unsigned long,const class SvtBroadcaster *,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:78 + class mdds::mtv::base_element_block * mdds_mtv_create_new_block(const class ScFormulaCell *,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:78 + void mdds_mtv_get_empty_value(class ScFormulaCell *&) +sc/inc/mtvelements.hxx:78 + void mdds_mtv_get_value(const class mdds::mtv::base_element_block &,unsigned long,class ScFormulaCell *&) +sc/inc/mtvelements.hxx:78 + void mdds_mtv_insert_values(class mdds::mtv::base_element_block &,unsigned long,const class ScFormulaCell *,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:79 + class mdds::mtv::base_element_block * mdds_mtv_create_new_block(const class EditTextObject *,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:79 + void mdds_mtv_get_empty_value(class EditTextObject *&) +sc/inc/mtvelements.hxx:79 + void mdds_mtv_get_value(const class mdds::mtv::base_element_block &,unsigned long,class EditTextObject *&) +sc/inc/mtvelements.hxx:79 + void mdds_mtv_insert_values(class mdds::mtv::base_element_block &,unsigned long,const class EditTextObject *,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:83 + class mdds::mtv::base_element_block * svl::mdds_mtv_create_new_block(const class svl::SharedString &,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvelements.hxx:83 + void svl::mdds_mtv_insert_values(class mdds::mtv::base_element_block &,unsigned long,const class svl::SharedString &,const type-parameter-?-? &,const type-parameter-?-? &) +sc/inc/mtvfunctions.hxx:365 + void sc::ProcessElements2(type-parameter-?-? &,type-parameter-?-? &,type-parameter-?-? &) +sc/inc/postit.hxx:47 + ScCaptionPtr::ScCaptionPtr(class SdrCaptionObj *) +sc/inc/scdll.hxx:35 + ScDLL::ScDLL() +sc/inc/scopetools.hxx:80 + void sc::DelayFormulaGroupingSwitch::reset() +sc/inc/segmenttree.hxx:149 + void ScFlatUInt16RowSegments::setValueIf(int,int,unsigned short,const class std::function<_Bool (unsigned short)> &) +sc/inc/segmenttree.hxx:162 + void ScFlatUInt16RowSegments::makeReady() +sc/inc/sheetlimits.hxx:41 + _Bool ScSheetLimits::ValidColRow(short,int) const +sc/inc/sheetlimits.hxx:45 + _Bool ScSheetLimits::ValidColRowTab(short,int,short) const +sc/inc/sheetlimits.hxx:57 + short ScSheetLimits::SanitizeCol(short) const +sc/inc/sheetlimits.hxx:58 + int ScSheetLimits::SanitizeRow(int) const +sc/inc/stlalgorithm.hxx:46 + sc::AlignedAllocator::AlignedAllocator(const AlignedAllocator &) +sc/inc/stlalgorithm.hxx:46 + sc::AlignedAllocator::AlignedAllocator(const AlignedAllocator &) +sc/inc/stlalgorithm.hxx:60 + _Bool sc::AlignedAllocator::operator==(const AlignedAllocator &) const +sc/inc/stlalgorithm.hxx:61 + _Bool sc::AlignedAllocator::operator!=(const AlignedAllocator &) const +sc/inc/table.hxx:328 + _Bool ScTable::IsColRowTabValid(const short,const int,const short) const +sc/inc/userlist.hxx:89 + class __gnu_debug::_Safe_iterator *, class std::__cxx1998::vector > >, class std::vector >, struct std::random_access_iterator_tag> ScUserList::begin() const +sc/qa/unit/helper/qahelper.hxx:164 + class std::basic_string print(const class ScAddress &) +sc/source/core/inc/interpre.hxx:70 + basic_ostream & sc::operator<<(basic_ostream &,const struct sc::ParamIfsResult &) +sc/source/core/opencl/formulagroupcl.cxx:1062 + _Bool sc::opencl::(anonymous namespace)::DynamicKernelSlidingArgument::NeedParallelReduction() const +sc/source/core/opencl/formulagroupcl.cxx:1070 + void sc::opencl::(anonymous namespace)::DynamicKernelSlidingArgument::GenSlidingWindowFunction(class std::basic_stringstream &) +sc/source/core/opencl/formulagroupcl.cxx:1353 + void sc::opencl::(anonymous namespace)::ParallelReductionVectorRef::GenSlidingWindowFunction(class std::basic_stringstream &) +sc/source/core/opencl/formulagroupcl.cxx:1355 + class std::basic_string sc::opencl::(anonymous namespace)::ParallelReductionVectorRef::GenSlidingWindowDeclRef(_Bool) const +sc/source/core/opencl/formulagroupcl.cxx:1369 + unsigned long sc::opencl::(anonymous namespace)::ParallelReductionVectorRef::Marshal(struct _cl_kernel *,int,int,struct _cl_program *) +sc/source/core/opencl/formulagroupcl.cxx:1382 + unsigned long sc::opencl::(anonymous namespace)::ParallelReductionVectorRef::GetArrayLength() const +sc/source/core/opencl/formulagroupcl.cxx:1384 + unsigned long sc::opencl::(anonymous namespace)::ParallelReductionVectorRef::GetWindowSize() const +sc/source/core/opencl/formulagroupcl.cxx:1386 + _Bool sc::opencl::(anonymous namespace)::ParallelReductionVectorRef::GetStartFixed() const +sc/source/core/opencl/formulagroupcl.cxx:1388 + _Bool sc::opencl::(anonymous namespace)::ParallelReductionVectorRef::GetEndFixed() const +sc/source/core/opencl/op_statistical.hxx:205 + sc::opencl::OpGeoMean::OpGeoMean() +sc/source/core/tool/interpr1.cxx:4152 + double ::operator()(double,unsigned long) const +sc/source/core/tool/interpr1.cxx:6464 + double ::operator()(const struct sc::ParamIfsResult &) const +sc/source/core/tool/scmatrix.cxx:2262 + type-parameter-?-? * (anonymous namespace)::wrapped_iterator::operator->() const +sc/source/filter/inc/orcusinterface.hxx:76 + ScOrcusRefResolver::ScOrcusRefResolver(const class ScOrcusGlobalSettings &) +sc/source/filter/inc/orcusinterface.hxx:632 + const class rtl::OUString * ScOrcusFactory::getString(unsigned long) const +sc/source/filter/inc/tokstack.hxx:212 + _Bool TokenPool::GrowTripel(unsigned short) +sc/source/filter/inc/xeextlst.hxx:197 + void XclExtLst::AddRecord(const class rtl::Reference &) +sc/source/filter/inc/xerecord.hxx:342 + void XclExpRecordList::InsertRecord(type-parameter-?-? *,unsigned long) +sc/source/filter/inc/xerecord.hxx:351 + void XclExpRecordList::AppendRecord(Reference) +sc/source/filter/inc/xerecord.hxx:362 + void XclExpRecordList::AppendNewRecord(const Reference &) +sc/source/filter/inc/xerecord.hxx:364 + void XclExpRecordList::AppendNewRecord(Reference) +sc/source/filter/inc/xestream.hxx:106 + class XclExpStream & XclExpStream::operator<<(float) +sc/source/filter/inc/xiescher.hxx:153 + class Color XclImpDrawObjBase::GetSolidLineColor(const struct XclObjLineData &) const +sc/source/filter/inc/xlformula.hxx:408 + _Bool XclTokenArray::operator==(const class XclTokenArray &) const +sc/source/filter/xml/xmltransformationi.hxx:159 + ScXMLDateTimeContext::ScXMLDateTimeContext(class ScXMLImport &,const class rtl::Reference &) +sc/source/ui/inc/dataprovider.hxx:56 + _Bool sc::CSVFetchThread::IsRequestedTerminate() +sc/source/ui/inc/dataprovider.hxx:57 + void sc::CSVFetchThread::Terminate() +sc/source/ui/inc/dataprovider.hxx:58 + void sc::CSVFetchThread::EndThread() +sc/source/ui/inc/dataprovider.hxx:83 + const class rtl::OUString & sc::DataProvider::GetURL() const +sc/source/ui/inc/dataproviderdlg.hxx:57 + void ScDataProviderDlg::LinkStubStartMenuHdl(void *,const class rtl::OString &) +sc/source/ui/inc/dataproviderdlg.hxx:57 + void ScDataProviderDlg::StartMenuHdl(const class rtl::OString &) +sc/source/ui/inc/dataproviderdlg.hxx:58 + void ScDataProviderDlg::ColumnMenuHdl(const class weld::ComboBox &) +sc/source/ui/inc/dataproviderdlg.hxx:58 + void ScDataProviderDlg::LinkStubColumnMenuHdl(void *,const class weld::ComboBox &) +sc/source/ui/inc/dataproviderdlg.hxx:75 + void ScDataProviderDlg::applyAndQuit() +sc/source/ui/inc/dataproviderdlg.hxx:76 + void ScDataProviderDlg::cancelAndQuit() +sc/source/ui/inc/datatableview.hxx:110 + void ScDataTableView::getRowRange(int &,int &) const +sc/source/ui/inc/datatransformation.hxx:197 + short sc::FindReplaceTransformation::getColumn() const +sc/source/ui/inc/datatransformation.hxx:198 + const class rtl::OUString & sc::FindReplaceTransformation::getFindString() const +sc/source/ui/inc/datatransformation.hxx:199 + const class rtl::OUString & sc::FindReplaceTransformation::getReplaceString() const +sc/source/ui/inc/datatransformation.hxx:211 + short sc::DeleteRowTransformation::getColumn() const +sc/source/ui/inc/datatransformation.hxx:212 + const class rtl::OUString & sc::DeleteRowTransformation::getFindString() const +sc/source/ui/inc/datatransformation.hxx:223 + int sc::SwapRowsTransformation::getFirstRow() const +sc/source/ui/inc/datatransformation.hxx:224 + int sc::SwapRowsTransformation::getSecondRow() const +sc/source/ui/inc/hfedtdlg.hxx:85 + ScHFEditFirstHeaderDlg::ScHFEditFirstHeaderDlg(class weld::Window *,const class SfxItemSet &,class std::basic_string_view) +sc/source/ui/inc/hfedtdlg.hxx:106 + ScHFEditFirstFooterDlg::ScHFEditFirstFooterDlg(class weld::Window *,const class SfxItemSet &,class std::basic_string_view) +sc/source/ui/inc/impex.hxx:92 + ScImportExport::ScImportExport(class ScDocument &,const class rtl::OUString &) +sc/source/ui/inc/RandomNumberGeneratorDialog.hxx:65 + void ScRandomNumberGeneratorDialog::GenerateNumbers(type-parameter-?-? &,struct TranslateId,const class std::optional) +sc/source/ui/inc/TableFillingAndNavigationTools.hxx:121 + unsigned long DataRangeIterator::size() +sc/source/ui/inc/viewdata.hxx:406 + long ScViewData::GetLOKDocWidthPixel() const +sc/source/ui/inc/viewdata.hxx:407 + long ScViewData::GetLOKDocHeightPixel() const +sc/source/ui/inc/viewdata.hxx:547 + _Bool ScViewData::IsGridMode() const +scaddins/source/analysis/analysishelper.hxx:797 + _Bool sca::analysis::ScaDate::operator>=(const class sca::analysis::ScaDate &) const +sccomp/source/solver/DifferentialEvolution.hxx:66 + int DifferentialEvolutionAlgorithm::getLastChange() +sccomp/source/solver/ParticelSwarmOptimization.hxx:84 + int ParticleSwarmOptimizationAlgorithm::getLastChange() +sd/inc/sdabstdlg.hxx:180 + class VclPtr SdAbstractDialogFactory::CreateSdOutlineBulletTabDlg(class weld::Window *,const class SfxItemSet *,class sd::View *) +sd/inc/sddll.hxx:47 + SdDLL::SdDLL() +sd/source/filter/ppt/pptinanimations.hxx:107 + void ppt::AnimationImporter::dump(const char *,long) +sd/source/ui/inc/filedlg.hxx:54 + _Bool SdOpenSoundFileDialog::IsInsertAsLinkSelected() const +sd/source/ui/inc/GraphicViewShell.hxx:43 + class SfxViewFactory * sd::GraphicViewShell::Factory() +sd/source/ui/inc/GraphicViewShell.hxx:43 + class SfxViewShell * sd::GraphicViewShell::CreateInstance(class SfxViewFrame *,class SfxViewShell *) +sd/source/ui/inc/GraphicViewShell.hxx:43 + void sd::GraphicViewShell::InitFactory() +sd/source/ui/inc/GraphicViewShell.hxx:43 + void sd::GraphicViewShell::RegisterFactory(struct o3tl::strong_int) +sd/source/ui/inc/optsitem.hxx:178 + _Bool SdOptionsContents::operator==(const class SdOptionsContents &) const +sd/source/ui/inc/OutlineViewShell.hxx:40 + class SfxViewFactory * sd::OutlineViewShell::Factory() +sd/source/ui/inc/OutlineViewShell.hxx:40 + class SfxViewShell * sd::OutlineViewShell::CreateInstance(class SfxViewFrame *,class SfxViewShell *) +sd/source/ui/inc/OutlineViewShell.hxx:40 + void sd::OutlineViewShell::InitFactory() +sd/source/ui/inc/OutlineViewShell.hxx:40 + void sd::OutlineViewShell::RegisterFactory(struct o3tl::strong_int) +sd/source/ui/inc/PaneShells.hxx:33 + void sd::LeftImpressPaneShell::RegisterInterface(const class SfxModule *) +sd/source/ui/inc/PaneShells.hxx:50 + void sd::LeftDrawPaneShell::RegisterInterface(const class SfxModule *) +sd/source/ui/inc/unomodel.hxx:135 + _Bool SdXImpressDocument::operator==(const class SdXImpressDocument &) const +sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx:199 + _Bool sd::slidesorter::view::InsertPosition::operator!=(const class sd::slidesorter::view::InsertPosition &) const +sdext/source/pdfimport/pdfparse/pdfparse.cxx:111 + long (anonymous namespace)::PDFGrammar>::pdf_string_parser::operator()(const type-parameter-?-? &,struct boost::spirit::classic::nil_t &) const +sfx2/inc/autoredactdialog.hxx:74 + void TargetsTable::select(int) +sfx2/source/appl/shutdownicon.hxx:78 + class rtl::OUString ShutdownIcon::getShortcutName() +sfx2/source/appl/shutdownicon.hxx:94 + class ShutdownIcon * ShutdownIcon::createInstance() +sfx2/source/appl/shutdownicon.hxx:96 + void ShutdownIcon::terminateDesktop() +sfx2/source/appl/shutdownicon.hxx:99 + void ShutdownIcon::FileOpen() +sfx2/source/appl/shutdownicon.hxx:102 + void ShutdownIcon::FromTemplate() +sfx2/source/appl/shutdownicon.hxx:111 + class rtl::OUString ShutdownIcon::GetUrlDescription(const class rtl::OUString &) +sfx2/source/appl/shutdownicon.hxx:113 + void ShutdownIcon::SetVeto(_Bool) +sfx2/source/inc/templdgi.hxx:133 + void SfxCommonTemplateDialog_Impl::LinkStubUpdateStyleDependents_Hdl(void *,void *) +shell/inc/xml_parser.hxx:43 + xml_parser::xml_parser() +shell/inc/xml_parser.hxx:66 + void xml_parser::parse(const char *,unsigned long,_Bool) +shell/inc/xml_parser.hxx:84 + void xml_parser::set_document_handler(class i_xml_parser_event_handler *) +slideshow/source/engine/activities/activitiesfactory.cxx:172 + void slideshow::internal::(anonymous namespace)::FromToByActivity::startAnimation() +slideshow/source/engine/activities/activitiesfactory.cxx:241 + void slideshow::internal::(anonymous namespace)::FromToByActivity::endAnimation() +slideshow/source/engine/activities/activitiesfactory.cxx:249 + void slideshow::internal::(anonymous namespace)::FromToByActivity::perform(double,unsigned int) const +slideshow/source/engine/activities/activitiesfactory.cxx:313 + void slideshow::internal::(anonymous namespace)::FromToByActivity::perform(unsigned int,unsigned int) const +slideshow/source/engine/activities/activitiesfactory.cxx:331 + void slideshow::internal::(anonymous namespace)::FromToByActivity::performEnd() +slideshow/source/engine/activities/activitiesfactory.cxx:344 + void slideshow::internal::(anonymous namespace)::FromToByActivity::dispose() +slideshow/source/engine/activities/activitiesfactory.cxx:525 + void slideshow::internal::(anonymous namespace)::ValuesActivity::startAnimation() +slideshow/source/engine/activities/activitiesfactory.cxx:536 + void slideshow::internal::(anonymous namespace)::ValuesActivity::endAnimation() +slideshow/source/engine/activities/activitiesfactory.cxx:544 + void slideshow::internal::(anonymous namespace)::ValuesActivity::perform(unsigned int,double,unsigned int) const +slideshow/source/engine/activities/activitiesfactory.cxx:566 + void slideshow::internal::(anonymous namespace)::ValuesActivity::perform(unsigned int,unsigned int) const +slideshow/source/engine/activities/activitiesfactory.cxx:581 + void slideshow::internal::(anonymous namespace)::ValuesActivity::performEnd() +slideshow/source/engine/animationfactory.cxx:616 + void slideshow::internal::(anonymous namespace)::GenericAnimation::prefetch() +slideshow/source/engine/animationfactory.cxx:619 + void slideshow::internal::(anonymous namespace)::GenericAnimation::start(const class std::shared_ptr &,const class std::shared_ptr &) +slideshow/source/engine/animationfactory.cxx:698 + _Bool slideshow::internal::(anonymous namespace)::GenericAnimation::operator()(const typename type-parameter-?-?::ValueType &) +slideshow/source/engine/animationfactory.cxx:715 + _Bool slideshow::internal::(anonymous namespace)::GenericAnimation::operator()(typename type-parameter-?-?::ValueType) +slideshow/source/engine/animationfactory.cxx:736 + typename type-parameter-?-?::ValueType slideshow::internal::(anonymous namespace)::GenericAnimation::getUnderlyingValue() const +slideshow/source/engine/opengl/TransitionImpl.cxx:1438 + struct std::array (anonymous namespace)::(anonymous)::__invoke() +slideshow/source/engine/opengl/TransitionImpl.hxx:180 + void OGLTransitionImpl::cleanup() +slideshow/source/inc/box2dtools.hxx:159 + void box2d::utils::box2DWorld::setShapeAngle(const class com::sun::star::uno::Reference,const double) +slideshow/source/inc/box2dtools.hxx:261 + _Bool box2d::utils::box2DWorld::shapesInitialized() +slideshow/source/inc/box2dtools.hxx:299 + class std::shared_ptr box2d::utils::box2DWorld::makeShapeStatic(const class std::shared_ptr &) +slideshow/source/inc/listenercontainer.hxx:44 + _Bool slideshow::internal::FunctionApply::apply(type-parameter-?-?,const class std::shared_ptr &) +slideshow/source/inc/listenercontainer.hxx:44 + _Bool slideshow::internal::FunctionApply::apply(type-parameter-?-?,const class std::shared_ptr &) +slideshow/source/inc/listenercontainer.hxx:44 + _Bool slideshow::internal::FunctionApply::apply(type-parameter-?-?,const class std::shared_ptr &) +slideshow/source/inc/listenercontainer.hxx:44 + _Bool slideshow::internal::FunctionApply::apply(type-parameter-?-?,const class std::shared_ptr &) +slideshow/source/inc/listenercontainer.hxx:44 + _Bool slideshow::internal::FunctionApply::apply(type-parameter-?-?,const class std::shared_ptr &) +slideshow/source/inc/listenercontainer.hxx:44 + _Bool slideshow::internal::FunctionApply::apply(type-parameter-?-?,const class std::shared_ptr &) +slideshow/source/inc/listenercontainer.hxx:44 + _Bool slideshow::internal::FunctionApply::apply(type-parameter-?-?,const class std::shared_ptr &) +slideshow/source/inc/listenercontainer.hxx:54 + _Bool slideshow::internal::FunctionApply::apply(type-parameter-?-?,const class std::shared_ptr &) +slideshow/source/inc/listenercontainer.hxx:54 + _Bool slideshow::internal::FunctionApply::apply(type-parameter-?-?,const class std::shared_ptr &) +starmath/inc/format.hxx:137 + _Bool SmFormat::operator!=(const class SmFormat &) const +starmath/inc/mathml/attribute.hxx:80 + SmMlAttribute::SmMlAttribute(const class SmMlAttribute *) +starmath/inc/mathml/attribute.hxx:116 + _Bool SmMlAttribute::isMlAttributeValueType(enum SmMlAttributeValueType) const +starmath/inc/mathml/attribute.hxx:132 + void SmMlAttribute::setMlAttributeValue(const class SmMlAttribute &) +starmath/inc/mathml/element.hxx:104 + _Bool SmMlElement::isMlElementType(enum SmMlElementType) const +starmath/inc/mathml/element.hxx:114 + const struct ESelection & SmMlElement::getESelection() const +starmath/inc/mathml/element.hxx:126 + void SmMlElement::setESelection(struct ESelection) +starmath/inc/mathml/element.hxx:133 + int SmMlElement::GetSourceCodeRow() const +starmath/inc/mathml/element.hxx:140 + int SmMlElement::GetSourceCodeColumn() const +starmath/inc/mathml/export.hxx:54 + void SmMLExportWrapper::setFlat(_Bool) +starmath/inc/mathml/export.hxx:58 + _Bool SmMLExportWrapper::getFlat() const +starmath/inc/mathml/export.hxx:62 + void SmMLExportWrapper::setUseHTMLMLEntities(_Bool) +starmath/inc/mathml/export.hxx:69 + _Bool SmMLExportWrapper::getUseHTMLMLEntities() const +starmath/inc/mathml/export.hxx:73 + _Bool SmMLExportWrapper::getUseExportTag() const +starmath/inc/mathml/export.hxx:77 + void SmMLExportWrapper::setUseExportTag(_Bool) +starmath/inc/mathml/export.hxx:80 + SmMLExportWrapper::SmMLExportWrapper(const class com::sun::star::uno::Reference &) +starmath/inc/mathml/export.hxx:91 + _Bool SmMLExportWrapper::Export(class SfxMedium &) +starmath/inc/mathml/export.hxx:95 + class rtl::OUString SmMLExportWrapper::Export(class SmMlElement *) +starmath/inc/mathml/export.hxx:138 + _Bool SmMLExport::getUseExportTag() const +starmath/inc/mathml/import.hxx:38 + class SmMlElement * SmMLImportWrapper::getElementTree() +starmath/inc/mathml/import.hxx:43 + SmMLImportWrapper::SmMLImportWrapper(const class com::sun::star::uno::Reference &) +starmath/inc/mathml/import.hxx:52 + class ErrCode SmMLImportWrapper::Import(class SfxMedium &) +starmath/inc/mathml/import.hxx:56 + class ErrCode SmMLImportWrapper::Import(class std::basic_string_view) +starmath/inc/mathml/import.hxx:144 + void SmMLImport::SetSmSyntaxVersion(unsigned short) +starmath/inc/mathml/import.hxx:148 + unsigned short SmMLImport::GetSmSyntaxVersion() const +starmath/inc/mathml/iterator.hxx:121 + class SmMlElement * mathml::SmMlIteratorCopy(class SmMlElement *) +starmath/inc/mathml/mathmlexport.hxx:61 + _Bool SmXMLExportWrapper::IsUseHTMLMLEntities() const +starmath/inc/mathml/mathmlimport.hxx:111 + unsigned short SmXMLImport::GetSmSyntaxVersion() const +starmath/inc/mathml/mathmlMo.hxx:82 + enum moOpDF operator|(enum moOpDF,enum moOpDF) +starmath/inc/mathml/mathmlMo.hxx:87 + enum moOpDF operator&(enum moOpDF,enum moOpDF) +starmath/inc/mathml/mathmlMo.hxx:97 + enum moOpDP operator&(enum moOpDP,enum moOpDP) +starmath/inc/mathml/starmathdatabase.hxx:274 + struct SmColorTokenTableEntry starmathdatabase::Identify_Color_HTML(unsigned int) +starmath/inc/mathml/starmathdatabase.hxx:294 + struct SmColorTokenTableEntry starmathdatabase::Identify_Color_DVIPSNAMES(unsigned int) +starmath/inc/node.hxx:507 + class SmNode * SmStructureNode::GetSubNodeBinMo(unsigned long) const +starmath/inc/node.hxx:532 + void SmStructureNode::SetSubNodes(class SmNode *,class SmNode *,class SmNode *) +starmath/inc/node.hxx:553 + void SmStructureNode::SetSubNodesBinMo(class SmNode *,class SmNode *,class SmNode *) +starmath/inc/nodetype.hxx:59 + _Bool starmathdatabase::isStructuralNode(enum SmNodeType) +starmath/inc/nodetype.hxx:71 + _Bool starmathdatabase::isBinOperatorNode(enum SmNodeType) +starmath/inc/nodetype.hxx:77 + _Bool starmathdatabase::isUnOperatorNode(enum SmNodeType) +starmath/inc/nodetype.hxx:82 + _Bool starmathdatabase::isOperatorNode(enum SmNodeType) +starmath/inc/nodetype.hxx:89 + _Bool starmathdatabase::isStandaloneNode(enum SmNodeType) +starmath/inc/parse.hxx:31 + class AbstractSmParser * starmathdatabase::GetDefaultSmParser() +starmath/inc/token.hxx:186 + SmColorTokenTableEntry::SmColorTokenTableEntry(const class std::unique_ptr) +starmath/inc/token.hxx:207 + _Bool SmColorTokenTableEntry::equals(const class rtl::OUString &) const +starmath/inc/token.hxx:214 + _Bool SmColorTokenTableEntry::equals(class Color) const +svgio/inc/svgstyleattributes.hxx:345 + class svgio::svgreader::SvgNumber svgio::svgreader::SvgStyleAttributes::getStrokeDashOffset() const +svgio/inc/svgstyleattributes.hxx:369 + enum svgio::svgreader::FontStretch svgio::svgreader::SvgStyleAttributes::getFontStretch() const +svgio/inc/svgtspannode.hxx:45 + double svgio::svgreader::SvgTspanNode::getCurrentFontSize() const +svl/source/misc/gridprinter.cxx:45 + class mdds::mtv::base_element_block * rtl::mdds_mtv_create_new_block(const class rtl::OUString &,const type-parameter-?-? &,const type-parameter-?-? &) +svl/source/misc/gridprinter.cxx:45 + void rtl::mdds_mtv_append_values(class mdds::mtv::base_element_block &,const class rtl::OUString &,const type-parameter-?-? &,const type-parameter-?-? &) +svl/source/misc/gridprinter.cxx:45 + void rtl::mdds_mtv_assign_values(class mdds::mtv::base_element_block &,const class rtl::OUString &,const type-parameter-?-? &,const type-parameter-?-? &) +svl/source/misc/gridprinter.cxx:45 + void rtl::mdds_mtv_get_empty_value(class rtl::OUString &) +svl/source/misc/gridprinter.cxx:45 + void rtl::mdds_mtv_get_value(const class mdds::mtv::base_element_block &,unsigned long,class rtl::OUString &) +svl/source/misc/gridprinter.cxx:45 + void rtl::mdds_mtv_insert_values(class mdds::mtv::base_element_block &,unsigned long,const class rtl::OUString &,const type-parameter-?-? &,const type-parameter-?-? &) +svl/source/misc/gridprinter.cxx:45 + void rtl::mdds_mtv_prepend_values(class mdds::mtv::base_element_block &,const class rtl::OUString &,const type-parameter-?-? &,const type-parameter-?-? &) +svl/source/misc/gridprinter.cxx:45 + void rtl::mdds_mtv_set_values(class mdds::mtv::base_element_block &,unsigned long,const class rtl::OUString &,const type-parameter-?-? &,const type-parameter-?-? &) +svx/inc/sdr/contact/viewcontactofgraphic.hxx:52 + class SdrGrafObj & sdr::contact::ViewContactOfGraphic::GetGrafObject() +sw/inc/calbck.hxx:295 + class sw::WriterListener * sw::ClientIteratorBase::GetLeftOfPos() +sw/inc/dbgoutsw.hxx:54 + const char * dbg_out(const void *) +sw/inc/dbgoutsw.hxx:56 + const char * dbg_out(const class SwRect &) +sw/inc/dbgoutsw.hxx:57 + const char * dbg_out(const class SwFrameFormat &) +sw/inc/dbgoutsw.hxx:60 + const char * dbg_out(const class SwContentNode *) +sw/inc/dbgoutsw.hxx:61 + const char * dbg_out(const class SwTextNode *) +sw/inc/dbgoutsw.hxx:62 + const char * dbg_out(const class SwTextAttr &) +sw/inc/dbgoutsw.hxx:63 + const char * dbg_out(const class SwpHints &) +sw/inc/dbgoutsw.hxx:64 + const char * dbg_out(const class SfxPoolItem &) +sw/inc/dbgoutsw.hxx:65 + const char * dbg_out(const class SfxPoolItem *) +sw/inc/dbgoutsw.hxx:66 + const char * dbg_out(const class SfxItemSet &) +sw/inc/dbgoutsw.hxx:67 + const char * dbg_out(const struct SwPosition &) +sw/inc/dbgoutsw.hxx:68 + const char * dbg_out(const class SwPaM &) +sw/inc/dbgoutsw.hxx:69 + const char * dbg_out(const class SwNodeNum &) +sw/inc/dbgoutsw.hxx:70 + const char * dbg_out(const class SwUndo &) +sw/inc/dbgoutsw.hxx:71 + const char * dbg_out(const class SwOutlineNodes &) +sw/inc/dbgoutsw.hxx:72 + const char * dbg_out(const class SwNumRule &) +sw/inc/dbgoutsw.hxx:73 + const char * dbg_out(const class SwTextFormatColl &) +sw/inc/dbgoutsw.hxx:74 + const char * dbg_out(const class SwFrameFormats &) +sw/inc/dbgoutsw.hxx:75 + const char * dbg_out(const class SwNumRuleTable &) +sw/inc/dbgoutsw.hxx:76 + const char * dbg_out(const class SwNodeRange &) +sw/inc/dbgoutsw.hxx:79 + class rtl::OUString lcl_dbg_out(const unordered_map, allocator > > &) +sw/inc/dbgoutsw.hxx:103 + const char * dbg_out(const unordered_map, allocator > > &) +sw/inc/dbgoutsw.hxx:107 + const char * dbg_out(const struct SwFormToken &) +sw/inc/dbgoutsw.hxx:108 + const char * dbg_out(const class std::vector &) +sw/inc/docary.hxx:98 + void SwVectorModifyBase::insert(class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag>,type-parameter-?-?,type-parameter-?-?) +sw/inc/docary.hxx:98 + void SwVectorModifyBase::insert(class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag>,type-parameter-?-?,type-parameter-?-?) +sw/inc/docary.hxx:98 + void SwVectorModifyBase::insert(class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag>,type-parameter-?-?,type-parameter-?-?) +sw/inc/docary.hxx:98 + void SwVectorModifyBase::insert(class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag>,type-parameter-?-?,type-parameter-?-?) +sw/inc/docary.hxx:98 + void SwVectorModifyBase::insert(class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag>,type-parameter-?-?,type-parameter-?-?) +sw/inc/docary.hxx:144 + void SwVectorModifyBase::dumpAsXml(struct _xmlTextWriter *) +sw/inc/docufld.hxx:501 + void SwPostItField::ToggleResolved() +sw/inc/editsh.hxx:370 + void SwEditShell::ValidateCurrentParagraphSignatures(_Bool) +sw/inc/extinput.hxx:47 + class SwExtTextInput * SwExtTextInput::GetPrev() +sw/inc/extinput.hxx:48 + const class SwExtTextInput * SwExtTextInput::GetPrev() const +sw/inc/frameformats.hxx:80 + void SwFrameFormats::erase(unsigned long) +sw/inc/frameformats.hxx:97 + class SwFrameFormat *const & SwFrameFormats::back() const +sw/inc/IDocumentLinksAdministration.hxx:54 + _Bool IDocumentLinksAdministration::GetData(const class rtl::OUString &,const class rtl::OUString &,class com::sun::star::uno::Any &) const +sw/inc/IDocumentLinksAdministration.hxx:56 + void IDocumentLinksAdministration::SetData(const class rtl::OUString &) +sw/inc/IDocumentMarkAccess.hxx:93 + class IDocumentMarkAccess::iterator IDocumentMarkAccess::iterator::operator++(int) +sw/inc/IDocumentMarkAccess.hxx:96 + class IDocumentMarkAccess::iterator & IDocumentMarkAccess::iterator::operator--() +sw/inc/IDocumentMarkAccess.hxx:97 + class IDocumentMarkAccess::iterator IDocumentMarkAccess::iterator::operator--(int) +sw/inc/IDocumentMarkAccess.hxx:98 + class IDocumentMarkAccess::iterator & IDocumentMarkAccess::iterator::operator+=(long) +sw/inc/IDocumentMarkAccess.hxx:100 + class IDocumentMarkAccess::iterator & IDocumentMarkAccess::iterator::operator-=(long) +sw/inc/IDocumentMarkAccess.hxx:104 + _Bool IDocumentMarkAccess::iterator::operator<(const class IDocumentMarkAccess::iterator &) const +sw/inc/IDocumentMarkAccess.hxx:105 + _Bool IDocumentMarkAccess::iterator::operator>(const class IDocumentMarkAccess::iterator &) const +sw/inc/IDocumentMarkAccess.hxx:107 + _Bool IDocumentMarkAccess::iterator::operator>=(const class IDocumentMarkAccess::iterator &) const +sw/inc/modcfg.hxx:344 + _Bool SwModuleOptions::IsFileEncryptedFromColumn() const +sw/inc/node.hxx:241 + const class IDocumentStylePoolAccess & SwNode::getIDocumentStylePoolAccess() const +sw/inc/node.hxx:245 + const class IDocumentDrawModelAccess & SwNode::getIDocumentDrawModelAccess() const +sw/inc/pagedesc.hxx:445 + void SwPageDescs::erase(class SwPageDesc *const &) +sw/inc/pagedesc.hxx:453 + class SwPageDesc *const & SwPageDescs::front() const +sw/inc/pagedesc.hxx:454 + class SwPageDesc *const & SwPageDescs::back() const +sw/inc/rdfhelper.hxx:76 + void SwRDFHelper::cloneStatements(const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &,const class rtl::OUString &,const class com::sun::star::uno::Reference &,const class com::sun::star::uno::Reference &) +sw/inc/rdfhelper.hxx:94 + void SwRDFHelper::removeTextNodeStatement(const class rtl::OUString &,class SwTextNode &,const class rtl::OUString &,const class rtl::OUString &) +sw/inc/rdfhelper.hxx:97 + void SwRDFHelper::updateTextNodeStatement(const class rtl::OUString &,const class rtl::OUString &,class SwTextNode &,const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &) +sw/inc/ring.hxx:203 + sw::RingIterator::RingIterator() +sw/inc/shellio.hxx:85 + void SwAsciiOptions::SetIncludeHidden(_Bool) +sw/inc/swatrset.hxx:219 + const class SvxNoHyphenItem & SwAttrSet::GetNoHyphenHere(_Bool) const +sw/inc/swcrsr.hxx:221 + class SwCursor * SwCursor::GetPrev() +sw/inc/swcrsr.hxx:222 + const class SwCursor * SwCursor::GetPrev() const +sw/inc/swcrsr.hxx:307 + class SwTableCursor * SwTableCursor::GetNext() +sw/inc/swcrsr.hxx:308 + const class SwTableCursor * SwTableCursor::GetNext() const +sw/inc/swcrsr.hxx:309 + class SwTableCursor * SwTableCursor::GetPrev() +sw/inc/swcrsr.hxx:310 + const class SwTableCursor * SwTableCursor::GetPrev() const +sw/inc/swrect.hxx:102 + class SwRect & SwRect::operator-=(const class Point &) +sw/inc/swrect.hxx:108 + class SvStream & WriteSwRect(class SvStream &,const class SwRect &) +sw/inc/swrect.hxx:152 + _Bool SwRect::OverStepTop(long) const +sw/inc/textboxhelper.hxx:252 + void SwTextBoxNode::SetTextBoxActive(const class SdrObject *) +sw/inc/textboxhelper.hxx:255 + _Bool SwTextBoxNode::IsGroupTextBox() const +sw/inc/textboxhelper.hxx:259 + unsigned long SwTextBoxNode::GetTextBoxCount() const +sw/inc/view.hxx:463 + void SwView::LinkStubMoveNavigationHdl(void *,void *) +sw/inc/viscrs.hxx:208 + class SwShellTableCursor * SwShellTableCursor::GetNext() +sw/inc/viscrs.hxx:209 + const class SwShellTableCursor * SwShellTableCursor::GetNext() const +sw/inc/viscrs.hxx:210 + class SwShellTableCursor * SwShellTableCursor::GetPrev() +sw/inc/viscrs.hxx:211 + const class SwShellTableCursor * SwShellTableCursor::GetPrev() const +sw/qa/inc/swmodeltestbase.hxx:282 + class com::sun::star::uno::Reference SwModelTestBase::getParagraphAnchoredObject(const int,const class com::sun::star::uno::Reference &) const +sw/qa/unit/sw-dialogs-test_2.cxx:92 + int main() +sw/source/core/access/accportions.cxx:57 + unsigned long FindBreak(const vector > &,type-parameter-?-?) +sw/source/core/access/accportions.cxx:61 + unsigned long FindLastBreak(const vector > &,type-parameter-?-?) +sw/source/core/inc/AccessibilityIssue.hxx:52 + const class std::vector & sw::AccessibilityIssue::getAdditionalInfo() const +sw/source/core/inc/AccessibilityIssue.hxx:54 + void sw::AccessibilityIssue::setAdditionalInfo(class std::vector &&) +sw/source/core/inc/frame.hxx:937 + void SwFrame::dumpTopMostAsXml(struct _xmlTextWriter *) const +sw/source/core/inc/frame.hxx:1385 + class Size SwRectFnSet::GetSize(const class SwRect &) const +sw/source/core/inc/frame.hxx:1416 + long SwRectFnSet::LeftDist(const class SwRect &,long) const +sw/source/core/inc/frame.hxx:1417 + long SwRectFnSet::RightDist(const class SwRect &,long) const +sw/source/core/inc/mvsave.hxx:171 + _Bool ZSortFly::operator==(const class ZSortFly &) const +sw/source/core/text/porlin.hxx:119 + _Bool SwLinePortion::IsTabRightPortion() const +sw/source/core/text/txtpaint.hxx:72 + DbgBackColor::DbgBackColor(class OutputDevice *,const _Bool) +sw/source/core/text/txtpaint.hxx:79 + DbgRect::DbgRect(class OutputDevice *,const class tools::Rectangle &,const _Bool,class Color) +sw/source/uibase/inc/swcont.hxx:88 + _Bool SwContent::operator==(const class SwContent &) const +test/source/sheet/xsubtotalfield.cxx:28 + _Bool CppUnit::assertion_traits::equal(const class com::sun::star::uno::Sequence &,const class com::sun::star::uno::Sequence &) +test/source/sheet/xsubtotalfield.cxx:34 + class std::basic_string CppUnit::assertion_traits::toString(const class com::sun::star::uno::Sequence &) +ucb/source/inc/regexpmap.hxx:285 + RegexpMapConstIter ucb_impl::RegexpMap::begin() const +ucb/source/inc/regexpmap.hxx:289 + RegexpMapConstIter ucb_impl::RegexpMap::end() const +ucb/source/ucp/ftp/ftpurl.hxx:108 + class rtl::OUString ftp::FTPURL::child() const +ucb/source/ucp/gio/gio_mount.cxx:37 + void * ooo_mount_operation_get_instance_private(struct OOoMountOperation *) +vcl/inc/bitmap/BitmapWriteAccess.hxx:73 + void BitmapWriteAccess::SetFillColor() +vcl/inc/bitmap/ScanlineTools.hxx:23 + void vcl::bitmap::ScanlineTransformer::skipPixel(unsigned int) +vcl/inc/ControlCacheKey.hxx:35 + ControlCacheKey::ControlCacheKey(enum ControlType,enum ControlPart,enum ControlState,const class Size &) +vcl/inc/ControlCacheKey.hxx:43 + _Bool ControlCacheKey::operator==(const class ControlCacheKey &) const +vcl/inc/ControlCacheKey.hxx:50 + _Bool ControlCacheKey::canCacheControl() const +vcl/inc/ControlCacheKey.hxx:81 + unsigned long ControlCacheHashFunction::operator()(const class ControlCacheKey &) const +vcl/inc/driverblocklist.hxx:95 + DriverBlocklist::DriverInfo::DriverInfo(enum DriverBlocklist::OperatingSystem,const class rtl::OUString &,enum DriverBlocklist::VersionComparisonOp,unsigned long,_Bool,const char *) +vcl/inc/font/FontSelectPattern.hxx:52 + _Bool vcl::font::FontSelectPattern::operator!=(const class vcl::font::FontSelectPattern &) const +vcl/inc/fontinstance.hxx:70 + void LogicalFontInstance::SetAverageWidthFactor(double) +vcl/inc/fontinstance.hxx:71 + double LogicalFontInstance::GetAverageWidthFactor() const +vcl/inc/graphic/GraphicID.hxx:39 + _Bool GraphicID::operator==(const class GraphicID &) const +vcl/inc/headless/CairoCommon.hxx:155 + struct _cairo_surface * CairoCommon::getSurface() const +vcl/inc/headless/svpgdi.hxx:103 + struct _cairo * SvpSalGraphics::createTmpCompatibleCairoContext() const +vcl/inc/jsdialog/jsdialogbuilder.hxx:197 + void JSDropTarget::fire_dragEnter(const struct com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent &) +vcl/inc/opengl/zone.hxx:26 + void OpenGLZone::relaxWatchdogTimings() +vcl/inc/qt5/QtAccessibleWidget.hxx:48 + void QtAccessibleWidget::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void **) +vcl/inc/qt5/QtAccessibleWidget.hxx:51 + QtAccessibleWidget::QtAccessibleWidget(const class com::sun::star::uno::Reference,class QObject *) +vcl/inc/qt5/QtAccessibleWidget.hxx:154 + class com::sun::star::uno::Reference QtAccessibleWidget::getAccessibleContextImpl() const +vcl/inc/qt5/QtAccessibleWidget.hxx:155 + class com::sun::star::uno::Reference QtAccessibleWidget::getAccessibleTableForParent() const +vcl/inc/qt5/QtClipboard.hxx:36 + void QtClipboard::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void **) +vcl/inc/qt5/QtClipboard.hxx:53 + _Bool QtClipboard::isOwner(const enum QClipboard::Mode) +vcl/inc/qt5/QtClipboard.hxx:54 + _Bool QtClipboard::isSupported(const enum QClipboard::Mode) +vcl/inc/qt5/QtClipboard.hxx:56 + QtClipboard::QtClipboard(const class rtl::OUString &,const enum QClipboard::Mode) +vcl/inc/qt5/QtClipboard.hxx:59 + void QtClipboard::handleChanged(enum QClipboard::Mode) +vcl/inc/qt5/QtClipboard.hxx:60 + void QtClipboard::handleClearClipboard() +vcl/inc/qt5/QtClipboard.hxx:63 + void QtClipboard::clearClipboard() +vcl/inc/qt5/QtDragAndDrop.hxx:49 + void QtDragSource::deinitialize() +vcl/inc/qt5/QtDragAndDrop.hxx:80 + void QtDropTarget::deinitialize() +vcl/inc/qt5/QtFilePicker.hxx:60 + void QtFilePicker::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void **) +vcl/inc/qt5/QtFilePicker.hxx:169 + class QString QtFilePicker::getResString(struct TranslateId) +vcl/inc/qt5/QtFilePicker.hxx:170 + class com::sun::star::uno::Any QtFilePicker::handleGetListValue(const class QComboBox *,short) +vcl/inc/qt5/QtFilePicker.hxx:171 + void QtFilePicker::handleSetListValue(class QComboBox *,short,const class com::sun::star::uno::Any &) +vcl/inc/qt5/QtFilePicker.hxx:174 + void QtFilePicker::prepareExecute() +vcl/inc/qt5/QtFilePicker.hxx:178 + void QtFilePicker::filterSelected(const class QString &) +vcl/inc/qt5/QtFilePicker.hxx:180 + void QtFilePicker::currentChanged(const class QString &) +vcl/inc/qt5/QtFilePicker.hxx:183 + void QtFilePicker::finished(int) +vcl/inc/qt5/QtFontFace.hxx:43 + class QtFontFace * QtFontFace::fromQFont(const class QFont &) +vcl/inc/qt5/QtFontFace.hxx:54 + int QtFontFace::GetFontTable(const char *,unsigned char *) const +vcl/inc/qt5/QtFontFace.hxx:58 + _Bool QtFontFace::HasChar(unsigned int) const +vcl/inc/qt5/QtFrame.hxx:69 + void QtFrame::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void **) +vcl/inc/qt5/QtFrame.hxx:112 + void QtFrame::SetDefaultPos() +vcl/inc/qt5/QtFrame.hxx:113 + class Size QtFrame::CalcDefaultSize() +vcl/inc/qt5/QtFrame.hxx:114 + void QtFrame::SetDefaultSize() +vcl/inc/qt5/QtFrame.hxx:116 + _Bool QtFrame::isChild(_Bool,_Bool) const +vcl/inc/qt5/QtFrame.hxx:126 + _Bool QtFrame::isWindow() const +vcl/inc/qt5/QtFrame.hxx:127 + class QWindow * QtFrame::windowHandle() const +vcl/inc/qt5/QtFrame.hxx:128 + class QScreen * QtFrame::screen() const +vcl/inc/qt5/QtFrame.hxx:129 + _Bool QtFrame::isMinimized() const +vcl/inc/qt5/QtFrame.hxx:130 + _Bool QtFrame::isMaximized() const +vcl/inc/qt5/QtFrame.hxx:131 + void QtFrame::SetWindowStateImpl(class QFlags) +vcl/inc/qt5/QtFrame.hxx:132 + int QtFrame::menuBarOffset() const +vcl/inc/qt5/QtFrame.hxx:134 + void QtFrame::fixICCCMwindowGroup() +vcl/inc/qt5/QtFrame.hxx:135 + void QtFrame::modalReparent(_Bool) +vcl/inc/qt5/QtFrame.hxx:146 + void QtFrame::Damage(int,int,int,int) const +vcl/inc/qt5/QtFrame.hxx:160 + void QtFrame::deregisterDragSource(const class QtDragSource *) +vcl/inc/qt5/QtFrame.hxx:162 + void QtFrame::deregisterDropTarget(const class QtDropTarget *) +vcl/inc/qt5/QtGraphics.hxx:180 + void QtGraphics::drawScaledImage(const struct SalTwoRect &,const class QImage &) +vcl/inc/qt5/QtGraphics_Controls.hxx:96 + class QPoint QtGraphics_Controls::upscale(const class QPoint &,enum QtGraphics_Controls::Round) +vcl/inc/qt5/QtInstance.hxx:54 + void QtInstance::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void **) +vcl/inc/qt5/QtInstance.hxx:70 + void QtInstance::LinkStubupdateStyleHdl(void *,class Timer *) +vcl/inc/qt5/QtInstance.hxx:70 + void QtInstance::updateStyleHdl(class Timer *) +vcl/inc/qt5/QtInstance.hxx:74 + _Bool QtInstance::ImplYield(_Bool,_Bool) +vcl/inc/qt5/QtInstance.hxx:75 + void QtInstance::deleteObjectLater(class QObject *) +vcl/inc/qt5/QtInstance.hxx:76 + void QtInstance::localeChanged() +vcl/inc/qt5/QtInstance.hxx:79 + _Bool QtInstance::ImplYieldSignal(_Bool,_Bool) +vcl/inc/qt5/QtInstance.hxx:80 + void QtInstance::deleteObjectLaterSignal(class QObject *) +vcl/inc/qt5/QtMainWindow.hxx:29 + void QtMainWindow::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void **) +vcl/inc/qt5/QtMenu.hxx:40 + void QtMenu::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void **) +vcl/inc/qt5/QtMenu.hxx:55 + void QtMenu::DoFullMenuUpdate(class Menu *) +vcl/inc/qt5/QtMenu.hxx:56 + void QtMenu::NativeItemText(class rtl::OUString &) +vcl/inc/qt5/QtMenu.hxx:58 + void QtMenu::InsertMenuItem(class QtMenuItem *,unsigned int) +vcl/inc/qt5/QtMenu.hxx:60 + void QtMenu::ReinitializeActionGroup(unsigned int) +vcl/inc/qt5/QtMenu.hxx:61 + void QtMenu::ResetAllActionGroups() +vcl/inc/qt5/QtMenu.hxx:62 + void QtMenu::UpdateActionGroupItem(const class QtMenuItem *) +vcl/inc/qt5/QtMenu.hxx:73 + const class QtFrame * QtMenu::GetFrame() const +vcl/inc/qt5/QtMenu.hxx:77 + class QtMenu * QtMenu::GetTopLevel() +vcl/inc/qt5/QtMenu.hxx:92 + class Menu * QtMenu::GetMenu() +vcl/inc/qt5/QtMenu.hxx:93 + unsigned int QtMenu::GetItemCount() const +vcl/inc/qt5/QtMenu.hxx:94 + class QtMenuItem * QtMenu::GetItemAtPos(unsigned int) +vcl/inc/qt5/QtMenu.hxx:97 + void QtMenu::slotMenuTriggered(class QtMenuItem *) +vcl/inc/qt5/QtMenu.hxx:98 + void QtMenu::slotMenuAboutToShow(class QtMenuItem *) +vcl/inc/qt5/QtMenu.hxx:99 + void QtMenu::slotMenuAboutToHide(class QtMenuItem *) +vcl/inc/qt5/QtMenu.hxx:100 + void QtMenu::slotCloseDocument() +vcl/inc/qt5/QtMenu.hxx:108 + class QAction * QtMenuItem::getAction() const +vcl/inc/qt5/QtObject.hxx:34 + void QtObject::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void **) +vcl/inc/qt5/QtObject.hxx:46 + class QtFrame * QtObject::frame() const +vcl/inc/qt5/QtObject.hxx:47 + class QWidget * QtObject::widget() const +vcl/inc/qt5/QtObject.hxx:78 + QtObjectWindow::QtObjectWindow(class QtObject &) +vcl/inc/qt5/QtPainter.hxx:61 + void QtPainter::update() +vcl/inc/qt5/QtTimer.hxx:27 + void QtTimer::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void **) +vcl/inc/qt5/QtTimer.hxx:32 + void QtTimer::timeoutActivated() +vcl/inc/qt5/QtTimer.hxx:33 + void QtTimer::startTimer(int) +vcl/inc/qt5/QtTimer.hxx:34 + void QtTimer::stopTimer() +vcl/inc/qt5/QtTimer.hxx:37 + void QtTimer::startTimerSignal(int) +vcl/inc/qt5/QtTimer.hxx:38 + void QtTimer::stopTimerSignal() +vcl/inc/qt5/QtTools.hxx:58 + class QRect toQRect(const class tools::Rectangle &,const double) +vcl/inc/qt5/QtWidget.hxx:35 + void QtWidget::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void **) +vcl/inc/qt5/QtWidget.hxx:48 + void QtWidget::commitText(class QtFrame &,const class QString &) +vcl/inc/qt5/QtWidget.hxx:51 + void QtWidget::fillSalAbstractMouseEvent(const class QtFrame &,const class QInputEvent *,const class QPoint &,class QFlags,int,struct SalAbstractMouseEvent &) +vcl/inc/qt5/QtWidget.hxx:78 + void QtWidget::closePopup() +vcl/inc/qt5/QtXAccessible.hxx:27 + void QtXAccessible::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void **) +vcl/inc/regionband.hxx:27 + const char * ImplDbgTestRegionBand(const void *) +vcl/inc/salgdi.hxx:672 + void SalGraphics::FillFontSubsetInfo(const struct vcl::TTGlobalFontInfo_ &,const class rtl::OUString &,class FontSubsetInfo &) +vcl/inc/salmenu.hxx:46 + SalMenuButtonItem::SalMenuButtonItem() +vcl/inc/salobj.hxx:73 + _Bool SalObject::IsEraseBackgroundEnabled() const +vcl/inc/saltimer.hxx:69 + VersionedEvent::VersionedEvent() +vcl/inc/saltimer.hxx:71 + int VersionedEvent::GetNextEventVersion() +vcl/inc/saltimer.hxx:90 + _Bool VersionedEvent::ExistsValidEvent() const +vcl/inc/saltimer.hxx:95 + _Bool VersionedEvent::IsValidEventVersion(const int) const +vcl/inc/salwtype.hxx:129 + SalMenuEvent::SalMenuEvent() +vcl/inc/schedulerimpl.hxx:49 + const char * ImplSchedulerData::GetDebugName() const +vcl/inc/skia/gdiimpl.hxx:49 + const class vcl::Region & SkiaSalGraphicsImpl::getClipRegion() const +vcl/inc/skia/gdiimpl.hxx:204 + void SkiaSalGraphicsImpl::dump(const char *) const +vcl/inc/skia/salbmp.hxx:99 + void SkiaSalBitmap::dump(const char *) const +vcl/inc/skia/utils.hxx:56 + class sk_sp SkiaHelper::createSkSurface(int,int,enum SkAlphaType) +vcl/inc/skia/utils.hxx:119 + void SkiaHelper::removeCachedImage(class sk_sp) +vcl/inc/skia/utils.hxx:129 + void SkiaHelper::setPixelGeometry(enum SkPixelGeometry) +vcl/inc/skia/utils.hxx:243 + void SkiaHelper::dump(const class SkBitmap &,const char *) +vcl/inc/skia/zone.hxx:25 + void SkiaZone::relaxWatchdogTimings() +vcl/inc/unx/fontmanager.hxx:179 + void psp::PrintFontManager::fillPrintFontInfo(struct psp::PrintFontManager::PrintFont &,struct psp::PrintFontInfo &) const +vcl/inc/unx/gtk/gtkframe.hxx:296 + void GtkSalFrame::DrawingAreaFocusInOut(enum SalEvent) +vcl/inc/unx/gtk/gtksalmenu.hxx:81 + const class GtkSalFrame * GtkSalMenu::GetFrame() const +vcl/inc/unx/printergfx.hxx:94 + _Bool psp::PrinterColor::operator!=(const class psp::PrinterColor &) const +vcl/inc/unx/saldisp.hxx:377 + class SalXLib * SalDisplay::GetXLib() const +vcl/inc/unx/salframe.h:185 + enum SalFrameStyleFlags X11SalFrame::GetStyle() const +vcl/qa/cppunit/lifecycle.cxx:197 + (anonymous namespace)::LeakTestClass::LeakTestClass(_Bool &,type-parameter-?-? &&...) +vcl/skia/salbmp.cxx:638 + void ::operator()(void *,void *) const +vcl/source/app/scheduler.cxx:83 + basic_ostream & (anonymous namespace)::operator<<(basic_ostream &,const class Idle &) +vcl/source/bitmap/BitmapColorQuantizationFilter.cxx:105 + int ::operator()(const void *,const void *) const +vcl/source/edit/textdat2.hxx:86 + class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag> TETextPortionList::begin() const +vcl/source/edit/textdat2.hxx:88 + class __gnu_debug::_Safe_iterator >, class std::vector, struct std::random_access_iterator_tag> TETextPortionList::end() const +vcl/source/filter/FilterConfigCache.hxx:71 + class rtl::OUString FilterConfigCache::GetImportFormatMediaType(unsigned short) +vcl/source/fontsubset/xlat.hxx:31 + unsigned short vcl::TranslateChar12(unsigned short) +vcl/source/fontsubset/xlat.hxx:32 + unsigned short vcl::TranslateChar13(unsigned short) +vcl/source/fontsubset/xlat.hxx:33 + unsigned short vcl::TranslateChar14(unsigned short) +vcl/source/fontsubset/xlat.hxx:34 + unsigned short vcl::TranslateChar15(unsigned short) +vcl/source/fontsubset/xlat.hxx:35 + unsigned short vcl::TranslateChar16(unsigned short) +vcl/source/window/menuitemlist.hxx:122 + void MenuItemList::Clear() +vcl/unx/gtk3/customcellrenderer.hxx:29 + int CUSTOM_IS_CELL_RENDERER(void *) +vcl/unx/gtk3/customcellrenderer.hxx:29 + struct _CustomCellRenderer * CUSTOM_CELL_RENDERER(void *) +vcl/unx/gtk3/customcellrenderer.hxx:29 + void glib_autoptr_cleanup_CustomCellRenderer(struct _CustomCellRenderer **) +vcl/unx/gtk3/customcellrenderer.hxx:29 + void glib_autoptr_cleanup_CustomCellRendererClass(CustomCellRendererClass **) +vcl/unx/gtk3/customcellrenderer.hxx:29 + void glib_listautoptr_cleanup_CustomCellRenderer(struct _GList **) +vcl/unx/gtk3/customcellrenderer.hxx:29 + void glib_listautoptr_cleanup_CustomCellRendererClass(struct _GList **) +vcl/unx/gtk3/customcellrenderer.hxx:29 + void glib_queueautoptr_cleanup_CustomCellRenderer(struct _GQueue **) +vcl/unx/gtk3/customcellrenderer.hxx:29 + void glib_queueautoptr_cleanup_CustomCellRendererClass(struct _GQueue **) +vcl/unx/gtk3/customcellrenderer.hxx:29 + void glib_slistautoptr_cleanup_CustomCellRenderer(struct _GSList **) +vcl/unx/gtk3/customcellrenderer.hxx:29 + void glib_slistautoptr_cleanup_CustomCellRendererClass(struct _GSList **) +vcl/unx/gtk3/gloactiongroup.cxx:51 + void * g_lo_action_get_instance_private(struct (anonymous namespace)::GLOAction *) +vcl/unx/gtk3/glomenu.cxx:30 + void * g_lo_menu_get_instance_private(struct GLOMenu *) +vcl/unx/kf5/KF5FilePicker.hxx:29 + void KF5FilePicker::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void **) +writerfilter/source/dmapper/SettingsTable.hxx:81 + const class rtl::OUString & writerfilter::dmapper::SettingsTable::GetDecimalSymbol() const +writerfilter/source/ooxml/OOXMLPropertySet.hxx:183 + class __gnu_debug::_Safe_iterator *, class std::__cxx1998::vector > >, class std::vector >, struct std::random_access_iterator_tag> writerfilter::ooxml::OOXMLPropertySet::begin() const +writerfilter/source/ooxml/OOXMLPropertySet.hxx:184 + class __gnu_debug::_Safe_iterator *, class std::__cxx1998::vector > >, class std::vector >, struct std::random_access_iterator_tag> writerfilter::ooxml::OOXMLPropertySet::end() const +writerfilter/source/ooxml/OOXMLPropertySet.hxx:187 + class std::basic_string writerfilter::ooxml::OOXMLPropertySet::toString() +xmlsecurity/source/gpg/XMLEncryption.hxx:24 + XMLEncryptionGpg::XMLEncryptionGpg() +xmlsecurity/source/xmlsec/nss/nssinitializer.hxx:45 + ONSSInitializer::ONSSInitializer(const class com::sun::star::uno::Reference &) diff --git a/compilerplugins/clang/unusedmethods.unused-returns.results b/compilerplugins/clang/unusedmethods.unused-returns.results new file mode 100644 index 000000000..71a3f4529 --- /dev/null +++ b/compilerplugins/clang/unusedmethods.unused-returns.results @@ -0,0 +1,388 @@ +connectivity/source/inc/java/lang/Object.hxx:109 + int connectivity::java_lang_Object::callIntMethodWithIntArg_ThrowRuntime(const char *,struct _jmethodID *&,int) const +connectivity/source/inc/odbc/OConnection.hxx:74 + short connectivity::odbc::OConnection::Construct(const class rtl::OUString &,const class com::sun::star::uno::Sequence &) +connectivity/source/inc/odbc/OStatement.hxx:113 + _Bool connectivity::odbc::OStatement_Base::lockIfNecessary(const class rtl::OUString &) +cui/source/inc/iconcdlg.hxx:70 + _Bool IconChoicePage::FillItemSet(class SfxItemSet *) +dbaccess/source/ui/app/AppSwapWindow.hxx:84 + _Bool dbaui::OApplicationSwapWindow::onContainerSelected(enum dbaui::ElementType) +extensions/source/scanner/sane.hxx:105 + _Bool Sane::CheckConsistency(const char *,_Bool) +extensions/source/scanner/sane.hxx:148 + _Bool Sane::GetOptionValue(int,double *) +extensions/source/scanner/sane.hxx:155 + _Bool Sane::ActivateButtonOption(int) +extensions/source/scanner/sane.hxx:161 + _Bool Sane::Open(int) +extensions/source/scanner/sanedlg.hxx:87 + _Bool SaneDlg::LoadState() +extensions/source/scanner/sanedlg.hxx:101 + _Bool SaneDlg::SetAdjustedNumericalValue(const char *,double,int) +framework/source/fwe/classes/addonsoptions.cxx:282 + _Bool framework::AddonsOptions_Impl::ReadToolBarItemSet(const class rtl::OUString &,class com::sun::star::uno::Sequence > &) +framework/source/fwe/classes/addonsoptions.cxx:284 + _Bool framework::AddonsOptions_Impl::ReadNotebookBarItemSet(const class rtl::OUString &,class com::sun::star::uno::Sequence > &) +i18nlangtag/source/languagetag/languagetag.cxx:298 + const class rtl::OUString & LanguageTagImpl::getBcp47() const +idlc/inc/aststack.hxx:38 + class AstStack * AstStack::push(class AstScope *) +include/basegfx/range/b2dconnectedranges.hxx:215 + type-parameter-?-? basegfx::B2DConnectedRanges::forEachAggregate(type-parameter-?-?) const +include/basegfx/vector/b2dvector.hxx:113 + class basegfx::B2DVector & basegfx::B2DVector::setLength(double) +include/basegfx/vector/b2ivector.hxx:98 + class basegfx::B2IVector & basegfx::B2IVector::setLength(double) +include/basegfx/vector/b3dvector.hxx:144 + class basegfx::B3DVector & basegfx::B3DVector::setLength(double) +include/basegfx/vector/b3dvector.hxx:169 + class basegfx::B3DVector & basegfx::B3DVector::normalize() +include/comphelper/backupfilehelper.hxx:205 + _Bool comphelper::BackupFileHelper::tryPush_extensionInfo(class std::basic_string_view) +include/comphelper/multiinterfacecontainer4.hxx:94 + int comphelper::OMultiTypeInterfaceContainerHelperVar4::addInterface(const type-parameter-?-? &,const Reference &) +include/editeng/editview.hxx:264 + class ErrCode EditView::Read(class SvStream &,enum EETextFormat,class SvKeyValueIterator *) +include/editeng/outliner.hxx:279 + _Bool OutlinerView::Command(const class CommandEvent &) +include/oox/crypto/AgileEngine.hxx:120 + _Bool oox::crypto::AgileEngine::decryptHmacKey() +include/oox/crypto/AgileEngine.hxx:121 + _Bool oox::crypto::AgileEngine::decryptHmacValue() +include/oox/crypto/AgileEngine.hxx:136 + _Bool oox::crypto::AgileEngine::encryptHmacValue() +include/oox/crypto/CryptoEngine.hxx:46 + _Bool oox::crypto::CryptoEngine::decrypt(class oox::BinaryXInputStream &,class oox::BinaryXOutputStream &) +include/oox/crypto/CryptTools.hxx:111 + _Bool oox::crypto::CryptoHash::update(class std::vector &,unsigned int) +include/oox/dump/dumperbase.hxx:640 + long oox::dump::FlagsList::getIgnoreFlags() const +include/oox/dump/dumperbase.hxx:1410 + type-parameter-?-? oox::dump::InputObjectBase::dumpName(const class oox::dump::String &,const class oox::dump::NameListWrapper &) +include/oox/dump/dumperbase.hxx:1416 + type-parameter-?-? oox::dump::InputObjectBase::dumpBin(const class oox::dump::String &,const class oox::dump::NameListWrapper &) +include/oox/dump/dumperbase.hxx:1418 + type-parameter-?-? oox::dump::InputObjectBase::dumpFix(const class oox::dump::String &,const class oox::dump::NameListWrapper &) +include/oox/dump/dumperbase.hxx:1422 + type-parameter-?-? oox::dump::InputObjectBase::dumpValue(const struct oox::dump::ItemFormat &) +include/oox/dump/dumperbase.hxx:1425 + type-parameter-?-? oox::dump::InputObjectBase::dumpName(_Bool,const class oox::dump::String &,const class oox::dump::NameListWrapper &) +include/oox/dump/dumperbase.hxx:1427 + type-parameter-?-? oox::dump::InputObjectBase::dumpDec(_Bool,const class oox::dump::String &,const class oox::dump::NameListWrapper &) +include/oox/dump/dumperbase.hxx:1431 + type-parameter-?-? oox::dump::InputObjectBase::dumpBin(_Bool,const class oox::dump::String &,const class oox::dump::NameListWrapper &) +include/oox/dump/dumperbase.hxx:1433 + type-parameter-?-? oox::dump::InputObjectBase::dumpFix(_Bool,const class oox::dump::String &,const class oox::dump::NameListWrapper &) +include/oox/dump/dumperbase.hxx:1435 + type-parameter-?-? oox::dump::InputObjectBase::dumpBool(_Bool,const class oox::dump::String &,const class oox::dump::NameListWrapper &) +include/oox/dump/dumperbase.hxx:1437 + type-parameter-?-? oox::dump::InputObjectBase::dumpValue(_Bool,const struct oox::dump::ItemFormat &) +include/oox/dump/oledumper.hxx:310 + _Bool oox::dump::AxPropertyObjectBase::dumpBoolProperty() +include/oox/dump/oledumper.hxx:311 + int oox::dump::AxPropertyObjectBase::dumpHmmProperty() +include/oox/dump/oledumper.hxx:312 + unsigned char oox::dump::AxPropertyObjectBase::dumpMousePtrProperty() +include/oox/dump/oledumper.hxx:314 + type-parameter-?-? oox::dump::AxPropertyObjectBase::dumpBorderStyleProperty(type-parameter-?-?) +include/oox/dump/oledumper.hxx:316 + type-parameter-?-? oox::dump::AxPropertyObjectBase::dumpSpecialEffectProperty(type-parameter-?-?) +include/oox/dump/oledumper.hxx:317 + unsigned int oox::dump::AxPropertyObjectBase::dumpEnabledProperty() +include/oox/dump/oledumper.hxx:318 + int oox::dump::AxPropertyObjectBase::dumpOrientationProperty() +include/oox/dump/oledumper.hxx:319 + int oox::dump::AxPropertyObjectBase::dumpDelayProperty() +include/oox/dump/oledumper.hxx:320 + unsigned int oox::dump::AxPropertyObjectBase::dumpImagePosProperty() +include/oox/dump/oledumper.hxx:321 + unsigned char oox::dump::AxPropertyObjectBase::dumpImageSizeModeProperty() +include/oox/dump/oledumper.hxx:322 + unsigned char oox::dump::AxPropertyObjectBase::dumpImageAlignProperty() +include/oox/dump/oledumper.hxx:325 + unsigned int oox::dump::AxPropertyObjectBase::dumpColorProperty(unsigned int) +include/oox/dump/oledumper.hxx:326 + char16_t oox::dump::AxPropertyObjectBase::dumpUnicodeProperty() +include/oox/export/shapes.hxx:137 + class oox::drawingml::ShapeExport & oox::drawingml::ShapeExport::WriteNonVisualDrawingProperties(const class com::sun::star::uno::Reference &,const char *) +include/oox/export/shapes.hxx:185 + class oox::drawingml::ShapeExport & oox::drawingml::ShapeExport::WriteTextBox(const class com::sun::star::uno::Reference &,int,_Bool) +include/oox/helper/binaryoutputstream.hxx:78 + class oox::BinaryOutputStream & oox::BinaryOutputStream::WriteInt16(short) +include/oox/helper/binaryoutputstream.hxx:79 + class oox::BinaryOutputStream & oox::BinaryOutputStream::WriteUInt16(unsigned short) +include/oox/helper/propertyset.hxx:110 + _Bool oox::PropertySet::setProperty(int,class Color) +include/oox/ole/axbinarywriter.hxx:115 + _Bool oox::ole::AxBinaryPropertyWriter::ComplexProperty::writeProperty(class oox::ole::AxAlignedOutputStream &) +include/oox/ole/olehelper.hxx:176 + _Bool oox::ole::MSConvertOCXControls::importControlFromStream(class oox::BinaryInputStream &,class com::sun::star::uno::Reference &,const class rtl::OUString &) +include/oox/ole/olehelper.hxx:187 + _Bool oox::ole::MSConvertOCXControls::ReadOCXCtlsStream(const class tools::SvRef &,class com::sun::star::uno::Reference &,int,int) +include/sax/fshelper.hxx:136 + class sax_fastparser::FastSerializerHelper * sax_fastparser::FastSerializerHelper::write(int) +include/sax/fshelper.hxx:137 + class sax_fastparser::FastSerializerHelper * sax_fastparser::FastSerializerHelper::write(long) +include/sax/fshelper.hxx:138 + class sax_fastparser::FastSerializerHelper * sax_fastparser::FastSerializerHelper::write(double) +include/sax/fshelper.hxx:140 + class sax_fastparser::FastSerializerHelper * sax_fastparser::FastSerializerHelper::writeEscaped(const char *) +include/sfx2/linkmgr.hxx:65 + _Bool sfx2::LinkManager::InsertLink(class sfx2::SvBaseLink *,enum sfx2::SvBaseLinkObjectType,enum SfxLinkUpdateMode,const class rtl::OUString *) +include/sfx2/lnkbase.hxx:112 + class sfx2::SvLinkSource * sfx2::SvBaseLink::GetRealObject() +include/svl/macitem.hxx:88 + class SvStream & SvxMacroTableDtor::Write(class SvStream &) const +include/svtools/ctrlbox.hxx:377 + _Bool FontNameBox::get_entry_selection_bounds(int &,int &) +include/svx/autoformathelper.hxx:212 + _Bool AutoFormatBase::LoadBlockA(class SvStream &,const struct AutoFormatVersions &,unsigned short) +include/svx/autoformathelper.hxx:213 + _Bool AutoFormatBase::LoadBlockB(class SvStream &,const struct AutoFormatVersions &,unsigned short) +include/svx/autoformathelper.hxx:215 + _Bool AutoFormatBase::SaveBlockA(class SvStream &,unsigned short) const +include/svx/autoformathelper.hxx:216 + _Bool AutoFormatBase::SaveBlockB(class SvStream &,unsigned short) const +include/svx/dlgctrl.hxx:101 + class Point SvxRectCtl::SetActualRPWithoutInvalidate(enum RectPoint) +include/svx/framelink.hxx:159 + class svx::frame::Style & svx::frame::Style::MirrorSelf() +include/svx/gallerybinaryengine.hxx:105 + class SvStream & GalleryBinaryEngine::writeGalleryTheme(class SvStream &,const class GalleryTheme &,const class GalleryThemeEntry *) +include/svx/gallerybinaryengineentry.hxx:57 + class std::unique_ptr & GalleryBinaryEngineEntry::getCachedTheme(class std::unique_ptr &) +include/test/helper/shape.hxx:41 + class com::sun::star::uno::Reference apitest::helper::shape::createEllipse(const class com::sun::star::uno::Reference &,const int,const int,const int,const int) +include/test/sheet/xdocumentauditing.hxx:28 + class com::sun::star::uno::Reference apitest::XDocumentAuditing::getXMSF() +include/test/sheet/xnamedrange.hxx:22 + class com::sun::star::uno::Reference apitest::XNamedRange::init() +include/test/sheet/xspreadsheets2.hxx:41 + class com::sun::star::uno::Reference apitest::XSpreadsheets2::getComponent() +include/tools/config.hxx:38 + _Bool Config::ImplUpdateConfig() const +include/tools/multisel.hxx:93 + _Bool StringRangeEnumerator::insertRange(int,int,_Bool) +include/tools/urlobj.hxx:739 + _Bool INetURLObject::SetParam(class std::basic_string_view,enum INetURLObject::EncodeMechanism,unsigned short) +include/unotools/localedatawrapper.hxx:159 + const class com::sun::star::uno::Sequence & LocaleDataWrapper::getAllInstalledLocaleNames() const +include/vcl/bitmapex.hxx:226 + _Bool BitmapEx::Rotate(struct o3tl::strong_int >,const class Color &) +include/vcl/filter/PngImageReader.hxx:42 + _Bool vcl::PngImageReader::read(class BitmapEx &) +include/vcl/filter/SvmReader.hxx:36 + class SvStream & SvmReader::Read(class GDIMetaFile &,struct ImplMetaReadData *) +include/vcl/filter/SvmWriter.hxx:37 + class SvStream & SvmWriter::Write(const class GDIMetaFile &) +include/vcl/formatter.hxx:218 + _Bool Formatter::SetFormat(const class rtl::OUString &,struct o3tl::strong_int) +include/vcl/graphicfilter.hxx:290 + class ErrCode GraphicFilter::ExportGraphic(const class Graphic &,const class INetURLObject &,unsigned short,const class com::sun::star::uno::Sequence *) +include/vcl/GraphicNativeMetadata.hxx:35 + _Bool GraphicNativeMetadata::read(class SvStream &) +include/vcl/GraphicNativeTransform.hxx:33 + _Bool GraphicNativeTransform::rotateBitmapOnly(struct o3tl::strong_int >) +include/vcl/GraphicNativeTransform.hxx:35 + _Bool GraphicNativeTransform::rotateGeneric(struct o3tl::strong_int >,class std::basic_string_view) +include/vcl/menu.hxx:385 + _Bool Menu::HandleMenuActivateEvent(class Menu *) const +include/vcl/menu.hxx:386 + _Bool Menu::HandleMenuDeActivateEvent(class Menu *) const +include/vcl/texteng.hxx:271 + _Bool TextEngine::Read(class SvStream &,const class TextSelection *) +include/vcl/window.hxx:1398 + _Bool vcl::Window::set_font_attribute(const class rtl::OString &,const class rtl::OUString &) +include/xmloff/unointerfacetouniqueidentifiermapper.hxx:65 + _Bool comphelper::UnoInterfaceToUniqueIdentifierMapper::registerReservedReference(const class rtl::OUString &,const class com::sun::star::uno::Reference &) +include/xmloff/xmluconv.hxx:281 + _Bool SvXMLUnitConverter::convertNumFormat(short &,const class rtl::OUString &,class std::basic_string_view,_Bool) const +linguistic/source/lngsvcmgr.hxx:118 + _Bool LngSvcMgr::SaveCfgSvcs(class std::basic_string_view) +lotuswordpro/inc/lwpsvstream.hxx:80 + class LwpSvStream & LwpSvStream::ReadUInt8(unsigned char &) +lotuswordpro/inc/lwpsvstream.hxx:81 + class LwpSvStream & LwpSvStream::ReadUInt16(unsigned short &) +lotuswordpro/inc/lwpsvstream.hxx:82 + class LwpSvStream & LwpSvStream::ReadUInt32(unsigned int &) +sc/inc/orcusfilters.hxx:44 + _Bool ScOrcusFilters::importODS_Styles(class ScDocument &,class rtl::OUString &) const +sc/inc/scabstdlg.hxx:56 + _Bool ScAsyncTabController::StartExecuteAsync(struct VclAbstractDialog::AsyncContext &) +sc/source/core/opencl/formulagroupcl.cxx:1095 + unsigned long sc::opencl::(anonymous namespace)::DynamicKernelSlidingArgument::GenReductionLoopHeader(class std::basic_stringstream &,_Bool &) +sc/source/core/opencl/formulagroupcl.cxx:1366 + unsigned long sc::opencl::(anonymous namespace)::ParallelReductionVectorRef::GenReductionLoopHeader(class std::basic_stringstream &,int,_Bool &) +sc/source/filter/inc/workbookhelper.hxx:262 + _Bool oox::xls::WorkbookHelper::importOoxFragment(const class rtl::Reference &,class oox::core::FastParser &) +sc/source/filter/xml/XMLStylesExportHelper.hxx:174 + _Bool ScFormatRangeStyles::AddStyleName(const class rtl::OUString &,int &,const _Bool) +sc/source/ui/inc/anyrefdg.hxx:95 + _Bool ScRefHandler::DoClose(unsigned short) +sc/source/ui/inc/docfunc.hxx:113 + _Bool ScDocFunc::SetFormulaCells(const class ScAddress &,class std::vector &,_Bool) +sc/source/ui/inc/docfunc.hxx:161 + _Bool ScDocFunc::Protect(short,const class rtl::OUString &) +sc/source/ui/inc/drawview.hxx:159 + _Bool ScDrawView::calculateGridOffsetForSdrObject(class SdrObject &,class basegfx::B2DVector &) const +sc/source/ui/inc/drawview.hxx:162 + _Bool ScDrawView::calculateGridOffsetForB2DRange(const class basegfx::B2DRange &,class basegfx::B2DVector &) const +sc/source/ui/inc/select.hxx:71 + _Bool ScViewFunctionSet::SetCursorAtCell(short,int,_Bool) +sc/source/ui/vba/vbaformat.hxx:69 + class com::sun::star::uno::Any ScVbaFormat::getAddIndent() +sc/source/ui/vba/vbaformat.hxx:73 + class com::sun::star::uno::Any ScVbaFormat::Borders(const class com::sun::star::uno::Any &) +sc/source/ui/vba/vbaformat.hxx:76 + class com::sun::star::uno::Reference ScVbaFormat::Font() +sc/source/ui/vba/vbaformat.hxx:79 + class com::sun::star::uno::Reference ScVbaFormat::Interior() +sc/source/ui/vba/vbaformat.hxx:85 + class com::sun::star::uno::Any ScVbaFormat::getNumberFormat() +sc/source/ui/vba/vbaformat.hxx:91 + class com::sun::star::uno::Any ScVbaFormat::getNumberFormatLocal() +sc/source/ui/vba/vbaformat.hxx:97 + class com::sun::star::uno::Any ScVbaFormat::getIndentLevel() +sc/source/ui/vba/vbaformat.hxx:103 + class com::sun::star::uno::Any ScVbaFormat::getHorizontalAlignment() +sc/source/ui/vba/vbaformat.hxx:109 + class com::sun::star::uno::Any ScVbaFormat::getVerticalAlignment() +sc/source/ui/vba/vbaformat.hxx:115 + class com::sun::star::uno::Any ScVbaFormat::getOrientation() +sc/source/ui/vba/vbaformat.hxx:121 + class com::sun::star::uno::Any ScVbaFormat::getShrinkToFit() +sc/source/ui/vba/vbaformat.hxx:127 + class com::sun::star::uno::Any ScVbaFormat::getWrapText() +sc/source/ui/vba/vbaformat.hxx:133 + class com::sun::star::uno::Any ScVbaFormat::getLocked() +sc/source/ui/vba/vbaformat.hxx:139 + class com::sun::star::uno::Any ScVbaFormat::getFormulaHidden() +sc/source/ui/vba/vbaformat.hxx:145 + class com::sun::star::uno::Any ScVbaFormat::getMergeCells() +sc/source/ui/vba/vbaformat.hxx:151 + class com::sun::star::uno::Any ScVbaFormat::getReadingOrder() +sd/source/filter/eppt/pptx-epptooxml.cxx:132 + class oox::drawingml::ShapeExport & oox::core::PowerPointShapeExport::WritePageShape(const class com::sun::star::uno::Reference &,enum PageType,_Bool) +sd/source/ui/inc/DrawViewShell.hxx:252 + _Bool sd::DrawViewShell::SelectPage(unsigned short,unsigned short) +sd/source/ui/inc/navigatr.hxx:120 + _Bool SdNavigatorWin::InsertFile(const class rtl::OUString &) +sd/source/ui/inc/OutlineViewShell.hxx:114 + class ErrCode sd::OutlineViewShell::ReadRtf(class SvStream &) +sd/source/ui/remotecontrol/IBluetoothSocket.hxx:36 + int sd::IBluetoothSocket::write(const void *,unsigned int) +sdext/source/pdfimport/tree/style.hxx:155 + int pdfi::StyleContainer::getStandardStyleId(class std::basic_string_view) +sfx2/inc/autoredactdialog.hxx:135 + _Bool SfxAutoRedactDialog::getTargets(class std::vector > &) +slideshow/source/engine/animationnodes/animationbasenode.hxx:62 + _Bool slideshow::internal::AnimationBaseNode::enqueueActivity() const +sw/inc/calc.hxx:122 + class SwSbxValue & SwSbxValue::MakeDouble() +sw/inc/docary.hxx:265 + _Bool SwRedlineTable::isMoved(unsigned long) const +sw/inc/docary.hxx:300 + _Bool SwExtraRedlineTable::DeleteAllTableRedlines(class SwDoc &,const class SwTable &,_Bool,enum RedlineType) +sw/inc/docary.hxx:301 + _Bool SwExtraRedlineTable::DeleteTableRowRedline(class SwDoc *,const class SwTableLine &,_Bool,enum RedlineType) +sw/inc/docary.hxx:302 + _Bool SwExtraRedlineTable::DeleteTableCellRedline(class SwDoc *,const class SwTableBox &,_Bool,enum RedlineType) +sw/inc/editsh.hxx:634 + const class GraphicAttr * SwEditShell::GetGraphicAttr(class GraphicAttr &) const +sw/inc/IDocumentUndoRedo.hxx:100 + _Bool IDocumentUndoRedo::Undo() +sw/inc/IDocumentUndoRedo.hxx:181 + _Bool IDocumentUndoRedo::Repeat(class sw::RepeatContext &,const unsigned short) +sw/inc/tblafmt.hxx:269 + _Bool SwTableAutoFormatTable::Load(class SvStream &) +sw/source/core/inc/laycache.hxx:64 + _Bool SwLayoutCache::CompareLayout(const class SwDoc &) const +sw/source/core/inc/scriptinfo.hxx:237 + _Bool SwScriptInfo::GetBoundsOfHiddenRange(struct o3tl::strong_int,struct o3tl::strong_int &,struct o3tl::strong_int &) const +sw/source/filter/ww8/ww8toolbar.hxx:337 + _Bool Tcg::ImportCustomToolBar(class SfxObjectShell &) +sw/source/uibase/inc/drawbase.hxx:54 + _Bool SwDrawBase::MouseMove(const class MouseEvent &) +sw/source/uibase/inc/fldmgr.hxx:116 + const class com::sun::star::uno::Reference & SwFieldMgr::GetNumberingInfo() const +sw/source/uibase/inc/mailmergewizard.hxx:79 + _Bool SwMailMergeWizard::skipUntil(unsigned short) +sw/source/uibase/inc/numpara.hxx:61 + _Bool SwParagraphNumTabPage::ExecuteEditNumStyle_Impl(unsigned short,const class rtl::OUString &,enum SfxStyleFamily) +ucb/source/ucp/webdav-curl/ContentProperties.hxx:159 + _Bool http_dav_ucp::CachableContentProperties::containsAllNames(const class com::sun::star::uno::Sequence &,class std::vector &) const +vcl/inc/font/FeatureCollector.hxx:45 + _Bool vcl::font::FeatureCollector::collect() +vcl/inc/impgraph.hxx:186 + _Bool ImpGraphic::swapOutGraphic(class SvStream &) +vcl/inc/pdf/pdfwriter_impl.hxx:1253 + _Bool vcl::PDFWriterImpl::setCurrentStructureElement(int) +vcl/inc/pdf/pdfwriter_impl.hxx:1254 + _Bool vcl::PDFWriterImpl::setStructureAttribute(enum vcl::PDFWriter::StructAttribute,enum vcl::PDFWriter::StructAttributeValue) +vcl/inc/pdf/pdfwriter_impl.hxx:1255 + _Bool vcl::PDFWriterImpl::setStructureAttributeNumerical(enum vcl::PDFWriter::StructAttribute,int) +vcl/inc/qt5/QtAccessibleWidget.hxx:48 + class QString QtAccessibleWidget::tr(const char *,const char *,int) +vcl/inc/qt5/QtAccessibleWidget.hxx:48 + class QString QtAccessibleWidget::trUtf8(const char *,const char *,int) +vcl/inc/qt5/QtClipboard.hxx:36 + class QString QtClipboard::tr(const char *,const char *,int) +vcl/inc/qt5/QtClipboard.hxx:36 + class QString QtClipboard::trUtf8(const char *,const char *,int) +vcl/inc/qt5/QtFilePicker.hxx:60 + class QString QtFilePicker::tr(const char *,const char *,int) +vcl/inc/qt5/QtFilePicker.hxx:60 + class QString QtFilePicker::trUtf8(const char *,const char *,int) +vcl/inc/qt5/QtFrame.hxx:69 + class QString QtFrame::tr(const char *,const char *,int) +vcl/inc/qt5/QtFrame.hxx:69 + class QString QtFrame::trUtf8(const char *,const char *,int) +vcl/inc/qt5/QtInstance.hxx:54 + class QString QtInstance::tr(const char *,const char *,int) +vcl/inc/qt5/QtInstance.hxx:54 + class QString QtInstance::trUtf8(const char *,const char *,int) +vcl/inc/qt5/QtMainWindow.hxx:29 + class QString QtMainWindow::tr(const char *,const char *,int) +vcl/inc/qt5/QtMainWindow.hxx:29 + class QString QtMainWindow::trUtf8(const char *,const char *,int) +vcl/inc/qt5/QtMenu.hxx:40 + class QString QtMenu::tr(const char *,const char *,int) +vcl/inc/qt5/QtMenu.hxx:40 + class QString QtMenu::trUtf8(const char *,const char *,int) +vcl/inc/qt5/QtObject.hxx:34 + class QString QtObject::tr(const char *,const char *,int) +vcl/inc/qt5/QtObject.hxx:34 + class QString QtObject::trUtf8(const char *,const char *,int) +vcl/inc/qt5/QtTimer.hxx:27 + class QString QtTimer::tr(const char *,const char *,int) +vcl/inc/qt5/QtTimer.hxx:27 + class QString QtTimer::trUtf8(const char *,const char *,int) +vcl/inc/qt5/QtWidget.hxx:35 + class QString QtWidget::tr(const char *,const char *,int) +vcl/inc/qt5/QtWidget.hxx:35 + class QString QtWidget::trUtf8(const char *,const char *,int) +vcl/inc/qt5/QtXAccessible.hxx:27 + class QString QtXAccessible::tr(const char *,const char *,int) +vcl/inc/qt5/QtXAccessible.hxx:27 + class QString QtXAccessible::trUtf8(const char *,const char *,int) +vcl/inc/salgdi.hxx:404 + _Bool SalGraphics::UpdateSettings(class AllSettings &) +vcl/inc/salgdi.hxx:406 + _Bool SalGraphics::BlendBitmap(const struct SalTwoRect &,const class SalBitmap &,const class OutputDevice &) +vcl/inc/salgdi.hxx:515 + _Bool SalGraphics::implDrawGradient(const class basegfx::B2DPolyPolygon &,const struct SalGradient &) +vcl/inc/salinst.hxx:176 + _Bool SalInstance::CallEventCallback(const void *,int) +vcl/inc/salprn.hxx:113 + _Bool SalPrinter::EndJob() +vcl/inc/salvtables.hxx:1603 + _Bool SalInstanceTreeView::get_iter_abs_pos(class weld::TreeIter &,int) const +vcl/inc/unx/gtk/gtkdata.hxx:335 + int GtkSalDisplay::CaptureMouse(class SalFrame *) +vcl/inc/unx/salframe.h:167 + _Bool X11SalFrame::Dispatch(union _XEvent *) +vcl/unx/kf5/KF5FilePicker.hxx:29 + class QString KF5FilePicker::tr(const char *,const char *,int) +vcl/unx/kf5/KF5FilePicker.hxx:29 + class QString KF5FilePicker::trUtf8(const char *,const char *,int) diff --git a/compilerplugins/clang/unusedmethodsremove.cxx b/compilerplugins/clang/unusedmethodsremove.cxx new file mode 100644 index 000000000..ff87c6b77 --- /dev/null +++ b/compilerplugins/clang/unusedmethodsremove.cxx @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if !defined _WIN32 //TODO, #include + +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" +#include +#include +#include +#include +#include +#include +#include + +/** + This is intended to be run as the second stage of the "unusedmethods" clang plugin. +*/ + +namespace { + +class UnusedMethodsRemove: + public loplugin::FilteringRewritePlugin +{ +public: + explicit UnusedMethodsRemove(loplugin::InstantiationData const & data); + ~UnusedMethodsRemove(); + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCXXMethodDecl( const CXXMethodDecl* var ); +private: + // I use a brute-force approach - mmap the results file and do a linear search on it + // It works surprisingly well, because the file is small enough to fit into L2 cache on modern CPU's + size_t mmapFilesize; + int mmapFD; + char* mmappedData; +}; + +size_t getFilesize(const char* filename) +{ + struct stat st; + stat(filename, &st); + return st.st_size; +} + +UnusedMethodsRemove::UnusedMethodsRemove(loplugin::InstantiationData const & data): FilteringRewritePlugin(data) +{ + static const char sInputFile[] = SRCDIR "/result.txt"; + mmapFilesize = getFilesize(sInputFile); + //Open file + mmapFD = open(sInputFile, O_RDONLY, 0); + assert(mmapFD != -1); + //Execute mmap + mmappedData = static_cast(mmap(NULL, mmapFilesize, PROT_READ, MAP_PRIVATE, mmapFD, 0)); + assert(mmappedData != NULL); +} + +UnusedMethodsRemove::~UnusedMethodsRemove() +{ + //Cleanup + int rc = munmap(mmappedData, mmapFilesize); + assert(rc == 0); + (void)rc; + close(mmapFD); +} + +std::string niceName(const CXXMethodDecl* functionDecl) +{ + std::string s = + functionDecl->getReturnType().getCanonicalType().getAsString() + + " " + functionDecl->getParent()->getQualifiedNameAsString() + + "::" + functionDecl->getNameAsString() + + "("; + bool bFirst = true; + for (const ParmVarDecl *pParmVarDecl : functionDecl->parameters()) { + if (bFirst) + bFirst = false; + else + s += ","; + s += pParmVarDecl->getType().getCanonicalType().getAsString(); + } + s += ")"; + if (functionDecl->isConst()) { + s += " const"; + } + return s; +} + +bool UnusedMethodsRemove::VisitCXXMethodDecl( const CXXMethodDecl* functionDecl ) +{ + if (rewriter == nullptr) { + return true; + } + if (ignoreLocation(functionDecl)) { + return true; + } + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(functionDecl)) { + return true; + } + + // don't mess with templates + if (functionDecl->getParent()->getDescribedClassTemplate() != nullptr) { + return true; + } + if (functionDecl->getTemplatedKind() != FunctionDecl::TK_NonTemplate) { + return true; + } + + std::string aNiceName = "\n" + niceName(functionDecl) + "\n"; + const char *aNiceNameStr = aNiceName.c_str(); + char* found = std::search(mmappedData, mmappedData + mmapFilesize, aNiceNameStr, aNiceNameStr + strlen(aNiceNameStr)); + if(!(found < mmappedData + mmapFilesize)) { + return true; + } + SourceRange replaceRange(functionDecl->getSourceRange()); + // sometimes the declaration has a semicolon just after it, and it's much neater to remove that too. + if (rewriter->getRewrittenText(SourceRange(replaceRange.getEnd(), replaceRange.getEnd().getLocWithOffset(1))) == ";") { + replaceRange.setEnd(replaceRange.getEnd().getLocWithOffset(1)); + } + // remove leading spaces + while (rewriter->getRewrittenText(SourceRange(replaceRange.getBegin().getLocWithOffset(-1), replaceRange.getBegin())) == " ") + { + replaceRange.setBegin(replaceRange.getBegin().getLocWithOffset(-1)); + } + if (!replaceText(replaceRange, "")) { + report( + DiagnosticsEngine::Warning, + "Could not remove unused method (" + niceName(functionDecl) + ")", + functionDecl->getBeginLoc()) + << functionDecl->getSourceRange(); + } + return true; +} + + +loplugin::Plugin::Registration< UnusedMethodsRemove > X("unusedmethodsremove", false); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unusedvariablecheck.cxx b/compilerplugins/clang/unusedvariablecheck.cxx new file mode 100644 index 000000000..f15521994 --- /dev/null +++ b/compilerplugins/clang/unusedvariablecheck.cxx @@ -0,0 +1,125 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include + +#include "compat.hxx" +#include "check.hxx" +#include "unusedvariablecheck.hxx" +#include "plugin.hxx" + +namespace loplugin +{ + +/* +This is a compile check. + +Check for unused classes where the compiler cannot decide (e.g. because of +non-trivial or extern ctors) if a variable is unused if only its ctor/dtor +are called and nothing else. For example std::vector is a class where +the ctor may call further functions, but an unused std::string variable +does nothing. On the other hand, std::scoped_lock instances are used +for their dtors and so are not unused even if not otherwise accessed. + +Classes which are safe to be warned about need to be marked using +SAL_WARN_UNUSED (see e.g. OUString). For external classes such as std::vector +that cannot be edited there is a manual list below. +*/ + +UnusedVariableCheck::UnusedVariableCheck( const InstantiationData& data ) + : FilteringPlugin( data ) + { + } + +void UnusedVariableCheck::run() + { + TraverseDecl( compiler.getASTContext().getTranslationUnitDecl()); + } + +bool UnusedVariableCheck::VisitVarDecl( const VarDecl* var ) + { + if( ignoreLocation( var )) + return true; + if( var->isReferenced() || var->isUsed()) + return true; + if( var->isDefinedOutsideFunctionOrMethod()) + return true; + + auto type = var->getType(); + bool check = loplugin::isExtraWarnUnusedType(type); + + if (!check) + check = isUnusedSmartPointer(var); + + + // this chunk of logic generates false+, which is why we don't leave it on +/* + if (!check && type->isRecordType()) + { + auto recordDecl + = dyn_cast_or_null(type->getAs()->getDecl()); + if (recordDecl && recordDecl->hasDefinition() && recordDecl->hasTrivialDestructor()) + check = true; + } +*/ + if(check) + { + if( const ParmVarDecl* param = dyn_cast< ParmVarDecl >( var )) + { + if( !param->getDeclName()) + return true; // unnamed parameter -> unused + // If this declaration does not have a body, then the parameter is indeed not used, + // so ignore. + auto const parent = param->getParentFunctionOrMethod(); + if( const FunctionDecl* func = dyn_cast_or_null< FunctionDecl >( parent)) + if( !func->doesThisDeclarationHaveABody() || func->getBody() == nullptr) + return true; + if (auto const d = dyn_cast_or_null(parent)) { + if (!d->hasBody()) { + return true; + } + } + report( DiagnosticsEngine::Warning, "unused parameter %0", + var->getLocation()) << var->getDeclName(); + } + else + report( DiagnosticsEngine::Warning, "unused variable %0", + var->getLocation()) << var->getDeclName(); + } + return true; + } + +bool UnusedVariableCheck::isUnusedSmartPointer( const VarDecl* var ) + { + // if we have a var of smart-pointer type, and that var is both uninitialised and + // not referenced, then we can remove it + if (!isSmartPointerType(var->getType())) + return false; + + if (!var->hasInit()) + return true; + + auto cxxConstructExpr = dyn_cast(var->getInit()); + if (!cxxConstructExpr) + return false; + return + cxxConstructExpr->getNumArgs() == 0 || cxxConstructExpr->getArg(0)->isDefaultArgument(); + } + +static Plugin::Registration< UnusedVariableCheck > unusedvariablecheck( "unusedvariablecheck" ); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unusedvariablecheck.hxx b/compilerplugins/clang/unusedvariablecheck.hxx new file mode 100644 index 000000000..5f5edbbba --- /dev/null +++ b/compilerplugins/clang/unusedvariablecheck.hxx @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#pragma once + +#include "plugin.hxx" + +namespace loplugin +{ + +class UnusedVariableCheck + : public FilteringPlugin< UnusedVariableCheck > + { + public: + explicit UnusedVariableCheck( const InstantiationData& data ); + virtual void run() override; + bool VisitVarDecl( const VarDecl* var ); + private: + bool isUnusedSmartPointer( const VarDecl* var ); + }; + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unusedvariablemore.cxx b/compilerplugins/clang/unusedvariablemore.cxx new file mode 100644 index 000000000..908edf33a --- /dev/null +++ b/compilerplugins/clang/unusedvariablemore.cxx @@ -0,0 +1,337 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "config_clang.h" +#include +#include "plugin.hxx" +#include "compat.hxx" +#include "check.hxx" +#include +#include + +#include "clang/AST/ParentMapContext.h" + +namespace loplugin +{ +/* + This is a compile check. The results of this plugin need to be checked by hand, since it is a collection of heuristics. + + Check for unused variable where + (*) we never call methods that return information from the variable. + (*) we never pass the variable to anything else + + Classes which are safe to be warned about need to be marked using + SAL_WARN_UNUSED (see e.g. OUString). For external classes such as std::vector + that cannot be edited there is a manual list. + + This is an expensive plugin, since it walks up the parent tree, + so it is off by default. +*/ + +class UnusedVariableMore : public loplugin::FilteringPlugin +{ +public: + explicit UnusedVariableMore(const InstantiationData& data); + virtual void run() override; + bool VisitVarDecl(VarDecl const*); + bool VisitDeclRefExpr(DeclRefExpr const*); + bool VisitFunctionDecl(FunctionDecl const*); + +private: + bool checkifUnused(Stmt const*, VarDecl const*); + bool isOkForParameter(const QualType&); + + std::unordered_set interestingSet; + // used to dump the last place that said the usage was unused, for debug purposes + std::unordered_map interestingDebugMap; +}; + +UnusedVariableMore::UnusedVariableMore(const InstantiationData& data) + : FilteringPlugin(data) +{ +} + +void UnusedVariableMore::run() +{ + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + + // ignore QA folders + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/i18npool/qa/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/qa/")) + return; + + // vector of shared_ptr used to delay destruction + if (fn == SRCDIR "/cppuhelper/source/servicemanager.cxx") + return; + if (fn == SRCDIR "/i18nlangtag/source/languagetag/languagetag.cxx") + return; + // unordered_set of Reference to delay destruction + if (fn == SRCDIR "/stoc/source/servicemanager/servicemanager.cxx") + return; + // TODO "operator >>" fooling me here + if (fn == SRCDIR "/editeng/source/accessibility/AccessibleEditableTextPara.cxx") + return; + // some weird stuff + if (fn == SRCDIR "/sfx2/source/dialog/dinfdlg.cxx") + return; + // std::vector< Reference< XInterface > > keep alive + if (fn == SRCDIR "/dbaccess/source/core/dataaccess/databasedocument.cxx") + return; + // template magic + if (fn == SRCDIR "/sc/source/core/tool/scmatrix.cxx") + return; + // storing local copy of Link<> + if (fn == SRCDIR "/sc/source/ui/miscdlgs/simpref.cxx") + return; + // Using an SwPaM to do stuff + if (fn == SRCDIR "/sw/source/core/crsr/bookmark.cxx") + return; + // index variable in for loop? + if (fn == SRCDIR "/sw/source/uibase/docvw/edtwin.cxx") + return; + // TODO "operator >>" fooling me here + if (fn == SRCDIR "/sw/source/filter/ww8/ww8par.cxx") + return; + // TODO "operator >>" fooling me here + if (fn == SRCDIR "/sc/source/filter/excel/xistream.cxx") + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + for (VarDecl const* varDecl : interestingSet) + { + report(DiagnosticsEngine::Warning, "unused variable %0", varDecl->getLocation()) + << varDecl->getDeclName(); + //auto it = interestingDebugMap.find(varDecl); + //if (it != interestingDebugMap.end()) + // it->second->dump(); + } +} + +bool isWarnUnusedType(QualType type) +{ + if (auto const t = type->getAs()) + { + if (t->getDecl()->hasAttr()) + { + return true; + } + } + if (auto const t = type->getAs()) + { + if (t->getDecl()->hasAttr()) + { + return true; + } + } + return loplugin::isExtraWarnUnusedType(type); +} + +bool UnusedVariableMore::VisitVarDecl(VarDecl const* var) +{ + if (ignoreLocation(var)) + return true; + if (var->isDefinedOutsideFunctionOrMethod()) + return true; + if (isa(var)) + return true; + if (!isWarnUnusedType(var->getType())) + return true; + + // some false + + auto dc = loplugin::TypeCheck(var->getType()); + if (dc.Class("ZCodec").GlobalNamespace()) + return true; + if (dc.Class("ScopedVclPtrInstance").GlobalNamespace()) + return true; + if (dc.Class("VclPtrInstance").GlobalNamespace()) + return true; + if (dc.Class("Config").GlobalNamespace()) + return true; + // I think these classes modify global state somehow + if (dc.Class("SvtHistoryOptions").GlobalNamespace()) + return true; + if (dc.Class("SvtSecurityOptions").GlobalNamespace()) + return true; + if (dc.Class("SvtViewOptions").GlobalNamespace()) + return true; + if (dc.Class("SvtUserOptions").GlobalNamespace()) + return true; + if (dc.Class("SvtMenuOptions").GlobalNamespace()) + return true; + if (dc.Class("SvtPathOptions").GlobalNamespace()) + return true; + if (dc.Class("SvtSysLocaleOptions").GlobalNamespace()) + return true; + + interestingSet.insert(var); + return true; +} + +bool UnusedVariableMore::VisitDeclRefExpr(DeclRefExpr const* declRefExpr) +{ + if (ignoreLocation(declRefExpr)) + return true; + auto varDecl = dyn_cast(declRefExpr->getDecl()); + if (!varDecl) + return true; + if (interestingSet.find(varDecl) == interestingSet.end()) + return true; + if (!checkifUnused(declRefExpr, varDecl)) + interestingSet.erase(varDecl); + return true; +} + +// Walk up from a statement that contains a DeclRefExpr, checking if the usage means that the +// related VarDecl is unused. +bool UnusedVariableMore::checkifUnused(Stmt const* stmt, VarDecl const* varDecl) +{ + const Stmt* parent = getParentStmt(stmt); + if (!parent) + { + // check if we're inside a CXXCtorInitializer + auto parentsRange = compiler.getASTContext().getParents(*stmt); + if (parentsRange.begin() != parentsRange.end()) + { + auto parentDecl = parentsRange.begin()->get(); + if (parentDecl && (isa(parentDecl) || isa(parentDecl))) + return false; + } + interestingDebugMap[varDecl] = stmt; + return true; + } + + if (isa(parent)) + return false; + if (isa(parent)) + return false; + if (isa(parent)) + return false; + if (isa(parent)) + return false; + if (isa(parent)) + return false; + if (isa(parent)) + return false; + if (isa(parent)) + return false; + if (isa(parent)) + return false; + if (isa(parent)) + return false; + if (isa(parent)) + return checkifUnused(parent, varDecl); + if (isa(parent)) + return checkifUnused(parent, varDecl); + + if (isa(parent)) + { + interestingDebugMap[varDecl] = parent; + return true; + } + + // check for cast to void + if (auto explicitCastExpr = dyn_cast(parent)) + { + if (loplugin::TypeCheck(explicitCastExpr->getTypeAsWritten()).Void()) + return false; + } + + if (isa(parent)) + return checkifUnused(parent, varDecl); + if (isa(parent)) + return checkifUnused(parent, varDecl); + if (isa(parent)) + return checkifUnused(parent, varDecl); + if (isa(parent)) + return checkifUnused(parent, varDecl); + + if (auto operatorCallExpr = dyn_cast(parent)) + { + const CXXMethodDecl* calleeMethodDecl + = dyn_cast_or_null(operatorCallExpr->getDirectCallee()); + if (calleeMethodDecl) + { + if (calleeMethodDecl->getNumParams() == 0) + return checkifUnused(parent, varDecl); + if (operatorCallExpr->getArg(0) == stmt) + return checkifUnused(parent, varDecl); + } + } + if (auto memberCallExpr = dyn_cast(parent)) + { + const MemberExpr* memberExpr = dyn_cast(stmt); + if (memberExpr && memberCallExpr->getImplicitObjectArgument() == memberExpr->getBase()) + { + // if we are calling a method on the varDecl, walk up + if (!checkifUnused(parent, varDecl)) + return false; + // check if we are passing something to the var by non-const ref, in which case it is updating something else for us + const FunctionDecl* calleeFunctionDecl = memberCallExpr->getDirectCallee(); + if (calleeFunctionDecl) + { + if (calleeFunctionDecl->isVariadic()) + return false; + for (unsigned i = 0; i < memberCallExpr->getNumArgs(); ++i) + { + if (i >= calleeFunctionDecl->getNumParams()) // can happen in template code + { + interestingDebugMap[varDecl] = parent; + return true; + } + if (!isOkForParameter(calleeFunctionDecl->getParamDecl(i)->getType())) + return false; + } + } + interestingDebugMap[varDecl] = parent; + return true; + } + } + if (isa(parent)) + return false; + + interestingDebugMap[varDecl] = parent; + return true; +} + +bool UnusedVariableMore::isOkForParameter(const QualType& qt) +{ + if (qt->isIntegralOrEnumerationType()) + return true; + auto const type = loplugin::TypeCheck(qt); + if (type.Pointer()) + { + return bool(type.Pointer().Const()); + } + else if (type.LvalueReference()) + { + return bool(type.LvalueReference().Const()); + } + return false; +} + +bool UnusedVariableMore::VisitFunctionDecl(FunctionDecl const* functionDecl) +{ + if (ignoreLocation(functionDecl)) + return true; + //functionDecl->dump(); + return true; +} + +static Plugin::Registration X("unusedvariablemore", false); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unusedvariableplus.cxx b/compilerplugins/clang/unusedvariableplus.cxx new file mode 100644 index 000000000..e8a8385bb --- /dev/null +++ b/compilerplugins/clang/unusedvariableplus.cxx @@ -0,0 +1,519 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" +#include "config_clang.h" +#include + +/* + * Very aggressive unused variable checker, we allowlist types that are known + * good when unused. +*/ + +namespace +{ +static bool startswith(const std::string& rStr, const char* pSubStr) +{ + return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; +} + +class UnusedVariablePlus : public loplugin::FilteringPlugin +{ +public: + explicit UnusedVariablePlus(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual bool preRun() override + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/canvas/workben/")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/uipreviewer/previewer.cxx")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/workben/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/qa/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/backendtest/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/lotuswordpro/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/salhelper/qa/")) + return false; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/idl/source/prj/svidl.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sot/source/unoolestorage/xolesimplestorage.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/core/tool/interpr7.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/vba/vbaapplication.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/doc/doccomp.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/swg/SwXMLTextBlocks.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/ww8/wrtw8esh.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR + "/shell/source/sessioninstall/SyncDbusSessionHelper.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/svl/qa/unit/items/test_IndexedStyleSheets.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/qa/unit/export-tests-ooxml2.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/qa/unit/subsequent_export-test.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/skia/SkiaHelper.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/dialog/dlgctrl.cxx")) + return false; + + // clang has a bug here, with vars in destructing assignments + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/binaryurp/")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/excel/xestring.cxx")) + return false; + return true; + } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitVarDecl(const VarDecl* var) + { + if (ignoreLocation(var)) + return true; + if (var->isReferenced() || var->isUsed()) + return true; + if (var->isDefinedOutsideFunctionOrMethod()) + return true; + if (var->isExceptionVariable()) // not interesting + return true; + if (isa(var)) + return true; + + auto type = var->getType().getCanonicalType().getUnqualifiedType(); + auto typeName = type.getAsString(); + if (typeName.compare(0, 7, "struct ") == 0) + typeName = typeName.substr(7); + if (typeName.compare(0, 6, "class ") == 0) + typeName = typeName.substr(6); + if (typeName.compare(0, 2, "::") == 0) + typeName = typeName.substr(2); + if (typeName.compare(0, 23, "(anonymous namespace)::") == 0) + typeName = typeName.substr(23); + static std::unordered_set ignoreClassNamesSet{ + "apphelper::NegativeGuard", + "avmedia::gstreamer::(anonymous namespace)::FlagGuard", + "BoolEnv_Impl", + "BoolResetter", + "boost::io::basic_ios_all_saver >", + "BorderLinesGuard", + "BorderTest", + "BroadcastRecalcOnRefMoveGuard", + "CacheLockGuard", + "cc_reset", + "chart::ControllerLockGuard", + "chart::ControllerLockGuardUNO", + "chart::HiddenUndoContext", + "chart::sidebar::(anonymous namespace)::PreventUpdate", + "chart::TimerTriggeredControllerLock", + "chart::TrueGuard", + "ClearableClipRegion", + "osl::ClearableGuard", + "rptui::ColorChanger", + "SortRefUpdateSetter", + "SortRefNoUpdateSetter", + "com::sun::star::uno::ContextLayer", + "comphelper::FlagGuard", + "comphelper::FlagRestorationGuard", + "comphelper::ValueRestorationGuard<_Bool>", + "comphelper::(anonymous namespace)::ProfileZone", + "comphelper::ProfileZone", + "comphelper::ORelease", + "comphelper::OStreamSection", + "ConfigurationController::Lock", + "SortTypeSetter", + "SkiaZone", + "MockMetadatable", + "connectivity::(anonymous namespace)::ForbidQueryName", + "connectivity::calc::OCalcConnection::ODocHolder", + "connectivity::writer::OWriterConnection::ODocHolder", + "connectivity::jdbc::ContextClassLoaderScope", + "CurrShell", + "dbaccess::ModifyLock", + "dbaccess::NameChangeNotifier", + "dbaccess::OFilteredContainer::EnsureReset", + "dbaccess::OQuery::OAutoActionReset", + "dbaccess::OQueryContainer::OAutoActionReset", + "dbaccess::(anonymous namespace)::LayoutManagerLock", + "dbaccess::(anonymous namespace)::LockModifiable", + "dbaccess::(anonymous namespace)::OExecuteImpl", + "dbaccess::(anonymous namespace)::PreserveVisualAreaSize", + "dbaccess::(anonymous namespace)::ProtectFlag", + "dbaui::BrowserViewStatusDisplay", + "dbaui::SbaXDataBrowserController::FormErrorHelper", + "dbaui::(anonymous namespace)::SelectionGuard", + "dbaxml::(anonymous namespace)::FocusWindowWaitGuard", + "DBG_Model", + "DeactivateUpdateMode", + "DepthProtect", + "desktop::Desktop", + "desktop::(anonymous namespace)::ConditionSetGuard", + "desktop::(anonymous namespace)::RefClearGuard " + ">", + "DetachCurrentThread", + "DialogReleaseGuard", + "DisableCallbackAction", + "DisableCallbacks", + "DisableGetPivotData", + "DispatchMutexLock_Impl", + "DisplayLockGuard", + "DocTemplLocker_Impl", + "DocumentSettingsGuard", + "DocxTableExportContext", + "dp_misc::AbortChannel::Chain", + "dp_misc::ProgressLevel", + "E3DModifySceneSnapRectUpdater", + "E3dObjFactory", + "ErrorHdlResetter", + "EscherExAtom", + "EscherExContainer", + "ExportDataSaveRestore", + "ExtensionRemoveGuard", + "frm::(anonymous namespace)::FieldChangeNotifier", + "frm::(anonymous namespace)::DocumentModifyGuard", + "FieldDeletionModify", + "FieldDeletionListener", + "FileHandle_Impl::Guard", + "FlowFrameJoinLockGuard", + "FmXFormShell::SuspendPropertyTracking", + "FocusWindowWaitCursor", + "formula::(anonymous namespace)::OpCodeList", + "formula::(anonymous namespace)::FormulaCompilerRecursionGuard", + "FontCacheGuard", + "FontLockGuard", + "FormatLevel", + "FormulaGrammarSwitch", + "framework::DocumentUndoGuard", + "framework::ShareGuard", + "framework::TransactionGuard", + "framework::(anonymous namespace)::QuickstartSuppressor", + "GalApp", + "GalleryProgress", + "GlibThreadDefaultMainContextScope", + "Guard", + "HandleResetAttrAtTextNode", + "HandleSetAttrAtTextNode", + "HelpParser", + "HtmlExport", + "HTMLSaveData", + "http_dav_ucp::CurlUri", + "IMapCompat", + "jni_uno::JLocalAutoRef", + "LoadMediumGuard", + "LockGuard", + "MacroInterpretIncrementer", + "MakeAllOutlineContentTemporarilyVisible", + "MailMergeExecuteFinalizer", + "ModifyBlocker_Impl", + "MutexRelease", + "MutexType", + "NewTextListsHelper", + "OAutoRegistration", + "rptui::GeometryHandler::OBlocker", + "rptui::OXReportControllerObserver::OEnvLock", + "oglcanvas::TransformationPreserver", + "io_acceptor::(anonymous namespace)::BeingInAccept", + "desktop::LibLibreOffice_Impl", + "ToolbarUnoDispatcher", + "ooo::vba::excel::(anonymous namespace)::PasteCellsWarningReseter", + "oox::drawingml::(anonymous namespace)::ActionLockGuard", + "oox::dump::IndentGuard", + "oox::dump::ItemGuard", + "oox::dump::MultiItemsGuard", + "oox::dump::TableGuard", + "OpenCLInitialZone", + "OpenCLZone", + "OpenGLVCLContextZone", + "OpenGLZone", + "osl::MutexGuard", + "rptui::OXUndoEnvironment::OUndoMode", + "rptui::OXUndoEnvironment::OUndoEnvLock", + "PaMIntoCursorShellRing", + "ParserCleanup", + "pcr::ComposedUIAutoFireGuard", + "PngDestructor", + "writerperfect::(anonymous namespace)::PositionHolder", + "pq_sdbc_driver::DisposeGuard", + "PropertyChangeNotifier", + "ProtectFormulaGroupContext", + "PreventUpdate", + "pyuno::PyThreadAttach", + "pyuno::PyThreadDetach", + "pyuno_loader::(anonymous namespace)::PythonInit", + "RecursionCounter", + "RefGuard", + "icu_65::RegexMatcher", + "RestoreMapMode", + "Runner", + "pyuno::Runtime", + "salhelper::ConditionModifier", + "salhelper::ConditionWaiter", + "SaveRunState", + "SbiExpression", + "sc::AutoCalcSwitch", + "sc::DelayDeletingBroadcasters", + "sc::DelayFormulaGroupingSwitch", + "sc::IdleSwitch", + "sc::UndoSwitch", + "ScBulkBroadcast", + "ScChartLockGuard", + "ScCompiler", + "ScDocument::NumFmtMergeHandler", + "ScDocShellModificator", + "ScDocShell::PrepareSaveGuard", + "ScExternalRefManager::ApiGuard", + "ScFormulaGroupCycleCheckGuard", + "ScFormulaGroupDependencyComputeGuard", + "SchedulerGuard", + "ScMutationDisable", + "ScNoteCaptionCreator", + "ScValidationRegisteredDlg", + "ScopedAntialiasing", + "ScRefreshTimerProtector", + "ScWaitCursorOff", + "ScXMLImport::MutexGuard", + "SdIOCompat", + "sd::slidesorter::controller::FocusManager::FocusHider", + "sd::slidesorter::controller::SlideSorterController::ModelChangeLock", + "sd::slidesorter::controller::PageSelector::BroadcastLock", + "sd::slidesorter::view::SlideSorterView::DrawLock", + "sd::slidesorter::controller::PageSelector::UpdateLock", + "sd::ViewShellManager::Implementation::UpdateLock", + "sd::(anonymous namespace)::LockUI", + "sd::ToolBarManager::UpdateLock", + "sd::ViewShellManager::UpdateLock", + "sd::OutlineViewPageChangesGuard", + "sd::framework::ConfigurationController::Lock", + "sd::slidesorter::controller::VisibleAreaManager::TemporaryDisabler", + "sd::slidesorter::controller::SelectionObserver::Context", + "sd::ToolBarManager::Implementation::UpdateLockImplementation", + "sd::OutlineViewModelChangeGuard", + "sd::slidesorter::controller::(anonymous " + "namespace)::TemporarySlideTrackingDeactivator", + "sd::ModifyGuard", + "sd::OutlineViewModelChangeGuard", + "setFastDocumentHandlerGuard", + "SmMathConfig::CommitLocker", + "SfxErrorContext", + "SfxFilterListener", + "SfxObjectShellLock", + "SfxProgress", + "SfxSaveGuard", + "SfxStack", + "ShellMoveCursor", + "SkAutoCanvasRestore", + "SolarMutexGuard", + "SolarMutexReleaser", + "StackHack", + "std::lock_guard", + "std::scoped_lock", + "std::unique_lock", + "std::unique_lock", + "std::unique_ptr", + "std::unique_ptr", + "std::unique_ptr>", + "std::unique_ptr", + "std::unique_ptr", + "std::unique_ptr", + "std::unique_ptr", + "StreamExceptionsEnabler", + "SvAddressParser_Impl", + "svl::undo::impl::LockGuard", + "svt::table::(anonymous namespace)::SuppressCursor", + "svx::(anonymous namespace)::FontSwitch", + "SvXMLElementExport", + "svxform::(anonymous namespace)::QuitGuard", + "sw::DrawUndoGuard", + "sw::FlyCreationSuppressor", + "sw::GroupUndoGuard", + "sw::UndoGuard", + "sw::(anonymous namespace)::CursorGuard", + "SwActContext", + "SwAutoFormat", + "SwCallLink", + "SwContentNotify", + "SwCursorSaveState", + "SwCSS1OutMode", + "SwDataChanged", + "SwDigitModeModifier", + "SwDrawViewSave", + "SwDropSave", + "SwEnhancedPDFExportHelper", + "SwEnterLeave", + "SwFieldSlot", + "SwFilterOptions", + "SwFntAccess", + "SwFontSave", + "SwFootnoteSave", + "SwFrameDeleteGuard", + "SwModelTestBase::Resetter", + "std::unique_ptr", // ScCompiler::CompileString has nasty semantics + "Resetter", + "SwFrameSwapper", + "SwFlyNotify", + "SwForbidFollowFormat", + "SwHandleAnchorNodeChg", + "SwHookOut", + "SwImplShellAction", + "SwKeepConversionDirectionStateContext", + "SwLayIdle", + "SwLayNotify", + "SwLayoutModeModifier", + "SwMvContext", + "SwNotifyAccAboutInvalidTextSelections", + "SwObjPositioningInProgress", + "SwParaSelection", + "SwPauseThreadStarting", + "SwPosNotify", + "SwRedlineItr", // ??? + "SwRegHistory", + "SwSaveFootnoteHeight", + "SwSaveSetLRUOfst", + "SwStyleBase_Impl::ItemSetOverrider", + "SwSwapIfNotSwapped", + "SwSwapIfSwapped", + "SwTableNumFormatMerge", + "SwTaggedPDFHelper", + "SwTestFormat", + "SwTextCursorSave", + "SwTextSlot", + "SwTrnsfrActionAndUndo", + "SwWait", + "SwXDispatchProviderInterceptor::DispatchMutexLock_Impl", + "TableWait", + "TargetStateControl_Impl", + "TempErrorHandler", + "TemporaryCellGroupMaker", + "TemporaryRedlineUpdater", + "TextFrameLockGuard", + "TimerContext", + "TimerTriggeredControllerLock", + "ToggleSaveToModule", + "toolkit::(anonymous namespace)::ResetFlagOnExit", + "tools::ScopedJsonWriterArray", + "tools::ScopedJsonWriterNode", + "tools::ScopedJsonWriterStruct", + "TravelSuspension", + "TreeUpdateSwitch", + "rptui::UndoContext", + "rptui::UndoSuppressor", + "UndoRedoRedlineGuard", + "UnoActionRemoveContext", + "UnoActionContext", + "UpdateFontsGuard", + "utl::CloseableComponent", + "utl::DisposableComponent", + "ValueCounter_Impl", + "VclListenerLock", + "vclcanvas::tools::OutDevStateKeeper", + "vcl::PaintBufferGuard", + "vcl::RoadmapWizardTravelSuspension", + "vcl::ScopedAntialiasing", + "vcl::WizardTravelSuspension", + "VerbExecutionControllerGuard", + "VersionCompatRead", + "VersionCompatWrite", + "ViewCallback", + "SlideShowImpl::WaitSymbolLock", + "weld::WaitObject", + "writerfilter::ooxml::(anonymous namespace)::StatusIndicatorGuard", + "WriterSpecificAutoFormatBlock", + "xmloff::OOfficeFormsExport", + "xmlscript::(anonymous namespace)::MGuard", + "XMLTextCharStyleNamesElementExport", + }; + if (ignoreClassNamesSet.find(typeName) != ignoreClassNamesSet.end()) + return true; + if (startswith(typeName, "comphelper::ScopeGuard<")) + return true; + if (startswith(typeName, "comphelper::ValueRestorationGuard<")) + return true; + if (startswith(typeName, "osl::Guard<")) + return true; + if (startswith(typeName, "dbaui::OMultiInstanceAutoRegistration<")) + return true; + if (startswith(typeName, "pcr::OAutoRegistration<")) + return true; + + if (var->getIdentifier()) + { + auto name = var->getName(); + if (name == "aBroadcastGuard" || name == "aDeleteRef" || name == "aGuard" + || name == "aGuard2" || name == "aHoldSelf" || name == "aKeepDoc" + || name == "aAutoRegistration" || name == "aLoadContentIfExists" + || name == "aOwnRef" || name == "createImpl" || name == "flyHolder" + || name == "guard" || name == "ensureDelete" || name == "s_xTerminateListener" + || name == "pThis" || name == "pOldViewShell" || name == "self" + || name == "xDocStor" || name == "xDeleteUponLeaving" || name == "xDeleteRef" + || name == "xHoldAlive" || name == "xHolder" || name == "xHoldRefForMethodAlive" + || name == "xLock" || name == "xMutexGuard" || name == "xKeepAlive" + || name == "xKeepContentHolderAlive" || name == "xKeepDocAlive" + || name == "xKeepMeAlive" || name == "xKeepProviderAlive" + || name == "xOperationHold" || name == "xPreventDelete" || name == "xSelf" + || name == "xSelfHold" || name == "xTempHold" || name == "xDisposeAfterNewOne" + || name == "xThis" || name == "xThisPackage" || name == "xTriggerInit" + || name == "xLifeCycle" || name == "xAnotherLifeCycle") + return true; + } + + if (isa(var)) + return true; + + if (typeName.find("Reference") != std::string::npos && var->getInit()) + { + if (auto cxxConstructExpr + = dyn_cast(var->getInit()->IgnoreImplicit())) + if (cxxConstructExpr->getNumArgs() == 2) + if (auto param1 = dyn_cast(cxxConstructExpr->getArg(1))) + if (auto enumDecl = dyn_cast(param1->getDecl())) + if (enumDecl->getName() == "UNO_QUERY_THROW" + || enumDecl->getName() == "UNO_SET_THROW") + return true; + } + + report(DiagnosticsEngine::Warning, "unused variable %0 of type %1", var->getLocation()) + << var->getDeclName() << typeName; + + return true; + } +}; + +loplugin::Plugin::Registration unusedvariableplus("unusedvariableplus", false); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unusedvarsglobal.cxx b/compilerplugins/clang/unusedvarsglobal.cxx new file mode 100644 index 000000000..50ac67d40 --- /dev/null +++ b/compilerplugins/clang/unusedvarsglobal.cxx @@ -0,0 +1,959 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if !defined _WIN32 //TODO, #include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config_clang.h" + +#include "plugin.hxx" +#include "compat.hxx" +#include "check.hxx" + +#include "clang/AST/ParentMapContext.h" + +/** +This performs two analyses: + (1) look for unused global vars + (2) look for global vars that are write-only +*/ + +namespace +{ +struct MyVarInfo +{ + const VarDecl* varDecl; + std::string fieldName; + std::string fieldType; + std::string sourceLocation; +}; +bool operator<(const MyVarInfo& lhs, const MyVarInfo& rhs) +{ + return std::tie(lhs.sourceLocation, lhs.fieldName) + < std::tie(rhs.sourceLocation, rhs.fieldName); +} + +// try to limit the voluminous output a little +static std::set readFromSet; +static std::set writeToSet; +static std::set definitionSet; + +/** + * Wrap the different kinds of callable and callee objects in the clang AST so I can define methods that handle everything. + */ +class CallerWrapper +{ + const CallExpr* m_callExpr; + const CXXConstructExpr* m_cxxConstructExpr; + +public: + CallerWrapper(const CallExpr* callExpr) + : m_callExpr(callExpr) + , m_cxxConstructExpr(nullptr) + { + } + CallerWrapper(const CXXConstructExpr* cxxConstructExpr) + : m_callExpr(nullptr) + , m_cxxConstructExpr(cxxConstructExpr) + { + } + unsigned getNumArgs() const + { + return m_callExpr ? m_callExpr->getNumArgs() : m_cxxConstructExpr->getNumArgs(); + } + const Expr* getArg(unsigned i) const + { + return m_callExpr ? m_callExpr->getArg(i) : m_cxxConstructExpr->getArg(i); + } +}; +class CalleeWrapper +{ + const FunctionDecl* m_calleeFunctionDecl = nullptr; + const CXXConstructorDecl* m_cxxConstructorDecl = nullptr; + const FunctionProtoType* m_functionPrototype = nullptr; + +public: + explicit CalleeWrapper(const FunctionDecl* calleeFunctionDecl) + : m_calleeFunctionDecl(calleeFunctionDecl) + { + } + explicit CalleeWrapper(const CXXConstructExpr* cxxConstructExpr) + : m_cxxConstructorDecl(cxxConstructExpr->getConstructor()) + { + } + explicit CalleeWrapper(const FunctionProtoType* functionPrototype) + : m_functionPrototype(functionPrototype) + { + } + unsigned getNumParams() const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getNumParams(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getNumParams(); + else if (m_functionPrototype->param_type_begin() == m_functionPrototype->param_type_end()) + // FunctionProtoType will assert if we call getParamTypes() and it has no params + return 0; + else + return m_functionPrototype->getParamTypes().size(); + } + const QualType getParamType(unsigned i) const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getParamDecl(i)->getType(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getParamDecl(i)->getType(); + else + return m_functionPrototype->getParamTypes()[i]; + } + std::string getNameAsString() const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getNameAsString(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getNameAsString(); + else + return ""; + } + CXXMethodDecl const* getAsCXXMethodDecl() const + { + if (m_calleeFunctionDecl) + return dyn_cast(m_calleeFunctionDecl); + return nullptr; + } +}; + +class UnusedVarsGlobal : public loplugin::FilteringPlugin +{ +public: + explicit UnusedVarsGlobal(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override; + + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitVarDecl(const VarDecl*); + bool VisitDeclRefExpr(const DeclRefExpr*); + bool TraverseCXXMethodDecl(CXXMethodDecl*); + bool TraverseFunctionDecl(FunctionDecl*); + bool TraverseIfStmt(IfStmt*); + +private: + MyVarInfo niceName(const VarDecl*); + void checkIfReadFrom(const VarDecl* fieldDecl, const DeclRefExpr* declRefExpr); + void checkIfWrittenTo(const VarDecl* fieldDecl, const DeclRefExpr* declRefExpr); + bool isSomeKindOfZero(const Expr* arg); + bool checkForWriteWhenUsingCollectionType(const CXXMethodDecl* calleeMethodDecl); + bool IsPassedByNonConst(const VarDecl* fieldDecl, const Stmt* child, CallerWrapper callExpr, + CalleeWrapper calleeFunctionDecl); + llvm::Optional getCallee(CallExpr const*); + + // For reasons I do not understand, parentFunctionDecl() is not reliable, so + // we store the parent function on the way down the AST. + FunctionDecl* insideFunctionDecl = nullptr; + std::vector insideConditionalCheckOfVarSet; +}; + +void UnusedVarsGlobal::run() +{ + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + if (!isUnitTestMode()) + { + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + std::string output; + for (const MyVarInfo& s : readFromSet) + output += "read:\t" + s.sourceLocation + "\t" + s.fieldName + "\n"; + for (const MyVarInfo& s : writeToSet) + output += "write:\t" + s.sourceLocation + "\t" + s.fieldName + "\n"; + for (const MyVarInfo& s : definitionSet) + output += "definition:\t" + s.fieldName + "\t" + s.fieldType + "\t" + s.sourceLocation + + "\n"; + std::ofstream myfile; + myfile.open(WORKDIR "/loplugin.unusedvarsglobal.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + else + { + for (const MyVarInfo& s : readFromSet) + report(DiagnosticsEngine::Warning, "read", s.varDecl->getBeginLoc()); + for (const MyVarInfo& s : writeToSet) + report(DiagnosticsEngine::Warning, "write", s.varDecl->getBeginLoc()); + } +} + +MyVarInfo UnusedVarsGlobal::niceName(const VarDecl* varDecl) +{ + MyVarInfo aInfo; + aInfo.varDecl = varDecl; + + aInfo.fieldName = varDecl->getNameAsString(); + // sometimes the name (if it's an anonymous thing) contains the full path of the build folder, which we don't need + size_t idx = aInfo.fieldName.find(SRCDIR); + if (idx != std::string::npos) + { + aInfo.fieldName = aInfo.fieldName.replace(idx, strlen(SRCDIR), ""); + } + aInfo.fieldType = varDecl->getType().getAsString(); + + SourceLocation expansionLoc + = compiler.getSourceManager().getExpansionLoc(varDecl->getLocation()); + StringRef name = getFilenameOfLocation(expansionLoc); + aInfo.sourceLocation + = std::string(name.substr(strlen(SRCDIR) + 1)) + ":" + + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(aInfo.sourceLocation); + + return aInfo; +} + +bool UnusedVarsGlobal::VisitVarDecl(const VarDecl* varDecl) +{ + varDecl = varDecl->getCanonicalDecl(); + if (isa(varDecl)) + return true; + if (!varDecl->hasGlobalStorage()) + return true; + if (!varDecl->getLocation().isValid() || ignoreLocation(varDecl)) + return true; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(varDecl->getLocation()))) + return true; + + /** + If we have + const size_t NB_PRODUCTS = 3; + int DefaultProductDir[NB_PRODUCTS] = { 3, 3, 3 }; + clang will inline the constant "3" and never tell us that we are reading from NB_PRODUCTS, + so just ignore integer constants. + */ + auto varType = varDecl->getType(); + if (varType.isConstQualified() && varType->isIntegerType()) + return true; + + auto initExpr = varDecl->getAnyInitializer(); + if (initExpr && !isSomeKindOfZero(initExpr)) + writeToSet.insert(niceName(varDecl)); + + definitionSet.insert(niceName(varDecl)); + return true; +} + +bool UnusedVarsGlobal::VisitDeclRefExpr(const DeclRefExpr* declRefExpr) +{ + const Decl* decl = declRefExpr->getDecl(); + const VarDecl* varDecl = dyn_cast(decl); + if (!varDecl) + return true; + if (isa(varDecl)) + return true; + if (!varDecl->hasGlobalStorage()) + return true; + varDecl = varDecl->getCanonicalDecl(); + if (!varDecl->getLocation().isValid() || ignoreLocation(varDecl)) + return true; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(varDecl->getLocation()))) + return true; + checkIfReadFrom(varDecl, declRefExpr); + checkIfWrittenTo(varDecl, declRefExpr); + return true; +} + +/** + Does the expression being used to initialise a field value evaluate to + the same as a default value? + */ +bool UnusedVarsGlobal::isSomeKindOfZero(const Expr* arg) +{ + assert(arg); + if (arg->isValueDependent()) + return false; + if (arg->getType().isNull()) + return false; + if (isa(arg)) + arg = dyn_cast(arg)->getExpr(); + arg = arg->IgnoreParenCasts(); + // ignore this, it seems to trigger an infinite recursion + if (isa(arg)) + return false; + if (auto cxxConstructExpr = dyn_cast(arg)) + return cxxConstructExpr->getConstructor()->isDefaultConstructor(); + APSInt x1; + if (compat::EvaluateAsInt(arg, x1, compiler.getASTContext())) + return x1 == 0; + if (isa(arg)) + return true; + if (isa(arg)) + { + const CXXBindTemporaryExpr* strippedArg + = dyn_cast_or_null(arg->IgnoreParenCasts()); + if (strippedArg) + { + auto temp = dyn_cast(strippedArg->getSubExpr()); + if (temp->getNumArgs() == 0) + { + if (loplugin::TypeCheck(temp->getType()) + .Class("OUString") + .Namespace("rtl") + .GlobalNamespace()) + return true; + if (loplugin::TypeCheck(temp->getType()) + .Class("OString") + .Namespace("rtl") + .GlobalNamespace()) + return true; + return false; + } + } + } + + // Get the expression contents. + // This helps us find params which are always initialised with something like "OUString()". + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = arg->getBeginLoc(); + SourceLocation endLoc = arg->getEndLoc(); + const char* p1 = SM.getCharacterData(startLoc); + const char* p2 = SM.getCharacterData(endLoc); + if (!p1 || !p2 || (p2 - p1) < 0 || (p2 - p1) > 40) + return false; + unsigned n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts()); + std::string s(p1, p2 - p1 + n); + // strip linefeed and tab characters so they don't interfere with the parsing of the log file + std::replace(s.begin(), s.end(), '\r', ' '); + std::replace(s.begin(), s.end(), '\n', ' '); + std::replace(s.begin(), s.end(), '\t', ' '); + + // now normalize the value. For some params, like OUString, we can pass it as OUString() or "" and they are the same thing + if (s == "OUString()") + return true; + else if (s == "OString()") + return true; + return false; +} + +static char easytolower(char in) +{ + if (in <= 'Z' && in >= 'A') + return in - ('Z' - 'z'); + return in; +} + +bool startswith(const std::string& rStr, const char* pSubStr) +{ + return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; +} + +bool UnusedVarsGlobal::TraverseCXXMethodDecl(CXXMethodDecl* cxxMethodDecl) +{ + auto copy2 = insideFunctionDecl; + insideFunctionDecl = cxxMethodDecl; + bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl); + insideFunctionDecl = copy2; + return ret; +} + +bool UnusedVarsGlobal::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + auto copy2 = insideFunctionDecl; + insideFunctionDecl = functionDecl; + bool ret = RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); + insideFunctionDecl = copy2; + return ret; +} + +bool UnusedVarsGlobal::TraverseIfStmt(IfStmt* ifStmt) +{ + VarDecl const* varDecl = nullptr; + Expr const* cond = ifStmt->getCond()->IgnoreParenImpCasts(); + + if (auto memberCallExpr = dyn_cast(cond)) + { + if (auto cxxConvert = dyn_cast_or_null(memberCallExpr->getMethodDecl())) + { + if (cxxConvert->getConversionType()->isBooleanType()) + if (auto declRefExpr = dyn_cast( + memberCallExpr->getImplicitObjectArgument()->IgnoreParenImpCasts())) + if ((varDecl = dyn_cast(declRefExpr->getDecl()))) + insideConditionalCheckOfVarSet.push_back(varDecl); + } + } + else if (auto declRefExpr = dyn_cast(cond)) + { + if ((varDecl = dyn_cast(declRefExpr->getDecl()))) + insideConditionalCheckOfVarSet.push_back(varDecl); + } + + bool ret = RecursiveASTVisitor::TraverseIfStmt(ifStmt); + if (varDecl) + insideConditionalCheckOfVarSet.pop_back(); + return ret; +} + +void UnusedVarsGlobal::checkIfReadFrom(const VarDecl* varDecl, const DeclRefExpr* declRefExpr) +{ + auto parentsRange = compiler.getASTContext().getParents(*declRefExpr); + const Stmt* child = declRefExpr; + const Stmt* parent + = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get(); + // walk up the tree until we find something interesting + bool bPotentiallyReadFrom = false; + bool bDump = false; + auto walkUp = [&]() { + child = parent; + auto parentsRange = compiler.getASTContext().getParents(*parent); + parent = parentsRange.begin() == parentsRange.end() ? nullptr + : parentsRange.begin()->get(); + }; + do + { + if (!parent) + { + // check if we're inside a CXXCtorInitializer or a VarDecl + auto parentsRange = compiler.getASTContext().getParents(*child); + if (parentsRange.begin() != parentsRange.end()) + { + const Decl* decl = parentsRange.begin()->get(); + if (decl && (isa(decl) || isa(decl))) + bPotentiallyReadFrom = true; + } + if (!bPotentiallyReadFrom) + return; + break; + } + if (isa(parent)) + { + // once we see one of these, there is not much useful we can know + bPotentiallyReadFrom = true; + break; + } + else if (isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent)) + { + walkUp(); + } + else if (auto unaryOperator = dyn_cast(parent)) + { + UnaryOperator::Opcode op = unaryOperator->getOpcode(); + if (declRefExpr->getType()->isArrayType() && op == UO_Deref) + { + // ignore, deref'ing an array does not count as a read + } + else if (op == UO_AddrOf || op == UO_Deref || op == UO_Plus || op == UO_Minus + || op == UO_Not || op == UO_LNot) + { + bPotentiallyReadFrom = true; + break; + } + /* The following are technically reads, but from a code-sense they're more of a write/modify, so + ignore them to find interesting fields that only modified, not usefully read: + UO_PreInc / UO_PostInc / UO_PreDec / UO_PostDec + But we still walk up in case the result of the expression is used in a read sense. + */ + walkUp(); + } + else if (auto caseStmt = dyn_cast(parent)) + { + bPotentiallyReadFrom = caseStmt->getLHS() == child || caseStmt->getRHS() == child; + break; + } + else if (auto ifStmt = dyn_cast(parent)) + { + bPotentiallyReadFrom = ifStmt->getCond() == child; + break; + } + else if (auto doStmt = dyn_cast(parent)) + { + bPotentiallyReadFrom = doStmt->getCond() == child; + break; + } + else if (auto arraySubscriptExpr = dyn_cast(parent)) + { + if (arraySubscriptExpr->getIdx() == child) + { + bPotentiallyReadFrom = true; + break; + } + walkUp(); + } + else if (auto binaryOp = dyn_cast(parent)) + { + BinaryOperator::Opcode op = binaryOp->getOpcode(); + const bool assignmentOp = op == BO_Assign || op == BO_MulAssign || op == BO_DivAssign + || op == BO_RemAssign || op == BO_AddAssign + || op == BO_SubAssign || op == BO_ShlAssign + || op == BO_ShrAssign || op == BO_AndAssign + || op == BO_XorAssign || op == BO_OrAssign; + if (binaryOp->getLHS() == child && assignmentOp) + break; + else + { + bPotentiallyReadFrom = true; + break; + } + } + else if (auto operatorCallExpr = dyn_cast(parent)) + { + auto op = operatorCallExpr->getOperator(); + const bool assignmentOp = op == OO_Equal || op == OO_StarEqual || op == OO_SlashEqual + || op == OO_PercentEqual || op == OO_PlusEqual + || op == OO_MinusEqual || op == OO_LessLessEqual + || op == OO_AmpEqual || op == OO_CaretEqual + || op == OO_PipeEqual; + if (operatorCallExpr->getArg(0) == child && assignmentOp) + break; + else if (op == OO_GreaterGreaterEqual && operatorCallExpr->getArg(1) == child) + break; // this is a write-only call + else + { + bPotentiallyReadFrom = true; + break; + } + } + else if (auto cxxMemberCallExpr = dyn_cast(parent)) + { + bool bWriteOnlyCall = false; + const CXXMethodDecl* callee = cxxMemberCallExpr->getMethodDecl(); + if (callee) + { + const Expr* tmp = dyn_cast(child); + if (tmp->isBoundMemberFunction(compiler.getASTContext())) + { + tmp = dyn_cast(tmp)->getBase(); + } + if (cxxMemberCallExpr->getImplicitObjectArgument() == tmp) + { + // FIXME perhaps a better solution here would be some kind of SAL_PARAM_WRITEONLY attribute + // which we could scatter around. + std::string name = callee->getNameAsString(); + std::transform(name.begin(), name.end(), name.begin(), easytolower); + if (startswith(name, "emplace") || name == "insert" || name == "erase" + || name == "remove" || name == "remove_if" || name == "sort" + || name == "push_back" || name == "pop_back" || name == "push_front" + || name == "pop_front" || name == "reserve" || name == "resize" + || name == "reset" || name == "clear" || name == "fill") + // write-only modifications to collections + bWriteOnlyCall = true; + else if (name == "dispose" || name == "disposeAndClear" || name == "swap") + // we're abusing the write-only analysis here to look for fields which don't have anything useful + // being done to them, so we're ignoring things like std::vector::clear, std::vector::swap, + // and VclPtr::disposeAndClear + bWriteOnlyCall = true; + } + } + if (!bWriteOnlyCall) + bPotentiallyReadFrom = true; + break; + } + else if (auto callExpr = dyn_cast(parent)) + { + bool bWriteOnlyCall = false; + // check for calls to ReadXXX(foo) type methods, where foo is write-only + auto callee = getCallee(callExpr); + if (callee) + { + // FIXME perhaps a better solution here would be some kind of SAL_PARAM_WRITEONLY attribute + // which we could scatter around. + std::string name = callee->getNameAsString(); + std::transform(name.begin(), name.end(), name.begin(), easytolower); + if (startswith(name, "read")) + // this is a write-only call + bWriteOnlyCall = true; + } + if (!bWriteOnlyCall) + bPotentiallyReadFrom = true; + break; + } + else if (isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent)) + { + bPotentiallyReadFrom = true; + break; + } + else if (isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) // TODO + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) || isa(parent) + || isa(parent)) + { + break; + } + else + { + bPotentiallyReadFrom = true; + bDump = true; + break; + } + } while (true); + + if (bDump) + { + report(DiagnosticsEngine::Warning, "oh dear, what can the matter be?", + declRefExpr->getBeginLoc()) + << declRefExpr->getSourceRange(); + report(DiagnosticsEngine::Note, "parent over here", parent->getBeginLoc()) + << parent->getSourceRange(); + parent->dump(); + declRefExpr->dump(); + } + + if (bPotentiallyReadFrom) + readFromSet.insert(niceName(varDecl)); +} + +void UnusedVarsGlobal::checkIfWrittenTo(const VarDecl* varDecl, const DeclRefExpr* declRefExpr) +{ + // if we're inside a block that looks like + // if (varDecl) + // ... + // then writes to this field don't matter, because unless we find another write to this field, this field is dead + if (std::find(insideConditionalCheckOfVarSet.begin(), insideConditionalCheckOfVarSet.end(), + varDecl) + != insideConditionalCheckOfVarSet.end()) + return; + + auto parentsRange = compiler.getASTContext().getParents(*declRefExpr); + const Stmt* child = declRefExpr; + const Stmt* parent + = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get(); + // walk up the tree until we find something interesting + bool bPotentiallyWrittenTo = false; + bool bDump = false; + auto walkUp = [&]() { + child = parent; + auto parentsRange = compiler.getASTContext().getParents(*parent); + parent = parentsRange.begin() == parentsRange.end() ? nullptr + : parentsRange.begin()->get(); + }; + do + { + if (!parent) + { + // check if we have an expression like + // int& r = m_field; + auto parentsRange = compiler.getASTContext().getParents(*child); + if (parentsRange.begin() != parentsRange.end()) + { + auto varDecl = dyn_cast_or_null(parentsRange.begin()->get()); + // The isImplicit() call is to avoid triggering when we see the vardecl which is part of a for-range statement, + // which is of type 'T&&' and also an l-value-ref ? + if (varDecl && !varDecl->isImplicit() + && loplugin::TypeCheck(varDecl->getType()).LvalueReference().NonConst()) + { + bPotentiallyWrittenTo = true; + } + } + break; + } + if (isa(parent)) + { + // once we see one of these, there is not much useful we can know + bPotentiallyWrittenTo = true; + break; + } + else if (isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent)) + { + walkUp(); + } + else if (auto unaryOperator = dyn_cast(parent)) + { + UnaryOperator::Opcode op = unaryOperator->getOpcode(); + if (op == UO_AddrOf || op == UO_PostInc || op == UO_PostDec || op == UO_PreInc + || op == UO_PreDec) + { + bPotentiallyWrittenTo = true; + } + break; + } + else if (auto arraySubscriptExpr = dyn_cast(parent)) + { + if (arraySubscriptExpr->getIdx() == child) + break; + walkUp(); + } + else if (auto operatorCallExpr = dyn_cast(parent)) + { + auto callee = getCallee(operatorCallExpr); + if (callee) + { + // if calling a non-const operator on the field + auto calleeMethodDecl = callee->getAsCXXMethodDecl(); + if (calleeMethodDecl && operatorCallExpr->getArg(0) == child) + { + if (!calleeMethodDecl->isConst()) + bPotentiallyWrittenTo + = checkForWriteWhenUsingCollectionType(calleeMethodDecl); + } + else if (IsPassedByNonConst(varDecl, child, operatorCallExpr, *callee)) + { + bPotentiallyWrittenTo = true; + } + } + else + bPotentiallyWrittenTo = true; // conservative, could improve + break; + } + else if (auto cxxMemberCallExpr = dyn_cast(parent)) + { + const CXXMethodDecl* calleeMethodDecl = cxxMemberCallExpr->getMethodDecl(); + if (calleeMethodDecl) + { + // if calling a non-const method on the field + const Expr* tmp = dyn_cast(child); + if (tmp->isBoundMemberFunction(compiler.getASTContext())) + { + tmp = dyn_cast(tmp)->getBase(); + } + if (cxxMemberCallExpr->getImplicitObjectArgument() == tmp) + { + if (!calleeMethodDecl->isConst()) + bPotentiallyWrittenTo + = checkForWriteWhenUsingCollectionType(calleeMethodDecl); + break; + } + else if (IsPassedByNonConst(varDecl, child, cxxMemberCallExpr, + CalleeWrapper(calleeMethodDecl))) + bPotentiallyWrittenTo = true; + } + else + bPotentiallyWrittenTo = true; // can happen in templates + break; + } + else if (auto cxxConstructExpr = dyn_cast(parent)) + { + if (IsPassedByNonConst(varDecl, child, cxxConstructExpr, + CalleeWrapper(cxxConstructExpr))) + bPotentiallyWrittenTo = true; + break; + } + else if (auto callExpr = dyn_cast(parent)) + { + auto callee = getCallee(callExpr); + if (callee) + { + if (IsPassedByNonConst(varDecl, child, callExpr, *callee)) + bPotentiallyWrittenTo = true; + } + else + bPotentiallyWrittenTo = true; // conservative, could improve + break; + } + else if (auto binaryOp = dyn_cast(parent)) + { + BinaryOperator::Opcode op = binaryOp->getOpcode(); + const bool assignmentOp = op == BO_Assign || op == BO_MulAssign || op == BO_DivAssign + || op == BO_RemAssign || op == BO_AddAssign + || op == BO_SubAssign || op == BO_ShlAssign + || op == BO_ShrAssign || op == BO_AndAssign + || op == BO_XorAssign || op == BO_OrAssign; + if (assignmentOp) + { + if (binaryOp->getLHS() == child) + bPotentiallyWrittenTo = true; + else if (loplugin::TypeCheck(binaryOp->getLHS()->getType()) + .LvalueReference() + .NonConst()) + // if the LHS is a non-const reference, we could write to the field later on + bPotentiallyWrittenTo = true; + } + break; + } + else if (isa(parent)) + { + if (insideFunctionDecl) + { + auto tc = loplugin::TypeCheck(insideFunctionDecl->getReturnType()); + if (tc.LvalueReference().NonConst()) + bPotentiallyWrittenTo = true; + } + break; + } + else if (isa(parent) || isa(parent) + || isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent)) // TODO + { + break; + } + else + { + bPotentiallyWrittenTo = true; + bDump = true; + break; + } + } while (true); + + if (bDump) + { + report(DiagnosticsEngine::Warning, "oh dear, what can the matter be? writtenTo=%0", + declRefExpr->getBeginLoc()) + << bPotentiallyWrittenTo << declRefExpr->getSourceRange(); + if (parent) + { + report(DiagnosticsEngine::Note, "parent over here", parent->getBeginLoc()) + << parent->getSourceRange(); + parent->dump(); + } + declRefExpr->dump(); + varDecl->getType()->dump(); + } + + if (bPotentiallyWrittenTo) + writeToSet.insert(niceName(varDecl)); +} + +// return true if this not a collection type, or if it is a collection type, and we might be writing to it +bool UnusedVarsGlobal::checkForWriteWhenUsingCollectionType(const CXXMethodDecl* calleeMethodDecl) +{ + auto const tc = loplugin::TypeCheck(calleeMethodDecl->getParent()); + bool listLike = false, setLike = false, mapLike = false, cssSequence = false; + if (tc.Class("deque").StdNamespace() || tc.Class("list").StdNamespace() + || tc.Class("queue").StdNamespace() || tc.Class("vector").StdNamespace()) + { + listLike = true; + } + else if (tc.Class("set").StdNamespace() || tc.Class("unordered_set").StdNamespace()) + { + setLike = true; + } + else if (tc.Class("map").StdNamespace() || tc.Class("unordered_map").StdNamespace()) + { + mapLike = true; + } + else if (tc.Class("Sequence") + .Namespace("uno") + .Namespace("star") + .Namespace("sun") + .Namespace("com") + .GlobalNamespace()) + { + cssSequence = true; + } + else + return true; + + if (calleeMethodDecl->isOverloadedOperator()) + { + auto oo = calleeMethodDecl->getOverloadedOperator(); + if (oo == OO_Equal) + return true; + // This is operator[]. We only care about things that add elements to the collection. + // if nothing modifies the size of the collection, then nothing useful + // is stored in it. + if (listLike) + return false; + return true; + } + + auto name = calleeMethodDecl->getName(); + if (listLike || setLike || mapLike) + { + if (name == "reserve" || name == "shrink_to_fit" || name == "clear" || name == "erase" + || name == "pop_back" || name == "pop_front" || name == "front" || name == "back" + || name == "data" || name == "remove" || name == "remove_if" || name == "unique" + || name == "sort" || name == "begin" || name == "end" || name == "rbegin" + || name == "rend" || name == "at" || name == "find" || name == "equal_range" + || name == "lower_bound" || name == "upper_bound") + return false; + } + if (cssSequence) + { + if (name == "getArray" || name == "begin" || name == "end") + return false; + } + + return true; +} + +bool UnusedVarsGlobal::IsPassedByNonConst(const VarDecl* varDecl, const Stmt* child, + CallerWrapper callExpr, CalleeWrapper calleeFunctionDecl) +{ + unsigned len = std::min(callExpr.getNumArgs(), calleeFunctionDecl.getNumParams()); + // if it's an array, passing it by value to a method typically means the + // callee takes a pointer and can modify the array + if (varDecl->getType()->isConstantArrayType()) + { + for (unsigned i = 0; i < len; ++i) + if (callExpr.getArg(i) == child) + if (loplugin::TypeCheck(calleeFunctionDecl.getParamType(i)).Pointer().NonConst()) + return true; + } + else + { + for (unsigned i = 0; i < len; ++i) + if (callExpr.getArg(i) == child) + if (loplugin::TypeCheck(calleeFunctionDecl.getParamType(i)) + .LvalueReference() + .NonConst()) + return true; + } + return false; +} + +llvm::Optional UnusedVarsGlobal::getCallee(CallExpr const* callExpr) +{ + FunctionDecl const* functionDecl = callExpr->getDirectCallee(); + if (functionDecl) + return CalleeWrapper(functionDecl); + + // Extract the functionprototype from a type + clang::Type const* calleeType = callExpr->getCallee()->getType().getTypePtr(); + if (auto pointerType = calleeType->getUnqualifiedDesugaredType()->getAs()) + { + if (auto prototype = pointerType->getPointeeType() + ->getUnqualifiedDesugaredType() + ->getAs()) + { + return CalleeWrapper(prototype); + } + } + + return llvm::Optional(); +} + +loplugin::Plugin::Registration X("unusedvarsglobal", false); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/unusedvarsglobal.py b/compilerplugins/clang/unusedvarsglobal.py new file mode 100755 index 000000000..da268794b --- /dev/null +++ b/compilerplugins/clang/unusedvarsglobal.py @@ -0,0 +1,151 @@ +#!/usr/bin/python2 + +import sys +import re +import io + +definitionSet = set() +readFromSet = set() +writeToSet = set() +defToTypeMap = dict() + +def parseFieldInfo( tokens ): + return (tokens[1].strip(), tokens[2].strip()) + +with io.open("workdir/loplugin.unusedvarsglobal.log", "rb", buffering=1024*1024) as txt: + for line in txt: + try: + tokens = line.strip().split("\t") + if tokens[0] == "definition:": + srcLoc = tokens[3] + # ignore external source code + if (srcLoc.startswith("external/")): + continue + # ignore build folder + if (srcLoc.startswith("workdir/")): + continue + varname = tokens[1].strip() + vartype = tokens[2].strip() + if vartype.startswith("const "): + vartype = vartype[6:] + if vartype.startswith("class "): + vartype = vartype[6:] + if vartype.startswith("struct "): + vartype = vartype[7:] + if vartype.startswith("::"): + vartype = vartype[2:] + fieldInfo = (srcLoc, varname) + definitionSet.add(fieldInfo) + defToTypeMap[fieldInfo] = vartype + elif tokens[0] == "read:": + if len(tokens) == 3: + readFromSet.add(parseFieldInfo(tokens)) + elif tokens[0] == "write:": + if len(tokens) == 3: + writeToSet.add(parseFieldInfo(tokens)) + else: + print( "unknown line: " + line) + except IndexError: + print "problem with line " + line.strip() + raise + +definitionSet2 = set() +for d in definitionSet: + varname = d[1] + vartype = defToTypeMap[d] + if len(varname) == 0: + continue + if varname.startswith("autoRegister"): # auto-generated CPPUNIT stuff + continue + if vartype in ["css::uno::ContextLayer", "SolarMutexGuard", "SolarMutexReleaser", "OpenGLZone"]: + continue + if vartype in ["PreDefaultWinNoOpenGLZone", "SchedulerGuard", "SkiaZone", "OpenGLVCLContextZone"]: + continue + if vartype in ["SwXDispatchProviderInterceptor::DispatchMutexLock_Impl", "SfxObjectShellLock", "OpenCLZone"]: + continue + if vartype in ["OpenCLInitialZone", "pyuno::PyThreadDetach", "SortRefUpdateSetter", "oglcanvas::TransformationPreserver"]: + continue + if vartype in ["StackHack", "osl::MutexGuard", "accessibility::SolarMethodGuard"]: + continue + if vartype in ["osl::ClearableMutexGuard", "comphelper::OExternalLockGuard", "osl::Guard< ::osl::Mutex>"]: + continue + if vartype in ["comphelper::OContextEntryGuard", "Guard", "basic::LibraryContainerMethodGuard"]: + continue + if vartype in ["canvas::CanvasBase::MutexType"]: + continue + definitionSet2.add(d) + +# Calculate untouched +untouchedSet = set() +for d in definitionSet2: + if d in readFromSet or d in writeToSet: + continue + varname = d[1] + if len(varname) == 0: + continue + untouchedSet.add(d) + +writeonlySet = set() +for d in definitionSet2: + if d in readFromSet or d in untouchedSet: + continue + varname = d[1] + vartype = defToTypeMap[d] + if "Alive" in varname: + continue + if "Keep" in varname: + continue + if vartype.endswith(" &"): + continue + writeonlySet.add(d) + +readonlySet = set() +for d in definitionSet2: + if d in writeToSet or d in untouchedSet: + continue + varname = d[1] + vartype = defToTypeMap[d] + if "Dummy" in varname: + continue + if "Empty" in varname: + continue + if varname in ["aOldValue", "aNewValue"]: + continue + if "Exception" in vartype and vartype.endswith(" &"): + continue + if "exception" in vartype and vartype.endswith(" &"): + continue + # TODO for now, focus on the simple stuff + if not (vartype in ["rtl::OUString", "Bool"]): + continue + readonlySet.add(d) + +# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[0]) + [v[1]] + +# sort results by name and line number +tmp1list = sorted(untouchedSet, key=lambda v: v_sort_key(v)) +tmp2list = sorted(writeonlySet, key=lambda v: v_sort_key(v)) +tmp3list = sorted(readonlySet, key=lambda v: v_sort_key(v)) + +# print out the results +with open("compilerplugins/clang/unusedvarsglobal.untouched.results", "wt") as f: + for t in tmp1list: + f.write( t[0] + "\n" ) + f.write( " " + defToTypeMap[t] + " " + t[1] + "\n" ) +with open("compilerplugins/clang/unusedvarsglobal.writeonly.results", "wt") as f: + for t in tmp2list: + f.write( t[0] + "\n" ) + f.write( " " + defToTypeMap[t] + " " + t[1] + "\n" ) +with open("compilerplugins/clang/unusedvarsglobal.readonly.results", "wt") as f: + for t in tmp3list: + f.write( t[0] + "\n" ) + f.write( " " + defToTypeMap[t] + " " + t[1] + "\n" ) + + diff --git a/compilerplugins/clang/unusedvarsglobal.untouched.results b/compilerplugins/clang/unusedvarsglobal.untouched.results new file mode 100644 index 000000000..4a40feec0 --- /dev/null +++ b/compilerplugins/clang/unusedvarsglobal.untouched.results @@ -0,0 +1,44 @@ +canvas/workben/canvasdemo.cxx:669 + (anonymous namespace)::DemoApp aApp +cppu/source/uno/check.cxx:315 + (anonymous namespace)::BinaryCompatible_Impl aTest +framework/source/services/ContextChangeEventMultiplexer.cxx:370 + framework::(anonymous namespace)::Hook g_hook +hwpfilter/source/nodes.h:92 + int count +pyuno/source/module/pyuno_gc.cxx:45 + pyuno::(anonymous namespace)::StaticDestructorGuard guard +sal/osl/all/utility.cxx:45 + osl::(anonymous namespace)::OGlobalTimer aGlobalTimer +sal/qa/osl/file/osl_File.cxx:4970 + (anonymous namespace)::GlobalObject theGlobalObject +sal/rtl/cmdargs.cxx:46 + (anonymous namespace)::ArgHolder argHolder +sal/rtl/strtmpl.hxx:1258 + IMPL_RTL_STRINGDATA data +sc/source/ui/inc/inscodlg.hxx:88 + _Bool bPreviousAllCheck +sdext/source/presenter/PresenterHelper.hxx:33 + rtl::OUString msCenterPaneURL +soltools/cpp/cpp.h:239 + int Lflag +soltools/mkdepend/parse.c:40 + symhash * maininclist +soltools/mkdepend/pr.c:34 + int width +starmath/inc/ElementsDockingWindow.hxx:81 + std::tuple [0] m_a6Categories +svx/source/gengal/gengal.cxx:323 + (anonymous namespace)::GalApp aGalApp +vcl/backendtest/VisualBackendTest.cxx:799 + (anonymous namespace)::VisualBackendTestApp aApplication +vcl/source/uipreviewer/previewer.cxx:113 + (anonymous namespace)::UIPreviewApp aApp +vcl/workben/icontest.cxx:214 + (anonymous namespace)::IconTestApp aApp +vcl/workben/mtfdemo.cxx:162 + (anonymous namespace)::DemoMtfApp aApp +vcl/workben/vcldemo.cxx:2258 + (anonymous namespace)::DemoApp aApp +xmloff/source/forms/elementimport.hxx:54 + xmloff::OElementNameMap::MapString2Element s_sElementTranslations diff --git a/compilerplugins/clang/unusedvarsglobal.writeonly.results b/compilerplugins/clang/unusedvarsglobal.writeonly.results new file mode 100644 index 000000000..a79fcd405 --- /dev/null +++ b/compilerplugins/clang/unusedvarsglobal.writeonly.results @@ -0,0 +1,180 @@ +basctl/source/basicide/localizationmgr.cxx:56 + rtl::OUStringLiteral<2> aSemi +chart2/source/view/inc/ViewDefines.hxx:29 + double ZDIRECTION +connectivity/source/drivers/hsqldb/HDriver.cxx:345 + Reference s_xTerminateListener +connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx:38 + std::string wild +cppuhelper/source/servicemanager.cxx:2024 + std::vector maMaps +dbaccess/source/ui/browser/genericcontroller.cxx:462 + sal_Int32 s_nRecursions +hwpfilter/source/grammar.cxx:399 + int yynerrs +hwpfilter/source/hbox.h:66 + int boxCount +hwpfilter/source/ksc5601.h:184 + hchar [4888] ksc5601_2uni_page4a +hwpfilter/source/nodes.h:98 + std::vector > nodelist +i18npool/inc/calendar_hijri.hxx:46 + double SynMonth +i18npool/inc/calendar_hijri.hxx:56 + double SA_TimeZone +i18npool/inc/calendar_hijri.hxx:59 + double EveningPeriod +i18npool/inc/calendar_hijri.hxx:62 + sal_Int32 [] LeapYear +idlc/source/idlccompile.cxx:51 + int yydebug +include/vcl/animate/Animation.hxx:96 + sal_uLong mnAnimCount +include/xmloff/xmlimp.hxx:531 + rtl::OUStringLiteral<1> aDefaultNamespace +libreofficekit/qa/gtktiledviewer/gtv-comments-sidebar.cxx:31 + gpointer gtv_comments_sidebar_parent_class +libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx:61 + gpointer gtv_lok_dialog_parent_class +sal/osl/unx/system.cxx:164 + void *[3] dummy +sal/qa/osl/condition/osl_Condition_Const.h:41 + rtl::OUString aTestCon +sal/qa/osl/condition/osl_Condition_Const.h:43 + char [17] pTestString +sal/qa/osl/file/osl_File_Const.h:63 + char [11] pBuffer_Number +sal/qa/osl/file/osl_File_Const.h:64 + char [1] pBuffer_Blank +sal/qa/osl/file/osl_File_Const.h:129 + rtl::OUString aCanURL2 +sal/qa/osl/file/osl_File_Const.h:131 + rtl::OUString aCanURL3 +sal/qa/osl/file/osl_File_Const.h:132 + rtl::OUString aCanURL4 +sal/qa/osl/file/osl_File_Const.h:139 + rtl::OUString aTmpName7 +sal/qa/osl/file/osl_File_Const.h:144 + rtl::OUString aRelURL1 +sal/qa/osl/file/osl_File_Const.h:145 + rtl::OUString aRelURL2 +sal/qa/osl/file/osl_File_Const.h:146 + rtl::OUString aRelURL3 +sal/qa/osl/file/osl_File_Const.h:148 + rtl::OUString aRelURL5 +sal/qa/osl/file/osl_File_Const.h:149 + rtl::OUString aLnkURL1 +sal/qa/osl/file/osl_File_Const.h:160 + rtl::OUString aSysPathLnk +sal/qa/osl/file/osl_File_Const.h:161 + rtl::OUString aFifoSys +sal/qa/osl/file/osl_File_Const.h:168 + rtl::OUString aTypeURL1 +sal/qa/osl/file/osl_File_Const.h:169 + rtl::OUString aTypeURL2 +sal/qa/osl/file/osl_File_Const.h:170 + rtl::OUString aTypeURL3 +sal/qa/osl/file/osl_File_Const.h:185 + rtl::OUString aVolURL2 +sal/qa/osl/file/osl_File_Const.h:187 + rtl::OUString aVolURL3 +sal/qa/osl/file/osl_File_Const.h:188 + rtl::OUString aVolURL4 +sal/qa/osl/file/osl_File_Const.h:189 + rtl::OUString aVolURL5 +sal/qa/osl/file/osl_File_Const.h:190 + rtl::OUString aVolURL6 +sal/qa/osl/security/osl_Security_Const.h:48 + char [17] pTestString +sal/qa/OStringBuffer/rtl_String_Const.h:275 + sal_Unicode [3] uTestStr31 +sal/qa/OStringBuffer/rtl_String_Const.h:276 + sal_Unicode [4] uTestStr32 +sal/qa/OStringBuffer/rtl_String_Const.h:297 + sal_Int32 [5] kInt32MaxNums +sal/qa/OStringBuffer/rtl_String_Const.h:306 + sal_Int64 [7] kInt64MaxNums +sal/qa/OStringBuffer/rtl_String_Const.h:335 + double [24] expValDouble +sal/qa/OStringBuffer/rtl_String_Const.h:345 + float [22] expValFloat +sal/qa/OStringBuffer/rtl_String_Const.h:355 + sal_Unicode [15] expValChar +sal/qa/OStringBuffer/rtl_String_Const.h:364 + sal_Unicode [6] input1Default +sal/qa/OStringBuffer/rtl_String_Const.h:368 + sal_Int32 [6] input2Default +sal/qa/OStringBuffer/rtl_String_Const.h:372 + sal_Int32 [6] expValDefault +sal/qa/OStringBuffer/rtl_String_Const.h:378 + sal_Unicode [10] input1Normal +sal/qa/OStringBuffer/rtl_String_Const.h:382 + sal_Int32 [10] input2Normal +sal/qa/OStringBuffer/rtl_String_Const.h:386 + sal_Int32 [10] expValNormal +sal/qa/OStringBuffer/rtl_String_Const.h:392 + sal_Unicode [5] input1lastDefault +sal/qa/OStringBuffer/rtl_String_Const.h:396 + sal_Int32 [5] input2lastDefault +sal/qa/OStringBuffer/rtl_String_Const.h:400 + sal_Int32 [5] expVallastDefault +sal/qa/OStringBuffer/rtl_String_Const.h:406 + sal_Unicode [8] input1lastNormal +sal/qa/OStringBuffer/rtl_String_Const.h:410 + sal_Int32 [8] input2lastNormal +sal/qa/OStringBuffer/rtl_String_Const.h:414 + sal_Int32 [8] expVallastNormal +sal/qa/OStringBuffer/rtl_String_Const.h:420 + sal_Int32 [6] input2StrDefault +sal/qa/OStringBuffer/rtl_String_Const.h:424 + sal_Int32 [6] expValStrDefault +sal/qa/OStringBuffer/rtl_String_Const.h:430 + sal_Int32 [9] input2StrNormal +sal/qa/OStringBuffer/rtl_String_Const.h:434 + sal_Int32 [9] expValStrNormal +sal/qa/OStringBuffer/rtl_String_Const.h:440 + sal_Int32 [6] input2StrLastDefault +sal/qa/OStringBuffer/rtl_String_Const.h:444 + sal_Int32 [6] expValStrLastDefault +sal/qa/OStringBuffer/rtl_String_Const.h:450 + sal_Int32 [12] input2StrLastNormal +sal/qa/OStringBuffer/rtl_String_Const.h:454 + sal_Int32 [12] expValStrLastNormal +sal/qa/rtl/strings/test_oustring_stringliterals.cxx:47 + rtlunittest::OUStringLiteral<6> dummy +sc/source/core/data/drwlayer.cxx:86 + E3dObjFactory * pF3d +sd/source/ui/inc/framework/FrameworkHelper.hxx:80 + rtl::OUStringLiteral<28> msTaskPanelURLPrefix +sfx2/source/appl/appdata.cxx:48 + BasicDLL * pBasic +sfx2/source/appl/shutdownicon.hxx:108 + _Bool bModalMode +soltools/cpp/cpp.h:246 + Nlist * kwdefined +starmath/inc/mathml/mathmlMo.hxx:106 + std::vector moOperatorDataDictionary +starmath/inc/mathml/starmathdatabase.hxx:189 + Color COL_SM_DIV_BLACK +starmath/inc/mathml/starmathdatabase.hxx:190 + Color COL_SM_DIV_BLUE +svl/source/items/style.cxx:59 + (anonymous namespace)::DbgStyleSheetReferences aDbgStyleSheetReferences +sw/source/core/inc/swfont.hxx:989 + SvStatistics g_SvStat +sw/source/filter/ww8/ww8par6.cxx:1083 + sal_uInt16 [2] nLef +sw/source/filter/ww8/ww8par6.cxx:1084 + sal_uInt16 [2] nRig +sw/source/filter/ww8/ww8par6.cxx:1135 + sal_uInt16 [2] nTop +sw/source/filter/ww8/ww8par6.cxx:1136 + sal_uInt16 [2] nBot +vcl/qa/cppunit/timer.cxx:54 + (anonymous namespace)::WatchDog * aWatchDog +vcl/source/filter/FilterConfigCache.hxx:49 + char *[] InternalVectorFilterNameList +vcl/unx/gtk3/a11y/gtk3atkutil.cxx:447 + (anonymous namespace)::WindowList g_aWindowList +xmloff/source/draw/sdpropls.cxx:365 + XMLPropertyMapEntry [5] aXMLSDPresPageProps_onlyHeadersFooter diff --git a/compilerplugins/clang/useuniqueptr.cxx b/compilerplugins/clang/useuniqueptr.cxx new file mode 100644 index 000000000..c0ef34b28 --- /dev/null +++ b/compilerplugins/clang/useuniqueptr.cxx @@ -0,0 +1,1307 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" +#include "check.hxx" + +/** + Find destructors that only contain a single call to delete of a field. In which + case that field should really be managed by unique_ptr. +*/ + +namespace { + +class UseUniquePtr: + public loplugin::FilteringPlugin +{ +public: + explicit UseUniquePtr(loplugin::InstantiationData const & data): + FilteringPlugin(data) {} + + virtual void run() override + { + fn = handler.getMainFileName().str(); + loplugin::normalizeDotDotInFilePath(fn); + // can't change these because we pass them down to the SfxItemPool stuff + if (fn == SRCDIR "/sc/source/core/data/docpool.cxx") + return; + // this just too clever for me + if (fn == SRCDIR "/sc/source/core/tool/chgtrack.cxx") + return; + // too clever + if (fn == SRCDIR "/pyuno/source/module/pyuno_runtime.cxx") + return; + // m_pExampleSet here is very badly managed. sometimes it is owning, sometimes not, + // and the logic depends on overriding methods. + if (fn == SRCDIR "/sfx2/source/dialog/tabdlg.cxx") + return; + // pLongArr is being deleted here because we temporarily overwrite a pointer to someone else's buffer, with a pointer + // to our own buffer + if (fn == SRCDIR "/editeng/source/misc/txtrange.cxx") + return; + // can't use std::set> until C++14 + if (fn == SRCDIR "/editeng/source/misc/svxacorr.cxx") + return; + // horrible horrible spawn of evil ownership and deletion here + if (fn == SRCDIR "/sfx2/source/view/ipclient.cxx") + return; + // sometimes it owns, sometimes it doesn't + if (fn == SRCDIR "/editeng/source/misc/svxacorr.cxx") + return; + // SwDoc::m_PageDescs has weird handling + if (fn == SRCDIR "/sw/source/core/doc/docnew.cxx") + return; + // SwRedlineData::pNext and pExtraData have complex handling + if (fn == SRCDIR "/sw/source/core/doc/docredln.cxx") + return; + // ScTempDocSource::pTempDoc + if (fn == SRCDIR "/sc/source/ui/unoobj/funcuno.cxx") + return; + // SwAttrIter::m_pFont + if (fn == SRCDIR "/sw/source/core/text/itratr.cxx" + || fn == SRCDIR "/sw/source/core/text/redlnitr.cxx") + return; + // SwWrongList + if (fn == SRCDIR "/sw/source/core/text/wrong.cxx") + return; + // SwLineLayout::m_pNext + if (fn == SRCDIR "/sw/source/core/text/porlay.cxx") + return; + // ODatabaseExport::m_aDestColumns + if (fn == SRCDIR "/dbaccess/source/ui/misc/DExport.cxx") + return; + // ScTabView::pDrawActual and pDrawOld + if (fn == SRCDIR "/sc/source/ui/view/tabview5.cxx") + return; + // SwHTMLParser::m_pPendStack + if (fn == SRCDIR "/sw/source/filter/html/htmlcss1.cxx") + return; + // Visual Studio 2017 has trouble with these + if (fn == SRCDIR "/comphelper/source/property/MasterPropertySet.cxx" + || fn == SRCDIR "/comphelper/source/property/MasterPropertySetInfo.cxx") + return; + // SwTableLine::m_aBoxes + if (fn == SRCDIR "/sw/source/core/table/swtable.cxx") + return; + // SwHTMLParser::m_pFormImpl + if (fn == SRCDIR "/sw/source/filter/html/htmlform.cxx") + return; + // SwHTMLParser::m_pPendStack, pNext + if (fn == SRCDIR "/sw/source/filter/html/htmltab.cxx") + return; + // SaveLine::pBox, pNext + if (fn == SRCDIR "/sw/source/core/undo/untbl.cxx") + return; + // RedlineInfo::pNextRedline + if (fn == SRCDIR "/sw/source/filter/xml/XMLRedlineImportHelper.cxx") + return; + // SfxObjectShell::pMedium + if (fn == SRCDIR "/sfx2/source/doc/objxtor.cxx") + return; + // various + if (fn == SRCDIR "/sw/source/filter/ww8/wrtww8.cxx") + return; + // WW8TabBandDesc + if (fn == SRCDIR "/sw/source/filter/ww8/ww8par2.cxx") + return; + // ZipOutputStream, ownership of ZipEntry is horribly complicated here + if (fn == SRCDIR "/package/source/zipapi/ZipOutputStream.cxx") + return; + // custom deleter + if (fn == SRCDIR "/sal/rtl/locale.cxx") + return; + // std::vector is tricky, changing it would require moving lots of class definitions around + if (fn == SRCDIR "/sc/source/core/data/documen2.cxx" + || fn == SRCDIR "/sc/source/core/tool/interpretercontext.cxx") + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitFunctionDecl(const FunctionDecl* ); + bool VisitCXXDeleteExpr(const CXXDeleteExpr* ); + bool TraverseFunctionDecl(FunctionDecl* ); + bool TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl* ); + bool TraverseCXXMethodDecl(CXXMethodDecl* ); + bool TraverseCXXConstructorDecl(CXXConstructorDecl* ); + bool TraverseCXXConversionDecl(CXXConversionDecl* ); + bool TraverseCXXDestructorDecl(CXXDestructorDecl* ); + bool TraverseConstructorInitializer(CXXCtorInitializer*); + +private: + void CheckCompoundStmt(const FunctionDecl*, const CompoundStmt* ); + void CheckIfStmt(const FunctionDecl*, const IfStmt* ); + void CheckCXXForRangeStmt(const FunctionDecl*, const CXXForRangeStmt* ); + void CheckLoopDelete(const FunctionDecl*, const Stmt* ); + void CheckLoopDelete(const FunctionDecl*, const CXXDeleteExpr* ); + void CheckDeleteExpr(const FunctionDecl*, const CXXDeleteExpr*); + void CheckDeleteLocalVar(const FunctionDecl*, const CXXDeleteExpr*, const VarDecl*); + void CheckDeleteParmVar(const CXXDeleteExpr*, const ParmVarDecl*); + void CheckParenExpr(const FunctionDecl*, const ParenExpr*); + void CheckMemberDeleteExpr(const FunctionDecl*, const CXXDeleteExpr*, + const MemberExpr*, StringRef message); + FunctionDecl const * mpCurrentFunctionDecl = nullptr; + std::string fn; +}; + +bool UseUniquePtr::VisitFunctionDecl(const FunctionDecl* functionDecl) +{ + if (ignoreLocation(functionDecl)) + return true; + if (isInUnoIncludeFile(functionDecl)) + return true; + + const CompoundStmt* compoundStmt = dyn_cast_or_null< CompoundStmt >( functionDecl->getBody() ); + if (!compoundStmt || compoundStmt->size() == 0) + return true; + + CheckCompoundStmt(functionDecl, compoundStmt); + + return true; +} + +/** + * check for simple call to delete i.e. direct unconditional call, or if-guarded call + */ +void UseUniquePtr::CheckCompoundStmt(const FunctionDecl* functionDecl, const CompoundStmt* compoundStmt) +{ + for (auto i = compoundStmt->body_begin(); i != compoundStmt->body_end(); ++i) + { + if (auto cxxForRangeStmt = dyn_cast(*i)) + CheckCXXForRangeStmt(functionDecl, cxxForRangeStmt); + else if (auto forStmt = dyn_cast(*i)) + CheckLoopDelete(functionDecl, forStmt->getBody()); + else if (auto whileStmt = dyn_cast(*i)) + CheckLoopDelete(functionDecl, whileStmt->getBody()); + // check for unconditional inner compound statements + else if (auto innerCompoundStmt = dyn_cast(*i)) + CheckCompoundStmt(functionDecl, innerCompoundStmt); + else if (auto deleteExpr = dyn_cast(*i)) + CheckDeleteExpr(functionDecl, deleteExpr); + else if (auto parenExpr = dyn_cast(*i)) + CheckParenExpr(functionDecl, parenExpr); + else if (auto ifStmt = dyn_cast(*i)) + CheckIfStmt(functionDecl, ifStmt); + } +} + +// Check for conditional deletes like: +// if (m_pField != nullptr) delete m_pField; +void UseUniquePtr::CheckIfStmt(const FunctionDecl* functionDecl, const IfStmt* ifStmt) +{ + auto cond = ifStmt->getCond()->IgnoreImplicit(); + if (auto ifCondMemberExpr = dyn_cast(cond)) + { + // ignore "if (bMine)" + if (!loplugin::TypeCheck(ifCondMemberExpr->getType()).Pointer()) + return; + // good + } + else if (auto binaryOp = dyn_cast(cond)) + { + if (!isa(binaryOp->getLHS()->IgnoreImplicit())) + return; + if (!isa(binaryOp->getRHS()->IgnoreImplicit())) + return; + // good + } + else // ignore anything more complicated + return; + + auto deleteExpr = dyn_cast(ifStmt->getThen()); + if (deleteExpr) + { + CheckDeleteExpr(functionDecl, deleteExpr); + return; + } + + auto parenExpr = dyn_cast(ifStmt->getThen()); + if (parenExpr) + { + CheckParenExpr(functionDecl, parenExpr); + return; + } + + auto ifThenCompoundStmt = dyn_cast(ifStmt->getThen()); + if (!ifThenCompoundStmt) + return; + for (auto j = ifThenCompoundStmt->body_begin(); j != ifThenCompoundStmt->body_end(); ++j) + { + auto ifDeleteExpr = dyn_cast(*j); + if (ifDeleteExpr) + CheckDeleteExpr(functionDecl, ifDeleteExpr); + ParenExpr const * parenExpr = dyn_cast(*j); + if (parenExpr) + CheckParenExpr(functionDecl, parenExpr); + } +} + +void UseUniquePtr::CheckDeleteExpr(const FunctionDecl* functionDecl, const CXXDeleteExpr* deleteExpr) +{ + auto deleteExprArg = deleteExpr->getArgument()->IgnoreParens()->IgnoreImplicit(); + + + if (const MemberExpr* memberExpr = dyn_cast(deleteExprArg)) + { + // ignore delete static_cast(p)->other; + if (!isa(memberExpr->getBase()->IgnoreCasts())) + return; + // don't always own this + if (fn == SRCDIR "/editeng/source/editeng/impedit2.cxx") + return; + // this member needs to get passed via an extern "C" API + if (fn == SRCDIR "/sd/source/filter/sdpptwrp.cxx") + return; + // ownership complicated between this and the group + if (fn == SRCDIR "/sc/source/core/data/formulacell.cxx") + return; + // linked list + if (fn == SRCDIR "/sw/source/filter/html/parcss1.cxx") + return; + // linked list + if (fn == SRCDIR "/sw/source/filter/writer/writer.cxx") + return; + // complicated + if (fn == SRCDIR "/sc/source/filter/html/htmlpars.cxx") + return; + // complicated pimpl stuff in SalLayoutGlyphs + if (fn == SRCDIR "/vcl/source/gdi/impglyphitem.cxx") + return; + + CheckMemberDeleteExpr(functionDecl, deleteExpr, memberExpr, + "unconditional call to delete on a member, should be using std::unique_ptr"); + return; + } + + const ArraySubscriptExpr* arrayExpr = dyn_cast(deleteExprArg); + if (arrayExpr) + { + auto baseMemberExpr = dyn_cast(arrayExpr->getBase()->IgnoreParens()->IgnoreImplicit()); + if (baseMemberExpr) + CheckMemberDeleteExpr(functionDecl, deleteExpr, baseMemberExpr, + "unconditional call to delete on an array member, should be using std::unique_ptr"); + } +} + +template +bool any_equal(StringRef needle, T first) { + return needle == first; +} + +template +bool any_equal(StringRef needle, T first, Args... args) { + return needle == first || any_equal(needle, args...); +} + +void UseUniquePtr::CheckDeleteLocalVar(const FunctionDecl* functionDecl, const CXXDeleteExpr* deleteExpr, const VarDecl* varDecl) +{ + // ignore globals for now + if (varDecl->hasGlobalStorage()) + return; + + // Ignore times when we are casting from void* to init the var, normally indicates + // some complex memory management. + if (varDecl->getInit()) + { + if (auto explicitCast = dyn_cast(varDecl->getInit())) + { + if (loplugin::TypeCheck(explicitCast->getSubExpr()->getType()).Pointer().Void()) + return; + } + } + + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/qa/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/comphelper/qa/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/cppuhelper/qa/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/libreofficekit/qa/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/qa/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/qa/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sfx2/qa/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/smoketest/")) + return; + if (loplugin::hasPathnamePrefix(fn, WORKDIR)) + return; + // linked lists + if (fn == SRCDIR "/vcl/source/gdi/regband.cxx") + return; + // this thing relies on explicit delete + if (loplugin::TypeCheck(varDecl->getType()).Pointer().Class("VersionCompatRead").GlobalNamespace()) + return; + if (loplugin::TypeCheck(varDecl->getType()).Pointer().Class("VersionCompatWrite").GlobalNamespace()) + return; + if (loplugin::TypeCheck(varDecl->getType()).Pointer().Class("IMapCompat").GlobalNamespace()) + return; + // passing data to gtk API and I can't figure out the types + if (fn == SRCDIR "/vcl/unx/gtk3/gtkdata.cxx") + return; + // sometimes this stuff is held by tools::SvRef, sometimes by std::unique_ptr... + if (fn == SRCDIR "/sot/source/unoolestorage/xolesimplestorage.cxx") + return; + // don't feel like messing with this chunk of sfx2 + if (fn == SRCDIR "/sfx2/source/appl/appinit.cxx") + return; + if (fn == SRCDIR "/svx/source/svdraw/svdobj.cxx") + return; + if (fn == SRCDIR "/svx/source/svdraw/svdmodel.cxx") + return; + // linked list + if (fn == SRCDIR "/basic/source/comp/parser.cxx") + return; + if (fn == SRCDIR "/basic/source/runtime/runtime.cxx") + return; + // just horrible + if (fn == SRCDIR "/svx/source/form/filtnav.cxx") + return; + // using clucene macros + if (fn == SRCDIR "/helpcompiler/source/HelpSearch.cxx") + return; + // linked list + if (fn == SRCDIR "/filter/source/graphicfilter/ios2met/ios2met.cxx") + return; + // no idea what this is trying to do + if (fn == SRCDIR "/cui/source/customize/SvxMenuConfigPage.cxx") + return; + // I cannot follow the ownership of OSQLParseNode's + if (fn == SRCDIR "/dbaccess/source/core/api/SingleSelectQueryComposer.cxx") + return; + if (fn == SRCDIR "/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx") + return; + // linked list + if (fn == SRCDIR "/formula/source/core/api/FormulaCompiler.cxx") + return; + // smuggling data around via SvxFontListItem + if (fn == SRCDIR "/extensions/source/propctrlr/fontdialog.cxx") + return; + // atomics + if (fn == SRCDIR "/sc/source/ui/docshell/documentlinkmgr.cxx") + return; + // finicky + if (fn == SRCDIR "/sc/source/core/data/stlpool.cxx") + return; + // macros + if (fn == SRCDIR "/sc/source/core/tool/autoform.cxx") + return; + // unsure about ownership + if (fn == SRCDIR "/xmlsecurity/source/framework/saxeventkeeperimpl.cxx") + return; + // ScTokenArray ownership complicated between this and the group + if (fn == SRCDIR "/sc/source/core/data/formulacell.cxx") + return; + // macros + if (fn == SRCDIR "/sw/source/core/doc/tblafmt.cxx") + return; + // more ScTokenArray + if (fn == SRCDIR "/sc/source/ui/unoobj/tokenuno.cxx") + return; + // SwDoc::DelTextFormatColl + if (fn == SRCDIR "/sw/source/core/doc/docfmt.cxx") + return; + // SwRootFrame::CalcFrameRects + if (fn == SRCDIR "/sw/source/core/layout/trvlfrm.cxx") + return; + // crazy code + if (fn == SRCDIR "/sw/source/core/undo/SwUndoPageDesc.cxx") + return; + // unsure about the SwLinePortion ownership + if (fn == SRCDIR "/sw/source/core/text/itrform2.cxx") + return; + // can't follow the ownership + if (fn == SRCDIR "/sw/source/filter/html/htmlatr.cxx") + return; + // SwTextFormatter::BuildMultiPortion complicated + if (fn == SRCDIR "/sw/source/core/text/pormulti.cxx") + return; + // SwXMLExport::ExportTableLines + if (fn == SRCDIR "/sw/source/filter/xml/xmltble.cxx") + return; + // SwPagePreview::~SwPagePreview + if (fn == SRCDIR "/sw/source/uibase/uiview/pview.cxx") + return; + // alloc/free routines for the hand constructed virtual function table + if (fn == SRCDIR "/sal/textenc/convertisciidevangari.cxx") + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/bridges/")) + return; + // bootstrap_map + if (fn == SRCDIR "/sal/rtl/bootstrap.cxx") + return; + // too complicated for my small brain + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/cppu/")) + return; + // linked list + if (fn == SRCDIR "/vcl/source/gdi/octree.cxx") + return; + // linked list + if (fn == SRCDIR "/vcl/source/filter/graphicfilter.cxx") + return; + // linked list + if (fn == SRCDIR "/svtools/source/control/ctrltool.cxx") + return; + // complicated + if (fn == SRCDIR "/sfx2/source/control/msgpool.cxx") + return; + // complicated + if (fn == SRCDIR "/svx/source/sdr/contact/objectcontact.cxx") + return; + // memory management in this module is a mess + if (fn == SRCDIR "/idlc/source/aststack.cxx") + return; + // complicated + if (fn == SRCDIR "/cui/source/customize/cfg.cxx") + return; + // linked list + if (fn == SRCDIR "/lotuswordpro/source/filter/lwpfribptr.cxx") + return; + // complicated + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/connectivity/source/drivers/file/")) + return; + // complicated + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/unodevtools/source/skeletonmaker/")) + return; + + llvm::StringRef parentName; + if (auto cxxMethodDecl = dyn_cast(functionDecl)) + { + parentName = cxxMethodDecl->getParent()->getName(); + } + + // no idea what is going on here + if (parentName == "ScChangeActionLinkEntry") + return; + // ok + if (parentName == "SfxItemSet" || parentName == "SfxItemPool") + return; + // linked list + if (parentName == "ScFunctionList" || parentName == "SwNodes" + || parentName == "SwUnoCursor" || parentName == "SortedResultSet" + || parentName == "Atom" || parentName == "RegionBand" || parentName == "WMFWriter" + || parentName == "Scheduler" || parentName == "OpenGLContext" + || parentName == "WizardDialog") + return; + // manual ref counting + if (parentName == "ScBroadcastAreaSlot") + return; + // complicated + if (any_equal(parentName, "SwFormatField", "FontPropertyBox", "SdFontPropertyBox", + "SwHTMLParser", "PDFWriterImpl", "SbiParser", "DictionaryList", "SwGlossaryHdl", "SwGlossaryGroupDlg")) + return; + // ok + if (any_equal(parentName, "SbTreeListBox")) + return; + + if (functionDecl->getIdentifier()) + { + auto name = functionDecl->getName(); + SmallString<256> buf; + if (!parentName.empty()) + name = (parentName + "::" + name).toStringRef(buf); + + // custom deleters + if (name == "Proxy_free" || name == "s_free" || name == "binuno_proxy_free") + return; + if (name == "SvpSalFrame::ReleaseGraphics") + return; + // don't feel like changing the API functions in registry + if (name == "createRegistry" || name == "openRegistry" || name == "closeRegistry" || name == "destroyRegistry" + || name == "reg_openRegistry") + return; + // linked list + if (any_equal(name, "TypeWriter::createBlop", "ImplDeleteConfigData", "Config::DeleteGroup", + "Config::DeleteKey", "E3dView::DoDepthArrange", + "DXFBlocks::Clear", "DXFTables::Clear", "DXFEntities::Clear", + "PSWriter::WritePS", "PSWriter::ImplWriteActions", "CUtList::Destroy", + "ScBroadcastAreaSlotMachine::UpdateBroadcastAreas")) + return; + // ok + if (any_equal(name, "write_uInt16s_FromOUString", "ProgressMonitor::removeText", + "StgDirEntry::SetSize", "UCBStorage::CopyStorageElement_Impl" + "OutputDevice::ImplDrawPolyPolygon", "OutputDevice::ImplDrawPolyPolygon", + "ImplListBox::InsertEntry", "Edit::dispose", + "ViewContact::deleteAllVOCs", "SfxViewFrame::ReleaseObjectShell_Impl", + "SfxViewFrame::SwitchToViewShell_Impl", "OfaSmartTagOptionsTabPage::ClearListBox", + "OfaSmartTagOptionsTabPage::FillItemSet", "doc_destroy", "lo_destroy", + "callColumnFormatDialog")) + return; + // very dodgy + if (any_equal(name, "UCBStorage::OpenStorage_Impl", "SdTransferable::GetData")) + return; + // complicated ownership + if (any_equal(name, "ParseCMAP", "OpenGLSalBitmap::CreateTexture", "X11SalGraphicsImpl::drawAlphaBitmap" + "SvEmbedTransferHelper::GetData", "ORoadmap::dispose", + "BrowseBox::SetMode", "ExportDialog::GetFilterData", "disposeComVariablesForBasic", + "ImpEditEngine::ImpRemoveParagraph", "FactoryImpl::createAdapter", + "SfxStateCache::SetVisibleState", "SfxBindings::QueryState", + "ViewContact::deleteAllVOCs", "SvxMSDffManager::ProcessObj", "SvEmbedTransferHelper::GetData", + "SvXMLExportPropertyMapper::Filter_", "SdXMLExport::ImpGetOrCreatePageMasterInfo", + "SfxDocumentDescPage::FillItemSet", "SfxCustomPropertiesPage::FillItemSet", + "SfxCmisPropertiesPage::FillItemSet", "SfxObjectShell::DoSaveCompleted", + "SfxObjectShell::DoSave_Impl", "SfxObjectShell::PreDoSaveAs_Impl", "SfxObjectShell::Save_Impl", + "SfxFrame::DoClose_Impl", "SfxBaseModel::load", + "SdrTextObj::TakeTextRect", "SdrTableObj::TakeTextRect", "SdrObjCustomShape::TakeTextRect", + "CellProperties::ItemSetChanged", "CellProperties::ItemChange", + "TableLayouter::SetBorder", "TableLayouter::ClearBorderLayout", + "ImpXPolygon::Resize", "SvxTextEditSourceImpl::GetBackgroundTextForwarder", + "Svx3DSceneObject::setPropertyValueImpl", "lcl_RemoveTextEditOutlinerViews", + "SdrObjEditView::SdrEndTextEdit", "SvxShape::_setPropertyValue", + "AccessibleShape::Init", "AccessibleCell::Init", + "SdrTableRtfExporter::WriteCell", "GalleryItem::_getPropertyValues", + "VMLExport::StartShape", "DrawingML::WriteText", + "MtfTools::DrawText", "FormulaTokenArray::RewriteMissing", + "OSQLParseNode::negateSearchCondition", "OSQLParseNodesContainer::clearAndDelete", + "SdFilter::GetLibrarySymbol", "SdPage::SetObjText", + "SdDrawDocument::InsertBookmarkAsPage", "SdDrawDocument::InsertBookmarkAsObject", + "SdDrawDocument::RemoveUnnecessaryMasterPages", + "ScTable::CopyConditionalFormat", "ScTable::ValidQuery", + "ScTable::SetOptimalHeight", "ScTable::SetOptimalHeightOnly", "ScCompiler::CompileString", + "ScProgress::DeleteInterpretProgress", "ScInterpreter::ScBase", + "UCBStorage::CopyStorageElement_Impl", "X11SalGraphicsImpl::drawAlphaBitmap", + "MasterPagesSelector::ClearPageSet", "View::IsPresObjSelected", + "SdDrawPagesAccess::remove", "SdMasterPagesAccess::remove", "View::InsertData", + "RemoteServer::execute", "Implementation::ReleaseOutlinerView", + "SwFormat::CopyAttrs", "FinitCore", "SwCursorShell::MoveFieldType", "SwExtraPainter::PaintExtra", + "SwMarginPortion::AdjustRight", "SwPaintQueue::Repaint", "SwTOXMgr::UpdateOrInsertTOX", + "SwBaseShell::Execute", "WW8Export::WriteSdrTextObj")) + return; + // complicated delete + if (name == "X11SalObject::CreateObject") + return; + } + + report( + DiagnosticsEngine::Warning, + "call to delete on a var, should be using std::unique_ptr", + deleteExpr->getBeginLoc()) + << deleteExpr->getSourceRange(); + report( + DiagnosticsEngine::Note, + "var is here", + varDecl->getBeginLoc()) + << varDecl->getSourceRange(); +} + +/** + * Look for DELETEZ expressions. + */ +void UseUniquePtr::CheckParenExpr(const FunctionDecl* functionDecl, const ParenExpr* parenExpr) +{ + auto binaryOp = dyn_cast(parenExpr->getSubExpr()); + if (!binaryOp || binaryOp->getOpcode() != BO_Comma) + return; + auto deleteExpr = dyn_cast(binaryOp->getLHS()); + if (!deleteExpr) + return; + CheckDeleteExpr(functionDecl, deleteExpr); +} + +void UseUniquePtr::CheckLoopDelete(const FunctionDecl* functionDecl, const Stmt* bodyStmt) +{ + if (auto deleteExpr = dyn_cast(bodyStmt)) + CheckLoopDelete(functionDecl, deleteExpr); + else if (auto compoundStmt = dyn_cast(bodyStmt)) + { + for (auto i = compoundStmt->body_begin(); i != compoundStmt->body_end(); ++i) + { + if (auto deleteExpr = dyn_cast(*i)) + CheckLoopDelete(functionDecl, deleteExpr); + } + } +} + +void UseUniquePtr::CheckLoopDelete(const FunctionDecl* functionDecl, const CXXDeleteExpr* deleteExpr) +{ + const MemberExpr* memberExpr = nullptr; + const VarDecl* varDecl = nullptr; + const Expr* subExpr = deleteExpr->getArgument(); + // drill down looking for a MemberExpr + for (;;) + { + subExpr = subExpr->IgnoreParens()->IgnoreImplicit(); + if ((memberExpr = dyn_cast(subExpr))) + { + if (memberExpr->getMemberDecl()->getName() == "first" || memberExpr->getMemberDecl()->getName() == "second") + { + subExpr = memberExpr->getBase(); + memberExpr = nullptr; + } + else + break; + } + else if (auto declRefExpr = dyn_cast(subExpr)) + { + if ((varDecl = dyn_cast(declRefExpr->getDecl()))) + break; + } + else if (auto arraySubscriptExpr = dyn_cast(subExpr)) + subExpr = arraySubscriptExpr->getBase(); + else if (auto cxxOperatorCallExpr = dyn_cast(subExpr)) + { + // look for deletes of an iterator object where the iterator is over a member field + if (auto declRefExpr = dyn_cast(cxxOperatorCallExpr->getArg(0)->IgnoreImplicit())) + { + if (auto iterVarDecl = dyn_cast(declRefExpr->getDecl())) + { + auto init = iterVarDecl->getInit(); + if (init) + { + init = init->IgnoreImplicit(); + if (auto x = dyn_cast(init)) + if (x->getNumArgs() == 1 + || (x->getNumArgs() >= 2 && isa(x->getArg(1)))) + { + init = x->getArg(0)->IgnoreImplicit(); + } + if (auto x = dyn_cast(init)) + init = x->getImplicitObjectArgument()->IgnoreParenImpCasts(); + if ((memberExpr = dyn_cast(init))) + break; + // look for deletes of an iterator object where the iterator is over a var + if (auto declRefExpr2 = dyn_cast(init)) + { + if ((varDecl = dyn_cast(declRefExpr2->getDecl()))) + break; + } + } + } + } + // look for deletes like "delete m_pField[0]" + if (cxxOperatorCallExpr->getOperator() == OO_Subscript) + { + subExpr = cxxOperatorCallExpr->getArg(0)->IgnoreImplicit(); + if ((memberExpr = dyn_cast(subExpr))) + break; + if (auto declRefExpr = dyn_cast(subExpr)) + { + if ((varDecl = dyn_cast(declRefExpr->getDecl()))) + break; + } + } + break; + } + else + break; + } + + if (memberExpr) + { + // OStorage_Impl::Commit very complicated ownership passing going on + if (fn == SRCDIR "/package/source/xstor/xstorage.cxx") + return; + // complicated + if (fn == SRCDIR "/vcl/source/gdi/print.cxx") + return; + // linked list + if (fn == SRCDIR "/basic/source/runtime/runtime.cxx") + return; + // complicated + if (fn == SRCDIR "/sw/source/core/bastyp/swcache.cxx") + return; + + CheckMemberDeleteExpr(functionDecl, deleteExpr, memberExpr, "rather manage this member with std::some_container>"); + } + + if (varDecl) + { + // ignore if the value for the var comes from somewhere else + if (varDecl->hasInit() && isa(varDecl->getInit()->IgnoreImpCasts())) + return; + + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/vcl/qa/")) + return; + // linked list + if (fn == SRCDIR "/registry/source/reflwrit.cxx") + return; + // linked list + if (fn == SRCDIR "/tools/source/generic/config.cxx") + return; + // linked lists + if (fn == SRCDIR "/vcl/source/gdi/regband.cxx") + return; + // linked lists + if (fn == SRCDIR "/vcl/source/gdi/regionband.cxx") + return; + // linked list + if (fn == SRCDIR "/vcl/source/gdi/octree.cxx") + return; + // linked list + if (fn == SRCDIR "/vcl/source/app/scheduler.cxx") + return; + // linked list + if (fn == SRCDIR "/vcl/source/filter/wmf/wmfwr.cxx") + return; + // linked list + if (fn == SRCDIR "/vcl/source/filter/graphicfilter.cxx") + return; + // valid code + if (fn == SRCDIR "/vcl/source/app/salvtables.cxx") + return; + // undo code is tricky + if (fn == SRCDIR "/svl/source/undo/undo.cxx") + return; + // subclass that messes with parent class in constructor/destructor, yuck + if (fn == SRCDIR "/svtools/source/contnr/imivctl1.cxx") + return; + // SQLParseNode + if (fn == SRCDIR "/connectivity/source/parse/sqlnode.cxx") + return; + // the whole svx model/contact/view thing confuses me + if (fn == SRCDIR "/svx/source/sdr/contact/viewcontact.cxx") + return; + if (fn == SRCDIR "/svx/source/sdr/contact/objectcontact.cxx") + return; + // no idea + if (fn == SRCDIR "/svx/source/unodialogs/textconversiondlgs/chinese_dictionarydialog.cxx") + return; + // SdrUndo stuff + if (fn == SRCDIR "/svx/source/svdraw/svdundo.cxx") + return; + // TODO the lazydelete stuff should probably just be ripped out altogether now that we have VclPtr + if (fn == SRCDIR "/vcl/source/helper/lazydelete.cxx") + return; + // linked list + if (fn == SRCDIR "/filter/source/graphicfilter/idxf/dxfblkrd.cxx") + return; + if (fn == SRCDIR "/filter/source/graphicfilter/idxf/dxftblrd.cxx") + return; + if (fn == SRCDIR "/lotuswordpro/source/filter/utlist.cxx") + return; + if (fn == SRCDIR "/lotuswordpro/source/filter/lwpfribptr.cxx") + return; + // valid + if (fn == SRCDIR "/sd/source/ui/sidebar/MasterPagesSelector.cxx") + return; + // linked list + if (fn == SRCDIR "/sd/source/filter/ppt/pptatom.cxx") + return; + // linked list + if (fn == SRCDIR "/sc/source/core/data/funcdesc.cxx") + return; + // linked list + if (fn == SRCDIR "/sw/source/core/crsr/crsrsh.cxx") + return; + // no idea + if (fn == SRCDIR "/sw/source/core/docnode/nodes.cxx") + return; + // linked list + if (fn == SRCDIR "/sw/source/core/unocore/unocrsr.cxx") + return; + // linked list + if (fn == SRCDIR "/filter/source/graphicfilter/idxf/dxfentrd.cxx") + return; + // linked list + if (fn == SRCDIR "/filter/source/graphicfilter/ios2met/ios2met.cxx") + return; + // sometimes owning, sometimes not + if (fn == SRCDIR "/sw/qa/core/Test-BigPtrArray.cxx") + return; + + report( + DiagnosticsEngine::Warning, + "loopdelete: rather manage this var with std::some_container>", + deleteExpr->getBeginLoc()) + << deleteExpr->getSourceRange(); + report( + DiagnosticsEngine::Note, + "var is here", + varDecl->getBeginLoc()) + << varDecl->getSourceRange(); + } +} + +void UseUniquePtr::CheckCXXForRangeStmt(const FunctionDecl* functionDecl, const CXXForRangeStmt* cxxForRangeStmt) +{ + CXXDeleteExpr const * deleteExpr = nullptr; + if (auto compoundStmt = dyn_cast(cxxForRangeStmt->getBody())) + { + for (auto i = compoundStmt->body_begin(); i != compoundStmt->body_end(); ++i) + if ((deleteExpr = dyn_cast(*i))) + break; + } + else + deleteExpr = dyn_cast(cxxForRangeStmt->getBody()); + if (!deleteExpr) + return; + + // check for delete of member + if (auto memberExpr = dyn_cast(cxxForRangeStmt->getRangeInit())) + { + auto fieldDecl = dyn_cast(memberExpr->getMemberDecl()); + if (!fieldDecl) + return; + + // appears to just randomly leak stuff, and it involves some lex/yacc stuff + if (fn == SRCDIR "/idlc/source/aststack.cxx") + return; + // complicated + if (fn == SRCDIR "/vcl/source/gdi/print.cxx") + return; + // sometimes it's an owning field, sometimes not + if (fn == SRCDIR "/i18npool/source/localedata/localedata.cxx") + return; + + CheckMemberDeleteExpr(functionDecl, deleteExpr, memberExpr, "rather manage this with std::some_container>"); + } + + // check for delete of var + if (auto declRefExpr = dyn_cast(cxxForRangeStmt->getRangeInit()->IgnoreParens()->IgnoreImplicit())) + { + auto varDecl = dyn_cast(declRefExpr->getDecl()); + if (!varDecl) + return; + + // don't feel like messing with this part of sfx2 + if (fn == SRCDIR "/sfx2/source/control/msgpool.cxx") + return; + if (fn == SRCDIR "/sfx2/source/doc/doctemplates.cxx") + return; + // lex/yacc + if (fn == SRCDIR "/hwpfilter/source/grammar.cxx") + return; + if (fn == SRCDIR "/hwpfilter/source/formula.cxx") + return; + // no idea why, but ui tests crash afterwards in weird ways + if (fn == SRCDIR "/svtools/source/control/roadmap.cxx") + return; + // sometimes it owns it, sometimes it does not + if (fn == SRCDIR "/dbaccess/source/ui/misc/WCopyTable.cxx") + return; + // SfxPoolItem array + if (fn == SRCDIR "/dbaccess/source/ui/misc/UITools.cxx") + return; + // SfxPoolItem array + if (fn == SRCDIR "/sw/source/core/bastyp/init.cxx") + return; + // SfxPoolItem array + if (fn == SRCDIR "/reportdesign/source/ui/misc/UITools.cxx") + return; + // SfxPoolItem array + if (fn == SRCDIR "/reportdesign/source/ui/report/ReportController.cxx") + return; + // complicated + if (fn == SRCDIR "/svx/source/sdr/contact/viewcontact.cxx") + return; + if (fn == SRCDIR "/svx/source/sdr/contact/objectcontact.cxx") + return; + + report( + DiagnosticsEngine::Warning, + "rather manage this var with std::some_container>", + deleteExpr->getBeginLoc()) + << deleteExpr->getSourceRange(); + report( + DiagnosticsEngine::Note, + "var is here", + varDecl->getBeginLoc()) + << varDecl->getSourceRange(); + } +} + +void UseUniquePtr::CheckMemberDeleteExpr(const FunctionDecl* functionDecl, const CXXDeleteExpr* deleteExpr, + const MemberExpr* memberExpr, StringRef message) +{ + // ignore union games + const FieldDecl* fieldDecl = dyn_cast(memberExpr->getMemberDecl()); + if (!fieldDecl) + return; + TagDecl const * td = dyn_cast(fieldDecl->getDeclContext()); + if (td->isUnion()) + return; + + // ignore calling delete on someone else's field + if (auto methodDecl = dyn_cast(functionDecl)) + if (fieldDecl->getParent() != methodDecl->getParent() ) + return; + + if (ignoreLocation(fieldDecl)) + return; + // to ignore things like the CPPUNIT macros + if (loplugin::hasPathnamePrefix(fn, WORKDIR "/")) + return; + // passes and stores pointers to member fields + if (fn == SRCDIR "/sot/source/sdstor/stgdir.hxx") + return; + // something platform-specific + if (fn == SRCDIR "/hwpfilter/source/htags.h") + return; + // passes pointers to member fields + if (fn == SRCDIR "/sd/inc/sdpptwrp.hxx") + return; + // @TODO intrusive linked-lists here, with some trickiness + if (fn == SRCDIR "/sw/source/filter/html/parcss1.hxx") + return; + // @TODO SwDoc has some weird ref-counting going on + if (fn == SRCDIR "/sw/inc/shellio.hxx") + return; + // @TODO it's sharing pointers with another class + if (fn == SRCDIR "/sc/inc/formulacell.hxx") + return; + // some weird stuff going on here around struct Entity + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sax/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/include/sax/")) + return; + // manipulation of tree structures ie. StgAvlNode, don't lend themselves to std::unique_ptr + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sot/")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/include/sot/")) + return; + // the std::vector is being passed to another class + if (fn == SRCDIR "/sfx2/source/explorer/nochaos.cxx") + return; + auto tc = loplugin::TypeCheck(fieldDecl->getType()); + // these sw::Ring based classes do not lend themselves to std::unique_ptr management + if (tc.Pointer().Class("SwNodeIndex").GlobalNamespace() || tc.Pointer().Class("SwShellTableCursor").GlobalNamespace() + || tc.Pointer().Class("SwBlockCursor").GlobalNamespace() || tc.Pointer().Class("SwVisibleCursor").GlobalNamespace() + || tc.Pointer().Class("SwShellCursor").GlobalNamespace()) + return; + // there is a loop in ~ImplPrnQueueList deleting stuff on a global data structure + if (fn == SRCDIR "/vcl/inc/print.h") + return; + // painful linked list + if (fn == SRCDIR "/basic/source/inc/runtime.hxx") + return; + // not sure how the node management is working here + if (fn == SRCDIR "/i18npool/source/localedata/saxparser.cxx") + return; + // has a pointer that it only sometimes owns + if (fn == SRCDIR "/editeng/source/editeng/impedit.hxx") + return; + + report( + DiagnosticsEngine::Warning, + message, + deleteExpr->getBeginLoc()) + << deleteExpr->getSourceRange(); + report( + DiagnosticsEngine::Note, + "member is here", + fieldDecl->getBeginLoc()) + << fieldDecl->getSourceRange(); +} + +bool UseUniquePtr::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + if (ignoreLocation(functionDecl)) + return true; + + auto oldCurrent = mpCurrentFunctionDecl; + mpCurrentFunctionDecl = functionDecl; + bool ret = RecursiveASTVisitor::TraverseFunctionDecl(functionDecl); + mpCurrentFunctionDecl = oldCurrent; + + return ret; +} + +bool UseUniquePtr::TraverseCXXMethodDecl(CXXMethodDecl* methodDecl) +{ + if (ignoreLocation(methodDecl)) + return true; + + auto oldCurrent = mpCurrentFunctionDecl; + mpCurrentFunctionDecl = methodDecl; + bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(methodDecl); + mpCurrentFunctionDecl = oldCurrent; + + return ret; +} + +bool UseUniquePtr::TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl* methodDecl) +{ + if (ignoreLocation(methodDecl)) + return true; + + auto oldCurrent = mpCurrentFunctionDecl; + mpCurrentFunctionDecl = methodDecl; + bool ret = RecursiveASTVisitor::TraverseCXXDeductionGuideDecl(methodDecl); + mpCurrentFunctionDecl = oldCurrent; + + return ret; +} + +bool UseUniquePtr::TraverseCXXConstructorDecl(CXXConstructorDecl* methodDecl) +{ + if (ignoreLocation(methodDecl)) + return true; + + auto oldCurrent = mpCurrentFunctionDecl; + mpCurrentFunctionDecl = methodDecl; + bool ret = RecursiveASTVisitor::TraverseCXXConstructorDecl(methodDecl); + mpCurrentFunctionDecl = oldCurrent; + + return ret; +} + +bool UseUniquePtr::TraverseCXXConversionDecl(CXXConversionDecl* methodDecl) +{ + if (ignoreLocation(methodDecl)) + return true; + + auto oldCurrent = mpCurrentFunctionDecl; + mpCurrentFunctionDecl = methodDecl; + bool ret = RecursiveASTVisitor::TraverseCXXConversionDecl(methodDecl); + mpCurrentFunctionDecl = oldCurrent; + + return ret; +} + +bool UseUniquePtr::TraverseCXXDestructorDecl(CXXDestructorDecl* methodDecl) +{ + if (ignoreLocation(methodDecl)) + return true; + + auto oldCurrent = mpCurrentFunctionDecl; + mpCurrentFunctionDecl = methodDecl; + bool ret = RecursiveASTVisitor::TraverseCXXDestructorDecl(methodDecl); + mpCurrentFunctionDecl = oldCurrent; + + return ret; +} + +bool UseUniquePtr::TraverseConstructorInitializer(CXXCtorInitializer * ctorInit) +{ + if (!ctorInit->getSourceLocation().isValid() || ignoreLocation(ctorInit->getSourceLocation())) + return true; + if (!ctorInit->getMember()) + return true; + if (!loplugin::TypeCheck(ctorInit->getMember()->getType()).Class("unique_ptr").StdNamespace()) + return true; + auto constructExpr = dyn_cast_or_null(ctorInit->getInit()); + if (!constructExpr || constructExpr->getNumArgs() == 0) + return true; + auto init = constructExpr->getArg(0)->IgnoreImpCasts(); + if (!isa(init)) + return true; + + StringRef fn = getFilenameOfLocation(compiler.getSourceManager().getSpellingLoc(ctorInit->getSourceLocation())); + // don't feel like fiddling with the yacc parser + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/idlc/")) + return true; + // cannot change URE + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/cppu/source/helper/purpenv/helper_purpenv_Environment.cxx")) + return true; + + report( + DiagnosticsEngine::Warning, + "should be passing via std::unique_ptr param", + ctorInit->getSourceLocation()) + << ctorInit->getSourceRange(); + return RecursiveASTVisitor::TraverseConstructorInitializer(ctorInit); +} + +// Only checks for calls to delete on a pointer param +bool UseUniquePtr::VisitCXXDeleteExpr(const CXXDeleteExpr* deleteExpr) +{ + if (!mpCurrentFunctionDecl) + return true; + if (ignoreLocation(mpCurrentFunctionDecl)) + return true; + if (isInUnoIncludeFile(mpCurrentFunctionDecl->getCanonicalDecl()->getBeginLoc())) + return true; + auto declRefExpr = dyn_cast(deleteExpr->getArgument()->IgnoreParenImpCasts()->IgnoreImplicit()); + if (!declRefExpr) + return true; + if (auto parmVarDecl = dyn_cast(declRefExpr->getDecl())) + CheckDeleteParmVar(deleteExpr, parmVarDecl); + else if (auto varDecl = dyn_cast(declRefExpr->getDecl())) + CheckDeleteLocalVar(mpCurrentFunctionDecl, deleteExpr, varDecl); + return true; +} + +void UseUniquePtr::CheckDeleteParmVar(const CXXDeleteExpr* deleteExpr, const ParmVarDecl* ) +{ + if (mpCurrentFunctionDecl->getIdentifier()) + { + auto name = mpCurrentFunctionDecl->getName(); + if (name == "delete_IncludesCollection" || name == "convertName" + || name == "createNamedType" + || name == "typelib_typedescriptionreference_release" || name == "deleteExceptions" + || name == "uno_threadpool_destroy" + || name == "AddRanges_Impl" + || name == "DestroySalInstance" + || name == "ImplHandleUserEvent" + || name == "releaseDecimalPtr" // TODO, basic + || name == "replaceAndReset" // TODO, connectivity + || name == "intrusive_ptr_release" + || name == "FreeParaList" + || name == "DeleteSdrUndoAction" // TODO, sc + || name == "lcl_MergeGCBox" || name == "lcl_MergeGCLine" || name == "lcl_DelHFFormat") + return; + } + if (auto cxxMethodDecl = dyn_cast(mpCurrentFunctionDecl)) + { + auto parentName = cxxMethodDecl->getParent()->getName(); + // include/o3tl/deleter.hxx + if (parentName == "default_delete") + return; + // TODO Bitmap::ReleaseAccess + // Tricky because it reverberates through other code and requires that BitmapWriteAccess move into /include again + if (parentName == "Bitmap") + return; + // TODO virtual ones are much trickier, leave for later + if (cxxMethodDecl->isVirtual()) + return; + // sw/inc/unobaseclass.hxx holds SolarMutex while deleting + if (parentName == "UnoImplPtrDeleter") + return; + } + + // StgAvlNode::Remove + if (fn == SRCDIR "/sot/source/sdstor/stgavl.cxx") + return; + // SfxItemPool::ReleaseDefaults and SfxItemPool::Free + if (fn == SRCDIR "/svl/source/items/itempool.cxx") + return; + // SwContourCache + if (fn == SRCDIR "/sw/source/core/text/txtfly.cxx") + return; + // too messy to cope with the SQL parser + if (fn == SRCDIR "/connectivity/source/parse/sqlnode.cxx") + return; + // I can't figure out the ownership of the SfxMedium in the call site(s) + if (fn == SRCDIR "/sfx2/source/doc/sfxbasemodel.cxx") + return; + // pointer passed via IMPL_LINK + if (fn == SRCDIR "/sfx2/source/control/dispatch.cxx") + return; + // NavigatorTreeModel::Remove + if (fn == SRCDIR "/svx/source/form/navigatortreemodel.cxx") + return; + // SdrModel::AddUndo + if (fn == SRCDIR "/svx/source/svdraw/svdmodel.cxx") + return; + // undo callback + if (fn == SRCDIR "/basctl/source/basicide/baside3.cxx") + return; + // ActualizeProgress::TimeoutHdl + if (fn == SRCDIR "/cui/source/dialogs/cuigaldlg.cxx") + return; + // ToolbarSaveInData::RemoveToolbar + if (fn == SRCDIR "/cui/source/customize/cfg.cxx") + return; + // OStorage_Impl::RemoveElement very complicated ownership passing going on + if (fn == SRCDIR "/package/source/xstor/xstorage.cxx") + return; + // actually held via shared_ptr, uses protected deleter object + if (fn == SRCDIR "/sd/source/ui/framework/tools/FrameworkHelper.cxx") + return; + // actually held via shared_ptr, uses protected deleter object + if (fn == SRCDIR "/sd/source/ui/presenter/CanvasUpdateRequester.cxx") + return; + // actually held via shared_ptr, uses protected deleter object + if (fn == SRCDIR "/sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx") + return; + // actually held via shared_ptr, uses protected deleter object + if (fn == SRCDIR "/sd/source/ui/sidebar/MasterPageContainer.cxx") + return; + // actually held via shared_ptr, uses protected deleter object + if (fn == SRCDIR "/sd/source/ui/tools/TimerBasedTaskExecution.cxx") + return; + // actually held via shared_ptr, uses protected deleter object + if (fn == SRCDIR "/sd/source/ui/view/ViewShellImplementation.cxx") + return; + // ScBroadcastAreaSlot::StartListeningArea manual ref-counting of ScBroadcastArea + if (fn == SRCDIR "/sc/source/core/data/bcaslot.cxx") + return; + // ScDrawLayer::AddCalcUndo undo stuff + if (fn == SRCDIR "/sc/source/core/data/drwlayer.cxx") + return; + // ScTable::SetFormulaCell + if (fn == SRCDIR "/sc/source/core/data/table2.cxx") + return; + // ScDocument::SetFormulaCell + if (fn == SRCDIR "/sc/source/core/data/documen2.cxx") + return; + // RemoveEditAttribsHandler, stored in mdds block + if (fn == SRCDIR "/sc/source/core/data/column2.cxx") + return; + // just turns into a mess + if (fn == SRCDIR "/sc/source/ui/Accessibility/AccessibleDocument.cxx") + return; + // SwCache::DeleteObj, linked list + if (fn == SRCDIR "/sw/source/core/bastyp/swcache.cxx") + return; + // SAXEventKeeperImpl::smashBufferNode + if (fn == SRCDIR "/xmlsecurity/source/framework/saxeventkeeperimpl.cxx") + return; + // SwDoc::DeleteExtTextInput + if (fn == SRCDIR "/sw/source/core/doc/extinput.cxx") + return; + // SwDoc::DelSectionFormat + if (fn == SRCDIR "/sw/source/core/docnode/ndsect.cxx") + return; + // SwFrame::DestroyFrame + if (fn == SRCDIR "/sw/source/core/layout/ssfrm.cxx") + return; + // SwGluePortion::Join + if (fn == SRCDIR "/sw/source/core/text/porglue.cxx") + return; + // SwDoc::DelFrameFormat + if (fn == SRCDIR "/sw/source/core/doc/docfmt.cxx") + return; + // SwTextAttr::Destroy + if (fn == SRCDIR "/sw/source/core/txtnode/txatbase.cxx") + return; + // IMPL_LINK( SwDoc, AddDrawUndo, SdrUndoAction *, pUndo, void ) + if (fn == SRCDIR "/sw/source/core/undo/undraw.cxx") + return; + // SwHTMLParser::EndAttr + if (fn == SRCDIR "/sw/source/filter/html/swhtml.cxx") + return; + // SwGlossaryHdl::Expand sometimes the pointer is owned, sometimes it is not + if (fn == SRCDIR "/sw/source/uibase/dochdl/gloshdl.cxx") + return; + // SwWrtShell::Insert only owned sometimes + if (fn == SRCDIR "/sw/source/uibase/wrtsh/wrtsh1.cxx") + return; + // NodeArrayDeleter + if (fn == SRCDIR "/unoxml/source/rdf/librdf_repository.cxx") + return; + // SmCursor::LineToList ran out of enthusiasm to rework the node handling + if (fn == SRCDIR "/starmath/source/cursor.cxx") + return; + // XMLEventOASISTransformerContext::FlushEventMap + if (fn == SRCDIR "/xmloff/source/transform/EventOASISTContext.cxx") + return; + // XMLEventOOoTransformerContext::FlushEventMap + if (fn == SRCDIR "/xmloff/source/transform/EventOOoTContext.cxx") + return; + // SbiProcDef::Match + if (fn == SRCDIR "/basic/source/comp/symtbl.cxx") + return; + + /* + Sometimes we can pass the param as std::unique_ptr& or std::unique_ptr, sometimes the method + just needs to be inlined, which normally exposes more simplification. + */ + report( + DiagnosticsEngine::Warning, + "calling delete on a pointer param, should be either allowlisted or simplified", + deleteExpr->getBeginLoc()) + << deleteExpr->getSourceRange(); +} + + +loplugin::Plugin::Registration< UseUniquePtr > X("useuniqueptr", false); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/vclwidgets.cxx b/compilerplugins/clang/vclwidgets.cxx new file mode 100644 index 000000000..2f5d6c57a --- /dev/null +++ b/compilerplugins/clang/vclwidgets.cxx @@ -0,0 +1,876 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include "clang/AST/CXXInheritance.h" + +// Final goal: Checker for VCL widget references. Makes sure that VCL Window subclasses are properly referenced counted and dispose()'ed. +// +// But at the moment it just finds subclasses of Window which are not heap-allocated +// +// TODO do I need to check for local and static variables, too ? +// TODO when we have a dispose() method, verify that the dispose() methods releases all of the Window references +// TODO when we have a dispose() method, verify that it calls the super-class dispose() method at some point. + +namespace { + +class VCLWidgets: + public loplugin::FilteringPlugin +{ +public: + explicit VCLWidgets(loplugin::InstantiationData const & data): FilteringPlugin(data) + {} + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool shouldVisitTemplateInstantiations () const { return true; } + + bool VisitVarDecl(const VarDecl *); + bool VisitFieldDecl(const FieldDecl *); + bool VisitParmVarDecl(const ParmVarDecl *); + bool VisitFunctionDecl(const FunctionDecl *); + bool VisitCXXDestructorDecl(const CXXDestructorDecl *); + bool VisitCXXDeleteExpr(const CXXDeleteExpr *); + bool VisitCallExpr(const CallExpr *); + bool VisitDeclRefExpr(const DeclRefExpr *); + bool VisitCXXConstructExpr(const CXXConstructExpr *); + bool VisitBinaryOperator(const BinaryOperator *); +private: + void checkAssignmentForVclPtrToRawConversion(const SourceLocation& sourceLoc, const clang::Type* lhsType, const Expr* rhs); + bool isDisposeCallingSuperclassDispose(const CXXMethodDecl* pMethodDecl); + bool mbCheckingMemcpy = false; +}; + +#define BASE_REF_COUNTED_CLASS "VclReferenceBase" + +bool BaseCheckNotWindowSubclass(const CXXRecordDecl *BaseDefinition) { + return !loplugin::DeclCheck(BaseDefinition).Class(BASE_REF_COUNTED_CLASS) + .GlobalNamespace(); +} + +bool isDerivedFromVclReferenceBase(const CXXRecordDecl *decl) { + if (!decl) + return false; + if (loplugin::DeclCheck(decl).Class(BASE_REF_COUNTED_CLASS) + .GlobalNamespace()) + { + return true; + } + if (!decl->hasDefinition()) { + return false; + } + if (// not sure what hasAnyDependentBases() does, + // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1 + !decl->hasAnyDependentBases() && + !decl->forallBases(BaseCheckNotWindowSubclass)) { + return true; + } + return false; +} + +bool containsVclReferenceBaseSubclass(const clang::Type* pType0); + +bool containsVclReferenceBaseSubclass(const QualType& qType) { + auto check = loplugin::TypeCheck(qType); + if (check.Class("ScopedVclPtr").GlobalNamespace() + || check.Class("ScopedVclPtrInstance").GlobalNamespace() + || check.Class("VclPtr").GlobalNamespace() + || check.Class("VclPtrInstance").GlobalNamespace()) + { + return false; + } + return containsVclReferenceBaseSubclass(qType.getTypePtr()); +} + +bool containsVclReferenceBaseSubclass(const clang::Type* pType0) { + if (!pType0) + return false; + const clang::Type* pType = pType0->getUnqualifiedDesugaredType(); + if (!pType) + return false; + const CXXRecordDecl* pRecordDecl = pType->getAsCXXRecordDecl(); + if (pRecordDecl) { + const ClassTemplateSpecializationDecl* pTemplate = dyn_cast(pRecordDecl); + if (pTemplate) { + auto check = loplugin::DeclCheck(pTemplate); + if (check.Class("VclStatusListener").GlobalNamespace()) { + return false; + } + bool link = bool(check.Class("Link").GlobalNamespace()); + for(unsigned i=0; igetTemplateArgs().size(); ++i) { + const TemplateArgument& rArg = pTemplate->getTemplateArgs()[i]; + if (rArg.getKind() == TemplateArgument::ArgKind::Type && + containsVclReferenceBaseSubclass(rArg.getAsType())) + { + // OK for first template argument of tools/link.hxx Link + // to be a Window-derived pointer: + if (!link || i != 0) { + return true; + } + } + } + } + } + if (pType->isPointerType()) { + QualType pointeeType = pType->getPointeeType(); + return containsVclReferenceBaseSubclass(pointeeType); + } else if (pType->isArrayType()) { + const clang::ArrayType* pArrayType = dyn_cast(pType); + QualType elementType = pArrayType->getElementType(); + return containsVclReferenceBaseSubclass(elementType); + } else { + return isDerivedFromVclReferenceBase(pRecordDecl); + } +} + +bool VCLWidgets::VisitCXXDestructorDecl(const CXXDestructorDecl* pCXXDestructorDecl) +{ + if (ignoreLocation(pCXXDestructorDecl)) { + return true; + } + if (!pCXXDestructorDecl->isThisDeclarationADefinition()) { + return true; + } + const CXXRecordDecl * pRecordDecl = pCXXDestructorDecl->getParent(); + // ignore + if (loplugin::DeclCheck(pRecordDecl).Class(BASE_REF_COUNTED_CLASS) + .GlobalNamespace()) + { + return true; + } + // check if this class is derived from VclReferenceBase + if (!isDerivedFromVclReferenceBase(pRecordDecl)) { + return true; + } + // check if we have any VclPtr<> fields + bool bFoundVclPtrField = false; + for(auto fieldDecl = pRecordDecl->field_begin(); + fieldDecl != pRecordDecl->field_end(); ++fieldDecl) + { + const RecordType *pFieldRecordType = fieldDecl->getType()->getAs(); + if (pFieldRecordType) { + if (loplugin::DeclCheck(pFieldRecordType->getDecl()) + .Class("VclPtr").GlobalNamespace()) + { + bFoundVclPtrField = true; + break; + } + } + } + // check if there is a dispose() method + bool bFoundDispose = false; + for(auto methodDecl = pRecordDecl->method_begin(); + methodDecl != pRecordDecl->method_end(); ++methodDecl) + { + if (methodDecl->isInstance() && methodDecl->param_size()==0 + && loplugin::DeclCheck(*methodDecl).Function("dispose")) + { + bFoundDispose = true; + break; + } + } + const CompoundStmt *pCompoundStatement = dyn_cast_or_null(pCXXDestructorDecl->getBody()); + // having an empty body and no dispose() method is fine + if (!bFoundVclPtrField && !bFoundDispose && (!pCompoundStatement || pCompoundStatement->size() == 0)) { + return true; + } + if (bFoundVclPtrField && (!pCompoundStatement || pCompoundStatement->size() == 0)) { + report( + DiagnosticsEngine::Warning, + BASE_REF_COUNTED_CLASS " subclass with VclPtr field must call disposeOnce() from its destructor", + pCXXDestructorDecl->getBeginLoc()) + << pCXXDestructorDecl->getSourceRange(); + return true; + } + // Check that the destructor for a BASE_REF_COUNTED_CLASS subclass either + // only calls disposeOnce() or, if !bFoundVclPtrField, does nothing at all: + bool bOk = false; + if (pCompoundStatement) { + bool bFoundDisposeOnce = false; + int nNumExtraStatements = 0; + for (auto i = pCompoundStatement->body_begin(); + i != pCompoundStatement->body_end(); ++i) + { + //TODO: The below erroneously also skips past entire statements like + // + // assert(true), ...; + // + auto skip = false; + for (auto loc = (*i)->getBeginLoc(); + compiler.getSourceManager().isMacroBodyExpansion(loc); + loc = compiler.getSourceManager().getImmediateMacroCallerLoc( + loc)) + { + auto const name = Lexer::getImmediateMacroName( + loc, compiler.getSourceManager(), compiler.getLangOpts()); + if (name == "SAL_DEBUG" || name == "assert") { + skip = true; + break; + } + } + if (skip) { + continue; + } + if (auto const pCallExpr = dyn_cast(*i)) { + if( const FunctionDecl* func = pCallExpr->getDirectCallee()) { + if( func->getNumParams() == 0 && func->getIdentifier() != NULL + && ( func->getName() == "disposeOnce" )) { + bFoundDisposeOnce = true; + continue; + } + } + } + nNumExtraStatements++; + } + bOk = (bFoundDisposeOnce || !bFoundVclPtrField) + && nNumExtraStatements == 0; + } + if (!bOk) { + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc( + pCXXDestructorDecl->getBeginLoc()); + StringRef filename = getFilenameOfLocation(spellingLocation); + if ( !(loplugin::isSamePathname(filename, SRCDIR "/vcl/source/window/window.cxx")) + && !(loplugin::isSamePathname(filename, SRCDIR "/vcl/source/gdi/virdev.cxx")) + && !(loplugin::isSamePathname(filename, SRCDIR "/vcl/qa/cppunit/lifecycle.cxx")) + && !(loplugin::isSamePathname(filename, SRCDIR "/sfx2/source/dialog/tabdlg.cxx")) ) + { + report( + DiagnosticsEngine::Warning, + BASE_REF_COUNTED_CLASS " subclass should have nothing in its destructor but a call to disposeOnce()", + pCXXDestructorDecl->getBeginLoc()) + << pCXXDestructorDecl->getSourceRange(); + } + } + return true; +} + +bool VCLWidgets::VisitBinaryOperator(const BinaryOperator * binaryOperator) +{ + if (ignoreLocation(binaryOperator)) { + return true; + } + if ( !binaryOperator->isAssignmentOp() ) { + return true; + } + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc( + binaryOperator->getBeginLoc()); + checkAssignmentForVclPtrToRawConversion(spellingLocation, binaryOperator->getLHS()->getType().getTypePtr(), binaryOperator->getRHS()); + return true; +} + +// Look for places where we are accidentally assigning a returned-by-value VclPtr to a T*, which generally +// ends up in a use-after-free. +void VCLWidgets::checkAssignmentForVclPtrToRawConversion(const SourceLocation& spellingLocation, const clang::Type* lhsType, const Expr* rhs) +{ + if (!lhsType || !isa(lhsType)) { + return; + } + if (!rhs) { + return; + } + StringRef filename = getFilenameOfLocation(spellingLocation); + if (loplugin::isSamePathname(filename, SRCDIR "/include/rtl/ref.hxx")) { + return; + } + const CXXRecordDecl* pointeeClass = lhsType->getPointeeType()->getAsCXXRecordDecl(); + if (!isDerivedFromVclReferenceBase(pointeeClass)) { + return; + } + + // if we have T* on the LHS and VclPtr on the RHS, we expect to see either + // an ImplicitCastExpr + // or an ExprWithCleanups and then an ImplicitCastExpr + if (auto implicitCastExpr = dyn_cast(rhs)) { + if (implicitCastExpr->getCastKind() != CK_UserDefinedConversion) { + return; + } + rhs = rhs->IgnoreCasts(); + } else if (auto exprWithCleanups = dyn_cast(rhs)) { + if (auto implicitCastExpr = dyn_cast(exprWithCleanups->getSubExpr())) { + if (implicitCastExpr->getCastKind() != CK_UserDefinedConversion) { + return; + } + rhs = exprWithCleanups->IgnoreCasts(); + } else { + return; + } + } else { + return; + } + if (isa(rhs)) { + return; + } + if (isa(rhs)) { + return; + } + + // ignore assignments from a member field to a local variable, to avoid unnecessary refcounting traffic + if (auto callExpr = dyn_cast(rhs)) { + if (auto calleeMemberExpr = dyn_cast(callExpr->getCallee())) { + if ((calleeMemberExpr = dyn_cast(calleeMemberExpr->getBase()->IgnoreImpCasts()))) { + if (isa(calleeMemberExpr->getMemberDecl())) { + return; + } + } + } + } + + // ignore assignments from a local variable to a local variable, to avoid unnecessary refcounting traffic + if (auto callExpr = dyn_cast(rhs)) { + if (auto calleeMemberExpr = dyn_cast(callExpr->getCallee())) { + if (auto declRefExpr = dyn_cast(calleeMemberExpr->getBase()->IgnoreImpCasts())) { + if (isa(declRefExpr->getDecl())) { + return; + } + } + } + } + if (auto declRefExpr = dyn_cast(rhs->IgnoreImpCasts())) { + if (isa(declRefExpr->getDecl())) { + return; + } + } + + report( + DiagnosticsEngine::Warning, + "assigning a returned-by-value VclPtr to a T* variable is dodgy, should be assigned to a VclPtr. If you know that the RHS does not return a newly created T, then add a '.get()' to the RHS", + rhs->getSourceRange().getBegin()) + << rhs->getSourceRange(); +} + +bool VCLWidgets::VisitVarDecl(const VarDecl * pVarDecl) { + if (ignoreLocation(pVarDecl)) { + return true; + } + if (isa(pVarDecl)) { + return true; + } + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc( + pVarDecl->getBeginLoc()); + if (pVarDecl->getInit()) { + checkAssignmentForVclPtrToRawConversion(spellingLocation, pVarDecl->getType().getTypePtr(), pVarDecl->getInit()); + } + StringRef aFileName = getFilenameOfLocation(spellingLocation); + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/vcl/vclptr.hxx")) + return true; + if (loplugin::isSamePathname(aFileName, SRCDIR "/vcl/source/window/layout.cxx")) + return true; + // allowlist the valid things that can contain pointers. + // It is containing stuff like std::unique_ptr we get worried + if (pVarDecl->getType()->isArrayType()) { + return true; + } + auto tc = loplugin::TypeCheck(pVarDecl->getType()); + if (tc.Pointer() + || tc.Class("map").StdNamespace() + || tc.Class("multimap").StdNamespace() + || tc.Class("vector").StdNamespace() + || tc.Class("list").StdNamespace() + || tc.Class("mem_fun1_t").StdNamespace() + // registration template thing, doesn't actually allocate anything we need to care about + || tc.Class("OMultiInstanceAutoRegistration").Namespace("compmodule").GlobalNamespace()) + { + return true; + } + // Apparently I should be doing some kind of lookup for a partial specialisations of std::iterator_traits to see if an + // object is an iterator, but that sounds like too much work + auto t = pVarDecl->getType().getDesugaredType(compiler.getASTContext()); + std::string s = t.getAsString(); + if (s.find("iterator") != std::string::npos + || loplugin::TypeCheck(t).Class("__wrap_iter").StdNamespace()) + { + return true; + } + // std::pair seems to show up in whacky ways in clang's AST. Sometimes it's a class, sometimes it's a typedef, and sometimes + // it's an ElaboratedType (whatever that is) + if (s.find("pair") != std::string::npos) { + return true; + } + + if (containsVclReferenceBaseSubclass(pVarDecl->getType())) { + report( + DiagnosticsEngine::Warning, + BASE_REF_COUNTED_CLASS " subclass %0 should be wrapped in VclPtr", + pVarDecl->getLocation()) + << pVarDecl->getType() << pVarDecl->getSourceRange(); + return true; + } + return true; +} + +bool VCLWidgets::VisitFieldDecl(const FieldDecl * fieldDecl) { + if (ignoreLocation(fieldDecl)) { + return true; + } + StringRef aFileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(fieldDecl->getBeginLoc())); + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/vcl/vclptr.hxx")) + return true; + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/rtl/ref.hxx")) + return true; + if (loplugin::isSamePathname(aFileName, SRCDIR "/include/o3tl/enumarray.hxx")) + return true; + if (loplugin::isSamePathname(aFileName, SRCDIR "/vcl/source/window/layout.cxx")) + return true; + if (fieldDecl->isBitField()) { + return true; + } + const CXXRecordDecl *pParentRecordDecl = isa(fieldDecl->getDeclContext()) ? dyn_cast(fieldDecl->getParent()) : nullptr; + if (loplugin::DeclCheck(pParentRecordDecl).Class("VclPtr") + .GlobalNamespace()) + { + return true; + } + if (containsVclReferenceBaseSubclass(fieldDecl->getType())) { + // have to ignore this for now, nasty reverse dependency from tools->vcl + auto check = loplugin::DeclCheck(pParentRecordDecl); + if (!(check.Struct("ImplErrorContext").GlobalNamespace() + || check.Class("ScHFEditPage").GlobalNamespace())) + { + report( + DiagnosticsEngine::Warning, + BASE_REF_COUNTED_CLASS " subclass %0 declared as a pointer member, should be wrapped in VclPtr", + fieldDecl->getLocation()) + << fieldDecl->getType() << fieldDecl->getSourceRange(); + if (auto parent = dyn_cast(fieldDecl->getParent())) { + report( + DiagnosticsEngine::Note, + "template field here", + parent->getPointOfInstantiation()); + } + return true; + } + } + const RecordType *recordType = fieldDecl->getType()->getAs(); + if (recordType == nullptr) { + return true; + } + const CXXRecordDecl *recordDecl = dyn_cast(recordType->getDecl()); + if (recordDecl == nullptr) { + return true; + } + + // check if this field is derived fromVclReferenceBase + if (isDerivedFromVclReferenceBase(recordDecl)) { + report( + DiagnosticsEngine::Warning, + BASE_REF_COUNTED_CLASS " subclass allocated as a class member, should be allocated via VclPtr", + fieldDecl->getLocation()) + << fieldDecl->getSourceRange(); + } + + // If this field is a VclPtr field, then the class MUST have a dispose method + if (pParentRecordDecl && isDerivedFromVclReferenceBase(pParentRecordDecl) + && loplugin::DeclCheck(recordDecl).Class("VclPtr").GlobalNamespace()) + { + bool bFoundDispose = false; + for(auto methodDecl = pParentRecordDecl->method_begin(); + methodDecl != pParentRecordDecl->method_end(); ++methodDecl) + { + if (methodDecl->isInstance() && methodDecl->param_size()==0 + && loplugin::DeclCheck(*methodDecl).Function("dispose")) + { + bFoundDispose = true; + break; + } + } + if (!bFoundDispose) { + report( + DiagnosticsEngine::Warning, + BASE_REF_COUNTED_CLASS " subclass with a VclPtr field MUST override dispose() (and call its superclass dispose() as the last thing it does)", + fieldDecl->getLocation()) + << fieldDecl->getSourceRange(); + } + if (!pParentRecordDecl->hasUserDeclaredDestructor()) { + report( + DiagnosticsEngine::Warning, + BASE_REF_COUNTED_CLASS " subclass with a VclPtr field MUST have a user-provided destructor (that calls disposeOnce())", + fieldDecl->getLocation()) + << fieldDecl->getSourceRange(); + } + } + + return true; +} + +bool VCLWidgets::VisitParmVarDecl(ParmVarDecl const * pvDecl) +{ + if (ignoreLocation(pvDecl)) { + return true; + } + // ignore the stuff in the VclPtr template class + const CXXMethodDecl *pMethodDecl = dyn_cast(pvDecl->getDeclContext()); + if (loplugin::DeclCheck(pMethodDecl).MemberFunction().Class("VclPtr") + .GlobalNamespace()) + { + return true; + } + // we exclude this method in VclBuilder because it's so useful to have it like this + auto check = loplugin::DeclCheck(pMethodDecl).Function("get"); + if (check.Class("VclBuilder").GlobalNamespace() + || check.Class("VclBuilderContainer").GlobalNamespace()) + { + return true; + } + return true; +} + + +static void findDisposeAndClearStatements(std::set& aVclPtrFields, const Stmt *pStmt) +{ + if (!pStmt) + return; + if (isa(pStmt)) { + const CompoundStmt *pCompoundStatement = dyn_cast(pStmt); + for (auto i = pCompoundStatement->body_begin(); + i != pCompoundStatement->body_end(); ++i) + { + findDisposeAndClearStatements(aVclPtrFields, *i); + } + return; + } + if (isa(pStmt)) { + findDisposeAndClearStatements(aVclPtrFields, dyn_cast(pStmt)->getBody()); + return; + } + if (isa(pStmt)) { + findDisposeAndClearStatements(aVclPtrFields, dyn_cast(pStmt)->getThen()); + findDisposeAndClearStatements(aVclPtrFields, dyn_cast(pStmt)->getElse()); + return; + } + if (!isa(pStmt)) return; + const CallExpr *pCallExpr = dyn_cast(pStmt); + + if (!pCallExpr->getDirectCallee()) return; + if (!isa(pCallExpr->getDirectCallee())) return; + auto check = loplugin::DeclCheck( + dyn_cast(pCallExpr->getDirectCallee())); + if (!(check.Function("disposeAndClear") || check.Function("clear"))) + return; + + if (!pCallExpr->getCallee()) return; + + if (!isa(pCallExpr->getCallee())) return; + const MemberExpr *pCalleeMemberExpr = dyn_cast(pCallExpr->getCallee()); + + if (!pCalleeMemberExpr->getBase()) return; + const MemberExpr *pCalleeMemberExprBase = dyn_cast(pCalleeMemberExpr->getBase()->IgnoreImpCasts()); + if (pCalleeMemberExprBase == nullptr) return; + + const FieldDecl* xxx = dyn_cast_or_null(pCalleeMemberExprBase->getMemberDecl()); + if (xxx) + aVclPtrFields.erase(xxx); +} + + +bool VCLWidgets::VisitFunctionDecl( const FunctionDecl* functionDecl ) +{ + if (ignoreLocation(functionDecl)) { + return true; + } + // ignore the stuff in the VclPtr template class + if (loplugin::DeclCheck(functionDecl).MemberFunction().Class("VclPtr") + .GlobalNamespace()) + { + return true; + } + // ignore the BASE_REF_COUNTED_CLASS::dispose() method + if (loplugin::DeclCheck(functionDecl).Function("dispose") + .Class(BASE_REF_COUNTED_CLASS).GlobalNamespace()) + { + return true; + } + const CXXMethodDecl *pMethodDecl = dyn_cast(functionDecl); + if (functionDecl->hasBody() && pMethodDecl && isDerivedFromVclReferenceBase(pMethodDecl->getParent())) { + // check the last thing that the dispose() method does, is to call into the superclass dispose method + if (loplugin::DeclCheck(functionDecl).Function("dispose")) { + if (!isDisposeCallingSuperclassDispose(pMethodDecl)) { + // We specifically have to clear a member variable AFTER calling super::dispose() here, unfortunately + if (!loplugin::DeclCheck(pMethodDecl->getParent()).Class("WindowOutputDevice")) + report( + DiagnosticsEngine::Warning, + BASE_REF_COUNTED_CLASS " subclass dispose() function MUST call dispose() of its superclass as the last thing it does", + functionDecl->getBeginLoc()) + << functionDecl->getSourceRange(); + } + } + } + + // check dispose method to make sure we are actually disposing all of the VclPtr fields + // FIXME this is not exhaustive. We should enable shouldVisitTemplateInstantiations and look deeper inside type declarations + if (pMethodDecl && pMethodDecl->isInstance() && pMethodDecl->getBody() + && pMethodDecl->param_size()==0 + && loplugin::DeclCheck(functionDecl).Function("dispose") + && isDerivedFromVclReferenceBase(pMethodDecl->getParent()) ) + { + auto check = loplugin::DeclCheck(functionDecl).MemberFunction(); + if (check.Class("VirtualDevice").GlobalNamespace() + || check.Class("Breadcrumb").GlobalNamespace()) + { + return true; + } + + std::set aVclPtrFields; + for (auto i = pMethodDecl->getParent()->field_begin(); + i != pMethodDecl->getParent()->field_end(); ++i) + { + auto const type = loplugin::TypeCheck((*i)->getType()); + if (type.Class("VclPtr").GlobalNamespace()) { + aVclPtrFields.insert(*i); + } else if (type.Class("vector").StdNamespace() + || type.Class("map").StdNamespace() + || type.Class("list").StdNamespace() + || type.Class("set").StdNamespace()) + { + const RecordType* recordType = dyn_cast_or_null((*i)->getType()->getUnqualifiedDesugaredType()); + if (recordType) { + auto d = dyn_cast(recordType->getDecl()); + if (d && d->getTemplateArgs().size()>0) { + auto const type = loplugin::TypeCheck(d->getTemplateArgs()[0].getAsType()); + if (type.Class("VclPtr").GlobalNamespace()) { + aVclPtrFields.insert(*i); + } + } + } + } + } + if (!aVclPtrFields.empty()) { + findDisposeAndClearStatements( aVclPtrFields, pMethodDecl->getBody() ); + if (!aVclPtrFields.empty()) { + //pMethodDecl->dump(); + std::string aMessage = BASE_REF_COUNTED_CLASS " subclass dispose() method does not call disposeAndClear() or clear() on the following field(s): "; + for(auto s : aVclPtrFields) + aMessage += ", " + s->getNameAsString(); + report( + DiagnosticsEngine::Warning, + aMessage, + functionDecl->getBeginLoc()) + << functionDecl->getSourceRange(); + } + } + } + + return true; +} + +bool VCLWidgets::VisitCXXDeleteExpr(const CXXDeleteExpr *pCXXDeleteExpr) +{ + if (ignoreLocation(pCXXDeleteExpr)) { + return true; + } + const CXXRecordDecl *pPointee = pCXXDeleteExpr->getArgument()->getType()->getPointeeCXXRecordDecl(); + if (pPointee && isDerivedFromVclReferenceBase(pPointee)) { + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc( + pCXXDeleteExpr->getBeginLoc()); + StringRef filename = getFilenameOfLocation(spellingLocation); + if ( !(loplugin::isSamePathname(filename, SRCDIR "/include/vcl/vclreferencebase.hxx"))) + { + report( + DiagnosticsEngine::Warning, + "calling delete on instance of " BASE_REF_COUNTED_CLASS " subclass, must rather call disposeAndClear()", + pCXXDeleteExpr->getBeginLoc()) + << pCXXDeleteExpr->getSourceRange(); + } + } + const ImplicitCastExpr* pImplicitCastExpr = dyn_cast(pCXXDeleteExpr->getArgument()); + if (!pImplicitCastExpr) { + return true; + } + if (pImplicitCastExpr->getCastKind() != CK_UserDefinedConversion) { + return true; + } + if (!loplugin::TypeCheck(pImplicitCastExpr->getSubExprAsWritten()->getType()).Class("VclPtr") + .GlobalNamespace()) + { + return true; + } + report( + DiagnosticsEngine::Warning, + "calling delete on instance of VclPtr, must rather call disposeAndClear()", + pCXXDeleteExpr->getBeginLoc()) + << pCXXDeleteExpr->getSourceRange(); + return true; +} + + +/** +The AST looks like: +`-CXXMemberCallExpr 0xb06d8b0 'void' + `-MemberExpr 0xb06d868 '' ->dispose 0x9d34880 + `-ImplicitCastExpr 0xb06d8d8 'class SfxTabPage *' + `-CXXThisExpr 0xb06d850 'class SfxAcceleratorConfigPage *' this + +*/ +bool VCLWidgets::isDisposeCallingSuperclassDispose(const CXXMethodDecl* pMethodDecl) +{ + const CompoundStmt *pCompoundStatement = dyn_cast(pMethodDecl->getBody()); + if (!pCompoundStatement) return false; + if (pCompoundStatement->size() == 0) return false; + // find the last statement + const CXXMemberCallExpr *pCallExpr = dyn_cast(*pCompoundStatement->body_rbegin()); + if (!pCallExpr) return false; + const MemberExpr *pMemberExpr = dyn_cast(pCallExpr->getCallee()); + if (!pMemberExpr) return false; + if (!loplugin::DeclCheck(pMemberExpr->getMemberDecl()).Function("dispose")) return false; + const CXXMethodDecl *pDirectCallee = dyn_cast(pCallExpr->getDirectCallee()); + if (!pDirectCallee) return false; +/* Not working yet. Partially because sometimes the superclass does not a dispose() method, so it gets passed up the chain. + Need complex checking for that case. + if (pDirectCallee->getParent()->getTypeForDecl() != (*pMethodDecl->getParent()->bases_begin()).getType().getTypePtr()) { + report( + DiagnosticsEngine::Warning, + "dispose() method calling wrong baseclass, calling " + pDirectCallee->getParent()->getQualifiedNameAsString() + + " should be calling " + (*pMethodDecl->getParent()->bases_begin()).getType().getAsString(), + pCallExpr->getLocStart()) + << pCallExpr->getSourceRange(); + return false; + }*/ + return true; +} + +bool containsVclPtr(const clang::Type* pType0); + +bool containsVclPtr(const QualType& qType) { + auto check = loplugin::TypeCheck(qType); + if (check.Class("ScopedVclPtr").GlobalNamespace() + || check.Class("ScopedVclPtrInstance").GlobalNamespace() + || check.Class("VclPtr").GlobalNamespace() + || check.Class("VclPtrInstance").GlobalNamespace()) + { + return true; + } + return containsVclPtr(qType.getTypePtr()); +} + +bool containsVclPtr(const clang::Type* pType0) { + if (!pType0) + return false; + const clang::Type* pType = pType0->getUnqualifiedDesugaredType(); + if (!pType) + return false; + if (pType->isPointerType()) { + return false; + } else if (pType->isArrayType()) { + const clang::ArrayType* pArrayType = dyn_cast(pType); + QualType elementType = pArrayType->getElementType(); + return containsVclPtr(elementType); + } else { + const CXXRecordDecl* pRecordDecl = pType->getAsCXXRecordDecl(); + if (pRecordDecl) + { + auto check = loplugin::DeclCheck(pRecordDecl); + if (check.Class("ScopedVclPtr").GlobalNamespace() + || check.Class("ScopedVclPtrInstance").GlobalNamespace() + || check.Class("VclPtr").GlobalNamespace() + || check.Class("VclPtrInstance").GlobalNamespace()) + { + return true; + } + for(auto fieldDecl = pRecordDecl->field_begin(); + fieldDecl != pRecordDecl->field_end(); ++fieldDecl) + { + const RecordType *pFieldRecordType = fieldDecl->getType()->getAs(); + if (pFieldRecordType && containsVclPtr(pFieldRecordType)) { + return true; + } + } + for(auto baseSpecifier = pRecordDecl->bases_begin(); + baseSpecifier != pRecordDecl->bases_end(); ++baseSpecifier) + { + const RecordType *pFieldRecordType = baseSpecifier->getType()->getAs(); + if (pFieldRecordType && containsVclPtr(pFieldRecordType)) { + return true; + } + } + } + } + return false; +} + +bool VCLWidgets::VisitCallExpr(const CallExpr* pCallExpr) +{ + if (ignoreLocation(pCallExpr)) { + return true; + } + FunctionDecl const * fdecl = pCallExpr->getDirectCallee(); + if (fdecl == nullptr) { + return true; + } + std::string qname { fdecl->getQualifiedNameAsString() }; + if (qname.find("memcpy") == std::string::npos + && qname.find("bcopy") == std::string::npos + && qname.find("memmove") == std::string::npos + && qname.find("rtl_copy") == std::string::npos) { + return true; + } + mbCheckingMemcpy = true; + Stmt * pStmt = const_cast(static_cast(pCallExpr->getArg(0))); + TraverseStmt(pStmt); + mbCheckingMemcpy = false; + return true; +} + +bool VCLWidgets::VisitDeclRefExpr(const DeclRefExpr* pDeclRefExpr) +{ + if (!mbCheckingMemcpy) { + return true; + } + if (ignoreLocation(pDeclRefExpr)) { + return true; + } + QualType pType = pDeclRefExpr->getDecl()->getType(); + if (pType->isPointerType()) { + pType = pType->getPointeeType(); + } + if (!containsVclPtr(pType)) { + return true; + } + report( + DiagnosticsEngine::Warning, + "Calling memcpy on a type which contains a VclPtr", + pDeclRefExpr->getExprLoc()); + return true; +} + +bool VCLWidgets::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr ) +{ + if (ignoreLocation(constructExpr)) { + return true; + } + if (constructExpr->getConstructionKind() != CXXConstructExpr::CK_Complete) { + return true; + } + const CXXConstructorDecl* pConstructorDecl = constructExpr->getConstructor(); + const CXXRecordDecl* recordDecl = pConstructorDecl->getParent(); + if (isDerivedFromVclReferenceBase(recordDecl)) { + StringRef aFileName = getFilenameOfLocation( + compiler.getSourceManager().getSpellingLoc(constructExpr->getBeginLoc())); + if (!loplugin::isSamePathname(aFileName, SRCDIR "/include/vcl/vclptr.hxx")) { + report( + DiagnosticsEngine::Warning, + "Calling constructor of a VclReferenceBase-derived type directly; all such creation should go via VclPtr<>::Create", + constructExpr->getExprLoc()); + } + } + return true; +} + +loplugin::Plugin::Registration< VCLWidgets > vclwidgets("vclwidgets"); + +} + +// Cannot be shared, uses TraverseStmt(). + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/virtualdead.cxx b/compilerplugins/clang/virtualdead.cxx new file mode 100644 index 000000000..1a63363aa --- /dev/null +++ b/compilerplugins/clang/virtualdead.cxx @@ -0,0 +1,283 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "plugin.hxx" +#include "check.hxx" +#include "compat.hxx" + +#include +#include +#include +#include +#include + +/** +Look for virtual methods where all of the overrides either +(a) do nothing +(b) all return the same value + +The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='VirtualDead' check + $ ./compilerplugins/clang/VirtualDead.py + $ for dir in *; do make FORCE_COMPILE=all UPDATE_FILES=$dir COMPILER_PLUGIN_TOOL='removevirtuals' $dir; done + +Note that the actual process may involve a fair amount of undoing, hand editing, and general messing around +to get it to work :-) +*/ + +namespace +{ +struct MyFuncInfo +{ + std::string name; + std::string sourceLocation; + std::string returnValue; +}; +bool operator<(const MyFuncInfo& lhs, const MyFuncInfo& rhs) +{ + return std::tie(lhs.name, lhs.returnValue) < std::tie(rhs.name, rhs.returnValue); +} +struct MyParamInfo +{ + std::string funcName; + std::string paramBitField; +}; +bool operator<(const MyParamInfo& lhs, const MyParamInfo& rhs) +{ + return std::tie(lhs.funcName, lhs.paramBitField) < std::tie(rhs.funcName, rhs.paramBitField); +} + +// try to limit the voluminous output a little +static std::set definitionSet; +static std::set paramUsedSet; + +class VirtualDead : public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit VirtualDead(loplugin::InstantiationData const& data) + : Plugin(data) + { + } + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + std::string output; + for (const MyFuncInfo& s : definitionSet) + output += "virtual:\t" + s.name + "\t" + s.sourceLocation + "\t" + s.returnValue + "\n"; + for (const MyParamInfo& s : paramUsedSet) + output += "param:\t" + s.funcName + "\t" + s.paramBitField + "\n"; + std::ofstream myfile; + myfile.open(WORKDIR "/loplugin.virtualdead.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitCXXMethodDecl(const CXXMethodDecl* decl); + +private: + std::string getCallValue(const Expr* arg); + std::string toString(SourceLocation loc); + void markSuperclassMethods(const CXXMethodDecl* methodDecl, const std::string& returnValue, + const std::string& paramBitField); +}; + +std::string niceName(const CXXMethodDecl* cxxMethodDecl) +{ + while (cxxMethodDecl->getTemplateInstantiationPattern()) + cxxMethodDecl = dyn_cast(cxxMethodDecl->getTemplateInstantiationPattern()); + while (cxxMethodDecl->getInstantiatedFromMemberFunction()) + cxxMethodDecl = dyn_cast(cxxMethodDecl->getInstantiatedFromMemberFunction()); + std::string s = cxxMethodDecl->getReturnType().getCanonicalType().getAsString() + " " + + cxxMethodDecl->getQualifiedNameAsString() + "("; + for (const ParmVarDecl* pParmVarDecl : cxxMethodDecl->parameters()) + { + s += pParmVarDecl->getType().getCanonicalType().getAsString(); + s += ","; + } + s += ")"; + if (cxxMethodDecl->isConst()) + { + s += "const"; + } + return s; +} + +bool VirtualDead::VisitCXXMethodDecl(const CXXMethodDecl* methodDecl) +{ + if (!methodDecl->isVirtual() || methodDecl->isDeleted()) + return true; + if (isa(methodDecl)) + return true; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(methodDecl->getCanonicalDecl())) + return true; + + if (!methodDecl->isThisDeclarationADefinition()) + return true; + + std::string returnValue; + + auto body = methodDecl->getBody(); + if (body) + { + auto compoundStmt = dyn_cast(body); + if (!compoundStmt) + returnValue = "empty"; + else if (compoundStmt->size() == 0) + returnValue = "empty"; + else + { + if (auto returnStmt = dyn_cast(*compoundStmt->body_begin())) + { + if (!returnStmt->getRetValue()) + returnValue = "empty"; + else + returnValue = getCallValue(returnStmt->getRetValue()); + } + else + returnValue = "unknown-stmt"; + } + } + else + returnValue = "empty"; + + std::string paramBitfield; + for (auto it = methodDecl->param_begin(); it != methodDecl->param_end(); ++it) + { + auto param = *it; + paramBitfield += param->getName().empty() ? "0" : "1"; + } + + markSuperclassMethods(methodDecl, returnValue, paramBitfield); + + return true; +} + +void VirtualDead::markSuperclassMethods(const CXXMethodDecl* methodDecl, + const std::string& returnValue, + std::string const& paramBitField) +{ + if (methodDecl->size_overridden_methods() == 0) + { + std::string aNiceName = niceName(methodDecl); + definitionSet.insert( + { aNiceName, toString(methodDecl->getCanonicalDecl()->getLocation()), returnValue }); + paramUsedSet.insert({ aNiceName, paramBitField }); + return; + } + + for (auto iter = methodDecl->begin_overridden_methods(); + iter != methodDecl->end_overridden_methods(); ++iter) + { + const CXXMethodDecl* overriddenMethod = *iter; + markSuperclassMethods(overriddenMethod, returnValue, paramBitField); + } +} + +std::string VirtualDead::getCallValue(const Expr* arg) +{ + arg = arg->IgnoreParenCasts(); + if (isa(arg)) + { + arg = dyn_cast(arg)->getExpr(); + } + arg = arg->IgnoreParenCasts(); + // ignore this, it seems to trigger an infinite recursion + if (isa(arg)) + return "unknown1"; + if (arg->isValueDependent()) + return "unknown2"; + APSInt x1; + if (compat::EvaluateAsInt(arg, x1, compiler.getASTContext())) + { + return compat::toString(x1, 10); + } + if (isa(arg)) + { + return "0"; + } + if (isa(arg)) + { + const CXXBindTemporaryExpr* strippedArg + = dyn_cast_or_null(arg->IgnoreParenCasts()); + if (strippedArg) + { + auto temp = dyn_cast(strippedArg->getSubExpr()); + if (temp->getNumArgs() == 0) + { + if (loplugin::TypeCheck(temp->getType()) + .Class("OUString") + .Namespace("rtl") + .GlobalNamespace()) + { + return "\"\""; + } + if (loplugin::TypeCheck(temp->getType()) + .Class("OString") + .Namespace("rtl") + .GlobalNamespace()) + { + return "\"\""; + } + return "defaultConstruct"; + } + } + } + + // Get the expression contents. + // This helps us find params which are always initialised with something like "OUString()". + SourceManager& SM = compiler.getSourceManager(); + SourceLocation startLoc = arg->getBeginLoc(); + SourceLocation endLoc = arg->getEndLoc(); + const char* p1 = SM.getCharacterData(startLoc); + const char* p2 = SM.getCharacterData(endLoc); + if (!p1 || !p2 || (p2 - p1) < 0 || (p2 - p1) > 40) + { + return "unknown3"; + } + unsigned n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts()); + std::string s(p1, p2 - p1 + n); + // strip linefeed and tab characters so they don't interfere with the parsing of the log file + std::replace(s.begin(), s.end(), '\r', ' '); + std::replace(s.begin(), s.end(), '\n', ' '); + std::replace(s.begin(), s.end(), '\t', ' '); + + // now normalize the value. For some params, like OUString, we can pass it as OUString() or "" and they are the same thing + if (s == "OUString()") + s = "\"\""; + else if (s == "OString()") + s = "\"\""; + + if (s[0] == '"' || s[0] == '\'') + return s; + return "unknown4"; +} + +std::string VirtualDead::toString(SourceLocation loc) +{ + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc(loc); + StringRef name = getFilenameOfLocation(expansionLoc); + std::string sourceLocation + = std::string(name.substr(strlen(SRCDIR) + 1)) + ":" + + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(sourceLocation); + return sourceLocation; +} + +loplugin::Plugin::Registration X("virtualdead", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/virtualdead.py b/compilerplugins/clang/virtualdead.py new file mode 100755 index 000000000..4584345da --- /dev/null +++ b/compilerplugins/clang/virtualdead.py @@ -0,0 +1,129 @@ +#!/usr/bin/python3 + +import sys +import re +import io + +callDict = dict() # callInfo tuple -> callValue +definitionToSourceLocationMap = dict() +paramSet = set() # paraminfo tuple + +# clang does not always use exactly the same numbers in the type-parameter vars it generates +# so I need to substitute them to ensure we can match correctly. +normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") +def normalizeTypeParams( line ): + return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) + +# reading as binary (since we known it is pure ascii) is much faster than reading as unicode +with io.open("workdir/loplugin.virtualdead.log", "r", encoding="ascii", errors="ignore", buffering=1024*1024) as txt: + for line in txt: + try: + tokens = line.strip().split("\t") + if tokens[0] == "virtual:": + nameAndParams = normalizeTypeParams(tokens[1]) + sourceLocation = tokens[2] + returnValue = tokens[3] + callInfo = (nameAndParams, sourceLocation) + if not callInfo in callDict: + callDict[callInfo] = set() + callDict[callInfo].add(returnValue) + definitionToSourceLocationMap[nameAndParams] = sourceLocation + elif tokens[0] == "param:": + name = normalizeTypeParams(tokens[1]) + if len(tokens)>2: + bitfield = tokens[2] + paramSet.add((name,bitfield)) + else: + print( "unknown line: " + line) + except IndexError: + print("problem with line " + line.strip()) + raise + +tmp1list = list() +for callInfo, callValues in iter(callDict.items()): + nameAndParams = callInfo[1] + if len(callValues) != 1: + continue + callValue = next(iter(callValues)) + if "unknown-stmt" in callValue: + continue + if "unknown2" in callValue: + continue + if "unknown3" in callValue: + continue + if "unknown4" in callValue: + continue + if "pure" in callValue: + continue + srcloc = callInfo[1] + if srcloc.startswith("workdir/"): continue + # ignore Qt stuff + if srcloc.startswith("Gui/"): continue + if srcloc.startswith("Widgets/"): continue + if srcloc.startswith("Core/"): continue + if srcloc.startswith("/Qt"): continue + if srcloc.startswith("Qt"): continue + if srcloc.startswith("64-"): continue + functionSig = callInfo[0] + tmp1list.append((srcloc, functionSig, callValue)) + +def merge_bitfield(a, b): + if len(a) == 0: return b + ret = "" + for i, c in enumerate(b): + if c == "1" or a[i] == "1": + ret += "1" + else: + ret += "0" + return ret; +tmp2dict = dict() +tmp2list = list() +for paramInfo in paramSet: + name = paramInfo[0] + bitfield = paramInfo[1] + if re.match( r"\w+ com::", name): continue + if re.match( r"\w+ ooo::vba::", name): continue + if re.match( r"\w+ orcus::", name): continue + if re.match( r"\w+ std::", name): continue + if not name in tmp2dict: + tmp2dict[name] = bitfield + else: + tmp2dict[name] = merge_bitfield(tmp2dict[name], bitfield) +for name, bitfield in iter(tmp2dict.items()): + srcloc = definitionToSourceLocationMap[name] + # ignore Qt stuff + if srcloc.startswith("Gui/"): continue + if srcloc.startswith("Widgets/"): continue + if srcloc.startswith("Core/"): continue + if srcloc.startswith("/Qt"): continue + if srcloc.startswith("Qt"): continue + if srcloc.startswith("64-"): continue + # ignore external stuff + if srcloc.startswith("workdir/"): continue + # referenced by generated code in workdir/ + if srcloc.startswith("writerfilter/source/ooxml/OOXMLFactory.hxx"): continue + if "0" in bitfield: + tmp2list.append((srcloc, name, bitfield)) + +# sort results by filename:lineno +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[0]) + [v[1]] +tmp1list.sort(key=lambda v: v_sort_key(v)) +tmp2list.sort(key=lambda v: v_sort_key(v)) + +# print out the results +with open("compilerplugins/clang/virtualdead.results", "wt") as f: + for v in tmp1list: + f.write(v[0] + "\n") + f.write(" " + v[1] + "\n") + f.write(" " + v[2] + "\n") +with open("compilerplugins/clang/virtualdead.unusedparams.results", "wt") as f: + for v in tmp2list: + f.write(v[0] + "\n") + f.write(" " + v[1] + "\n") + f.write(" " + v[2] + "\n") diff --git a/compilerplugins/clang/virtualdead.results b/compilerplugins/clang/virtualdead.results new file mode 100644 index 000000000..fe2a437e2 --- /dev/null +++ b/compilerplugins/clang/virtualdead.results @@ -0,0 +1,126 @@ +basic/source/comp/codegen.cxx:478 + void (anonymous namespace)::OffSetAccumulator::start(const unsigned char *,) + empty +basic/source/comp/codegen.cxx:490 + _Bool (anonymous namespace)::OffSetAccumulator::processParams() + 0 +basic/source/comp/codegen.cxx:540 + _Bool (anonymous namespace)::BufferTransformer::processParams() + 1 +canvas/inc/base/bitmapcanvasbase.hxx:79 + unsigned char canvas::BitmapCanvasBase::hasAlpha() + 1 +canvas/inc/base/bufferedgraphicdevicebase.hxx:105 + void canvas::BufferedGraphicDeviceBase::destroyBuffers() + empty +canvas/inc/base/graphicdevicebase.hxx:233 + unsigned char canvas::GraphicDeviceBase::hasFullScreenMode() + 0 +canvas/inc/base/graphicdevicebase.hxx:238 + unsigned char canvas::GraphicDeviceBase::enterFullScreenMode(unsigned char,) + 0 +canvas/inc/base/graphicdevicebase.hxx:304 + void canvas::GraphicDeviceBase::removePropertyChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) + empty +canvas/inc/base/graphicdevicebase.hxx:317 + void canvas::GraphicDeviceBase::removeVetoableChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) + empty +include/basegfx/utils/unopolypolygon.hxx:94 + void basegfx::unotools::UnoPolyPolygon::modifying()const + empty +include/connectivity/sdbcx/IRefreshable.hxx:29 + void connectivity::sdbcx::IRefreshableGroups::refreshGroups() + empty +include/filter/msfilter/msdffimp.hxx:544 + _Bool SvxMSDffManager::ShapeHasText(unsigned long,unsigned long,)const + 1 +include/svl/svdde.hxx:236 + class DdeData * DdeTopic::Get(enum SotClipboardFormatId,) + 0 +include/svl/svdde.hxx:237 + _Bool DdeTopic::Put(const class DdeData *,) + 0 +include/svl/svdde.hxx:238 + _Bool DdeTopic::Execute(const class rtl::OUString *,) + 0 +include/svl/svdde.hxx:240 + _Bool DdeTopic::MakeItem(const class rtl::OUString &,) + 0 +include/svl/svdde.hxx:243 + _Bool DdeTopic::StartAdviseLoop() + 0 +include/svtools/unoevent.hxx:198 + unsigned short SvEventDescriptor::getMacroItemWhich()const + 108 +include/ucbhelper/resultset.hxx:410 + void ucbhelper::ResultSetDataSupplier::close() + empty +include/unotools/desktopterminationobserver.hxx:36 + _Bool utl::ITerminationListener::queryTermination()const + 1 +include/vbahelper/vbahelperinterface.hxx:74 + int InheritedHelperInterfaceImpl::getCreator() + 1400204879 +sc/source/core/opencl/formulagroupcl.cxx:1070 + void sc::opencl::(anonymous namespace)::DynamicKernelSlidingArgument::GenSlidingWindowFunction(class std::__cxx11::basic_stringstream &,) + empty +sc/source/core/opencl/opbase.hxx:202 + _Bool sc::opencl::OpBase::takeNumeric()const + 1 +sc/source/ui/vba/vbasheetobject.hxx:116 + class rtl::OUString ScVbaSheetObjectBase::implGetBaseName()const + "Button" +sc/source/ui/vba/vbasheetobjects.cxx:142 + class rtl::OUString ScVbaObjectContainer::implGetShapeServiceName()const + "com.sun.star.drawing.ControlShape" +slideshow/source/engine/animationfactory.cxx:616 + void slideshow::internal::(anonymous namespace)::GenericAnimation::prefetch() + empty +sw/inc/IDocumentRedlineAccess.hxx:132 + _Bool IDocumentRedlineAccess::HasExtraRedlineTable()const + 1 +vcl/inc/qt5/Qt5FilePicker.hxx:173 + void Qt5FilePicker::updateAutomaticFileExtension() + empty +vcl/inc/salframe.hxx:145 + void SalFrame::SetRepresentedURL(const class rtl::OUString &,) + empty +vcl/inc/salframe.hxx:147 + void SalFrame::DrawMenuBar() + empty +vcl/inc/salframe.hxx:204 + _Bool SalFrame::MapUnicodeToKeyCode(char16_t,struct o3tl::strong_int,class vcl::KeyCode &,) + 0 +vcl/inc/salinst.hxx:94 + _Bool SalInstance::SVMainHook(int *,) + 0 +vcl/inc/salinst.hxx:201 + void SalInstance::releaseMainThread() + empty +vcl/inc/salinst.hxx:210 + void SalInstance::BeforeAbort(const class rtl::OUString &,_Bool,) + empty +vcl/inc/salmenu.hxx:77 + void SalMenu::GetSystemMenuData(struct SystemMenuData *,) + empty +vcl/inc/salobj.hxx:49 + void SalObject::Enable(_Bool,) + empty +vcl/inc/salprn.hxx:85 + int SalInfoPrinter::GetLandscapeAngle(const class ImplJobSetup *,) + 900 +vcl/inc/salprn.hxx:116 + enum SalPrinterError SalPrinter::GetErrorCode() + 0 +writerfilter/source/ooxml/OOXMLFactory.hxx:66 + void writerfilter::ooxml::OOXMLFactory_ns::startAction(class writerfilter::ooxml::OOXMLFastContextHandler *,) + empty +writerfilter/source/ooxml/OOXMLFactory.hxx:67 + void writerfilter::ooxml::OOXMLFactory_ns::charactersAction(class writerfilter::ooxml::OOXMLFastContextHandler *,const class rtl::OUString &,) + empty +writerfilter/source/ooxml/OOXMLFactory.hxx:68 + void writerfilter::ooxml::OOXMLFactory_ns::endAction(class writerfilter::ooxml::OOXMLFastContextHandler *,) + empty +writerfilter/source/ooxml/OOXMLFactory.hxx:69 + void writerfilter::ooxml::OOXMLFactory_ns::attributeAction(class writerfilter::ooxml::OOXMLFastContextHandler *,int,const class tools::SvRef &,) + empty diff --git a/compilerplugins/clang/virtualdead.unusedparams.results b/compilerplugins/clang/virtualdead.unusedparams.results new file mode 100644 index 000000000..960cee40e --- /dev/null +++ b/compilerplugins/clang/virtualdead.unusedparams.results @@ -0,0 +1,264 @@ +basctl/source/inc/doceventnotifier.hxx:41 + void basctl::DocumentEventListener::onDocumentCreated(const class basctl::ScriptDocument &,) + 0 +basctl/source/inc/doceventnotifier.hxx:42 + void basctl::DocumentEventListener::onDocumentOpened(const class basctl::ScriptDocument &,) + 0 +basctl/source/inc/doceventnotifier.hxx:43 + void basctl::DocumentEventListener::onDocumentSave(const class basctl::ScriptDocument &,) + 0 +basctl/source/inc/doceventnotifier.hxx:44 + void basctl::DocumentEventListener::onDocumentSaveDone(const class basctl::ScriptDocument &,) + 0 +basctl/source/inc/doceventnotifier.hxx:45 + void basctl::DocumentEventListener::onDocumentSaveAs(const class basctl::ScriptDocument &,) + 0 +basctl/source/inc/doceventnotifier.hxx:46 + void basctl::DocumentEventListener::onDocumentSaveAsDone(const class basctl::ScriptDocument &,) + 0 +basctl/source/inc/doceventnotifier.hxx:48 + void basctl::DocumentEventListener::onDocumentTitleChanged(const class basctl::ScriptDocument &,) + 0 +basic/source/comp/codegen.cxx:478 + void (anonymous namespace)::OffSetAccumulator::start(const unsigned char *,) + 0 +basic/source/comp/codegen.cxx:479 + void (anonymous namespace)::OffSetAccumulator::processOpCode0(enum SbiOpcode,) + 0 +basic/source/comp/codegen.cxx:480 + void (anonymous namespace)::OffSetAccumulator::processOpCode1(enum SbiOpcode,type-parameter-?-?,) + 00 +basic/source/comp/codegen.cxx:481 + void (anonymous namespace)::OffSetAccumulator::processOpCode2(enum SbiOpcode,type-parameter-?-?,type-parameter-?-?,) + 000 +canvas/inc/base/bufferedgraphicdevicebase.hxx:227 + void canvas::BufferedGraphicDeviceBase::windowShown(const struct com::sun::star::lang::EventObject &,) + 0 +canvas/inc/base/bufferedgraphicdevicebase.hxx:234 + void canvas::BufferedGraphicDeviceBase::windowHidden(const struct com::sun::star::lang::EventObject &,) + 0 +canvas/inc/base/graphicdevicebase.hxx:238 + unsigned char canvas::GraphicDeviceBase::enterFullScreenMode(unsigned char,) + 0 +canvas/inc/base/graphicdevicebase.hxx:304 + void canvas::GraphicDeviceBase::removePropertyChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) + 00 +canvas/inc/base/graphicdevicebase.hxx:317 + void canvas::GraphicDeviceBase::removeVetoableChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) + 00 +canvas/inc/base/integerbitmapbase.hxx:57 + void canvas::IntegerBitmapBase::setData(const class com::sun::star::uno::Sequence &,const struct com::sun::star::rendering::IntegerBitmapLayout &,const struct com::sun::star::geometry::IntegerRectangle2D &,) + 011 +canvas/inc/base/integerbitmapbase.hxx:71 + void canvas::IntegerBitmapBase::setPixel(const class com::sun::star::uno::Sequence &,const struct com::sun::star::rendering::IntegerBitmapLayout &,const struct com::sun::star::geometry::IntegerPoint2D &,) + 011 +desktop/source/deployment/registry/inc/dp_backend.h:78 + void dp_registry::backend::Package::processPackage_(class osl::ResettableGuard &,_Bool,_Bool,const class rtl::Reference &,const class com::sun::star::uno::Reference &,) + 01111 +extensions/source/bibliography/loadlisteneradapter.hxx:109 + void bib::OLoadListener::_unloading(const struct com::sun::star::lang::EventObject &,) + 0 +extensions/source/bibliography/loadlisteneradapter.hxx:110 + void bib::OLoadListener::_reloading(const struct com::sun::star::lang::EventObject &,) + 0 +include/cppuhelper/propshlp.hxx:330 + void cppu::IEventNotificationHook::fireEvents(int *,int,unsigned char,_Bool,) + 0111 +include/drawinglayer/primitive2d/textbreakuphelper.hxx:58 + _Bool drawinglayer::primitive2d::TextBreakupHelper::allowChange(unsigned int,class basegfx::B2DHomMatrix &,unsigned int,unsigned int,) + 0111 +include/editeng/editeng.hxx:493 + void EditEngine::ParagraphConnected(int,int,) + 01 +include/filter/msfilter/msdffimp.hxx:544 + _Bool SvxMSDffManager::ShapeHasText(unsigned long,unsigned long,)const + 00 +include/oox/dump/dumperbase.hxx:473 + void oox::dump::ConfigItemBase::implProcessConfigItemInt(class oox::TextInputStream &,long,const class rtl::OUString &,) + 011 +include/oox/dump/dumperbase.hxx:564 + class rtl::OUString oox::dump::NameListBase::implGetNameDbl(const class oox::dump::Config &,double,)const + 01 +include/oox/dump/oledumper.hxx:165 + void oox::dump::ComCtlObjectBase::implDumpCommonExtra(long,) + 0 +include/oox/export/shapes.hxx:138 + class oox::drawingml::ShapeExport & oox::drawingml::ShapeExport::WriteNonVisualProperties(const class com::sun::star::uno::Reference &,) + 0 +include/sfx2/stbitem.hxx:101 + _Bool SfxStatusBarControl::MouseButtonUp(const class MouseEvent &,) + 0 +include/svl/svdde.hxx:227 + _Bool DdeGetPutItem::Put(const class DdeData *,) + 0 +include/svl/svdde.hxx:236 + class DdeData * DdeTopic::Get(enum SotClipboardFormatId,) + 0 +include/svl/svdde.hxx:237 + _Bool DdeTopic::Put(const class DdeData *,) + 0 +include/svl/svdde.hxx:238 + _Bool DdeTopic::Execute(const class rtl::OUString *,) + 0 +include/svl/svdde.hxx:240 + _Bool DdeTopic::MakeItem(const class rtl::OUString &,) + 0 +include/svtools/editbrowsebox.hxx:101 + void svt::CellController::ActivatingMouseEvent(const class BrowserMouseEvent &,_Bool,) + 10 +include/svx/IAccessibleParent.hxx:81 + _Bool accessibility::IAccessibleParent::ReplaceChild(class accessibility::AccessibleShape *,const class com::sun::star::uno::Reference &,const long,const class accessibility::AccessibleShapeTreeInfo &,) + 1101 +include/svx/selectioncontroller.hxx:47 + _Bool sdr::SelectionController::onMouseButtonUp(const class MouseEvent &,class vcl::Window *,) + 10 +include/vcl/accessibletable.hxx:91 + class tools::Rectangle vcl::table::IAccessibleTable::GetFieldCharacterBounds(int,int,int,) + 001 +include/vcl/accessibletable.hxx:92 + int vcl::table::IAccessibleTable::GetFieldIndexAtPoint(int,int,const class Point &,) + 001 +include/vcl/accessibletable.hxx:93 + void vcl::table::IAccessibleTable::FillAccessibleStateSetForCell(class utl::AccessibleStateSetHelper &,int,unsigned short,)const + 110 +include/vcl/dndhelp.hxx:62 + void vcl::unohelper::DragAndDropClient::dragExit(const struct com::sun::star::datatransfer::dnd::DropTargetEvent &,) + 0 +include/vcl/opengl/OpenGLContext.hxx:101 + struct SystemWindowData OpenGLContext::generateWinData(class vcl::Window *,_Bool,) + 10 +include/xmloff/txtimp.hxx:108 + class SvXMLImportContext * XMLTextImportHelper::CreateTableChildContext(class SvXMLImport &,int,const class com::sun::star::uno::Reference &,) + 101 +sc/inc/filter.hxx:81 + void ScFormatFilterPlugin::ScExportHTML(class SvStream &,const class rtl::OUString &,class ScDocument *,const class ScRange &,const unsigned short,_Bool,const class rtl::OUString &,class rtl::OUString &,const class rtl::OUString &,) + 111101111 +sc/inc/filter.hxx:83 + void ScFormatFilterPlugin::ScExportRTF(class SvStream &,class ScDocument *,const class ScRange &,const unsigned short,) + 1110 +sc/inc/formulagroup.hxx:144 + class boost::intrusive_ptr sc::FormulaGroupInterpreter::inverseMatrix(const class ScMatrix &,) + 0 +sc/source/core/opencl/formulagroupcl.cxx:1070 + void sc::opencl::(anonymous namespace)::DynamicKernelSlidingArgument::GenSlidingWindowFunction(class std::__cxx11::basic_stringstream &,) + 0 +sdext/source/pdfimport/inc/contentsink.hxx:151 + void pdfi::ContentSink::drawMask(const class com::sun::star::uno::Sequence &,_Bool,) + 10 +sdext/source/pdfimport/inc/contentsink.hxx:161 + void pdfi::ContentSink::drawColorMaskedImage(const class com::sun::star::uno::Sequence &,const class com::sun::star::uno::Sequence &,) + 10 +sdext/source/pdfimport/inc/contentsink.hxx:165 + void pdfi::ContentSink::drawMaskedImage(const class com::sun::star::uno::Sequence &,const class com::sun::star::uno::Sequence &,_Bool,) + 110 +sdext/source/pdfimport/inc/treevisiting.hxx:46 + void pdfi::ElementTreeVisitor::visit(struct pdfi::HyperlinkElement &,const class __gnu_debug::_Safe_iterator > >, class std::__debug::list >, class std::allocator > > >, struct std::bidirectional_iterator_tag> &,) + 10 +sdext/source/pdfimport/inc/treevisiting.hxx:47 + void pdfi::ElementTreeVisitor::visit(struct pdfi::TextElement &,const class __gnu_debug::_Safe_iterator > >, class std::__debug::list >, class std::allocator > > >, struct std::bidirectional_iterator_tag> &,) + 10 +sdext/source/pdfimport/inc/treevisiting.hxx:49 + void pdfi::ElementTreeVisitor::visit(struct pdfi::FrameElement &,const class __gnu_debug::_Safe_iterator > >, class std::__debug::list >, class std::allocator > > >, struct std::bidirectional_iterator_tag> &,) + 10 +sdext/source/pdfimport/inc/treevisiting.hxx:51 + void pdfi::ElementTreeVisitor::visit(struct pdfi::ImageElement &,const class __gnu_debug::_Safe_iterator > >, class std::__debug::list >, class std::allocator > > >, struct std::bidirectional_iterator_tag> &,) + 10 +sdext/source/pdfimport/inc/treevisiting.hxx:52 + void pdfi::ElementTreeVisitor::visit(struct pdfi::PageElement &,const class __gnu_debug::_Safe_iterator > >, class std::__debug::list >, class std::allocator > > >, struct std::bidirectional_iterator_tag> &,) + 10 +sdext/source/pdfimport/inc/treevisiting.hxx:53 + void pdfi::ElementTreeVisitor::visit(struct pdfi::DocumentElement &,const class __gnu_debug::_Safe_iterator > >, class std::__debug::list >, class std::allocator > > >, struct std::bidirectional_iterator_tag> &,) + 10 +sdext/source/presenter/PresenterScrollBar.hxx:177 + double sdext::presenter::PresenterScrollBar::GetDragDistance(const int,const int,)const + 01 +sdext/source/presenter/PresenterScrollBar.hxx:179 + double sdext::presenter::PresenterScrollBar::GetMinor(const double,const double,)const + 10 +starmath/source/wordexportbase.hxx:28 + void SmWordExportBase::HandleText(const class SmNode *,int,) + 10 +sw/inc/swcrsr.hxx:163 + _Bool SwCursor::LeftRight(_Bool,unsigned short,unsigned short,_Bool,_Bool,_Bool,const class SwRootFrame *,_Bool,) + 11000000 +sw/source/core/access/acccontext.hxx:354 + _Bool SwAccessibleContext::SetSelectedState(_Bool,) + 0 +sw/source/core/inc/txmsrt.hxx:145 + void SwTOXSortTabBase::FillText(class SwTextNode &,const class SwIndex &,unsigned short,const class SwRootFrame *const,)const + 1100 +sw/source/filter/ww8/wrtww8.hxx:797 + void MSWordExportBase::WriteHyperlinkData(const class sw::mark::IFieldmark &,) + 0 +sw/source/filter/ww8/wrtww8.hxx:863 + void MSWordExportBase::OutputGrfNode(const class SwGrfNode &,) + 0 +vcl/inc/outdev.h:122 + _Bool ImplGlyphFallbackFontSubstitution::FindFontSubstitute(class FontSelectPattern &,class LogicalFontInstance *,class rtl::OUString &,)const + 101 +vcl/inc/salbmp.hxx:79 + _Bool SalBitmap::Replace(const class Color &,const class Color &,unsigned char,) + 000 +vcl/inc/salframe.hxx:145 + void SalFrame::SetRepresentedURL(const class rtl::OUString &,) + 0 +vcl/inc/salframe.hxx:194 + void SalFrame::Flush(const class tools::Rectangle &,) + 0 +vcl/inc/salframe.hxx:204 + _Bool SalFrame::MapUnicodeToKeyCode(char16_t,struct o3tl::strong_int,class vcl::KeyCode &,) + 000 +vcl/inc/salframe.hxx:251 + void SalFrame::BeginSetClipRegion(unsigned int,) + 0 +vcl/inc/salgdiimpl.hxx:96 + void SalGraphicsImpl::SetXORMode(_Bool,_Bool,) + 10 +vcl/inc/salgdiimpl.hxx:151 + void SalGraphicsImpl::copyArea(long,long,long,long,long,long,_Bool,) + 1111110 +vcl/inc/salinst.hxx:94 + _Bool SalInstance::SVMainHook(int *,) + 0 +vcl/inc/salinst.hxx:127 + void SalInstance::GetPrinterQueueState(struct SalPrinterQueueInfo *,) + 0 +vcl/inc/salinst.hxx:165 + class weld::Builder * SalInstance::CreateInterimBuilder(class vcl::Window *,const class rtl::OUString &,const class rtl::OUString &,_Bool,unsigned long,) + 11110 +vcl/inc/salinst.hxx:184 + void SalInstance::AddToRecentDocumentList(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,) + 100 +vcl/inc/salinst.hxx:210 + void SalInstance::BeforeAbort(const class rtl::OUString &,_Bool,) + 00 +vcl/inc/salmenu.hxx:71 + void SalMenu::SetItemBits(unsigned int,enum MenuItemBits,) + 10 +vcl/inc/salmenu.hxx:75 + void SalMenu::SetItemImage(unsigned int,class SalMenuItem *,const class Image &,) + 011 +vcl/inc/salmenu.hxx:76 + void SalMenu::SetAccelerator(unsigned int,class SalMenuItem *,const class vcl::KeyCode &,const class rtl::OUString &,) + 0101 +vcl/inc/salmenu.hxx:77 + void SalMenu::GetSystemMenuData(struct SystemMenuData *,) + 0 +vcl/inc/salobj.hxx:49 + void SalObject::Enable(_Bool,) + 0 +vcl/inc/salprn.hxx:83 + void SalInfoPrinter::InitPaperFormats(const class ImplJobSetup *,) + 0 +vcl/inc/salprn.hxx:85 + int SalInfoPrinter::GetLandscapeAngle(const class ImplJobSetup *,) + 0 +vcl/inc/salprn.hxx:114 + class SalGraphics * SalPrinter::StartPage(class ImplJobSetup *,_Bool,) + 10 +vcl/inc/WidgetDrawInterface.hxx:64 + _Bool vcl::WidgetDrawInterface::drawNativeControl(enum ControlType,enum ControlPart,const class tools::Rectangle &,enum ControlState,const class ImplControlValue &,const class rtl::OUString &,const class Color &,) + 1111101 +vcl/inc/WidgetDrawInterface.hxx:88 + _Bool vcl::WidgetDrawInterface::getNativeControlRegion(enum ControlType,enum ControlPart,const class tools::Rectangle &,enum ControlState,const class ImplControlValue &,const class rtl::OUString &,class tools::Rectangle &,class tools::Rectangle &,) + 11111011 diff --git a/compilerplugins/clang/virtualdown.cxx b/compilerplugins/clang/virtualdown.cxx new file mode 100644 index 000000000..946d8bc95 --- /dev/null +++ b/compilerplugins/clang/virtualdown.cxx @@ -0,0 +1,219 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include "config_clang.h" +#include "plugin.hxx" +#include + +/** +Look for virtual methods where we never call the defining virtual method, and only call the overriding virtual +methods, which indicates a places where the virtual-ness is unwarranted, normally a result of premature abstraction. + +The process goes something like this: + $ make check + $ make FORCE_COMPILE=all COMPILER_PLUGIN_TOOL='VirtualDown' check + $ ./compilerplugins/clang/VirtualDown.py + +@TODO for some reason, we get false+ for operator== methods +@TODO some templates confuse it and we get false+ + +*/ + +namespace +{ +struct MyFuncInfo +{ + std::string name; + std::string sourceLocation; +}; +bool operator<(const MyFuncInfo& lhs, const MyFuncInfo& rhs) { return lhs.name < rhs.name; } + +// try to limit the voluminous output a little +static std::set definitionSet; +static std::set callSet; + +class VirtualDown : public loplugin::FilteringPlugin +{ +public: + explicit VirtualDown(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + // dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes + // writing to the same logfile + std::string output; + for (const MyFuncInfo& s : definitionSet) + output += "definition:\t" + s.name + "\t" + s.sourceLocation + "\n"; + for (const std::string& s : callSet) + output += "call:\t" + s + "\n"; + std::ofstream myfile; + myfile.open(WORKDIR "/loplugin.virtualdown.log", std::ios::app | std::ios::out); + myfile << output; + myfile.close(); + } + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitCXXMethodDecl(CXXMethodDecl const*); + bool VisitCXXMemberCallExpr(CXXMemberCallExpr const*); + bool TraverseFunctionDecl(FunctionDecl*); + bool TraverseCXXMethodDecl(CXXMethodDecl*); + bool TraverseCXXConversionDecl(CXXConversionDecl*); + bool TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl*); + +private: + std::string toString(SourceLocation loc); + std::string niceName(const CXXMethodDecl* functionDecl); + FunctionDecl const* currentFunctionDecl = nullptr; +}; + +bool VirtualDown::VisitCXXMethodDecl(const CXXMethodDecl* methodDecl) +{ + if (ignoreLocation(methodDecl)) + { + return true; + } + if (!methodDecl->isThisDeclarationADefinition() || !methodDecl->isVirtual() + || methodDecl->isDeleted()) + { + return true; + } + methodDecl = methodDecl->getCanonicalDecl(); + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(methodDecl)) + { + return true; + } + + std::string aNiceName = niceName(methodDecl); + + if (isa(methodDecl)) + return true; + if (isa(methodDecl)) + return true; + + if (methodDecl->size_overridden_methods() == 0) + definitionSet.insert({ aNiceName, toString(methodDecl->getLocation()) }); + + return true; +} + +bool VirtualDown::VisitCXXMemberCallExpr(CXXMemberCallExpr const* expr) +{ + // Note that I don't ignore ANYTHING here, because I want to get calls to my code that result + // from template instantiation deep inside the STL and other external code + + FunctionDecl const* calleeFunctionDecl = expr->getDirectCallee(); + if (calleeFunctionDecl == nullptr) + { + Expr const* callee = expr->getCallee()->IgnoreParenImpCasts(); + DeclRefExpr const* dr = dyn_cast(callee); + if (dr) + { + calleeFunctionDecl = dyn_cast(dr->getDecl()); + if (calleeFunctionDecl) + goto gotfunc; + } + return true; + } + +gotfunc: + + // ignore recursive calls + if (currentFunctionDecl == calleeFunctionDecl) + return true; + + auto cxxMethodDecl = dyn_cast(calleeFunctionDecl); + if (!cxxMethodDecl) + return true; + + while (cxxMethodDecl->getTemplateInstantiationPattern()) + cxxMethodDecl = dyn_cast(cxxMethodDecl->getTemplateInstantiationPattern()); + while (cxxMethodDecl->getInstantiatedFromMemberFunction()) + cxxMethodDecl = dyn_cast(cxxMethodDecl->getInstantiatedFromMemberFunction()); + if (cxxMethodDecl->getLocation().isValid() && !ignoreLocation(cxxMethodDecl)) + callSet.insert(niceName(cxxMethodDecl)); + + return true; +} + +bool VirtualDown::TraverseFunctionDecl(FunctionDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseFunctionDecl(f); + currentFunctionDecl = copy; + return ret; +} +bool VirtualDown::TraverseCXXMethodDecl(CXXMethodDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(f); + currentFunctionDecl = copy; + return ret; +} +bool VirtualDown::TraverseCXXConversionDecl(CXXConversionDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseCXXConversionDecl(f); + currentFunctionDecl = copy; + return ret; +} +bool VirtualDown::TraverseCXXDeductionGuideDecl(CXXDeductionGuideDecl* f) +{ + auto copy = currentFunctionDecl; + currentFunctionDecl = f; + bool ret = RecursiveASTVisitor::TraverseCXXDeductionGuideDecl(f); + currentFunctionDecl = copy; + return ret; +} + +std::string VirtualDown::niceName(const CXXMethodDecl* cxxMethodDecl) +{ + std::string s = cxxMethodDecl->getReturnType().getCanonicalType().getAsString() + " " + + cxxMethodDecl->getQualifiedNameAsString() + "("; + for (const ParmVarDecl* pParmVarDecl : cxxMethodDecl->parameters()) + { + s += pParmVarDecl->getType().getCanonicalType().getAsString(); + s += ","; + } + s += ")"; + if (cxxMethodDecl->isConst()) + { + s += "const"; + } + return s; +} + +std::string VirtualDown::toString(SourceLocation loc) +{ + SourceLocation expansionLoc = compiler.getSourceManager().getExpansionLoc(loc); + StringRef name = getFilenameOfLocation(expansionLoc); + std::string sourceLocation + = std::string(name.substr(strlen(SRCDIR) + 1)) + ":" + + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(sourceLocation); + return sourceLocation; +} + +loplugin::Plugin::Registration X("virtualdown", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/virtualdown.py b/compilerplugins/clang/virtualdown.py new file mode 100755 index 000000000..35623b558 --- /dev/null +++ b/compilerplugins/clang/virtualdown.py @@ -0,0 +1,55 @@ +#!/usr/bin/python + +import io +import re +import sys + +definitionSet = set() +definitionToSourceLocationMap = dict() +callSet = set() + + +with io.open("workdir/loplugin.virtualdown.log", "rb", buffering=1024*1024) as txt: + for line in txt: + tokens = line.strip().split("\t") + if tokens[0] == "definition:": + fullMethodName = tokens[1] + sourceLocation = tokens[2] + definitionSet.add(fullMethodName) + definitionToSourceLocationMap[fullMethodName] = sourceLocation + elif tokens[0] == "call:": + fullMethodName = tokens[1] + callSet.add(fullMethodName) + else: + print( "unknown line: " + line) + +unnecessaryVirtualSet = set() + +for clazz in (definitionSet - callSet): +# if clazz.startswith("canvas::"): continue +# if clazz == "basegfx::unotools::UnoPolyPolygon::void-modifying()const": continue + # ignore external code + if definitionToSourceLocationMap[clazz].startswith("external/"): continue + + unnecessaryVirtualSet.add((clazz,definitionToSourceLocationMap[clazz] )) + + +# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely +def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): + return [int(text) if text.isdigit() else text.lower() + for text in re.split(_nsre, s)] +# sort by both the source-line and the datatype, so the output file ordering is stable +# when we have multiple items on the same source line +def v_sort_key(v): + return natural_sort_key(v[1]) + [v[0]] + +# sort results by name and line number +tmp1list = sorted(unnecessaryVirtualSet, key=lambda v: v_sort_key(v)) + +with open("compilerplugins/clang/virtualdown.results", "wt") as f: + for t in tmp1list: + f.write( t[1] + "\n" ) + f.write( " " + t[0] + "\n" ) + # add an empty line at the end to make it easier for the removevirtuals plugin to mmap() the output file + f.write("\n") + diff --git a/compilerplugins/clang/virtualdown.results b/compilerplugins/clang/virtualdown.results new file mode 100644 index 000000000..d521868ec --- /dev/null +++ b/compilerplugins/clang/virtualdown.results @@ -0,0 +1,675 @@ +basic/source/comp/codegen.cxx:464 + void OffSetAccumulator::start(const unsigned char *,) +basic/source/comp/codegen.cxx:465 + void OffSetAccumulator::processOpCode0(enum SbiOpcode,) +basic/source/comp/codegen.cxx:466 + void OffSetAccumulator::processOpCode1(enum SbiOpcode,type-parameter-0-0,) +basic/source/comp/codegen.cxx:467 + void OffSetAccumulator::processOpCode2(enum SbiOpcode,type-parameter-0-0,type-parameter-0-0,) +basic/source/comp/codegen.cxx:476 + _Bool OffSetAccumulator::processParams() +basic/source/comp/codegen.cxx:487 + void BufferTransformer::start(const unsigned char *,) +basic/source/comp/codegen.cxx:488 + void BufferTransformer::processOpCode0(enum SbiOpcode,) +basic/source/comp/codegen.cxx:492 + void BufferTransformer::processOpCode1(enum SbiOpcode,type-parameter-0-0,) +basic/source/comp/codegen.cxx:517 + void BufferTransformer::processOpCode2(enum SbiOpcode,type-parameter-0-0,type-parameter-0-0,) +basic/source/comp/codegen.cxx:526 + _Bool BufferTransformer::processParams() +chart2/qa/extras/chart2dump/chart2dump.cxx:141 + void Chart2DumpTest::verify() +chart2/source/inc/WeakListenerAdapter.hxx:57 + void chart::WeakListenerAdapter::disposing(const struct com::sun::star::lang::EventObject &,) +extensions/source/dbpilots/unoautopilot.hxx:99 + class cppu::IPropertyArrayHelper * dbp::OUnoAutoPilot::createArrayHelper()const +extensions/source/propctrlr/commoncontrol.hxx:127 + short pcr::CommonBehaviourControl::getControlType() +extensions/source/propctrlr/commoncontrol.hxx:129 + class com::sun::star::uno::Reference pcr::CommonBehaviourControl::getControlContext() +extensions/source/propctrlr/commoncontrol.hxx:131 + void pcr::CommonBehaviourControl::setControlContext(const class com::sun::star::uno::Reference &,) +extensions/source/propctrlr/commoncontrol.hxx:133 + class com::sun::star::uno::Reference pcr::CommonBehaviourControl::getControlWindow() +extensions/source/propctrlr/commoncontrol.hxx:135 + unsigned char pcr::CommonBehaviourControl::isModified() +forms/source/xforms/collection.hxx:130 + _Bool Collection >::isValid(const class com::sun::star::uno::Reference &,)const +forms/source/xforms/collection.hxx:130 + _Bool Collection >::isValid(const class com::sun::star::uno::Sequence &,)const +forms/source/xforms/collection.hxx:139 + void Collection >::_insert(const class com::sun::star::uno::Sequence &,) +forms/source/xforms/collection.hxx:139 + void Collection >::_insert(const class com::sun::star::uno::Reference &,) +forms/source/xforms/collection.hxx:142 + void Collection >::_remove(const class com::sun::star::uno::Sequence &,) +forms/source/xforms/collection.hxx:142 + void Collection >::_remove(const class com::sun::star::uno::Reference &,) +forms/source/xforms/datatypes.hxx:234 + class cppu::IPropertyArrayHelper * xforms::ODerivedDataType::createArrayHelper()const +forms/source/xforms/datatypes.hxx:237 + class com::sun::star::uno::Reference xforms::ODerivedDataType::getPropertySetInfo() +forms/source/xforms/namedcollection.hxx:80 + class com::sun::star::uno::Type NamedCollection::getElementType() +forms/source/xforms/namedcollection.hxx:85 + unsigned char NamedCollection::hasElements() +forms/source/xforms/namedcollection.hxx:91 + class com::sun::star::uno::Any NamedCollection::getByName(const class rtl::OUString &,) +forms/source/xforms/namedcollection.hxx:99 + class com::sun::star::uno::Sequence NamedCollection::getElementNames() +forms/source/xforms/namedcollection.hxx:104 + unsigned char NamedCollection::hasByName(const class rtl::OUString &,) +include/basic/sbxvar.hxx:127 + enum SbxClassType SbxValue::GetClass()const +include/canvas/base/basemutexhelper.hxx:54 + void canvas::BaseMutexHelper >::disposeThis() +include/canvas/base/basemutexhelper.hxx:54 + void canvas::BaseMutexHelper >::disposeThis() +include/canvas/base/basemutexhelper.hxx:54 + void canvas::BaseMutexHelper >::disposeThis() +include/canvas/base/basemutexhelper.hxx:54 + void canvas::BaseMutexHelper >::disposeThis() +include/canvas/base/basemutexhelper.hxx:54 + void canvas::BaseMutexHelper >::disposeThis() +include/canvas/base/basemutexhelper.hxx:59 + void canvas::BaseMutexHelper::disposing() +include/canvas/base/bitmapcanvasbase.hxx:80 + unsigned char canvas::BitmapCanvasBase::hasAlpha() +include/canvas/base/bitmapcanvasbase.hxx:85 + class com::sun::star::uno::Reference canvas::BitmapCanvasBase::getScaledBitmap(const struct com::sun::star::geometry::RealSize2D &,unsigned char,) +include/canvas/base/bitmapcanvasbase.hxx:106 + void canvas::BitmapCanvasBase2::copyRect(const class com::sun::star::uno::Reference &,const struct com::sun::star::geometry::RealRectangle2D &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const struct com::sun::star::geometry::RealRectangle2D &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +include/canvas/base/bufferedgraphicdevicebase.hxx:95 + class com::sun::star::uno::Reference canvas::BufferedGraphicDeviceBase::getBufferController() +include/canvas/base/bufferedgraphicdevicebase.hxx:101 + int canvas::BufferedGraphicDeviceBase::createBuffers(int,) +include/canvas/base/bufferedgraphicdevicebase.hxx:108 + void canvas::BufferedGraphicDeviceBase::destroyBuffers() +include/canvas/base/bufferedgraphicdevicebase.hxx:210 + void canvas::BufferedGraphicDeviceBase::disposeEventSource(const struct com::sun::star::lang::EventObject &,) +include/canvas/base/bufferedgraphicdevicebase.hxx:220 + void canvas::BufferedGraphicDeviceBase::windowResized(const struct com::sun::star::awt::WindowEvent &,) +include/canvas/base/bufferedgraphicdevicebase.hxx:225 + void canvas::BufferedGraphicDeviceBase::windowMoved(const struct com::sun::star::awt::WindowEvent &,) +include/canvas/base/bufferedgraphicdevicebase.hxx:230 + void canvas::BufferedGraphicDeviceBase::windowShown(const struct com::sun::star::lang::EventObject &,) +include/canvas/base/bufferedgraphicdevicebase.hxx:237 + void canvas::BufferedGraphicDeviceBase::windowHidden(const struct com::sun::star::lang::EventObject &,) +include/canvas/base/canvasbase.hxx:144 + void canvas::CanvasBase::drawPoint(const struct com::sun::star::geometry::RealPoint2D &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +include/canvas/base/canvasbase.hxx:157 + void canvas::CanvasBase::drawLine(const struct com::sun::star::geometry::RealPoint2D &,const struct com::sun::star::geometry::RealPoint2D &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +include/canvas/base/canvasbase.hxx:173 + void canvas::CanvasBase::drawBezier(const struct com::sun::star::geometry::RealBezierSegment2D &,const struct com::sun::star::geometry::RealPoint2D &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +include/canvas/base/canvasbase.hxx:190 + class com::sun::star::uno::Reference canvas::CanvasBase::drawPolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +include/canvas/base/canvasbase.hxx:206 + class com::sun::star::uno::Reference canvas::CanvasBase::strokePolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const struct com::sun::star::rendering::StrokeAttributes &,) +include/canvas/base/canvasbase.hxx:223 + class com::sun::star::uno::Reference canvas::CanvasBase::strokeTexturedPolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const class com::sun::star::uno::Sequence &,const struct com::sun::star::rendering::StrokeAttributes &,) +include/canvas/base/canvasbase.hxx:241 + class com::sun::star::uno::Reference canvas::CanvasBase::strokeTextureMappedPolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const class com::sun::star::uno::Sequence &,const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::StrokeAttributes &,) +include/canvas/base/canvasbase.hxx:260 + class com::sun::star::uno::Reference canvas::CanvasBase::queryStrokeShapes(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const struct com::sun::star::rendering::StrokeAttributes &,) +include/canvas/base/canvasbase.hxx:277 + class com::sun::star::uno::Reference canvas::CanvasBase::fillPolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +include/canvas/base/canvasbase.hxx:293 + class com::sun::star::uno::Reference canvas::CanvasBase::fillTexturedPolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const class com::sun::star::uno::Sequence &,) +include/canvas/base/canvasbase.hxx:310 + class com::sun::star::uno::Reference canvas::CanvasBase::fillTextureMappedPolyPolygon(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,const class com::sun::star::uno::Sequence &,const class com::sun::star::uno::Reference &,) +include/canvas/base/canvasbase.hxx:329 + class com::sun::star::uno::Reference canvas::CanvasBase::createFont(const struct com::sun::star::rendering::FontRequest &,const class com::sun::star::uno::Sequence &,const struct com::sun::star::geometry::Matrix2D &,) +include/canvas/base/canvasbase.hxx:347 + class com::sun::star::uno::Sequence canvas::CanvasBase::queryAvailableFonts(const struct com::sun::star::rendering::FontInfo &,const class com::sun::star::uno::Sequence &,) +include/canvas/base/canvasbase.hxx:361 + class com::sun::star::uno::Reference canvas::CanvasBase::drawText(const struct com::sun::star::rendering::StringContext &,const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,signed char,) +include/canvas/base/canvasbase.hxx:383 + class com::sun::star::uno::Reference canvas::CanvasBase::drawTextLayout(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +include/canvas/base/canvasbase.hxx:416 + class com::sun::star::uno::Reference canvas::CanvasBase::drawBitmapModulated(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +include/canvas/base/canvasbase.hxx:432 + class com::sun::star::uno::Reference canvas::CanvasBase::getDevice() +include/canvas/base/canvascustomspritebase.hxx:103 + void canvas::CanvasCustomSpriteBase::clear() +include/canvas/base/canvascustomspritebase.hxx:114 + class com::sun::star::uno::Reference canvas::CanvasCustomSpriteBase::drawBitmap(const class com::sun::star::uno::Reference &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +include/canvas/base/canvascustomspritebase.hxx:140 + void canvas::CanvasCustomSpriteBase::setAlpha(double,) +include/canvas/base/canvascustomspritebase.hxx:149 + void canvas::CanvasCustomSpriteBase::move(const struct com::sun::star::geometry::RealPoint2D &,const struct com::sun::star::rendering::ViewState &,const struct com::sun::star::rendering::RenderState &,) +include/canvas/base/canvascustomspritebase.hxx:162 + void canvas::CanvasCustomSpriteBase::transform(const struct com::sun::star::geometry::AffineMatrix2D &,) +include/canvas/base/canvascustomspritebase.hxx:173 + void canvas::CanvasCustomSpriteBase::clip(const class com::sun::star::uno::Reference &,) +include/canvas/base/canvascustomspritebase.hxx:182 + void canvas::CanvasCustomSpriteBase::setPriority(double,) +include/canvas/base/canvascustomspritebase.hxx:189 + void canvas::CanvasCustomSpriteBase::show() +include/canvas/base/canvascustomspritebase.hxx:196 + void canvas::CanvasCustomSpriteBase::hide() +include/canvas/base/canvascustomspritebase.hxx:205 + class com::sun::star::uno::Reference canvas::CanvasCustomSpriteBase::getContentCanvas() +include/canvas/base/canvascustomspritebase.hxx:213 + _Bool canvas::CanvasCustomSpriteBase::isAreaUpdateOpaque(const class basegfx::B2DRange &,)const +include/canvas/base/canvascustomspritebase.hxx:220 + _Bool canvas::CanvasCustomSpriteBase::isContentChanged()const +include/canvas/base/canvascustomspritebase.hxx:227 + class basegfx::B2DPoint canvas::CanvasCustomSpriteBase::getPosPixel()const +include/canvas/base/canvascustomspritebase.hxx:234 + class basegfx::B2DVector canvas::CanvasCustomSpriteBase::getSizePixel()const +include/canvas/base/canvascustomspritebase.hxx:241 + class basegfx::B2DRange canvas::CanvasCustomSpriteBase::getUpdateArea()const +include/canvas/base/canvascustomspritebase.hxx:248 + double canvas::CanvasCustomSpriteBase::getPriority()const +include/canvas/base/disambiguationhelper.hxx:62 + void canvas::DisambiguationHelper >::disposeThis() +include/canvas/base/disambiguationhelper.hxx:62 + void canvas::DisambiguationHelper >::disposeThis() +include/canvas/base/disambiguationhelper.hxx:65 + void canvas::DisambiguationHelper >::disposeEventSource(const struct com::sun::star::lang::EventObject &,) +include/canvas/base/disambiguationhelper.hxx:65 + void canvas::DisambiguationHelper >::disposeEventSource(const struct com::sun::star::lang::EventObject &,) +include/canvas/base/disambiguationhelper.hxx:71 + void canvas::DisambiguationHelper::disposing() +include/canvas/base/disambiguationhelper.hxx:74 + void canvas::DisambiguationHelper::disposing(const struct com::sun::star::lang::EventObject &,) +include/canvas/base/graphicdevicebase.hxx:140 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::getBufferController() +include/canvas/base/graphicdevicebase.hxx:145 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::getDeviceColorSpace() +include/canvas/base/graphicdevicebase.hxx:152 + struct com::sun::star::geometry::RealSize2D canvas::GraphicDeviceBase::getPhysicalResolution() +include/canvas/base/graphicdevicebase.hxx:159 + struct com::sun::star::geometry::RealSize2D canvas::GraphicDeviceBase::getPhysicalSize() +include/canvas/base/graphicdevicebase.hxx:166 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createCompatibleLinePolyPolygon(const class com::sun::star::uno::Sequence > &,) +include/canvas/base/graphicdevicebase.hxx:173 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createCompatibleBezierPolyPolygon(const class com::sun::star::uno::Sequence > &,) +include/canvas/base/graphicdevicebase.hxx:180 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createCompatibleBitmap(const struct com::sun::star::geometry::IntegerSize2D &,) +include/canvas/base/graphicdevicebase.hxx:191 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createVolatileBitmap(const struct com::sun::star::geometry::IntegerSize2D &,) +include/canvas/base/graphicdevicebase.hxx:202 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createCompatibleAlphaBitmap(const struct com::sun::star::geometry::IntegerSize2D &,) +include/canvas/base/graphicdevicebase.hxx:213 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createVolatileAlphaBitmap(const struct com::sun::star::geometry::IntegerSize2D &,) +include/canvas/base/graphicdevicebase.hxx:224 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::getParametricPolyPolygonFactory() +include/canvas/base/graphicdevicebase.hxx:229 + unsigned char canvas::GraphicDeviceBase::hasFullScreenMode() +include/canvas/base/graphicdevicebase.hxx:234 + unsigned char canvas::GraphicDeviceBase::enterFullScreenMode(unsigned char,) +include/canvas/base/graphicdevicebase.hxx:240 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createInstance(const class rtl::OUString &,) +include/canvas/base/graphicdevicebase.hxx:248 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::createInstanceWithArguments(const class rtl::OUString &,const class com::sun::star::uno::Sequence &,) +include/canvas/base/graphicdevicebase.hxx:256 + class com::sun::star::uno::Sequence canvas::GraphicDeviceBase::getAvailableServiceNames() +include/canvas/base/graphicdevicebase.hxx:263 + void canvas::GraphicDeviceBase::update() +include/canvas/base/graphicdevicebase.hxx:273 + class com::sun::star::uno::Reference canvas::GraphicDeviceBase::getPropertySetInfo() +include/canvas/base/graphicdevicebase.hxx:279 + void canvas::GraphicDeviceBase::setPropertyValue(const class rtl::OUString &,const class com::sun::star::uno::Any &,) +include/canvas/base/graphicdevicebase.hxx:286 + class com::sun::star::uno::Any canvas::GraphicDeviceBase::getPropertyValue(const class rtl::OUString &,) +include/canvas/base/graphicdevicebase.hxx:292 + void canvas::GraphicDeviceBase::addPropertyChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) +include/canvas/base/graphicdevicebase.hxx:300 + void canvas::GraphicDeviceBase::removePropertyChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) +include/canvas/base/graphicdevicebase.hxx:305 + void canvas::GraphicDeviceBase::addVetoableChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) +include/canvas/base/graphicdevicebase.hxx:313 + void canvas::GraphicDeviceBase::removeVetoableChangeListener(const class rtl::OUString &,const class com::sun::star::uno::Reference &,) +include/canvas/base/integerbitmapbase.hxx:45 + class com::sun::star::uno::Sequence canvas::IntegerBitmapBase::getData(struct com::sun::star::rendering::IntegerBitmapLayout &,const struct com::sun::star::geometry::IntegerRectangle2D &,) +include/canvas/base/integerbitmapbase.hxx:59 + void canvas::IntegerBitmapBase::setData(const class com::sun::star::uno::Sequence &,const struct com::sun::star::rendering::IntegerBitmapLayout &,const struct com::sun::star::geometry::IntegerRectangle2D &,) +include/canvas/base/integerbitmapbase.hxx:73 + void canvas::IntegerBitmapBase::setPixel(const class com::sun::star::uno::Sequence &,const struct com::sun::star::rendering::IntegerBitmapLayout &,const struct com::sun::star::geometry::IntegerPoint2D &,) +include/canvas/base/integerbitmapbase.hxx:87 + class com::sun::star::uno::Sequence canvas::IntegerBitmapBase::getPixel(struct com::sun::star::rendering::IntegerBitmapLayout &,const struct com::sun::star::geometry::IntegerPoint2D &,) +include/canvas/base/integerbitmapbase.hxx:101 + struct com::sun::star::rendering::IntegerBitmapLayout canvas::IntegerBitmapBase::getMemoryLayout() +include/canvas/base/spritecanvasbase.hxx:96 + class com::sun::star::uno::Reference canvas::SpriteCanvasBase::createSpriteFromAnimation(const class com::sun::star::uno::Reference &,) +include/canvas/base/spritecanvasbase.hxx:107 + class com::sun::star::uno::Reference canvas::SpriteCanvasBase::createSpriteFromBitmaps(const class com::sun::star::uno::Sequence > &,signed char,) +include/canvas/base/spritecanvasbase.hxx:122 + class com::sun::star::uno::Reference canvas::SpriteCanvasBase::createCustomSprite(const struct com::sun::star::geometry::RealSize2D &,) +include/canvas/base/spritecanvasbase.hxx:133 + class com::sun::star::uno::Reference canvas::SpriteCanvasBase::createClonedSprite(const class com::sun::star::uno::Reference &,) +include/canvas/base/spritecanvasbase.hxx:145 + void canvas::SpriteCanvasBase::showSprite(const class rtl::Reference &,) +include/canvas/base/spritecanvasbase.hxx:154 + void canvas::SpriteCanvasBase::hideSprite(const class rtl::Reference &,) +include/canvas/base/spritecanvasbase.hxx:163 + void canvas::SpriteCanvasBase::moveSprite(const class rtl::Reference &,const class basegfx::B2DPoint &,const class basegfx::B2DPoint &,const class basegfx::B2DVector &,) +include/canvas/base/spritecanvasbase.hxx:175 + void canvas::SpriteCanvasBase::updateSprite(const class rtl::Reference &,const class basegfx::B2DPoint &,const class basegfx::B2DRange &,) +include/comphelper/interaction.hxx:54 + void comphelper::OInteraction::select() +include/comphelper/proparrhlp.hxx:83 + class cppu::IPropertyArrayHelper * comphelper::OAggregationArrayUsageHelper::createArrayHelper()const +include/comphelper/servicedecl.hxx:164 + class rtl::OUString comphelper::service_decl::detail::OwnServiceImpl::getImplementationName() +include/comphelper/servicedecl.hxx:167 + unsigned char comphelper::service_decl::detail::OwnServiceImpl::supportsService(const class rtl::OUString &,) +include/comphelper/servicedecl.hxx:171 + class com::sun::star::uno::Sequence comphelper::service_decl::detail::OwnServiceImpl::getSupportedServiceNames() +include/comphelper/unique_disposing_ptr.hxx:41 + void comphelper::unique_disposing_ptr::reset(class basctl::(anonymous namespace)::Dll *,) +include/comphelper/unique_disposing_ptr.hxx:41 + void comphelper::unique_disposing_ptr::reset(class SwDLL *,) +include/comphelper/unique_disposing_ptr.hxx:41 + void comphelper::unique_disposing_ptr<(anonymous namespace)::ImpTimedRefDev>::reset(class (anonymous namespace)::ImpTimedRefDev *,) +include/comphelper/unique_disposing_ptr.hxx:41 + void comphelper::unique_disposing_ptr::reset(class sd::SdGlobalResourceContainer *,) +include/comphelper/weakeventlistener.hxx:119 + void comphelper::OWeakListenerAdapter::disposing(const struct com::sun::star::lang::EventObject &,) +include/editeng/flditem.hxx:61 + _Bool SvxFieldData::operator==(const class SvxFieldData &,)const +include/filter/msfilter/msocximex.hxx:55 + _Bool SvxMSConvertOCXControls::InsertControl(const class com::sun::star::uno::Reference &,const struct com::sun::star::awt::Size &,class com::sun::star::uno::Reference *,_Bool,) +include/sfx2/viewsh.hxx:216 + class SfxShell * SfxViewShell::GetFormShell() +include/svl/poolitem.hxx:156 + _Bool SfxPoolItem::operator<(const class SfxPoolItem &,)const +include/svl/svdde.hxx:227 + class DdeData * DdeGetPutItem::Get(enum SotClipboardFormatId,) +include/svl/svdde.hxx:228 + _Bool DdeGetPutItem::Put(const class DdeData *,) +include/svl/svdde.hxx:229 + void DdeGetPutItem::AdviseLoop(_Bool,) +include/svl/svdde.hxx:237 + class DdeData * DdeTopic::Get(enum SotClipboardFormatId,) +include/svl/svdde.hxx:238 + _Bool DdeTopic::Put(const class DdeData *,) +include/svl/svdde.hxx:239 + _Bool DdeTopic::Execute(const class rtl::OUString *,) +include/svl/svdde.hxx:241 + _Bool DdeTopic::MakeItem(const class rtl::OUString &,) +include/svl/svdde.hxx:244 + _Bool DdeTopic::StartAdviseLoop() +include/svtools/svparser.hxx:127 + void SvParser::Continue(int,) +include/svtools/svparser.hxx:127 + void SvParser::Continue(enum HtmlTokenId,) +include/svx/AccessibleShape.hxx:416 + class rtl::OUString accessibility::AccessibleShape::CreateAccessibleDescription() +include/svx/ctredlin.hxx:150 + void SvxTPage::DeactivatePage() +include/svx/svdpage.hxx:472 + enum Orientation SdrPage::GetOrientation()const +include/svx/svdtext.hxx:73 + void SdrText::SetObjectItem(const class SfxPoolItem &,) +include/test/container/xnamecontainer.hxx:38 + void apitest::XNameContainer::setElement(const class com::sun::star::uno::Any &,) +include/test/drawing/xdrawpages.hxx:26 + void apitest::XDrawPages::testInsertNewByIndex() +include/test/drawing/xdrawpages.hxx:27 + void apitest::XDrawPages::testRemove() +include/test/table/xtablerows.hxx:27 + void apitest::XTableRows::testInsertByIndex() +include/test/table/xtablerows.hxx:28 + void apitest::XTableRows::testRemoveByIndex() +include/toolkit/controls/geometrycontrolmodel.hxx:184 + void OGeometryControlModel::fillProperties(class com::sun::star::uno::Sequence &,class com::sun::star::uno::Sequence &,)const +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:244 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByStringIndex(const class rtl::OUString &,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:266 + class com::sun::star::uno::Any ScVbaCollectionBase >::getItemByIntIndex(const int,) +include/vbahelper/vbacollectionimpl.hxx:324 + unsigned char ScVbaCollectionBase::hasElements() +include/vbahelper/vbahelperinterface.hxx:77 + int InheritedHelperInterfaceImpl::getCreator() +include/vbahelper/vbahelperinterface.hxx:91 + class rtl::OUString InheritedHelperInterfaceImpl::getImplementationName() +include/vbahelper/vbahelperinterface.hxx:92 + unsigned char InheritedHelperInterfaceImpl::supportsService(const class rtl::OUString &,) +include/vbahelper/vbareturntypes.hxx:40 + void ooo::vba::DefaultReturnHelper::setValue(type-parameter-0-0,) +include/vbahelper/vbareturntypes.hxx:41 + type-parameter-0-0 ooo::vba::DefaultReturnHelper::getValue() +include/vcl/customweld.hxx:41 + class rtl::OUString weld::CustomWidgetController::GetHelpText()const +include/vcl/svapp.hxx:801 + void Application::AppEvent(const class ApplicationEvent &,) +sc/source/core/opencl/formulagroupcl.cxx:1053 + _Bool sc::opencl::DynamicKernelSlidingArgument::NeedParallelReduction()const +sc/source/core/opencl/formulagroupcl.cxx:1061 + void sc::opencl::DynamicKernelSlidingArgument::GenSlidingWindowFunction(class std::__cxx11::basic_stringstream &,) +sc/source/core/opencl/formulagroupcl.cxx:1340 + void sc::opencl::ParallelReductionVectorRef::GenSlidingWindowFunction(class std::__cxx11::basic_stringstream &,) +sc/source/core/opencl/formulagroupcl.cxx:1520 + class std::__cxx11::basic_string, class std::allocator > sc::opencl::ParallelReductionVectorRef::GenSlidingWindowDeclRef(_Bool,)const +sc/source/core/opencl/formulagroupcl.cxx:1555 + unsigned long sc::opencl::ParallelReductionVectorRef::Marshal(struct _cl_kernel *,int,int,struct _cl_program *,) +sc/source/ui/inc/dataprovider.hxx:85 + class std::__debug::map, class std::allocator > > sc::DataProvider::getDataSourcesForURL(const class rtl::OUString &,) +sc/source/ui/vba/vbacondition.hxx:41 + class rtl::OUString ScVbaCondition::Formula1() +sc/source/ui/vba/vbacondition.hxx:42 + class rtl::OUString ScVbaCondition::Formula2() +sc/source/ui/vba/vbacondition.hxx:44 + int ScVbaCondition::Operator(_Bool,) +sc/source/ui/vba/vbaformat.hxx:62 + class ScCellRangesBase * ScVbaFormat::getCellRangesBase() +sc/source/ui/vba/vbaformat.hxx:62 + class ScCellRangesBase * ScVbaFormat::getCellRangesBase() +sc/source/ui/vba/vbaformat.hxx:74 + class com::sun::star::uno::Any ScVbaFormat::Borders(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:77 + class com::sun::star::uno::Reference ScVbaFormat::Font() +sc/source/ui/vba/vbaformat.hxx:80 + class com::sun::star::uno::Reference ScVbaFormat::Interior() +sc/source/ui/vba/vbaformat.hxx:83 + void ScVbaFormat::setNumberFormat(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:86 + class com::sun::star::uno::Any ScVbaFormat::getNumberFormat() +sc/source/ui/vba/vbaformat.hxx:89 + void ScVbaFormat::setNumberFormatLocal(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:92 + class com::sun::star::uno::Any ScVbaFormat::getNumberFormatLocal() +sc/source/ui/vba/vbaformat.hxx:95 + void ScVbaFormat::setIndentLevel(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:98 + class com::sun::star::uno::Any ScVbaFormat::getIndentLevel() +sc/source/ui/vba/vbaformat.hxx:101 + void ScVbaFormat::setHorizontalAlignment(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:104 + class com::sun::star::uno::Any ScVbaFormat::getHorizontalAlignment() +sc/source/ui/vba/vbaformat.hxx:107 + void ScVbaFormat::setVerticalAlignment(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:110 + class com::sun::star::uno::Any ScVbaFormat::getVerticalAlignment() +sc/source/ui/vba/vbaformat.hxx:113 + void ScVbaFormat::setOrientation(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:116 + class com::sun::star::uno::Any ScVbaFormat::getOrientation() +sc/source/ui/vba/vbaformat.hxx:119 + void ScVbaFormat::setShrinkToFit(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:122 + class com::sun::star::uno::Any ScVbaFormat::getShrinkToFit() +sc/source/ui/vba/vbaformat.hxx:125 + void ScVbaFormat::setWrapText(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:128 + class com::sun::star::uno::Any ScVbaFormat::getWrapText() +sc/source/ui/vba/vbaformat.hxx:131 + void ScVbaFormat::setLocked(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:134 + class com::sun::star::uno::Any ScVbaFormat::getLocked() +sc/source/ui/vba/vbaformat.hxx:137 + void ScVbaFormat::setFormulaHidden(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:140 + class com::sun::star::uno::Any ScVbaFormat::getFormulaHidden() +sc/source/ui/vba/vbaformat.hxx:149 + void ScVbaFormat::setReadingOrder(const class com::sun::star::uno::Any &,) +sc/source/ui/vba/vbaformat.hxx:152 + class com::sun::star::uno::Any ScVbaFormat::getReadingOrder() +sc/source/ui/vba/vbapagebreak.hxx:45 + int ScVbaPageBreak::getType() +sc/source/ui/vba/vbapagebreak.hxx:46 + void ScVbaPageBreak::setType(int,) +sc/source/ui/vba/vbapagebreak.hxx:48 + void ScVbaPageBreak::Delete() +sc/source/ui/vba/vbapagebreak.hxx:49 + class com::sun::star::uno::Reference ScVbaPageBreak::Location() +sd/source/ui/inc/BulletAndPositionDlg.hxx:153 + void SvxBulletAndPositionDlg::dispose() +sd/source/ui/inc/OutlinerIteratorImpl.hxx:93 + _Bool sd::outliner::IteratorImplBase::operator==(const class sd::outliner::IteratorImplBase &,)const +sfx2/source/inc/docundomanager.hxx:45 + void SfxModelSubComponent::disposing() +slideshow/source/engine/activities/activitiesfactory.cxx:173 + void slideshow::internal::(anonymous namespace)::FromToByActivity::startAnimation() +slideshow/source/engine/activities/activitiesfactory.cxx:242 + void slideshow::internal::(anonymous namespace)::FromToByActivity::endAnimation() +slideshow/source/engine/activities/activitiesfactory.cxx:332 + void slideshow::internal::(anonymous namespace)::FromToByActivity::performEnd() +slideshow/source/engine/activities/activitiesfactory.cxx:345 + void slideshow::internal::(anonymous namespace)::FromToByActivity::dispose() +slideshow/source/engine/activities/activitiesfactory.cxx:527 + void slideshow::internal::(anonymous namespace)::ValuesActivity::startAnimation() +slideshow/source/engine/activities/activitiesfactory.cxx:538 + void slideshow::internal::(anonymous namespace)::ValuesActivity::endAnimation() +slideshow/source/engine/activities/activitiesfactory.cxx:583 + void slideshow::internal::(anonymous namespace)::ValuesActivity::performEnd() +slideshow/source/engine/animationfactory.cxx:443 + void slideshow::internal::(anonymous namespace)::GenericAnimation::prefetch(const class std::shared_ptr &,const class std::shared_ptr &,) +slideshow/source/engine/animationfactory.cxx:447 + void slideshow::internal::(anonymous namespace)::GenericAnimation::start(const class std::shared_ptr &,const class std::shared_ptr &,) +slideshow/source/engine/opengl/TransitionImpl.hxx:180 + void OGLTransitionImpl::finish(double,double,double,double,double,) +sw/inc/redline.hxx:50 + _Bool SwRedlineExtraData::operator==(const class SwRedlineExtraData &,)const +vcl/inc/unx/saldata.hxx:68 + void X11SalData::initNWF() +workdir/../vcl/inc/qt5/Qt5FilePicker.hxx:142 + void Qt5FilePicker::disposing(const struct com::sun::star::lang::EventObject &,) +workdir/../vcl/inc/qt5/Qt5Frame.hxx:143 + void Qt5Frame::deregisterDragSource(const class Qt5DragSource *,) +workdir/../vcl/inc/qt5/Qt5Frame.hxx:145 + void Qt5Frame::deregisterDropTarget(const class Qt5DropTarget *,) +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:141 + void writerfilter::ooxml::OOXMLFastContextHandler::pushBiDiEmbedLevel() +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:142 + void writerfilter::ooxml::OOXMLFastContextHandler::popBiDiEmbedLevel() +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:184 + void writerfilter::ooxml::OOXMLFastContextHandler::setDefaultBooleanValue() +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:185 + void writerfilter::ooxml::OOXMLFastContextHandler::setDefaultIntegerValue() +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:186 + void writerfilter::ooxml::OOXMLFastContextHandler::setDefaultHexValue() +writerfilter/source/ooxml/OOXMLFastContextHandler.hxx:187 + void writerfilter::ooxml::OOXMLFastContextHandler::setDefaultStringValue() +writerperfect/inc/ImportFilter.hxx:166 + void writerperfect::detail::ImportFilterImpl::doRegisterHandlers(class OdpGenerator &,) +writerperfect/inc/ImportFilter.hxx:166 + void writerperfect::detail::ImportFilterImpl::doRegisterHandlers(class OdtGenerator &,) +writerperfect/inc/ImportFilter.hxx:166 + void writerperfect::detail::ImportFilterImpl::doRegisterHandlers(class OdgGenerator &,) +writerperfect/inc/ImportFilter.hxx:166 + void writerperfect::detail::ImportFilterImpl::doRegisterHandlers(class OdsGenerator &,) +xmloff/source/forms/elementimport.hxx:575 + class rtl::Reference xmloff::OContainerImport::CreateChildContext(unsigned short,const class rtl::OUString &,const class com::sun::star::uno::Reference &,) +xmloff/source/forms/elementimport.hxx:583 + class com::sun::star::uno::Reference xmloff::OContainerImport::createElement() +xmloff/source/forms/elementimport.hxx:610 + class com::sun::star::uno::Reference xmloff::OColumnImport::createElement() +xmloff/source/transform/TransformerContext.hxx:96 + void XMLTransformerContext::ExportContent() + diff --git a/compilerplugins/clang/weakbase.cxx b/compilerplugins/clang/weakbase.cxx new file mode 100644 index 000000000..666444ff7 --- /dev/null +++ b/compilerplugins/clang/weakbase.cxx @@ -0,0 +1,123 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include + +#include "plugin.hxx" +#include "clang/AST/CXXInheritance.h" + +/** + * Check for multiple copies of WeakBase in base classes + */ +namespace +{ +class WeakBase : public loplugin::FilteringPlugin +{ +public: + explicit WeakBase(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitCXXRecordDecl(CXXRecordDecl const*); +}; + +bool WeakBase::VisitCXXRecordDecl(CXXRecordDecl const* recordDecl) +{ + if (ignoreLocation(recordDecl)) + { + return true; + } + // StringRef aFileName = getFilenameOfLocation( + // compiler.getSourceManager().getSpellingLoc(fieldDecl->getBeginLoc())); + + // if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/chart2/source/")) + // return true; + // if (loplugin::isSamePathname(aFileName, SRCDIR "/include/sfx2/recentdocsview.hxx")) + // return true; + // if (loplugin::isSamePathname(aFileName, SRCDIR "/include/sfx2/templatelocalview.hxx")) + // return true; + // if (loplugin::isSamePathname(aFileName, SRCDIR "/store/source/stortree.hxx") + // || loplugin::isSamePathname(aFileName, SRCDIR "/store/source/stordata.hxx")) + // return true; + // if (loplugin::isSamePathname(aFileName, SRCDIR "/sw/source/uibase/inc/dbtree.hxx")) + // return true; + + recordDecl = recordDecl->getCanonicalDecl(); + if (!recordDecl->hasDefinition()) + return true; + + int noWeakBases = 0; + std::string basePaths; + auto BaseMatchesCallback = [&](const CXXBaseSpecifier* cxxBaseSpecifier, CXXBasePath& Paths) { + if (!cxxBaseSpecifier->getType().getTypePtr()) + return false; + const CXXRecordDecl* baseCXXRecordDecl = cxxBaseSpecifier->getType()->getAsCXXRecordDecl(); + if (!baseCXXRecordDecl) + return false; + if (baseCXXRecordDecl->isInvalidDecl()) + return false; + if (baseCXXRecordDecl->getName() != "WeakBase") + return false; + ++noWeakBases; + std::string sPath; + for (CXXBasePathElement const& pathElement : Paths) + { + if (!sPath.empty()) + { + sPath += "->"; + } + if (pathElement.Class->hasDefinition()) + sPath += pathElement.Class->getNameAsString(); + else + sPath += "???"; + } + sPath += "->"; + sPath += baseCXXRecordDecl->getNameAsString(); + if (!basePaths.empty()) + basePaths += ", "; + basePaths += sPath; + return false; + }; + + CXXBasePaths aPaths; + recordDecl->lookupInBases(BaseMatchesCallback, aPaths); + + if (noWeakBases > 1) + { + report(DiagnosticsEngine::Warning, + "multiple copies of WeakBase, through inheritance paths %0", + recordDecl->getBeginLoc()) + << basePaths << recordDecl->getSourceRange(); + } + return true; +} + +loplugin::Plugin::Registration weakbase("weakbase"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/weakobject.cxx b/compilerplugins/clang/weakobject.cxx new file mode 100644 index 000000000..d021dd419 --- /dev/null +++ b/compilerplugins/clang/weakobject.cxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include +#include +#include +#include +#include +#include "plugin.hxx" +#include "check.hxx" + +/* +Check for places where we end up with more than one copy of cppu::OweakObject in a class, which +really should not happen - we should be using one of the AggImplInheritanceHelper classes then +to inherit. +*/ + +namespace +{ +class WeakObject : public loplugin::FilteringPlugin +{ +public: + explicit WeakObject(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual bool preRun() override + { + return true; + } + + virtual void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitCXXRecordDecl( const CXXRecordDecl* decl); + +}; + +bool WeakObject::VisitCXXRecordDecl(const CXXRecordDecl* decl) +{ + if (ignoreLocation(decl)) + return true; + if (!decl->hasDefinition()) + return true; + if (decl->hasAnyDependentBases()) + return true; + int cnt = 0; + decl->forallBases( + [&cnt] (const CXXRecordDecl *BaseDefinition) -> bool + { + if (loplugin::DeclCheck(BaseDefinition).Class("OWeakObject").Namespace("cppu").GlobalNamespace()) + ++cnt; + return true; + }); + if (cnt < 2) + return true; + + report(DiagnosticsEngine::Warning, "more than one copy of cppu::OWeakObject inherited", + decl->getBeginLoc()) + << decl->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration weakobject("weakobject", false); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/writeonlyvars.cxx b/compilerplugins/clang/writeonlyvars.cxx new file mode 100644 index 000000000..f5051c99e --- /dev/null +++ b/compilerplugins/clang/writeonlyvars.cxx @@ -0,0 +1,1142 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if !defined _WIN32 //TODO, #include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config_clang.h" + +#include "plugin.hxx" +#include "check.hxx" + +#include "clang/AST/ParentMapContext.h" + +/** + Finds variables that are effectively write-only. + + Largely the same as the unusedfields.cxx loplugin. +*/ + +namespace +{ +struct MyVarInfo +{ + const VarDecl* varDecl; + std::string parent; + std::string varName; + std::string varType; + std::string sourceLocation; +}; +bool operator<(const MyVarInfo& lhs, const MyVarInfo& rhs) +{ + return std::tie(lhs.parent, lhs.varName) < std::tie(rhs.parent, rhs.varName); +} + +// try to limit the voluminous output a little +static std::set readFromSet; +static std::set writeToSet; +static std::set definitionSet; + +/** + * Wrap the different kinds of callable and callee objects in the clang AST so I can define methods that handle everything. + */ +class CallerWrapper +{ + const CallExpr* m_callExpr; + const CXXConstructExpr* m_cxxConstructExpr; + +public: + CallerWrapper(const CallExpr* callExpr) + : m_callExpr(callExpr) + , m_cxxConstructExpr(nullptr) + { + } + CallerWrapper(const CXXConstructExpr* cxxConstructExpr) + : m_callExpr(nullptr) + , m_cxxConstructExpr(cxxConstructExpr) + { + } + unsigned getNumArgs() const + { + return m_callExpr ? m_callExpr->getNumArgs() : m_cxxConstructExpr->getNumArgs(); + } + const Expr* getArg(unsigned i) const + { + return m_callExpr ? m_callExpr->getArg(i) : m_cxxConstructExpr->getArg(i); + } +}; +class CalleeWrapper +{ + const FunctionDecl* m_calleeFunctionDecl = nullptr; + const CXXConstructorDecl* m_cxxConstructorDecl = nullptr; + const FunctionProtoType* m_functionPrototype = nullptr; + +public: + explicit CalleeWrapper(const FunctionDecl* calleeFunctionDecl) + : m_calleeFunctionDecl(calleeFunctionDecl) + { + } + explicit CalleeWrapper(const CXXConstructExpr* cxxConstructExpr) + : m_cxxConstructorDecl(cxxConstructExpr->getConstructor()) + { + } + explicit CalleeWrapper(const FunctionProtoType* functionPrototype) + : m_functionPrototype(functionPrototype) + { + } + unsigned getNumParams() const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getNumParams(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getNumParams(); + else if (m_functionPrototype->param_type_begin() == m_functionPrototype->param_type_end()) + // FunctionProtoType will assert if we call getParamTypes() and it has no params + return 0; + else + return m_functionPrototype->getParamTypes().size(); + } + const QualType getParamType(unsigned i) const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getParamDecl(i)->getType(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getParamDecl(i)->getType(); + else + return m_functionPrototype->getParamTypes()[i]; + } + std::string getNameAsString() const + { + if (m_calleeFunctionDecl) + return m_calleeFunctionDecl->getNameAsString(); + else if (m_cxxConstructorDecl) + return m_cxxConstructorDecl->getNameAsString(); + else + return ""; + } + CXXMethodDecl const* getAsCXXMethodDecl() const + { + if (m_calleeFunctionDecl) + return dyn_cast(m_calleeFunctionDecl); + return nullptr; + } +}; + +class WriteOnlyVars : public loplugin::FilteringPlugin +{ +public: + explicit WriteOnlyVars(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + virtual void run() override; + + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + bool VisitVarDecl(const VarDecl*); + bool VisitDeclRefExpr(const DeclRefExpr*); + bool TraverseIfStmt(IfStmt*); + +private: + MyVarInfo niceName(const VarDecl*); + void checkIfReadFrom(const VarDecl* varDecl, const Expr* memberExpr); + void checkIfWrittenTo(const VarDecl* varDecl, const Expr* memberExpr); + bool checkForWriteWhenUsingCollectionType(const CXXMethodDecl* calleeMethodDecl); + bool IsPassedByNonConst(const VarDecl* varDecl, const Stmt* child, CallerWrapper callExpr, + CalleeWrapper calleeFunctionDecl); + llvm::Optional getCallee(CallExpr const*); + + // For reasons I do not understand, parentFunctionDecl() is not reliable, so + // we store the parent function on the way down the AST. + FunctionDecl* insideFunctionDecl = nullptr; + std::vector insideConditionalCheckOfMemberSet; +}; + +void WriteOnlyVars::run() +{ + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + + if (!isUnitTestMode()) + { + StringRef fn(handler.getMainFileName()); + // playing paging-in games with volatile + if (loplugin::isSamePathname(fn, SRCDIR "/sal/osl/unx/file.cxx")) + return; + // playing paging-in games with volatile + if (loplugin::isSamePathname(fn, SRCDIR "/desktop/unx/source/file_image_unx.c")) + return; + // false+ + if (loplugin::isSamePathname(fn, SRCDIR "/store/source/storpage.cxx")) + return; + // yydebug? + if (loplugin::isSamePathname(fn, SRCDIR "/idlc/source/idlccompile.cxx")) + return; + if (fn.contains("/qa/")) + return; + if (fn.contains("/vcl/workben/")) + return; + // preload + if (loplugin::isSamePathname(fn, SRCDIR "/cppuhelper/source/servicemanager.cxx")) + return; + // doing a "free items outside lock" thing + if (loplugin::isSamePathname(fn, SRCDIR "/unotools/source/config/itemholder1.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svl/source/config/itemholder2.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/config/itemholder2.cxx")) + return; + // doing a "keep objects alive" thing + if (loplugin::isSamePathname(fn, SRCDIR "/jvmfwk/source/framework.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/jvmfwk/plugins/sunmajor/pluginlib/util.cxx")) + return; + // debug code + if (loplugin::isSamePathname(fn, SRCDIR "/svl/source/items/style.cxx")) + return; + // ok + if (loplugin::isSamePathname(fn, SRCDIR "/stoc/source/inspect/introspection.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/package/source/zippackage/ZipPackage.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/hwpfilter/source/hwpreader.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/treelist/transfer.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/app/brand.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/filter/igif/gifread.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/gdi/metaact.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/fontsubset/sft.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/filter/ipdf/pdfdocument.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/filter/ipdf/pdfdocument2.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/generic/app/sm.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/filter/jpeg/JpegWriter.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/generic/dtrans/X11_selection.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/filter/jpeg/jpegc.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vcl/unx/generic/window/FWS.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/toolkit/source/awt/vclxspinbutton.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/toolkit/source/controls/formattedcontrol.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/config/helpopt.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/filter/SvFilterOptionsDialog.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svtools/source/java/javainteractionhandler.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/basic/source/classes/sbunoobj.cxx")) + return; + if (loplugin::isSamePathname(fn, + SRCDIR "/accessibility/source/standard/vclxaccessiblebox.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/cppcanvas/source/mtfrenderer/implrenderer.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sfx2/source/doc/guisaveas.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sfx2/source/appl/newhelp.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sfx2/source/control/thumbnailview.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sfx2/source/control/recentdocsview.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sfx2/source/view/viewfrm.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/framework/source/services/desktop.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR + "/framework/source/uielement/generictoolbarcontroller.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR + "/framework/source/uielement/complextoolbarcontroller.cxx")) + return; + if (loplugin::isSamePathname(fn, + SRCDIR "/framework/source/interaction/quietinteraction.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/editeng/source/editeng/editdoc.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/editeng/source/editeng/impedit4.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/editeng/source/editeng/editobj.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/editeng/source/items/frmitems.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/binaryurp/source/bridge.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svx/source/tbxctrls/fontworkgallery.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/basctl/source/basicide/moduldl2.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/canvas/source/cairo/cairo_spritecanvas.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/chart2/source/tools/DiagramHelper.cxx")) + return; + if (loplugin::isSamePathname(fn, + SRCDIR "/chart2/source/tools/ExplicitCategoriesProvider.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/chart2/source/tools/LegendHelper.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/chart2/source/tools/OPropertySet.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/chart2/source/tools/CommonConverters.cxx")) + return; + if (loplugin::isSamePathname( + fn, + SRCDIR "/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/chart2/source/tools/DataSourceHelper.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/oox/source/export/shapes.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/oox/source/export/chartexport.cxx")) + return; + if (loplugin::isSamePathname(fn, + SRCDIR "/filter/source/storagefilterdetect/filterdetect.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/filter/source/pdf/pdfexport.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/filter/source/svg/svgexport.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/filter/source/msfilter/svdfppt.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR + "/dbaccess/source/core/recovery/subcomponentrecovery.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR + "/dbaccess/source/core/dataaccess/documentcontainer.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR + "/dbaccess/source/core/dataaccess/databasedocument.cxx")) + return; + if (loplugin::isSamePathname(fn, + SRCDIR "/dbaccess/source/ui/browser/genericcontroller.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/ucb/source/core/ucbcmds.cxx")) + return; + if (loplugin::isSamePathname(fn, + SRCDIR "/desktop/source/deployment/manager/dp_manager.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR + "/desktop/source/deployment/registry/package/dp_package.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/desktop/source/lib/init.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR + "/extensions/source/propctrlr/formcomponenthandler.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/embeddedobj/source/general/docholder.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR + "/extensions/source/propctrlr/stringrepresentation.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwpcontent.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwpdivinfo.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwpdoc.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/filter/source/pdf/impdialog.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwplayout.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwpoleobject.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwprowlayout.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwpfoundry.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwpparastyle.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwpnotes.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwpfont.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwptblcell.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwpusrdicts.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwpverdocument.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/lotuswordpro/source/filter/lwptblformula.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vbahelper/source/vbahelper/vbafontbase.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/vbahelper/source/vbahelper/vbadocumentbase.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/docshell/docsh8.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/docshell/docsh6.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/core/data/table3.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/unoobj/cellsuno.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/excel/xelink.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/lotus/lotus.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/vba/vbaworkbooks.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/vba/vbaworksheets.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/ui/vba/vbarange.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/view/drviews2.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/filter/ppt/pptin.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/app/sdxfer.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/ui/view/drviewsf.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/filter/xml/sdxmlwrp.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sd/source/filter/html/pubdlg.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/txtnode/thints.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/doc/docbm.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/crsr/crsrsh.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/xml/swxml.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/core/doc/docredln.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/ww8/ww8par2.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/uibase/shells/drformsh.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/filter/ww8/ww8par6.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sw/source/ui/dbui/dbinsdlg.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sdext/source/minimizer/impoptimizer.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sdext/source/presenter/PresenterTheme.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/sdext/source/pdfimport/wrapper/wrapper.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR + "/slideshow/source/engine/animationnodes/generateevent.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/starmath/source/mathmlimport.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/starmath/source/eqnolefilehdr.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/svgio/source/svgreader/svgmarkernode.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/uui/source/iahndl-locking.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR + "/shell/source/sessioninstall/SyncDbusSessionHelper.cxx")) + return; + if (loplugin::isSamePathname(fn, + SRCDIR "/slideshow/source/engine/opengl/TransitionerImpl.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/FormattedField.cxx")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/forms/source/component/DatabaseForm.cxx")) + return; + if (loplugin::isSamePathname(fn, + SRCDIR "/reportdesign/source/ui/report/ReportController.cxx")) + return; + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/test/")) + return; + if (loplugin::isSamePathname(fn, SRCDIR "/i18npool/source/localedata/LocaleNode.cxx")) + return; + + // yynerrs? + if (loplugin::isSamePathname(fn, SRCDIR "/hwpfilter/source/grammar.cxx")) + return; + + for (MyVarInfo const& v : definitionSet) + { + bool read = readFromSet.find(v) != readFromSet.end(); + bool write = writeToSet.find(v) != writeToSet.end(); + if (!read && write) + report(DiagnosticsEngine::Warning, "write-only %0", v.varDecl->getBeginLoc()) + << v.varName; + } + } + else + { + for (const MyVarInfo& s : readFromSet) + report(DiagnosticsEngine::Warning, "read %0", s.varDecl->getBeginLoc()) << s.varName; + for (const MyVarInfo& s : writeToSet) + report(DiagnosticsEngine::Warning, "write %0", s.varDecl->getBeginLoc()) << s.varName; + } +} + +MyVarInfo WriteOnlyVars::niceName(const VarDecl* varDecl) +{ + MyVarInfo aInfo; + + aInfo.varDecl = varDecl->getCanonicalDecl(); + aInfo.varName = varDecl->getNameAsString(); + // sometimes the name (if it's an anonymous thing) contains the full path of the build folder, which we don't need + size_t idx = aInfo.varName.find(SRCDIR); + if (idx != std::string::npos) + { + aInfo.varName = aInfo.varName.replace(idx, strlen(SRCDIR), ""); + } + aInfo.varType = varDecl->getType().getAsString(); + + SourceLocation expansionLoc + = compiler.getSourceManager().getExpansionLoc(varDecl->getLocation()); + StringRef filename = getFilenameOfLocation(expansionLoc); + aInfo.sourceLocation + = std::string(filename.substr(strlen(SRCDIR) + 1)) + ":" + + std::to_string(compiler.getSourceManager().getSpellingLineNumber(expansionLoc)); + loplugin::normalizeDotDotInFilePath(aInfo.sourceLocation); + aInfo.parent = filename.str(); + + return aInfo; +} + +static bool contains(std::string const& s, std::string const& needle) +{ + return s.find(needle) != std::string::npos; +} + +bool WriteOnlyVars::VisitVarDecl(const VarDecl* varDecl) +{ + if (varDecl->isImplicit() || varDecl->isExternC() || isa(varDecl)) + return true; + auto tc = loplugin::TypeCheck(varDecl->getType()); + if (tc.Pointer() || tc.LvalueReference() || tc.Class("shared_ptr").StdNamespace() + || tc.Class("unique_ptr").StdNamespace()) + return true; + if (tc.Typedef("BitmapScopedWriteAccess")) + return true; + std::string typeName = varDecl->getType().getAsString(); + if (contains(typeName, "Guard") || contains(typeName, "Reader") || contains(typeName, "Stream") + || contains(typeName, "Parser") || contains(typeName, "Codec") + || contains(typeName, "Exception")) + return true; + varDecl = varDecl->getCanonicalDecl(); + if (!varDecl->getLocation().isValid() || ignoreLocation(varDecl)) + return true; + if (!compiler.getSourceManager().isInMainFile(varDecl->getLocation())) + return true; + if (compiler.getSourceManager().isMacroBodyExpansion(varDecl->getBeginLoc())) + return true; + if (compiler.getSourceManager().isMacroArgExpansion(varDecl->getBeginLoc())) + return true; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(varDecl->getLocation()))) + return true; + + definitionSet.insert(niceName(varDecl)); + return true; +} + +static char easytolower(char in) +{ + if (in <= 'Z' && in >= 'A') + return in - ('Z' - 'z'); + return in; +} + +bool startswith(const std::string& rStr, const char* pSubStr) +{ + return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; +} + +bool WriteOnlyVars::TraverseIfStmt(IfStmt* ifStmt) +{ + VarDecl const* varDecl = nullptr; + Expr const* cond = ifStmt->getCond()->IgnoreParenImpCasts(); + if (auto declRefExpr = dyn_cast(cond)) + { + if ((varDecl = dyn_cast(declRefExpr->getDecl()))) + insideConditionalCheckOfMemberSet.push_back(varDecl); + } + bool ret = RecursiveASTVisitor::TraverseIfStmt(ifStmt); + if (varDecl) + insideConditionalCheckOfMemberSet.pop_back(); + return ret; +} + +void WriteOnlyVars::checkIfReadFrom(const VarDecl* varDecl, const Expr* memberExpr) +{ + auto parentsRange = compiler.getASTContext().getParents(*memberExpr); + const Stmt* child = memberExpr; + const Stmt* parent + = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get(); + // walk up the tree until we find something interesting + bool bPotentiallyReadFrom = false; + bool bDump = false; + auto walkupUp = [&]() { + child = parent; + auto parentsRange = compiler.getASTContext().getParents(*parent); + parent = parentsRange.begin() == parentsRange.end() ? nullptr + : parentsRange.begin()->get(); + }; + do + { + if (!parent) + { + // check if we're inside a CXXCtorInitializer or a VarDecl + auto parentsRange = compiler.getASTContext().getParents(*child); + if (parentsRange.begin() != parentsRange.end()) + { + const Decl* decl = parentsRange.begin()->get(); + if (decl && (isa(decl) || isa(decl))) + bPotentiallyReadFrom = true; + } + if (!bPotentiallyReadFrom) + return; + break; + } + if (isa(parent)) + { + // once we see one of these, there is not much useful we can know + bPotentiallyReadFrom = true; + break; + } + else if (isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent)) + { + walkupUp(); + } + else if (auto unaryOperator = dyn_cast(parent)) + { + UnaryOperator::Opcode op = unaryOperator->getOpcode(); + if (memberExpr->getType()->isArrayType() && op == UO_Deref) + { + // ignore, deref'ing an array does not count as a read + } + else if (op == UO_AddrOf || op == UO_Deref || op == UO_Plus || op == UO_Minus + || op == UO_Not || op == UO_LNot) + { + bPotentiallyReadFrom = true; + break; + } + /* The following are technically reads, but from a code-sense they're more of a write/modify, so + ignore them to find interesting fields that only modified, not usefully read: + UO_PreInc / UO_PostInc / UO_PreDec / UO_PostDec + But we still walk up in case the result of the expression is used in a read sense. + */ + walkupUp(); + } + else if (auto caseStmt = dyn_cast(parent)) + { + bPotentiallyReadFrom = caseStmt->getLHS() == child || caseStmt->getRHS() == child; + break; + } + else if (auto ifStmt = dyn_cast(parent)) + { + bPotentiallyReadFrom = ifStmt->getCond() == child; + break; + } + else if (auto doStmt = dyn_cast(parent)) + { + bPotentiallyReadFrom = doStmt->getCond() == child; + break; + } + else if (auto arraySubscriptExpr = dyn_cast(parent)) + { + if (arraySubscriptExpr->getIdx() == child) + { + bPotentiallyReadFrom = true; + break; + } + walkupUp(); + } + else if (auto callExpr = dyn_cast(parent)) + { + // check for calls to ReadXXX() type methods and the operator>>= methods on Any. + auto callee = getCallee(callExpr); + if (callee && *callExpr->child_begin() == child) + { + // FIXME perhaps a better solution here would be some kind of SAL_PARAM_WRITEONLY attribute + // which we could scatter around. + std::string name = callee->getNameAsString(); + std::transform(name.begin(), name.end(), name.begin(), easytolower); + if (startswith(name, "read")) + // this is a write-only call + ; + else if (startswith(name, "emplace") || name == "insert" || name == "erase" + || name == "remove" || name == "remove_if" || name == "sort" + || name == "push_back" || name == "pop_back" || name == "push_front" + || name == "pop_front" || name == "reserve" || name == "resize" + || name == "clear" || name == "fill") + // write-only modifications to collections + ; + else if (name.find(">>=") != std::string::npos && callExpr->getArg(1) == child) + // this is a write-only call + ; + else if (name == "dispose" || name == "disposeAndClear" || name == "swap") + // we're abusing the write-only analysis here to look for vars which don't have anything useful + // being done to them, so we're ignoring things like std::vector::clear, std::vector::swap, + // and VclPtr::disposeAndClear + ; + else + bPotentiallyReadFrom = true; + } + else + bPotentiallyReadFrom = true; + break; + } + else if (auto callExpr = dyn_cast(parent)) + { + // check for calls to ReadXXX() type methods and the operator>>= methods on Any. + auto callee = getCallee(callExpr); + if (callee) + { + // FIXME perhaps a better solution here would be some kind of SAL_PARAM_WRITEONLY attribute + // which we could scatter around. + std::string name = callee->getNameAsString(); + std::transform(name.begin(), name.end(), name.begin(), easytolower); + if (startswith(name, "read")) + // this is a write-only call + ; + else if (name.find(">>=") != std::string::npos && callExpr->getArg(1) == child) + // this is a write-only call + ; + else + bPotentiallyReadFrom = true; + } + else + bPotentiallyReadFrom = true; + break; + } + else if (auto binaryOp = dyn_cast(parent)) + { + BinaryOperator::Opcode op = binaryOp->getOpcode(); + // If the child is on the LHS and it is an assignment op, we are obviously not reading from it + const bool assignmentOp = op == BO_Assign || op == BO_MulAssign || op == BO_DivAssign + || op == BO_RemAssign || op == BO_AddAssign + || op == BO_SubAssign || op == BO_ShlAssign + || op == BO_ShrAssign || op == BO_AndAssign + || op == BO_XorAssign || op == BO_OrAssign; + if (!(binaryOp->getLHS() == child && assignmentOp)) + { + bPotentiallyReadFrom = true; + } + break; + } + else if (isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent)) + { + bPotentiallyReadFrom = true; + break; + } + else if (isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent)) + { + break; + } + else + { + bPotentiallyReadFrom = true; + bDump = true; + break; + } + } while (true); + + if (bDump) + { + report(DiagnosticsEngine::Warning, "oh dear, what can the matter be?", + memberExpr->getBeginLoc()) + << memberExpr->getSourceRange(); + report(DiagnosticsEngine::Note, "parent over here", parent->getBeginLoc()) + << parent->getSourceRange(); + parent->dump(); + memberExpr->dump(); + } + + MyVarInfo varInfo = niceName(varDecl); + if (bPotentiallyReadFrom) + { + readFromSet.insert(varInfo); + } +} + +void WriteOnlyVars::checkIfWrittenTo(const VarDecl* varDecl, const Expr* memberExpr) +{ + // if we're inside a block that looks like + // if (varDecl) + // ... + // then writes to this var don't matter, because unless we find another write to this var, this var is dead + if (std::find(insideConditionalCheckOfMemberSet.begin(), + insideConditionalCheckOfMemberSet.end(), varDecl) + != insideConditionalCheckOfMemberSet.end()) + return; + + auto parentsRange = compiler.getASTContext().getParents(*memberExpr); + const Stmt* child = memberExpr; + const Stmt* parent + = parentsRange.begin() == parentsRange.end() ? nullptr : parentsRange.begin()->get(); + // walk up the tree until we find something interesting + bool bPotentiallyWrittenTo = false; + bool bDump = false; + auto walkupUp = [&]() { + child = parent; + auto parentsRange = compiler.getASTContext().getParents(*parent); + parent = parentsRange.begin() == parentsRange.end() ? nullptr + : parentsRange.begin()->get(); + }; + do + { + if (!parent) + { + // check if we have an expression like + // int& r = var; + auto parentsRange = compiler.getASTContext().getParents(*child); + if (parentsRange.begin() != parentsRange.end()) + { + auto varDecl = dyn_cast_or_null(parentsRange.begin()->get()); + // The isImplicit() call is to avoid triggering when we see the vardecl which is part of a for-range statement, + // which is of type 'T&&' and also an l-value-ref ? + if (varDecl && !varDecl->isImplicit() + && loplugin::TypeCheck(varDecl->getType()).LvalueReference().NonConst()) + { + bPotentiallyWrittenTo = true; + } + } + break; + } + if (isa(parent)) + { + // once we see one of these, there is not much useful we can know + bPotentiallyWrittenTo = true; + break; + } + else if (isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent)) + { + walkupUp(); + } + else if (auto unaryOperator = dyn_cast(parent)) + { + UnaryOperator::Opcode op = unaryOperator->getOpcode(); + if (op == UO_AddrOf || op == UO_PostInc || op == UO_PostDec || op == UO_PreInc + || op == UO_PreDec) + { + bPotentiallyWrittenTo = true; + } + break; + } + else if (auto arraySubscriptExpr = dyn_cast(parent)) + { + if (arraySubscriptExpr->getIdx() == child) + break; + walkupUp(); + } + else if (auto operatorCallExpr = dyn_cast(parent)) + { + auto callee = getCallee(operatorCallExpr); + if (callee) + { + // if calling a non-const operator on the var + auto calleeMethodDecl = callee->getAsCXXMethodDecl(); + if (calleeMethodDecl && operatorCallExpr->getArg(0) == child) + { + if (!calleeMethodDecl->isConst()) + bPotentiallyWrittenTo + = checkForWriteWhenUsingCollectionType(calleeMethodDecl); + } + else if (IsPassedByNonConst(varDecl, child, operatorCallExpr, *callee)) + { + bPotentiallyWrittenTo = true; + } + } + else + bPotentiallyWrittenTo = true; // conservative, could improve + break; + } + else if (auto cxxMemberCallExpr = dyn_cast(parent)) + { + const CXXMethodDecl* calleeMethodDecl = cxxMemberCallExpr->getMethodDecl(); + if (calleeMethodDecl) + { + // if calling a non-const method on the var + const Expr* tmp = dyn_cast(child); + if (tmp->isBoundMemberFunction(compiler.getASTContext())) + { + tmp = dyn_cast(tmp)->getBase(); + } + if (cxxMemberCallExpr->getImplicitObjectArgument() == tmp) + { + if (!calleeMethodDecl->isConst()) + bPotentiallyWrittenTo + = checkForWriteWhenUsingCollectionType(calleeMethodDecl); + break; + } + else if (IsPassedByNonConst(varDecl, child, cxxMemberCallExpr, + CalleeWrapper(calleeMethodDecl))) + bPotentiallyWrittenTo = true; + } + else + bPotentiallyWrittenTo = true; // can happen in templates + break; + } + else if (auto cxxConstructExpr = dyn_cast(parent)) + { + if (IsPassedByNonConst(varDecl, child, cxxConstructExpr, + CalleeWrapper(cxxConstructExpr))) + bPotentiallyWrittenTo = true; + break; + } + else if (auto callExpr = dyn_cast(parent)) + { + auto callee = getCallee(callExpr); + if (callee) + { + if (IsPassedByNonConst(varDecl, child, callExpr, *callee)) + bPotentiallyWrittenTo = true; + } + else + bPotentiallyWrittenTo = true; // conservative, could improve + break; + } + else if (auto binaryOp = dyn_cast(parent)) + { + BinaryOperator::Opcode op = binaryOp->getOpcode(); + const bool assignmentOp = op == BO_Assign || op == BO_MulAssign || op == BO_DivAssign + || op == BO_RemAssign || op == BO_AddAssign + || op == BO_SubAssign || op == BO_ShlAssign + || op == BO_ShrAssign || op == BO_AndAssign + || op == BO_XorAssign || op == BO_OrAssign; + if (assignmentOp) + { + if (binaryOp->getLHS() == child) + bPotentiallyWrittenTo = true; + else if (loplugin::TypeCheck(binaryOp->getLHS()->getType()) + .LvalueReference() + .NonConst()) + // if the LHS is a non-const reference, we could write to the var later on + bPotentiallyWrittenTo = true; + } + break; + } + else if (isa(parent)) + { + if (insideFunctionDecl) + { + auto tc = loplugin::TypeCheck(insideFunctionDecl->getReturnType()); + if (tc.LvalueReference().NonConst()) + bPotentiallyWrittenTo = true; + } + break; + } + else if (isa(parent) || isa(parent) + || isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent) || isa(parent) || isa(parent) + || isa(parent) || isa(parent) + || isa(parent)) + { + break; + } + else + { + bPotentiallyWrittenTo = true; + bDump = true; + break; + } + } while (true); + + if (bDump) + { + report(DiagnosticsEngine::Warning, "oh dear2, what can the matter be? writtenTo=%0", + memberExpr->getBeginLoc()) + << bPotentiallyWrittenTo << memberExpr->getSourceRange(); + if (parent) + { + report(DiagnosticsEngine::Note, "parent over here", parent->getBeginLoc()) + << parent->getSourceRange(); + parent->dump(); + } + memberExpr->dump(); + varDecl->getType()->dump(); + } + + MyVarInfo varInfo = niceName(varDecl); + if (bPotentiallyWrittenTo) + { + writeToSet.insert(varInfo); + } +} + +// return true if this not a collection type, or if it is a collection type, and we might be writing to it +bool WriteOnlyVars::checkForWriteWhenUsingCollectionType(const CXXMethodDecl* calleeMethodDecl) +{ + auto const tc = loplugin::TypeCheck(calleeMethodDecl->getParent()); + bool listLike = false, setLike = false, mapLike = false, cssSequence = false; + if (tc.Class("deque").StdNamespace() || tc.Class("list").StdNamespace() + || tc.Class("queue").StdNamespace() || tc.Class("vector").StdNamespace()) + { + listLike = true; + } + else if (tc.Class("set").StdNamespace() || tc.Class("unordered_set").StdNamespace()) + { + setLike = true; + } + else if (tc.Class("map").StdNamespace() || tc.Class("unordered_map").StdNamespace()) + { + mapLike = true; + } + else if (tc.Class("Sequence") + .Namespace("uno") + .Namespace("star") + .Namespace("sun") + .Namespace("com") + .GlobalNamespace()) + { + cssSequence = true; + } + else + return true; + + if (calleeMethodDecl->isOverloadedOperator()) + { + auto oo = calleeMethodDecl->getOverloadedOperator(); + if (oo == OO_Equal) + return true; + // This is operator[]. We only care about things that add elements to the collection. + // if nothing modifies the size of the collection, then nothing useful + // is stored in it. + if (listLike) + return false; + return true; + } + + auto name = calleeMethodDecl->getName(); + if (listLike || setLike || mapLike) + { + if (name == "reserve" || name == "shrink_to_fit" || name == "clear" || name == "erase" + || name == "pop_back" || name == "pop_front" || name == "front" || name == "back" + || name == "data" || name == "remove" || name == "remove_if" || name == "unique" + || name == "sort" || name == "begin" || name == "end" || name == "rbegin" + || name == "rend" || name == "at" || name == "find" || name == "equal_range" + || name == "lower_bound" || name == "upper_bound") + return false; + } + if (cssSequence) + { + if (name == "getArray" || name == "begin" || name == "end") + return false; + } + + return true; +} + +bool WriteOnlyVars::IsPassedByNonConst(const VarDecl* varDecl, const Stmt* child, + CallerWrapper callExpr, CalleeWrapper calleeFunctionDecl) +{ + unsigned len = std::min(callExpr.getNumArgs(), calleeFunctionDecl.getNumParams()); + // if it's an array, passing it by value to a method typically means the + // callee takes a pointer and can modify the array + if (varDecl->getType()->isConstantArrayType()) + { + for (unsigned i = 0; i < len; ++i) + if (callExpr.getArg(i) == child) + if (loplugin::TypeCheck(calleeFunctionDecl.getParamType(i)).Pointer().NonConst()) + return true; + } + else + { + for (unsigned i = 0; i < len; ++i) + if (callExpr.getArg(i) == child) + if (loplugin::TypeCheck(calleeFunctionDecl.getParamType(i)) + .LvalueReference() + .NonConst()) + return true; + } + return false; +} + +bool WriteOnlyVars::VisitDeclRefExpr(const DeclRefExpr* declRefExpr) +{ + const Decl* decl = declRefExpr->getDecl(); + const VarDecl* varDecl = dyn_cast(decl); + if (!varDecl) + return true; + if (varDecl->isImplicit() || isa(varDecl)) + return true; + varDecl = varDecl->getCanonicalDecl(); + if (ignoreLocation(varDecl)) + return true; + // ignore stuff that forms part of the stable URE interface + if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(varDecl->getLocation()))) + return true; + + checkIfReadFrom(varDecl, declRefExpr); + + checkIfWrittenTo(varDecl, declRefExpr); + + return true; +} + +llvm::Optional WriteOnlyVars::getCallee(CallExpr const* callExpr) +{ + FunctionDecl const* functionDecl = callExpr->getDirectCallee(); + if (functionDecl) + return CalleeWrapper(functionDecl); + + // Extract the functionprototype from a type + clang::Type const* calleeType = callExpr->getCallee()->getType().getTypePtr(); + if (auto pointerType = calleeType->getUnqualifiedDesugaredType()->getAs()) + { + if (auto prototype = pointerType->getPointeeType() + ->getUnqualifiedDesugaredType() + ->getAs()) + { + return CalleeWrapper(prototype); + } + } + + return llvm::Optional(); +} + +loplugin::Plugin::Registration X("writeonlyvars", false); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/xmlimport.cxx b/compilerplugins/clang/xmlimport.cxx new file mode 100644 index 000000000..1f9f44090 --- /dev/null +++ b/compilerplugins/clang/xmlimport.cxx @@ -0,0 +1,394 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" +#include "check.hxx" +#include "config_clang.h" +#include +#include +#include "clang/AST/CXXInheritance.h" + +/* + * This is a compile-time checker. + * + * Check that when we override SvXmlImportContext, and we override createFastChildContext, + * we have also overridden startFastElement, or the fast-parser stuff will not work + * correctly. +*/ + +namespace +{ +class XmlImport : public loplugin::FilteringPlugin +{ +public: + explicit XmlImport(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override + { + StringRef fn(handler.getMainFileName()); + if (loplugin::isSamePathname(fn, SRCDIR "/xmloff/source/core/xmlictxt.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/xmloff/source/core/xmlimp.cxx")) + return false; + // These are mostly classes delegating calls to other classes + if (loplugin::isSamePathname(fn, SRCDIR "/xmloff/source/text/XMLTextFrameContext.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/xmloff/source/draw/ximpshap.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/xmloff/source/table/XMLTableImport.cxx")) + return false; + if (loplugin::isSamePathname(fn, + SRCDIR "/sc/source/filter/xml/XMLTrackedChangesContext.cxx")) + return false; + if (loplugin::isSamePathname(fn, SRCDIR "/sc/source/filter/xml/xmlannoi.cxx")) + return false; + // this class specifically wants to prevent some endFastElement processing happening in its superclass + if (loplugin::isSamePathname(fn, SRCDIR + "/xmloff/source/text/XMLIndexBibliographySourceContext.cxx")) + return false; + // calling mxSlaveContext + if (loplugin::isSamePathname(fn, SRCDIR "/xmloff/source/draw/XMLNumberStyles.cxx")) + return false; + return true; + } + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitCXXMethodDecl(const CXXMethodDecl*); + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr*); + bool VisitBinaryOperator(const BinaryOperator*); + bool VisitSwitchStmt(const SwitchStmt*); + bool VisitCallExpr(const CallExpr*); + +private: + bool isXmlTokEnum(const Expr*); + bool isUInt16(const Expr*); + bool isUInt16(QualType); + + std::unordered_map startFastElementSet; + std::unordered_map StartElementSet; + std::unordered_map endFastElementSet; + std::unordered_map EndElementSet; + std::unordered_map charactersSet; + std::unordered_map CharactersSet; +}; + +bool XmlImport::VisitCXXMethodDecl(const CXXMethodDecl* methodDecl) +{ + auto beginLoc = methodDecl->getBeginLoc(); + if (!beginLoc.isValid() || ignoreLocation(beginLoc)) + return true; + + if (!methodDecl->getIdentifier()) + return true; + + auto cxxRecordDecl = methodDecl->getParent(); + if (!cxxRecordDecl || !cxxRecordDecl->getIdentifier()) + return true; + + if (loplugin::DeclCheck(cxxRecordDecl).Class("SvXMLImportContext")) + return true; + + if (!loplugin::isDerivedFrom(cxxRecordDecl, [](Decl const* decl) -> bool { + auto const dc = loplugin::DeclCheck(decl); + return bool(dc.ClassOrStruct("SvXMLImportContext").GlobalNamespace()); + })) + return true; + + auto name = methodDecl->getName(); + if (name == "startFastElement") + startFastElementSet.insert({ cxxRecordDecl, methodDecl }); + else if (name == "StartElement") + StartElementSet.insert({ cxxRecordDecl, methodDecl }); + else if (name == "endFastElement") + endFastElementSet.insert({ cxxRecordDecl, methodDecl }); + else if (name == "EndElement") + EndElementSet.insert({ cxxRecordDecl, methodDecl }); + else if (name == "characters") + { + if (methodDecl->getNumParams() == 1) + charactersSet.insert({ cxxRecordDecl, methodDecl }); + } + else if (name == "Characters") + { + if (methodDecl->getNumParams() == 1) + CharactersSet.insert({ cxxRecordDecl, methodDecl }); + } + + { + auto it1 = endFastElementSet.find(cxxRecordDecl); + auto it2 = EndElementSet.find(cxxRecordDecl); + if (it1 != endFastElementSet.end() && it2 != EndElementSet.end()) + { + auto methodDecl1 = it1->second; + report(DiagnosticsEngine::Warning, "cannot override both endFastElement and EndElement", + methodDecl1->getBeginLoc()) + << methodDecl1->getSourceRange(); + auto methodDecl2 = it2->second; + report(DiagnosticsEngine::Warning, "cannot override both endFastElement and EndElement", + methodDecl2->getBeginLoc()) + << methodDecl2->getSourceRange(); + } + } + + { + auto it1 = startFastElementSet.find(cxxRecordDecl); + auto it2 = StartElementSet.find(cxxRecordDecl); + if (it1 != startFastElementSet.end() && it2 != StartElementSet.end()) + { + auto methodDecl1 = it1->second; + report(DiagnosticsEngine::Warning, + "cannot override both startFastElement and StartElement", + methodDecl1->getBeginLoc()) + << methodDecl1->getSourceRange(); + auto methodDecl2 = it2->second; + report(DiagnosticsEngine::Warning, + "cannot override both startFastElement and StartElement", + methodDecl2->getBeginLoc()) + << methodDecl2->getSourceRange(); + } + } + { + auto it1 = charactersSet.find(cxxRecordDecl); + auto it2 = CharactersSet.find(cxxRecordDecl); + if (it1 != charactersSet.end() && it2 != CharactersSet.end()) + { + auto methodDecl1 = it1->second; + report(DiagnosticsEngine::Warning, "cannot override both characters and Characters", + methodDecl1->getBeginLoc()) + << methodDecl1->getSourceRange(); + auto methodDecl2 = it2->second; + report(DiagnosticsEngine::Warning, "cannot override both characters and Characters", + methodDecl2->getBeginLoc()) + << methodDecl2->getSourceRange(); + } + } + + auto checkEmpty = [&]() { + if (!methodDecl->isThisDeclarationADefinition()) + return; + auto compoundStmt = dyn_cast_or_null(methodDecl->getBody()); + if (compoundStmt == nullptr || compoundStmt->size() > 0) + return; + report(DiagnosticsEngine::Warning, "empty, should be removed", methodDecl->getBeginLoc()) + << methodDecl->getSourceRange(); + auto canonicalDecl = methodDecl->getCanonicalDecl(); + if (canonicalDecl != methodDecl) + report(DiagnosticsEngine::Note, "definition here", canonicalDecl->getBeginLoc()) + << canonicalDecl->getSourceRange(); + }; + auto checkOnlyReturn = [&]() { + if (!methodDecl->isThisDeclarationADefinition()) + return; + auto compoundStmt = dyn_cast_or_null(methodDecl->getBody()); + if (compoundStmt == nullptr || compoundStmt->size() > 1) + return; + auto returnStmt = dyn_cast_or_null(*compoundStmt->body_begin()); + if (!returnStmt) + return; + auto cxxConstructExpr + = dyn_cast_or_null(returnStmt->getRetValue()->IgnoreImplicit()); + if (!cxxConstructExpr) + return; + if (cxxConstructExpr->getNumArgs() != 1) + return; + if (!isa(cxxConstructExpr->getArg(0)->IgnoreImplicit())) + return; + report(DiagnosticsEngine::Warning, "empty, should be removed", methodDecl->getBeginLoc()) + << methodDecl->getSourceRange(); + auto canonicalDecl = methodDecl->getCanonicalDecl(); + if (canonicalDecl != methodDecl) + report(DiagnosticsEngine::Note, "definition here", canonicalDecl->getBeginLoc()) + << canonicalDecl->getSourceRange(); + }; + + if (name == "startFastElement") + checkEmpty(); + else if (name == "endFastElement") + checkEmpty(); + else if (name == "characters") + checkEmpty(); + else if (name == "createFastChildContext") + checkOnlyReturn(); + else if (name == "createUnknownChildContext") + checkOnlyReturn(); + + return true; +} + +bool XmlImport::VisitCXXMemberCallExpr(const CXXMemberCallExpr* callExpr) +{ + auto beginLoc = callExpr->getBeginLoc(); + if (!beginLoc.isValid() || ignoreLocation(callExpr)) + return true; + + CXXMethodDecl* methodDecl = callExpr->getMethodDecl(); + if (!methodDecl || !methodDecl->getIdentifier()) + return true; + + auto cxxRecordDecl = methodDecl->getParent(); + if (!cxxRecordDecl || !cxxRecordDecl->getIdentifier()) + return true; + + if (!loplugin::DeclCheck(cxxRecordDecl).Class("SvXMLImportContext")) + return true; + + auto name = methodDecl->getName(); + if (name == "startFastElement" || name == "characters" || name == "endFastElement" + || name == "createFastChildContext" || name == "createUnknownChildContext" + || name == "StartElement" || name == "EndElement" || name == "Characters" + || name == "CreateChildContext") + { + /** + * Calling this superclass method from a subclass method will mess with the fallback logic in the superclass. + */ + report(DiagnosticsEngine::Warning, "don't call this superclass method", + callExpr->getBeginLoc()) + << callExpr->getSourceRange(); + } + return true; +} + +bool XmlImport::VisitBinaryOperator(const BinaryOperator* binaryOp) +{ + auto beginLoc = binaryOp->getBeginLoc(); + if (!beginLoc.isValid() || ignoreLocation(binaryOp)) + return true; + auto op = binaryOp->getOpcode(); + if (op != BO_EQ && op != BO_NE) + return true; + auto check2 = [&](const Expr* expr) -> void { + if (!isUInt16(expr)) + report(DiagnosticsEngine::Warning, + "comparing XML_TOK enum to 'sal_uInt32', expected sal_uInt16", + binaryOp->getBeginLoc()) + << binaryOp->getSourceRange(); + }; + if (isXmlTokEnum(binaryOp->getLHS())) + check2(binaryOp->getRHS()); + else if (isXmlTokEnum(binaryOp->getRHS())) + check2(binaryOp->getLHS()); + return true; +} + +bool XmlImport::VisitSwitchStmt(const SwitchStmt* switchStmt) +{ + auto beginLoc = switchStmt->getBeginLoc(); + if (!beginLoc.isValid() || ignoreLocation(switchStmt)) + return true; + if (isUInt16(switchStmt->getCond())) + return true; + // if the condition is an enum type, ignore this switch + auto condEnumType = switchStmt->getCond() + ->IgnoreImplicit() + ->getType() + ->getUnqualifiedDesugaredType() + ->getAs(); + if (condEnumType) + return true; + auto switchCaseStmt = switchStmt->getSwitchCaseList(); + for (; switchCaseStmt != nullptr; switchCaseStmt = switchCaseStmt->getNextSwitchCase()) + { + auto caseStmt = dyn_cast(switchCaseStmt); + if (!caseStmt) + continue; + if (!isXmlTokEnum(caseStmt->getLHS())) + continue; + report(DiagnosticsEngine::Warning, + "comparing XML_TOK enum to 'sal_uInt32', expected sal_uInt16", + caseStmt->getBeginLoc()) + << caseStmt->getSourceRange(); + } + return true; +} + +bool XmlImport::VisitCallExpr(const CallExpr* callExpr) +{ + auto beginLoc = callExpr->getBeginLoc(); + if (!beginLoc.isValid() || ignoreLocation(callExpr)) + return true; + + const FunctionDecl* functionDecl; + if (isa(callExpr)) + functionDecl = dyn_cast(callExpr)->getMethodDecl(); + else + functionDecl = callExpr->getDirectCallee(); + if (!functionDecl) + return true; + for (unsigned i = 0; i != callExpr->getNumArgs(); ++i) + { + auto argExpr = callExpr->getArg(i)->IgnoreImplicit(); + if (!isXmlTokEnum(argExpr)) + continue; + // if the condition is an enum type, ignore this switch + auto condEnumType = functionDecl->getParamDecl(i) + ->getType() + ->getUnqualifiedDesugaredType() + ->getAs(); + if (condEnumType) + continue; + if (isUInt16(functionDecl->getParamDecl(i)->getType())) + return true; + report(DiagnosticsEngine::Warning, + "passing XML_TOK enum to 'sal_Int32', wrong param or XML token type", + callExpr->getBeginLoc()) + << callExpr->getSourceRange(); + } + + return true; +} + +bool XmlImport::isXmlTokEnum(const Expr* expr) +{ + expr = expr->IgnoreImplicit(); + // check that we have an unscoped enum type + auto condEnumType = expr->getType()->getUnqualifiedDesugaredType()->getAs(); + if (!condEnumType || condEnumType->getDecl()->isScoped()) + return false; + auto declRefExpr = dyn_cast(expr); + if (!declRefExpr) + return false; + auto enumConstant = dyn_cast(declRefExpr->getDecl()); + if (!enumConstant) + return false; + return enumConstant->getIdentifier() && enumConstant->getName().startswith("XML_TOK_"); +} + +bool XmlImport::isUInt16(const Expr* expr) +{ + expr = expr->IgnoreImplicit(); + return isUInt16(expr->getType()); +} + +bool XmlImport::isUInt16(QualType qt) +{ + if (qt->isSpecificBuiltinType(BuiltinType::UShort)) + return true; + return bool(loplugin::TypeCheck(qt).Typedef("sal_uInt16")); +} + +loplugin::Plugin::Registration xmlimport("xmlimport"); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3