Merge branch 'revert-mutex-delete' into multi-mutex-lock

This commit is contained in:
Paul 2020-07-14 13:05:14 -05:00
commit 1f74400f13
43 changed files with 1949 additions and 223 deletions

View File

@ -35,7 +35,6 @@ before_install:
- travis_retry python3 -m pip install --user pexpect # imported by tools/ci.py
- travis_retry python3 -m pip install --user requests # imported by tools/pr.py
- travis_retry python3 -m pip install --user pygments
- travis_retry sudo python3 -m pip install demjson # installs jsonlint => sudo required
- travis_retry python3 -m pip install --user natsort
- cp externals/z3_version_old.h externals/z3_version.h # because travis z3 version is old
@ -183,7 +182,7 @@ matrix:
- make -s -j2 CXXFLAGS=-funsigned-char testrunner
- ./testrunner TestSymbolDatabase
# check .json files
- find . -name '*.json' -not -path '*/\.*' | xargs jsonlint -s
- find . -name '*.json' | xargs -n 1 python3 -m json.tool > /dev/null
# build fuzz client
- make -s -j2 CXXFLAGS="-fsanitize=address" -C oss-fuzz fuzz-client

View File

@ -484,7 +484,7 @@ $(libcppdir)/checkuninitvar.o: lib/checkuninitvar.cpp lib/astutils.h lib/check.h
$(libcppdir)/checkunusedfunctions.o: lib/checkunusedfunctions.cpp externals/tinyxml/tinyxml2.h lib/astutils.h lib/check.h lib/checkunusedfunctions.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkunusedfunctions.o $(libcppdir)/checkunusedfunctions.cpp
$(libcppdir)/checkunusedvar.o: lib/checkunusedvar.cpp lib/astutils.h lib/check.h lib/checkunusedvar.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(libcppdir)/checkunusedvar.o: lib/checkunusedvar.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/check.h lib/checkunusedvar.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkunusedvar.o $(libcppdir)/checkunusedvar.cpp
$(libcppdir)/checkvaarg.o: lib/checkvaarg.cpp lib/astutils.h lib/check.h lib/checkvaarg.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
@ -556,7 +556,7 @@ $(libcppdir)/timer.o: lib/timer.cpp lib/config.h lib/timer.h
$(libcppdir)/token.o: lib/token.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/token.o $(libcppdir)/token.cpp
$(libcppdir)/tokenize.o: lib/tokenize.cpp lib/check.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/check.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/tokenize.o $(libcppdir)/tokenize.cpp
$(libcppdir)/tokenlist.o: lib/tokenlist.cpp externals/simplecpp/simplecpp.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h
@ -622,7 +622,7 @@ test/testclass.o: test/testclass.cpp externals/tinyxml/tinyxml2.h lib/check.h li
test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlineparser.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/redirect.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testcmdlineparser.o test/testcmdlineparser.cpp
test/testcondition.o: test/testcondition.cpp externals/simplecpp/simplecpp.h externals/tinyxml/tinyxml2.h lib/check.h lib/checkcondition.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
test/testcondition.o: test/testcondition.cpp externals/simplecpp/simplecpp.h externals/tinyxml/tinyxml2.h lib/check.h lib/checkcondition.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testcondition.o test/testcondition.cpp
test/testconstructors.o: test/testconstructors.cpp lib/check.h lib/checkclass.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
@ -679,7 +679,7 @@ test/testnullpointer.o: test/testnullpointer.cpp externals/simplecpp/simplecpp.h
test/testoptions.o: test/testoptions.cpp lib/config.h lib/errorlogger.h lib/errortypes.h lib/suppressions.h test/options.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testoptions.o test/testoptions.cpp
test/testother.o: test/testother.cpp externals/simplecpp/simplecpp.h externals/tinyxml/tinyxml2.h lib/check.h lib/checkother.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
test/testother.o: test/testother.cpp externals/simplecpp/simplecpp.h externals/tinyxml/tinyxml2.h lib/check.h lib/checkother.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testother.o test/testother.cpp
test/testpath.o: test/testpath.cpp lib/config.h lib/errorlogger.h lib/errortypes.h lib/path.h lib/suppressions.h test/testsuite.h
@ -760,7 +760,7 @@ test/testunusedfunctions.o: test/testunusedfunctions.cpp lib/check.h lib/checkun
test/testunusedprivfunc.o: test/testunusedprivfunc.cpp externals/simplecpp/simplecpp.h lib/check.h lib/checkclass.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testunusedprivfunc.o test/testunusedprivfunc.cpp
test/testunusedvar.o: test/testunusedvar.cpp lib/check.h lib/checkunusedvar.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
test/testunusedvar.o: test/testunusedvar.cpp externals/simplecpp/simplecpp.h lib/check.h lib/checkunusedvar.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testunusedvar.o test/testunusedvar.cpp
test/testutils.o: test/testutils.cpp lib/config.h lib/errorlogger.h lib/errortypes.h lib/suppressions.h lib/utils.h test/testsuite.h

View File

@ -5047,11 +5047,14 @@
<define name="Q_DISABLE_COPY(C)" value="C(C&amp;);C&amp; operator=(const C&amp;);"/>
<define name="Q_ENUM(X)" value=""/>
<define name="Q_ENUMS(X)" value=""/>
<define name="Q_ENUM_NS(X)" value=""/>
<define name="Q_FLAG(X)" value=""/>
<define name="Q_FLAGS(X)" value=""/>
<define name="Q_FLAG_NS(X)" value=""/>
<define name="Q_FOREVER" value="for (;;)"/>
<define name="Q_INTERFACES(X)" value=""/>
<define name="Q_LIKELY(expr)" value="expr"/>
<define name="Q_NAMESPACE" value=""/>
<define name="Q_NULLPTR" value="NULL"/>
<define name="Q_OBJECT" value=""/>
<define name="Q_PRIVATE_SLOT(d, signature)" value=""/>

View File

@ -1475,6 +1475,16 @@
<not-uninit/>
</arg>
</function>
<!-- int std::at_quick_exit( /*atexit-handler*/* func ) noexcept;-->
<function name="std::at_quick_exit,at_quick_exit">
<noreturn>false</noreturn>
<use-retval/>
<returnValue type="int"/>
<arg nr="1" direction="in">
<not-uninit/>
<not-null/>
</arg>
</function>
<!-- double fabs(double x); -->
<function name="fabs,std::fabs">
<use-retval/>
@ -3755,8 +3765,8 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<valid>0:</valid>
</arg>
</function>
<!-- const void * memchr ( const void * ptr, int value, size_t num );-->
<!-- void * memchr ( void * ptr, int value, size_t num );-->
<!-- const void * memchr ( const void * ptr, int value, size_t num ); -->
<!-- void * memchr ( void * ptr, int value, size_t num ); -->
<function name="memchr,std::memchr">
<use-retval/>
<pure/>
@ -4222,6 +4232,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<arg nr="2" direction="in">
<not-null/>
<not-uninit/>
<minsize type="argvalue" arg="3"/>
</arg>
<arg nr="3" direction="in">
<not-uninit/>

View File

@ -6113,6 +6113,22 @@ HFONT CreateFont(
<not-uninit/>
</arg>
</function>
<!-- BOOL SystemParametersInfoA(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni); -->
<function name="SystemParametersInfo,SystemParametersInfoA,SystemParametersInfoW">
<noreturn>false</noreturn>
<returnValue type="BOOL"/>
<leak-ignore/>
<arg nr="1" direction="in">
<not-uninit/>
</arg>
<arg nr="2" direction="in">
<not-uninit/>
</arg>
<arg nr="3" direction="out"/>
<arg nr="4" direction="in">
<not-uninit/>
</arg>
</function>
<!-- BOOL WINAPI CancelIo(
_In_ HANDLE hFile); -->
<function name="CancelIo">
@ -12645,6 +12661,147 @@ HFONT CreateFont(
<define name="INVALID_SET_FILE_POINTER" value="((DWORD)-1)"/>
<define name="INVALID_FILE_ATTRIBUTES" value="((DWORD)-1)"/>
<!-- WinUser.h -->
<define name="SPI_GETBEEP" value="0x0001"/>
<define name="SPI_SETBEEP" value="0x0002"/>
<define name="SPI_GETMOUSE" value="0x0003"/>
<define name="SPI_SETMOUSE" value="0x0004"/>
<define name="SPI_GETBORDER" value="0x0005"/>
<define name="SPI_SETBORDER" value="0x0006"/>
<define name="SPI_GETKEYBOARDSPEED" value="0x000A"/>
<define name="SPI_SETKEYBOARDSPEED" value="0x000B"/>
<define name="SPI_LANGDRIVER" value="0x000C"/>
<define name="SPI_ICONHORIZONTALSPACING" value="0x000D"/>
<define name="SPI_GETSCREENSAVETIMEOUT" value="0x000E"/>
<define name="SPI_SETSCREENSAVETIMEOUT" value="0x000F"/>
<define name="SPI_GETSCREENSAVEACTIVE" value="0x0010"/>
<define name="SPI_SETSCREENSAVEACTIVE" value="0x0011"/>
<define name="SPI_GETGRIDGRANULARITY" value="0x0012"/>
<define name="SPI_SETGRIDGRANULARITY" value="0x0013"/>
<define name="SPI_SETDESKWALLPAPER" value="0x0014"/>
<define name="SPI_SETDESKPATTERN" value="0x0015"/>
<define name="SPI_GETKEYBOARDDELAY" value="0x0016"/>
<define name="SPI_SETKEYBOARDDELAY" value="0x0017"/>
<define name="SPI_ICONVERTICALSPACING" value="0x0018"/>
<define name="SPI_GETICONTITLEWRAP" value="0x0019"/>
<define name="SPI_SETICONTITLEWRAP" value="0x001A"/>
<define name="SPI_GETMENUDROPALIGNMENT" value="0x001B"/>
<define name="SPI_SETMENUDROPALIGNMENT" value="0x001C"/>
<define name="SPI_SETDOUBLECLKWIDTH" value="0x001D"/>
<define name="SPI_SETDOUBLECLKHEIGHT" value="0x001E"/>
<define name="SPI_GETICONTITLELOGFONT" value="0x001F"/>
<define name="SPI_SETDOUBLECLICKTIME" value="0x0020"/>
<define name="SPI_SETMOUSEBUTTONSWAP" value="0x0021"/>
<define name="SPI_SETICONTITLELOGFONT" value="0x0022"/>
<define name="SPI_GETFASTTASKSWITCH" value="0x0023"/>
<define name="SPI_SETFASTTASKSWITCH" value="0x0024"/>
<define name="SPI_SETDRAGFULLWINDOWS" value="0x0025"/>
<define name="SPI_GETDRAGFULLWINDOWS" value="0x0026"/>
<define name="SPI_GETNONCLIENTMETRICS" value="0x0029"/>
<define name="SPI_SETNONCLIENTMETRICS" value="0x002A"/>
<define name="SPI_GETMINIMIZEDMETRICS" value="0x002B"/>
<define name="SPI_SETMINIMIZEDMETRICS" value="0x002C"/>
<define name="SPI_GETICONMETRICS" value="0x002D"/>
<define name="SPI_SETICONMETRICS" value="0x002E"/>
<define name="SPI_SETWORKAREA" value="0x002F"/>
<define name="SPI_GETWORKAREA" value="0x0030"/>
<define name="SPI_SETPENWINDOWS" value="0x0031"/>
<define name="SPI_GETHIGHCONTRAST" value="0x0042"/>
<define name="SPI_SETHIGHCONTRAST" value="0x0043"/>
<define name="SPI_GETKEYBOARDPREF" value="0x0044"/>
<define name="SPI_SETKEYBOARDPREF" value="0x0045"/>
<define name="SPI_GETSCREENREADER" value="0x0046"/>
<define name="SPI_SETSCREENREADER" value="0x0047"/>
<define name="SPI_GETANIMATION" value="0x0048"/>
<define name="SPI_SETANIMATION" value="0x0049"/>
<define name="SPI_GETFONTSMOOTHING" value="0x004A"/>
<define name="SPI_SETFONTSMOOTHING" value="0x004B"/>
<define name="SPI_SETDRAGWIDTH" value="0x004C"/>
<define name="SPI_SETDRAGHEIGHT" value="0x004D"/>
<define name="SPI_SETHANDHELD" value="0x004E"/>
<define name="SPI_GETLOWPOWERTIMEOUT" value="0x004F"/>
<define name="SPI_GETPOWEROFFTIMEOUT" value="0x0050"/>
<define name="SPI_SETLOWPOWERTIMEOUT" value="0x0051"/>
<define name="SPI_SETPOWEROFFTIMEOUT" value="0x0052"/>
<define name="SPI_GETLOWPOWERACTIVE" value="0x0053"/>
<define name="SPI_GETPOWEROFFACTIVE" value="0x0054"/>
<define name="SPI_SETLOWPOWERACTIVE" value="0x0055"/>
<define name="SPI_SETPOWEROFFACTIVE" value="0x0056"/>
<define name="SPI_SETCURSORS" value="0x0057"/>
<define name="SPI_SETICONS" value="0x0058"/>
<define name="SPI_GETDEFAULTINPUTLANG" value="0x0059"/>
<define name="SPI_SETDEFAULTINPUTLANG" value="0x005A"/>
<define name="SPI_SETLANGTOGGLE" value="0x005B"/>
<define name="SPI_GETWINDOWSEXTENSION" value="0x005C"/>
<define name="SPI_SETMOUSETRAILS" value="0x005D"/>
<define name="SPI_GETMOUSETRAILS" value="0x005E"/>
<define name="SPI_SETSCREENSAVERRUNNING" value="0x0061"/>
<define name="SPI_SCREENSAVERRUNNING" value="SPI_SETSCREENSAVERRUNNING"/>
<define name="SPI_GETFILTERKEYS" value="0x0032"/>
<define name="SPI_SETFILTERKEYS" value="0x0033"/>
<define name="SPI_GETTOGGLEKEYS" value="0x0034"/>
<define name="SPI_SETTOGGLEKEYS" value="0x0035"/>
<define name="SPI_GETMOUSEKEYS" value="0x0036"/>
<define name="SPI_SETMOUSEKEYS" value="0x0037"/>
<define name="SPI_GETSHOWSOUNDS" value="0x0038"/>
<define name="SPI_SETSHOWSOUNDS" value="0x0039"/>
<define name="SPI_GETSTICKYKEYS" value="0x003A"/>
<define name="SPI_SETSTICKYKEYS" value="0x003B"/>
<define name="SPI_GETACCESSTIMEOUT" value="0x003C"/>
<define name="SPI_SETACCESSTIMEOUT" value="0x003D"/>
<define name="SPI_GETSERIALKEYS" value="0x003E"/>
<define name="SPI_SETSERIALKEYS" value="0x003F"/>
<define name="SPI_GETSOUNDSENTRY" value="0x0040"/>
<define name="SPI_SETSOUNDSENTRY" value="0x0041"/>
<define name="SPI_GETSNAPTODEFBUTTON" value="0x005F"/>
<define name="SPI_SETSNAPTODEFBUTTON" value="0x0060"/>
<define name="SPI_GETMOUSEHOVERWIDTH" value="0x0062"/>
<define name="SPI_SETMOUSEHOVERWIDTH" value="0x0063"/>
<define name="SPI_GETMOUSEHOVERHEIGHT" value="0x0064"/>
<define name="SPI_SETMOUSEHOVERHEIGHT" value="0x0065"/>
<define name="SPI_GETMOUSEHOVERTIME" value="0x0066"/>
<define name="SPI_SETMOUSEHOVERTIME" value="0x0067"/>
<define name="SPI_GETWHEELSCROLLLINES" value="0x0068"/>
<define name="SPI_SETWHEELSCROLLLINES" value="0x0069"/>
<define name="SPI_GETMENUSHOWDELAY" value="0x006A"/>
<define name="SPI_SETMENUSHOWDELAY" value="0x006B"/>
<define name="SPI_GETWHEELSCROLLCHARS" value="0x006C"/>
<define name="SPI_SETWHEELSCROLLCHARS" value="0x006D"/>
<define name="SPI_GETSHOWIMEUI" value="0x006E"/>
<define name="SPI_SETSHOWIMEUI" value="0x006F"/>
<define name="SPI_GETMOUSESPEED" value="0x0070"/>
<define name="SPI_SETMOUSESPEED" value="0x0071"/>
<define name="SPI_GETSCREENSAVERRUNNING" value="0x0072"/>
<define name="SPI_GETDESKWALLPAPER" value="0x0073"/>
<define name="SPI_GETAUDIODESCRIPTION" value="0x0074"/>
<define name="SPI_SETAUDIODESCRIPTION" value="0x0075"/>
<define name="SPI_GETSCREENSAVESECURE" value="0x0076"/>
<define name="SPI_SETSCREENSAVESECURE" value="0x0077"/>
<define name="SPI_GETHUNGAPPTIMEOUT" value="0x0078"/>
<define name="SPI_SETHUNGAPPTIMEOUT" value="0x0079"/>
<define name="SPI_GETWAITTOKILLTIMEOUT" value="0x007A"/>
<define name="SPI_SETWAITTOKILLTIMEOUT" value="0x007B"/>
<define name="SPI_GETWAITTOKILLSERVICETIMEOUT" value="0x007C"/>
<define name="SPI_SETWAITTOKILLSERVICETIMEOUT" value="0x007D"/>
<define name="SPI_GETMOUSEDOCKTHRESHOLD" value="0x007E"/>
<define name="SPI_SETMOUSEDOCKTHRESHOLD" value="0x007F"/>
<define name="SPI_GETPENDOCKTHRESHOLD" value="0x0080"/>
<define name="SPI_SETPENDOCKTHRESHOLD" value="0x0081"/>
<define name="SPI_GETWINARRANGING" value="0x0082"/>
<define name="SPI_SETWINARRANGING" value="0x0083"/>
<define name="SPI_GETMOUSEDRAGOUTTHRESHOLD" value="0x0084"/>
<define name="SPI_SETMOUSEDRAGOUTTHRESHOLD" value="0x0085"/>
<define name="SPI_GETPENDRAGOUTTHRESHOLD" value="0x0086"/>
<define name="SPI_SETPENDRAGOUTTHRESHOLD" value="0x0087"/>
<define name="SPI_GETMOUSESIDEMOVETHRESHOLD" value="0x0088"/>
<define name="SPI_SETMOUSESIDEMOVETHRESHOLD" value="0x0089"/>
<define name="SPI_GETPENSIDEMOVETHRESHOLD" value="0x008A"/>
<define name="SPI_SETPENSIDEMOVETHRESHOLD" value="0x008B"/>
<define name="SPI_GETDRAGFROMMAXIMIZE" value="0x008C"/>
<define name="SPI_SETDRAGFROMMAXIMIZE" value="0x008D"/>
<define name="SPI_GETSNAPSIZING" value="0x008E"/>
<define name="SPI_SETSNAPSIZING" value="0x008F"/>
<define name="SPI_GETDOCKMOVING" value="0x0090"/>
<define name="SPI_SETDOCKMOVING" value="0x0091"/>
<define name="IDOK" value="1"/>
<define name="IDCANCEL" value="2"/>
<define name="IDABORT" value="3"/>

View File

@ -5139,6 +5139,17 @@
<not-uninit/>
</arg>
</function>
<!-- void wxString::SetChar(size_t n, wxUniChar ch) -->
<function name="wxString::SetChar">
<returnValue type="size_t"/>
<noreturn>false</noreturn>
<leak-ignore/>
<arg nr="1" direction="in">
<not-uninit/>
<valid>0:</valid>
</arg>
<arg nr="2" direction="in"/>
</function>
<!-- wxUniChar wxString::GetChar(size_t n) const -->
<function name="wxString::GetChar">
<returnValue type="wxUniChar"/>
@ -5528,6 +5539,19 @@
<not-bool/>
</arg>
</function>
<!-- virtual wxString wxListbox::GetString (unsigned int n) const-->
<function name="wxListbox::GetString">
<noreturn>false</noreturn>
<leak-ignore/>
<use-retval/>
<const/>
<returnValue type="wxString"/>
<arg nr="1" direction="in">
<valid>0:</valid>
<not-uninit/>
<not-bool/>
</arg>
</function>
<!--virtual int wxListBox::GetSelection(void) const-->
<function name="wxListBox::GetSelection">
<noreturn>false</noreturn>
@ -6189,6 +6213,7 @@
<use-retval/>
</function>
<!--virtual bool wxWindow::Enable(bool enable = true)-->
<!--virtual bool wxComboBox::Enable(bool enable = true)-->
<!--virtual bool wxButton::Enable(bool enable = true)-->
<!--virtual bool wxAnyButton::Enable(bool enable = true)-->
<!--virtual bool wxBitmapButton::Enable(bool enable = true)-->
@ -6201,7 +6226,7 @@
<!--virtual bool wxStaticBitmap::Enable(bool enable = true)-->
<!--virtual bool wxSpinCtrl::Enable(bool enable = true)-->
<!--virtual bool wxOwnerDrawnComboBox::Enable(bool enable = true)-->
<function name="wxWindow::Enable,wxButton::Enable,wxStaticBitmap::Enable,wxSpinCtrl::Enable,wxAnyButton::Enable,wxCommandLinkButton::Enable,wxToggleButton::Enable,wxOwnerDrawnComboBox::Enable,wxBitmapToggleButton::Enable,wxContextHelpButton::Enable,wxBitmapButton::Enable,wxPropertyGridManager::Enable,wxFilePickerCtrl::Enable">
<function name="wxWindow::Enable,wxComboBox::Enable,wxButton::Enable,wxStaticBitmap::Enable,wxSpinCtrl::Enable,wxAnyButton::Enable,wxCommandLinkButton::Enable,wxToggleButton::Enable,wxOwnerDrawnComboBox::Enable,wxBitmapToggleButton::Enable,wxContextHelpButton::Enable,wxBitmapButton::Enable,wxPropertyGridManager::Enable,wxFilePickerCtrl::Enable">
<noreturn>false</noreturn>
<leak-ignore/>
<returnValue type="bool"/>
@ -9907,7 +9932,8 @@
</function>
<!-- wxSizerItem* wxSizer::AddStretchSpacer (int prop = 1) -->
<!-- wxSizerItem* wxBoxSizer::AddStretchSpacer (int prop = 1) -->
<function name="wxSizer::AddStretchSpacer,wxBoxSizer::AddStretchSpacer">
<!-- wxSizerItem* wxStaticBoxSizer::AddStretchSpacer (int prop = 1) -->
<function name="wxSizer::AddStretchSpacer,wxBoxSizer::AddStretchSpacer,wxStaticBoxSizer::AddStretchSpacer">
<noreturn>false</noreturn>
<leak-ignore/>
<returnValue type="wxSizerItem *"/>
@ -11177,6 +11203,21 @@
<arg nr="4" direction="in" default="wxEmptyString"/>
<arg nr="5" direction="in" default="wxITEM_NORMAL"/>
</function>
<!-- wxAuiToolBarItem* wxAuiToolBar::AddTool(int tool_id, const wxString & label, const wxBitmap & bitmap, const wxString & short_help_string = wxEmptyString,
wxItemKind kind = wxITEM_NORMAL) -->
<function name="wxToolBar::AddTool">
<leak-ignore/>
<noreturn>false</noreturn>
<returnValue type="wxAuiToolBarItem*"/>
<arg nr="1" direction="in">
<not-uninit/>
<not-bool/>
</arg>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in" default="wxEmptyString"/>
<arg nr="5" direction="in" default="wxITEM_NORMAL"/>
</function>
<!-- wxString wxString::SubString( size_t from, size_t to ) const -->
<function name="wxString::SubString">
<leak-ignore/>
@ -13076,6 +13117,17 @@
<use-retval/>
<arg nr="1"/>
</function>
<!-- bool wxAuiManager::AddPane(wxWindow * window, const wxAuiPaneInfo & pane_info)-->
<!-- bool wxAuiManager::AddPane(wxWindow * window, int direction = wxLEFT, const wxString & caption = wxEmptyString) -->
<!-- bool wxAuiManager::AddPane(wxWindow * window, const wxAuiPaneInfo & pane_info, const wxPoint & drop_pos) -->
<function name="wxAuiManager::AddPane">
<noreturn>false</noreturn>
<returnValue type="bool"/>
<leak-ignore/>
<arg nr="1"/>
<arg nr="2" direction="in" default="wxLEFT"/>
<arg nr="3" direction="in" default="wxEmptyString"/>
</function>
<!-- virtual void wxConfigBase::SetPath(const wxString &strPath) = 0 -->
<!-- virtual void wxConfig::SetPath(const wxString &strPath) -->
<!-- virtual void wxFileConfig::SetPath(const wxString &strPath)-->
@ -14272,4 +14324,24 @@
<arg nr="4" default="0" direction="in"/>
<arg nr="5" default="NULL" direction="in"/>
</function>
<!-- bool wxImageList::Create (int width, int height, bool mask = true, int initialCount = 1) -->
<function name="wxImageList::Create">
<noreturn>false</noreturn>
<returnValue type="bool"/>
<arg nr="1" direction="in">
<not-uninit/>
<valid>0:</valid>
</arg>
<arg nr="2" direction="in">
<not-uninit/>
<valid>0:</valid>
</arg>
<arg nr="3" default="true" direction="in">
<not-uninit/>
</arg>
<arg nr="4" default="1" direction="in">
<not-uninit/>
<valid>0:</valid>
</arg>
</function>
</def>

View File

@ -1026,15 +1026,15 @@ void simplecpp::TokenList::constFoldBitwise(Token *tok)
{
Token * const tok1 = tok;
for (const char *op = "&^|"; *op; op++) {
const std::string* altop;
const std::string* alternativeOp;
if (*op == '&')
altop = &BITAND;
alternativeOp = &BITAND;
else if (*op == '|')
altop = &BITOR;
alternativeOp = &BITOR;
else
altop = &XOR;
alternativeOp = &XOR;
for (tok = tok1; tok && tok->op != ')'; tok = tok->next) {
if (tok->op != *op && !isAlternativeBinaryOp(tok, *altop))
if (tok->op != *op && !isAlternativeBinaryOp(tok, *alternativeOp))
continue;
if (!tok->previous || !tok->previous->number)
continue;
@ -1472,7 +1472,8 @@ namespace simplecpp {
}
const Token *appendTokens(TokenList *tokens,
const Token *lpar,
const Location &rawloc,
const Token * const lpar,
const std::map<TokenString,Macro> &macros,
const std::set<TokenString> &expandedmacros,
const std::vector<const Token*> &parametertokens) const {
@ -1483,17 +1484,17 @@ namespace simplecpp {
while (sameline(lpar, tok)) {
if (tok->op == '#' && sameline(tok,tok->next) && tok->next->op == '#' && sameline(tok,tok->next->next)) {
// A##B => AB
tok = expandHashHash(tokens, tok->location, tok, macros, expandedmacros, parametertokens);
tok = expandHashHash(tokens, rawloc, tok, macros, expandedmacros, parametertokens);
} else if (tok->op == '#' && sameline(tok, tok->next) && tok->next->op != '#') {
tok = expandHash(tokens, tok->location, tok, macros, expandedmacros, parametertokens);
tok = expandHash(tokens, rawloc, tok, macros, expandedmacros, parametertokens);
} else {
if (!expandArg(tokens, tok, tok->location, macros, expandedmacros, parametertokens)) {
if (!expandArg(tokens, tok, rawloc, macros, expandedmacros, parametertokens)) {
bool expanded = false;
const std::map<TokenString, Macro>::const_iterator it = macros.find(tok->str());
if (it != macros.end() && expandedmacros.find(tok->str()) == expandedmacros.end()) {
const Macro &m = it->second;
if (!m.functionLike()) {
m.expand(tokens, tok->location, tok, macros, expandedmacros);
m.expand(tokens, rawloc, tok, macros, expandedmacros);
expanded = true;
}
}
@ -1511,6 +1512,8 @@ namespace simplecpp {
tok = tok->next;
}
}
for (Token *tok2 = tokens->front(); tok2; tok2 = tok2->next)
tok2->location = lpar->location;
return sameline(lpar,tok) ? tok : NULL;
}
@ -1612,13 +1615,19 @@ namespace simplecpp {
hashToken = hashToken->next;
++numberOfHash;
}
if (numberOfHash == 4) {
if (numberOfHash == 4 && tok->next->location.col + 1 == tok->next->next->location.col) {
// # ## # => ##
output->push_back(newMacroToken("##", loc, isReplaced(expandedmacros)));
tok = hashToken;
continue;
}
if (numberOfHash >= 2 && tok->location.col + 1 < tok->next->location.col) {
output->push_back(new Token(*tok));
tok = tok->next;
continue;
}
tok = tok->next;
if (tok == endToken) {
output->push_back(new Token(*tok->previous));
@ -1645,6 +1654,41 @@ namespace simplecpp {
return functionLike() ? parametertokens2.back()->next : nameTokInst->next;
}
const Token *recursiveExpandToken(TokenList *output, TokenList &temp, const Location &loc, const Token *tok, const std::map<TokenString,Macro> &macros, const std::set<TokenString> &expandedmacros, const std::vector<const Token*> &parametertokens) const {
if (!(temp.cback() && temp.cback()->name && tok->next && tok->next->op == '(')) {
output->takeTokens(temp);
return tok->next;
}
if (!sameline(tok, tok->next)) {
output->takeTokens(temp);
return tok->next;
}
const std::map<TokenString, Macro>::const_iterator it = macros.find(temp.cback()->str());
if (it == macros.end() || expandedmacros.find(temp.cback()->str()) != expandedmacros.end()) {
output->takeTokens(temp);
return tok->next;
}
const Macro &calledMacro = it->second;
if (!calledMacro.functionLike()) {
output->takeTokens(temp);
return tok->next;
}
TokenList temp2(files);
temp2.push_back(new Token(temp.cback()->str(), tok->location));
const Token *tok2 = appendTokens(&temp2, loc, tok->next, macros, expandedmacros, parametertokens);
if (!tok2)
return tok->next;
output->takeTokens(temp);
output->deleteToken(output->back());
calledMacro.expand(output, loc, temp2.cfront(), macros, expandedmacros);
return tok2->next;
}
const Token *expandToken(TokenList *output, const Location &loc, const Token *tok, const std::map<TokenString,Macro> &macros, const std::set<TokenString> &expandedmacros, const std::vector<const Token*> &parametertokens) const {
// Not name..
if (!tok->name) {
@ -1655,63 +1699,36 @@ namespace simplecpp {
// Macro parameter..
{
TokenList temp(files);
if (expandArg(&temp, tok, loc, macros, expandedmacros, parametertokens)) {
if (!(temp.cback() && temp.cback()->name && tok->next && tok->next->op == '(')) {
output->takeTokens(temp);
return tok->next;
}
if (!sameline(tok, tok->next)) {
output->takeTokens(temp);
return tok->next;
}
const std::map<TokenString, Macro>::const_iterator it = macros.find(temp.cback()->str());
if (it == macros.end() || expandedmacros.find(temp.cback()->str()) != expandedmacros.end()) {
output->takeTokens(temp);
return tok->next;
}
const Macro &calledMacro = it->second;
if (!calledMacro.functionLike()) {
output->takeTokens(temp);
return tok->next;
}
TokenList temp2(files);
temp2.push_back(new Token(temp.cback()->str(), tok->location));
const Token *tok2 = appendTokens(&temp2, tok->next, macros, expandedmacros, parametertokens);
if (!tok2)
return tok->next;
output->takeTokens(temp);
output->deleteToken(output->back());
calledMacro.expand(output, loc, temp2.cfront(), macros, expandedmacros);
return tok2->next;
}
if (expandArg(&temp, tok, loc, macros, expandedmacros, parametertokens))
return recursiveExpandToken(output, temp, loc, tok, macros, expandedmacros, parametertokens);
}
// Macro..
const std::map<TokenString, Macro>::const_iterator it = macros.find(tok->str());
if (it != macros.end() && expandedmacros.find(tok->str()) == expandedmacros.end()) {
std::set<std::string> expandedmacros2(expandedmacros);
expandedmacros2.insert(tok->str());
const Macro &calledMacro = it->second;
if (!calledMacro.functionLike())
return calledMacro.expand(output, loc, tok, macros, expandedmacros);
if (!calledMacro.functionLike()) {
TokenList temp(files);
calledMacro.expand(&temp, loc, tok, macros, expandedmacros);
return recursiveExpandToken(output, temp, loc, tok, macros, expandedmacros2, parametertokens);
}
if (!sameline(tok, tok->next) || tok->next->op != '(') {
output->push_back(newMacroToken(tok->str(), loc, true));
return tok->next;
}
TokenList tokens(files);
tokens.push_back(new Token(*tok));
const Token *tok2 = appendTokens(&tokens, tok->next, macros, expandedmacros, parametertokens);
const Token *tok2 = appendTokens(&tokens, loc, tok->next, macros, expandedmacros, parametertokens);
if (!tok2) {
output->push_back(newMacroToken(tok->str(), loc, true));
return tok->next;
}
calledMacro.expand(output, loc, tokens.cfront(), macros, expandedmacros);
return tok2->next;
TokenList temp(files);
calledMacro.expand(&temp, loc, tokens.cfront(), macros, expandedmacros);
return recursiveExpandToken(output, temp, loc, tok2, macros, expandedmacros2, parametertokens);
}
else if (tok->str() == DEFINED) {
@ -1879,7 +1896,7 @@ namespace simplecpp {
if (tokensB.empty() && sameline(B,B->next) && B->next->op=='(') {
const std::map<TokenString,Macro>::const_iterator it = macros.find(strAB);
if (it != macros.end() && expandedmacros.find(strAB) == expandedmacros.end() && it->second.functionLike()) {
const Token *tok2 = appendTokens(&tokens, B->next, macros, expandedmacros, parametertokens);
const Token *tok2 = appendTokens(&tokens, loc, B->next, macros, expandedmacros, parametertokens);
if (tok2)
nextTok = tok2->next;
}

View File

@ -1133,7 +1133,7 @@ void ResultsTree::saveResults(Report *report) const
report->writeFooter();
}
void ResultsTree::saveErrors(Report *report, QStandardItem *fileItem) const
void ResultsTree::saveErrors(Report *report, const QStandardItem *fileItem) const
{
if (!fileItem) {
return;

View File

@ -333,7 +333,7 @@ protected:
* @param report Report that errors are saved to
* @param fileItem Item whose errors to save
*/
void saveErrors(Report *report, QStandardItem *fileItem) const;
void saveErrors(Report *report, const QStandardItem *fileItem) const;
/**
* @brief Convert a severity string to a icon filename

View File

@ -171,13 +171,6 @@ void ResultsView::updateFromOldReport(const QString &filename) const
void ResultsView::save(const QString &filename, Report::Type type) const
{
if (!hasResults()) {
QMessageBox msgBox;
msgBox.setText(tr("No errors found, nothing to save."));
msgBox.setIcon(QMessageBox::Critical);
msgBox.exec();
}
Report *report = nullptr;
switch (type) {

View File

@ -59,12 +59,6 @@ void AnalyzerInformation::writeFilesTxt(const std::string &buildDir, const std::
const std::string afile = getFilename(fs.filename);
fout << afile << ".a" << (++fileCount[afile]) << ":" << fs.cfg << ":" << Path::simplifyPath(Path::fromNativeSeparators(fs.filename)) << std::endl;
}
std::ofstream fc(buildDir + "/__temp__.c");
fc << "int x;\n";
std::ofstream fcpp(buildDir + "/__temp__.cpp");
fcpp << "int x;\n";
}
void AnalyzerInformation::close()

View File

@ -438,7 +438,9 @@ const Token* getCondTokFromEnd(const Token* endBlock)
bool extractForLoopValues(const Token *forToken,
nonneg int * const varid,
bool * const knownInitValue,
MathLib::bigint * const initValue,
bool * const partialCond,
MathLib::bigint * const stepValue,
MathLib::bigint * const lastValue)
{
@ -447,10 +449,21 @@ bool extractForLoopValues(const Token *forToken,
const Token *initExpr = forToken->next()->astOperand2()->astOperand1();
const Token *condExpr = forToken->next()->astOperand2()->astOperand2()->astOperand1();
const Token *incExpr = forToken->next()->astOperand2()->astOperand2()->astOperand2();
if (!initExpr || !initExpr->isBinaryOp() || initExpr->str() != "=" || !Token::Match(initExpr->astOperand1(), "%var%") || !initExpr->astOperand2()->hasKnownIntValue())
if (!initExpr || !initExpr->isBinaryOp() || initExpr->str() != "=" || !Token::Match(initExpr->astOperand1(), "%var%"))
return false;
*varid = initExpr->astOperand1()->varId();
*initValue = initExpr->astOperand2()->getKnownIntValue();
*knownInitValue = initExpr->astOperand2()->hasKnownIntValue();
*initValue = (*knownInitValue) ? initExpr->astOperand2()->getKnownIntValue() : 0;
*partialCond = Token::Match(condExpr, "%oror%|&&");
visitAstNodes(condExpr, [varid, &condExpr](const Token *tok) {
if (Token::Match(tok, "%oror%|&&"))
return ChildrenToVisit::op1_and_op2;
if (Token::Match(tok, "<|<=") && tok->isBinaryOp() && tok->astOperand1()->varId() == *varid && tok->astOperand2()->hasKnownIntValue()) {
if (Token::Match(condExpr, "%oror%|&&") || tok->astOperand2()->getKnownIntValue() < condExpr->astOperand2()->getKnownIntValue())
condExpr = tok;
}
return ChildrenToVisit::none;
});
if (!Token::Match(condExpr, "<|<=") || !condExpr->isBinaryOp() || condExpr->astOperand1()->varId() != *varid || !condExpr->astOperand2()->hasKnownIntValue())
return false;
if (!incExpr || !incExpr->isUnaryOp("++") || incExpr->astOperand1()->varId() != *varid)
@ -539,7 +552,10 @@ bool exprDependsOnThis(const Token* expr, nonneg int depth)
// calling nonstatic method?
if (Token::Match(expr->previous(), "!!:: %name% (") && expr->function() && expr->function()->nestedIn && expr->function()->nestedIn->isClassOrStruct()) {
// is it a method of this?
const Scope *nestedIn = expr->scope()->functionOf;
const Scope* fScope = expr->scope();
while (!fScope->functionOf && fScope->nestedIn)
fScope = fScope->nestedIn;
const Scope* nestedIn = fScope->functionOf;
if (nestedIn && nestedIn->function)
nestedIn = nestedIn->function->token->scope();
while (nestedIn && nestedIn != expr->function()->nestedIn) {
@ -1293,7 +1309,7 @@ const Token * getTokenArgumentFunction(const Token * tok, int& argn)
return tok;
}
const Variable* getArgumentVar(const Token* tok, int argnr)
static const Variable* getArgumentVar(const Token* tok, int argnr)
{
if (!tok)
return nullptr;
@ -1562,6 +1578,27 @@ bool isVariablesChanged(const Token* start,
return false;
}
bool isThisChanged(const Token* start, const Token* end, int indirect, const Settings* settings, bool cpp)
{
for (const Token* tok = start; tok != end; tok = tok->next()) {
if (!exprDependsOnThis(tok))
continue;
if (Token::Match(tok->previous(), "%name% (")) {
if (tok->previous()->function()) {
if (!tok->previous()->function()->isConst())
return true;
else
continue;
} else if (!tok->previous()->isKeyword()) {
return true;
}
}
if (isVariableChanged(tok, indirect, settings, cpp))
return true;
}
return false;
}
int numberOfArguments(const Token *start)
{
int arguments=0;

View File

@ -113,7 +113,9 @@ const Token* getCondTokFromEnd(const Token* endBlock);
*/
bool extractForLoopValues(const Token *forToken,
nonneg int * const varid,
bool * const knownInitValue,
long long * const initValue,
bool * const partialCond,
long long * const stepValue,
long long * const lastValue);
@ -192,6 +194,8 @@ bool isVariablesChanged(const Token* start,
const Settings* settings,
bool cpp);
bool isThisChanged(const Token* start, const Token* end, int indirect, const Settings* settings, bool cpp);
const Token* findVariableChanged(const Token *start, const Token *end, int indirect, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
Token* findVariableChanged(Token *start, const Token *end, int indirect, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);

View File

@ -87,7 +87,7 @@ static void divByZero(const Token *tok, const ExprEngine::Value &value, ExprEngi
return;
if (tok->isImpossibleIntValue(0))
return;
if (value.isUninit())
if (value.isUninit() && value.type != ExprEngine::ValueType::BailoutValue)
return;
float f = getKnownFloatValue(tok, 0.0f);
if (f > 0.0f || f < 0.0f)
@ -216,20 +216,18 @@ static void uninit(const Token *tok, const ExprEngine::Value &value, ExprEngine:
if (value.type == ExprEngine::ValueType::BailoutValue) {
if (tok->hasKnownValue())
return;
if (tok->function())
return;
if (Token::Match(tok, "<<|>>|,"))
// Only warn about the operands
if (!tok->variable())
// FIXME
return;
// lhs for scope operator
if (Token::Match(tok, "%name% ::"))
return;
if (tok->astParent()->str() == "::" && tok == tok->astParent()->astOperand1())
return;
if (tok->str() == "(")
// cast: result is not uninitialized if expression is initialized
// function: does not return a uninitialized value
// Object allocated on the stack
if (Token::Match(tok, "%var% .") && tok->next()->originalName() != "->")
return;
// Containers are not uninitialized
@ -242,18 +240,34 @@ static void uninit(const Token *tok, const ExprEngine::Value &value, ExprEngine:
}
const Variable *var = tok->variable();
if (var && var->nameToken() == tok)
return;
if (var && !var->isLocal())
return; // FIXME
if (var && !var->isPointer()) {
if (!var->isLocal() || var->isStatic())
return;
}
if (var && (Token::Match(var->nameToken(), "%name% =") || Token::Match(var->nameToken(), "%varid% ; %varid% =", var->declarationId())))
if (var && (Token::Match(var->nameToken(), "%name% [=:]") || Token::Match(var->nameToken(), "%varid% ; %varid% =", var->declarationId())))
return;
if (var && var->nameToken() == tok)
return;
// Are there unconditional assignment?
if (var && Token::Match(var->nameToken(), "%varid% ;| %varid%| =", tok->varId()))
return;
for (const Token *prev = tok->previous(); prev; prev = prev->previous()) {
if (!precedes(var->nameToken(), prev))
break;
if (prev->str() == "}")
prev = prev->link();
if (Token::Match(prev, "%varid% =", tok->varId()))
return;
}
}
// Uninitialized function argument
bool inconclusive = false;
if (Token::Match(tok->astParent(), "[,(]")) {
const Token *parent = tok->astParent();
int count = 0;
@ -271,10 +285,16 @@ static void uninit(const Token *tok, const ExprEngine::Value &value, ExprEngine:
const Variable *argvar = parent->astOperand1()->function()->getArgumentVar(count);
if (argvar && argvar->isReference() && !argvar->isConst())
return;
if (uninitData && argvar && !argvar->isConst())
return;
if (!uninitStructMember.empty() && dataBase->isC() && argvar && !argvar->isConst())
return;
if (uninitData && argvar && !argvar->isConst()) {
if (parent->astOperand1()->function()->hasBody())
return;
inconclusive = true;
}
if (!uninitStructMember.empty() && dataBase->isC() && argvar && !argvar->isConst()) {
if (parent->astOperand1()->function()->hasBody())
return;
inconclusive = true;
}
} else if (uninitData) {
if (dataBase->settings->library.getFunction(parent->astOperand1()))
return;
@ -285,6 +305,9 @@ static void uninit(const Token *tok, const ExprEngine::Value &value, ExprEngine:
return;
}
if (inconclusive && !dataBase->settings->inconclusive)
return;
// Avoid FP for array declaration
const Token *parent = tok->astParent();
while (parent && parent->str() == "[")
@ -292,13 +315,15 @@ static void uninit(const Token *tok, const ExprEngine::Value &value, ExprEngine:
if (!parent)
return;
const std::string inconclusiveMessage(inconclusive ? ". It is inconclusive if there would be a problem in the function call." : "");
if (!uninitStructMember.empty()) {
dataBase->reportError(tok,
Severity::SeverityType::error,
"bughuntingUninitStructMember",
"Cannot determine that '" + tok->expressionString() + "." + uninitStructMember + "' is initialized",
"Cannot determine that '" + tok->expressionString() + "." + uninitStructMember + "' is initialized" + inconclusiveMessage,
CWE_USE_OF_UNINITIALIZED_VARIABLE,
false,
inconclusive,
value.type == ExprEngine::ValueType::BailoutValue);
return;
}
@ -310,9 +335,9 @@ static void uninit(const Token *tok, const ExprEngine::Value &value, ExprEngine:
dataBase->reportError(tok,
Severity::SeverityType::error,
"bughuntingUninit",
"Cannot determine that '" + uninitexpr + "' is initialized",
"Cannot determine that '" + uninitexpr + "' is initialized" + inconclusiveMessage,
CWE_USE_OF_UNINITIALIZED_VARIABLE,
false,
inconclusive,
value.type == ExprEngine::ValueType::BailoutValue);
}

View File

@ -452,7 +452,13 @@ void CheckCondition::duplicateCondition()
continue;
bool modified = false;
visitAstNodes(cond1, [&](const Token *tok3) {
visitAstNodes(cond1, [&](const Token* tok3) {
if (exprDependsOnThis(tok3)) {
if (isThisChanged(scope.classDef->next(), cond2, false, mSettings, mTokenizer->isCPP())) {
modified = true;
return ChildrenToVisit::done;
}
}
if (tok3->varId() > 0 &&
isVariableChanged(scope.classDef->next(), cond2, tok3->varId(), false, mSettings, mTokenizer->isCPP())) {
modified = true;
@ -702,22 +708,19 @@ void CheckCondition::multiCondition2()
}
}
} else {
std::stack<const Token *> tokens2;
tokens2.push(cond2);
while (!tokens2.empty()) {
const Token *secondCondition = tokens2.top();
tokens2.pop();
if (!secondCondition)
continue;
if (secondCondition->str() == "||" || secondCondition->str() == "&&") {
tokens2.push(secondCondition->astOperand1());
tokens2.push(secondCondition->astOperand2());
} else if ((!cond1->hasKnownIntValue() || !secondCondition->hasKnownIntValue()) &&
isSameExpression(mTokenizer->isCPP(), true, cond1, secondCondition, mSettings->library, true, true, &errorPath)) {
if (!isAliased(vars))
visitAstNodes(cond2, [&](const Token *secondCondition) {
if (secondCondition->str() == "||" || secondCondition->str() == "&&")
return ChildrenToVisit::op1_and_op2;
if ((!cond1->hasKnownIntValue() || !secondCondition->hasKnownIntValue()) &&
isSameExpression(mTokenizer->isCPP(), true, cond1, secondCondition, mSettings->library, true, true, &errorPath)) {
if (!isAliased(vars) && !mTokenizer->hasIfdef(cond1, secondCondition)) {
identicalConditionAfterEarlyExitError(cond1, secondCondition, errorPath);
return ChildrenToVisit::done;
}
}
}
return ChildrenToVisit::none;
});
}
}
if (Token::Match(tok, "%name% (") && isVariablesChanged(tok, tok->linkAt(1), true, varsInCond, mSettings, mTokenizer->isCPP())) {
@ -1460,6 +1463,7 @@ void CheckCondition::alwaysTrueFalse()
// don't warn when condition checks sizeof result
bool hasSizeof = false;
bool hasNonNumber = false;
tokens.push(tok);
while (!tokens.empty()) {
const Token *tok2 = tokens.top();
@ -1476,9 +1480,9 @@ void CheckCondition::alwaysTrueFalse()
tokens.push(tok2->astOperand1());
tokens.push(tok2->astOperand2());
} else
break;
hasNonNumber = true;
}
if (tokens.empty() && hasSizeof)
if (!hasNonNumber && hasSizeof)
continue;
alwaysTrueFalseError(tok, &tok->values().front());

View File

@ -465,7 +465,11 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
// Recursively scan variable comparisons in condition
std::stack<const Token *> tokens;
tokens.push(tok->next()->astOperand2());
// Skip expressions before commas
const Token * astOperand2AfterCommas = tok->next()->astOperand2();
while (Token::simpleMatch(astOperand2AfterCommas, ","))
astOperand2AfterCommas = astOperand2AfterCommas->astOperand2();
tokens.push(astOperand2AfterCommas);
while (!tokens.empty()) {
const Token *tok3 = tokens.top();
tokens.pop();
@ -856,7 +860,8 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
}
int argNr = 1;
for (const Token *arg = tokFirstArg; arg; arg = arg->nextArgument()) {
for (const Token *funcArg = tokFirstArg; funcArg; funcArg = funcArg->nextArgument()) {
const Token* arg = funcArg;
if (mTokenizer->isCPP() && arg->str() == "new") {
arg = arg->next();
if (Token::simpleMatch(arg, "( std :: nothrow )"))

View File

@ -764,6 +764,8 @@ void CheckMemoryLeakStructMember::check()
continue;
if (var->typeEndToken()->isStandardType())
continue;
if (var->scope()->hasInlineOrLambdaFunction())
continue;
checkStructVariable(var);
}
}

View File

@ -882,6 +882,9 @@ void CheckOther::checkVariableScope()
if (var->isConst())
continue;
if (mTokenizer->hasIfdef(var->nameToken(), var->scope()->bodyEnd))
continue;
// reference of range for loop variable..
if (Token::Match(var->nameToken()->previous(), "& %var% = %var% .")) {
const Token *otherVarToken = var->nameToken()->tokAt(2);
@ -2011,7 +2014,9 @@ void CheckOther::checkDuplicateExpression()
if (tok->isOp() && tok->astOperand1() && !Token::Match(tok, "+|*|<<|>>|+=|*=|<<=|>>=")) {
if (Token::Match(tok, "==|!=|-") && astIsFloat(tok->astOperand1(), true))
continue;
const bool followVar = !isConstVarExpression(tok) || Token::Match(tok, "%comp%|%oror%|&&");
const bool pointerDereference = (tok->astOperand1() && tok->astOperand1()->isUnaryOp("*")) ||
(tok->astOperand2() && tok->astOperand2()->isUnaryOp("*"));
const bool followVar = (!isConstVarExpression(tok) || Token::Match(tok, "%comp%|%oror%|&&")) && !pointerDereference;
if (isSameExpression(mTokenizer->isCPP(),
true,
tok->astOperand1(),
@ -2637,6 +2642,7 @@ void CheckOther::checkUnusedLabel()
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
for (const Scope * scope : symbolDatabase->functionScopes) {
const bool hasIfdef = mTokenizer->hasIfdef(scope->bodyStart, scope->bodyEnd);
for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
if (!tok->scope()->isExecutable())
tok = tok->scope()->bodyEnd;
@ -2644,25 +2650,35 @@ void CheckOther::checkUnusedLabel()
if (Token::Match(tok, "{|}|; %name% :") && tok->strAt(1) != "default") {
const std::string tmp("goto " + tok->strAt(1));
if (!Token::findsimplematch(scope->bodyStart->next(), tmp.c_str(), tmp.size(), scope->bodyEnd->previous()))
unusedLabelError(tok->next(), tok->next()->scope()->type == Scope::eSwitch);
unusedLabelError(tok->next(), tok->next()->scope()->type == Scope::eSwitch, hasIfdef);
}
}
}
}
void CheckOther::unusedLabelError(const Token* tok, bool inSwitch)
void CheckOther::unusedLabelError(const Token* tok, bool inSwitch, bool hasIfdef)
{
if (inSwitch) {
if (!tok || mSettings->isEnabled(Settings::WARNING))
reportError(tok, Severity::warning, "unusedLabelSwitch",
"$symbol:" + (tok ? tok->str() : emptyString) + "\n"
"Label '$symbol' is not used. Should this be a 'case' of the enclosing switch()?", CWE398, false);
} else {
if (!tok || mSettings->isEnabled(Settings::STYLE))
reportError(tok, Severity::style, "unusedLabel",
"$symbol:" + (tok ? tok->str() : emptyString) + "\n"
"Label '$symbol' is not used.", CWE398, false);
}
if (tok && !mSettings->isEnabled(inSwitch ? Settings::WARNING : Settings::STYLE))
return;
std::string id = "unusedLabel";
if (inSwitch)
id += "Switch";
if (hasIfdef)
id += "Configuration";
std::string msg = "$symbol:" + (tok ? tok->str() : emptyString) + "\nLabel '$symbol' is not used.";
if (hasIfdef)
msg += " There is #if in function body so the label might be used in code that is removed by the preprocessor.";
if (inSwitch)
msg += " Should this be a 'case' of the enclosing switch()?";
reportError(tok,
inSwitch ? Severity::warning : Severity::style,
id,
msg,
CWE398,
false);
}

View File

@ -266,7 +266,7 @@ private:
void commaSeparatedReturnError(const Token *tok);
void redundantPointerOpError(const Token* tok, const std::string& varname, bool inconclusive);
void raceAfterInterlockedDecrementError(const Token* tok);
void unusedLabelError(const Token* tok, bool inSwitch);
void unusedLabelError(const Token* tok, bool inSwitch, bool hasIfdef);
void unknownEvaluationOrder(const Token* tok);
static bool isMovedParameterAllowedForInconclusiveFunction(const Token * tok);
void accessMovedError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive);
@ -331,8 +331,10 @@ private:
c.nanInArithmeticExpressionError(nullptr);
c.commaSeparatedReturnError(nullptr);
c.redundantPointerOpError(nullptr, "varname", false);
c.unusedLabelError(nullptr, true);
c.unusedLabelError(nullptr, false);
c.unusedLabelError(nullptr, false, false);
c.unusedLabelError(nullptr, false, true);
c.unusedLabelError(nullptr, true, false);
c.unusedLabelError(nullptr, true, true);
c.unknownEvaluationOrder(nullptr);
c.accessMovedError(nullptr, "v", nullptr, false);
c.funcArgNamesDifferent("function", 1, nullptr, nullptr);

View File

@ -21,6 +21,7 @@
#include "checkunusedvar.h"
#include "astutils.h"
#include "preprocessor.h"
#include "settings.h"
#include "symboldatabase.h"
#include "token.h"
@ -1340,6 +1341,17 @@ void CheckUnusedVar::checkStructMemberUsage()
// Packed struct => possibly used by lowlevel code. Struct members might be required by hardware.
if (scope.bodyEnd->isAttributePacked())
continue;
if (const Preprocessor *preprocessor = mTokenizer->getPreprocessor()) {
bool isPacked = false;
for (const Directive &d: preprocessor->getDirectives()) {
if (d.str == "#pragma pack(1)" && d.file == mTokenizer->list.getFiles().front() && d.linenr < scope.bodyStart->linenr()) {
isPacked=true;
break;
}
}
if (isPacked)
continue;
}
// Bail out if struct/union contains any functions
if (!scope.functionList.empty())

View File

@ -37,6 +37,15 @@
# define NOEXCEPT
#endif
// C++11 noreturn
#if (defined(__GNUC__) && (__GNUC__ >= 5)) \
|| (defined(__clang__) && (defined (__cplusplus)) && (__cplusplus >= 201103L)) \
|| defined(__CPPCHECK__)
# define NORETURN [[noreturn]]
#else
# define NORETURN
#endif
#define REQUIRES(msg, ...) class=typename std::enable_if<__VA_ARGS__::value>::type
#include <string>

View File

@ -688,16 +688,17 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
continue;
}
Tokenizer mTokenizer(&mSettings, this);
Tokenizer tokenizer(&mSettings, this);
tokenizer.setPreprocessor(&preprocessor);
if (mSettings.showtime != SHOWTIME_MODES::SHOWTIME_NONE)
mTokenizer.setTimerResults(&s_timerResults);
tokenizer.setTimerResults(&s_timerResults);
try {
// Create tokens, skip rest of iteration if failed
{
Timer timer("Tokenizer::createTokens", mSettings.showtime, &s_timerResults);
simplecpp::TokenList tokensP = preprocessor.preprocess(tokens1, mCurrentConfig, files, true);
mTokenizer.createTokens(std::move(tokensP));
tokenizer.createTokens(std::move(tokensP));
}
hasValidConfig = true;
@ -708,7 +709,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
mErrorLogger.reportOut("Checking " + fixedpath + ": " + mCurrentConfig + "...");
}
if (!mTokenizer.tokens())
if (!tokenizer.tokens())
continue;
// skip rest of iteration if just checking configuration
@ -716,11 +717,11 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
continue;
// Check raw tokens
checkRawTokens(mTokenizer);
checkRawTokens(tokenizer);
// Simplify tokens into normal form, skip rest of iteration if failed
Timer timer2("Tokenizer::simplifyTokens1", mSettings.showtime, &s_timerResults);
bool result = mTokenizer.simplifyTokens1(mCurrentConfig);
bool result = tokenizer.simplifyTokens1(mCurrentConfig);
timer2.stop();
if (!result)
continue;
@ -733,13 +734,13 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
fdump << " <cpp version=\"" << mSettings.standards.getCPP() << "\"/>" << std::endl;
fdump << " </standards>" << std::endl;
preprocessor.dump(fdump);
mTokenizer.dump(fdump);
tokenizer.dump(fdump);
fdump << "</dump>" << std::endl;
}
// Skip if we already met the same simplified token list
if (mSettings.force || mSettings.maxConfigs > 1) {
const unsigned long long checksum = mTokenizer.list.calculateChecksum();
const unsigned long long checksum = tokenizer.list.calculateChecksum();
if (checksums.find(checksum) != checksums.end()) {
if (mSettings.debugwarnings)
purgedConfigurationMessage(filename, mCurrentConfig);
@ -749,11 +750,11 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
}
// Check normal tokens
checkNormalTokens(mTokenizer);
checkNormalTokens(tokenizer);
// Analyze info..
if (!mSettings.buildDir.empty())
checkUnusedFunctions.parseTokens(mTokenizer, filename.c_str(), &mSettings);
checkUnusedFunctions.parseTokens(tokenizer, filename.c_str(), &mSettings);
// simplify more if required, skip rest of iteration if failed
if (mSimplify && hasRule("simple")) {
@ -761,13 +762,13 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
// if further simplification fails then skip rest of iteration
Timer timer3("Tokenizer::simplifyTokenList2", mSettings.showtime, &s_timerResults);
result = mTokenizer.simplifyTokenList2();
result = tokenizer.simplifyTokenList2();
timer3.stop();
if (!result)
continue;
if (!Settings::terminated())
executeRules("simple", mTokenizer);
executeRules("simple", tokenizer);
}
} catch (const simplecpp::Output &o) {
@ -779,16 +780,16 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
} catch (const InternalError &e) {
std::list<ErrorMessage::FileLocation> locationList;
if (e.token) {
ErrorMessage::FileLocation loc(e.token, &mTokenizer.list);
ErrorMessage::FileLocation loc(e.token, &tokenizer.list);
locationList.push_back(loc);
} else {
ErrorMessage::FileLocation loc(mTokenizer.list.getSourceFilePath(), 0, 0);
ErrorMessage::FileLocation loc(tokenizer.list.getSourceFilePath(), 0, 0);
ErrorMessage::FileLocation loc2(filename, 0, 0);
locationList.push_back(loc2);
locationList.push_back(loc);
}
ErrorMessage errmsg(locationList,
mTokenizer.list.getSourceFilePath(),
tokenizer.list.getSourceFilePath(),
Severity::error,
e.errorMessage,
e.id,

View File

@ -154,6 +154,7 @@ namespace {
const Token *tok;
const std::string what;
};
struct TerminateExpression {};
}
static std::string str(ExprEngine::ValuePtr val)
@ -716,6 +717,8 @@ namespace {
const std::string c = line.substr(pos, end-pos);
pos = end;
d.constraints.push_back(c);
} else {
throw ExprEngineException(nullptr, "Internal Error: Data::parsestr(), line:" + line);
}
}
importData->push_back(d);
@ -2151,6 +2154,9 @@ static ExprEngine::ValuePtr executeStringLiteral(const Token *tok, Data &data)
static ExprEngine::ValuePtr executeExpression1(const Token *tok, Data &data)
{
if (data.settings->terminated())
throw TerminateExpression();
if (tok->str() == "return")
return executeReturn(tok, data);
@ -2371,8 +2377,9 @@ static std::string execute(const Token *start, const Token *end, Data &data)
if (Token::simpleMatch(tok, "for (")) {
nonneg int varid;
bool hasKnownInitValue, partialCond;
MathLib::bigint initValue, stepValue, lastValue;
if (extractForLoopValues(tok, &varid, &initValue, &stepValue, &lastValue)) {
if (extractForLoopValues(tok, &varid, &hasKnownInitValue, &initValue, &partialCond, &stepValue, &lastValue) && hasKnownInitValue && !partialCond) {
auto loopValues = std::make_shared<ExprEngine::IntRange>(data.getNewSymbolName(), initValue, lastValue);
data.assignValue(tok, varid, loopValues);
tok = tok->linkAt(1);
@ -2486,6 +2493,8 @@ void ExprEngine::executeAllFunctions(ErrorLogger *errorLogger, const Tokenizer *
// FIXME.. there should not be exceptions
std::string functionName = functionScope->function->name();
std::cout << "Verify: Aborted analysis of function '" << functionName << "': " << e.what() << std::endl;
} catch (const TerminateExpression &) {
break;
}
}
}

View File

@ -317,11 +317,9 @@ namespace ExprEngine {
bool isEqual(DataBase * /*dataBase*/, int /*value*/) const OVERRIDE {
return true;
}
/* FIXME: This is too noisy
bool isUninit() const OVERRIDE {
return true;
}
*/
};
typedef std::function<void(const Token *, const ExprEngine::Value &, ExprEngine::DataBase *)> Callback;

View File

@ -91,6 +91,9 @@ public:
void inlineSuppressions(const simplecpp::TokenList &tokens);
void setDirectives(const simplecpp::TokenList &tokens);
void setDirectives(const std::list<Directive> &directives) {
mDirectives = directives;
}
/** list of all directives met while preprocessing file */
const std::list<Directive> &getDirectives() const {

View File

@ -3560,7 +3560,6 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
typeTok = typeTok->next();
if (Token::Match(typeTok, ",|)")) { // #8333
symbolDatabase->mTokenizer->syntaxError(typeTok);
return;
}
// skip over qualification
while (Token::Match(typeTok, "%type% ::"))
@ -4448,6 +4447,8 @@ bool Scope::hasInlineOrLambdaFunction() const
// Lambda function
if (s->type == Scope::eLambda)
return true;
if (s->hasInlineOrLambdaFunction())
return true;
}
return false;
}

View File

@ -1352,7 +1352,7 @@ bool TemplateSimplifier::getTemplateNamePositionTemplateFunction(const Token *to
// skip decltype(...)
else if (Token::simpleMatch(tok->next(), "decltype (")) {
const Token * end = tok->linkAt(2)->previous();
while (tok && tok->next() && tok != end) {
while (tok->next() && tok != end) {
tok = tok->next();
namepos++;
}
@ -1361,7 +1361,7 @@ bool TemplateSimplifier::getTemplateNamePositionTemplateFunction(const Token *to
if (closing) {
if (closing->strAt(1) == "(" && Tokenizer::isFunctionHead(closing->next(), ";|{|:", true))
return true;
while (tok && tok->next() && tok->next() != closing) {
while (tok->next() && tok->next() != closing) {
tok = tok->next();
namepos++;
}
@ -1384,7 +1384,7 @@ bool TemplateSimplifier::getTemplateNamePositionTemplateVariable(const Token *to
// skip decltype(...)
else if (Token::simpleMatch(tok->next(), "decltype (")) {
const Token * end = tok->linkAt(2);
while (tok && tok->next() && tok != end) {
while (tok->next() && tok != end) {
tok = tok->next();
namepos++;
}
@ -1393,7 +1393,7 @@ bool TemplateSimplifier::getTemplateNamePositionTemplateVariable(const Token *to
if (closing) {
if (Token::Match(closing->next(), "=|;"))
return true;
while (tok && tok->next() && tok->next() != closing) {
while (tok->next() && tok->next() != closing) {
tok = tok->next();
namepos++;
}

View File

@ -24,6 +24,7 @@
#include "library.h"
#include "mathlib.h"
#include "platform.h"
#include "preprocessor.h"
#include "settings.h"
#include "standards.h"
#include "symboldatabase.h"
@ -157,8 +158,9 @@ Tokenizer::Tokenizer() :
mCodeWithTemplates(false), //is there any templates?
mTimerResults(nullptr)
#ifdef MAXTIME
,mMaxTime(std::time(0) + MAXTIME)
, mMaxTime(std::time(0) + MAXTIME)
#endif
, mPreprocessor(nullptr)
{
}
@ -175,6 +177,7 @@ Tokenizer::Tokenizer(const Settings *settings, ErrorLogger *errorLogger) :
#ifdef MAXTIME
,mMaxTime(std::time(0) + MAXTIME)
#endif
, mPreprocessor(nullptr)
{
// make sure settings are specified
assert(mSettings);
@ -11771,3 +11774,19 @@ bool Tokenizer::VariableMap::hasVariable(const std::string &varname) const
{
return mVariableId.find(varname) != mVariableId.end();
}
bool Tokenizer::hasIfdef(const Token *start, const Token *end) const
{
if (!mPreprocessor)
return false;
for (const Directive &d: mPreprocessor->getDirectives()) {
if (d.str.compare(0,3,"#if") == 0 &&
d.linenr >= start->linenr() &&
d.linenr <= end->linenr() &&
start->fileIndex() < list.getFiles().size() &&
d.file == list.getFiles()[start->fileIndex()])
return true;
}
return false;
}

View File

@ -37,6 +37,7 @@ class TimerResults;
class Token;
class TemplateSimplifier;
class ErrorLogger;
class Preprocessor;
namespace simplecpp {
class TokenList;
@ -560,6 +561,15 @@ public:
*/
static const Token * isFunctionHead(const Token *tok, const std::string &endsWith, bool cpp);
void setPreprocessor(const Preprocessor *preprocessor) {
mPreprocessor = preprocessor;
}
const Preprocessor *getPreprocessor() const {
return mPreprocessor;
}
bool hasIfdef(const Token *start, const Token *end) const;
private:
/**
@ -607,16 +617,16 @@ private:
public:
/** Syntax error */
void syntaxError(const Token *tok, const std::string &code = "") const;
NORETURN void syntaxError(const Token *tok, const std::string &code = "") const;
/** Syntax error. Unmatched character. */
void unmatchedToken(const Token *tok) const;
NORETURN void unmatchedToken(const Token *tok) const;
/** Syntax error. C++ code in C file. */
void syntaxErrorC(const Token *tok, const std::string &what) const;
NORETURN void syntaxErrorC(const Token *tok, const std::string &what) const;
/** Warn about unknown macro(s), configuration is recommended */
void unknownMacroError(const Token *tok1) const;
NORETURN void unknownMacroError(const Token *tok1) const;
private:
@ -956,6 +966,8 @@ private:
/** Tokenizer maxtime */
const std::time_t mMaxTime;
#endif
const Preprocessor *mPreprocessor;
};
/// @}

View File

@ -4232,7 +4232,7 @@ struct ValueFlowConditionHandler {
// TODO: constValue could be true if there are no assignments in the conditional blocks and
// perhaps if there are no && and no || in the condition
bool constValue = false;
forward(after, top->scope()->bodyEnd, cond.vartok, values, constValue);
forward(after, scope->bodyEnd, cond.vartok, values, constValue);
}
}
}
@ -4444,44 +4444,6 @@ static void valueFlowInferCondition(TokenList* tokenlist,
}
}
static bool valueFlowForLoop1(const Token *tok, int * const varid, MathLib::bigint * const num1, MathLib::bigint * const num2, MathLib::bigint * const numAfter)
{
tok = tok->tokAt(2);
if (!Token::Match(tok, "%type%| %var% ="))
return false;
const Token * const vartok = Token::Match(tok, "%var% =") ? tok : tok->next();
*varid = vartok->varId();
tok = vartok->tokAt(2);
const Token * const num1tok = Token::Match(tok, "%num% ;") ? tok : nullptr;
if (num1tok)
*num1 = MathLib::toLongNumber(num1tok->str());
while (Token::Match(tok, "%name%|%num%|%or%|+|-|*|/|&|[|]|("))
tok = (tok->str() == "(") ? tok->link()->next() : tok->next();
if (!tok || tok->str() != ";")
return false;
tok = tok->next();
const Token *num2tok = nullptr;
if (Token::Match(tok, "%varid% <|<=|!=", vartok->varId())) {
tok = tok->next();
num2tok = tok->astOperand2();
if (num2tok && num2tok->str() == "(" && !num2tok->astOperand2())
num2tok = num2tok->astOperand1();
if (!Token::Match(num2tok, "%num% ;|%oror%")) // TODO: || enlarges the scope of the condition, so it should not cause FP, but it should no lnger be part of this pattern as soon as valueFlowForLoop2 can handle an unknown RHS of || better
num2tok = nullptr;
}
if (!num2tok)
return false;
*num2 = MathLib::toLongNumber(num2tok->str()) - ((tok->str()=="<=") ? 0 : 1);
*numAfter = *num2 + 1;
if (!num1tok)
*num1 = *num2;
while (tok && tok->str() != ";")
tok = tok->next();
if (!Token::Match(tok, "; %varid% ++ ) {", vartok->varId()) && !Token::Match(tok, "; ++ %varid% ) {", vartok->varId()))
return false;
return true;
}
static bool valueFlowForLoop2(const Token *tok,
ProgramMemory *memory1,
ProgramMemory *memory2,
@ -4663,16 +4625,19 @@ static void valueFlowForLoop(TokenList *tokenlist, SymbolDatabase* symboldatabas
!Token::simpleMatch(tok->next()->astOperand2()->astOperand2(), ";"))
continue;
int varid(0);
MathLib::bigint num1(0), num2(0), numAfter(0);
nonneg int varid;
bool knownInitValue, partialCond;
MathLib::bigint initValue, stepValue, lastValue;
if (valueFlowForLoop1(tok, &varid, &num1, &num2, &numAfter)) {
if (num1 <= num2) {
valueFlowForLoopSimplify(bodyStart, varid, false, num1, tokenlist, errorLogger, settings);
valueFlowForLoopSimplify(bodyStart, varid, false, num2, tokenlist, errorLogger, settings);
valueFlowForLoopSimplifyAfter(tok, varid, numAfter, tokenlist, errorLogger, settings);
} else
valueFlowForLoopSimplifyAfter(tok, varid, num1, tokenlist, errorLogger, settings);
if (extractForLoopValues(tok, &varid, &knownInitValue, &initValue, &partialCond, &stepValue, &lastValue)) {
const bool executeBody = !knownInitValue || initValue <= lastValue;
if (executeBody) {
valueFlowForLoopSimplify(bodyStart, varid, false, initValue, tokenlist, errorLogger, settings);
if (stepValue == 1)
valueFlowForLoopSimplify(bodyStart, varid, false, lastValue, tokenlist, errorLogger, settings);
}
const MathLib::bigint afterValue = executeBody ? lastValue + stepValue : initValue;
valueFlowForLoopSimplifyAfter(tok, varid, afterValue, tokenlist, errorLogger, settings);
} else {
ProgramMemory mem1, mem2, memAfter;
if (valueFlowForLoop2(tok, &mem1, &mem2, &memAfter)) {

View File

@ -1,6 +1,7 @@
# Test if --bug-hunting works using cve tests
import glob
import logging
import os
import re
import shutil
@ -14,26 +15,32 @@ else:
CPPCHECK_PATH = '../../cppcheck'
TEST_SUITE = 'cve'
slow = '--slow' in sys.argv
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
def test(test_folder):
print(test_folder)
logging.info(test_folder)
cmd_file = os.path.join(test_folder, 'cmd.txt')
expected_file = os.path.join(test_folder, 'expected.txt')
cmd = [CPPCHECK_PATH,
cmd = ['nice',
CPPCHECK_PATH,
'-D__GNUC__',
'--bug-hunting',
'--inconclusive',
'--platform=unix64',
'--template={file}:{line}:{id}',
'-rp=' + test_folder,
test_folder]
'-rp=' + test_folder]
if os.path.isfile(cmd_file):
for line in open(cmd_file, 'rt'):
if len(line) > 1:
cmd.append(line.strip())
cmd.append(test_folder)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
comm = p.communicate()
stdout = comm[0].decode(encoding='utf-8', errors='ignore')
@ -49,10 +56,20 @@ def test(test_folder):
print(stderr)
sys.exit(1)
if len(sys.argv) > 1:
if (slow is False) and len(sys.argv) > 1:
test(sys.argv[1])
sys.exit(0)
SLOW = []
for test_folder in sorted(glob.glob(TEST_SUITE + '/CVE*')):
if slow is False:
check = False
for s in SLOW:
if s in test_folder:
check = True
if check is True:
logging.info('skipping %s', test_folder)
continue
test(test_folder)

View File

@ -0,0 +1,2 @@
-DMAGICKCORE_LIBOPENJP2_DELEGATE

View File

@ -0,0 +1 @@
jp2.c:865:bughuntingUninit

File diff suppressed because it is too large Load Diff

View File

@ -38,8 +38,6 @@ def get_error_lines(filename):
linenr = 176
elif linenr == 241:
linenr = 242 # warn about usage
elif linenr == 266:
continue # no warning should be written
ret.append(linenr)
return ret

View File

@ -2040,6 +2040,19 @@ void uninivar_bsearch(void)
(void)std::bsearch(key,base,num,size,(int(*)(const void*,const void*)) strcmp);
}
void minsize_bsearch(const void* key, const void* base,
size_t num, size_t size,
int (*compar)(const void*,const void*))
{
int Base [3] = {42, 43, 44};
(void)std::bsearch(key,Base,2,size,(int(*)(const void*,const void*)) strcmp);
(void)std::bsearch(key,Base,3,size,(int(*)(const void*,const void*)) strcmp);
(void)std::bsearch(key,Base,4,size,(int(*)(const void*,const void*)) strcmp);
(void)std::bsearch(key,base,2,size,(int(*)(const void*,const void*)) strcmp);
}
void uninitvar_qsort(void)
{
void *base;

View File

@ -33,6 +33,7 @@ private:
void run() OVERRIDE {
#ifdef USE_Z3
settings.inconclusive = true;
LOAD_LIB_2(settings.library, "std.cfg");
TEST_CASE(uninit);
TEST_CASE(uninit_array);
@ -86,7 +87,7 @@ private:
check("char foo(char id[]);\n"
"void bar() { char data[10]; foo(data); }");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (error, inconclusive) Cannot determine that 'data[0]' is initialized. It is inconclusive if there would be a problem in the function call.\n", errout.str());
check("void foo(int *p) { if (p) *p=0; }");
ASSERT_EQUALS("", errout.str());

View File

@ -18,6 +18,7 @@
#include "checkcondition.h"
#include "library.h"
#include "preprocessor.h"
#include "settings.h"
#include "testsuite.h"
#include "tokenize.h"
@ -136,10 +137,14 @@ private:
std::map<std::string, simplecpp::TokenList*> filedata;
simplecpp::preprocess(tokens2, tokens1, files, filedata, simplecpp::DUI());
Preprocessor preprocessor(settings0, nullptr);
preprocessor.setDirectives(tokens1);
// Tokenizer..
Tokenizer tokenizer(&settings0, this);
tokenizer.createTokens(std::move(tokens2));
tokenizer.simplifyTokens1("");
tokenizer.setPreprocessor(&preprocessor);
// Run checks..
CheckCondition checkCondition;
@ -2570,6 +2575,18 @@ private:
" int FileIndex; \n"
"};\n");
ASSERT_EQUALS("", errout.str());
// #8858 - #if
check("short Do() {\n"
" short ret = bar1();\n"
" if ( ret )\n"
" return ret;\n"
"#ifdef FEATURE\n"
" ret = bar2();\n"
"#endif\n"
" return ret;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void innerConditionModified() {
@ -2970,14 +2987,17 @@ private:
// Avoid FP for sizeof condition
check("void f() {\n"
" if (sizeof(char) != 123) {}\n"
" if (123 != sizeof(char)) {}\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f() {\n"
" int x = 123;\n"
" if (sizeof(char) != x) {}\n"
" if (x != sizeof(char)) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'sizeof(char)!=x' is always true\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'sizeof(char)!=x' is always true\n"
"[test.cpp:4]: (style) Condition 'x!=sizeof(char)' is always true\n", errout.str());
// Don't warn in assertions. Condition is often 'always true' by intention.
// If platform,defines,etc cause an 'always false' assertion then that is not very dangerous neither
@ -3668,6 +3688,55 @@ private:
" if (a.b) {}\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("struct A {\n"
" int a;\n"
" void b() const {\n"
" return a == 1;\n"
" }\n"
" void c();\n"
" void d() {\n"
" if(b()) {\n"
" c();\n"
" }\n"
" if (b()) {\n"
" a = 3;\n"
" }\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("struct A {\n"
" int a;\n"
" void b() const {\n"
" return a == 1;\n"
" }\n"
" void d() {\n"
" if(b()) {\n"
" a = 2;\n"
" }\n"
" if (b()) {\n"
" a = 3;\n"
" }\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("struct A {\n"
" int a;\n"
" void b() const {\n"
" return a == 1;\n"
" }\n"
" void d() {\n"
" if(b()) {\n"
" }\n"
" if (b()) {\n"
" a = 3;\n"
" }\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:9]: (style) The if condition is the same as the previous if condition\n",
errout.str());
}
void checkInvalidTestForOverflow() {

View File

@ -134,6 +134,7 @@ private:
TEST_CASE(ifelse13); // #8392
TEST_CASE(ifelse14); // #9130 - if (x == (char*)NULL)
TEST_CASE(ifelse15); // #9206 - if (global_ptr = malloc(1))
TEST_CASE(ifelse16); // #9635 - if (p = malloc(4), p == NULL)
// switch
TEST_CASE(switch1);
@ -184,6 +185,8 @@ private:
TEST_CASE(smartPtrInContainer); // #8262
TEST_CASE(recursiveCountLimit); // #5872 #6157 #9097
TEST_CASE(functionCallCastConfig); // #9652
}
void check(const char code[], bool cpp = false) {
@ -202,6 +205,22 @@ private:
c.runChecks(&tokenizer, &settings, this);
}
void check(const char code[], Settings & settings) {
// Clear the error buffer..
errout.str("");
// Tokenize..
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
// Check for leaks..
CheckLeakAutoVar c;
settings.checkLibrary = true;
settings.addEnabled("information");
c.runChecks(&tokenizer, &settings, this);
}
void checkP(const char code[], bool cpp = false) {
// Clear the error buffer..
errout.str("");
@ -1466,6 +1485,26 @@ private:
ASSERT_EQUALS("", errout.str());
}
void ifelse16() { // #9635
check("void f(void) {\n"
" char *p;\n"
" if(p = malloc(4), p == NULL)\n"
" return;\n"
" free(p);\n"
" return;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(void) {\n"
" char *p, q;\n"
" if(p = malloc(4), q = 1, p == NULL)\n"
" return;\n"
" free(p);\n"
" return;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void switch1() {
check("void f() {\n"
" char *p = 0;\n"
@ -2023,6 +2062,31 @@ private:
"}"));
}
void functionCallCastConfig() { // #9652
Settings settingsFunctionCall = settings;
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
"<def format=\"2\">\n"
" <function name=\"free_func\">\n"
" <noreturn>false</noreturn>\n"
" <arg nr=\"1\">\n"
" <not-uninit/>\n"
" </arg>\n"
" <arg nr=\"2\">\n"
" <not-uninit/>\n"
" </arg>\n"
" </function>\n"
"</def>";
tinyxml2::XMLDocument doc;
doc.Parse(xmldata, sizeof(xmldata));
settingsFunctionCall.library.load(doc);
check("void test_func()\n"
"{\n"
" char * buf = malloc(4);\n"
" free_func((void *)(1), buf);\n"
"}", settingsFunctionCall);
ASSERT_EQUALS("[test.cpp:5]: (information) --check-library: Function free_func() should have <use>/<leak-ignore> configuration\n", errout.str());
}
};
REGISTER_TEST(TestLeakAutoVar)

View File

@ -1677,6 +1677,8 @@ private:
TEST_CASE(varid_2); // #5315: Analysis confused by ((variable).attribute) notation
TEST_CASE(customAllocation);
TEST_CASE(lambdaInForLoop); // #9793
}
void err() {
@ -2062,6 +2064,22 @@ private:
"}", false);
ASSERT_EQUALS("[test.c:7]: (error) Memory leak: abc.a\n", errout.str());
}
void lambdaInForLoop() { // #9793
check(
"struct S { int * p{nullptr}; };\n"
"int main()\n"
"{\n"
" S s;\n"
" s.p = new int[10];\n"
" for (int i = 0; i < 10; ++i) {\n"
" s.p[i] = []() { return 1; }();\n"
" }\n"
" delete[] s.p;\n"
" return 0;\n"
"}", true);
ASSERT_EQUALS("", errout.str());
}
};
REGISTER_TEST(TestMemleakStructMember)

View File

@ -262,7 +262,7 @@ private:
" }\n"
" tok->str();\n"
"}\n");
TODO_ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (warning, inconclusive) Possible null pointer dereference: tok - otherwise it is redundant to check it against null.\n", "", errout.str());
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (warning) Either the condition 'tok' is redundant or there is possible null pointer dereference: tok.\n", errout.str());
check("int foo(const Token *tok)\n"
"{\n"

View File

@ -19,6 +19,7 @@
#include "checkother.h"
#include "library.h"
#include "platform.h"
#include "preprocessor.h"
#include "settings.h"
#include "standards.h"
#include "testsuite.h"
@ -86,6 +87,7 @@ private:
TEST_CASE(varScope24); // pointer / reference
TEST_CASE(varScope25); // time_t
TEST_CASE(varScope26); // range for loop, map
TEST_CASE(varScope27); // #7733 - #if
TEST_CASE(oldStylePointerCast);
TEST_CASE(invalidPointerCast);
@ -241,6 +243,8 @@ private:
TEST_CASE(unusedVariableValueTemplate); // #8994
TEST_CASE(moduloOfOne);
TEST_CASE(sameExpressionPointers);
}
void check(const char code[], const char *filename = nullptr, bool experimental = false, bool inconclusive = true, bool runSimpleChecks=true, bool verbose=false, Settings* settings = nullptr) {
@ -300,10 +304,14 @@ private:
std::map<std::string, simplecpp::TokenList*> filedata;
simplecpp::preprocess(tokens2, tokens1, files, filedata, simplecpp::DUI());
Preprocessor preprocessor(*settings, nullptr);
preprocessor.setDirectives(tokens1);
// Tokenizer..
Tokenizer tokenizer(settings, this);
tokenizer.createTokens(std::move(tokens2));
tokenizer.simplifyTokens1("");
tokenizer.setPreprocessor(&preprocessor);
// Check..
CheckOther checkOther(&tokenizer, settings, this);
@ -1229,6 +1237,24 @@ private:
ASSERT_EQUALS("", errout.str());
}
void varScope27() {
checkP("void f() {\n"
" int x = 0;\n"
"#ifdef X\n"
"#endif\n"
" if (id == ABC) { return x; }\n"
"}");
ASSERT_EQUALS("", errout.str());
checkP("void f() {\n"
"#ifdef X\n"
"#endif\n"
" int x = 0;\n"
" if (id == ABC) { return x; }\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) The scope of the variable 'x' can be reduced.\n", errout.str());
}
void checkOldStylePointerCast(const char code[]) {
// Clear the error buffer..
errout.str("");
@ -5460,6 +5486,24 @@ private:
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison 'val < 0' is always false.\n"
"[test.cpp:2] -> [test.cpp:4]: (style) The comparison 'val > 0' is always false.\n", errout.str());
check("void f() {\n"
" int val = 0;\n"
" int *p = &val;n"
" val = 1;\n"
" if (*p < 0) continue;\n"
" if ((*p > 0)) {}\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void f() {\n"
" int val = 0;\n"
" int *p = &val;n"
" if (*p < 0) continue;\n"
" if ((*p > 0)) {}\n"
"}\n");
TODO_ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) The comparison '*p < 0' is always false.\n"
"[test.cpp:2] -> [test.cpp:4]: (style) The comparison '*p > 0' is always false.\n", "", errout.str());
check("void f() {\n"
" int val = 0;\n"
" if (val < 0) {\n"
@ -8677,6 +8721,15 @@ private:
ASSERT_EQUALS("", errout.str());
}
void sameExpressionPointers() {
check("int f(int *i);\n"
"void g(int *a, int *b) {\n"
" int c = *a;\n"
" f(a);\n"
" if (b && c != *a) {}\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
};
REGISTER_TEST(TestOther)

View File

@ -17,6 +17,7 @@
*/
#include "checkunusedvar.h"
#include "preprocessor.h"
#include "settings.h"
#include "testsuite.h"
#include "tokenize.h"
@ -55,6 +56,7 @@ private:
TEST_CASE(structmember12); // #7179 - FP unused structmember
TEST_CASE(structmember13); // #3088 - __attribute__((packed))
TEST_CASE(structmember14); // #6508 - (struct x){1,2,..}
TEST_CASE(structmember15); // #3088 - #pragma pack(1)
TEST_CASE(structmember_sizeof);
TEST_CASE(localvar1);
@ -211,12 +213,17 @@ private:
TEST_CASE(volatileData); // #9280
}
void checkStructMemberUsage(const char code[]) {
void checkStructMemberUsage(const char code[], const std::list<Directive> *directives=nullptr) {
// Clear the error buffer..
errout.str("");
Preprocessor preprocessor(settings, nullptr);
if (directives)
preprocessor.setDirectives(*directives);
// Tokenize..
Tokenizer tokenizer(&settings, this);
tokenizer.setPreprocessor(&preprocessor);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
@ -473,6 +480,13 @@ private:
ASSERT_EQUALS("", errout.str());
}
void structmember15() { // #3088
std::list<Directive> directives;
directives.emplace_back("test.cpp", 1, "#pragma pack(1)");
checkStructMemberUsage("\nstruct Foo { int x; int y; };", &directives);
ASSERT_EQUALS("", errout.str());
}
void structmember_extern() {
// extern struct => no false positive
checkStructMemberUsage("extern struct AB\n"