Merge branch 'revert-mutex-delete' into multi-mutex-lock
This commit is contained in:
commit
1f74400f13
|
@ -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
|
||||
|
||||
|
|
10
Makefile
10
Makefile
|
@ -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
|
||||
|
|
|
@ -5047,11 +5047,14 @@
|
|||
<define name="Q_DISABLE_COPY(C)" value="C(C&);C& operator=(const C&);"/>
|
||||
<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=""/>
|
||||
|
|
15
cfg/std.cfg
15
cfg/std.cfg
|
@ -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/>
|
||||
|
|
157
cfg/windows.cfg
157
cfg/windows.cfg
|
@ -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"/>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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> ¯os,
|
||||
const std::set<TokenString> &expandedmacros,
|
||||
const std::vector<const Token*> ¶metertokens) 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> ¯os, const std::set<TokenString> &expandedmacros, const std::vector<const Token*> ¶metertokens) 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> ¯os, const std::set<TokenString> &expandedmacros, const std::vector<const Token*> ¶metertokens) 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 )"))
|
||||
|
|
|
@ -764,6 +764,8 @@ void CheckMemoryLeakStructMember::check()
|
|||
continue;
|
||||
if (var->typeEndToken()->isStandardType())
|
||||
continue;
|
||||
if (var->scope()->hasInlineOrLambdaFunction())
|
||||
continue;
|
||||
checkStructVariable(var);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
-DMAGICKCORE_LIBOPENJP2_DELEGATE
|
||||
|
|
@ -0,0 +1 @@
|
|||
jp2.c:865:bughuntingUninit
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue