diff --git a/Makefile b/Makefile index 5a348e27001..684e79179cf 100644 --- a/Makefile +++ b/Makefile @@ -208,7 +208,6 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/addoninfo.o \ $(libcppdir)/analyzerinfo.o \ $(libcppdir)/astutils.o \ - $(libcppdir)/check.o \ $(libcppdir)/check64bit.o \ $(libcppdir)/checkassert.o \ $(libcppdir)/checkautovariables.o \ @@ -221,6 +220,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/checkersreport.o \ $(libcppdir)/checkexceptionsafety.o \ $(libcppdir)/checkfunctions.o \ + $(libcppdir)/checkimpl.o \ $(libcppdir)/checkinternal.o \ $(libcppdir)/checkio.o \ $(libcppdir)/checkleakautovar.o \ @@ -483,7 +483,7 @@ check-nonneg: ###### Build -$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkers.h lib/checkuninitvar.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/regex.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyzers.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h +$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkuninitvar.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/regex.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyzers.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.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 lib/vfvalue.h @@ -498,31 +498,28 @@ $(libcppdir)/addoninfo.o: lib/addoninfo.cpp externals/picojson/picojson.h lib/ad $(libcppdir)/analyzerinfo.o: lib/analyzerinfo.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/mathlib.h lib/path.h lib/platform.h lib/standards.h lib/utils.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/analyzerinfo.cpp -$(libcppdir)/astutils.o: lib/astutils.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkclass.h lib/checkers.h lib/config.h lib/errortypes.h lib/findtoken.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vfvalue.h +$(libcppdir)/astutils.o: lib/astutils.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkclass.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/findtoken.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/astutils.cpp -$(libcppdir)/check.o: lib/check.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/check.cpp - -$(libcppdir)/check64bit.o: lib/check64bit.cpp lib/addoninfo.h lib/check.h lib/check64bit.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/check64bit.o: lib/check64bit.cpp lib/addoninfo.h lib/check.h lib/check64bit.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/check64bit.cpp -$(libcppdir)/checkassert.o: lib/checkassert.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkassert.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkassert.o: lib/checkassert.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkassert.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkassert.cpp -$(libcppdir)/checkautovariables.o: lib/checkautovariables.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkautovariables.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checkautovariables.o: lib/checkautovariables.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkautovariables.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkautovariables.cpp -$(libcppdir)/checkbool.o: lib/checkbool.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkbool.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkbool.o: lib/checkbool.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkbool.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkbool.cpp -$(libcppdir)/checkbufferoverrun.o: lib/checkbufferoverrun.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkbufferoverrun.h lib/checkers.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vf_common.h lib/vfvalue.h lib/xml.h +$(libcppdir)/checkbufferoverrun.o: lib/checkbufferoverrun.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkbufferoverrun.h lib/checkers.h lib/checkimpl.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vf_common.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkbufferoverrun.cpp -$(libcppdir)/checkclass.o: lib/checkclass.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkclass.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h +$(libcppdir)/checkclass.o: lib/checkclass.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkclass.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkclass.cpp -$(libcppdir)/checkcondition.o: lib/checkcondition.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkcondition.h lib/checkers.h lib/checkother.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkcondition.o: lib/checkcondition.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkcondition.h lib/checkers.h lib/checkimpl.h lib/checkother.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkcondition.cpp $(libcppdir)/checkers.o: lib/checkers.cpp lib/checkers.h lib/config.h @@ -534,58 +531,61 @@ $(libcppdir)/checkersidmapping.o: lib/checkersidmapping.cpp lib/checkers.h lib/c $(libcppdir)/checkersreport.o: lib/checkersreport.cpp lib/addoninfo.h lib/checkers.h lib/checkersreport.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkersreport.cpp -$(libcppdir)/checkexceptionsafety.o: lib/checkexceptionsafety.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkexceptionsafety.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkexceptionsafety.o: lib/checkexceptionsafety.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkexceptionsafety.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkexceptionsafety.cpp -$(libcppdir)/checkfunctions.o: lib/checkfunctions.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkfunctions.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checkfunctions.o: lib/checkfunctions.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkfunctions.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkfunctions.cpp -$(libcppdir)/checkinternal.o: lib/checkinternal.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkinternal.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkimpl.o: lib/checkimpl.cpp lib/addoninfo.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkimpl.cpp + +$(libcppdir)/checkinternal.o: lib/checkinternal.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkinternal.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkinternal.cpp -$(libcppdir)/checkio.o: lib/checkio.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkio.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkio.o: lib/checkio.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkio.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkio.cpp -$(libcppdir)/checkleakautovar.o: lib/checkleakautovar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkleakautovar.h lib/checkmemoryleak.h lib/checknullpointer.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkleakautovar.o: lib/checkleakautovar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkleakautovar.h lib/checkmemoryleak.h lib/checknullpointer.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkleakautovar.cpp -$(libcppdir)/checkmemoryleak.o: lib/checkmemoryleak.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkmemoryleak.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkmemoryleak.o: lib/checkmemoryleak.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkmemoryleak.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkmemoryleak.cpp -$(libcppdir)/checknullpointer.o: lib/checknullpointer.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checknullpointer.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checknullpointer.o: lib/checknullpointer.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checknullpointer.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checknullpointer.cpp -$(libcppdir)/checkother.o: lib/checkother.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkother.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checkother.o: lib/checkother.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkother.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkother.cpp -$(libcppdir)/checkpostfixoperator.o: lib/checkpostfixoperator.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkpostfixoperator.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkpostfixoperator.o: lib/checkpostfixoperator.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkpostfixoperator.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkpostfixoperator.cpp -$(libcppdir)/checks.o: lib/checks.cpp lib/check.h lib/check64bit.h lib/checkassert.h lib/checkautovariables.h lib/checkbool.h lib/checkbufferoverrun.h lib/checkclass.h lib/checkcondition.h lib/checkexceptionsafety.h lib/checkfunctions.h lib/checkinternal.h lib/checkio.h lib/checkleakautovar.h lib/checkmemoryleak.h lib/checknullpointer.h lib/checkother.h lib/checkpostfixoperator.h lib/checks.h lib/checksizeof.h lib/checkstl.h lib/checkstring.h lib/checktype.h lib/checkuninitvar.h lib/checkunusedvar.h lib/checkvaarg.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/standards.h lib/vfvalue.h +$(libcppdir)/checks.o: lib/checks.cpp lib/check.h lib/check64bit.h lib/checkassert.h lib/checkautovariables.h lib/checkbool.h lib/checkbufferoverrun.h lib/checkclass.h lib/checkcondition.h lib/checkexceptionsafety.h lib/checkfunctions.h lib/checkimpl.h lib/checkinternal.h lib/checkio.h lib/checkleakautovar.h lib/checkmemoryleak.h lib/checknullpointer.h lib/checkother.h lib/checkpostfixoperator.h lib/checks.h lib/checksizeof.h lib/checkstl.h lib/checkstring.h lib/checktype.h lib/checkuninitvar.h lib/checkunusedvar.h lib/checkvaarg.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/standards.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checks.cpp -$(libcppdir)/checksizeof.o: lib/checksizeof.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checksizeof.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checksizeof.o: lib/checksizeof.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checksizeof.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checksizeof.cpp -$(libcppdir)/checkstl.o: lib/checkstl.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checknullpointer.h lib/checkstl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/pathanalysis.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checkstl.o: lib/checkstl.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checknullpointer.h lib/checkstl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/pathanalysis.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkstl.cpp -$(libcppdir)/checkstring.o: lib/checkstring.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkstring.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkstring.o: lib/checkstring.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkstring.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkstring.cpp -$(libcppdir)/checktype.o: lib/checktype.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checktype.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checktype.o: lib/checktype.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checktype.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checktype.cpp -$(libcppdir)/checkuninitvar.o: lib/checkuninitvar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checknullpointer.h lib/checkuninitvar.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkuninitvar.o: lib/checkuninitvar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checknullpointer.h lib/checkuninitvar.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkuninitvar.cpp $(libcppdir)/checkunusedfunctions.o: lib/checkunusedfunctions.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/astutils.h lib/checkers.h lib/checkunusedfunctions.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkunusedfunctions.cpp -$(libcppdir)/checkunusedvar.o: lib/checkunusedvar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkunusedvar.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checkunusedvar.o: lib/checkunusedvar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkunusedvar.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkunusedvar.cpp -$(libcppdir)/checkvaarg.o: lib/checkvaarg.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkvaarg.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkvaarg.o: lib/checkvaarg.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkvaarg.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkvaarg.cpp $(libcppdir)/clangimport.o: lib/clangimport.cpp lib/clangimport.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h @@ -744,28 +744,28 @@ test/main.o: test/main.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/c test/options.o: test/options.cpp lib/config.h lib/timer.h test/options.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/options.cpp -test/test64bit.o: test/test64bit.cpp lib/addoninfo.h lib/check.h lib/check64bit.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/test64bit.o: test/test64bit.cpp lib/addoninfo.h lib/check.h lib/check64bit.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/test64bit.cpp test/testanalyzerinformation.o: test/testanalyzerinformation.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h lib/xml.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testanalyzerinformation.cpp -test/testassert.o: test/testassert.cpp lib/addoninfo.h lib/check.h lib/checkassert.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testassert.o: test/testassert.cpp lib/addoninfo.h lib/check.h lib/checkassert.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testassert.cpp test/testastutils.o: test/testastutils.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testastutils.cpp -test/testautovariables.o: test/testautovariables.cpp lib/addoninfo.h lib/check.h lib/checkautovariables.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testautovariables.o: test/testautovariables.cpp lib/addoninfo.h lib/check.h lib/checkautovariables.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testautovariables.cpp -test/testbool.o: test/testbool.cpp lib/addoninfo.h lib/check.h lib/checkbool.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testbool.o: test/testbool.cpp lib/addoninfo.h lib/check.h lib/checkbool.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testbool.cpp -test/testbufferoverrun.o: test/testbufferoverrun.cpp lib/addoninfo.h lib/check.h lib/checkbufferoverrun.h lib/checkers.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testbufferoverrun.o: test/testbufferoverrun.cpp lib/addoninfo.h lib/check.h lib/checkbufferoverrun.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testbufferoverrun.cpp -test/testcharvar.o: test/testcharvar.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testcharvar.o: test/testcharvar.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcharvar.cpp test/testcheck.o: test/testcheck.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checks.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h @@ -777,7 +777,7 @@ test/testcheckersreport.o: test/testcheckersreport.cpp lib/addoninfo.h lib/check test/testclangimport.o: test/testclangimport.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/clangimport.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testclangimport.cpp -test/testclass.o: test/testclass.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testclass.o: test/testclass.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testclass.cpp test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h @@ -786,10 +786,10 @@ test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlinelogger.h cli/cmd test/testcolor.o: test/testcolor.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcolor.cpp -test/testcondition.o: test/testcondition.cpp lib/addoninfo.h lib/check.h lib/checkcondition.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testcondition.o: test/testcondition.cpp lib/addoninfo.h lib/check.h lib/checkcondition.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcondition.cpp -test/testconstructors.o: test/testconstructors.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testconstructors.o: test/testconstructors.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testconstructors.cpp test/testcppcheck.o: test/testcppcheck.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h @@ -798,7 +798,7 @@ test/testcppcheck.o: test/testcppcheck.cpp externals/simplecpp/simplecpp.h lib/a test/testerrorlogger.o: test/testerrorlogger.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/xml.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testerrorlogger.cpp -test/testexceptionsafety.o: test/testexceptionsafety.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkexceptionsafety.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testexceptionsafety.o: test/testexceptionsafety.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkexceptionsafety.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testexceptionsafety.cpp test/testexecutor.o: test/testexecutor.cpp cli/executor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h @@ -813,7 +813,7 @@ test/testfilesettings.o: test/testfilesettings.cpp lib/addoninfo.h lib/check.h l test/testfrontend.o: test/testfrontend.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testfrontend.cpp -test/testfunctions.o: test/testfunctions.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkfunctions.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testfunctions.o: test/testfunctions.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkfunctions.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testfunctions.cpp test/testgarbage.o: test/testgarbage.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checks.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h @@ -822,16 +822,16 @@ test/testgarbage.o: test/testgarbage.cpp lib/addoninfo.h lib/check.h lib/checker test/testimportproject.o: test/testimportproject.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h lib/xml.h test/fixture.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testimportproject.cpp -test/testincompletestatement.o: test/testincompletestatement.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testincompletestatement.o: test/testincompletestatement.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testincompletestatement.cpp -test/testinternal.o: test/testinternal.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkinternal.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testinternal.o: test/testinternal.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkinternal.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testinternal.cpp -test/testio.o: test/testio.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkio.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testio.o: test/testio.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkio.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testio.cpp -test/testleakautovar.o: test/testleakautovar.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkleakautovar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testleakautovar.o: test/testleakautovar.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkleakautovar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testleakautovar.cpp test/testlibrary.o: test/testlibrary.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h @@ -840,16 +840,16 @@ test/testlibrary.o: test/testlibrary.cpp lib/addoninfo.h lib/check.h lib/checker test/testmathlib.o: test/testmathlib.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testmathlib.cpp -test/testmemleak.o: test/testmemleak.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkmemoryleak.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testmemleak.o: test/testmemleak.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkmemoryleak.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testmemleak.cpp -test/testnullpointer.o: test/testnullpointer.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checknullpointer.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testnullpointer.o: test/testnullpointer.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checknullpointer.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testnullpointer.cpp test/testoptions.o: test/testoptions.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h test/options.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testoptions.cpp -test/testother.o: test/testother.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testother.o: test/testother.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testother.cpp test/testpath.o: test/testpath.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h @@ -861,7 +861,7 @@ test/testpathmatch.o: test/testpathmatch.cpp lib/addoninfo.h lib/check.h lib/che test/testplatform.o: test/testplatform.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h lib/xml.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testplatform.cpp -test/testpostfixoperator.o: test/testpostfixoperator.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkpostfixoperator.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testpostfixoperator.o: test/testpostfixoperator.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkpostfixoperator.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testpostfixoperator.cpp test/testpreprocessor.o: test/testpreprocessor.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h @@ -897,16 +897,16 @@ test/testsimplifyusing.o: test/testsimplifyusing.cpp lib/addoninfo.h lib/check.h test/testsingleexecutor.o: test/testsingleexecutor.cpp cli/executor.h cli/singleexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsingleexecutor.cpp -test/testsizeof.o: test/testsizeof.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checksizeof.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testsizeof.o: test/testsizeof.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checksizeof.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsizeof.cpp test/teststandards.o: test/teststandards.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/teststandards.cpp -test/teststl.o: test/teststl.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkstl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/teststl.o: test/teststl.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkstl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/teststl.cpp -test/teststring.o: test/teststring.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkstring.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/teststring.o: test/teststring.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkstring.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/teststring.cpp test/testsummaries.o: test/testsummaries.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/summaries.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h @@ -936,25 +936,25 @@ test/testtokenlist.o: test/testtokenlist.cpp externals/simplecpp/simplecpp.h lib test/testtokenrange.o: test/testtokenrange.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/tokenrange.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtokenrange.cpp -test/testtype.o: test/testtype.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checktype.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testtype.o: test/testtype.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checktype.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtype.cpp -test/testuninitvar.o: test/testuninitvar.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkuninitvar.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testuninitvar.o: test/testuninitvar.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkuninitvar.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testuninitvar.cpp test/testunusedfunctions.o: test/testunusedfunctions.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testunusedfunctions.cpp -test/testunusedprivfunc.o: test/testunusedprivfunc.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testunusedprivfunc.o: test/testunusedprivfunc.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testunusedprivfunc.cpp -test/testunusedvar.o: test/testunusedvar.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/checkunusedvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testunusedvar.o: test/testunusedvar.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkunusedvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testunusedvar.cpp test/testutils.o: test/testutils.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testutils.cpp -test/testvaarg.o: test/testvaarg.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkvaarg.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testvaarg.o: test/testvaarg.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkvaarg.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvaarg.cpp test/testvalueflow.o: test/testvalueflow.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 56a9489d00e..8dfd03596d3 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2157,7 +2157,7 @@ bool isWithoutSideEffects(const Token* tok, bool checkArrayAccess, bool checkRef if (tok && tok->varId()) { const Variable* var = tok->variable(); return var && ((!var->isClass() && (checkReference || !var->isReference())) || var->isPointer() || - (checkArrayAccess ? var->isArray() || (var->isStlType() && !var->isStlType(CheckClass::stl_containers_not_const)) : var->isStlType())); + (checkArrayAccess ? var->isArray() || (var->isStlType() && !var->isStlType(CheckClassImpl::stl_containers_not_const)) : var->isStlType())); } return true; } diff --git a/lib/check.h b/lib/check.h index 9a50e64baa1..06febbd5eaa 100644 --- a/lib/check.h +++ b/lib/check.h @@ -22,7 +22,6 @@ //--------------------------------------------------------------------------- #include "config.h" -#include "errortypes.h" #include #include @@ -36,14 +35,8 @@ namespace CTU { class FileInfo; } -namespace ValueFlow { - class Value; -} - class Settings; -class Token; class ErrorLogger; -class ErrorMessage; class Tokenizer; /** Use WRONG_DATA in checkers to mark conditions that check that data is correct */ @@ -59,17 +52,9 @@ class Tokenizer; class CPPCHECKLIB Check { public: /** This constructor is used when registering the CheckClass */ - explicit Check(std::string aname); - -protected: - /** This constructor is used when running checks. */ - Check(std::string aname, const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : mTokenizer(tokenizer), mSettings(settings), mErrorLogger(errorLogger), mName(std::move(aname)) {} - -private: - static std::list &instances_internal(); - -public: + explicit Check(std::string aname) + : mName(std::move(aname)) + {} virtual ~Check() = default; Check(const Check &) = delete; @@ -89,13 +74,6 @@ class CPPCHECKLIB Check { /** get information about this class, used to generate documentation */ virtual std::string classInfo() const = 0; - /** - * Write given error to stdout in xml format. - * This is for for printout out the error list with --errorlist - * @param errmsg Error message to write - */ - static void writeToErrorList(const ErrorMessage &errmsg); - /** Base class used for whole-program analysis */ class CPPCHECKLIB FileInfo { public: @@ -121,40 +99,6 @@ class CPPCHECKLIB Check { return false; } -protected: - static std::string getMessageId(const ValueFlow::Value &value, const char id[]); - - const Tokenizer* const mTokenizer{}; - const Settings* const mSettings{}; - ErrorLogger* const mErrorLogger{}; - - /** report an error */ - void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg) { - reportError(tok, severity, id, msg, CWE(0U), Certainty::normal); - } - - /** report an error */ - void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg, const CWE &cwe, Certainty certainty) { - const std::list callstack(1, tok); - reportError(callstack, severity, id, msg, cwe, certainty); - } - - /** report an error */ - void reportError(const std::list &callstack, Severity severity, const std::string &id, const std::string &msg, const CWE &cwe, Certainty certainty); - - void reportError(ErrorPath errorPath, Severity severity, const char id[], const std::string &msg, const CWE &cwe, Certainty certainty); - - /** log checker */ - void logChecker(const char id[]); - - ErrorPath getErrorPath(const Token* errtok, const ValueFlow::Value* value, std::string bug) const; - - /** - * Use WRONG_DATA in checkers when you check for wrong data. That - * will call this method - */ - bool wrongData(const Token *tok, const char *str); - private: const std::string mName; }; diff --git a/lib/check64bit.cpp b/lib/check64bit.cpp index b33ab5bdbcb..e1e6f086ff3 100644 --- a/lib/check64bit.cpp +++ b/lib/check64bit.cpp @@ -51,7 +51,7 @@ static bool isFunctionPointer(const Token* tok) return Tokenizer::isFunctionPointer(tok->variable()->nameToken()); } -void Check64BitPortability::pointerassignment() +void Check64BitPortabilityImpl::pointerassignment() { if (!mSettings->severity.isEnabled(Severity::portability)) return; @@ -139,7 +139,7 @@ void Check64BitPortability::pointerassignment() } } -void Check64BitPortability::assignmentAddressToIntegerError(const Token *tok) +void Check64BitPortabilityImpl::assignmentAddressToIntegerError(const Token *tok) { reportError(tok, Severity::portability, "AssignmentAddressToInteger", @@ -150,7 +150,7 @@ void Check64BitPortability::assignmentAddressToIntegerError(const Token *tok) "way is to store addresses only in pointer types (or typedefs like uintptr_t).", CWE758, Certainty::normal); } -void Check64BitPortability::assignmentIntegerToAddressError(const Token *tok) +void Check64BitPortabilityImpl::assignmentIntegerToAddressError(const Token *tok) { reportError(tok, Severity::portability, "AssignmentIntegerToAddress", @@ -161,7 +161,7 @@ void Check64BitPortability::assignmentIntegerToAddressError(const Token *tok) "way is to store addresses only in pointer types (or typedefs like uintptr_t).", CWE758, Certainty::normal); } -void Check64BitPortability::returnPointerError(const Token *tok) +void Check64BitPortabilityImpl::returnPointerError(const Token *tok) { reportError(tok, Severity::portability, "CastAddressToIntegerAtReturn", @@ -172,7 +172,7 @@ void Check64BitPortability::returnPointerError(const Token *tok) "to 32-bit integer. The safe way is to return a type such as intptr_t.", CWE758, Certainty::normal); } -void Check64BitPortability::returnIntegerError(const Token *tok) +void Check64BitPortabilityImpl::returnIntegerError(const Token *tok) { reportError(tok, Severity::portability, "CastIntegerToAddressAtReturn", @@ -185,13 +185,13 @@ void Check64BitPortability::returnIntegerError(const Token *tok) void Check64BitPortability::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - Check64BitPortability check64BitPortability(&tokenizer, &tokenizer.getSettings(), errorLogger); + Check64BitPortabilityImpl check64BitPortability(&tokenizer, &tokenizer.getSettings(), errorLogger); check64BitPortability.pointerassignment(); } void Check64BitPortability::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - Check64BitPortability c(nullptr, settings, errorLogger); + Check64BitPortabilityImpl c(nullptr, settings, errorLogger); c.assignmentAddressToIntegerError(nullptr); c.assignmentIntegerToAddressError(nullptr); c.returnIntegerError(nullptr); diff --git a/lib/check64bit.h b/lib/check64bit.h index 79397e98e5f..e6654004eda 100644 --- a/lib/check64bit.h +++ b/lib/check64bit.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -44,36 +45,35 @@ class CPPCHECKLIB Check64BitPortability : public Check { public: /** This constructor is used when registering the Check64BitPortability */ - Check64BitPortability() : Check(myName()) {} + Check64BitPortability() : Check("64-bit portability") {} private: - /** This constructor is used when running checks. */ - Check64BitPortability(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; - /** Check for pointer assignment */ - void pointerassignment(); - - void assignmentAddressToIntegerError(const Token *tok); - void assignmentIntegerToAddressError(const Token *tok); - void returnIntegerError(const Token *tok); - void returnPointerError(const Token *tok); - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - static std::string myName() { - return "64-bit portability"; - } - std::string classInfo() const override { return "Check if there is 64-bit portability issues:\n" "- assign address to/from int/long\n" "- casting address from/to integer when returning from function\n"; } }; + +class Check64BitPortabilityImpl : public CheckImpl { +public: + /** This constructor is used when running checks. */ + Check64BitPortabilityImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + + /** Check for pointer assignment */ + void pointerassignment(); + + void assignmentAddressToIntegerError(const Token *tok); + void assignmentIntegerToAddressError(const Token *tok); + void returnIntegerError(const Token *tok); + void returnPointerError(const Token *tok); +}; /// @} //--------------------------------------------------------------------------- #endif // check64bitH diff --git a/lib/checkassert.cpp b/lib/checkassert.cpp index ce2d7c62169..5242b595e67 100644 --- a/lib/checkassert.cpp +++ b/lib/checkassert.cpp @@ -39,7 +39,7 @@ // CWE ids used static const CWE CWE398(398U); // Indicator of Poor Code Quality -void CheckAssert::assertWithSideEffects() +void CheckAssertImpl::assertWithSideEffects() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -117,7 +117,7 @@ void CheckAssert::assertWithSideEffects() //--------------------------------------------------------------------------- -void CheckAssert::sideEffectInAssertError(const Token *tok, const std::string& functionName) +void CheckAssertImpl::sideEffectInAssertError(const Token *tok, const std::string& functionName) { reportError(tok, Severity::warning, "assertWithSideEffect", @@ -129,7 +129,7 @@ void CheckAssert::sideEffectInAssertError(const Token *tok, const std::string& f "builds, this is a bug.", CWE398, Certainty::normal); } -void CheckAssert::assignmentInAssertError(const Token *tok, const std::string& varname) +void CheckAssertImpl::assignmentInAssertError(const Token *tok, const std::string& varname) { reportError(tok, Severity::warning, "assignmentInAssert", @@ -142,7 +142,7 @@ void CheckAssert::assignmentInAssertError(const Token *tok, const std::string& v } // checks if side effects happen on the variable prior to tmp -void CheckAssert::checkVariableAssignment(const Token* assignTok, const Scope *assertionScope) +void CheckAssertImpl::checkVariableAssignment(const Token* assignTok, const Scope *assertionScope) { if (!assignTok->isAssignmentOp() && assignTok->tokType() != Token::eIncDecOp) return; @@ -172,7 +172,7 @@ void CheckAssert::checkVariableAssignment(const Token* assignTok, const Scope *a // TODO: function calls on var } -bool CheckAssert::inSameScope(const Token* returnTok, const Token* assignTok) +bool CheckAssertImpl::inSameScope(const Token* returnTok, const Token* assignTok) { // TODO: even if a return is in the same scope, the assignment might not affect it. return returnTok->scope() == assignTok->scope(); @@ -180,13 +180,13 @@ bool CheckAssert::inSameScope(const Token* returnTok, const Token* assignTok) void CheckAssert::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckAssert checkAssert(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckAssertImpl checkAssert(&tokenizer, &tokenizer.getSettings(), errorLogger); checkAssert.assertWithSideEffects(); } void CheckAssert::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckAssert c(nullptr, settings, errorLogger); + CheckAssertImpl c(nullptr, settings, errorLogger); c.sideEffectInAssertError(nullptr, "function"); c.assignmentInAssertError(nullptr, "var"); } diff --git a/lib/checkassert.h b/lib/checkassert.h index b01831a5eec..ef30fe023ca 100644 --- a/lib/checkassert.h +++ b/lib/checkassert.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -42,14 +43,22 @@ class Tokenizer; class CPPCHECKLIB CheckAssert : public Check { public: - CheckAssert() : Check(myName()) {} + CheckAssert() : Check("Assert") {} private: - CheckAssert(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - /** run checks, the token list is not simplified */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + return "Warn if there are side effects in assert statements (since this cause different behaviour in debug/release builds).\n"; + } +}; + +class CheckAssertImpl: public CheckImpl { +public: + CheckAssertImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} void assertWithSideEffects(); @@ -58,16 +67,6 @@ class CPPCHECKLIB CheckAssert : public Check { void sideEffectInAssertError(const Token *tok, const std::string& functionName); void assignmentInAssertError(const Token *tok, const std::string &varname); - - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "Assert"; - } - - std::string classInfo() const override { - return "Warn if there are side effects in assert statements (since this cause different behaviour in debug/release builds).\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index fdc5deceefa..0d3cae1c2fa 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -202,7 +202,7 @@ static bool variableIsUsedInScope(const Token* start, nonneg int varId, const Sc return false; } -void CheckAutoVariables::assignFunctionArg() +void CheckAutoVariablesImpl::assignFunctionArg() { const bool printStyle = mSettings->severity.isEnabled(Severity::style); const bool printWarning = mSettings->severity.isEnabled(Severity::warning); @@ -280,7 +280,7 @@ static bool isMemberAssignment(const Token* tok, const Token*& rhs, const Settin return true; } -void CheckAutoVariables::autoVariables() +void CheckAutoVariablesImpl::autoVariables() { logChecker("CheckAutoVariables::autoVariables"); @@ -343,7 +343,7 @@ void CheckAutoVariables::autoVariables() } } -bool CheckAutoVariables::checkAutoVariableAssignment(const Token *expr, bool inconclusive, const Token *startToken) +bool CheckAutoVariablesImpl::checkAutoVariableAssignment(const Token *expr, bool inconclusive, const Token *startToken) { if (!startToken) startToken = Token::findsimplematch(expr, "=")->next(); @@ -386,7 +386,7 @@ bool CheckAutoVariables::checkAutoVariableAssignment(const Token *expr, bool inc //--------------------------------------------------------------------------- -void CheckAutoVariables::errorAutoVariableAssignment(const Token *tok, bool inconclusive) +void CheckAutoVariablesImpl::errorAutoVariableAssignment(const Token *tok, bool inconclusive) { diag(tok); @@ -409,7 +409,7 @@ void CheckAutoVariables::errorAutoVariableAssignment(const Token *tok, bool inco } } -void CheckAutoVariables::errorUselessAssignmentArg(const Token *tok) +void CheckAutoVariablesImpl::errorUselessAssignmentArg(const Token *tok) { reportError(tok, Severity::style, @@ -417,7 +417,7 @@ void CheckAutoVariables::errorUselessAssignmentArg(const Token *tok) "Assignment of function parameter has no effect outside the function.", CWE398, Certainty::normal); } -void CheckAutoVariables::errorUselessAssignmentPtrArg(const Token *tok) +void CheckAutoVariablesImpl::errorUselessAssignmentPtrArg(const Token *tok) { reportError(tok, Severity::warning, @@ -425,7 +425,7 @@ void CheckAutoVariables::errorUselessAssignmentPtrArg(const Token *tok) "Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?", CWE398, Certainty::normal); } -bool CheckAutoVariables::diag(const Token* tokvalue) +bool CheckAutoVariablesImpl::diag(const Token* tokvalue) { if (!tokvalue) return true; @@ -562,7 +562,7 @@ static bool isAssignedToNonLocal(const Token* tok) return !var->isLocal() || var->isStatic(); } -void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token * end) +void CheckAutoVariablesImpl::checkVarLifetimeScope(const Token * start, const Token * end) { const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); if (!start) @@ -705,7 +705,7 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token } } -void CheckAutoVariables::checkVarLifetime() +void CheckAutoVariablesImpl::checkVarLifetime() { logChecker("CheckAutoVariables::checkVarLifetime"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -716,7 +716,7 @@ void CheckAutoVariables::checkVarLifetime() } } -void CheckAutoVariables::errorReturnDanglingLifetime(const Token *tok, const ValueFlow::Value *val) +void CheckAutoVariablesImpl::errorReturnDanglingLifetime(const Token *tok, const ValueFlow::Value *val) { const bool inconclusive = val ? val->isInconclusive() : false; ErrorPath errorPath = val ? val->errorPath : ErrorPath(); @@ -725,7 +725,7 @@ void CheckAutoVariables::errorReturnDanglingLifetime(const Token *tok, const Val reportError(std::move(errorPath), Severity::error, "returnDanglingLifetime", msg + " that will be invalid when returning.", CWE562, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckAutoVariables::errorInvalidLifetime(const Token *tok, const ValueFlow::Value* val) +void CheckAutoVariablesImpl::errorInvalidLifetime(const Token *tok, const ValueFlow::Value* val) { const bool inconclusive = val ? val->isInconclusive() : false; ErrorPath errorPath = val ? val->errorPath : ErrorPath(); @@ -734,7 +734,7 @@ void CheckAutoVariables::errorInvalidLifetime(const Token *tok, const ValueFlow: reportError(std::move(errorPath), Severity::error, "invalidLifetime", msg + " that is out of scope.", CWE562, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckAutoVariables::errorDanglingTemporaryLifetime(const Token* tok, const ValueFlow::Value* val, const Token* tempTok) +void CheckAutoVariablesImpl::errorDanglingTemporaryLifetime(const Token* tok, const ValueFlow::Value* val, const Token* tempTok) { const bool inconclusive = val ? val->isInconclusive() : false; ErrorPath errorPath = val ? val->errorPath : ErrorPath(); @@ -749,7 +749,7 @@ void CheckAutoVariables::errorDanglingTemporaryLifetime(const Token* tok, const inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckAutoVariables::errorDanglngLifetime(const Token *tok, const ValueFlow::Value *val, bool isStatic) +void CheckAutoVariablesImpl::errorDanglngLifetime(const Token *tok, const ValueFlow::Value *val, bool isStatic) { const bool inconclusive = val ? val->isInconclusive() : false; ErrorPath errorPath = val ? val->errorPath : ErrorPath(); @@ -760,21 +760,21 @@ void CheckAutoVariables::errorDanglngLifetime(const Token *tok, const ValueFlow: reportError(std::move(errorPath), Severity::error, "danglingLifetime", msg + ".", CWE562, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckAutoVariables::errorDanglingTempReference(const Token* tok, ErrorPath errorPath, bool inconclusive) +void CheckAutoVariablesImpl::errorDanglingTempReference(const Token* tok, ErrorPath errorPath, bool inconclusive) { errorPath.emplace_back(tok, ""); reportError( std::move(errorPath), Severity::error, "danglingTempReference", "Using reference to dangling temporary.", CWE562, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckAutoVariables::errorReturnReference(const Token* tok, ErrorPath errorPath, bool inconclusive) +void CheckAutoVariablesImpl::errorReturnReference(const Token* tok, ErrorPath errorPath, bool inconclusive) { errorPath.emplace_back(tok, ""); reportError( std::move(errorPath), Severity::error, "returnReference", "Reference to local variable returned.", CWE562, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckAutoVariables::errorDanglingReference(const Token *tok, const Variable *var, ErrorPath errorPath) +void CheckAutoVariablesImpl::errorDanglingReference(const Token *tok, const Variable *var, ErrorPath errorPath) { std::string tokName = tok ? tok->str() : "x"; std::string varName = var ? var->name() : "y"; @@ -783,14 +783,14 @@ void CheckAutoVariables::errorDanglingReference(const Token *tok, const Variable reportError(std::move(errorPath), Severity::error, "danglingReference", msg, CWE562, Certainty::normal); } -void CheckAutoVariables::errorReturnTempReference(const Token* tok, ErrorPath errorPath, bool inconclusive) +void CheckAutoVariablesImpl::errorReturnTempReference(const Token* tok, ErrorPath errorPath, bool inconclusive) { errorPath.emplace_back(tok, ""); reportError( std::move(errorPath), Severity::error, "returnTempReference", "Reference to temporary returned.", CWE562, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckAutoVariables::errorInvalidDeallocation(const Token *tok, const ValueFlow::Value *val) +void CheckAutoVariablesImpl::errorInvalidDeallocation(const Token *tok, const ValueFlow::Value *val) { const Variable *var = val ? val->tokvalue->variable() : (tok ? tok->variable() : nullptr); @@ -819,7 +819,7 @@ void CheckAutoVariables::errorInvalidDeallocation(const Token *tok, const ValueF void CheckAutoVariables::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckAutoVariables checkAutoVariables(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckAutoVariablesImpl checkAutoVariables(&tokenizer, &tokenizer.getSettings(), errorLogger); checkAutoVariables.assignFunctionArg(); checkAutoVariables.autoVariables(); checkAutoVariables.checkVarLifetime(); @@ -827,7 +827,7 @@ void CheckAutoVariables::runChecks(const Tokenizer &tokenizer, ErrorLogger *erro void CheckAutoVariables::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckAutoVariables c(nullptr,settings,errorLogger); + CheckAutoVariablesImpl c(nullptr,settings,errorLogger); c.errorAutoVariableAssignment(nullptr, false); c.errorReturnReference(nullptr, ErrorPath{}, false); c.errorDanglingReference(nullptr, nullptr, ErrorPath{}); diff --git a/lib/checkautovariables.h b/lib/checkautovariables.h index d94f254508f..f8f700a910f 100644 --- a/lib/checkautovariables.h +++ b/lib/checkautovariables.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include "errortypes.h" @@ -47,16 +48,33 @@ namespace ValueFlow { class CPPCHECKLIB CheckAutoVariables : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckAutoVariables() : Check(myName()) {} + CheckAutoVariables() : Check("Auto Variables") {} private: - /** This constructor is used when running checks. */ - CheckAutoVariables(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + return "A pointer to a variable is only valid as long as the variable is in scope.\n" + "Check:\n" + "- returning a pointer to auto or temporary variable\n" + "- assigning address of an variable to an effective parameter of a function\n" + "- returning reference to local/temporary variable\n" + "- returning address of function parameter\n" + "- suspicious assignment of pointer argument\n" + "- useless assignment of function argument\n"; + } +}; + +class CheckAutoVariablesImpl : public CheckImpl +{ +public: + /** This constructor is used when running checks. */ + CheckAutoVariablesImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** assign function argument */ void assignFunctionArg(); @@ -69,7 +87,6 @@ class CPPCHECKLIB CheckAutoVariables : public Check { bool checkAutoVariableAssignment(const Token *expr, bool inconclusive, const Token *startToken = nullptr); void checkVarLifetime(); - void checkVarLifetimeScope(const Token * start, const Token * end); void errorAutoVariableAssignment(const Token *tok, bool inconclusive); @@ -85,24 +102,8 @@ class CPPCHECKLIB CheckAutoVariables : public Check { void errorUselessAssignmentArg(const Token *tok); void errorUselessAssignmentPtrArg(const Token *tok); - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "Auto Variables"; - } - - std::string classInfo() const override { - return "A pointer to a variable is only valid as long as the variable is in scope.\n" - "Check:\n" - "- returning a pointer to auto or temporary variable\n" - "- assigning address of an variable to an effective parameter of a function\n" - "- returning reference to local/temporary variable\n" - "- returning address of function parameter\n" - "- suspicious assignment of pointer argument\n" - "- useless assignment of function argument\n"; - } - /** returns true if tokvalue has already been diagnosed */ +private: bool diag(const Token* tokvalue); std::set mDiagDanglingTemp; diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index c9a66876317..e4f55f26085 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -43,7 +43,7 @@ static bool isBool(const Variable* var) } //--------------------------------------------------------------------------- -void CheckBool::checkIncrementBoolean() +void CheckBoolImpl::checkIncrementBoolean() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("incrementboolean")) return; @@ -60,7 +60,7 @@ void CheckBool::checkIncrementBoolean() } } -void CheckBool::incrementBooleanError(const Token *tok) +void CheckBoolImpl::incrementBooleanError(const Token *tok) { reportError( tok, @@ -83,7 +83,7 @@ static bool isConvertedToBool(const Token* tok) // if (bool & bool) -> if (bool && bool) // if (bool | bool) -> if (bool || bool) //--------------------------------------------------------------------------- -void CheckBool::checkBitwiseOnBoolean() +void CheckBoolImpl::checkBitwiseOnBoolean() { if (!mSettings->isPremiumEnabled("bitwiseOnBoolean") && !mSettings->severity.isEnabled(Severity::style) && @@ -127,7 +127,7 @@ void CheckBool::checkBitwiseOnBoolean() } } -void CheckBool::bitwiseOnBooleanError(const Token* tok, const std::string& expression, const std::string& op, bool isCompound) +void CheckBoolImpl::bitwiseOnBooleanError(const Token* tok, const std::string& expression, const std::string& op, bool isCompound) { std::string msg = "Boolean expression '" + expression + "' is used in bitwise operation."; if (!isCompound) @@ -144,7 +144,7 @@ void CheckBool::bitwiseOnBooleanError(const Token* tok, const std::string& expre // if (!x==3) <- Probably meant to be "x!=3" //--------------------------------------------------------------------------- -void CheckBool::checkComparisonOfBoolWithInt() +void CheckBoolImpl::checkComparisonOfBoolWithInt() { if (!mSettings->severity.isEnabled(Severity::warning) || !mTokenizer->isCPP()) return; @@ -171,7 +171,7 @@ void CheckBool::checkComparisonOfBoolWithInt() } } -void CheckBool::comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression) +void CheckBoolImpl::comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression) { reportError(tok, Severity::warning, "comparisonOfBoolWithInvalidComparator", "Comparison of a boolean value using relational operator (<, >, <= or >=).\n" @@ -195,7 +195,7 @@ static bool tokenIsFunctionReturningBool(const Token* tok) return false; } -void CheckBool::checkComparisonOfFuncReturningBool() +void CheckBoolImpl::checkComparisonOfFuncReturningBool() { if (!mSettings->severity.isEnabled(Severity::style)) return; @@ -239,7 +239,7 @@ void CheckBool::checkComparisonOfFuncReturningBool() } } -void CheckBool::comparisonOfFuncReturningBoolError(const Token *tok, const std::string &expression) +void CheckBoolImpl::comparisonOfFuncReturningBoolError(const Token *tok, const std::string &expression) { reportError(tok, Severity::style, "comparisonOfFuncReturningBoolError", "Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n" @@ -248,7 +248,7 @@ void CheckBool::comparisonOfFuncReturningBoolError(const Token *tok, const std:: " operator could cause unexpected results.", CWE398, Certainty::normal); } -void CheckBool::comparisonOfTwoFuncsReturningBoolError(const Token *tok, const std::string &expression1, const std::string &expression2) +void CheckBoolImpl::comparisonOfTwoFuncsReturningBoolError(const Token *tok, const std::string &expression1, const std::string &expression2) { reportError(tok, Severity::style, "comparisonOfTwoFuncsReturningBoolError", "Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n" @@ -261,7 +261,7 @@ void CheckBool::comparisonOfTwoFuncsReturningBoolError(const Token *tok, const s // Comparison of bool with bool //------------------------------------------------------------------------------- -void CheckBool::checkComparisonOfBoolWithBool() +void CheckBoolImpl::checkComparisonOfBoolWithBool() { if (!mSettings->severity.isEnabled(Severity::style)) return; @@ -302,7 +302,7 @@ void CheckBool::checkComparisonOfBoolWithBool() } } -void CheckBool::comparisonOfBoolWithBoolError(const Token *tok, const std::string &expression) +void CheckBoolImpl::comparisonOfBoolWithBoolError(const Token *tok, const std::string &expression) { reportError(tok, Severity::style, "comparisonOfBoolWithBoolError", "Comparison of a variable having boolean value using relational (<, >, <= or >=) operator.\n" @@ -312,7 +312,7 @@ void CheckBool::comparisonOfBoolWithBoolError(const Token *tok, const std::strin } //----------------------------------------------------------------------------- -void CheckBool::checkAssignBoolToPointer() +void CheckBoolImpl::checkAssignBoolToPointer() { logChecker("CheckBool::checkAssignBoolToPointer"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -325,7 +325,7 @@ void CheckBool::checkAssignBoolToPointer() } } -void CheckBool::assignBoolToPointerError(const Token *tok) +void CheckBoolImpl::assignBoolToPointerError(const Token *tok) { reportError(tok, Severity::error, "assignBoolToPointer", "Boolean value assigned to pointer.", CWE587, Certainty::normal); @@ -333,7 +333,7 @@ void CheckBool::assignBoolToPointerError(const Token *tok) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -void CheckBool::checkComparisonOfBoolExpressionWithInt() +void CheckBoolImpl::checkComparisonOfBoolExpressionWithInt() { if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->isPremiumEnabled("compareBoolExpressionWithInt")) return; @@ -393,7 +393,7 @@ void CheckBool::checkComparisonOfBoolExpressionWithInt() } } -void CheckBool::comparisonOfBoolExpressionWithIntError(const Token *tok, bool not0or1) +void CheckBoolImpl::comparisonOfBoolExpressionWithIntError(const Token *tok, bool not0or1) { if (not0or1) reportError(tok, Severity::warning, "compareBoolExpressionWithInt", @@ -404,7 +404,7 @@ void CheckBool::comparisonOfBoolExpressionWithIntError(const Token *tok, bool no } -void CheckBool::pointerArithBool() +void CheckBoolImpl::pointerArithBool() { logChecker("CheckBool::pointerArithBool"); @@ -427,7 +427,7 @@ void CheckBool::pointerArithBool() } } -void CheckBool::pointerArithBoolCond(const Token *tok) +void CheckBoolImpl::pointerArithBoolCond(const Token *tok) { if (!tok) return; @@ -447,7 +447,7 @@ void CheckBool::pointerArithBoolCond(const Token *tok) pointerArithBoolError(tok); } -void CheckBool::pointerArithBoolError(const Token *tok) +void CheckBoolImpl::pointerArithBoolError(const Token *tok) { reportError(tok, Severity::error, @@ -456,7 +456,7 @@ void CheckBool::pointerArithBoolError(const Token *tok) "Converting pointer arithmetic result to bool. The boolean result is always true unless there is pointer arithmetic overflow, and overflow is undefined behaviour. Probably a dereference is forgotten.", CWE571, Certainty::normal); } -void CheckBool::checkAssignBoolToFloat() +void CheckBoolImpl::checkAssignBoolToFloat() { if (!mTokenizer->isCPP()) return; @@ -473,13 +473,13 @@ void CheckBool::checkAssignBoolToFloat() } } -void CheckBool::assignBoolToFloatError(const Token *tok) +void CheckBoolImpl::assignBoolToFloatError(const Token *tok) { reportError(tok, Severity::style, "assignBoolToFloat", "Boolean value assigned to floating point variable.", CWE704, Certainty::normal); } -void CheckBool::returnValueOfFunctionReturningBool() +void CheckBoolImpl::returnValueOfFunctionReturningBool() { if (!mSettings->severity.isEnabled(Severity::style)) return; @@ -507,14 +507,14 @@ void CheckBool::returnValueOfFunctionReturningBool() } } -void CheckBool::returnValueBoolError(const Token *tok) +void CheckBoolImpl::returnValueBoolError(const Token *tok) { reportError(tok, Severity::style, "returnNonBoolInBooleanFunction", "Non-boolean value returned from function returning bool"); } void CheckBool::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckBool checkBool(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckBoolImpl checkBool(&tokenizer, &tokenizer.getSettings(), errorLogger); // Checks checkBool.checkComparisonOfBoolExpressionWithInt(); @@ -531,7 +531,7 @@ void CheckBool::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) void CheckBool::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckBool c(nullptr, settings, errorLogger); + CheckBoolImpl c(nullptr, settings, errorLogger); c.assignBoolToPointerError(nullptr); c.assignBoolToFloatError(nullptr); c.comparisonOfFuncReturningBoolError(nullptr, "func_name"); diff --git a/lib/checkbool.h b/lib/checkbool.h index 65e5d0254ea..cde184c72e3 100644 --- a/lib/checkbool.h +++ b/lib/checkbool.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -41,16 +42,34 @@ class Tokenizer; class CPPCHECKLIB CheckBool : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckBool() : Check(myName()) {} + CheckBool() : Check("Boolean") {} private: - /** @brief This constructor is used when running checks. */ - CheckBool(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + return "Boolean type checks\n" + "- using increment on boolean\n" + "- comparison of a boolean expression with an integer other than 0 or 1\n" + "- comparison of a function returning boolean value using relational operator\n" + "- comparison of a boolean value with boolean value using relational operator\n" + "- using bool in bitwise expression\n" + "- pointer addition in condition (either dereference is forgot or pointer overflow is required to make the condition false)\n" + "- Assigning bool value to pointer or float\n" + "- Returning an integer other than 0 or 1 from a function with boolean return value\n"; + } +}; + +class CheckBoolImpl: public CheckImpl +{ +public: + /** @brief This constructor is used when running checks. */ + CheckBoolImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** @brief %Check for comparison of function returning bool*/ void checkComparisonOfFuncReturningBool(); @@ -94,24 +113,6 @@ class CPPCHECKLIB CheckBool : public Check { void comparisonOfBoolExpressionWithIntError(const Token *tok, bool not0or1); void pointerArithBoolError(const Token *tok); void returnValueBoolError(const Token *tok); - - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "Boolean"; - } - - std::string classInfo() const override { - return "Boolean type checks\n" - "- using increment on boolean\n" - "- comparison of a boolean expression with an integer other than 0 or 1\n" - "- comparison of a function returning boolean value using relational operator\n" - "- comparison of a boolean value with boolean value using relational operator\n" - "- using bool in bitwise expression\n" - "- pointer addition in condition (either dereference is forgot or pointer overflow is required to make the condition false)\n" - "- Assigning bool value to pointer or float\n" - "- Returning an integer other than 0 or 1 from a function with boolean return value\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 3ba41882316..59907d25a52 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -284,7 +284,7 @@ static std::vector getOverrunIndexValues(const Token* tok, return {}; } -void CheckBufferOverrun::arrayIndex() +void CheckBufferOverrunImpl::arrayIndex() { logChecker("CheckBufferOverrun::arrayIndex"); @@ -405,7 +405,7 @@ static std::string arrayIndexMessage(const Token* tok, return errmsg.str(); } -void CheckBufferOverrun::arrayIndexError(const Token* tok, +void CheckBufferOverrunImpl::arrayIndexError(const Token* tok, const std::vector& dimensions, const std::vector& indexes) { @@ -434,7 +434,7 @@ void CheckBufferOverrun::arrayIndexError(const Token* tok, index->isInconclusive() ? Certainty::inconclusive : Certainty::normal); } -void CheckBufferOverrun::negativeIndexError(const Token* tok, +void CheckBufferOverrunImpl::negativeIndexError(const Token* tok, const std::vector& dimensions, const std::vector& indexes) { @@ -464,7 +464,7 @@ void CheckBufferOverrun::negativeIndexError(const Token* tok, //--------------------------------------------------------------------------- -void CheckBufferOverrun::pointerArithmetic() +void CheckBufferOverrunImpl::pointerArithmetic() { if (!mSettings->severity.isEnabled(Severity::portability) && !mSettings->isPremiumEnabled("pointerOutOfBounds")) return; @@ -528,7 +528,7 @@ void CheckBufferOverrun::pointerArithmetic() } } -void CheckBufferOverrun::pointerArithmeticError(const Token *tok, const Token *indexToken, const ValueFlow::Value *indexValue) +void CheckBufferOverrunImpl::pointerArithmeticError(const Token *tok, const Token *indexToken, const ValueFlow::Value *indexValue) { if (!tok) { reportError(tok, Severity::portability, "pointerOutOfBounds", "Pointer arithmetic overflow.", CWE_POINTER_ARITHMETIC_OVERFLOW, Certainty::normal); @@ -552,7 +552,7 @@ void CheckBufferOverrun::pointerArithmeticError(const Token *tok, const Token *i //--------------------------------------------------------------------------- -ValueFlow::Value CheckBufferOverrun::getBufferSize(const Token *bufTok) const +ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok) const { if (!bufTok->valueType()) return ValueFlow::Value(-1); @@ -634,7 +634,7 @@ static bool checkBufferSize(const Token *ftok, const Library::ArgumentChecks::Mi } -void CheckBufferOverrun::bufferOverflow() +void CheckBufferOverrunImpl::bufferOverflow() { logChecker("CheckBufferOverrun::bufferOverflow"); @@ -691,14 +691,14 @@ void CheckBufferOverrun::bufferOverflow() } } -void CheckBufferOverrun::bufferOverflowError(const Token *tok, const ValueFlow::Value *value, Certainty certainty) +void CheckBufferOverrunImpl::bufferOverflowError(const Token *tok, const ValueFlow::Value *value, Certainty certainty) { reportError(getErrorPath(tok, value, "Buffer overrun"), Severity::error, "bufferAccessOutOfBounds", "Buffer is accessed out of bounds: " + (tok ? getRealBufferTok(tok)->expressionString() : "buf"), CWE_BUFFER_OVERRUN, certainty); } //--------------------------------------------------------------------------- -void CheckBufferOverrun::arrayIndexThenCheck() +void CheckBufferOverrunImpl::arrayIndexThenCheck() { if (!mSettings->severity.isEnabled(Severity::style)) return; @@ -742,7 +742,7 @@ void CheckBufferOverrun::arrayIndexThenCheck() } } -void CheckBufferOverrun::arrayIndexThenCheckError(const Token *tok, const std::string &indexName) +void CheckBufferOverrunImpl::arrayIndexThenCheckError(const Token *tok, const std::string &indexName) { reportError(tok, Severity::style, "arrayIndexThenCheck", "$symbol:" + indexName + "\n" @@ -755,7 +755,7 @@ void CheckBufferOverrun::arrayIndexThenCheckError(const Token *tok, const std::s //--------------------------------------------------------------------------- -void CheckBufferOverrun::stringNotZeroTerminated() +void CheckBufferOverrunImpl::stringNotZeroTerminated() { // this is currently 'inconclusive'. See TestBufferOverrun::terminateStrncpy3 if (!mSettings->severity.isEnabled(Severity::warning) || !mSettings->certainty.isEnabled(Certainty::inconclusive)) @@ -808,7 +808,7 @@ void CheckBufferOverrun::stringNotZeroTerminated() } } -void CheckBufferOverrun::terminateStrncpyError(const Token *tok, const std::string &varname) +void CheckBufferOverrunImpl::terminateStrncpyError(const Token *tok, const std::string &varname) { const std::string shortMessage = "The buffer '$symbol' may not be null-terminated after the call to strncpy()."; reportError(tok, Severity::warning, "terminateStrncpy", @@ -821,7 +821,7 @@ void CheckBufferOverrun::terminateStrncpyError(const Token *tok, const std::stri } //--------------------------------------------------------------------------- -void CheckBufferOverrun::argumentSize() +void CheckBufferOverrunImpl::argumentSize() { // Check '%type% x[10]' arguments if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->isPremiumEnabled("argumentSize")) @@ -869,7 +869,7 @@ void CheckBufferOverrun::argumentSize() } } -void CheckBufferOverrun::argumentSizeError(const Token *tok, const std::string &functionName, nonneg int paramIndex, const std::string ¶mExpression, const Variable *paramVar, const Variable *functionArg) +void CheckBufferOverrunImpl::argumentSizeError(const Token *tok, const std::string &functionName, nonneg int paramIndex, const std::string ¶mExpression, const Variable *paramVar, const Variable *functionArg) { const std::string strParamNum = std::to_string(paramIndex + 1) + getOrdinalText(paramIndex + 1); ErrorPath errorPath; @@ -920,7 +920,7 @@ namespace }; } -bool CheckBufferOverrun::isCtuUnsafeBufferUsage(const Settings &settings, const Token *argtok, CTU::FileInfo::Value *offset, int type) +bool CheckBufferOverrunImpl::isCtuUnsafeBufferUsage(const Settings &settings, const Token *argtok, CTU::FileInfo::Value *offset, int type) { if (!offset) return false; @@ -941,12 +941,12 @@ bool CheckBufferOverrun::isCtuUnsafeBufferUsage(const Settings &settings, const return true; } -bool CheckBufferOverrun::isCtuUnsafeArrayIndex(const Settings &settings, const Token *argtok, CTU::FileInfo::Value *offset) +bool CheckBufferOverrunImpl::isCtuUnsafeArrayIndex(const Settings &settings, const Token *argtok, CTU::FileInfo::Value *offset) { return isCtuUnsafeBufferUsage(settings, argtok, offset, 1); } -bool CheckBufferOverrun::isCtuUnsafePointerArith(const Settings &settings, const Token *argtok, CTU::FileInfo::Value* offset) +bool CheckBufferOverrunImpl::isCtuUnsafePointerArith(const Settings &settings, const Token *argtok, CTU::FileInfo::Value* offset) { return isCtuUnsafeBufferUsage(settings, argtok, offset, 2); } @@ -954,8 +954,8 @@ bool CheckBufferOverrun::isCtuUnsafePointerArith(const Settings &settings, const /** @brief Parse current TU and extract file info */ Check::FileInfo *CheckBufferOverrun::getFileInfo(const Tokenizer &tokenizer, const Settings &settings, const std::string& /*currentConfig*/) const { - const std::list &unsafeArrayIndex = CTU::getUnsafeUsage(tokenizer, settings, isCtuUnsafeArrayIndex); - const std::list &unsafePointerArith = CTU::getUnsafeUsage(tokenizer, settings, isCtuUnsafePointerArith); + const std::list &unsafeArrayIndex = CTU::getUnsafeUsage(tokenizer, settings, CheckBufferOverrunImpl::isCtuUnsafeArrayIndex); + const std::list &unsafePointerArith = CTU::getUnsafeUsage(tokenizer, settings, CheckBufferOverrunImpl::isCtuUnsafePointerArith); if (unsafeArrayIndex.empty() && unsafePointerArith.empty()) { return nullptr; } @@ -991,7 +991,7 @@ Check::FileInfo * CheckBufferOverrun::loadFileInfoFromXml(const tinyxml2::XMLEle /** @brief Analyse all file infos for all TU */ bool CheckBufferOverrun::analyseWholeProgram(const CTU::FileInfo &ctu, const std::list &fileInfo, const Settings& settings, ErrorLogger &errorLogger) { - CheckBufferOverrun dummy(nullptr, &settings, &errorLogger); + CheckBufferOverrunImpl dummy(nullptr, &settings, &errorLogger); dummy. logChecker("CheckBufferOverrun::analyseWholeProgram"); @@ -1058,7 +1058,7 @@ bool CheckBufferOverrun::analyseWholeProgram1(const std::mapgetSymbolDatabase(); @@ -1130,7 +1130,7 @@ void CheckBufferOverrun::objectIndex() } } -void CheckBufferOverrun::objectIndexError(const Token *tok, const ValueFlow::Value *v, bool known) +void CheckBufferOverrunImpl::objectIndexError(const Token *tok, const ValueFlow::Value *v, bool known) { ErrorPath errorPath; std::string name; @@ -1167,7 +1167,7 @@ static bool isVLAIndex(const Token* tok) return isVLAIndex(tok->astOperand1()) || isVLAIndex(tok->astOperand2()); } -void CheckBufferOverrun::negativeArraySize() +void CheckBufferOverrunImpl::negativeArraySize() { logChecker("CheckBufferOverrun::negativeArraySize"); const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -1197,7 +1197,7 @@ void CheckBufferOverrun::negativeArraySize() } } -void CheckBufferOverrun::negativeArraySizeError(const Token* tok) +void CheckBufferOverrunImpl::negativeArraySizeError(const Token* tok) { const std::string arrayName = tok ? tok->expressionString() : std::string(); const std::string line1 = arrayName.empty() ? std::string() : ("$symbol:" + arrayName + '\n'); @@ -1206,7 +1206,7 @@ void CheckBufferOverrun::negativeArraySizeError(const Token* tok) "Declaration of array '" + arrayName + "' with negative size is undefined behaviour", CWE758, Certainty::normal); } -void CheckBufferOverrun::negativeMemoryAllocationSizeError(const Token* tok, const ValueFlow::Value* value) +void CheckBufferOverrunImpl::negativeMemoryAllocationSizeError(const Token* tok, const ValueFlow::Value* value) { const std::string msg = "Memory allocation size is negative."; ErrorPath errorPath = getErrorPath(tok, value, msg); @@ -1217,7 +1217,7 @@ void CheckBufferOverrun::negativeMemoryAllocationSizeError(const Token* tok, con void CheckBufferOverrun::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckBufferOverrun checkBufferOverrun(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckBufferOverrunImpl checkBufferOverrun(&tokenizer, &tokenizer.getSettings(), errorLogger); checkBufferOverrun.arrayIndex(); checkBufferOverrun.pointerArithmetic(); checkBufferOverrun.bufferOverflow(); @@ -1230,7 +1230,7 @@ void CheckBufferOverrun::runChecks(const Tokenizer &tokenizer, ErrorLogger *erro void CheckBufferOverrun::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckBufferOverrun c(nullptr, settings, errorLogger); + CheckBufferOverrunImpl c(nullptr, settings, errorLogger); c.arrayIndexError(nullptr, std::vector(), std::vector()); c.pointerArithmeticError(nullptr, nullptr, nullptr); c.negativeIndexError(nullptr, std::vector(), std::vector()); diff --git a/lib/checkbufferoverrun.h b/lib/checkbufferoverrun.h index 9c6e1f0386d..e91ecc48514 100644 --- a/lib/checkbufferoverrun.h +++ b/lib/checkbufferoverrun.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include "ctu.h" @@ -60,23 +61,44 @@ namespace ValueFlow class CPPCHECKLIB CheckBufferOverrun : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckBufferOverrun() : Check(myName()) {} + CheckBufferOverrun() : Check("Bounds checking") {} private: - /** This constructor is used when running checks. */ - CheckBufferOverrun(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - /** @brief Parse current TU and extract file info */ Check::FileInfo *getFileInfo(const Tokenizer &tokenizer, const Settings &settings, const std::string& /*currentConfig*/) const override; /** @brief Analyse all file infos for all TU */ bool analyseWholeProgram(const CTU::FileInfo &ctu, const std::list &fileInfo, const Settings& settings, ErrorLogger &errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const override; + + std::string classInfo() const override { + return "Out of bounds checking:\n" + "- Array index out of bounds\n" + "- Pointer arithmetic overflow\n" + "- Buffer overflow\n" + "- Dangerous usage of strncat()\n" + "- Using array index before checking it\n" + "- Partial string write that leads to buffer that is not zero terminated.\n" + "- Check for large enough arrays being passed to functions\n" + "- Allocating memory with a negative size\n"; + } + + static bool analyseWholeProgram1(const std::map> &callsMap, const CTU::FileInfo::UnsafeUsage &unsafeUsage, + int type, ErrorLogger &errorLogger, int maxCtuDepth, const std::string& file0); +}; + +class CheckBufferOverrunImpl : public CheckImpl +{ +public: + /** This constructor is used when running checks. */ + CheckBufferOverrunImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + void arrayIndex(); void arrayIndexError(const Token* tok, const std::vector& dimensions, @@ -113,27 +135,6 @@ class CPPCHECKLIB CheckBufferOverrun : public Check { static bool isCtuUnsafeBufferUsage(const Settings &settings, const Token *argtok, CTU::FileInfo::Value *offset, int type); static bool isCtuUnsafeArrayIndex(const Settings &settings, const Token *argtok, CTU::FileInfo::Value *offset); static bool isCtuUnsafePointerArith(const Settings &settings, const Token *argtok, CTU::FileInfo::Value *offset); - - Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const override; - static bool analyseWholeProgram1(const std::map> &callsMap, const CTU::FileInfo::UnsafeUsage &unsafeUsage, - int type, ErrorLogger &errorLogger, int maxCtuDepth, const std::string& file0); - - - static std::string myName() { - return "Bounds checking"; - } - - std::string classInfo() const override { - return "Out of bounds checking:\n" - "- Array index out of bounds\n" - "- Pointer arithmetic overflow\n" - "- Buffer overflow\n" - "- Dangerous usage of strncat()\n" - "- Using array index before checking it\n" - "- Partial string write that leads to buffer that is not zero terminated.\n" - "- Check for large enough arrays being passed to functions\n" - "- Allocating memory with a negative size\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 3313fb636ed..397eb623d80 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -106,12 +106,12 @@ static bool isVclTypeInit(const Type *type) } //--------------------------------------------------------------------------- -CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger), +CheckClassImpl::CheckClassImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger), mSymbolDatabase(tokenizer?tokenizer->getSymbolDatabase():nullptr) {} -bool CheckClass::isInitialized(const CheckClass::Usage& usage, FunctionType funcType) const +bool CheckClassImpl::isInitialized(const Usage& usage, FunctionType funcType) const { const Variable& var = *usage.var; @@ -170,7 +170,7 @@ bool CheckClass::isInitialized(const CheckClass::Usage& usage, FunctionType func return false; } -void CheckClass::handleUnionMembers(std::vector& usageList) +void CheckClassImpl::handleUnionMembers(std::vector& usageList) { // Assign 1 union member => assign all union members for (const Usage& usage : usageList) { @@ -199,7 +199,7 @@ void CheckClass::handleUnionMembers(std::vector& usageList) // ClassCheck: Check that all class constructors are ok. //--------------------------------------------------------------------------- -void CheckClass::constructors() +void CheckClassImpl::constructors() { const bool printStyle = mSettings->severity.isEnabled(Severity::style); const bool printWarnings = mSettings->severity.isEnabled(Severity::warning); @@ -385,7 +385,7 @@ static bool isPermissibleConversion(const std::string& type) return type == "std::initializer_list" || type == "std::nullptr_t"; } -void CheckClass::checkExplicitConstructors() +void CheckClassImpl::checkExplicitConstructors() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("noExplicitConstructor")) return; @@ -454,7 +454,7 @@ static bool hasNonCopyableBase(const Scope *scope, bool *unknown) return false; } -void CheckClass::copyconstructors() +void CheckClassImpl::copyconstructors() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -611,7 +611,7 @@ void CheckClass::copyconstructors() } */ -void CheckClass::copyConstructorShallowCopyError(const Token *tok, const std::string& varname) +void CheckClassImpl::copyConstructorShallowCopyError(const Token *tok, const std::string& varname) { reportError(tok, Severity::warning, "copyCtorPointerCopying", "$symbol:" + varname + "\nValue of pointer '$symbol', which points to allocated memory, is copied in copy constructor instead of allocating new memory.", CWE398, Certainty::normal); @@ -637,22 +637,22 @@ static std::string noMemberErrorMessage(const Scope *scope, const char function[ return errmsg; } -void CheckClass::noCopyConstructorError(const Scope *scope, bool isdefault, const Token *alloc, bool inconclusive) +void CheckClassImpl::noCopyConstructorError(const Scope *scope, bool isdefault, const Token *alloc, bool inconclusive) { reportError(alloc, Severity::warning, "noCopyConstructor", noMemberErrorMessage(scope, "copy constructor", isdefault), CWE398, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckClass::noOperatorEqError(const Scope *scope, bool isdefault, const Token *alloc, bool inconclusive) +void CheckClassImpl::noOperatorEqError(const Scope *scope, bool isdefault, const Token *alloc, bool inconclusive) { reportError(alloc, Severity::warning, "noOperatorEq", noMemberErrorMessage(scope, "operator=", isdefault), CWE398, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckClass::noDestructorError(const Scope *scope, bool isdefault, const Token *alloc) +void CheckClassImpl::noDestructorError(const Scope *scope, bool isdefault, const Token *alloc) { reportError(alloc, Severity::warning, "noDestructor", noMemberErrorMessage(scope, "destructor", isdefault), CWE398, Certainty::normal); } -bool CheckClass::canNotCopy(const Scope *scope) +bool CheckClassImpl::canNotCopy(const Scope *scope) { bool constructor = false; bool publicAssign = false; @@ -676,7 +676,7 @@ bool CheckClass::canNotCopy(const Scope *scope) return constructor && !(publicAssign || publicCopy); } -bool CheckClass::canNotMove(const Scope *scope) +bool CheckClassImpl::canNotMove(const Scope *scope) { bool constructor = false; bool publicAssign = false; @@ -721,7 +721,7 @@ static void getAllVariableMembers(const Scope *scope, std::vector CheckClass::createUsageList(const Scope *scope) +std::vector CheckClassImpl::createUsageList(const Scope *scope) { std::vector ret; std::vector varlist; @@ -733,7 +733,7 @@ std::vector CheckClass::createUsageList(const Scope *scope) return ret; } -void CheckClass::assignVar(std::vector &usageList, nonneg int varid) +void CheckClassImpl::assignVar(std::vector &usageList, nonneg int varid) { auto it = std::find_if(usageList.begin(), usageList.end(), [varid](const Usage& usage) { return usage.var->declarationId() == varid; @@ -742,7 +742,7 @@ void CheckClass::assignVar(std::vector &usageList, nonneg int varid) it->assign = true; } -void CheckClass::assignVar(std::vector &usageList, const Token* vartok) +void CheckClassImpl::assignVar(std::vector &usageList, const Token* vartok) { if (vartok->varId() > 0) { assignVar(usageList, vartok->varId()); @@ -756,7 +756,7 @@ void CheckClass::assignVar(std::vector &usageList, const Token* vartok) it->assign = true; } -void CheckClass::initVar(std::vector &usageList, nonneg int varid) +void CheckClassImpl::initVar(std::vector &usageList, nonneg int varid) { auto it = std::find_if(usageList.begin(), usageList.end(), [varid](const Usage& usage) { return usage.var->declarationId() == varid; @@ -765,13 +765,13 @@ void CheckClass::initVar(std::vector &usageList, nonneg int varid) it->init = true; } -void CheckClass::assignAllVar(std::vector &usageList) +void CheckClassImpl::assignAllVar(std::vector &usageList) { for (Usage & i : usageList) i.assign = true; } -void CheckClass::assignAllVarsVisibleFromScope(std::vector& usageList, const Scope* scope) +void CheckClassImpl::assignAllVarsVisibleFromScope(std::vector& usageList, const Scope* scope) { for (Usage& usage : usageList) { if (usage.var->scope() == scope) @@ -787,7 +787,7 @@ void CheckClass::assignAllVarsVisibleFromScope(std::vector& usageList, co } } -void CheckClass::clearAllVar(std::vector &usageList) +void CheckClassImpl::clearAllVar(std::vector &usageList) { for (Usage & i : usageList) { i.assign = false; @@ -795,7 +795,7 @@ void CheckClass::clearAllVar(std::vector &usageList) } } -bool CheckClass::isBaseClassMutableMemberFunc(const Token *tok, const Scope *scope) +bool CheckClassImpl::isBaseClassMutableMemberFunc(const Token *tok, const Scope *scope) { // Iterate through each base class... for (const Type::BaseInfo & i : scope->definedType->derivedFrom) { @@ -822,7 +822,7 @@ bool CheckClass::isBaseClassMutableMemberFunc(const Token *tok, const Scope *sco return false; } -void CheckClass::initializeVarList(const Function &func, std::list &callstack, const Scope *scope, std::vector &usage) const +void CheckClassImpl::initializeVarList(const Function &func, std::list &callstack, const Scope *scope, std::vector &usage) const { if (!func.functionScope) return; @@ -1154,7 +1154,7 @@ void CheckClass::initializeVarList(const Function &func, std::listseverity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("unusedPrivateFunction")) return; @@ -1422,7 +1422,7 @@ void CheckClass::privateFunctions() } } -void CheckClass::unusedPrivateFunctionError(const Token* tok1, const Token *tok2, const std::string &classname, const std::string &funcname) +void CheckClassImpl::unusedPrivateFunctionError(const Token* tok1, const Token *tok2, const std::string &classname, const std::string &funcname) { std::list toks{ tok1 }; if (tok2) @@ -1444,7 +1444,7 @@ static const Scope* findFunctionOf(const Scope* scope) return nullptr; } -void CheckClass::checkMemset() +void CheckClassImpl::checkMemset() { logChecker("CheckClass::checkMemset"); const bool printWarnings = mSettings->severity.isEnabled(Severity::warning); @@ -1540,7 +1540,7 @@ void CheckClass::checkMemset() } } -void CheckClass::checkMemsetType(const Scope *start, const Token *tok, const Scope *type, bool allocation, std::set parsedTypes) +void CheckClassImpl::checkMemsetType(const Scope *start, const Token *tok, const Scope *type, bool allocation, std::set parsedTypes) { // If type has been checked there is no need to check it again if (parsedTypes.find(type) != parsedTypes.end()) @@ -1606,7 +1606,7 @@ void CheckClass::checkMemsetType(const Scope *start, const Token *tok, const Sco } } -void CheckClass::mallocOnClassWarning(const Token* tok, const std::string &memfunc, const Token* classTok) +void CheckClassImpl::mallocOnClassWarning(const Token* tok, const std::string &memfunc, const Token* classTok) { std::list toks = { tok, classTok }; reportError(toks, Severity::warning, "mallocOnClassWarning", @@ -1616,7 +1616,7 @@ void CheckClass::mallocOnClassWarning(const Token* tok, const std::string &memfu "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.", CWE762, Certainty::normal); } -void CheckClass::mallocOnClassError(const Token* tok, const std::string &memfunc, const Token* classTok, const std::string &classname) +void CheckClassImpl::mallocOnClassError(const Token* tok, const std::string &memfunc, const Token* classTok, const std::string &classname) { std::list toks = { tok, classTok }; reportError(toks, Severity::error, "mallocOnClassError", @@ -1627,7 +1627,7 @@ void CheckClass::mallocOnClassError(const Token* tok, const std::string &memfunc "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.", CWE665, Certainty::normal); } -void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type, bool isContainer) +void CheckClassImpl::memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type, bool isContainer) { const std::string typeStr = isContainer ? std::string() : (type + " that contains a "); const std::string msg = "$symbol:" + memfunc + "\n" @@ -1639,14 +1639,14 @@ void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const reportError(tok, Severity::error, "memsetClass", msg, CWE762, Certainty::normal); } -void CheckClass::memsetErrorReference(const Token *tok, const std::string &memfunc, const std::string &type) +void CheckClassImpl::memsetErrorReference(const Token *tok, const std::string &memfunc, const std::string &type) { reportError(tok, Severity::error, "memsetClassReference", "$symbol:" + memfunc +"\n" "Using '" + memfunc + "' on " + type + " that contains a reference.", CWE665, Certainty::normal); } -void CheckClass::memsetErrorFloat(const Token *tok, const std::string &type) +void CheckClassImpl::memsetErrorFloat(const Token *tok, const std::string &type) { reportError(tok, Severity::portability, "memsetClassFloat", "Using memset() on " + type + " which contains a floating point number.\n" "Using memset() on " + type + " which contains a floating point number." @@ -1661,7 +1661,7 @@ void CheckClass::memsetErrorFloat(const Token *tok, const std::string &type) // operator= should return a reference to *this //--------------------------------------------------------------------------- -void CheckClass::operatorEqRetRefThis() +void CheckClassImpl::operatorEqRetRefThis() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("operatorEqRetRefThis")) return; @@ -1680,13 +1680,13 @@ void CheckClass::operatorEqRetRefThis() } } -void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last) +void CheckClassImpl::checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last) { std::set analyzedFunctions; checkReturnPtrThis(scope, func, tok, last, analyzedFunctions); } -void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last, std::set& analyzedFunctions) +void CheckClassImpl::checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last, std::set& analyzedFunctions) { bool foundReturn = false; @@ -1772,17 +1772,17 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co operatorEqMissingReturnStatementError(func->token, func->access == AccessControl::Public); } -void CheckClass::operatorEqRetRefThisError(const Token *tok) +void CheckClassImpl::operatorEqRetRefThisError(const Token *tok) { reportError(tok, Severity::style, "operatorEqRetRefThis", "'operator=' should return reference to 'this' instance.", CWE398, Certainty::normal); } -void CheckClass::operatorEqShouldBeLeftUnimplementedError(const Token *tok) +void CheckClassImpl::operatorEqShouldBeLeftUnimplementedError(const Token *tok) { reportError(tok, Severity::style, "operatorEqShouldBeLeftUnimplemented", "'operator=' should either return reference to 'this' instance or be declared private and left unimplemented.", CWE398, Certainty::normal); } -void CheckClass::operatorEqMissingReturnStatementError(const Token *tok, bool error) +void CheckClassImpl::operatorEqMissingReturnStatementError(const Token *tok, bool error) { if (error) { reportError(tok, Severity::error, "operatorEqMissingReturnStatement", "No 'return' statement in non-void function causes undefined behavior.", CWE398, Certainty::normal); @@ -1805,7 +1805,7 @@ void CheckClass::operatorEqMissingReturnStatementError(const Token *tok, bool er // assignment to self. //--------------------------------------------------------------------------- -void CheckClass::operatorEqToSelf() +void CheckClassImpl::operatorEqToSelf() { if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->isPremiumEnabled("operatorEqToSelf")) return; @@ -1846,7 +1846,7 @@ void CheckClass::operatorEqToSelf() } } -bool CheckClass::hasAllocationInIfScope(const Function *func, const Scope* scope, const Token *ifStatementScopeStart) const +bool CheckClassImpl::hasAllocationInIfScope(const Function *func, const Scope* scope, const Token *ifStatementScopeStart) const { const Token *end; if (ifStatementScopeStart->str() == "{") @@ -1856,12 +1856,12 @@ bool CheckClass::hasAllocationInIfScope(const Function *func, const Scope* scope return hasAllocation(func, scope, ifStatementScopeStart, end); } -bool CheckClass::hasAllocation(const Function *func, const Scope* scope) const +bool CheckClassImpl::hasAllocation(const Function *func, const Scope* scope) const { return hasAllocation(func, scope, func->functionScope->bodyStart, func->functionScope->bodyEnd); } -bool CheckClass::hasAllocation(const Function *func, const Scope* scope, const Token *start, const Token *end) const +bool CheckClassImpl::hasAllocation(const Function *func, const Scope* scope, const Token *start, const Token *end) const { if (!end) end = func->functionScope->bodyEnd; @@ -1907,7 +1907,7 @@ static bool isFalseKeyword(const Token* tok) * Checks if self-assignment test is inverse * For example 'if (this == &rhs)' */ -CheckClass::Bool CheckClass::isInverted(const Token *tok, const Token *rhs) +CheckClassImpl::Bool CheckClassImpl::isInverted(const Token *tok, const Token *rhs) { bool res = true; for (const Token *itr = tok; itr && itr->str()!="("; itr=itr->astParent()) { @@ -1936,7 +1936,7 @@ CheckClass::Bool CheckClass::isInverted(const Token *tok, const Token *rhs) return Bool::False; } -const Token * CheckClass::getIfStmtBodyStart(const Token *tok, const Token *rhs) +const Token * CheckClassImpl::getIfStmtBodyStart(const Token *tok, const Token *rhs) { const Token *top = tok->astTop(); if (Token::simpleMatch(top->link(), ") {")) { @@ -1952,7 +1952,7 @@ const Token * CheckClass::getIfStmtBodyStart(const Token *tok, const Token *rhs) return nullptr; } -bool CheckClass::hasAssignSelf(const Function *func, const Token *rhs, const Token *&out_ifStatementScopeStart) +bool CheckClassImpl::hasAssignSelf(const Function *func, const Token *rhs, const Token *&out_ifStatementScopeStart) { if (!rhs) return false; @@ -1986,7 +1986,7 @@ bool CheckClass::hasAssignSelf(const Function *func, const Token *rhs, const Tok return false; } -void CheckClass::operatorEqToSelfError(const Token *tok) +void CheckClassImpl::operatorEqToSelfError(const Token *tok) { reportError(tok, Severity::warning, "operatorEqToSelf", "'operator=' should check for assignment to self to avoid problems with dynamic memory.\n" @@ -1998,7 +1998,7 @@ void CheckClass::operatorEqToSelfError(const Token *tok) // A destructor in a base class should be virtual //--------------------------------------------------------------------------- -void CheckClass::virtualDestructor() +void CheckClassImpl::virtualDestructor() { // This error should only be given if: // * base class doesn't have virtual destructor @@ -2133,7 +2133,7 @@ void CheckClass::virtualDestructor() virtualDestructorError(func->tokenDef, func->name(), "", true); } -void CheckClass::virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived, bool inconclusive) +void CheckClassImpl::virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived, bool inconclusive) { if (inconclusive) { if (mSettings->severity.isEnabled(Severity::warning)) @@ -2154,7 +2154,7 @@ void CheckClass::virtualDestructorError(const Token *tok, const std::string &Bas // warn for "this-x". The indented code may be "this->x" //--------------------------------------------------------------------------- -void CheckClass::thisSubtraction() +void CheckClassImpl::thisSubtraction() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -2174,7 +2174,7 @@ void CheckClass::thisSubtraction() } } -void CheckClass::thisSubtractionError(const Token *tok) +void CheckClassImpl::thisSubtractionError(const Token *tok) { reportError(tok, Severity::warning, "thisSubtraction", "Suspicious pointer subtraction. Did you intend to write '->'?", CWE398, Certainty::normal); } @@ -2183,7 +2183,7 @@ void CheckClass::thisSubtractionError(const Token *tok) // can member function be const? //--------------------------------------------------------------------------- -void CheckClass::checkConst() +void CheckClassImpl::checkConst() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("functionConst") && @@ -2319,7 +2319,7 @@ static const Token* getFuncTokFromThis(const Token* tok) { return Token::Match(tok, "%name% (") ? tok : nullptr; } -bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) const +bool CheckClassImpl::isMemberVar(const Scope *scope, const Token *tok) const { bool again = false; @@ -2406,7 +2406,7 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) const return false; } -bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) +bool CheckClassImpl::isMemberFunc(const Scope *scope, const Token *tok) { if (!tok->function()) { if (Token::simpleMatch(tok->astParent(), ".") && Token::simpleMatch(tok->astParent()->astOperand1(), "this")) @@ -2449,7 +2449,7 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) return false; } -bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) +bool CheckClassImpl::isConstMemberFunc(const Scope *scope, const Token *tok) { if (!tok->function()) return false; @@ -2474,7 +2474,7 @@ bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) return false; } -const std::set CheckClass::stl_containers_not_const = { "map", "unordered_map", "std :: map|unordered_map <" }; // start pattern +const std::set CheckClassImpl::stl_containers_not_const = { "map", "unordered_map", "std :: map|unordered_map <" }; // start pattern static bool isNonConstPtrCast(const Token* tok) { @@ -2484,7 +2484,7 @@ static bool isNonConstPtrCast(const Token* tok) return !vt || (vt->pointer > 0 && !vt->isConst(vt->pointer)); } -bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, MemberAccess& memberAccessed) const +bool CheckClassImpl::checkConstFunc(const Scope *scope, const Function *func, MemberAccess& memberAccessed) const { if (mTokenizer->hasIfdef(func->functionScope->bodyStart, func->functionScope->bodyEnd)) return false; @@ -2758,12 +2758,12 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, Member return true; } -void CheckClass::checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic, bool foundAllBaseClasses) +void CheckClassImpl::checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic, bool foundAllBaseClasses) { checkConstError2(tok, nullptr, classname, funcname, suggestStatic, foundAllBaseClasses); } -void CheckClass::checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic, bool foundAllBaseClasses) +void CheckClassImpl::checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic, bool foundAllBaseClasses) { std::list toks{ tok1 }; if (tok2) @@ -2804,7 +2804,7 @@ namespace { // avoid one-definition-rule violation }; } -void CheckClass::initializerListOrder() +void CheckClassImpl::initializerListOrder() { if (!mSettings->isPremiumEnabled("initializerList")) { if (!mSettings->severity.isEnabled(Severity::style)) @@ -2883,7 +2883,7 @@ void CheckClass::initializerListOrder() } } -void CheckClass::initializerListError(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &varname, const std::string& argname) +void CheckClassImpl::initializerListError(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &varname, const std::string& argname) { std::list toks = { tok1, tok2 }; const std::string msg = argname.empty() ? @@ -2904,7 +2904,7 @@ void CheckClass::initializerListError(const Token *tok1, const Token *tok2, cons // Check for self initialization in initialization list //--------------------------------------------------------------------------- -void CheckClass::checkSelfInitialization() +void CheckClassImpl::checkSelfInitialization() { logChecker("CheckClass::checkSelfInitialization"); @@ -2933,7 +2933,7 @@ void CheckClass::checkSelfInitialization() } } -void CheckClass::selfInitializationError(const Token* tok, const std::string& varname) +void CheckClassImpl::selfInitializationError(const Token* tok, const std::string& varname) { reportError(tok, Severity::error, "selfInitialization", "$symbol:" + varname + "\nMember variable '$symbol' is initialized by itself.", CWE665, Certainty::normal); } @@ -2943,7 +2943,7 @@ void CheckClass::selfInitializationError(const Token* tok, const std::string& va // Check for virtual function calls in constructor/destructor //--------------------------------------------------------------------------- -void CheckClass::checkVirtualFunctionCallInConstructor() +void CheckClassImpl::checkVirtualFunctionCallInConstructor() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -2973,7 +2973,7 @@ void CheckClass::checkVirtualFunctionCallInConstructor() } } -const std::list & CheckClass::getVirtualFunctionCalls(const Function & function, +const std::list & CheckClassImpl::getVirtualFunctionCalls(const Function & function, std::map> & virtualFunctionCallsMap) { const auto found = utils::as_const(virtualFunctionCallsMap).find(&function); @@ -3031,7 +3031,7 @@ const std::list & CheckClass::getVirtualFunctionCalls(const Funct return virtualFunctionCalls; } -void CheckClass::getFirstVirtualFunctionCallStack( +void CheckClassImpl::getFirstVirtualFunctionCallStack( std::map> & virtualFunctionCallsMap, const Token * callToken, std::list & pureFuncStack) @@ -3051,7 +3051,7 @@ void CheckClass::getFirstVirtualFunctionCallStack( getFirstVirtualFunctionCallStack(virtualFunctionCallsMap, firstCall, pureFuncStack); } -void CheckClass::virtualFunctionCallInConstructorError( +void CheckClassImpl::virtualFunctionCallInConstructorError( const Function * scopeFunction, const std::list & tokStack, const std::string &funcname) @@ -3089,7 +3089,7 @@ void CheckClass::virtualFunctionCallInConstructorError( "Virtual function '" + funcname + "' is called from " + scopeFunctionTypeName + " '" + constructorName + "' at line " + std::to_string(lineNumber) + ". Dynamic binding is not used.", CWE(0U), Certainty::normal); } -void CheckClass::pureVirtualFunctionCallInConstructorError( +void CheckClassImpl::pureVirtualFunctionCallInConstructorError( const Function * scopeFunction, const std::list & tokStack, const std::string &purefuncname) @@ -3114,7 +3114,7 @@ void CheckClass::pureVirtualFunctionCallInConstructorError( // Check for members hiding inherited members with the same name //--------------------------------------------------------------------------- -void CheckClass::checkDuplInheritedMembers() +void CheckClassImpl::checkDuplInheritedMembers() { if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->isPremiumEnabled("duplInheritedMember")) return; @@ -3203,7 +3203,7 @@ static std::vector getDuplInheritedMemberFunctionsRecursive( return results; } -void CheckClass::checkDuplInheritedMembersRecursive(const Type* typeCurrent, const Type* typeBase) +void CheckClassImpl::checkDuplInheritedMembersRecursive(const Type* typeCurrent, const Type* typeBase) { const auto resultsVar = getDuplInheritedMembersRecursive(typeCurrent, typeBase); for (const auto& r : resultsVar) { @@ -3222,7 +3222,7 @@ void CheckClass::checkDuplInheritedMembersRecursive(const Type* typeCurrent, con } } -void CheckClass::duplInheritedMembersError(const Token *tok1, const Token* tok2, +void CheckClassImpl::duplInheritedMembersError(const Token *tok1, const Token* tok2, const std::string &derivedName, const std::string &baseName, const std::string &memberName, bool derivedIsStruct, bool baseIsStruct, bool isFunction) { @@ -3250,7 +3250,7 @@ enum class CtorType : std::uint8_t { WITH_BODY }; -void CheckClass::checkCopyCtorAndEqOperator() +void CheckClassImpl::checkCopyCtorAndEqOperator() { // TODO: This is disabled because of #8388 // The message must be clarified. How is the behaviour different? @@ -3302,7 +3302,7 @@ void CheckClass::checkCopyCtorAndEqOperator() } } -void CheckClass::copyCtorAndEqOperatorError(const Token *tok, const std::string &classname, bool isStruct, bool hasCopyCtor) +void CheckClassImpl::copyCtorAndEqOperatorError(const Token *tok, const std::string &classname, bool isStruct, bool hasCopyCtor) { const std::string message = "$symbol:" + classname + "\n" "The " + std::string(isStruct ? "struct" : "class") + " '$symbol' has '" + @@ -3312,7 +3312,7 @@ void CheckClass::copyCtorAndEqOperatorError(const Token *tok, const std::string reportError(tok, Severity::warning, "copyCtorAndEqOperator", message); } -void CheckClass::checkOverride() +void CheckClassImpl::checkOverride() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("missingOverride")) return; @@ -3336,7 +3336,7 @@ void CheckClass::checkOverride() } } -void CheckClass::overrideError(const Function *funcInBase, const Function *funcInDerived) +void CheckClassImpl::overrideError(const Function *funcInBase, const Function *funcInDerived) { const std::string functionName = funcInDerived ? ((funcInDerived->isDestructor() ? "~" : "") + funcInDerived->name()) : ""; const std::string funcType = (funcInDerived && funcInDerived->isDestructor()) ? "destructor" : "function"; @@ -3354,7 +3354,7 @@ void CheckClass::overrideError(const Function *funcInBase, const Function *funcI Certainty::normal); } -void CheckClass::uselessOverrideError(const Function *funcInBase, const Function *funcInDerived, bool isSameCode) +void CheckClassImpl::uselessOverrideError(const Function *funcInBase, const Function *funcInDerived, bool isSameCode) { const std::string functionName = funcInDerived ? ((funcInDerived->isDestructor() ? "~" : "") + funcInDerived->name()) : ""; const std::string funcType = (funcInDerived && funcInDerived->isDestructor()) ? "destructor" : "function"; @@ -3418,7 +3418,7 @@ static bool compareTokenRanges(const Token* start1, const Token* end1, const Tok return isEqual; } -void CheckClass::checkUselessOverride() +void CheckClassImpl::checkUselessOverride() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("uselessOverride")) return; @@ -3499,7 +3499,7 @@ static const Variable* getSingleReturnVar(const Scope* scope) { return tok->variable(); } -void CheckClass::checkReturnByReference() +void CheckClassImpl::checkReturnByReference() { if (!mSettings->severity.isEnabled(Severity::performance) && !mSettings->isPremiumEnabled("returnByReference")) return; @@ -3542,14 +3542,14 @@ void CheckClass::checkReturnByReference() } } -void CheckClass::returnByReferenceError(const Function* func, const Variable* var) +void CheckClassImpl::returnByReferenceError(const Function* func, const Variable* var) { const Token* tok = func ? func->tokenDef : nullptr; const std::string message = "Function '" + (func ? func->name() : "func") + "()' should return member '" + (var ? var->name() : "var") + "' by const reference."; reportError(tok, Severity::performance, "returnByReference", message); } -void CheckClass::checkThisUseAfterFree() +void CheckClassImpl::checkThisUseAfterFree() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -3598,7 +3598,7 @@ void CheckClass::checkThisUseAfterFree() } } -bool CheckClass::checkThisUseAfterFreeRecursive(const Scope *classScope, const Function *func, const Variable *selfPointer, std::set callstack, const Token *&freeToken) +bool CheckClassImpl::checkThisUseAfterFreeRecursive(const Scope *classScope, const Function *func, const Variable *selfPointer, std::set callstack, const Token *&freeToken) { if (!func || !func->functionScope) return false; @@ -3637,7 +3637,7 @@ bool CheckClass::checkThisUseAfterFreeRecursive(const Scope *classScope, const F return false; } -void CheckClass::thisUseAfterFree(const Token *self, const Token *free, const Token *use) +void CheckClassImpl::thisUseAfterFree(const Token *self, const Token *free, const Token *use) { std::string selfPointer = self ? self->str() : "ptr"; ErrorPath errorPath = { ErrorPathItem(self, "Assuming '" + selfPointer + "' is used as 'this'"), ErrorPathItem(free, "Delete '" + selfPointer + "', invalidating 'this'"), ErrorPathItem(use, "Call method when 'this' is invalid") }; @@ -3649,7 +3649,7 @@ void CheckClass::thisUseAfterFree(const Token *self, const Token *free, const To CWE(0), Certainty::normal); } -void CheckClass::checkUnsafeClassRefMember() +void CheckClassImpl::checkUnsafeClassRefMember() { if (!mSettings->safeChecks.classes || !mSettings->severity.isEnabled(Severity::warning)) return; @@ -3673,7 +3673,7 @@ void CheckClass::checkUnsafeClassRefMember() } } -void CheckClass::unsafeClassRefMemberError(const Token *tok, const std::string &varname) +void CheckClassImpl::unsafeClassRefMemberError(const Token *tok, const std::string &varname) { reportError(tok, Severity::warning, "unsafeClassRefMember", "$symbol:" + varname + "\n" @@ -3833,9 +3833,8 @@ bool CheckClass::analyseWholeProgram(const CTU::FileInfo &ctu, const std::list @@ -49,23 +50,63 @@ enum class FunctionType : std::uint8_t; /** @brief %Check classes. Uninitialized member variables, non-conforming operators, missing virtual destructor, etc */ class CPPCHECKLIB CheckClass : public Check { friend class TestClass; + friend class TestConstructors; + friend class TestUnusedPrivateFunction; public: /** @brief This constructor is used when registering the CheckClass */ - CheckClass() : Check(myName()) {} - - /** @brief Set of the STL types whose operator[] is not const */ - static const std::set stl_containers_not_const; - -private: - /** @brief This constructor is used when running checks. */ - CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger); + CheckClass() : Check("Class") {} /** @brief Run checks on the normal token list */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + /** @brief Parse current TU and extract file info */ + Check::FileInfo *getFileInfo(const Tokenizer &tokenizer, const Settings& /*settings*/, const std::string& currentConfig) const override; + + Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const override; + + /** @brief Analyse all file infos for all TU */ + bool analyseWholeProgram(const CTU::FileInfo &ctu, const std::list &fileInfo, const Settings& settings, ErrorLogger &errorLogger) override; + + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + return "Check the code for each class.\n" + "- Missing constructors and copy constructors\n" + //"- Missing allocation of memory in copy constructor\n" + "- Constructors which should be explicit\n" + "- Are all variables initialized by the constructors?\n" + "- Are all variables assigned by 'operator='?\n" + "- Warn if memset, memcpy etc are used on a class\n" + "- Warn if memory for classes is allocated with malloc()\n" + "- If it's a base class, check that the destructor is virtual\n" + "- Are there unused private functions?\n" + "- 'operator=' should check for assignment to self\n" + "- Constness for member functions\n" + "- Order of initializations\n" + "- Suggest usage of initialization list\n" + "- Initialization of a member with itself\n" + "- Suspicious subtraction from 'this'\n" + "- Call of pure virtual function in constructor/destructor\n" + "- Duplicated inherited data members\n" + // disabled for now "- If 'copy constructor' defined, 'operator=' also should be defined and vice versa\n" + "- Check that arbitrary usage of public interface does not result in division by zero\n" + "- Delete \"self pointer\" and then access 'this'\n" + "- Check that the 'override' keyword is used when overriding virtual functions\n" + "- Check that the 'one definition rule' is not violated\n"; + } +}; + +class CheckClassImpl : public CheckImpl { +public: + /** This constructor is used when running checks. */ + CheckClassImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger); + + /** @brief Set of the STL types whose operator[] is not const */ + static const std::set stl_containers_not_const; + /** @brief %Check that all class constructors are ok */ void constructors(); @@ -137,14 +178,6 @@ class CPPCHECKLIB CheckClass : public Check { /** @brief Unsafe class check - const reference member */ void checkUnsafeClassRefMember(); - /** @brief Parse current TU and extract file info */ - Check::FileInfo *getFileInfo(const Tokenizer &tokenizer, const Settings& /*settings*/, const std::string& currentConfig) const override; - - Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const override; - - /** @brief Analyse all file infos for all TU */ - bool analyseWholeProgram(const CTU::FileInfo &ctu, const std::list &fileInfo, const Settings& settings, ErrorLogger &errorLogger) override; - const SymbolDatabase* mSymbolDatabase{}; // Reporting errors.. @@ -187,38 +220,6 @@ class CPPCHECKLIB CheckClass : public Check { void unsafeClassRefMemberError(const Token *tok, const std::string &varname); void checkDuplInheritedMembersRecursive(const Type* typeCurrent, const Type* typeBase); - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "Class"; - } - - std::string classInfo() const override { - return "Check the code for each class.\n" - "- Missing constructors and copy constructors\n" - //"- Missing allocation of memory in copy constructor\n" - "- Constructors which should be explicit\n" - "- Are all variables initialized by the constructors?\n" - "- Are all variables assigned by 'operator='?\n" - "- Warn if memset, memcpy etc are used on a class\n" - "- Warn if memory for classes is allocated with malloc()\n" - "- If it's a base class, check that the destructor is virtual\n" - "- Are there unused private functions?\n" - "- 'operator=' should check for assignment to self\n" - "- Constness for member functions\n" - "- Order of initializations\n" - "- Suggest usage of initialization list\n" - "- Initialization of a member with itself\n" - "- Suspicious subtraction from 'this'\n" - "- Call of pure virtual function in constructor/destructor\n" - "- Duplicated inherited data members\n" - // disabled for now "- If 'copy constructor' defined, 'operator=' also should be defined and vice versa\n" - "- Check that arbitrary usage of public interface does not result in division by zero\n" - "- Delete \"self pointer\" and then access 'this'\n" - "- Check that the 'override' keyword is used when overriding virtual functions\n" - "- Check that the 'one definition rule' is not violated\n"; - } - // operatorEqRetRefThis helper functions void checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last); void checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last, std::set& analyzedFunctions); diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index cec3293ad27..e9fc0b0de99 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -52,7 +52,7 @@ static const CWE CWE571(571U); // Expression is Always True //--------------------------------------------------------------------------- -bool CheckCondition::diag(const Token* tok, bool insert) +bool CheckConditionImpl::diag(const Token* tok, bool insert) { if (!tok) return false; @@ -73,14 +73,14 @@ bool CheckCondition::diag(const Token* tok, bool insert) return true; } -bool CheckCondition::diag(const Token* tok1, const Token* tok2) +bool CheckConditionImpl::diag(const Token* tok1, const Token* tok2) { const bool b1 = diag(tok1); const bool b2 = diag(tok2); return b1 && b2; } -bool CheckCondition::isAliased(const std::set &vars) const +bool CheckConditionImpl::isAliased(const std::set &vars) const { for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "= & %var% ;") && vars.find(tok->tokAt(2)->varId()) != vars.end()) @@ -89,7 +89,7 @@ bool CheckCondition::isAliased(const std::set &vars) const return false; } -void CheckCondition::assignIf() +void CheckConditionImpl::assignIf() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("assignIfError")) return; @@ -162,7 +162,7 @@ static bool isParameterChanged(const Token *partok) } /** parse scopes recursively */ -bool CheckCondition::assignIfParseScope(const Token * const assignTok, +bool CheckConditionImpl::assignIfParseScope(const Token * const assignTok, const Token * const startTok, const nonneg int varid, const bool islocal, @@ -240,7 +240,7 @@ bool CheckCondition::assignIfParseScope(const Token * const assignTok, return false; } -void CheckCondition::assignIfError(const Token *tok1, const Token *tok2, const std::string &condition, bool result) +void CheckConditionImpl::assignIfError(const Token *tok1, const Token *tok2, const std::string &condition, bool result) { if (tok2 && diag(tok2->tokAt(2))) return; @@ -252,7 +252,7 @@ void CheckCondition::assignIfError(const Token *tok1, const Token *tok2, const s } -void CheckCondition::mismatchingBitAndError(const Token *tok1, const MathLib::bigint num1, const Token *tok2, const MathLib::bigint num2) +void CheckConditionImpl::mismatchingBitAndError(const Token *tok1, const MathLib::bigint num1, const Token *tok2, const MathLib::bigint num2) { std::list locations = { tok1, tok2 }; @@ -308,7 +308,7 @@ static bool isOperandExpanded(const Token *tok) return false; } -void CheckCondition::checkBadBitmaskCheck() +void CheckConditionImpl::checkBadBitmaskCheck() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("badBitmaskCheck")) return; @@ -348,7 +348,7 @@ void CheckCondition::checkBadBitmaskCheck() } } -void CheckCondition::badBitmaskCheckError(const Token *tok, bool isNoOp) +void CheckConditionImpl::badBitmaskCheckError(const Token *tok, bool isNoOp) { if (isNoOp) reportError(tok, Severity::style, "badBitmaskCheck", "Operator '|' with one operand equal to zero is redundant.", CWE571, Certainty::normal); @@ -356,7 +356,7 @@ void CheckCondition::badBitmaskCheckError(const Token *tok, bool isNoOp) reportError(tok, Severity::warning, "badBitmaskCheck", "Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?", CWE571, Certainty::normal); } -void CheckCondition::comparison() +void CheckConditionImpl::comparison() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("comparisonError")) return; @@ -421,7 +421,7 @@ void CheckCondition::comparison() } } -void CheckCondition::comparisonError(const Token *tok, const std::string &bitop, MathLib::bigint value1, const std::string &op, MathLib::bigint value2, bool result) +void CheckConditionImpl::comparisonError(const Token *tok, const std::string &bitop, MathLib::bigint value1, const std::string &op, MathLib::bigint value2, bool result) { std::ostringstream expression; expression << std::hex << "(X " << bitop << " 0x" << value1 << ") " << op << " 0x" << value2; @@ -435,7 +435,7 @@ void CheckCondition::comparisonError(const Token *tok, const std::string &bitop, reportError(tok, Severity::style, "comparisonError", errmsg, CWE398, Certainty::normal); } -bool CheckCondition::isOverlappingCond(const Token * const cond1, const Token * const cond2, bool pure) const +bool CheckConditionImpl::isOverlappingCond(const Token * const cond1, const Token * const cond2, bool pure) const { if (!cond1 || !cond2) return false; @@ -476,7 +476,7 @@ bool CheckCondition::isOverlappingCond(const Token * const cond1, const Token * return false; } -void CheckCondition::duplicateCondition() +void CheckConditionImpl::duplicateCondition() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("duplicateCondition")) return; @@ -515,7 +515,7 @@ void CheckCondition::duplicateCondition() } } -void CheckCondition::duplicateConditionError(const Token *tok1, const Token *tok2, ErrorPath errorPath) +void CheckConditionImpl::duplicateConditionError(const Token *tok1, const Token *tok2, ErrorPath errorPath) { if (diag(tok1, tok2)) return; @@ -527,7 +527,7 @@ void CheckCondition::duplicateConditionError(const Token *tok1, const Token *tok reportError(std::move(errorPath), Severity::style, "duplicateCondition", msg, CWE398, Certainty::normal); } -void CheckCondition::multiCondition() +void CheckConditionImpl::multiCondition() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("multiCondition")) return; @@ -570,7 +570,7 @@ void CheckCondition::multiCondition() } } -void CheckCondition::overlappingElseIfConditionError(const Token *tok, nonneg int line1) +void CheckConditionImpl::overlappingElseIfConditionError(const Token *tok, nonneg int line1) { if (diag(tok)) return; @@ -581,7 +581,7 @@ void CheckCondition::overlappingElseIfConditionError(const Token *tok, nonneg in reportError(tok, Severity::style, "multiCondition", errmsg.str(), CWE398, Certainty::normal); } -void CheckCondition::oppositeElseIfConditionError(const Token *ifCond, const Token *elseIfCond, ErrorPath errorPath) +void CheckConditionImpl::oppositeElseIfConditionError(const Token *ifCond, const Token *elseIfCond, ErrorPath errorPath) { if (diag(ifCond, elseIfCond)) return; @@ -629,7 +629,7 @@ static bool isNestedInLambda(const Scope* inner, const Scope* outer) return false; } -void CheckCondition::multiCondition2() +void CheckConditionImpl::multiCondition2() { if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->isPremiumEnabled("identicalConditionAfterEarlyExit") && @@ -861,7 +861,7 @@ static std::string innerSmtString(const Token * tok) return top->str(); } -void CheckCondition::oppositeInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath) +void CheckConditionImpl::oppositeInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath) { if (diag(tok1, tok2)) return; @@ -876,7 +876,7 @@ void CheckCondition::oppositeInnerConditionError(const Token *tok1, const Token* reportError(std::move(errorPath), Severity::warning, "oppositeInnerCondition", msg, CWE398, Certainty::normal); } -void CheckCondition::overlappingInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath) +void CheckConditionImpl::overlappingInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath) { if (diag(tok1, tok2)) return; @@ -891,7 +891,7 @@ void CheckCondition::overlappingInnerConditionError(const Token *tok1, const To reportError(std::move(errorPath), Severity::warning, "overlappingInnerCondition", msg, CWE398, Certainty::normal); } -void CheckCondition::identicalInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath) +void CheckConditionImpl::identicalInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath) { if (diag(tok1, tok2)) return; @@ -906,7 +906,7 @@ void CheckCondition::identicalInnerConditionError(const Token *tok1, const Token reportError(std::move(errorPath), Severity::warning, "identicalInnerCondition", msg, CWE398, Certainty::normal); } -void CheckCondition::identicalConditionAfterEarlyExitError(const Token *cond1, const Token* cond2, ErrorPath errorPath) +void CheckConditionImpl::identicalConditionAfterEarlyExitError(const Token *cond1, const Token* cond2, ErrorPath errorPath) { if (diag(cond1, cond2)) return; @@ -1156,7 +1156,7 @@ static bool isIfConstexpr(const Token* tok) { return Token::simpleMatch(top->astOperand1(), "if") && top->astOperand1()->isConstexpr(); } -void CheckCondition::checkIncorrectLogicOperator() +void CheckConditionImpl::checkIncorrectLogicOperator() { const bool printStyle = mSettings->severity.isEnabled(Severity::style); const bool printWarning = mSettings->severity.isEnabled(Severity::warning); @@ -1367,7 +1367,7 @@ void CheckCondition::checkIncorrectLogicOperator() } } -void CheckCondition::incorrectLogicOperatorError(const Token *tok, const std::string &condition, bool always, bool inconclusive, ErrorPath errors) +void CheckConditionImpl::incorrectLogicOperatorError(const Token *tok, const std::string &condition, bool always, bool inconclusive, ErrorPath errors) { if (diag(tok)) return; @@ -1384,7 +1384,7 @@ void CheckCondition::incorrectLogicOperatorError(const Token *tok, const std::st "Are these conditions necessary? Did you intend to use || instead? Are the numbers correct? Are you comparing the correct variables?", CWE570, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckCondition::redundantConditionError(const Token *tok, const std::string &text, bool inconclusive) +void CheckConditionImpl::redundantConditionError(const Token *tok, const std::string &text, bool inconclusive) { if (diag(tok)) return; @@ -1394,7 +1394,7 @@ void CheckCondition::redundantConditionError(const Token *tok, const std::string //----------------------------------------------------------------------------- // Detect "(var % val1) > val2" where val2 is >= val1. //----------------------------------------------------------------------------- -void CheckCondition::checkModuloAlwaysTrueFalse() +void CheckConditionImpl::checkModuloAlwaysTrueFalse() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -1424,7 +1424,7 @@ void CheckCondition::checkModuloAlwaysTrueFalse() } } -void CheckCondition::moduloAlwaysTrueFalseError(const Token* tok, const std::string& maxVal) +void CheckConditionImpl::moduloAlwaysTrueFalseError(const Token* tok, const std::string& maxVal) { if (diag(tok)) return; @@ -1450,7 +1450,7 @@ static int countPar(const Token *tok1, const Token *tok2) // Clarify condition '(x = a < 0)' into '((x = a) < 0)' or '(x = (a < 0))' // Clarify condition '(a & b == c)' into '((a & b) == c)' or '(a & (b == c))' //--------------------------------------------------------------------------- -void CheckCondition::clarifyCondition() +void CheckConditionImpl::clarifyCondition() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("clarifyCondition")) return; @@ -1491,7 +1491,7 @@ void CheckCondition::clarifyCondition() } } -void CheckCondition::clarifyConditionError(const Token *tok, bool assign, bool boolop) +void CheckConditionImpl::clarifyConditionError(const Token *tok, bool assign, bool boolop) { std::string errmsg; @@ -1514,7 +1514,7 @@ void CheckCondition::clarifyConditionError(const Token *tok, bool assign, bool b errmsg, CWE398, Certainty::normal); } -void CheckCondition::alwaysTrueFalse() +void CheckConditionImpl::alwaysTrueFalse() { const bool pedantic = mSettings->isPremiumEnabled("alwaysTrue") || mSettings->isPremiumEnabled("alwaysFalse") || @@ -1669,7 +1669,7 @@ static std::string getConditionString(const Token* condition) return "Condition"; } -void CheckCondition::alwaysTrueFalseError(const Token* tok, const Token* condition, const ValueFlow::Value* value) +void CheckConditionImpl::alwaysTrueFalseError(const Token* tok, const Token* condition, const ValueFlow::Value* value) { const bool alwaysTrue = value && (value->intvalue != 0 || value->isImpossible()); const std::string expr = tok ? tok->expressionString() : std::string("x"); @@ -1683,7 +1683,7 @@ void CheckCondition::alwaysTrueFalseError(const Token* tok, const Token* conditi (alwaysTrue ? CWE571 : CWE570), Certainty::normal); } -void CheckCondition::checkInvalidTestForOverflow() +void CheckConditionImpl::checkInvalidTestForOverflow() { // Interesting blogs: // https://www.airs.com/blog/archives/120 @@ -1771,7 +1771,7 @@ void CheckCondition::checkInvalidTestForOverflow() } } -void CheckCondition::invalidTestForOverflow(const Token* tok, const ValueType *valueType, const std::string &replace) +void CheckConditionImpl::invalidTestForOverflow(const Token* tok, const ValueType *valueType, const std::string &replace) { const std::string expr = (tok ? tok->expressionString() : std::string("x + c < x")); const std::string overflow = (valueType && valueType->pointer) ? "pointer overflow" : "signed integer overflow"; @@ -1786,7 +1786,7 @@ void CheckCondition::invalidTestForOverflow(const Token* tok, const ValueType *v } -void CheckCondition::checkPointerAdditionResultNotNull() +void CheckConditionImpl::checkPointerAdditionResultNotNull() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -1827,13 +1827,13 @@ void CheckCondition::checkPointerAdditionResultNotNull() } } -void CheckCondition::pointerAdditionResultNotNullError(const Token *tok, const Token *calc) +void CheckConditionImpl::pointerAdditionResultNotNullError(const Token *tok, const Token *calc) { const std::string s = calc ? calc->expressionString() : "ptr+1"; reportError(tok, Severity::warning, "pointerAdditionResultNotNull", "Comparison is wrong. Result of '" + s + "' can't be 0 unless there is pointer overflow, and pointer overflow is undefined behaviour."); } -void CheckCondition::checkDuplicateConditionalAssign() +void CheckConditionImpl::checkDuplicateConditionalAssign() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("duplicateConditionalAssign")) return; @@ -1890,7 +1890,7 @@ void CheckCondition::checkDuplicateConditionalAssign() } } -void CheckCondition::duplicateConditionalAssignError(const Token *condTok, const Token* assignTok, bool isRedundant) +void CheckConditionImpl::duplicateConditionalAssignError(const Token *condTok, const Token* assignTok, bool isRedundant) { ErrorPath errors; std::string msg = "Duplicate expression for the condition and assignment."; @@ -1912,7 +1912,7 @@ void CheckCondition::duplicateConditionalAssignError(const Token *condTok, const } -void CheckCondition::checkAssignmentInCondition() +void CheckConditionImpl::checkAssignmentInCondition() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("assignmentInCondition")) return; @@ -1946,7 +1946,7 @@ void CheckCondition::checkAssignmentInCondition() } } -void CheckCondition::assignmentInCondition(const Token *eq) +void CheckConditionImpl::assignmentInCondition(const Token *eq) { std::string expr = eq ? eq->expressionString() : "x=y"; @@ -1959,7 +1959,7 @@ void CheckCondition::assignmentInCondition(const Token *eq) Certainty::normal); } -void CheckCondition::checkCompareValueOutOfTypeRange() +void CheckConditionImpl::checkCompareValueOutOfTypeRange() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("compareValueOutOfTypeRangeError")) return; @@ -2080,7 +2080,7 @@ void CheckCondition::checkCompareValueOutOfTypeRange() } } -void CheckCondition::compareValueOutOfTypeRangeError(const Token *comparisonTok, const std::string &type, MathLib::bigint value, bool result) +void CheckConditionImpl::compareValueOutOfTypeRangeError(const Token *comparisonTok, const std::string &type, MathLib::bigint value, bool result) { reportError( comparisonTok, @@ -2093,7 +2093,7 @@ void CheckCondition::compareValueOutOfTypeRangeError(const Token *comparisonTok, void CheckCondition::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckCondition checkCondition(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckConditionImpl checkCondition(&tokenizer, &tokenizer.getSettings(), errorLogger); checkCondition.multiCondition(); checkCondition.clarifyCondition(); // not simplified because ifAssign checkCondition.multiCondition2(); @@ -2113,7 +2113,7 @@ void CheckCondition::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLog void CheckCondition::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckCondition c(nullptr, settings, errorLogger); + CheckConditionImpl c(nullptr, settings, errorLogger); c.assignIfError(nullptr, nullptr, "", false); c.badBitmaskCheckError(nullptr); diff --git a/lib/checkcondition.h b/lib/checkcondition.h index 2ea20158b11..d2a82e54655 100644 --- a/lib/checkcondition.h +++ b/lib/checkcondition.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include "mathlib.h" #include "errortypes.h" @@ -50,15 +51,39 @@ namespace ValueFlow { class CPPCHECKLIB CheckCondition : public Check { public: /** This constructor is used when registering the CheckAssignIf */ - CheckCondition() : Check(myName()) {} + CheckCondition() : Check("Condition") {} private: - /** This constructor is used when running checks. */ - CheckCondition(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + return "Match conditions with assignments and other conditions:\n" + "- Mismatching assignment and comparison => comparison is always true/false\n" + "- Mismatching lhs and rhs in comparison => comparison is always true/false\n" + "- Detect usage of | where & should be used\n" + "- Duplicate condition and assignment\n" + "- Detect matching 'if' and 'else if' conditions\n" + "- Mismatching bitand (a &= 0xf0; a &= 1; => a = 0)\n" + "- Opposite inner condition is always false\n" + "- Identical condition after early exit is always false\n" + "- Condition that is always true/false\n" + "- Mutual exclusion over || always evaluating to true\n" + "- Comparisons of modulo results that are always true/false.\n" + "- Known variable values => condition is always true/false\n" + "- Invalid test for overflow. Some mainstream compilers remove such overflow tests when optimising code.\n" + "- Suspicious assignment of container/iterator in condition => condition is always true.\n"; + } +}; + + +class CheckConditionImpl : public CheckImpl { +public: + /** This constructor is used when running checks. */ + CheckConditionImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** mismatching assignment / comparison */ void assignIf(); @@ -157,30 +182,6 @@ class CPPCHECKLIB CheckCondition : public Check { void checkCompareValueOutOfTypeRange(); void compareValueOutOfTypeRangeError(const Token *comparisonTok, const std::string &type, MathLib::bigint value, bool result); - - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "Condition"; - } - - std::string classInfo() const override { - return "Match conditions with assignments and other conditions:\n" - "- Mismatching assignment and comparison => comparison is always true/false\n" - "- Mismatching lhs and rhs in comparison => comparison is always true/false\n" - "- Detect usage of | where & should be used\n" - "- Duplicate condition and assignment\n" - "- Detect matching 'if' and 'else if' conditions\n" - "- Mismatching bitand (a &= 0xf0; a &= 1; => a = 0)\n" - "- Opposite inner condition is always false\n" - "- Identical condition after early exit is always false\n" - "- Condition that is always true/false\n" - "- Mutual exclusion over || always evaluating to true\n" - "- Comparisons of modulo results that are always true/false.\n" - "- Known variable values => condition is always true/false\n" - "- Invalid test for overflow. Some mainstream compilers remove such overflow tests when optimising code.\n" - "- Suspicious assignment of container/iterator in condition => condition is always true.\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkexceptionsafety.cpp b/lib/checkexceptionsafety.cpp index 6da5281e80a..463e47bea1c 100644 --- a/lib/checkexceptionsafety.cpp +++ b/lib/checkexceptionsafety.cpp @@ -40,7 +40,7 @@ static const CWE CWE480(480U); // Use of Incorrect Operator //--------------------------------------------------------------------------- -void CheckExceptionSafety::destructors() +void CheckExceptionSafetyImpl::destructors() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -78,7 +78,7 @@ void CheckExceptionSafety::destructors() } } -void CheckExceptionSafety::destructorsError(const Token * const tok, const std::string &className) +void CheckExceptionSafetyImpl::destructorsError(const Token * const tok, const std::string &className) { reportError(tok, Severity::warning, "exceptThrowInDestructor", "Class " + className + " is not safe, destructor throws exception\n" @@ -88,7 +88,7 @@ void CheckExceptionSafety::destructorsError(const Token * const tok, const std:: } -void CheckExceptionSafety::deallocThrow() +void CheckExceptionSafetyImpl::deallocThrow() { if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->isPremiumEnabled("exceptDeallocThrow")) return; @@ -151,7 +151,7 @@ void CheckExceptionSafety::deallocThrow() } } -void CheckExceptionSafety::deallocThrowError(const Token * const tok, const std::string &varname) +void CheckExceptionSafetyImpl::deallocThrowError(const Token * const tok, const std::string &varname) { reportError(tok, Severity::warning, "exceptDeallocThrow", "Exception thrown in invalid state, '" + varname + "' points at deallocated memory.", CWE398, Certainty::normal); @@ -163,7 +163,7 @@ void CheckExceptionSafety::deallocThrowError(const Token * const tok, const std: // throw err; // <- should be just "throw;" // } //--------------------------------------------------------------------------- -void CheckExceptionSafety::checkRethrowCopy() +void CheckExceptionSafetyImpl::checkRethrowCopy() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("exceptRethrowCopy")) return; @@ -196,7 +196,7 @@ void CheckExceptionSafety::checkRethrowCopy() } } -void CheckExceptionSafety::rethrowCopyError(const Token * const tok, const std::string &varname) +void CheckExceptionSafetyImpl::rethrowCopyError(const Token * const tok, const std::string &varname) { reportError(tok, Severity::style, "exceptRethrowCopy", "Throwing a copy of the caught exception instead of rethrowing the original exception.\n" @@ -207,7 +207,7 @@ void CheckExceptionSafety::rethrowCopyError(const Token * const tok, const std:: //--------------------------------------------------------------------------- // try {} catch (std::exception err) {} <- Should be "std::exception& err" //--------------------------------------------------------------------------- -void CheckExceptionSafety::checkCatchExceptionByValue() +void CheckExceptionSafetyImpl::checkCatchExceptionByValue() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("catchExceptionByValue")) return; @@ -228,7 +228,7 @@ void CheckExceptionSafety::checkCatchExceptionByValue() } } -void CheckExceptionSafety::catchExceptionByValueError(const Token *tok) +void CheckExceptionSafetyImpl::catchExceptionByValueError(const Token *tok) { reportError(tok, Severity::style, "catchExceptionByValue", "Exception should be caught by reference.\n" @@ -281,7 +281,7 @@ static const Token * functionThrows(const Function * function) // void func() throw() { throw x; } // void func() __attribute__((nothrow)); void func() { throw x; } //-------------------------------------------------------------------------- -void CheckExceptionSafety::nothrowThrows() +void CheckExceptionSafetyImpl::nothrowThrows() { logChecker("CheckExceptionSafety::nothrowThrows"); @@ -313,12 +313,12 @@ void CheckExceptionSafety::nothrowThrows() } } -void CheckExceptionSafety::noexceptThrowError(const Token * const tok) +void CheckExceptionSafetyImpl::noexceptThrowError(const Token * const tok) { reportError(tok, Severity::error, "throwInNoexceptFunction", "Unhandled exception thrown in function declared not to throw exceptions.", CWE398, Certainty::normal); } -void CheckExceptionSafety::entryPointThrowError(const Token * const tok) +void CheckExceptionSafetyImpl::entryPointThrowError(const Token * const tok) { reportError(tok, Severity::error, "throwInEntryPoint", "Unhandled exception thrown in function that is an entry point.", CWE398, Certainty::normal); } @@ -326,7 +326,7 @@ void CheckExceptionSafety::entryPointThrowError(const Token * const tok) //-------------------------------------------------------------------------- // void func() { functionWithExceptionSpecification(); } //-------------------------------------------------------------------------- -void CheckExceptionSafety::unhandledExceptionSpecification() +void CheckExceptionSafetyImpl::unhandledExceptionSpecification() { if ((!mSettings->severity.isEnabled(Severity::style) || !mSettings->certainty.isEnabled(Certainty::inconclusive)) && !mSettings->isPremiumEnabled("unhandledExceptionSpecification")) @@ -356,7 +356,7 @@ void CheckExceptionSafety::unhandledExceptionSpecification() } } -void CheckExceptionSafety::unhandledExceptionSpecificationError(const Token * const tok1, const Token * const tok2, const std::string & funcname) +void CheckExceptionSafetyImpl::unhandledExceptionSpecificationError(const Token * const tok1, const Token * const tok2, const std::string & funcname) { const std::string str1(tok1 ? tok1->str() : "foo"); const std::list locationList = { tok1, tok2 }; @@ -369,7 +369,7 @@ void CheckExceptionSafety::unhandledExceptionSpecificationError(const Token * co //-------------------------------------------------------------------------- // 7.6.18.4 If no exception is presently being handled, evaluating a throw-expression with no operand calls std​::​​terminate(). //-------------------------------------------------------------------------- -void CheckExceptionSafety::rethrowNoCurrentException() +void CheckExceptionSafetyImpl::rethrowNoCurrentException() { logChecker("CheckExceptionSafety::rethrowNoCurrentException"); const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -400,7 +400,7 @@ void CheckExceptionSafety::rethrowNoCurrentException() } } -void CheckExceptionSafety::rethrowNoCurrentExceptionError(const Token *tok) +void CheckExceptionSafetyImpl::rethrowNoCurrentExceptionError(const Token *tok) { reportError(tok, Severity::error, "rethrowNoCurrentException", "Rethrowing current exception with 'throw;', it seems there is no current exception to rethrow." @@ -414,7 +414,7 @@ void CheckExceptionSafety::runChecks(const Tokenizer &tokenizer, ErrorLogger *er if (tokenizer.isC()) return; - CheckExceptionSafety checkExceptionSafety(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckExceptionSafetyImpl checkExceptionSafety(&tokenizer, &tokenizer.getSettings(), errorLogger); checkExceptionSafety.destructors(); checkExceptionSafety.deallocThrow(); checkExceptionSafety.checkRethrowCopy(); @@ -426,7 +426,7 @@ void CheckExceptionSafety::runChecks(const Tokenizer &tokenizer, ErrorLogger *er void CheckExceptionSafety::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckExceptionSafety c(nullptr, settings, errorLogger); + CheckExceptionSafetyImpl c(nullptr, settings, errorLogger); c.destructorsError(nullptr, "Class"); c.deallocThrowError(nullptr, "p"); c.rethrowCopyError(nullptr, "varname"); diff --git a/lib/checkexceptionsafety.h b/lib/checkexceptionsafety.h index 7c5a52b5605..f1a432cc896 100644 --- a/lib/checkexceptionsafety.h +++ b/lib/checkexceptionsafety.h @@ -22,6 +22,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -46,15 +47,33 @@ class Tokenizer; class CPPCHECKLIB CheckExceptionSafety : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckExceptionSafety() : Check(myName()) {} + CheckExceptionSafety() : Check("Exception Safety") {} private: - /** This constructor is used when running checks. */ - CheckExceptionSafety(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + /** Generate all possible errors (for --errorlist) */ + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + /** wiki formatted description of the class (for --doc) */ + std::string classInfo() const override { + return "Checking exception safety\n" + "- Throwing exceptions in destructors\n" + "- Throwing exception during invalid state\n" + "- Throwing a copy of a caught exception instead of rethrowing the original exception\n" + "- Exception caught by value instead of by reference\n" + "- Throwing exception in noexcept, nothrow(), __attribute__((nothrow)) or __declspec(nothrow) function\n" + "- Unhandled exception specification when calling function foo()\n" + "- Rethrow without currently handled exception\n"; + } +}; + +class CheckExceptionSafetyImpl : public CheckImpl { +public: + /** This constructor is used when running checks. */ + CheckExceptionSafetyImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** Don't throw exceptions in destructors */ void destructors(); @@ -87,26 +106,6 @@ class CPPCHECKLIB CheckExceptionSafety : public Check { void unhandledExceptionSpecificationError(const Token * tok1, const Token * tok2, const std::string & funcname); /** Rethrow without currently handled exception */ void rethrowNoCurrentExceptionError(const Token *tok); - - /** Generate all possible errors (for --errorlist) */ - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - /** Short description of class (for --doc) */ - static std::string myName() { - return "Exception Safety"; - } - - /** wiki formatted description of the class (for --doc) */ - std::string classInfo() const override { - return "Checking exception safety\n" - "- Throwing exceptions in destructors\n" - "- Throwing exception during invalid state\n" - "- Throwing a copy of a caught exception instead of rethrowing the original exception\n" - "- Exception caught by value instead of by reference\n" - "- Throwing exception in noexcept, nothrow(), __attribute__((nothrow)) or __declspec(nothrow) function\n" - "- Unhandled exception specification when calling function foo()\n" - "- Rethrow without currently handled exception\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index 733b868814e..47a3828de31 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -52,7 +52,7 @@ static const CWE CWE686(686U); // Function Call With Incorrect Argument Type static const CWE CWE687(687U); // Function Call With Incorrectly Specified Argument Value static const CWE CWE688(688U); // Function Call With Incorrect Variable or Reference as Argument -void CheckFunctions::checkProhibitedFunctions() +void CheckFunctionsImpl::checkProhibitedFunctions() { const bool checkAlloca = mSettings->severity.isEnabled(Severity::warning) && ((mTokenizer->isC() && mSettings->standards.c >= Standards::C99) || mSettings->standards.cpp >= Standards::CPP11); @@ -88,7 +88,8 @@ void CheckFunctions::checkProhibitedFunctions() if (wi) { if (mSettings->severity.isEnabled(wi->severity) && ((tok->isC() && mSettings->standards.c >= wi->standards.c) || (tok->isCpp() && mSettings->standards.cpp >= wi->standards.cpp))) { const std::string daca = mSettings->daca ? "prohibited" : ""; - reportError(tok, wi->severity, daca + tok->str() + "Called", wi->message, CWE477, Certainty::normal); + const std::string prefix = daca + tok->str(); + functionCalledError(tok, wi->severity, prefix, wi->message); } } } @@ -96,10 +97,15 @@ void CheckFunctions::checkProhibitedFunctions() } } +void CheckFunctionsImpl::functionCalledError(const Token* tok, Severity severity, const std::string& prefix, const std::string& msg) +{ + reportError(tok, severity, prefix + "Called", msg, CWE477, Certainty::normal); +} + //--------------------------------------------------------------------------- // Check , and //--------------------------------------------------------------------------- -void CheckFunctions::invalidFunctionUsage() +void CheckFunctionsImpl::invalidFunctionUsage() { logChecker("CheckFunctions::invalidFunctionUsage"); const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -191,7 +197,7 @@ void CheckFunctions::invalidFunctionUsage() } } -void CheckFunctions::invalidFunctionArgError(const Token *tok, const std::string &functionName, int argnr, const ValueFlow::Value *invalidValue, const std::string &validstr) +void CheckFunctionsImpl::invalidFunctionArgError(const Token *tok, const std::string &functionName, int argnr, const ValueFlow::Value *invalidValue, const std::string &validstr) { std::ostringstream errmsg; errmsg << "$symbol:" << functionName << '\n'; @@ -220,7 +226,7 @@ void CheckFunctions::invalidFunctionArgError(const Token *tok, const std::string Certainty::normal); } -void CheckFunctions::invalidFunctionArgBoolError(const Token *tok, const std::string &functionName, int argnr) +void CheckFunctionsImpl::invalidFunctionArgBoolError(const Token *tok, const std::string &functionName, int argnr) { std::ostringstream errmsg; errmsg << "$symbol:" << functionName << '\n'; @@ -228,7 +234,7 @@ void CheckFunctions::invalidFunctionArgBoolError(const Token *tok, const std::st reportError(tok, Severity::error, "invalidFunctionArgBool", errmsg.str(), CWE628, Certainty::normal); } -void CheckFunctions::invalidFunctionArgStrError(const Token *tok, const std::string &functionName, nonneg int argnr) +void CheckFunctionsImpl::invalidFunctionArgStrError(const Token *tok, const std::string &functionName, nonneg int argnr) { std::ostringstream errmsg; errmsg << "$symbol:" << functionName << '\n'; @@ -239,7 +245,7 @@ void CheckFunctions::invalidFunctionArgStrError(const Token *tok, const std::str //--------------------------------------------------------------------------- // Check for ignored return values. //--------------------------------------------------------------------------- -void CheckFunctions::checkIgnoredReturnValue() +void CheckFunctionsImpl::checkIgnoredReturnValue() { if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->severity.isEnabled(Severity::style) && @@ -290,13 +296,13 @@ void CheckFunctions::checkIgnoredReturnValue() } } -void CheckFunctions::ignoredReturnValueError(const Token* tok, const std::string& function) +void CheckFunctionsImpl::ignoredReturnValueError(const Token* tok, const std::string& function) { reportError(tok, Severity::warning, "ignoredReturnValue", "$symbol:" + function + "\nReturn value of function $symbol() is not used.", CWE252, Certainty::normal); } -void CheckFunctions::ignoredReturnErrorCode(const Token* tok, const std::string& function) +void CheckFunctionsImpl::ignoredReturnErrorCode(const Token* tok, const std::string& function) { reportError(tok, Severity::style, "ignoredReturnErrorCode", "$symbol:" + function + "\nError code from the return value of function $symbol() is not used.", CWE252, Certainty::normal); @@ -307,7 +313,7 @@ void CheckFunctions::ignoredReturnErrorCode(const Token* tok, const std::string& //--------------------------------------------------------------------------- static const Token *checkMissingReturnScope(const Token *tok, const Library &library); -void CheckFunctions::checkMissingReturn() +void CheckFunctionsImpl::checkMissingReturn() { logChecker("CheckFunctions::checkMissingReturn"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -425,7 +431,7 @@ static const Token *checkMissingReturnScope(const Token *tok, const Library &lib return nullptr; } -void CheckFunctions::missingReturnError(const Token* tok) +void CheckFunctionsImpl::missingReturnError(const Token* tok) { reportError(tok, Severity::error, "missingReturn", "Found an exit path from function with non-void return type that has missing return statement", CWE758, Certainty::normal); @@ -433,7 +439,7 @@ void CheckFunctions::missingReturnError(const Token* tok) //--------------------------------------------------------------------------- // Detect passing wrong values to functions like atan(0, x); //--------------------------------------------------------------------------- -void CheckFunctions::checkMathFunctions() +void CheckFunctionsImpl::checkMathFunctions() { const bool styleC99 = mSettings->severity.isEnabled(Severity::style) && ((mTokenizer->isC() && mSettings->standards.c != Standards::C89) || (mTokenizer->isCPP() && mSettings->standards.cpp != Standards::CPP03)); const bool printWarnings = mSettings->severity.isEnabled(Severity::warning); @@ -494,7 +500,7 @@ void CheckFunctions::checkMathFunctions() } } -void CheckFunctions::mathfunctionCallWarning(const Token *tok, const nonneg int numParam) +void CheckFunctionsImpl::mathfunctionCallWarning(const Token *tok, const nonneg int numParam) { if (tok) { if (numParam == 1) @@ -505,7 +511,7 @@ void CheckFunctions::mathfunctionCallWarning(const Token *tok, const nonneg int reportError(tok, Severity::warning, "wrongmathcall", "Passing value '#' to #() leads to implementation-defined result.", CWE758, Certainty::normal); } -void CheckFunctions::mathfunctionCallWarning(const Token *tok, const std::string& oldexp, const std::string& newexp) +void CheckFunctionsImpl::mathfunctionCallWarning(const Token *tok, const std::string& oldexp, const std::string& newexp) { reportError(tok, Severity::style, "unpreciseMathCall", "Expression '" + oldexp + "' can be replaced by '" + newexp + "' to avoid loss of precision.", CWE758, Certainty::normal); } @@ -513,7 +519,7 @@ void CheckFunctions::mathfunctionCallWarning(const Token *tok, const std::string //--------------------------------------------------------------------------- // memset(p, y, 0 /* bytes to fill */) <- 2nd and 3rd arguments inverted //--------------------------------------------------------------------------- -void CheckFunctions::memsetZeroBytes() +void CheckFunctionsImpl::memsetZeroBytes() { // FIXME: // Replace this with library configuration. @@ -542,7 +548,7 @@ void CheckFunctions::memsetZeroBytes() } } -void CheckFunctions::memsetZeroBytesError(const Token *tok) +void CheckFunctionsImpl::memsetZeroBytesError(const Token *tok) { const std::string summary("memset() called to fill 0 bytes."); const std::string verbose(summary + " The second and third arguments might be inverted." @@ -551,7 +557,7 @@ void CheckFunctions::memsetZeroBytesError(const Token *tok) reportError(tok, Severity::warning, "memsetZeroBytes", summary + "\n" + verbose, CWE687, Certainty::normal); } -void CheckFunctions::memsetInvalid2ndParam() +void CheckFunctionsImpl::memsetInvalid2ndParam() { // FIXME: // Replace this with library configuration. @@ -599,7 +605,7 @@ void CheckFunctions::memsetInvalid2ndParam() } } -void CheckFunctions::memsetFloatError(const Token *tok, const std::string &var_value) +void CheckFunctionsImpl::memsetFloatError(const Token *tok, const std::string &var_value) { const std::string message("The 2nd memset() argument '" + var_value + "' is a float, its representation is implementation defined."); @@ -608,7 +614,7 @@ void CheckFunctions::memsetFloatError(const Token *tok, const std::string &var_v reportError(tok, Severity::portability, "memsetFloat", message + "\n" + verbose, CWE688, Certainty::normal); } -void CheckFunctions::memsetValueOutOfRangeError(const Token *tok, const std::string &value) +void CheckFunctionsImpl::memsetValueOutOfRangeError(const Token *tok, const std::string &value) { const std::string message("The 2nd memset() argument '" + value + "' doesn't fit into an 'unsigned char'."); const std::string verbose(message + " The 2nd parameter is passed as an 'int', but the function fills the block of memory using the 'unsigned char' conversion of this value."); @@ -619,7 +625,7 @@ void CheckFunctions::memsetValueOutOfRangeError(const Token *tok, const std::str // --check-library => warn for unconfigured functions //--------------------------------------------------------------------------- -void CheckFunctions::checkLibraryMatchFunctions() +void CheckFunctionsImpl::checkLibraryMatchFunctions() { if (!mSettings->checkLibrary) return; @@ -697,7 +703,7 @@ void CheckFunctions::checkLibraryMatchFunctions() // Check for problems to compiler apply (Named) Return Value Optimization for local variable // Technically we have different guarantees between standard versions // details: https://en.cppreference.com/w/cpp/language/copy_elision -void CheckFunctions::returnLocalStdMove() +void CheckFunctionsImpl::returnLocalStdMove() { if (!mTokenizer->isCPP() || mSettings->standards.cpp < Standards::CPP11) return; @@ -727,7 +733,7 @@ void CheckFunctions::returnLocalStdMove() } } -void CheckFunctions::copyElisionError(const Token *tok) +void CheckFunctionsImpl::copyElisionError(const Token *tok) { reportError(tok, Severity::performance, @@ -736,7 +742,7 @@ void CheckFunctions::copyElisionError(const Token *tok) " More: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-return-move-local"); } -void CheckFunctions::useStandardLibrary() +void CheckFunctionsImpl::useStandardLibrary() { if (!mSettings->severity.isEnabled(Severity::style)) return; @@ -840,7 +846,7 @@ void CheckFunctions::useStandardLibrary() } } -void CheckFunctions::useStandardLibraryError(const Token *tok, const std::string& expected) +void CheckFunctionsImpl::useStandardLibraryError(const Token *tok, const std::string& expected) { reportError(tok, Severity::style, "useStandardLibrary", @@ -849,7 +855,7 @@ void CheckFunctions::useStandardLibraryError(const Token *tok, const std::string void CheckFunctions::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckFunctions checkFunctions(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckFunctionsImpl checkFunctions(&tokenizer, &tokenizer.getSettings(), errorLogger); checkFunctions.checkIgnoredReturnValue(); checkFunctions.checkMissingReturn(); // Missing "return" in exit path @@ -868,10 +874,10 @@ void CheckFunctions::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLog void CheckFunctions::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckFunctions c(nullptr, settings, errorLogger); + CheckFunctionsImpl c(nullptr, settings, errorLogger); for (auto i = settings->library.functionwarn().cbegin(); i != settings->library.functionwarn().cend(); ++i) { - c.reportError(nullptr, Severity::style, i->first+"Called", i->second.message); + c.functionCalledError(nullptr, Severity::style, i->first, i->second.message); } c.invalidFunctionArgError(nullptr, "func_name", 1, nullptr,"1:4"); diff --git a/lib/checkfunctions.h b/lib/checkfunctions.h index f5954d14043..0bf56c708af 100644 --- a/lib/checkfunctions.h +++ b/lib/checkfunctions.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -47,16 +48,34 @@ namespace ValueFlow { class CPPCHECKLIB CheckFunctions : public Check { public: /** This constructor is used when registering the CheckFunctions */ - CheckFunctions() : Check(myName()) {} + CheckFunctions() : Check("Check function usage") {} private: - /** This constructor is used when running checks. */ - CheckFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + return "Check function usage:\n" + "- missing 'return' in non-void function\n" + "- return value of certain functions not used\n" + "- invalid input values for functions\n" + "- Warn if a function is called whose usage is discouraged\n" + "- memset() third argument is zero\n" + "- memset() with a value out of range as the 2nd parameter\n" + "- memset() with a float as the 2nd parameter\n" + "- copy elision optimization for returning value affected by std::move\n" + "- use memcpy()/memset() instead of for loop\n"; + } +}; + +class CheckFunctionsImpl : public CheckImpl { +public: + /** This constructor is used when running checks. */ + CheckFunctionsImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** Check for functions that should not be used */ void checkProhibitedFunctions(); @@ -106,25 +125,7 @@ class CPPCHECKLIB CheckFunctions : public Check { void missingReturnError(const Token *tok); void copyElisionError(const Token *tok); void useStandardLibraryError(const Token *tok, const std::string& expected); - - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "Check function usage"; - } - - std::string classInfo() const override { - return "Check function usage:\n" - "- missing 'return' in non-void function\n" - "- return value of certain functions not used\n" - "- invalid input values for functions\n" - "- Warn if a function is called whose usage is discouraged\n" - "- memset() third argument is zero\n" - "- memset() with a value out of range as the 2nd parameter\n" - "- memset() with a float as the 2nd parameter\n" - "- copy elision optimization for returning value affected by std::move\n" - "- use memcpy()/memset() instead of for loop\n"; - } + void functionCalledError(const Token* tok, Severity severity, const std::string& prefix, const std::string& msg); }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/check.cpp b/lib/checkimpl.cpp similarity index 57% rename from lib/check.cpp rename to lib/checkimpl.cpp index 4033378e927..e0ae4d70722 100644 --- a/lib/check.cpp +++ b/lib/checkimpl.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,9 +16,7 @@ * along with this program. If not, see . */ -//--------------------------------------------------------------------------- - -#include "check.h" +#include "checkimpl.h" #include "errorlogger.h" #include "settings.h" @@ -26,59 +24,37 @@ #include "tokenize.h" #include "vfvalue.h" -#include -#include +#include #include -//--------------------------------------------------------------------------- - -Check::Check(std::string aname) - : mName(std::move(aname)) -{} - -void Check::writeToErrorList(const ErrorMessage &errmsg) +void CheckImpl::reportError(const std::list &callstack, Severity severity, const std::string &id, const std::string &msg, const CWE &cwe, Certainty certainty) { - std::cout << errmsg.toXML() << std::endl; -} - + if (!mErrorLogger) + assert(false); -void Check::reportError(const std::list &callstack, Severity severity, const std::string &id, const std::string &msg, const CWE &cwe, Certainty certainty) -{ // TODO: report debug warning when error is for a disabled severity const ErrorMessage errmsg(callstack, mTokenizer ? &mTokenizer->list : nullptr, severity, id, msg, cwe, certainty); - if (mErrorLogger) - mErrorLogger->reportErr(errmsg); - else - writeToErrorList(errmsg); + mErrorLogger->reportErr(errmsg); } -void Check::reportError(ErrorPath errorPath, Severity severity, const char id[], const std::string &msg, const CWE &cwe, Certainty certainty) +void CheckImpl::reportError(ErrorPath errorPath, Severity severity, const char id[], const std::string &msg, const CWE &cwe, Certainty certainty) { + if (!mErrorLogger) + assert(false); + // TODO: report debug warning when error is for a disabled severity - const ErrorMessage errmsg(std::move(errorPath), mTokenizer ? &mTokenizer->list : nullptr, severity, id, msg, cwe, certainty); - if (mErrorLogger) - mErrorLogger->reportErr(errmsg); - else - writeToErrorList(errmsg); + const ErrorMessage errmsg(errorPath, mTokenizer ? &mTokenizer->list : nullptr, severity, id, msg, cwe, certainty); + mErrorLogger->reportErr(errmsg); } -bool Check::wrongData(const Token *tok, const char *str) +bool CheckImpl::wrongData(const Token *tok, const char *str) { if (mSettings->daca) reportError(tok, Severity::debug, "DacaWrongData", "Wrong data detected by condition " + std::string(str)); return true; } -std::string Check::getMessageId(const ValueFlow::Value &value, const char id[]) -{ - if (value.condition != nullptr) - return id + std::string("Cond"); - if (value.safe) - return std::string("safe") + static_cast(std::toupper(id[0])) + (id + 1); - return id; -} - -ErrorPath Check::getErrorPath(const Token* errtok, const ValueFlow::Value* value, std::string bug) const +ErrorPath CheckImpl::getErrorPath(const Token* errtok, const ValueFlow::Value* value, std::string bug) const { ErrorPath errorPath; if (!value) { @@ -96,9 +72,8 @@ ErrorPath Check::getErrorPath(const Token* errtok, const ValueFlow::Value* value return errorPath; } -void Check::logChecker(const char id[]) +void CheckImpl::logChecker(const char id[]) { if (!mSettings->buildDir.empty() || mSettings->collectLogCheckers()) reportError(nullptr, Severity::internal, "logChecker", id); } - diff --git a/lib/checkimpl.h b/lib/checkimpl.h new file mode 100644 index 00000000000..6139973c8e5 --- /dev/null +++ b/lib/checkimpl.h @@ -0,0 +1,84 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2026 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef checkimplH +#define checkimplH + +#include "errortypes.h" + +#include +#include + +class Settings; +class ErrorLogger; +class Tokenizer; +class Check; +class Token; +namespace ValueFlow { + class Value; +} + +class CheckImpl +{ +public: + /** This constructor is used when running checks. */ + CheckImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : mTokenizer(tokenizer), mSettings(settings), mErrorLogger(errorLogger) {} + + CheckImpl(const CheckImpl &) = delete; + Check& operator=(const CheckImpl &) = delete; + +protected: + const Tokenizer* const mTokenizer{}; + const Settings* const mSettings{}; + ErrorLogger* const mErrorLogger{}; + + /** report an error */ + void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg) { + reportError(tok, severity, id, msg, CWE(0U), Certainty::normal); + } + + /** report an error */ + void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg, const CWE &cwe, Certainty certainty) { + const std::list callstack(1, tok); + reportError(callstack, severity, id, msg, cwe, certainty); + } + + /** report an error */ + void reportError(const std::list &callstack, Severity severity, const std::string &id, const std::string &msg) { + reportError(callstack, severity, id, msg, CWE(0U), Certainty::normal); + } + + /** report an error */ + void reportError(const std::list &callstack, Severity severity, const std::string &id, const std::string &msg, const CWE &cwe, Certainty certainty); + + void reportError(ErrorPath errorPath, Severity severity, const char id[], const std::string &msg, const CWE &cwe, Certainty certainty); + + ErrorPath getErrorPath(const Token* errtok, const ValueFlow::Value* value, std::string bug) const; + + /** + * Use WRONG_DATA in checkers when you check for wrong data. That + * will call this method + */ + bool wrongData(const Token *tok, const char *str); + +public: // TODO: should be protected + void logChecker(const char id[]); +}; + +#endif // checkimplH diff --git a/lib/checkinternal.cpp b/lib/checkinternal.cpp index ed39b4db96a..10af0543cec 100644 --- a/lib/checkinternal.cpp +++ b/lib/checkinternal.cpp @@ -31,7 +31,7 @@ #include #include -void CheckInternal::checkTokenMatchPatterns() +void CheckInternalImpl::checkTokenMatchPatterns() { const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { @@ -82,7 +82,7 @@ void CheckInternal::checkTokenMatchPatterns() } } -void CheckInternal::checkRedundantTokCheck() +void CheckInternalImpl::checkRedundantTokCheck() { for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "&& Token :: simpleMatch|Match|findsimplematch|findmatch (")) { @@ -117,13 +117,13 @@ void CheckInternal::checkRedundantTokCheck() } -void CheckInternal::checkRedundantTokCheckError(const Token* tok) +void CheckInternalImpl::checkRedundantTokCheckError(const Token* tok) { reportError(tok, Severity::style, "redundantTokCheck", "Unnecessary check of \"" + (tok? tok->expressionString(): "") + "\", match-function already checks if it is null."); } -void CheckInternal::checkTokenSimpleMatchPatterns() +void CheckInternalImpl::checkTokenSimpleMatchPatterns() { const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope* scope : symbolDatabase->functionScopes) { @@ -207,7 +207,7 @@ namespace { }; } -void CheckInternal::checkMissingPercentCharacter() +void CheckInternalImpl::checkMissingPercentCharacter() { const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope* scope : symbolDatabase->functionScopes) { @@ -248,7 +248,7 @@ void CheckInternal::checkMissingPercentCharacter() } } -void CheckInternal::checkUnknownPattern() +void CheckInternalImpl::checkUnknownPattern() { const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope* scope : symbolDatabase->functionScopes) { @@ -282,7 +282,7 @@ void CheckInternal::checkUnknownPattern() } } -void CheckInternal::checkRedundantNextPrevious() +void CheckInternalImpl::checkRedundantNextPrevious() { const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope* scope : symbolDatabase->functionScopes) { @@ -305,7 +305,7 @@ void CheckInternal::checkRedundantNextPrevious() } } -void CheckInternal::checkExtraWhitespace() +void CheckInternalImpl::checkExtraWhitespace() { const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope* scope : symbolDatabase->functionScopes) { @@ -331,46 +331,46 @@ void CheckInternal::checkExtraWhitespace() } } -void CheckInternal::simplePatternError(const Token* tok, const std::string& pattern, const std::string &funcname) +void CheckInternalImpl::simplePatternError(const Token* tok, const std::string& pattern, const std::string &funcname) { reportError(tok, Severity::warning, "simplePatternError", "Found simple pattern inside Token::" + funcname + "() call: \"" + pattern + "\"" ); } -void CheckInternal::complexPatternError(const Token* tok, const std::string& pattern, const std::string &funcname) +void CheckInternalImpl::complexPatternError(const Token* tok, const std::string& pattern, const std::string &funcname) { reportError(tok, Severity::error, "complexPatternError", "Found complex pattern inside Token::" + funcname + "() call: \"" + pattern + "\"" ); } -void CheckInternal::missingPercentCharacterError(const Token* tok, const std::string& pattern, const std::string& funcname) +void CheckInternalImpl::missingPercentCharacterError(const Token* tok, const std::string& pattern, const std::string& funcname) { reportError(tok, Severity::error, "missingPercentCharacter", "Missing percent end character in Token::" + funcname + "() pattern: \"" + pattern + "\"" ); } -void CheckInternal::unknownPatternError(const Token* tok, const std::string& pattern) +void CheckInternalImpl::unknownPatternError(const Token* tok, const std::string& pattern) { reportError(tok, Severity::error, "unknownPattern", "Unknown pattern used: \"" + pattern + "\""); } -void CheckInternal::redundantNextPreviousError(const Token* tok, const std::string& func1, const std::string& func2) +void CheckInternalImpl::redundantNextPreviousError(const Token* tok, const std::string& func1, const std::string& func2) { reportError(tok, Severity::style, "redundantNextPrevious", "Call to 'Token::" + func1 + "()' followed by 'Token::" + func2 + "()' can be simplified."); } -void CheckInternal::orInComplexPattern(const Token* tok, const std::string& pattern, const std::string &funcname) +void CheckInternalImpl::orInComplexPattern(const Token* tok, const std::string& pattern, const std::string &funcname) { reportError(tok, Severity::error, "orInComplexPattern", "Token::" + funcname + "() pattern \"" + pattern + "\" contains \"||\" or \"|\". Replace it by \"%oror%\" or \"%or%\"."); } -void CheckInternal::extraWhitespaceError(const Token* tok, const std::string& pattern, const std::string &funcname) +void CheckInternalImpl::extraWhitespaceError(const Token* tok, const std::string& pattern, const std::string &funcname) { reportError(tok, Severity::warning, "extraWhitespaceError", "Found extra whitespace inside Token::" + funcname + "() call: \"" + pattern + "\"" @@ -382,7 +382,7 @@ void CheckInternal::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogg if (!tokenizer.getSettings().checks.isEnabled(Checks::internalCheck)) return; - CheckInternal checkInternal(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckInternalImpl checkInternal(&tokenizer, &tokenizer.getSettings(), errorLogger); checkInternal.checkTokenMatchPatterns(); checkInternal.checkTokenSimpleMatchPatterns(); @@ -395,7 +395,7 @@ void CheckInternal::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogg void CheckInternal::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckInternal c(nullptr, settings, errorLogger); + CheckInternalImpl c(nullptr, settings, errorLogger); c.simplePatternError(nullptr, "class {", "Match"); c.complexPatternError(nullptr, "%type% ( )", "Match"); c.missingPercentCharacterError(nullptr, "%num", "Match"); diff --git a/lib/checkinternal.h b/lib/checkinternal.h index d62d9698b8d..bf1e09c160c 100644 --- a/lib/checkinternal.h +++ b/lib/checkinternal.h @@ -25,6 +25,7 @@ #ifdef CHECK_INTERNAL #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -42,15 +43,26 @@ class Settings; class CPPCHECKLIB CheckInternal : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckInternal() : Check(myName()) {} + CheckInternal() : Check("cppcheck internal API usage") {} private: - /** This constructor is used when running checks. */ - CheckInternal(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + // Don't include these checks on the WIKI where people can read what + // checks there are. These checks are not intended for users. + return ""; + } +}; + +class CheckInternalImpl : public CheckImpl { +public: + /** This constructor is used when running checks. */ + CheckInternalImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** @brief %Check if a simple pattern is used inside Token::Match or Token::findmatch */ void checkTokenMatchPatterns(); @@ -80,18 +92,6 @@ class CPPCHECKLIB CheckInternal : public Check { void orInComplexPattern(const Token *tok, const std::string &pattern, const std::string &funcname); void extraWhitespaceError(const Token *tok, const std::string &pattern, const std::string &funcname); void checkRedundantTokCheckError(const Token *tok); - - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "cppcheck internal API usage"; - } - - std::string classInfo() const override { - // Don't include these checks on the WIKI where people can read what - // checks there are. These checks are not intended for users. - return ""; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 4161b9b224d..33ab6edbdc7 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -58,7 +58,7 @@ static const CWE CWE910(910U); // Use of Expired File Descriptor //--------------------------------------------------------------------------- // std::cout << std::cout; //--------------------------------------------------------------------------- -void CheckIO::checkCoutCerrMisusage() +void CheckIOImpl::checkCoutCerrMisusage() { if (mTokenizer->isC()) return; @@ -80,7 +80,7 @@ void CheckIO::checkCoutCerrMisusage() } } -void CheckIO::coutCerrMisusageError(const Token* tok, const std::string& streamName) +void CheckIOImpl::coutCerrMisusageError(const Token* tok, const std::string& streamName) { reportError(tok, Severity::error, "coutCerrMisusage", "Invalid usage of output stream: '<< std::" + streamName + "'.", CWE398, Certainty::normal); } @@ -119,7 +119,7 @@ namespace { const std::unordered_set whitelist = { "clearerr", "feof", "ferror", "fgetpos", "ftell", "setbuf", "setvbuf", "ungetc", "ungetwc" }; } -void CheckIO::checkFileUsage() +void CheckIOImpl::checkFileUsage() { const bool windows = mSettings->platform.isWindows(); const bool printPortability = mSettings->severity.isEnabled(Severity::portability); @@ -379,37 +379,37 @@ void CheckIO::checkFileUsage() } } -void CheckIO::fflushOnInputStreamError(const Token *tok, const std::string &varname) +void CheckIOImpl::fflushOnInputStreamError(const Token *tok, const std::string &varname) { reportError(tok, Severity::portability, "fflushOnInputStream", "fflush() called on input stream '" + varname + "' may result in undefined behaviour on non-linux systems.", CWE398, Certainty::normal); } -void CheckIO::ioWithoutPositioningError(const Token *tok) +void CheckIOImpl::ioWithoutPositioningError(const Token *tok) { reportError(tok, Severity::error, "IOWithoutPositioning", "Read and write operations without a call to a positioning function (fseek, fsetpos or rewind) or fflush in between result in undefined behaviour.", CWE664, Certainty::normal); } -void CheckIO::readWriteOnlyFileError(const Token *tok) +void CheckIOImpl::readWriteOnlyFileError(const Token *tok) { reportError(tok, Severity::error, "readWriteOnlyFile", "Read operation on a file that was opened only for writing.", CWE664, Certainty::normal); } -void CheckIO::writeReadOnlyFileError(const Token *tok) +void CheckIOImpl::writeReadOnlyFileError(const Token *tok) { reportError(tok, Severity::error, "writeReadOnlyFile", "Write operation on a file that was opened only for reading.", CWE664, Certainty::normal); } -void CheckIO::useClosedFileError(const Token *tok) +void CheckIOImpl::useClosedFileError(const Token *tok) { reportError(tok, Severity::error, "useClosedFile", "Used file that is not opened.", CWE910, Certainty::normal); } -void CheckIO::fcloseInLoopConditionError(const Token *tok, const std::string &varname) +void CheckIOImpl::fcloseInLoopConditionError(const Token *tok, const std::string &varname) { reportError(tok, Severity::warning, "fcloseInLoopCondition", @@ -418,13 +418,13 @@ void CheckIO::fcloseInLoopConditionError(const Token *tok, const std::string &va CWE910, Certainty::normal); } -void CheckIO::seekOnAppendedFileError(const Token *tok) +void CheckIOImpl::seekOnAppendedFileError(const Token *tok) { reportError(tok, Severity::warning, "seekOnAppendedFile", "Repositioning operation performed on a file opened in append mode has no effect.", CWE398, Certainty::normal); } -void CheckIO::incompatibleFileOpenError(const Token *tok, const std::string &filename) +void CheckIOImpl::incompatibleFileOpenError(const Token *tok, const std::string &filename) { reportError(tok, Severity::warning, "incompatibleFileOpen", "The file '" + filename + "' is opened for read and write access at the same time on different streams", CWE664, Certainty::normal); @@ -434,7 +434,7 @@ void CheckIO::incompatibleFileOpenError(const Token *tok, const std::string &fil //--------------------------------------------------------------------------- // scanf without field width limits can crash with huge input data //--------------------------------------------------------------------------- -void CheckIO::invalidScanf() +void CheckIOImpl::invalidScanf() { if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->isPremiumEnabled("invalidscanf")) return; @@ -481,7 +481,7 @@ void CheckIO::invalidScanf() } } -void CheckIO::invalidScanfError(const Token *tok) +void CheckIOImpl::invalidScanfError(const Token *tok) { const std::string fname = (tok ? tok->str() : std::string("scanf")); reportError(tok, Severity::warning, @@ -553,7 +553,7 @@ static inline bool typesMatch(const std::string& iToTest, const std::string& iTy return (iToTest == iTypename) || (iToTest == iOptionalPrefix + iTypename); } -void CheckIO::checkWrongPrintfScanfArguments() +void CheckIOImpl::checkWrongPrintfScanfArguments() { const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); const bool isWindows = mSettings->platform.isWindows(); @@ -625,7 +625,7 @@ void CheckIO::checkWrongPrintfScanfArguments() } } -void CheckIO::checkFormatString(const Token * const tok, +void CheckIOImpl::checkFormatString(const Token * const tok, const Token * const formatStringTok, const Token * argListTok, const bool scan, @@ -1368,7 +1368,7 @@ void CheckIO::checkFormatString(const Token * const tok, // We currently only support string literals, variables, and functions. /// @todo add non-string literals, and generic expressions -CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings &settings, bool _isCPP) +CheckIOImpl::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings &settings, bool _isCPP) : isCPP(_isCPP) { if (!arg) @@ -1582,7 +1582,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings &settings, } } -CheckIO::ArgumentInfo::~ArgumentInfo() +CheckIOImpl::ArgumentInfo::~ArgumentInfo() { if (tempToken) { while (tempToken->next()) @@ -1597,7 +1597,7 @@ namespace { const std::set stl_string = { "string", "u16string", "u32string", "wstring" }; } -bool CheckIO::ArgumentInfo::isStdVectorOrString() +bool CheckIOImpl::ArgumentInfo::isStdVectorOrString() { if (!isCPP) return false; @@ -1659,7 +1659,7 @@ static const std::set stl_container = { "unordered_map", "unordered_multimap", "unordered_multiset", "unordered_set", "vector" }; -bool CheckIO::ArgumentInfo::isStdContainer(const Token *tok) +bool CheckIOImpl::ArgumentInfo::isStdContainer(const Token *tok) { if (!isCPP) return false; @@ -1691,7 +1691,7 @@ bool CheckIO::ArgumentInfo::isStdContainer(const Token *tok) return false; } -bool CheckIO::ArgumentInfo::isArrayOrPointer() const +bool CheckIOImpl::ArgumentInfo::isArrayOrPointer() const { if (address) return true; @@ -1704,7 +1704,7 @@ bool CheckIO::ArgumentInfo::isArrayOrPointer() const return tok && tok->strAt(1) == "*"; } -bool CheckIO::ArgumentInfo::isComplexType() const +bool CheckIOImpl::ArgumentInfo::isComplexType() const { if (variableInfo->type()) return true; @@ -1716,7 +1716,7 @@ bool CheckIO::ArgumentInfo::isComplexType() const return ((variableInfo->isStlStringType() || (varTypeTok->strAt(1) == "<" && varTypeTok->linkAt(1) && varTypeTok->linkAt(1)->strAt(1) != "::")) && !variableInfo->isArrayOrPointer()); } -bool CheckIO::ArgumentInfo::isKnownType() const +bool CheckIOImpl::ArgumentInfo::isKnownType() const { if (variableInfo) return (typeToken->isStandardType() || typeToken->next()->isStandardType() || isComplexType()); @@ -1726,12 +1726,12 @@ bool CheckIO::ArgumentInfo::isKnownType() const return typeToken->isStandardType() || Token::Match(typeToken, "std :: string|wstring"); } -bool CheckIO::ArgumentInfo::isLibraryType(const Settings &settings) const +bool CheckIOImpl::ArgumentInfo::isLibraryType(const Settings &settings) const { return typeToken && typeToken->isStandardType() && settings.library.podtype(typeToken->str()); } -void CheckIO::wrongPrintfScanfArgumentsError(const Token* tok, +void CheckIOImpl::wrongPrintfScanfArgumentsError(const Token* tok, const std::string &functionName, nonneg int numFormat, nonneg int numFunction) @@ -1753,7 +1753,7 @@ void CheckIO::wrongPrintfScanfArgumentsError(const Token* tok, reportError(tok, severity, "wrongPrintfScanfArgNum", errmsg.str(), CWE685, Certainty::normal); } -void CheckIO::wrongPrintfScanfPosixParameterPositionError(const Token* tok, const std::string& functionName, +void CheckIOImpl::wrongPrintfScanfPosixParameterPositionError(const Token* tok, const std::string& functionName, nonneg int index, nonneg int numFunction) { if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->isPremiumEnabled("wrongPrintfScanfParameterPositionError")) @@ -1768,7 +1768,7 @@ void CheckIO::wrongPrintfScanfPosixParameterPositionError(const Token* tok, cons reportError(tok, Severity::warning, "wrongPrintfScanfParameterPositionError", errmsg.str(), CWE685, Certainty::normal); } -void CheckIO::invalidScanfArgTypeError_s(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo) +void CheckIOImpl::invalidScanfArgTypeError_s(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo) { const Severity severity = getSeverity(argInfo); if (!mSettings->severity.isEnabled(severity)) @@ -1784,7 +1784,7 @@ void CheckIO::invalidScanfArgTypeError_s(const Token* tok, nonneg int numFormat, errmsg << "."; reportError(tok, severity, "invalidScanfArgType_s", errmsg.str(), CWE686, Certainty::normal); } -void CheckIO::invalidScanfArgTypeError_int(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo, bool isUnsigned) +void CheckIOImpl::invalidScanfArgTypeError_int(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo, bool isUnsigned) { const Severity severity = getSeverity(argInfo); if (!mSettings->severity.isEnabled(severity)) @@ -1829,7 +1829,7 @@ void CheckIO::invalidScanfArgTypeError_int(const Token* tok, nonneg int numForma errmsg << "."; reportError(tok, severity, "invalidScanfArgType_int", errmsg.str(), CWE686, Certainty::normal); } -void CheckIO::invalidScanfArgTypeError_float(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo) +void CheckIOImpl::invalidScanfArgTypeError_float(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo) { const Severity severity = getSeverity(argInfo); if (!mSettings->severity.isEnabled(severity)) @@ -1848,7 +1848,7 @@ void CheckIO::invalidScanfArgTypeError_float(const Token* tok, nonneg int numFor reportError(tok, severity, "invalidScanfArgType_float", errmsg.str(), CWE686, Certainty::normal); } -void CheckIO::invalidPrintfArgTypeError_s(const Token* tok, nonneg int numFormat, const ArgumentInfo* argInfo) +void CheckIOImpl::invalidPrintfArgTypeError_s(const Token* tok, nonneg int numFormat, const ArgumentInfo* argInfo) { const Severity severity = getSeverity(argInfo); if (!mSettings->severity.isEnabled(severity)) @@ -1859,7 +1859,7 @@ void CheckIO::invalidPrintfArgTypeError_s(const Token* tok, nonneg int numFormat errmsg << "."; reportError(tok, severity, "invalidPrintfArgType_s", errmsg.str(), CWE686, Certainty::normal); } -void CheckIO::invalidPrintfArgTypeError_n(const Token* tok, nonneg int numFormat, const ArgumentInfo* argInfo) +void CheckIOImpl::invalidPrintfArgTypeError_n(const Token* tok, nonneg int numFormat, const ArgumentInfo* argInfo) { const Severity severity = getSeverity(argInfo); if (!mSettings->severity.isEnabled(severity)) @@ -1870,7 +1870,7 @@ void CheckIO::invalidPrintfArgTypeError_n(const Token* tok, nonneg int numFormat errmsg << "."; reportError(tok, severity, "invalidPrintfArgType_n", errmsg.str(), CWE686, Certainty::normal); } -void CheckIO::invalidPrintfArgTypeError_p(const Token* tok, nonneg int numFormat, const ArgumentInfo* argInfo) +void CheckIOImpl::invalidPrintfArgTypeError_p(const Token* tok, nonneg int numFormat, const ArgumentInfo* argInfo) { const Severity severity = getSeverity(argInfo); if (!mSettings->severity.isEnabled(severity)) @@ -1920,7 +1920,7 @@ static void printfFormatType(std::ostream& os, const std::string& specifier, boo os << "\'"; } -void CheckIO::invalidPrintfArgTypeError_uint(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo) +void CheckIOImpl::invalidPrintfArgTypeError_uint(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo) { const Severity severity = getSeverity(argInfo); if (!mSettings->severity.isEnabled(severity)) @@ -1934,7 +1934,7 @@ void CheckIO::invalidPrintfArgTypeError_uint(const Token* tok, nonneg int numFor reportError(tok, severity, "invalidPrintfArgType_uint", errmsg.str(), CWE686, Certainty::normal); } -void CheckIO::invalidPrintfArgTypeError_sint(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo) +void CheckIOImpl::invalidPrintfArgTypeError_sint(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo) { const Severity severity = getSeverity(argInfo); if (!mSettings->severity.isEnabled(severity)) @@ -1947,7 +1947,7 @@ void CheckIO::invalidPrintfArgTypeError_sint(const Token* tok, nonneg int numFor errmsg << "."; reportError(tok, severity, "invalidPrintfArgType_sint", errmsg.str(), CWE686, Certainty::normal); } -void CheckIO::invalidPrintfArgTypeError_float(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo) +void CheckIOImpl::invalidPrintfArgTypeError_float(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo) { const Severity severity = getSeverity(argInfo); if (!mSettings->severity.isEnabled(severity)) @@ -1962,12 +1962,12 @@ void CheckIO::invalidPrintfArgTypeError_float(const Token* tok, nonneg int numFo reportError(tok, severity, "invalidPrintfArgType_float", errmsg.str(), CWE686, Certainty::normal); } -Severity CheckIO::getSeverity(const CheckIO::ArgumentInfo *argInfo) +Severity CheckIOImpl::getSeverity(const ArgumentInfo *argInfo) { return (argInfo && argInfo->typeToken && !argInfo->typeToken->originalName().empty()) ? Severity::portability : Severity::warning; } -void CheckIO::argumentType(std::ostream& os, const ArgumentInfo * argInfo) +void CheckIOImpl::argumentType(std::ostream& os, const ArgumentInfo * argInfo) { if (argInfo) { os << "\'"; @@ -2017,7 +2017,7 @@ void CheckIO::argumentType(std::ostream& os, const ArgumentInfo * argInfo) os << "Unknown"; } -void CheckIO::invalidLengthModifierError(const Token* tok, nonneg int numFormat, const std::string& modifier) +void CheckIOImpl::invalidLengthModifierError(const Token* tok, nonneg int numFormat, const std::string& modifier) { if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->isPremiumEnabled("invalidLengthModifierError")) return; @@ -2026,7 +2026,7 @@ void CheckIO::invalidLengthModifierError(const Token* tok, nonneg int numFormat, reportError(tok, Severity::warning, "invalidLengthModifierError", errmsg.str(), CWE704, Certainty::normal); } -void CheckIO::invalidScanfFormatWidthError(const Token* tok, nonneg int numFormat, int width, const Variable *var, const std::string& specifier) +void CheckIOImpl::invalidScanfFormatWidthError(const Token* tok, nonneg int numFormat, int width, const Variable *var, const std::string& specifier) { MathLib::bigint arrlen = 0; std::string varname; @@ -2052,7 +2052,7 @@ void CheckIO::invalidScanfFormatWidthError(const Token* tok, nonneg int numForma void CheckIO::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckIO checkIO(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckIOImpl checkIO(&tokenizer, &tokenizer.getSettings(), errorLogger); checkIO.checkWrongPrintfScanfArguments(); checkIO.checkCoutCerrMisusage(); @@ -2062,7 +2062,7 @@ void CheckIO::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) void CheckIO::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckIO c(nullptr, settings, errorLogger); + CheckIOImpl c(nullptr, settings, errorLogger); c.coutCerrMisusageError(nullptr, "cout"); c.fflushOnInputStreamError(nullptr, "stdin"); c.ioWithoutPositioningError(nullptr); diff --git a/lib/checkio.h b/lib/checkio.h index b3c86da3577..929d987a630 100644 --- a/lib/checkio.h +++ b/lib/checkio.h @@ -22,6 +22,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -45,16 +46,38 @@ class CPPCHECKLIB CheckIO : public Check { public: /** @brief This constructor is used when registering CheckIO */ - CheckIO() : Check(myName()) {} + CheckIO() : Check("IO using format string") {} private: - /** @brief This constructor is used when running checks. */ - CheckIO(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - /** @brief Run checks on the normal token list */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + return "Check format string input/output operations.\n" + "- Bad usage of the function 'sprintf' (overlapping data)\n" + "- Missing or wrong width specifiers in 'scanf' format string\n" + "- Use a file that has been closed\n" + "- File input/output without positioning results in undefined behaviour\n" + "- Read to a file that has only been opened for writing (or vice versa)\n" + "- Repositioning operation on a file opened in append mode\n" + "- The same file can't be open for read and write at the same time on different streams\n" + "- Using fflush() on an input stream\n" + "- Invalid usage of output stream. For example: 'std::cout << std::cout;'\n" + "- Wrong number of arguments given to 'printf' or 'scanf;'\n"; + } + + // for testing + static void checkWrongPrintfScanfArguments(Tokenizer* tokenizer, const Settings *settings, ErrorLogger *errorLogger); +}; + +class CheckIOImpl : public CheckImpl { +public: + /** @brief This constructor is used when running checks. */ + CheckIOImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** @brief %Check for missusage of std::cout */ void checkCoutCerrMisusage(); @@ -128,26 +151,6 @@ class CPPCHECKLIB CheckIO : public Check { void invalidScanfFormatWidthError(const Token* tok, nonneg int numFormat, int width, const Variable *var, const std::string& specifier); static void argumentType(std::ostream & os, const ArgumentInfo * argInfo); static Severity getSeverity(const ArgumentInfo *argInfo); - - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "IO using format string"; - } - - std::string classInfo() const override { - return "Check format string input/output operations.\n" - "- Bad usage of the function 'sprintf' (overlapping data)\n" - "- Missing or wrong width specifiers in 'scanf' format string\n" - "- Use a file that has been closed\n" - "- File input/output without positioning results in undefined behaviour\n" - "- Read to a file that has only been opened for writing (or vice versa)\n" - "- Repositioning operation on a file opened in append mode\n" - "- The same file can't be open for read and write at the same time on different streams\n" - "- Using fflush() on an input stream\n" - "- Invalid usage of output stream. For example: 'std::cout << std::cout;'\n" - "- Wrong number of arguments given to 'printf' or 'scanf;'\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 1c9a7283161..9bdcf27cfae 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -107,35 +107,35 @@ void VarInfo::possibleUsageAll(const std::pair& functionUsa } -void CheckLeakAutoVar::leakError(const Token *tok, const std::string &varname, int type) const +void CheckLeakAutoVarImpl::leakError(const Token *tok, const std::string &varname, int type) const { - const CheckMemoryLeak checkmemleak(mTokenizer, mErrorLogger, mSettings); + const CheckMemoryLeakImpl checkmemleak(mTokenizer, mSettings, mErrorLogger); if (Library::isresource(type)) checkmemleak.resourceLeakError(tok, varname); else checkmemleak.memleakError(tok, varname); } -void CheckLeakAutoVar::mismatchError(const Token *deallocTok, const Token *allocTok, const std::string &varname) const +void CheckLeakAutoVarImpl::mismatchError(const Token *deallocTok, const Token *allocTok, const std::string &varname) const { - const CheckMemoryLeak c(mTokenizer, mErrorLogger, mSettings); + const CheckMemoryLeakImpl c(mTokenizer, mSettings, mErrorLogger); const std::list callstack = { allocTok, deallocTok }; c.mismatchAllocDealloc(callstack, varname); } -void CheckLeakAutoVar::deallocUseError(const Token *tok, const std::string &varname) const +void CheckLeakAutoVarImpl::deallocUseError(const Token *tok, const std::string &varname) const { - const CheckMemoryLeak c(mTokenizer, mErrorLogger, mSettings); + const CheckMemoryLeakImpl c(mTokenizer, mSettings, mErrorLogger); c.deallocuseError(tok, varname); } -void CheckLeakAutoVar::deallocReturnError(const Token *tok, const Token *deallocTok, const std::string &varname) +void CheckLeakAutoVarImpl::deallocReturnError(const Token *tok, const Token *deallocTok, const std::string &varname) { const std::list locations = { deallocTok, tok }; reportError(locations, Severity::error, "deallocret", "$symbol:" + varname + "\nReturning/dereferencing '$symbol' after it is deallocated / released", CWE672, Certainty::normal); } -void CheckLeakAutoVar::configurationInfo(const Token* tok, const std::pair& functionUsage) +void CheckLeakAutoVarImpl::configurationInfo(const Token* tok, const std::pair& functionUsage) { if (mSettings->checkLibrary && functionUsage.second == VarInfo::USED && (!functionUsage.first || !functionUsage.first->function() || !functionUsage.first->function()->hasBody())) { @@ -149,7 +149,7 @@ void CheckLeakAutoVar::configurationInfo(const Token* tok, const std::pair locations = { prevFreeTok, tok }; @@ -160,7 +160,7 @@ void CheckLeakAutoVar::doubleFreeError(const Token *tok, const Token *prevFreeTo } -void CheckLeakAutoVar::check() +void CheckLeakAutoVarImpl::check() { if (mSettings->clang) return; @@ -303,7 +303,7 @@ static std::vector getComparisonTokens(const Token* tok) return result; } -bool CheckLeakAutoVar::checkScope(const Token * const startToken, +bool CheckLeakAutoVarImpl::checkScope(const Token * const startToken, VarInfo &varInfo, std::set notzero, nonneg int recursiveCount) @@ -887,7 +887,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, } -const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const tok, VarInfo &varInfo, bool inFuncCall) +const Token * CheckLeakAutoVarImpl::checkTokenInsideExpression(const Token * const tok, VarInfo &varInfo, bool inFuncCall) { // Deallocation and then dereferencing pointer.. if (tok->varId() > 0) { @@ -956,7 +956,7 @@ const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const t } -void CheckLeakAutoVar::changeAllocStatusIfRealloc(std::map &alloctype, const Token *fTok, const Token *retTok) const +void CheckLeakAutoVarImpl::changeAllocStatusIfRealloc(std::map &alloctype, const Token *fTok, const Token *retTok) const { const Library::AllocFunc* f = mSettings->library.getReallocFuncInfo(fTok); if (f && f->arg == -1 && f->reallocArg > 0 && f->reallocArg <= numberOfArguments(fTok)) { @@ -977,7 +977,7 @@ void CheckLeakAutoVar::changeAllocStatusIfRealloc(std::map &alloctype = varInfo.alloctype; const auto var = alloctype.find(arg->varId()); @@ -1014,7 +1014,7 @@ void CheckLeakAutoVar::changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocI } } -void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af) +void CheckLeakAutoVarImpl::functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af) { // Ignore function call? const bool isLeakIgnore = mSettings->library.isLeakIgnore(mSettings->library.getFunctionName(tokName)); @@ -1153,7 +1153,7 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin } -void CheckLeakAutoVar::leakIfAllocated(const Token *vartok, +void CheckLeakAutoVarImpl::leakIfAllocated(const Token *vartok, const VarInfo &varInfo) { const std::map &alloctype = varInfo.alloctype; @@ -1176,7 +1176,7 @@ static bool isSafeCast(const ValueType* vt, const Settings& settings) return sizeOf == 0 || sizeOf >= settings.platform.sizeof_pointer; } -void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndOfScope) +void CheckLeakAutoVarImpl::ret(const Token *tok, VarInfo &varInfo, const bool isEndOfScope) { const std::map &alloctype = varInfo.alloctype; const auto& possibleUsage = varInfo.possibleUsage; @@ -1280,13 +1280,13 @@ void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndO void CheckLeakAutoVar::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckLeakAutoVar checkLeakAutoVar(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckLeakAutoVarImpl checkLeakAutoVar(&tokenizer, &tokenizer.getSettings(), errorLogger); checkLeakAutoVar.check(); } void CheckLeakAutoVar::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckLeakAutoVar c(nullptr, settings, errorLogger); + CheckLeakAutoVarImpl c(nullptr, settings, errorLogger); c.deallocReturnError(nullptr, nullptr, "p"); c.configurationInfo(nullptr, { nullptr, VarInfo::USED }); // user configuration is needed to complete analysis c.doubleFreeError(nullptr, nullptr, "varname", 0); diff --git a/lib/checkleakautovar.h b/lib/checkleakautovar.h index d7d8d390b3d..9089d418de4 100644 --- a/lib/checkleakautovar.h +++ b/lib/checkleakautovar.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include "library.h" @@ -107,15 +108,24 @@ class CPPCHECKLIB VarInfo { class CPPCHECKLIB CheckLeakAutoVar : public Check { public: /** This constructor is used when registering the CheckLeakAutoVar */ - CheckLeakAutoVar() : Check(myName()) {} + CheckLeakAutoVar() : Check("Leaks (auto variables)") {} private: - /** This constructor is used when running checks. */ - CheckLeakAutoVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + return "Detect when a auto variable is allocated but not deallocated or deallocated twice.\n"; + } +}; + +class CheckLeakAutoVarImpl : public CheckImpl { +public: + /** This constructor is used when running checks. */ + CheckLeakAutoVarImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** check for leaks in all scopes */ void check(); @@ -157,16 +167,6 @@ class CPPCHECKLIB CheckLeakAutoVar : public Check { /** message: user configuration is needed to complete analysis */ void configurationInfo(const Token* tok, const std::pair& functionUsage); - - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "Leaks (auto variables)"; - } - - std::string classInfo() const override { - return "Detect when a auto variable is allocated but not deallocated or deallocated twice.\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index b2f97693cd6..e90ed552426 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -31,6 +31,7 @@ #include "utils.h" #include +#include #include #include #include @@ -45,7 +46,8 @@ static const CWE CWE772(772U); // Missing Release of Resource after Effective L //--------------------------------------------------------------------------- -CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, nonneg int varid, std::list *callstack) const + +CheckMemoryLeakImpl::AllocType CheckMemoryLeakImpl::getAllocationType(const Token *tok2, nonneg int varid, std::list *callstack) const { // What we may have... // * var = (char *)malloc(10); @@ -93,7 +95,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, return New; } - if (mSettings_->hasLib("posix")) { + if (mSettings->hasLib("posix")) { if (Token::Match(tok2, "open|openat|creat|mkstemp|mkostemp|socket (")) { // simple sanity check of function parameters.. // TODO: Make such check for all these functions @@ -112,11 +114,11 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, } // Does tok2 point on a Library allocation function? - const int alloctype = mSettings_->library.getAllocId(tok2, -1); + const int alloctype = mSettings->library.getAllocId(tok2, -1); if (alloctype > 0) { - if (alloctype == mSettings_->library.deallocId("free")) + if (alloctype == mSettings->library.deallocId("free")) return Malloc; - if (alloctype == mSettings_->library.deallocId("fclose")) + if (alloctype == mSettings->library.deallocId("fclose")) return File; return Library::ismemory(alloctype) ? OtherMem : OtherRes; } @@ -143,7 +145,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, } -CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok2, nonneg int varid) const +CheckMemoryLeakImpl::AllocType CheckMemoryLeakImpl::getReallocationType(const Token *tok2, nonneg int varid) const { // What we may have... // * var = (char *)realloc(..; @@ -157,7 +159,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok if (!Token::Match(tok2, "%name% (")) return No; - const Library::AllocFunc *f = mSettings_->library.getReallocFuncInfo(tok2); + const Library::AllocFunc *f = mSettings->library.getReallocFuncInfo(tok2); if (!(f && f->reallocArg > 0 && f->reallocArg <= numberOfArguments(tok2))) return No; const auto args = getArguments(tok2); @@ -171,11 +173,11 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok if (varid > 0 && !Token::Match(arg, "%varid% [,)]", varid)) return No; - const int realloctype = mSettings_->library.getReallocId(tok2, -1); + const int realloctype = mSettings->library.getReallocId(tok2, -1); if (realloctype > 0) { - if (realloctype == mSettings_->library.deallocId("free")) + if (realloctype == mSettings->library.deallocId("free")) return Malloc; - if (realloctype == mSettings_->library.deallocId("fclose")) + if (realloctype == mSettings->library.deallocId("fclose")) return File; return Library::ismemory(realloctype) ? OtherMem : OtherRes; } @@ -183,7 +185,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok } -CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok, nonneg int varid) const +CheckMemoryLeakImpl::AllocType CheckMemoryLeakImpl::getDeallocationType(const Token *tok, nonneg int varid) const { if (tok->isCpp() && tok->str() == "delete" && tok->astOperand1()) { const Token* vartok = tok->astOperand1(); @@ -214,7 +216,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok if (tok->str() == "realloc" && Token::simpleMatch(vartok->next(), ", 0 )")) return Malloc; - if (mSettings_->hasLib("posix")) { + if (mSettings->hasLib("posix")) { if (tok->str() == "close") return Fd; if (tok->str() == "pclose") @@ -222,11 +224,11 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok } // Does tok point on a Library deallocation function? - const int dealloctype = mSettings_->library.getDeallocId(tok, argNr); + const int dealloctype = mSettings->library.getDeallocId(tok, argNr); if (dealloctype > 0) { - if (dealloctype == mSettings_->library.deallocId("free")) + if (dealloctype == mSettings->library.deallocId("free")) return Malloc; - if (dealloctype == mSettings_->library.deallocId("fclose")) + if (dealloctype == mSettings->library.deallocId("fclose")) return File; return Library::ismemory(dealloctype) ? OtherMem : OtherRes; } @@ -238,10 +240,10 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok return No; } -bool CheckMemoryLeak::isReopenStandardStream(const Token *tok) const +bool CheckMemoryLeakImpl::isReopenStandardStream(const Token *tok) const { if (getReallocationType(tok, 0) == File) { - const Library::AllocFunc *f = mSettings_->library.getReallocFuncInfo(tok); + const Library::AllocFunc *f = mSettings->library.getReallocFuncInfo(tok); if (f && f->reallocArg > 0 && f->reallocArg <= numberOfArguments(tok)) { const Token* arg = getArguments(tok).at(f->reallocArg - 1); if (Token::Match(arg, "stdin|stdout|stderr")) @@ -251,9 +253,9 @@ bool CheckMemoryLeak::isReopenStandardStream(const Token *tok) const return false; } -bool CheckMemoryLeak::isOpenDevNull(const Token *tok) const +bool CheckMemoryLeakImpl::isOpenDevNull(const Token *tok) const { - if (mSettings_->hasLib("posix") && tok->str() == "open" && numberOfArguments(tok) == 2) { + if (mSettings->hasLib("posix") && tok->str() == "open" && numberOfArguments(tok) == 2) { const Token* arg = getArguments(tok).at(0); if (Token::simpleMatch(arg, "\"/dev/null\"")) return true; @@ -261,24 +263,18 @@ bool CheckMemoryLeak::isOpenDevNull(const Token *tok) const return false; } -//-------------------------------------------------------------------------- - - -//-------------------------------------------------------------------------- - -void CheckMemoryLeak::memoryLeak(const Token *tok, const std::string &varname, AllocType alloctype) const +void CheckMemoryLeakImpl::memoryLeak(const Token *tok, const std::string &varname, AllocType alloctype) const { - if (alloctype == CheckMemoryLeak::File || - alloctype == CheckMemoryLeak::Pipe || - alloctype == CheckMemoryLeak::Fd || - alloctype == CheckMemoryLeak::OtherRes) + if (alloctype == File || + alloctype == Pipe || + alloctype == Fd || + alloctype == OtherRes) resourceLeakError(tok, varname); else memleakError(tok, varname); } -//--------------------------------------------------------------------------- -void CheckMemoryLeak::reportErr(const Token *tok, Severity severity, const std::string &id, const std::string &msg, const CWE &cwe) const +void CheckMemoryLeakImpl::reportErr(const Token *tok, Severity severity, const std::string &id, const std::string &msg, const CWE &cwe) const { std::list callstack; @@ -288,26 +284,26 @@ void CheckMemoryLeak::reportErr(const Token *tok, Severity severity, const std:: reportErr(callstack, severity, id, msg, cwe); } -void CheckMemoryLeak::reportErr(const std::list &callstack, Severity severity, const std::string &id, const std::string &msg, const CWE &cwe) const +void CheckMemoryLeakImpl::reportErr(const std::list &callstack, Severity severity, const std::string &id, const std::string &msg, const CWE &cwe) const { - const ErrorMessage errmsg(callstack, mTokenizer_ ? &mTokenizer_->list : nullptr, severity, id, msg, cwe, Certainty::normal); - if (mErrorLogger_) - mErrorLogger_->reportErr(errmsg); - else - Check::writeToErrorList(errmsg); + if (!mErrorLogger) + assert(false); + + const ErrorMessage errmsg(callstack, mTokenizer ? &mTokenizer->list : nullptr, severity, id, msg, cwe, Certainty::normal); + mErrorLogger->reportErr(errmsg); } -void CheckMemoryLeak::memleakError(const Token *tok, const std::string &varname) const +void CheckMemoryLeakImpl::memleakError(const Token *tok, const std::string &varname) const { reportErr(tok, Severity::error, "memleak", "$symbol:" + varname + "\nMemory leak: $symbol", CWE(401U)); } -void CheckMemoryLeak::memleakUponReallocFailureError(const Token *tok, const std::string &reallocfunction, const std::string &varname) const +void CheckMemoryLeakImpl::memleakUponReallocFailureError(const Token *tok, const std::string &reallocfunction, const std::string &varname) const { reportErr(tok, Severity::error, "memleakOnRealloc", "$symbol:" + varname + "\nCommon " + reallocfunction + " mistake: \'$symbol\' nulled but not freed upon failure", CWE(401U)); } -void CheckMemoryLeak::resourceLeakError(const Token *tok, const std::string &varname) const +void CheckMemoryLeakImpl::resourceLeakError(const Token *tok, const std::string &varname) const { std::string errmsg("Resource leak"); if (!varname.empty()) @@ -315,17 +311,17 @@ void CheckMemoryLeak::resourceLeakError(const Token *tok, const std::string &var reportErr(tok, Severity::error, "resourceLeak", errmsg, CWE(775U)); } -void CheckMemoryLeak::deallocuseError(const Token *tok, const std::string &varname) const +void CheckMemoryLeakImpl::deallocuseError(const Token *tok, const std::string &varname) const { reportErr(tok, Severity::error, "deallocuse", "$symbol:" + varname + "\nDereferencing '$symbol' after it is deallocated / released", CWE(416U)); } -void CheckMemoryLeak::mismatchAllocDealloc(const std::list &callstack, const std::string &varname) const +void CheckMemoryLeakImpl::mismatchAllocDealloc(const std::list &callstack, const std::string &varname) const { reportErr(callstack, Severity::error, "mismatchAllocDealloc", "$symbol:" + varname + "\nMismatching allocation and deallocation: $symbol", CWE(762U)); } -CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Function* func, std::list *callstack) const +CheckMemoryLeakImpl::AllocType CheckMemoryLeakImpl::functionReturnType(const Function* func, std::list *callstack) const { if (!func || !func->hasBody() || !func->functionScope) return No; @@ -423,7 +419,7 @@ static bool ifvar(const Token *tok, nonneg int varid, const std::string &comp, c // a = malloc(10); a = realloc(a, 100); //--------------------------------------------------------------------------- -void CheckMemoryLeakInFunction::checkReallocUsage() +void CheckMemoryLeakInFunctionImpl::checkReallocUsage() { logChecker("CheckMemoryLeakInFunction::checkReallocUsage"); @@ -494,17 +490,15 @@ void CheckMemoryLeakInFunction::checkReallocUsage() } } } -//--------------------------------------------------------------------------- -void CheckMemoryLeakInFunction::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) -{ - CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &tokenizer.getSettings(), errorLogger); +void CheckMemoryLeakInFunction::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { + CheckMemoryLeakInFunctionImpl checkMemoryLeak(&tokenizer, &tokenizer.getSettings(), errorLogger); checkMemoryLeak.checkReallocUsage(); } -void CheckMemoryLeakInFunction::getErrorMessages(ErrorLogger *e, const Settings *settings) const -{ - CheckMemoryLeakInFunction c(nullptr, settings, e); +/** Report all possible errors (for the --errorlist) */ +void CheckMemoryLeakInFunction::getErrorMessages(ErrorLogger *e, const Settings *settings) const { + CheckMemoryLeakInFunctionImpl c(nullptr, settings, e); c.memleakError(nullptr, "varname"); c.resourceLeakError(nullptr, "varname"); c.deallocuseError(nullptr, "varname"); @@ -517,8 +511,7 @@ void CheckMemoryLeakInFunction::getErrorMessages(ErrorLogger *e, const Settings // Checks for memory leaks in classes.. //--------------------------------------------------------------------------- - -void CheckMemoryLeakInClass::check() +void CheckMemoryLeakInClassImpl::check() { logChecker("CheckMemoryLeakInClass::check"); @@ -543,15 +536,15 @@ void CheckMemoryLeakInClass::check() } -void CheckMemoryLeakInClass::variable(const Scope *scope, const Token *tokVarname) +void CheckMemoryLeakInClassImpl::variable(const Scope *scope, const Token *tokVarname) { const std::string& varname = tokVarname->str(); const int varid = tokVarname->varId(); const std::string& classname = scope->className; // Check if member variable has been allocated and deallocated.. - CheckMemoryLeak::AllocType memberAlloc = CheckMemoryLeak::No; - CheckMemoryLeak::AllocType memberDealloc = CheckMemoryLeak::No; + AllocType memberAlloc = AllocType::No; + AllocType memberDealloc = AllocType::No; bool allocInConstructor = false; bool deallocInDestructor = false; @@ -563,7 +556,7 @@ void CheckMemoryLeakInClass::variable(const Scope *scope, const Token *tokVarnam if (!func.hasBody()) { if (destructor && !func.isDefault()) { // implementation for destructor is not seen and not defaulted => assume it deallocates all variables properly deallocInDestructor = true; - memberDealloc = CheckMemoryLeak::Many; + memberDealloc = AllocType::Many; } continue; } @@ -596,14 +589,14 @@ void CheckMemoryLeakInClass::variable(const Scope *scope, const Token *tokVarnam allocTok = tok->astParent()->astParent()->astOperand2(); AllocType alloc = getAllocationType(allocTok, 0); - if (alloc != CheckMemoryLeak::No) { + if (alloc != AllocType::No) { if (constructor) allocInConstructor = true; - if (memberAlloc != No && memberAlloc != alloc) - alloc = CheckMemoryLeak::Many; + if (memberAlloc != AllocType::No && memberAlloc != alloc) + alloc = AllocType::Many; - if (alloc != CheckMemoryLeak::Many && memberDealloc != CheckMemoryLeak::No && memberDealloc != CheckMemoryLeak::Many && memberDealloc != alloc) { + if (alloc != AllocType::Many && memberDealloc != AllocType::No && memberDealloc != AllocType::Many && memberDealloc != alloc) { mismatchAllocDealloc({tok}, classname + "::" + varname); } @@ -619,18 +612,18 @@ void CheckMemoryLeakInClass::variable(const Scope *scope, const Token *tokVarnam // some usage in the destructor => assume it's related // to deallocation if (destructor && tok->str() == varname) - dealloc = CheckMemoryLeak::Many; - if (dealloc != CheckMemoryLeak::No) { + dealloc = AllocType::Many; + if (dealloc != AllocType::No) { if (destructor) deallocInDestructor = true; - if (dealloc != CheckMemoryLeak::Many && memberAlloc != CheckMemoryLeak::No && memberAlloc != Many && memberAlloc != dealloc) { + if (dealloc != AllocType::Many && memberAlloc != AllocType::No && memberAlloc != Many && memberAlloc != dealloc) { mismatchAllocDealloc({tok}, classname + "::" + varname); } // several types of allocation/deallocation? - if (memberDealloc != CheckMemoryLeak::No && memberDealloc != dealloc) - dealloc = CheckMemoryLeak::Many; + if (memberDealloc != AllocType::No && memberDealloc != dealloc) + dealloc = AllocType::Many; memberDealloc = dealloc; } @@ -645,12 +638,12 @@ void CheckMemoryLeakInClass::variable(const Scope *scope, const Token *tokVarnam if (allocInConstructor && !deallocInDestructor) { unsafeClassError(tokVarname, classname, classname + "::" + varname /*, memberAlloc*/); - } else if (memberAlloc != CheckMemoryLeak::No && memberDealloc == CheckMemoryLeak::No) { + } else if (memberAlloc != AllocType::No && memberDealloc == AllocType::No) { unsafeClassError(tokVarname, classname, classname + "::" + varname /*, memberAlloc*/); } } -void CheckMemoryLeakInClass::unsafeClassError(const Token *tok, const std::string &classname, const std::string &varname) +void CheckMemoryLeakInClassImpl::unsafeClassError(const Token *tok, const std::string &classname, const std::string &varname) { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("unsafeClassCanLeak")) return; @@ -663,7 +656,7 @@ void CheckMemoryLeakInClass::unsafeClassError(const Token *tok, const std::strin } -void CheckMemoryLeakInClass::checkPublicFunctions(const Scope *scope, const Token *classtok) +void CheckMemoryLeakInClassImpl::checkPublicFunctions(const Scope *scope, const Token *classtok) { // Check that public functions deallocate the pointers that they allocate. // There is no checking how these functions are used and therefore it @@ -680,20 +673,20 @@ void CheckMemoryLeakInClass::checkPublicFunctions(const Scope *scope, const Toke func.access == AccessControl::Public && func.hasBody()) { const Token *tok2 = func.functionScope->bodyStart->next(); if (Token::Match(tok2, "%varid% =", varid)) { - const CheckMemoryLeak::AllocType alloc = getAllocationType(tok2->tokAt(2), varid); - if (alloc != CheckMemoryLeak::No) + const AllocType alloc = getAllocationType(tok2->tokAt(2), varid); + if (alloc != AllocType::No) publicAllocationError(tok2, tok2->str()); } else if (Token::Match(tok2, "%type% :: %varid% =", varid) && tok2->str() == scope->className) { - const CheckMemoryLeak::AllocType alloc = getAllocationType(tok2->tokAt(4), varid); - if (alloc != CheckMemoryLeak::No) + const AllocType alloc = getAllocationType(tok2->tokAt(4), varid); + if (alloc != AllocType::No) publicAllocationError(tok2, tok2->strAt(2)); } } } } -void CheckMemoryLeakInClass::publicAllocationError(const Token *tok, const std::string &varname) +void CheckMemoryLeakInClassImpl::publicAllocationError(const Token *tok, const std::string &varname) { reportError(tok, Severity::warning, "publicAllocationError", "$symbol:" + varname + "\nPossible leak in public function. The pointer '$symbol' is not deallocated before it is allocated.", CWE398, Certainty::normal); } @@ -703,19 +696,18 @@ void CheckMemoryLeakInClass::runChecks(const Tokenizer &tokenizer, ErrorLogger * if (!tokenizer.isCPP()) return; - CheckMemoryLeakInClass checkMemoryLeak(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckMemoryLeakInClassImpl checkMemoryLeak(&tokenizer, &tokenizer.getSettings(), errorLogger); checkMemoryLeak.check(); } void CheckMemoryLeakInClass::getErrorMessages(ErrorLogger *e, const Settings *settings) const { - CheckMemoryLeakInClass c(nullptr, settings, e); + CheckMemoryLeakInClassImpl c(nullptr, settings, e); c.publicAllocationError(nullptr, "varname"); c.unsafeClassError(nullptr, "class", "class::varname"); } - -void CheckMemoryLeakStructMember::check() +void CheckMemoryLeakStructMemberImpl::check() { if (mSettings->clang) return; @@ -734,7 +726,7 @@ void CheckMemoryLeakStructMember::check() } } -bool CheckMemoryLeakStructMember::isMalloc(const Variable *variable) const +bool CheckMemoryLeakStructMemberImpl::isMalloc(const Variable *variable) const { if (!variable) return false; @@ -756,7 +748,7 @@ bool CheckMemoryLeakStructMember::isMalloc(const Variable *variable) const return alloc; } -void CheckMemoryLeakStructMember::checkStructVariable(const Variable* const variable) const +void CheckMemoryLeakStructMemberImpl::checkStructVariable(const Variable* const variable) const { if (!variable) return; @@ -976,15 +968,11 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable* const vari void CheckMemoryLeakStructMember::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckMemoryLeakStructMember checkMemoryLeak(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckMemoryLeakStructMemberImpl checkMemoryLeak(&tokenizer, &tokenizer.getSettings(), errorLogger); checkMemoryLeak.check(); } -void CheckMemoryLeakStructMember::getErrorMessages(ErrorLogger * /*errorLogger*/, const Settings * /*settings*/) const -{} - - -void CheckMemoryLeakNoVar::check() +void CheckMemoryLeakNoVarImpl::check() { logChecker("CheckMemoryLeakNoVar::check"); @@ -1010,7 +998,7 @@ void CheckMemoryLeakNoVar::check() // Checks if an input argument to a function is the return value of an allocation function // like malloc(), and the function does not release it. //--------------------------------------------------------------------------- -void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope) +void CheckMemoryLeakNoVarImpl::checkForUnreleasedInputArgument(const Scope *scope) { // parse the executable scope until tok is reached... for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { @@ -1083,7 +1071,7 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope) //--------------------------------------------------------------------------- // Checks if a call to an allocation function like malloc() is made and its return value is not assigned. //--------------------------------------------------------------------------- -void CheckMemoryLeakNoVar::checkForUnusedReturnValue(const Scope *scope) +void CheckMemoryLeakNoVarImpl::checkForUnusedReturnValue(const Scope *scope) { for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { const bool isNew = tok->isCpp() && tok->str() == "new"; @@ -1150,7 +1138,7 @@ void CheckMemoryLeakNoVar::checkForUnusedReturnValue(const Scope *scope) // f(shared_ptr(new int(42)), g()); // } //--------------------------------------------------------------------------- -void CheckMemoryLeakNoVar::checkForUnsafeArgAlloc(const Scope *scope) +void CheckMemoryLeakNoVarImpl::checkForUnsafeArgAlloc(const Scope *scope) { // This test only applies to C++ source if (!mTokenizer->isCPP()) @@ -1200,17 +1188,17 @@ void CheckMemoryLeakNoVar::checkForUnsafeArgAlloc(const Scope *scope) } } -void CheckMemoryLeakNoVar::functionCallLeak(const Token *loc, const std::string &alloc, const std::string &functionCall) +void CheckMemoryLeakNoVarImpl::functionCallLeak(const Token *loc, const std::string &alloc, const std::string &functionCall) { reportError(loc, Severity::error, "leakNoVarFunctionCall", "Allocation with " + alloc + ", " + functionCall + " doesn't release it.", CWE772, Certainty::normal); } -void CheckMemoryLeakNoVar::returnValueNotUsedError(const Token *tok, const std::string &alloc) +void CheckMemoryLeakNoVarImpl::returnValueNotUsedError(const Token *tok, const std::string &alloc) { reportError(tok, Severity::error, "leakReturnValNotUsed", "$symbol:" + alloc + "\nReturn value of allocation function '$symbol' is not stored.", CWE771, Certainty::normal); } -void CheckMemoryLeakNoVar::unsafeArgAllocError(const Token *tok, const std::string &funcName, const std::string &ptrType, const std::string& objType) +void CheckMemoryLeakNoVarImpl::unsafeArgAllocError(const Token *tok, const std::string &funcName, const std::string &ptrType, const std::string& objType) { const std::string factoryFunc = ptrType == "shared_ptr" ? "make_shared" : "make_unique"; reportError(tok, Severity::warning, "leakUnsafeArgAlloc", @@ -1222,13 +1210,13 @@ void CheckMemoryLeakNoVar::unsafeArgAllocError(const Token *tok, const std::stri void CheckMemoryLeakNoVar::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckMemoryLeakNoVar checkMemoryLeak(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckMemoryLeakNoVarImpl checkMemoryLeak(&tokenizer, &tokenizer.getSettings(), errorLogger); checkMemoryLeak.check(); } void CheckMemoryLeakNoVar::getErrorMessages(ErrorLogger *e, const Settings *settings) const { - CheckMemoryLeakNoVar c(nullptr, settings, e); + CheckMemoryLeakNoVarImpl c(nullptr, settings, e); c.functionCallLeak(nullptr, "funcName", "funcName"); c.returnValueNotUsedError(nullptr, "funcName"); c.unsafeArgAllocError(nullptr, "funcName", "shared_ptr", "int"); diff --git a/lib/checkmemoryleak.h b/lib/checkmemoryleak.h index c9fb2274252..0f37c86ef44 100644 --- a/lib/checkmemoryleak.h +++ b/lib/checkmemoryleak.h @@ -33,6 +33,7 @@ */ #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -52,18 +53,103 @@ enum class Severity : std::uint8_t; /// @addtogroup Core /// @{ -/** @brief Base class for memory leaks checking */ -class CPPCHECKLIB CheckMemoryLeak { + +/** + * @brief %CheckMemoryLeakInFunction detects when a function variable is allocated but not deallocated properly. + * + * The checking is done by looking at each function variable separately. By repeating these 4 steps over and over: + * -# locate a function variable + * -# create a simple token list that describes the usage of the function variable. + * -# simplify the token list. + * -# finally, check if the simplified token list contain any leaks. + */ + +class CPPCHECKLIB CheckMemoryLeakInFunction : public Check { + friend class TestMemleakInFunction; + +public: + /** @brief This constructor is used when registering this class */ + CheckMemoryLeakInFunction() : Check("Memory leaks (function variables)") {} + +private: + void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + + /** Report all possible errors (for the --errorlist) */ + void getErrorMessages(ErrorLogger *e, const Settings *settings) const override; + + /** + * Get class information (--doc) + * @return Wiki formatted information about this class + */ + std::string classInfo() const override { + return "Is there any allocated memory when a function goes out of scope\n"; + } +}; + + +/** + * @brief %Check class variables, variables that are allocated in the constructor should be deallocated in the destructor + */ + +class CPPCHECKLIB CheckMemoryLeakInClass : public Check { + friend class TestMemleakInClass; + +public: + CheckMemoryLeakInClass() : Check("Memory leaks (class variables)") {} + +private: + void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + + void getErrorMessages(ErrorLogger *e, const Settings *settings) const override; + + std::string classInfo() const override { + return "If the constructor allocate memory then the destructor must deallocate it.\n"; + } +}; + + + +/** @brief detect simple memory leaks for struct members */ + +class CPPCHECKLIB CheckMemoryLeakStructMember : public Check { + friend class TestMemleakStructMember; + +public: + CheckMemoryLeakStructMember() : Check("Memory leaks (struct members)") {} + +private: + void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + + void getErrorMessages(ErrorLogger * /*errorLogger*/, const Settings * /*settings*/) const override {} + + std::string classInfo() const override { + return "Don't forget to deallocate struct members\n"; + } +}; + + + +/** @brief detect simple memory leaks (address not taken) */ + +class CPPCHECKLIB CheckMemoryLeakNoVar : public Check { + friend class TestMemleakNoVar; + +public: + CheckMemoryLeakNoVar() : Check("Memory leaks (address not taken)") {} + private: - /** For access to the tokens */ - const Tokenizer * const mTokenizer_; + void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; - /** ErrorLogger used to report errors */ - ErrorLogger * const mErrorLogger_; + void getErrorMessages(ErrorLogger *e, const Settings *settings) const override; - /** Enabled standards */ - const Settings * const mSettings_; + std::string classInfo() const override { + return "Not taking the address to allocated memory\n"; + } +}; +/** @brief Base class for memory leaks checking */ +class CheckMemoryLeakImpl : public CheckImpl { +private: /** * Report error. Similar with the function Check::reportError * @param tok the token where the error occurs @@ -85,12 +171,12 @@ class CPPCHECKLIB CheckMemoryLeak { void reportErr(const std::list &callstack, Severity severity, const std::string &id, const std::string &msg, const CWE &cwe) const; public: - CheckMemoryLeak() = delete; - CheckMemoryLeak(const CheckMemoryLeak &) = delete; - CheckMemoryLeak& operator=(const CheckMemoryLeak &) = delete; + CheckMemoryLeakImpl() = delete; + CheckMemoryLeakImpl(const CheckMemoryLeakImpl &) = delete; + CheckMemoryLeakImpl& operator=(const CheckMemoryLeakImpl &) = delete; - CheckMemoryLeak(const Tokenizer *t, ErrorLogger *e, const Settings *s) - : mTokenizer_(t), mErrorLogger_(e), mSettings_(s) {} + CheckMemoryLeakImpl(const Tokenizer *t, const Settings *s, ErrorLogger *e) + : CheckImpl(t, s, e) {} /** @brief What type of allocation are used.. the "Many" means that several types of allocation and deallocation are used */ enum AllocType : std::uint8_t { No, Malloc, New, NewArray, File, Fd, Pipe, OtherMem, OtherRes, Many }; @@ -165,43 +251,16 @@ class CPPCHECKLIB CheckMemoryLeak { * -# finally, check if the simplified token list contain any leaks. */ -class CPPCHECKLIB CheckMemoryLeakInFunction : public Check, public CheckMemoryLeak { - friend class TestMemleakInFunction; - +class CPPCHECKLIB CheckMemoryLeakInFunctionImpl : public CheckMemoryLeakImpl { public: - /** @brief This constructor is used when registering this class */ - CheckMemoryLeakInFunction() : Check(myName()), CheckMemoryLeak(nullptr, nullptr, nullptr) {} - -private: /** @brief This constructor is used when running checks */ - CheckMemoryLeakInFunction(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger, settings) {} - - void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + CheckMemoryLeakInFunctionImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckMemoryLeakImpl(tokenizer, settings, errorLogger) {} /** * Checking for a memory leak caused by improper realloc usage. */ void checkReallocUsage(); - - /** Report all possible errors (for the --errorlist) */ - void getErrorMessages(ErrorLogger *e, const Settings *settings) const override; - - /** - * Get name of class (--doc) - * @return name of class - */ - static std::string myName() { - return "Memory leaks (function variables)"; - } - - /** - * Get class information (--doc) - * @return Wiki formatted information about this class - */ - std::string classInfo() const override { - return "Is there any allocated memory when a function goes out of scope\n"; - } }; @@ -210,17 +269,10 @@ class CPPCHECKLIB CheckMemoryLeakInFunction : public Check, public CheckMemoryLe * @brief %Check class variables, variables that are allocated in the constructor should be deallocated in the destructor */ -class CPPCHECKLIB CheckMemoryLeakInClass : public Check, private CheckMemoryLeak { - friend class TestMemleakInClass; - +class CPPCHECKLIB CheckMemoryLeakInClassImpl : private CheckMemoryLeakImpl { public: - CheckMemoryLeakInClass() : Check(myName()), CheckMemoryLeak(nullptr, nullptr, nullptr) {} - -private: - CheckMemoryLeakInClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger, settings) {} - - void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + CheckMemoryLeakInClassImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckMemoryLeakImpl(tokenizer, settings, errorLogger) {} void check(); @@ -231,33 +283,17 @@ class CPPCHECKLIB CheckMemoryLeakInClass : public Check, private CheckMemoryLeak void publicAllocationError(const Token *tok, const std::string &varname); void unsafeClassError(const Token *tok, const std::string &classname, const std::string &varname); - - void getErrorMessages(ErrorLogger *e, const Settings *settings) const override; - - static std::string myName() { - return "Memory leaks (class variables)"; - } - - std::string classInfo() const override { - return "If the constructor allocate memory then the destructor must deallocate it.\n"; - } }; /** @brief detect simple memory leaks for struct members */ -class CPPCHECKLIB CheckMemoryLeakStructMember : public Check, private CheckMemoryLeak { - friend class TestMemleakStructMember; - +class CPPCHECKLIB CheckMemoryLeakStructMemberImpl : private CheckMemoryLeakImpl { public: - CheckMemoryLeakStructMember() : Check(myName()), CheckMemoryLeak(nullptr, nullptr, nullptr) {} -private: - CheckMemoryLeakStructMember(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger, settings) {} - - void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + CheckMemoryLeakStructMemberImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckMemoryLeakImpl(tokenizer, settings, errorLogger) {} void check(); @@ -265,33 +301,16 @@ class CPPCHECKLIB CheckMemoryLeakStructMember : public Check, private CheckMemor bool isMalloc(const Variable *variable) const; void checkStructVariable(const Variable* variable) const; - - void getErrorMessages(ErrorLogger* /*errorLogger*/, const Settings* /*settings*/) const override; - - static std::string myName() { - return "Memory leaks (struct members)"; - } - - std::string classInfo() const override { - return "Don't forget to deallocate struct members\n"; - } }; /** @brief detect simple memory leaks (address not taken) */ -class CPPCHECKLIB CheckMemoryLeakNoVar : public Check, private CheckMemoryLeak { - friend class TestMemleakNoVar; - +class CPPCHECKLIB CheckMemoryLeakNoVarImpl : private CheckMemoryLeakImpl { public: - CheckMemoryLeakNoVar() : Check(myName()), CheckMemoryLeak(nullptr, nullptr, nullptr) {} - -private: - CheckMemoryLeakNoVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger, settings) {} - - void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + CheckMemoryLeakNoVarImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckMemoryLeakImpl(tokenizer, settings, errorLogger) {} void check(); @@ -317,16 +336,6 @@ class CPPCHECKLIB CheckMemoryLeakNoVar : public Check, private CheckMemoryLeak { void functionCallLeak(const Token *loc, const std::string &alloc, const std::string &functionCall); void returnValueNotUsedError(const Token* tok, const std::string &alloc); void unsafeArgAllocError(const Token *tok, const std::string &funcName, const std::string &ptrType, const std::string &objType); - - void getErrorMessages(ErrorLogger *e, const Settings *settings) const override; - - static std::string myName() { - return "Memory leaks (address not taken)"; - } - - std::string classInfo() const override { - return "Not taking the address to allocated memory\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 5bd602488b4..21360e62783 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -54,7 +54,7 @@ static bool checkNullpointerFunctionCallPlausibility(const Function* func, unsig return !func || (func->argCount() >= arg && func->getArgumentVar(arg - 1) && func->getArgumentVar(arg - 1)->isPointer()); } -std::list CheckNullPointer::parseFunctionCall(const Token &tok, const Library &library, bool checkNullArg) +std::list CheckNullPointerImpl::parseFunctionCall(const Token &tok, const Library &library, bool checkNullArg) { if (Token::Match(&tok, "%name% ( )") || !tok.tokAt(2)) return {}; @@ -128,20 +128,6 @@ namespace { }; } -/** - * Is there a pointer dereference? Everything that should result in - * a nullpointer dereference error message will result in a true - * return value. If it's unknown if the pointer is dereferenced false - * is returned. - * @param tok token for the pointer - * @param unknown it is not known if there is a pointer dereference (could be reported as a debug message) - * @return true => there is a dereference - */ -bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown) const -{ - return isPointerDeRef(tok, unknown, *mSettings); -} - bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Settings &settings, bool checkNullArg) { unknown = false; @@ -155,7 +141,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Set ftok = ftok->previous(); } if (ftok && ftok->previous()) { - const std::list varlist = parseFunctionCall(*ftok->previous(), settings.library, checkNullArg); + const std::list varlist = CheckNullPointerImpl::parseFunctionCall(*ftok->previous(), settings.library, checkNullArg); if (std::find(varlist.cbegin(), varlist.cend(), tok) != varlist.cend()) { return true; } @@ -273,7 +259,7 @@ static bool isNullablePointer(const Token* tok) return false; } -void CheckNullPointer::nullPointerByDeRefAndCheck() +void CheckNullPointerImpl::nullPointerByDeRefAndCheck() { const bool printInconclusive = (mSettings->certainty.isEnabled(Certainty::inconclusive)); @@ -307,7 +293,7 @@ void CheckNullPointer::nullPointerByDeRefAndCheck() // Pointer dereference. bool unknown = false; - if (!isPointerDeRef(tok, unknown)) { + if (!CheckNullPointer::isPointerDeRef(tok, unknown, *mSettings)) { if (unknown) nullPointerError(tok, tok->expressionString(), value, true); continue; @@ -318,7 +304,7 @@ void CheckNullPointer::nullPointerByDeRefAndCheck() } } -void CheckNullPointer::nullPointer() +void CheckNullPointerImpl::nullPointer() { logChecker("CheckNullPointer::nullPointer"); nullPointerByDeRefAndCheck(); @@ -332,7 +318,7 @@ namespace { } /** Dereferencing null constant (simplified token list) */ -void CheckNullPointer::nullConstantDereference() +void CheckNullPointerImpl::nullConstantDereference() { logChecker("CheckNullPointer::nullConstantDereference"); @@ -425,14 +411,14 @@ void CheckNullPointer::nullConstantDereference() } } -void CheckNullPointer::nullPointerError(const Token *tok) +void CheckNullPointerImpl::nullPointerError(const Token *tok) { ValueFlow::Value v(0); v.setKnown(); nullPointerError(tok, "", &v, false); } -void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive) +void CheckNullPointerImpl::nullPointerError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive) { const std::string errmsgcond("$symbol:" + varname + '\n' + ValueFlow::eitherTheConditionIsRedundant(value ? value->condition : nullptr) + " or there is possible null pointer dereference: $symbol."); const std::string errmsgdefarg("$symbol:" + varname + "\nPossible null pointer dereference if the default parameter value is used: $symbol"); @@ -486,7 +472,7 @@ void CheckNullPointer::nullPointerError(const Token *tok, const std::string &var } } -void CheckNullPointer::arithmetic() +void CheckNullPointerImpl::arithmetic() { logChecker("CheckNullPointer::arithmetic"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -533,7 +519,7 @@ static std::string arithmeticTypeString(const Token *tok) return "arithmetic"; } -void CheckNullPointer::pointerArithmeticError(const Token* tok, const ValueFlow::Value *value, bool inconclusive) +void CheckNullPointerImpl::pointerArithmeticError(const Token* tok, const ValueFlow::Value *value, bool inconclusive) { // cppcheck-suppress shadowFunction - TODO: fix this std::string arithmetic = arithmeticTypeString(tok); @@ -563,7 +549,7 @@ void CheckNullPointer::pointerArithmeticError(const Token* tok, const ValueFlow: inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckNullPointer::redundantConditionWarning(const Token* tok, const ValueFlow::Value *value, const Token *condition, bool inconclusive) +void CheckNullPointerImpl::redundantConditionWarning(const Token* tok, const ValueFlow::Value *value, const Token *condition, bool inconclusive) { // cppcheck-suppress shadowFunction - TODO: fix this std::string arithmetic = arithmeticTypeString(tok); @@ -615,7 +601,7 @@ namespace Check::FileInfo *CheckNullPointer::getFileInfo(const Tokenizer &tokenizer, const Settings &settings, const std::string& /*currentConfig*/) const { - const std::list &unsafeUsage = CTU::getUnsafeUsage(tokenizer, settings, isUnsafeUsage); + const std::list &unsafeUsage = CTU::getUnsafeUsage(tokenizer, settings, ::isUnsafeUsage); if (unsafeUsage.empty()) return nullptr; @@ -639,9 +625,9 @@ bool CheckNullPointer::analyseWholeProgram(const CTU::FileInfo &ctu, const std:: { (void)settings; - CheckNullPointer dummy(nullptr, &settings, &errorLogger); + CheckNullPointerImpl dummy(nullptr, &settings, &errorLogger); dummy. - logChecker("CheckNullPointer::analyseWholeProgram"); // unusedfunctions + logChecker("CheckNullPointer::analyseWholeProgram"); if (fileInfo.empty()) return false; @@ -701,7 +687,7 @@ bool CheckNullPointer::analyseWholeProgram(const CTU::FileInfo &ctu, const std:: void CheckNullPointer::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckNullPointer checkNullPointer(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckNullPointerImpl checkNullPointer(&tokenizer, &tokenizer.getSettings(), errorLogger); checkNullPointer.nullPointer(); checkNullPointer.arithmetic(); checkNullPointer.nullConstantDereference(); @@ -709,7 +695,7 @@ void CheckNullPointer::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorL void CheckNullPointer::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckNullPointer c(nullptr, settings, errorLogger); + CheckNullPointerImpl c(nullptr, settings, errorLogger); c.nullPointerError(nullptr, "pointer", nullptr, false); c.pointerArithmeticError(nullptr, nullptr, false); // TODO: nullPointerArithmeticOutOfMemory diff --git a/lib/checknullpointer.h b/lib/checknullpointer.h index c02feae303e..a53546927fe 100644 --- a/lib/checknullpointer.h +++ b/lib/checknullpointer.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -51,7 +52,7 @@ class CPPCHECKLIB CheckNullPointer : public Check { public: /** @brief This constructor is used when registering the CheckNullPointer */ - CheckNullPointer() : Check(myName()) {} + CheckNullPointer() : Check("Null pointer") {} /** * Is there a pointer dereference? Everything that should result in @@ -62,38 +63,14 @@ class CPPCHECKLIB CheckNullPointer : public Check { * @param unknown it is not known if there is a pointer dereference (could be reported as a debug message) * @return true => there is a dereference */ - bool isPointerDeRef(const Token *tok, bool &unknown) const; - static bool isPointerDeRef(const Token *tok, bool &unknown, const Settings &settings, bool checkNullArg = true); private: - /** - * @brief parse a function call and extract information about variable usage - * @param tok first token - * @param library --library files data - * @param checkNullArg perform isnullargbad check for each argument? - * @return list of variables that the function reads / writes. - */ - static std::list parseFunctionCall(const Token &tok, const Library &library, bool checkNullArg = true); - - /** @brief This constructor is used when running checks. */ - CheckNullPointer(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; - /** @brief possible null pointer dereference */ - void nullPointer(); - - /** @brief dereferencing null constant (after Tokenizer::simplifyKnownVariables) */ - void nullConstantDereference(); - - void nullPointerError(const Token *tok); - void nullPointerError(const Token *tok, const std::string &varname, const ValueFlow::Value* value, bool inconclusive); - /** @brief Parse current TU and extract file info */ - Check::FileInfo *getFileInfo(const Tokenizer &tokenizer, const Settings &settings, const std::string& /*currentConfig*/) const override; + Check::FileInfo *getFileInfo(const Tokenizer &tokenizer, const Settings &settings, const std::string& currentConfig) const override; Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const override; @@ -103,17 +80,37 @@ class CPPCHECKLIB CheckNullPointer : public Check { /** Get error messages. Used by --errorlist */ void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - /** Name of check */ - static std::string myName() { - return "Null pointer"; - } - /** class info in WIKI format. Used by --doc */ std::string classInfo() const override { return "Null pointers\n" "- null pointer dereferencing\n" "- undefined null pointer arithmetic\n"; } +}; + +class CheckNullPointerImpl : public CheckImpl { +public: + /** @brief This constructor is used when running checks. */ + CheckNullPointerImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + + /** + * @brief parse a function call and extract information about variable usage + * @param tok first token + * @param library --library files data + * @param checkNullArg perform isnullargbad check for each argument? + * @return list of variables that the function reads / writes. + */ + static std::list parseFunctionCall(const Token &tok, const Library &library, bool checkNullArg = true); + + /** @brief possible null pointer dereference */ + void nullPointer(); + + /** @brief dereferencing null constant (after Tokenizer::simplifyKnownVariables) */ + void nullConstantDereference(); + + void nullPointerError(const Token *tok); + void nullPointerError(const Token *tok, const std::string &varname, const ValueFlow::Value* value, bool inconclusive); /** * @brief Does one part of the check for nullPointer(). diff --git a/lib/checkother.cpp b/lib/checkother.cpp index b454c4410cf..14c12ec27a7 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -80,12 +80,12 @@ static const CWE CWE783(783U); // Operator Precedence Logic Error // - http://www.cplusplus.com/reference/cstdio/getchar/ // - http://www.cplusplus.com/reference/cstdio/ungetc/ ... //---------------------------------------------------------------------------------- -void CheckOther::checkCastIntToCharAndBack() +void CheckOtherImpl::checkCastIntToCharAndBack() { if (!mSettings->severity.isEnabled(Severity::warning)) return; - logChecker("CheckOther::checkCastIntToCharAndBack"); // warning + logChecker("CheckOtherImpl::checkCastIntToCharAndBack"); // warning const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -130,7 +130,7 @@ void CheckOther::checkCastIntToCharAndBack() } } -void CheckOther::checkCastIntToCharAndBackError(const Token *tok, const std::string &strFunctionName) +void CheckOtherImpl::checkCastIntToCharAndBackError(const Token *tok, const std::string &strFunctionName) { reportError( tok, @@ -150,12 +150,12 @@ void CheckOther::checkCastIntToCharAndBackError(const Token *tok, const std::str //--------------------------------------------------------------------------- // Clarify calculation precedence for ternary operators. //--------------------------------------------------------------------------- -void CheckOther::clarifyCalculation() +void CheckOtherImpl::clarifyCalculation() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("clarifyCalculation")) return; - logChecker("CheckOther::clarifyCalculation"); // style + logChecker("CheckOtherImpl::clarifyCalculation"); // style const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -199,7 +199,7 @@ void CheckOther::clarifyCalculation() } } -void CheckOther::clarifyCalculationError(const Token *tok, const std::string &op) +void CheckOtherImpl::clarifyCalculationError(const Token *tok, const std::string &op) { // suspicious calculation const std::string calc("'a" + op + "b?c:d'"); @@ -221,12 +221,12 @@ void CheckOther::clarifyCalculationError(const Token *tok, const std::string &op //--------------------------------------------------------------------------- // Clarify (meaningless) statements like *foo++; with parentheses. //--------------------------------------------------------------------------- -void CheckOther::clarifyStatement() +void CheckOtherImpl::clarifyStatement() { if (!mSettings->severity.isEnabled(Severity::warning)) return; - logChecker("CheckOther::clarifyStatement"); // warning + logChecker("CheckOtherImpl::clarifyStatement"); // warning const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -247,7 +247,7 @@ void CheckOther::clarifyStatement() } } -void CheckOther::clarifyStatementError(const Token *tok) +void CheckOtherImpl::clarifyStatementError(const Token *tok) { reportError(tok, Severity::warning, "clarifyStatement", "In expression like '*A++' the result of '*' is unused. Did you intend to write '(*A)++;'?\n" "A statement like '*A++;' might not do what you intended. Postfix 'operator++' is executed before 'operator*'. " @@ -257,14 +257,14 @@ void CheckOther::clarifyStatementError(const Token *tok) //--------------------------------------------------------------------------- // Check for suspicious occurrences of 'if(); {}'. //--------------------------------------------------------------------------- -void CheckOther::checkSuspiciousSemicolon() +void CheckOtherImpl::checkSuspiciousSemicolon() { if (!mSettings->certainty.isEnabled(Certainty::inconclusive) || !mSettings->severity.isEnabled(Severity::warning)) return; const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); - logChecker("CheckOther::checkSuspiciousSemicolon"); // warning,inconclusive + logChecker("CheckOtherImpl::checkSuspiciousSemicolon"); // warning,inconclusive // Look for "if(); {}", "for(); {}" or "while(); {}" for (const Scope &scope : symbolDatabase->scopeList) { @@ -281,7 +281,7 @@ void CheckOther::checkSuspiciousSemicolon() } } -void CheckOther::suspiciousSemicolonError(const Token* tok) +void CheckOtherImpl::suspiciousSemicolonError(const Token* tok) { reportError(tok, Severity::warning, "suspiciousSemicolon", "Suspicious use of ; at the end of '" + (tok ? tok->str() : std::string()) + "' statement.", CWE398, Certainty::normal); @@ -329,7 +329,7 @@ static bool isDangerousTypeConversion(const Token* const tok) //--------------------------------------------------------------------------- // For C++ code, warn if C-style casts are used on pointer types //--------------------------------------------------------------------------- -void CheckOther::warningOldStylePointerCast() +void CheckOtherImpl::warningOldStylePointerCast() { // Only valid on C++ code if (!mTokenizer->isCPP()) @@ -338,7 +338,7 @@ void CheckOther::warningOldStylePointerCast() if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("cstyleCast")) return; - logChecker("CheckOther::warningOldStylePointerCast"); // style,c++ + logChecker("CheckOtherImpl::warningOldStylePointerCast"); // style,c++ const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -394,7 +394,7 @@ void CheckOther::warningOldStylePointerCast() } } -void CheckOther::cstyleCastError(const Token *tok, bool isPtr) +void CheckOtherImpl::cstyleCastError(const Token *tok, bool isPtr) { const std::string type = isPtr ? "pointer" : "reference"; reportError(tok, Severity::style, "cstyleCast", @@ -405,7 +405,7 @@ void CheckOther::cstyleCastError(const Token *tok, bool isPtr) "which kind of cast is expected.", CWE398, Certainty::normal); } -void CheckOther::warningDangerousTypeCast() +void CheckOtherImpl::warningDangerousTypeCast() { // Only valid on C++ code if (!mTokenizer->isCPP()) @@ -433,7 +433,7 @@ void CheckOther::warningDangerousTypeCast() } } -void CheckOther::dangerousTypeCastError(const Token *tok, bool isPtr) +void CheckOtherImpl::dangerousTypeCastError(const Token *tok, bool isPtr) { //const std::string type = isPtr ? "pointer" : "reference"; (void)isPtr; @@ -442,7 +442,7 @@ void CheckOther::dangerousTypeCastError(const Token *tok, bool isPtr) CWE398, Certainty::normal); } -void CheckOther::warningIntToPointerCast() +void CheckOtherImpl::warningIntToPointerCast() { if (!mSettings->severity.isEnabled(Severity::portability) && !mSettings->isPremiumEnabled("cstyleCast")) return; @@ -471,14 +471,14 @@ void CheckOther::warningIntToPointerCast() } } -void CheckOther::intToPointerCastError(const Token *tok, const std::string& format) +void CheckOtherImpl::intToPointerCastError(const Token *tok, const std::string& format) { reportError(tok, Severity::portability, "intToPointerCast", "Casting non-zero " + format + " integer literal to pointer.", CWE398, Certainty::normal); } -void CheckOther::suspiciousFloatingPointCast() +void CheckOtherImpl::suspiciousFloatingPointCast() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("suspiciousFloatingPointCast")) return; @@ -528,7 +528,7 @@ void CheckOther::suspiciousFloatingPointCast() } } -void CheckOther::suspiciousFloatingPointCastError(const Token* tok) +void CheckOtherImpl::suspiciousFloatingPointCastError(const Token* tok) { reportError(tok, Severity::style, "suspiciousFloatingPointCast", "Floating-point cast causes loss of precision.\n" @@ -539,12 +539,12 @@ void CheckOther::suspiciousFloatingPointCastError(const Token* tok) // float* f; double* d = (double*)f; <-- Pointer cast to a type with an incompatible binary data representation //--------------------------------------------------------------------------- -void CheckOther::invalidPointerCast() +void CheckOtherImpl::invalidPointerCast() { if (!mSettings->severity.isEnabled(Severity::portability)) return; - logChecker("CheckOther::invalidPointerCast"); // portability + logChecker("CheckOtherImpl::invalidPointerCast"); // portability const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -579,7 +579,7 @@ void CheckOther::invalidPointerCast() } -void CheckOther::invalidPointerCastError(const Token* tok, const std::string& from, const std::string& to, bool inconclusive, bool toIsInt) +void CheckOtherImpl::invalidPointerCastError(const Token* tok, const std::string& from, const std::string& to, bool inconclusive, bool toIsInt) { if (toIsInt) { // If we cast something to int*, this can be useful to play with its binary data representation reportError(tok, Severity::portability, "invalidPointerCast", "Casting from " + from + " to " + to + " is not portable due to different binary data representations on different platforms.", CWE704, inconclusive ? Certainty::inconclusive : Certainty::normal); @@ -592,14 +592,14 @@ void CheckOther::invalidPointerCastError(const Token* tok, const std::string& fr // Detect redundant assignments: x = 0; x = 4; //--------------------------------------------------------------------------- -void CheckOther::checkRedundantAssignment() +void CheckOtherImpl::checkRedundantAssignment() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("redundantAssignment") && !mSettings->isPremiumEnabled("redundantAssignInSwitch")) return; - logChecker("CheckOther::checkRedundantAssignment"); // style + logChecker("CheckOtherImpl::checkRedundantAssignment"); // style const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope : symbolDatabase->functionScopes) { @@ -729,7 +729,7 @@ void CheckOther::checkRedundantAssignment() } } -void CheckOther::redundantCopyError(const Token *tok1, const Token* tok2, const std::string& var) +void CheckOtherImpl::redundantCopyError(const Token *tok1, const Token* tok2, const std::string& var) { const std::list callstack = { tok1, tok2 }; reportError(callstack, Severity::performance, "redundantCopy", @@ -737,7 +737,7 @@ void CheckOther::redundantCopyError(const Token *tok1, const Token* tok2, const "Buffer '$symbol' is being written before its old content has been used.", CWE563, Certainty::normal); } -void CheckOther::redundantAssignmentError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive) +void CheckOtherImpl::redundantAssignmentError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive) { ErrorPath errorPath = { ErrorPathItem(tok1, var + " is assigned"), ErrorPathItem(tok2, var + " is overwritten") }; if (inconclusive) @@ -751,7 +751,7 @@ void CheckOther::redundantAssignmentError(const Token *tok1, const Token* tok2, "Variable '$symbol' is reassigned a value before the old one has been used.", CWE563, Certainty::normal); } -void CheckOther::redundantInitializationError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive) +void CheckOtherImpl::redundantInitializationError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive) { ErrorPath errorPath = { ErrorPathItem(tok1, var + " is initialized"), ErrorPathItem(tok2, var + " is overwritten") }; reportError(std::move(errorPath), Severity::style, "redundantInitialization", @@ -760,7 +760,7 @@ void CheckOther::redundantInitializationError(const Token *tok1, const Token* to inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckOther::redundantAssignmentInSwitchError(const Token *tok1, const Token* tok2, const std::string &var) +void CheckOtherImpl::redundantAssignmentInSwitchError(const Token *tok1, const Token* tok2, const std::string &var) { ErrorPath errorPath = { ErrorPathItem(tok1, "$symbol is assigned"), ErrorPathItem(tok2, "$symbol is overwritten") }; reportError(std::move(errorPath), Severity::style, "redundantAssignInSwitch", @@ -768,7 +768,7 @@ void CheckOther::redundantAssignmentInSwitchError(const Token *tok1, const Token "Variable '$symbol' is reassigned a value before the old one has been used. 'break;' missing?", CWE563, Certainty::normal); } -void CheckOther::redundantAssignmentSameValueError(const Token *tok, const ValueFlow::Value* val, const std::string &var) +void CheckOtherImpl::redundantAssignmentSameValueError(const Token *tok, const ValueFlow::Value* val, const std::string &var) { auto errorPath = val->errorPath; errorPath.emplace_back(tok, ""); @@ -792,12 +792,12 @@ static inline bool isFunctionOrBreakPattern(const Token *tok) return Token::Match(tok, "%name% (") || Token::Match(tok, "break|continue|return|exit|goto|throw"); } -void CheckOther::redundantBitwiseOperationInSwitchError() +void CheckOtherImpl::redundantBitwiseOperationInSwitchError() { if (!mSettings->severity.isEnabled(Severity::warning)) return; - logChecker("CheckOther::redundantBitwiseOperationInSwitch"); // warning + logChecker("CheckOtherImpl::redundantBitwiseOperationInSwitch"); // warning const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -909,7 +909,7 @@ void CheckOther::redundantBitwiseOperationInSwitchError() } } -void CheckOther::redundantBitwiseOperationInSwitchError(const Token *tok, const std::string &varname) +void CheckOtherImpl::redundantBitwiseOperationInSwitchError(const Token *tok, const std::string &varname) { reportError(tok, Severity::style, "redundantBitwiseOperationInSwitch", @@ -921,12 +921,12 @@ void CheckOther::redundantBitwiseOperationInSwitchError(const Token *tok, const //--------------------------------------------------------------------------- // Check for statements like case A||B: in switch() //--------------------------------------------------------------------------- -void CheckOther::checkSuspiciousCaseInSwitch() +void CheckOtherImpl::checkSuspiciousCaseInSwitch() { if (!mSettings->certainty.isEnabled(Certainty::inconclusive) || !mSettings->severity.isEnabled(Severity::warning)) return; - logChecker("CheckOther::checkSuspiciousCaseInSwitch"); // warning,inconclusive + logChecker("CheckOtherImpl::checkSuspiciousCaseInSwitch"); // warning,inconclusive const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -955,7 +955,7 @@ void CheckOther::checkSuspiciousCaseInSwitch() } } -void CheckOther::suspiciousCaseInSwitchError(const Token* tok, const std::string& operatorString) +void CheckOtherImpl::suspiciousCaseInSwitchError(const Token* tok, const std::string& operatorString) { reportError(tok, Severity::warning, "suspiciousCase", "Found suspicious case label in switch(). Operator '" + operatorString + "' probably doesn't work as intended.\n" @@ -1005,7 +1005,7 @@ static bool isVardeclInSwitch(const Token* tok) // Detect dead code, that follows such a statement. e.g.: // return(0); foo(); //--------------------------------------------------------------------------- -void CheckOther::checkUnreachableCode() +void CheckOtherImpl::checkUnreachableCode() { // misra-c-2012-2.1 // misra-c-2023-2.1 @@ -1014,7 +1014,7 @@ void CheckOther::checkUnreachableCode() if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("duplicateBreak") && !mSettings->isPremiumEnabled("unreachableCode")) return; - logChecker("CheckOther::checkUnreachableCode"); // style + logChecker("CheckOtherImpl::checkUnreachableCode"); // style const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -1125,7 +1125,7 @@ void CheckOther::checkUnreachableCode() } } -void CheckOther::duplicateBreakError(const Token *tok, bool inconclusive) +void CheckOtherImpl::duplicateBreakError(const Token *tok, bool inconclusive) { reportError(tok, Severity::style, "duplicateBreak", "Consecutive return, break, continue, goto or throw statements are unnecessary.\n" @@ -1133,7 +1133,7 @@ void CheckOther::duplicateBreakError(const Token *tok, bool inconclusive) "The second statement can never be executed, and so should be removed.", CWE561, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckOther::unreachableCodeError(const Token *tok, const Token* noreturn, bool inconclusive) +void CheckOtherImpl::unreachableCodeError(const Token *tok, const Token* noreturn, bool inconclusive) { std::string msg = "Statements following "; if (noreturn && (noreturn->function() || mSettings->library.isnoreturn(noreturn))) @@ -1147,7 +1147,7 @@ void CheckOther::unreachableCodeError(const Token *tok, const Token* noreturn, b msg, CWE561, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckOther::redundantContinueError(const Token *tok) +void CheckOtherImpl::redundantContinueError(const Token *tok) { reportError(tok, Severity::style, "redundantContinue", "'continue' is redundant since it is the last statement in a loop.", CWE561, Certainty::normal); @@ -1183,7 +1183,7 @@ static bool isSimpleExpr(const Token* tok, const Variable* var, const Settings& //--------------------------------------------------------------------------- // Check scope of variables.. //--------------------------------------------------------------------------- -void CheckOther::checkVariableScope() +void CheckOtherImpl::checkVariableScope() { if (mSettings->clang) return; @@ -1198,7 +1198,7 @@ void CheckOther::checkVariableScope() if (mSettings->daca && mTokenizer->isC()) return; - logChecker("CheckOther::checkVariableScope"); // style,notclang + logChecker("CheckOtherImpl::checkVariableScope"); // style,notclang for (const Variable* var : symbolDatabase->variableList()) { if (!var || !var->isLocal() || var->isConst()) @@ -1335,7 +1335,7 @@ static bool isOnlyUsedInCurrentScope(const Variable* var, const Token *tok, cons return !Token::findmatch(tok->scope()->bodyEnd, "%varid%", var->scope()->bodyEnd, var->declarationId()); } -bool CheckOther::checkInnerScope(const Token *tok, const Variable* var, bool& used) const +bool CheckOtherImpl::checkInnerScope(const Token *tok, const Variable* var, bool& used) const { const Scope* scope = tok->next()->scope(); bool loopVariable = scope->isLoopScope(); @@ -1446,7 +1446,7 @@ bool CheckOther::checkInnerScope(const Token *tok, const Variable* var, bool& us return true; } -void CheckOther::variableScopeError(const Token *tok, const std::string &varname) +void CheckOtherImpl::variableScopeError(const Token *tok, const std::string &varname) { reportError(tok, Severity::style, @@ -1473,7 +1473,7 @@ void CheckOther::variableScopeError(const Token *tok, const std::string &varname //--------------------------------------------------------------------------- // Comma in return statement: return a+1, b++;. (experimental) //--------------------------------------------------------------------------- -void CheckOther::checkCommaSeparatedReturn() +void CheckOtherImpl::checkCommaSeparatedReturn() { // TODO: This is experimental for now. See #5076 if ((true) || !mSettings->severity.isEnabled(Severity::style)) // NOLINT(readability-simplify-boolean-expr,readability-redundant-parentheses) @@ -1500,7 +1500,7 @@ void CheckOther::checkCommaSeparatedReturn() } } -void CheckOther::commaSeparatedReturnError(const Token *tok) +void CheckOtherImpl::commaSeparatedReturnError(const Token *tok) { reportError(tok, Severity::style, @@ -1538,12 +1538,12 @@ static bool isLargeContainer(const Variable* var, const Settings& settings) return arraySize > maxByValueSize; } -void CheckOther::checkPassByReference() +void CheckOtherImpl::checkPassByReference() { if (!mSettings->severity.isEnabled(Severity::performance) || mTokenizer->isC()) return; - logChecker("CheckOther::checkPassByReference"); // performance,c++ + logChecker("CheckOtherImpl::checkPassByReference"); // performance,c++ const SymbolDatabase * const symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -1617,7 +1617,7 @@ void CheckOther::checkPassByReference() } } -void CheckOther::passedByValueError(const Variable* var, bool inconclusive, bool isRangeBasedFor) +void CheckOtherImpl::passedByValueError(const Variable* var, bool inconclusive, bool isRangeBasedFor) { std::string id = isRangeBasedFor ? "iterateByValue" : "passedByValue"; const std::string action = isRangeBasedFor ? "declared as": "passed by"; @@ -1682,7 +1682,7 @@ static bool isCastToVoid(const Variable* var) return false; } -void CheckOther::checkConstVariable() +void CheckOtherImpl::checkConstVariable() { if ((!mSettings->severity.isEnabled(Severity::style) || mTokenizer->isC()) && !mSettings->isPremiumEnabled("constVariable")) return; @@ -1875,7 +1875,7 @@ static const Function* getEnclosingFunction(const Variable* var) return scope ? scope->function : nullptr; } -void CheckOther::checkConstPointer() +void CheckOtherImpl::checkConstPointer() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("constParameter") && @@ -1884,7 +1884,7 @@ void CheckOther::checkConstPointer() !mSettings->isPremiumEnabled("constVariablePointer")) return; - logChecker("CheckOther::checkConstPointer"); // style + logChecker("CheckOtherImpl::checkConstPointer"); // style std::set pointers, nonConstPointers; for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { @@ -2051,7 +2051,7 @@ void CheckOther::checkConstPointer() } } -void CheckOther::constVariableError(const Variable *var, const Function *function) +void CheckOtherImpl::constVariableError(const Variable *var, const Function *function) { if (!var) { reportError(nullptr, Severity::style, "constParameter", "Parameter 'x' can be declared with const"); @@ -2089,14 +2089,14 @@ void CheckOther::constVariableError(const Variable *var, const Function *functio // Check usage of char variables.. //--------------------------------------------------------------------------- -void CheckOther::checkCharVariable() +void CheckOtherImpl::checkCharVariable() { const bool warning = mSettings->severity.isEnabled(Severity::warning); const bool portability = mSettings->severity.isEnabled(Severity::portability); if (!warning && !portability) return; - logChecker("CheckOther::checkCharVariable"); // warning,portability + logChecker("CheckOtherImpl::checkCharVariable"); // warning,portability const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -2140,7 +2140,7 @@ void CheckOther::checkCharVariable() } } -void CheckOther::signedCharArrayIndexError(const Token *tok) +void CheckOtherImpl::signedCharArrayIndexError(const Token *tok) { reportError(tok, Severity::warning, @@ -2151,7 +2151,7 @@ void CheckOther::signedCharArrayIndexError(const Token *tok) "because of sign extension.", CWE128, Certainty::normal); } -void CheckOther::unknownSignCharArrayIndexError(const Token *tok) +void CheckOtherImpl::unknownSignCharArrayIndexError(const Token *tok) { reportError(tok, Severity::portability, @@ -2161,7 +2161,7 @@ void CheckOther::unknownSignCharArrayIndexError(const Token *tok) "treated depending on whether 'char' is signed or unsigned on target platform.", CWE758, Certainty::normal); } -void CheckOther::charBitOpError(const Token *tok) +void CheckOtherImpl::charBitOpError(const Token *tok) { reportError(tok, Severity::warning, @@ -2348,13 +2348,13 @@ static bool isConstTop(const Token *tok) return false; } -void CheckOther::checkIncompleteStatement() +void CheckOtherImpl::checkIncompleteStatement() { if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->isPremiumEnabled("constStatement")) return; - logChecker("CheckOther::checkIncompleteStatement"); // warning + logChecker("CheckOtherImpl::checkIncompleteStatement"); // warning for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { const Scope *scope = tok->scope(); @@ -2410,7 +2410,7 @@ void CheckOther::checkIncompleteStatement() } } -void CheckOther::constStatementError(const Token *tok, const std::string &type, bool inconclusive) +void CheckOtherImpl::constStatementError(const Token *tok, const std::string &type, bool inconclusive) { const Token *valueTok = tok; while (valueTok && valueTok->isCast()) @@ -2465,9 +2465,9 @@ void CheckOther::constStatementError(const Token *tok, const std::string &type, //--------------------------------------------------------------------------- // Detect division by zero. //--------------------------------------------------------------------------- -void CheckOther::checkZeroDivision() +void CheckOtherImpl::checkZeroDivision() { - logChecker("CheckOther::checkZeroDivision"); + logChecker("CheckOtherImpl::checkZeroDivision"); for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (!tok->astOperand2() || !tok->astOperand1()) @@ -2486,7 +2486,7 @@ void CheckOther::checkZeroDivision() } } -void CheckOther::zerodivError(const Token *tok, const ValueFlow::Value *value) +void CheckOtherImpl::zerodivError(const Token *tok, const ValueFlow::Value *value) { if (!tok && !value) { reportError(tok, Severity::error, "zerodiv", "Division by zero.", CWE369, Certainty::normal); @@ -2515,11 +2515,11 @@ void CheckOther::zerodivError(const Token *tok, const ValueFlow::Value *value) // double d = 1.0 / 0.0 + 100.0; //--------------------------------------------------------------------------- -void CheckOther::checkNanInArithmeticExpression() +void CheckOtherImpl::checkNanInArithmeticExpression() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("nanInArithmeticExpression")) return; - logChecker("CheckOther::checkNanInArithmeticExpression"); // style + logChecker("CheckOtherImpl::checkNanInArithmeticExpression"); // style for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (tok->str() != "/") continue; @@ -2530,7 +2530,7 @@ void CheckOther::checkNanInArithmeticExpression() } } -void CheckOther::nanInArithmeticExpressionError(const Token *tok) +void CheckOtherImpl::nanInArithmeticExpressionError(const Token *tok) { reportError(tok, Severity::style, "nanInArithmeticExpression", "Using NaN/Inf in a computation.\n" @@ -2541,7 +2541,7 @@ void CheckOther::nanInArithmeticExpressionError(const Token *tok) //--------------------------------------------------------------------------- // Creating instance of classes which are destroyed immediately //--------------------------------------------------------------------------- -void CheckOther::checkMisusedScopedObject() +void CheckOtherImpl::checkMisusedScopedObject() { // Skip this check for .c files if (mTokenizer->isC()) @@ -2550,7 +2550,7 @@ void CheckOther::checkMisusedScopedObject() if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("unusedScopedObject")) return; - logChecker("CheckOther::checkMisusedScopedObject"); // style,c++ + logChecker("CheckOtherImpl::checkMisusedScopedObject"); // style,c++ auto getConstructorTok = [](const Token* tok, std::string& typeStr) -> const Token* { if (!Token::Match(tok, "[;{}] %name%") || tok->next()->isKeyword()) @@ -2616,7 +2616,7 @@ void CheckOther::checkMisusedScopedObject() } } -void CheckOther::misusedScopeObjectError(const Token *tok, const std::string& varname, bool isAssignment) +void CheckOtherImpl::misusedScopeObjectError(const Token *tok, const std::string& varname, bool isAssignment) { std::string msg = "Instance of '$symbol' object is destroyed immediately"; msg += isAssignment ? ", assignment has no effect." : "."; @@ -2641,7 +2641,7 @@ static const Token * getSingleExpressionInBlock(const Token * tok) // check for duplicate code in if and else branches // if (a) { b = true; } else { b = true; } //----------------------------------------------------------------------------- -void CheckOther::checkDuplicateBranch() +void CheckOtherImpl::checkDuplicateBranch() { // This is inconclusive since in practice most warnings are noise: // * There can be unfixed low-priority todos. The code is fine as it @@ -2654,7 +2654,7 @@ void CheckOther::checkDuplicateBranch() if (!mSettings->severity.isEnabled(Severity::style) || !mSettings->certainty.isEnabled(Certainty::inconclusive)) return; - logChecker("CheckOther::checkDuplicateBranch"); // style,inconclusive + logChecker("CheckOtherImpl::checkDuplicateBranch"); // style,inconclusive const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -2720,7 +2720,7 @@ void CheckOther::checkDuplicateBranch() } } -void CheckOther::duplicateBranchError(const Token *tok1, const Token *tok2, ErrorPath errors) +void CheckOtherImpl::duplicateBranchError(const Token *tok1, const Token *tok2, ErrorPath errors) { errors.emplace_back(tok2, ""); errors.emplace_back(tok1, ""); @@ -2737,12 +2737,12 @@ void CheckOther::duplicateBranchError(const Token *tok1, const Token *tok2, Erro // char* p = malloc(100); // free(p + 10); //----------------------------------------------------------------------------- -void CheckOther::checkInvalidFree() +void CheckOtherImpl::checkInvalidFree() { std::map inconclusive; std::map allocation; - logChecker("CheckOther::checkInvalidFree"); + logChecker("CheckOtherImpl::checkInvalidFree"); const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -2811,7 +2811,7 @@ void CheckOther::checkInvalidFree() } } -void CheckOther::invalidFreeError(const Token *tok, const std::string &allocation, bool inconclusive) +void CheckOtherImpl::invalidFreeError(const Token *tok, const std::string &allocation, bool inconclusive) { std::string alloc = allocation; if (alloc != "new") @@ -2870,7 +2870,7 @@ isStaticAssert(const Settings &settings, const Token *tok) return false; } -void CheckOther::checkDuplicateExpression() +void CheckOtherImpl::checkDuplicateExpression() { { const bool styleEnabled = mSettings->severity.isEnabled(Severity::style); @@ -2886,7 +2886,7 @@ void CheckOther::checkDuplicateExpression() return; } - logChecker("CheckOther::checkDuplicateExpression"); // style,warning + logChecker("CheckOtherImpl::checkDuplicateExpression"); // style,warning // Parse all executing scopes.. const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -3068,7 +3068,7 @@ void CheckOther::checkDuplicateExpression() } } -void CheckOther::oppositeExpressionError(const Token *opTok, ErrorPath errors) +void CheckOtherImpl::oppositeExpressionError(const Token *opTok, ErrorPath errors) { errors.emplace_back(opTok, ""); @@ -3080,7 +3080,7 @@ void CheckOther::oppositeExpressionError(const Token *opTok, ErrorPath errors) "determine if it is correct.", CWE398, Certainty::normal); } -void CheckOther::duplicateExpressionError(const Token *tok1, const Token *tok2, const Token *opTok, ErrorPath errors, bool hasMultipleExpr) +void CheckOtherImpl::duplicateExpressionError(const Token *tok1, const Token *tok2, const Token *opTok, ErrorPath errors, bool hasMultipleExpr) { errors.emplace_back(opTok, ""); @@ -3108,7 +3108,7 @@ void CheckOther::duplicateExpressionError(const Token *tok1, const Token *tok2, "determine if it is correct.", CWE398, Certainty::normal); } -void CheckOther::duplicateAssignExpressionError(const Token *tok1, const Token *tok2, bool inconclusive) +void CheckOtherImpl::duplicateAssignExpressionError(const Token *tok1, const Token *tok2, bool inconclusive) { const std::list toks = { tok2, tok1 }; @@ -3122,7 +3122,7 @@ void CheckOther::duplicateAssignExpressionError(const Token *tok1, const Token * "determine if it is correct.", CWE398, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckOther::duplicateExpressionTernaryError(const Token *tok, ErrorPath errors) +void CheckOtherImpl::duplicateExpressionTernaryError(const Token *tok, ErrorPath errors) { errors.emplace_back(tok, ""); reportError(std::move(errors), Severity::style, "duplicateExpressionTernary", "Same expression in both branches of ternary operator.\n" @@ -3130,14 +3130,14 @@ void CheckOther::duplicateExpressionTernaryError(const Token *tok, ErrorPath err "the same code is executed regardless of the condition.", CWE398, Certainty::normal); } -void CheckOther::duplicateValueTernaryError(const Token *tok) +void CheckOtherImpl::duplicateValueTernaryError(const Token *tok) { reportError(tok, Severity::style, "duplicateValueTernary", "Same value in both branches of ternary operator.\n" "Finding the same value in both branches of ternary operator is suspicious as " "the same code is executed regardless of the condition.", CWE398, Certainty::normal); } -void CheckOther::selfAssignmentError(const Token *tok, const std::string &varname) +void CheckOtherImpl::selfAssignmentError(const Token *tok, const std::string &varname) { reportError(tok, Severity::style, "selfAssignment", @@ -3154,12 +3154,12 @@ void CheckOther::selfAssignmentError(const Token *tok, const std::string &varnam // Reference: // - http://www.cplusplus.com/reference/cmath/ //----------------------------------------------------------------------------- -void CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalse() +void CheckOtherImpl::checkComparisonFunctionIsAlwaysTrueOrFalse() { if (!mSettings->severity.isEnabled(Severity::warning)) return; - logChecker("CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalse"); // warning + logChecker("CheckOtherImpl::checkComparisonFunctionIsAlwaysTrueOrFalse"); // warning const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -3184,7 +3184,7 @@ void CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalse() } } } -void CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalseError(const Token* tok, const std::string &functionName, const std::string &varName, const bool result) +void CheckOtherImpl::checkComparisonFunctionIsAlwaysTrueOrFalseError(const Token* tok, const std::string &functionName, const std::string &varName, const bool result) { const std::string strResult = bool_to_string(result); const CWE cweResult = result ? CWE571 : CWE570; @@ -3199,12 +3199,12 @@ void CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalseError(const Token* to //--------------------------------------------------------------------------- // Check testing sign of unsigned variables and pointers. //--------------------------------------------------------------------------- -void CheckOther::checkSignOfUnsignedVariable() +void CheckOtherImpl::checkSignOfUnsignedVariable() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("unsignedLessThanZero")) return; - logChecker("CheckOther::checkSignOfUnsignedVariable"); // style + logChecker("CheckOtherImpl::checkSignOfUnsignedVariable"); // style const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -3213,13 +3213,13 @@ void CheckOther::checkSignOfUnsignedVariable() for (const Token *tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { const ValueFlow::Value *zeroValue = nullptr; const Token *nonZeroExpr = nullptr; - if (comparisonNonZeroExpressionLessThanZero(tok, zeroValue, nonZeroExpr)) { + if (CheckOther::comparisonNonZeroExpressionLessThanZero(tok, zeroValue, nonZeroExpr)) { const ValueType* vt = nonZeroExpr->valueType(); if (vt->pointer) pointerLessThanZeroError(tok, zeroValue); else unsignedLessThanZeroError(tok, zeroValue, nonZeroExpr->expressionString()); - } else if (testIfNonZeroExpressionIsPositive(tok, zeroValue, nonZeroExpr)) { + } else if (CheckOther::testIfNonZeroExpressionIsPositive(tok, zeroValue, nonZeroExpr)) { const ValueType* vt = nonZeroExpr->valueType(); if (vt->pointer) pointerPositiveError(tok, zeroValue); @@ -3278,7 +3278,7 @@ bool CheckOther::testIfNonZeroExpressionIsPositive(const Token *tok, const Value return vt && (vt->pointer || vt->sign == ValueType::UNSIGNED); } -void CheckOther::unsignedLessThanZeroError(const Token *tok, const ValueFlow::Value * v, const std::string &varname) +void CheckOtherImpl::unsignedLessThanZeroError(const Token *tok, const ValueFlow::Value * v, const std::string &varname) { reportError(getErrorPath(tok, v, "Unsigned less than zero"), Severity::style, "unsignedLessThanZero", "$symbol:" + varname + "\n" @@ -3287,20 +3287,20 @@ void CheckOther::unsignedLessThanZeroError(const Token *tok, const ValueFlow::Va "is either pointless or an error to check if it is.", CWE570, Certainty::normal); } -void CheckOther::pointerLessThanZeroError(const Token *tok, const ValueFlow::Value *v) +void CheckOtherImpl::pointerLessThanZeroError(const Token *tok, const ValueFlow::Value *v) { reportError(getErrorPath(tok, v, "Pointer less than zero"), Severity::style, "pointerLessThanZero", "A pointer can not be negative so it is either pointless or an error to check if it is.", CWE570, Certainty::normal); } -void CheckOther::unsignedPositiveError(const Token *tok, const ValueFlow::Value * v, const std::string &varname) +void CheckOtherImpl::unsignedPositiveError(const Token *tok, const ValueFlow::Value * v, const std::string &varname) { reportError(getErrorPath(tok, v, "Unsigned positive"), Severity::style, "unsignedPositive", "$symbol:" + varname + "\n" "Unsigned expression '$symbol' can't be negative so it is unnecessary to test it.", CWE570, Certainty::normal); } -void CheckOther::pointerPositiveError(const Token *tok, const ValueFlow::Value * v) +void CheckOtherImpl::pointerPositiveError(const Token *tok, const ValueFlow::Value * v) { reportError(getErrorPath(tok, v, "Pointer positive"), Severity::style, "pointerPositive", "A pointer can not be negative so it is either pointless or an error to check if it is not.", CWE570, Certainty::normal); @@ -3383,12 +3383,12 @@ static bool checkVariableAssignment(const Token* tok, const ValueType* vtLhs, co return scope && scope->function && (!scope->functionOf || scope->function->isConst() || scope->function->isStatic()); } -void CheckOther::checkRedundantCopy() +void CheckOtherImpl::checkRedundantCopy() { if (!mSettings->severity.isEnabled(Severity::performance) || mTokenizer->isC() || !mSettings->certainty.isEnabled(Certainty::inconclusive)) return; - logChecker("CheckOther::checkRedundantCopy"); // c++,performance,inconclusive + logChecker("CheckOtherImpl::checkRedundantCopy"); // c++,performance,inconclusive const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -3421,7 +3421,7 @@ void CheckOther::checkRedundantCopy() } } -void CheckOther::redundantCopyError(const Token *tok,const std::string& varname) +void CheckOtherImpl::redundantCopyError(const Token *tok,const std::string& varname) { reportError(tok, Severity::performance, "redundantCopyLocalConst", "$symbol:" + varname + "\n" @@ -3441,11 +3441,11 @@ static bool isNegative(const Token *tok, const Settings &settings) return tok->valueType() && tok->valueType()->sign == ValueType::SIGNED && tok->getValueLE(-1LL, settings); } -void CheckOther::checkNegativeBitwiseShift() +void CheckOtherImpl::checkNegativeBitwiseShift() { const bool portability = mSettings->severity.isEnabled(Severity::portability); - logChecker("CheckOther::checkNegativeBitwiseShift"); + logChecker("CheckOtherImpl::checkNegativeBitwiseShift"); for (const Token* tok = mTokenizer->tokens(); tok; tok = tok->next()) { tok = skipUnreachableBranch(tok); @@ -3483,7 +3483,7 @@ void CheckOther::checkNegativeBitwiseShift() } -void CheckOther::negativeBitwiseShiftError(const Token *tok, int op) +void CheckOtherImpl::negativeBitwiseShiftError(const Token *tok, int op) { if (op == 1) // LHS - this is used by intention in various software, if it @@ -3497,7 +3497,7 @@ void CheckOther::negativeBitwiseShiftError(const Token *tok, int op) //--------------------------------------------------------------------------- // Check for incompletely filled buffers. //--------------------------------------------------------------------------- -void CheckOther::checkIncompleteArrayFill() +void CheckOtherImpl::checkIncompleteArrayFill() { if (!mSettings->certainty.isEnabled(Certainty::inconclusive)) return; @@ -3506,7 +3506,7 @@ void CheckOther::checkIncompleteArrayFill() if (!printPortability && !printWarning) return; - logChecker("CheckOther::checkIncompleteArrayFill"); // warning,portability,inconclusive + logChecker("CheckOtherImpl::checkIncompleteArrayFill"); // warning,portability,inconclusive const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -3546,7 +3546,7 @@ void CheckOther::checkIncompleteArrayFill() } } -void CheckOther::incompleteArrayFillError(const Token* tok, const std::string& buffer, const std::string& function, bool boolean) +void CheckOtherImpl::incompleteArrayFillError(const Token* tok, const std::string& buffer, const std::string& function, bool boolean) { if (boolean) reportError(tok, Severity::portability, "incompleteArrayFill", @@ -3566,12 +3566,12 @@ void CheckOther::incompleteArrayFillError(const Token* tok, const std::string& b // Detect NULL being passed to variadic function. //--------------------------------------------------------------------------- -void CheckOther::checkVarFuncNullUB() +void CheckOtherImpl::checkVarFuncNullUB() { if (!mSettings->severity.isEnabled(Severity::portability)) return; - logChecker("CheckOther::checkVarFuncNullUB"); // portability + logChecker("CheckOtherImpl::checkVarFuncNullUB"); // portability const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -3604,7 +3604,7 @@ void CheckOther::checkVarFuncNullUB() } } -void CheckOther::varFuncNullUBError(const Token *tok) +void CheckOtherImpl::varFuncNullUBError(const Token *tok) { reportError(tok, Severity::portability, @@ -3651,12 +3651,12 @@ void CheckOther::varFuncNullUBError(const Token *tok) "}", CWE475, Certainty::normal); } -void CheckOther::checkRedundantPointerOp() +void CheckOtherImpl::checkRedundantPointerOp() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("redundantPointerOp")) return; - logChecker("CheckOther::checkRedundantPointerOp"); // style + logChecker("CheckOtherImpl::checkRedundantPointerOp"); // style for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (tok->isExpandedMacro() && tok->str() == "(") @@ -3690,20 +3690,20 @@ void CheckOther::checkRedundantPointerOp() } } -void CheckOther::redundantPointerOpError(const Token* tok, const std::string &varname, bool inconclusive, bool addressOfDeref) +void CheckOtherImpl::redundantPointerOpError(const Token* tok, const std::string &varname, bool inconclusive, bool addressOfDeref) { std::string msg = "$symbol:" + varname + "\nRedundant pointer operation on '$symbol' - it's already a "; msg += addressOfDeref ? "pointer." : "variable."; reportError(tok, Severity::style, "redundantPointerOp", msg, CWE398, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckOther::checkInterlockedDecrement() +void CheckOtherImpl::checkInterlockedDecrement() { if (!mSettings->platform.isWindows()) { return; } - logChecker("CheckOther::checkInterlockedDecrement"); // windows-platform + logChecker("CheckOtherImpl::checkInterlockedDecrement"); // windows-platform for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (tok->isName() && Token::Match(tok, "InterlockedDecrement ( & %name% ) ; if ( %name%|!|0")) { @@ -3737,18 +3737,18 @@ void CheckOther::checkInterlockedDecrement() } } -void CheckOther::raceAfterInterlockedDecrementError(const Token* tok) +void CheckOtherImpl::raceAfterInterlockedDecrementError(const Token* tok) { reportError(tok, Severity::error, "raceAfterInterlockedDecrement", "Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.", CWE362, Certainty::normal); } -void CheckOther::checkUnusedLabel() +void CheckOtherImpl::checkUnusedLabel() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->severity.isEnabled(Severity::warning) && !mSettings->isPremiumEnabled("unusedLabel")) return; - logChecker("CheckOther::checkUnusedLabel"); // style,warning + logChecker("CheckOtherImpl::checkUnusedLabel"); // style,warning const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -3766,7 +3766,7 @@ void CheckOther::checkUnusedLabel() } } -void CheckOther::unusedLabelError(const Token* tok, bool inSwitch, bool hasIfdef) +void CheckOtherImpl::unusedLabelError(const Token* tok, bool inSwitch, bool hasIfdef) { if (tok && !mSettings->severity.isEnabled(inSwitch ? Severity::warning : Severity::style) && !mSettings->isPremiumEnabled("unusedLabel")) return; @@ -3860,7 +3860,7 @@ static bool checkEvaluationOrderCpp17(const Token * tok, const Token * tok2, con return foundUndefined || foundUnspecified; } -void CheckOther::checkEvaluationOrder() +void CheckOtherImpl::checkEvaluationOrder() { logChecker("CheckOther::checkEvaluationOrder"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -3922,7 +3922,7 @@ void CheckOther::checkEvaluationOrder() } } -void CheckOther::unknownEvaluationOrder(const Token* tok, bool isUnspecifiedBehavior) +void CheckOtherImpl::unknownEvaluationOrder(const Token* tok, bool isUnspecifiedBehavior) { isUnspecifiedBehavior ? reportError(tok, Severity::portability, "unknownEvaluationOrder", @@ -3931,13 +3931,13 @@ void CheckOther::unknownEvaluationOrder(const Token* tok, bool isUnspecifiedBeha "Expression '" + (tok ? tok->expressionString() : std::string("x = x++;")) + "' depends on order of evaluation of side effects", CWE768, Certainty::normal); } -void CheckOther::checkAccessOfMovedVariable() +void CheckOtherImpl::checkAccessOfMovedVariable() { if (!mTokenizer->isCPP() || mSettings->standards.cpp < Standards::CPP11) return; if (!mSettings->isPremiumEnabled("accessMoved") && !mSettings->severity.isEnabled(Severity::warning)) return; - logChecker("CheckOther::checkAccessOfMovedVariable"); // c++11,warning + logChecker("CheckOtherImpl::checkAccessOfMovedVariable"); // c++11,warning const bool reportInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { @@ -3978,7 +3978,7 @@ void CheckOther::checkAccessOfMovedVariable() } } -void CheckOther::accessMovedError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive) +void CheckOtherImpl::accessMovedError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive) { if (!tok) { reportError(tok, Severity::warning, "accessMoved", "Access of moved variable 'v'.", CWE672, Certainty::normal); @@ -4007,7 +4007,7 @@ void CheckOther::accessMovedError(const Token *tok, const std::string &varname, -void CheckOther::checkFuncArgNamesDifferent() +void CheckOtherImpl::checkFuncArgNamesDifferent() { const bool style = mSettings->severity.isEnabled(Severity::style); const bool inconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); @@ -4016,7 +4016,7 @@ void CheckOther::checkFuncArgNamesDifferent() if (!(warning || (style && inconclusive)) && !mSettings->isPremiumEnabled("funcArgNamesDifferent")) return; - logChecker("CheckOther::checkFuncArgNamesDifferent"); // style,warning,inconclusive + logChecker("CheckOtherImpl::checkFuncArgNamesDifferent"); // style,warning,inconclusive const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); // check every function @@ -4090,7 +4090,7 @@ void CheckOther::checkFuncArgNamesDifferent() } } -void CheckOther::funcArgNamesDifferent(const std::string & functionName, nonneg int index, +void CheckOtherImpl::funcArgNamesDifferent(const std::string & functionName, nonneg int index, const Token* declaration, const Token* definition) { std::list tokens = { declaration,definition }; @@ -4102,7 +4102,7 @@ void CheckOther::funcArgNamesDifferent(const std::string & functionName, nonneg (definition ? definition->str() : "") + "'.", CWE628, Certainty::inconclusive); } -void CheckOther::funcArgOrderDifferent(const std::string & functionName, +void CheckOtherImpl::funcArgOrderDifferent(const std::string & functionName, const Token* declaration, const Token* definition, const std::vector & declarations, const std::vector & definitions) @@ -4153,11 +4153,11 @@ static const Token *findShadowed(const Scope *scope, const Variable& var, int li return shadowed; } -void CheckOther::checkShadowVariables() +void CheckOtherImpl::checkShadowVariables() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("shadowVariable")) return; - logChecker("CheckOther::checkShadowVariables"); // style + logChecker("CheckOtherImpl::checkShadowVariables"); // style const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope & scope : symbolDatabase->scopeList) { if (!scope.isExecutable() || scope.type == ScopeType::eLambda) @@ -4213,7 +4213,7 @@ void CheckOther::checkShadowVariables() } } -void CheckOther::shadowError(const Token *shadows, const std::string &shadowsType, +void CheckOtherImpl::shadowError(const Token *shadows, const std::string &shadowsType, const Token *shadowed, const std::string &shadowedType) { ErrorPath errorPath; @@ -4254,11 +4254,11 @@ static bool isVariableExprHidden(const Token* tok) return false; } -void CheckOther::checkKnownArgument() +void CheckOtherImpl::checkKnownArgument() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("knownArgument")) return; - logChecker("CheckOther::checkKnownArgument"); // style + logChecker("CheckOtherImpl::checkKnownArgument"); // style const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *functionScope : symbolDatabase->functionScopes) { for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { @@ -4323,7 +4323,7 @@ void CheckOther::checkKnownArgument() } } -void CheckOther::knownArgumentError(const Token *tok, const Token *ftok, const ValueFlow::Value *value, const std::string &varexpr, bool isVariableExpressionHidden) +void CheckOtherImpl::knownArgumentError(const Token *tok, const Token *ftok, const ValueFlow::Value *value, const std::string &varexpr, bool isVariableExpressionHidden) { if (!tok) { reportError(tok, Severity::style, "knownArgument", "Argument 'x-x' to function 'func' is always 0. It does not matter what value 'x' has."); @@ -4355,11 +4355,11 @@ void CheckOther::knownArgumentError(const Token *tok, const Token *ftok, const V reportError(std::move(errorPath), Severity::style, id, errmsg, CWE570, Certainty::normal); } -void CheckOther::checkKnownPointerToBool() +void CheckOtherImpl::checkKnownPointerToBool() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("knownPointerToBool")) return; - logChecker("CheckOther::checkKnownPointerToBool"); // style + logChecker("CheckOtherImpl::checkKnownPointerToBool"); // style const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope* functionScope : symbolDatabase->functionScopes) { for (const Token* tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { @@ -4385,7 +4385,7 @@ void CheckOther::checkKnownPointerToBool() } } -void CheckOther::knownPointerToBoolError(const Token* tok, const ValueFlow::Value* value) +void CheckOtherImpl::knownPointerToBoolError(const Token* tok, const ValueFlow::Value* value) { if (!tok) { reportError(tok, Severity::style, "knownPointerToBool", "Pointer expression 'p' converted to bool is always true."); @@ -4398,9 +4398,9 @@ void CheckOther::knownPointerToBoolError(const Token* tok, const ValueFlow::Valu reportError(std::move(errorPath), Severity::style, "knownPointerToBool", errmsg, CWE570, Certainty::normal); } -void CheckOther::checkComparePointers() +void CheckOtherImpl::checkComparePointers() { - logChecker("CheckOther::checkComparePointers"); + logChecker("CheckOtherImpl::checkComparePointers"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *functionScope : symbolDatabase->functionScopes) { for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { @@ -4439,7 +4439,7 @@ void CheckOther::checkComparePointers() } } -void CheckOther::comparePointersError(const Token *tok, const ValueFlow::Value *v1, const ValueFlow::Value *v2) +void CheckOtherImpl::comparePointersError(const Token *tok, const ValueFlow::Value *v1, const ValueFlow::Value *v2) { ErrorPath errorPath; std::string verb = "Comparing"; @@ -4459,12 +4459,12 @@ void CheckOther::comparePointersError(const Token *tok, const ValueFlow::Value * std::move(errorPath), Severity::error, id, verb + " pointers that point to different objects", CWE758, Certainty::normal); } -void CheckOther::checkModuloOfOne() +void CheckOtherImpl::checkModuloOfOne() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("moduloofone")) return; - logChecker("CheckOther::checkModuloOfOne"); // style + logChecker("CheckOtherImpl::checkModuloOfOne"); // style for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (!tok->astOperand2() || !tok->astOperand1()) @@ -4481,7 +4481,7 @@ void CheckOther::checkModuloOfOne() } } -void CheckOther::checkModuloOfOneError(const Token *tok) +void CheckOtherImpl::checkModuloOfOneError(const Token *tok) { reportError(tok, Severity::style, "moduloofone", "Modulo of one is always equal to zero"); } @@ -4569,7 +4569,7 @@ static bool isZeroInitializer(const Token *tok) } -void CheckOther::checkUnionZeroInit() +void CheckOtherImpl::checkUnionZeroInit() { if (!mSettings->severity.isEnabled(Severity::portability)) return; @@ -4607,7 +4607,7 @@ void CheckOther::checkUnionZeroInit() } } -void CheckOther::unionZeroInitError(const Token *tok, +void CheckOtherImpl::unionZeroInitError(const Token *tok, const UnionMember& largestMember) { reportError(tok, Severity::portability, "UnionZeroInit", @@ -4679,9 +4679,9 @@ static bool getBufAndOffset(const Token *expr, const Token *&buf, MathLib::bigin return true; } -void CheckOther::checkOverlappingWrite() +void CheckOtherImpl::checkOverlappingWrite() { - logChecker("CheckOther::checkOverlappingWrite"); + logChecker("CheckOtherImpl::checkOverlappingWrite"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *functionScope : symbolDatabase->functionScopes) { for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { @@ -4777,19 +4777,19 @@ void CheckOther::checkOverlappingWrite() } } -void CheckOther::overlappingWriteUnion(const Token *tok) +void CheckOtherImpl::overlappingWriteUnion(const Token *tok) { reportError(tok, Severity::error, "overlappingWriteUnion", "Overlapping read/write of union is undefined behavior"); } -void CheckOther::overlappingWriteFunction(const Token *tok, const std::string& funcname) +void CheckOtherImpl::overlappingWriteFunction(const Token *tok, const std::string& funcname) { reportError(tok, Severity::error, "overlappingWriteFunction", "Overlapping read/write in " + funcname + "() is undefined behavior"); } void CheckOther::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckOther checkOther(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckOtherImpl checkOther(&tokenizer, &tokenizer.getSettings(), errorLogger); // Checks checkOther.warningOldStylePointerCast(); @@ -4841,7 +4841,7 @@ void CheckOther::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) void CheckOther::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckOther c(nullptr, settings, errorLogger); + CheckOtherImpl c(nullptr, settings, errorLogger); // error c.zerodivError(nullptr, nullptr); diff --git a/lib/checkother.h b/lib/checkother.h index f779141f499..e8291e52b82 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include "errortypes.h" @@ -55,7 +56,7 @@ class CPPCHECKLIB CheckOther : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckOther() : Check(myName()) {} + CheckOther() : Check("Other") {} /** Is expression a comparison that checks if a nonzero (unsigned/pointer) expression is less than zero? */ static bool comparisonNonZeroExpressionLessThanZero(const Token *tok, const ValueFlow::Value *&zeroValue, const Token *&nonZeroExpr, bool suppress = false); @@ -64,14 +65,77 @@ class CPPCHECKLIB CheckOther : public Check { static bool testIfNonZeroExpressionIsPositive(const Token *tok, const ValueFlow::Value *&zeroValue, const Token *&nonZeroExpr); private: - /** @brief This constructor is used when running checks. */ - CheckOther(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - - /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + return "Other checks\n" + + // error + "- division with zero\n" + "- scoped object destroyed immediately after construction\n" + "- assignment in an assert statement\n" + "- free() or delete of an invalid memory location\n" + "- bitwise operation with negative right operand\n" + "- cast the return values of getc(),fgetc() and getchar() to character and compare it to EOF\n" + "- race condition with non-interlocked access after InterlockedDecrement() call\n" + "- expression 'x = x++;' depends on order of evaluation of side effects\n" + "- overlapping write of union\n" + + // warning + "- either division by zero or useless condition\n" + "- access of moved or forwarded variable.\n" + + // performance + "- redundant data copying for const variable\n" + "- subsequent assignment or copying to a variable or buffer\n" + "- passing parameter by value\n" + + // portability + "- Passing NULL pointer to function with variable number of arguments leads to UB.\n" + + // style + "- C-style pointer cast in C++ code\n" + "- casting between incompatible pointer types\n" + "- [Incomplete statement](IncompleteStatement)\n" + "- [check how signed char variables are used](CharVar)\n" + "- variable scope can be limited\n" + "- unusual pointer arithmetic. For example: \"abc\" + 'd'\n" + "- redundant assignment, increment, or bitwise operation in a switch statement\n" + "- redundant strcpy in a switch statement\n" + "- Suspicious case labels in switch()\n" + "- assignment of a variable to itself\n" + "- Comparison of values leading always to true or false\n" + "- Clarify calculation with parentheses\n" + "- suspicious comparison of '\\0' with a char\\* variable\n" + "- duplicate break statement\n" + "- unreachable code\n" + "- testing if unsigned variable is negative/positive\n" + "- Suspicious use of ; at the end of 'if/for/while' statement.\n" + "- Array filled incompletely using memset/memcpy/memmove.\n" + "- NaN (not a number) value used in arithmetic expression.\n" + "- comma in return statement (the comma can easily be misread as a semicolon).\n" + "- prefer erfc, expm1 or log1p to avoid loss of precision.\n" + "- identical code in both branches of if/else or ternary operator.\n" + "- redundant pointer operation on pointer like &\\*some_ptr.\n" + "- find unused 'goto' labels.\n" + "- function declaration and definition argument names different.\n" + "- function declaration and definition argument order different.\n" + "- shadow variable.\n" + "- variable can be declared const.\n" + "- calculating modulo of one.\n" + "- known function argument, suspicious calculation.\n"; + } +}; + +class CheckOtherImpl : public CheckImpl { +public: + /** @brief This constructor is used when running checks. */ + CheckOtherImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** @brief Clarify calculation for ".. a * b ? .." */ void clarifyCalculation(); @@ -265,74 +329,6 @@ class CPPCHECKLIB CheckOther : public Check { void checkModuloOfOneError(const Token *tok); void unionZeroInitError(const Token *tok, const UnionMember& largestMember); - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "Other"; - } - - std::string classInfo() const override { - return "Other checks\n" - - // error - "- division with zero\n" - "- scoped object destroyed immediately after construction\n" - "- assignment in an assert statement\n" - "- free() or delete of an invalid memory location\n" - "- bitwise operation with negative right operand\n" - "- cast the return values of getc(),fgetc() and getchar() to character and compare it to EOF\n" - "- race condition with non-interlocked access after InterlockedDecrement() call\n" - "- expression 'x = x++;' depends on order of evaluation of side effects\n" - "- overlapping write of union\n" - - // warning - "- either division by zero or useless condition\n" - "- access of moved or forwarded variable.\n" - "- potentially dangerous C style type cast of pointer/reference to object.\n" - - // performance - "- redundant data copying for const variable\n" - "- subsequent assignment or copying to a variable or buffer\n" - "- passing parameter by value\n" - - // portability - "- Passing NULL pointer to function with variable number of arguments leads to UB.\n" - "- Casting non-zero integer literal in decimal or octal format to pointer.\n" - "- Incorrect zero initialization of unions can lead to access of uninitialized memory.\n" - - // style - "- C-style pointer cast in C++ code\n" - "- casting between incompatible pointer types\n" - "- [Incomplete statement](IncompleteStatement)\n" - "- [check how signed char variables are used](CharVar)\n" - "- variable scope can be limited\n" - "- unusual pointer arithmetic. For example: \"abc\" + 'd'\n" - "- redundant assignment, increment, or bitwise operation in a switch statement\n" - "- redundant strcpy in a switch statement\n" - "- Suspicious case labels in switch()\n" - "- assignment of a variable to itself\n" - "- Comparison of values leading always to true or false\n" - "- Clarify calculation with parentheses\n" - "- suspicious comparison of '\\0' with a char\\* variable\n" - "- duplicate break statement\n" - "- unreachable code\n" - "- testing if unsigned variable is negative/positive\n" - "- Suspicious use of ; at the end of 'if/for/while' statement.\n" - "- Array filled incompletely using memset/memcpy/memmove.\n" - "- NaN (not a number) value used in arithmetic expression.\n" - "- comma in return statement (the comma can easily be misread as a semicolon).\n" - "- prefer erfc, expm1 or log1p to avoid loss of precision.\n" - "- identical code in both branches of if/else or ternary operator.\n" - "- redundant pointer operation on pointer like &\\*some_ptr.\n" - "- find unused 'goto' labels.\n" - "- function declaration and definition argument names different.\n" - "- function declaration and definition argument order different.\n" - "- shadow variable.\n" - "- variable can be declared const.\n" - "- calculating modulo of one.\n" - "- known function argument, suspicious calculation.\n"; - } - bool diag(const Token* tok) { return !mRedundantAssignmentDiag.emplace(tok).second; } diff --git a/lib/checkpostfixoperator.cpp b/lib/checkpostfixoperator.cpp index d771177b2d2..0b02313b672 100644 --- a/lib/checkpostfixoperator.cpp +++ b/lib/checkpostfixoperator.cpp @@ -37,8 +37,7 @@ // CWE ids used static const CWE CWE398(398U); // Indicator of Poor Code Quality - -void CheckPostfixOperator::postfixOperator() +void CheckPostfixOperatorImpl::postfixOperator() { if (!mSettings->severity.isEnabled(Severity::performance)) return; @@ -84,7 +83,7 @@ void CheckPostfixOperator::postfixOperator() //--------------------------------------------------------------------------- -void CheckPostfixOperator::postfixOperatorError(const Token *tok) +void CheckPostfixOperatorImpl::postfixOperatorError(const Token *tok) { reportError(tok, Severity::performance, "postfixOperator", "Prefer prefix ++/-- operators for non-primitive types.\n" @@ -100,12 +99,12 @@ void CheckPostfixOperator::runChecks(const Tokenizer &tokenizer, ErrorLogger *er if (tokenizer.isC()) return; - CheckPostfixOperator checkPostfixOperator(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckPostfixOperatorImpl checkPostfixOperator(&tokenizer, &tokenizer.getSettings(), errorLogger); checkPostfixOperator.postfixOperator(); } void CheckPostfixOperator::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckPostfixOperator c(nullptr, settings, errorLogger); + CheckPostfixOperatorImpl c(nullptr, settings, errorLogger); c.postfixOperatorError(nullptr); } diff --git a/lib/checkpostfixoperator.h b/lib/checkpostfixoperator.h index c9f58a7e143..95ba242381e 100644 --- a/lib/checkpostfixoperator.h +++ b/lib/checkpostfixoperator.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -44,30 +45,28 @@ class CPPCHECKLIB CheckPostfixOperator : public Check { public: /** This constructor is used when registering the CheckPostfixOperator */ - CheckPostfixOperator() : Check(myName()) {} + CheckPostfixOperator() : Check("Using postfix operators") {} private: - /** This constructor is used when running checks. */ - CheckPostfixOperator(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + std::string classInfo() const override { + return "Warn if using postfix operators ++ or -- rather than prefix operator\n"; + } +}; + +class CheckPostfixOperatorImpl : public CheckImpl { +public: + /** This constructor is used when running checks. */ + CheckPostfixOperatorImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** Check postfix operators */ void postfixOperator(); /** Report Error */ void postfixOperatorError(const Token *tok); - - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "Using postfix operators"; - } - - std::string classInfo() const override { - return "Warn if using postfix operators ++ or -- rather than prefix operator\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checksizeof.cpp b/lib/checksizeof.cpp index 134cca92b7f..8e0f247f2c7 100644 --- a/lib/checksizeof.cpp +++ b/lib/checksizeof.cpp @@ -39,7 +39,7 @@ static const CWE CWE467(467U); // Use of sizeof() on a Pointer Type static const CWE CWE682(682U); // Incorrect Calculation //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -void CheckSizeof::checkSizeofForNumericParameter() +void CheckSizeofImpl::checkSizeofForNumericParameter() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -57,7 +57,7 @@ void CheckSizeof::checkSizeofForNumericParameter() } } -void CheckSizeof::sizeofForNumericParameterError(const Token *tok) +void CheckSizeofImpl::sizeofForNumericParameterError(const Token *tok) { reportError(tok, Severity::warning, "sizeofwithnumericparameter", "Suspicious usage of 'sizeof' with a numeric constant as parameter.\n" @@ -69,7 +69,7 @@ void CheckSizeof::sizeofForNumericParameterError(const Token *tok) //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -void CheckSizeof::checkSizeofForArrayParameter() +void CheckSizeofImpl::checkSizeofForArrayParameter() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -94,7 +94,7 @@ void CheckSizeof::checkSizeofForArrayParameter() } } -void CheckSizeof::sizeofForArrayParameterError(const Token *tok) +void CheckSizeofImpl::sizeofForArrayParameterError(const Token *tok) { reportError(tok, Severity::warning, "sizeofwithsilentarraypointer", "Using 'sizeof' on array given as function argument " @@ -110,7 +110,7 @@ void CheckSizeof::sizeofForArrayParameterError(const Token *tok) ); } -void CheckSizeof::checkSizeofForPointerSize() +void CheckSizeofImpl::checkSizeofForPointerSize() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -262,7 +262,7 @@ void CheckSizeof::checkSizeofForPointerSize() } } -void CheckSizeof::sizeofForPointerError(const Token *tok, const std::string &varname) +void CheckSizeofImpl::sizeofForPointerError(const Token *tok, const std::string &varname) { reportError(tok, Severity::warning, "pointerSize", "Size of pointer '" + varname + "' used instead of size of its data.\n" @@ -271,7 +271,7 @@ void CheckSizeof::sizeofForPointerError(const Token *tok, const std::string &var "write 'sizeof(*" + varname + ")'.", CWE467, Certainty::normal); } -void CheckSizeof::divideBySizeofError(const Token *tok, const std::string &memfunc) +void CheckSizeofImpl::divideBySizeofError(const Token *tok, const std::string &memfunc) { reportError(tok, Severity::warning, "sizeofDivisionMemfunc", "Division by result of sizeof(). " + memfunc + "() expects a size in bytes, did you intend to multiply instead?", CWE682, Certainty::normal); @@ -279,7 +279,7 @@ void CheckSizeof::divideBySizeofError(const Token *tok, const std::string &memfu //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -void CheckSizeof::sizeofsizeof() +void CheckSizeofImpl::sizeofsizeof() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -294,7 +294,7 @@ void CheckSizeof::sizeofsizeof() } } -void CheckSizeof::sizeofsizeofError(const Token *tok) +void CheckSizeofImpl::sizeofsizeofError(const Token *tok) { reportError(tok, Severity::warning, "sizeofsizeof", "Calling 'sizeof' on 'sizeof'.\n" @@ -305,7 +305,7 @@ void CheckSizeof::sizeofsizeofError(const Token *tok) //----------------------------------------------------------------------------- -void CheckSizeof::sizeofCalculation() +void CheckSizeofImpl::sizeofCalculation() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -343,7 +343,7 @@ void CheckSizeof::sizeofCalculation() } } -void CheckSizeof::sizeofCalculationError(const Token *tok, bool inconclusive) +void CheckSizeofImpl::sizeofCalculationError(const Token *tok, bool inconclusive) { reportError(tok, Severity::warning, "sizeofCalculation", "Found calculation inside sizeof().", CWE682, inconclusive ? Certainty::inconclusive : Certainty::normal); @@ -351,7 +351,7 @@ void CheckSizeof::sizeofCalculationError(const Token *tok, bool inconclusive) //----------------------------------------------------------------------------- -void CheckSizeof::sizeofFunction() +void CheckSizeofImpl::sizeofFunction() { if (!mSettings->severity.isEnabled(Severity::warning) && !mSettings->isPremiumEnabled("sizeofFunctionCall")) return; @@ -385,7 +385,7 @@ void CheckSizeof::sizeofFunction() } } -void CheckSizeof::sizeofFunctionError(const Token *tok) +void CheckSizeofImpl::sizeofFunctionError(const Token *tok) { reportError(tok, Severity::warning, "sizeofFunctionCall", "Found function call inside sizeof().", CWE682, Certainty::normal); @@ -394,7 +394,7 @@ void CheckSizeof::sizeofFunctionError(const Token *tok) //----------------------------------------------------------------------------- // Check for code like sizeof()*sizeof() or sizeof(ptr)/value //----------------------------------------------------------------------------- -void CheckSizeof::suspiciousSizeofCalculation() +void CheckSizeofImpl::suspiciousSizeofCalculation() { if (!mSettings->severity.isEnabled(Severity::warning) || !mSettings->certainty.isEnabled(Certainty::inconclusive)) return; @@ -424,13 +424,13 @@ void CheckSizeof::suspiciousSizeofCalculation() } } -void CheckSizeof::multiplySizeofError(const Token *tok) +void CheckSizeofImpl::multiplySizeofError(const Token *tok) { reportError(tok, Severity::warning, "multiplySizeof", "Multiplying sizeof() with sizeof() indicates a logic error.", CWE682, Certainty::inconclusive); } -void CheckSizeof::divideSizeofError(const Token *tok) +void CheckSizeofImpl::divideSizeofError(const Token *tok) { reportError(tok, Severity::warning, "divideSizeof", "Division of result of sizeof() on pointer type.\n" @@ -438,7 +438,7 @@ void CheckSizeof::divideSizeofError(const Token *tok) "not the size of the memory area it points to.", CWE682, Certainty::inconclusive); } -void CheckSizeof::sizeofVoid() +void CheckSizeofImpl::sizeofVoid() { if (!mSettings->severity.isEnabled(Severity::portability)) return; @@ -476,21 +476,21 @@ void CheckSizeof::sizeofVoid() } } -void CheckSizeof::sizeofVoidError(const Token *tok) +void CheckSizeofImpl::sizeofVoidError(const Token *tok) { const std::string message = "Behaviour of 'sizeof(void)' is not covered by the ISO C standard."; const std::string verbose = message + " A value for 'sizeof(void)' is defined only as part of a GNU C extension, which defines 'sizeof(void)' to be 1."; reportError(tok, Severity::portability, "sizeofVoid", message + "\n" + verbose, CWE682, Certainty::normal); } -void CheckSizeof::sizeofDereferencedVoidPointerError(const Token *tok, const std::string &varname) +void CheckSizeofImpl::sizeofDereferencedVoidPointerError(const Token *tok, const std::string &varname) { const std::string message = "'*" + varname + "' is of type 'void', the behaviour of 'sizeof(void)' is not covered by the ISO C standard."; const std::string verbose = message + " A value for 'sizeof(void)' is defined only as part of a GNU C extension, which defines 'sizeof(void)' to be 1."; reportError(tok, Severity::portability, "sizeofDereferencedVoidPointer", message + "\n" + verbose, CWE682, Certainty::normal); } -void CheckSizeof::arithOperationsOnVoidPointerError(const Token* tok, const std::string &varname, const std::string &vartype) +void CheckSizeofImpl::arithOperationsOnVoidPointerError(const Token* tok, const std::string &varname, const std::string &vartype) { const std::string message = "'$symbol' is of type '" + vartype + "'. When using void pointers in calculations, the behaviour is undefined."; const std::string verbose = message + " Arithmetic operations on 'void *' is a GNU C extension, which defines the 'sizeof(void)' to be 1."; @@ -499,7 +499,7 @@ void CheckSizeof::arithOperationsOnVoidPointerError(const Token* tok, const std: void CheckSizeof::runChecks(const Tokenizer& tokenizer, ErrorLogger* errorLogger) { - CheckSizeof checkSizeof(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckSizeofImpl checkSizeof(&tokenizer, &tokenizer.getSettings(), errorLogger); // Checks checkSizeof.sizeofsizeof(); @@ -514,7 +514,7 @@ void CheckSizeof::runChecks(const Tokenizer& tokenizer, ErrorLogger* errorLogger void CheckSizeof::getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const { - CheckSizeof c(nullptr, settings, errorLogger); + CheckSizeofImpl c(nullptr, settings, errorLogger); c.sizeofForArrayParameterError(nullptr); c.sizeofForPointerError(nullptr, "varname"); c.divideBySizeofError(nullptr, "memset"); diff --git a/lib/checksizeof.h b/lib/checksizeof.h index 4c10ca88dac..d45a46c5ad6 100644 --- a/lib/checksizeof.h +++ b/lib/checksizeof.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -41,16 +42,33 @@ class Tokenizer; class CPPCHECKLIB CheckSizeof : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckSizeof() : Check(myName()) {} + CheckSizeof() : Check("Sizeof") {} private: - /** @brief This constructor is used when running checks. */ - CheckSizeof(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer& tokenizer, ErrorLogger* errorLogger) override; + void getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const override; + + std::string classInfo() const override { + return "sizeof() usage checks\n" + "- sizeof for array given as function argument\n" + "- sizeof for numeric given as function argument\n" + "- using sizeof(pointer) instead of the size of pointed data\n" + "- look for 'sizeof sizeof ..'\n" + "- look for calculations inside sizeof()\n" + "- look for function calls inside sizeof()\n" + "- look for suspicious calculations with sizeof()\n" + "- using 'sizeof(void)' which is undefined\n"; + } +}; + +class CheckSizeofImpl : public CheckImpl { +public: + /** @brief This constructor is used when running checks. */ + CheckSizeofImpl(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** @brief %Check for 'sizeof sizeof ..' */ void sizeofsizeof(); @@ -88,24 +106,6 @@ class CPPCHECKLIB CheckSizeof : public Check { void sizeofVoidError(const Token *tok); void sizeofDereferencedVoidPointerError(const Token *tok, const std::string &varname); void arithOperationsOnVoidPointerError(const Token* tok, const std::string &varname, const std::string &vartype); - - void getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const override; - - static std::string myName() { - return "Sizeof"; - } - - std::string classInfo() const override { - return "sizeof() usage checks\n" - "- sizeof for array given as function argument\n" - "- sizeof for numeric given as function argument\n" - "- using sizeof(pointer) instead of the size of pointed data\n" - "- look for 'sizeof sizeof ..'\n" - "- look for calculations inside sizeof()\n" - "- look for function calls inside sizeof()\n" - "- look for suspicious calculations with sizeof()\n" - "- using 'sizeof(void)' which is undefined\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index b1543f4af37..616f8603afe 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -127,7 +127,7 @@ static const Token* getContainerFromSize(const Library::Container* container, co return nullptr; } -void CheckStl::outOfBounds() +void CheckStlImpl::outOfBounds() { logChecker("CheckStl::outOfBounds"); @@ -215,7 +215,7 @@ static std::string indexValueString(const ValueFlow::Value& indexValue, const st return indexString; } -void CheckStl::outOfBoundsError(const Token *tok, const std::string &containerName, const ValueFlow::Value *containerSize, const std::string &index, const ValueFlow::Value *indexValue) +void CheckStlImpl::outOfBoundsError(const Token *tok, const std::string &containerName, const ValueFlow::Value *containerSize, const std::string &index, const ValueFlow::Value *indexValue) { // Do not warn if both the container size and index value are possible if (containerSize && indexValue && containerSize->isPossible() && indexValue->isPossible()) @@ -274,7 +274,7 @@ void CheckStl::outOfBoundsError(const Token *tok, const std::string &containerNa (containerSize && containerSize->isInconclusive()) || (indexValue && indexValue->isInconclusive()) ? Certainty::inconclusive : Certainty::normal); } -bool CheckStl::isContainerSize(const Token *containerToken, const Token *expr) const +bool CheckStlImpl::isContainerSize(const Token *containerToken, const Token *expr) const { if (!Token::simpleMatch(expr, "( )")) return false; @@ -285,7 +285,7 @@ bool CheckStl::isContainerSize(const Token *containerToken, const Token *expr) c return containerToken->valueType()->container->getYield(expr->strAt(-1)) == Library::Container::Yield::SIZE; } -bool CheckStl::isContainerSizeGE(const Token * containerToken, const Token *expr) const +bool CheckStlImpl::isContainerSizeGE(const Token * containerToken, const Token *expr) const { if (!expr) return false; @@ -314,7 +314,7 @@ bool CheckStl::isContainerSizeGE(const Token * containerToken, const Token *expr return false; } -void CheckStl::outOfBoundsIndexExpression() +void CheckStlImpl::outOfBoundsIndexExpression() { logChecker("CheckStl::outOfBoundsIndexExpression"); for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) { @@ -334,7 +334,7 @@ void CheckStl::outOfBoundsIndexExpression() } } -void CheckStl::outOfBoundsIndexExpressionError(const Token *tok, const Token *index) +void CheckStlImpl::outOfBoundsIndexExpressionError(const Token *tok, const Token *index) { const std::string varname = tok ? tok->str() : std::string("var"); const std::string i = index ? index->expressionString() : (varname + ".size()"); @@ -352,12 +352,12 @@ void CheckStl::outOfBoundsIndexExpressionError(const Token *tok, const Token *in // Error message for bad iterator usage.. -void CheckStl::invalidIteratorError(const Token *tok, const std::string &iteratorName) +void CheckStlImpl::invalidIteratorError(const Token *tok, const std::string &iteratorName) { reportError(tok, Severity::error, "invalidIterator1", "$symbol:"+iteratorName+"\nInvalid iterator: $symbol", CWE664, Certainty::normal); } -void CheckStl::iteratorsError(const Token* tok, const std::string& containerName1, const std::string& containerName2) +void CheckStlImpl::iteratorsError(const Token* tok, const std::string& containerName1, const std::string& containerName2) { reportError(tok, Severity::error, "iterators1", "$symbol:" + containerName1 + "\n" @@ -365,7 +365,7 @@ void CheckStl::iteratorsError(const Token* tok, const std::string& containerName "Same iterator is used with different containers '" + containerName1 + "' and '" + containerName2 + "'.", CWE664, Certainty::normal); } -void CheckStl::iteratorsError(const Token* tok, const Token* containerTok, const std::string& containerName) +void CheckStlImpl::iteratorsError(const Token* tok, const Token* containerTok, const std::string& containerName) { std::list callstack = { tok, containerTok }; reportError(callstack, @@ -379,7 +379,7 @@ void CheckStl::iteratorsError(const Token* tok, const Token* containerTok, const } // Error message used when dereferencing an iterator that has been erased.. -void CheckStl::dereferenceErasedError(const Token *erased, const Token* deref, const std::string &itername, bool inconclusive) +void CheckStlImpl::dereferenceErasedError(const Token *erased, const Token* deref, const std::string &itername, bool inconclusive) { if (erased) { std::list callstack = { deref, erased }; @@ -449,7 +449,7 @@ static bool isVector(const Token* tok) return Token::simpleMatch(decltok, "std :: vector"); } -void CheckStl::iterators() +void CheckStlImpl::iterators() { logChecker("CheckStl::iterators"); @@ -634,7 +634,7 @@ void CheckStl::iterators() } } -void CheckStl::mismatchingContainerIteratorError(const Token* containerTok, const Token* iterTok, const Token* containerTok2) +void CheckStlImpl::mismatchingContainerIteratorError(const Token* containerTok, const Token* iterTok, const Token* containerTok2) { const std::string container(containerTok ? containerTok->expressionString() : std::string("v1")); const std::string container2(containerTok2 ? containerTok2->expressionString() : std::string("v2")); @@ -648,7 +648,7 @@ void CheckStl::mismatchingContainerIteratorError(const Token* containerTok, cons } // Error message for bad iterator usage.. -void CheckStl::mismatchingContainersError(const Token* tok1, const Token* tok2) +void CheckStlImpl::mismatchingContainersError(const Token* tok1, const Token* tok2) { const std::string expr1(tok1 ? tok1->expressionString() : std::string("v1")); const std::string expr2(tok2 ? tok2->expressionString() : std::string("v2")); @@ -660,7 +660,7 @@ void CheckStl::mismatchingContainersError(const Token* tok1, const Token* tok2) Certainty::normal); } -void CheckStl::mismatchingContainerExpressionError(const Token *tok1, const Token *tok2) +void CheckStlImpl::mismatchingContainerExpressionError(const Token *tok1, const Token *tok2) { const std::string expr1(tok1 ? tok1->expressionString() : std::string("v1")); const std::string expr2(tok2 ? tok2->expressionString() : std::string("v2")); @@ -669,7 +669,7 @@ void CheckStl::mismatchingContainerExpressionError(const Token *tok1, const Toke expr1 + "' and '" + expr2 + "' are used together.", CWE664, Certainty::normal); } -void CheckStl::sameIteratorExpressionError(const Token *tok) +void CheckStlImpl::sameIteratorExpressionError(const Token *tok) { reportError(tok, Severity::style, "sameIteratorExpression", "Same iterators expression are used for algorithm.", CWE664, Certainty::normal); } @@ -754,7 +754,7 @@ static ValueFlow::Value getLifetimeIteratorValue(const Token* tok, MathLib::bigi return ValueFlow::Value{}; } -bool CheckStl::checkIteratorPair(const Token* tok1, const Token* tok2) +bool CheckStlImpl::checkIteratorPair(const Token* tok1, const Token* tok2) { if (!tok1) return false; @@ -806,7 +806,7 @@ namespace { }; } -void CheckStl::mismatchingContainers() +void CheckStlImpl::mismatchingContainers() { logChecker("CheckStl::misMatchingContainers"); @@ -866,7 +866,7 @@ void CheckStl::mismatchingContainers() } } -void CheckStl::mismatchingContainerIterator() +void CheckStlImpl::mismatchingContainerIterator() { logChecker("CheckStl::misMatchingContainerIterator"); @@ -1118,7 +1118,7 @@ static const Token* endOfExpression(const Token* tok) return endToken; } -void CheckStl::invalidContainer() +void CheckStlImpl::invalidContainer() { logChecker("CheckStl::invalidContainer"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -1232,7 +1232,7 @@ void CheckStl::invalidContainer() } } -void CheckStl::invalidContainerLoopError(const Token* tok, const Token* loopTok, ErrorPath errorPath) +void CheckStlImpl::invalidContainerLoopError(const Token* tok, const Token* loopTok, ErrorPath errorPath) { const std::string method = tok ? tok->str() : "erase"; errorPath.emplace_back(loopTok, "Iterating container here."); @@ -1247,7 +1247,7 @@ void CheckStl::invalidContainerLoopError(const Token* tok, const Token* loopTok, reportError(std::move(errorPath), Severity::error, "invalidContainerLoop", msg, CWE664, Certainty::normal); } -void CheckStl::invalidContainerError(const Token *tok, const ValueFlow::Value *val, ErrorPath errorPath) +void CheckStlImpl::invalidContainerError(const Token *tok, const ValueFlow::Value *val, ErrorPath errorPath) { const bool inconclusive = val ? val->isInconclusive() : false; if (val) @@ -1257,7 +1257,7 @@ void CheckStl::invalidContainerError(const Token *tok, const ValueFlow::Value *v reportError(std::move(errorPath), Severity::error, "invalidContainer", msg + " that may be invalid.", CWE664, inconclusive ? Certainty::inconclusive : Certainty::normal); } -void CheckStl::invalidContainerReferenceError(const Token* tok, const Token* contTok, ErrorPath errorPath) +void CheckStlImpl::invalidContainerReferenceError(const Token* tok, const Token* contTok, ErrorPath errorPath) { std::string name = contTok ? contTok->expressionString() : "x"; std::string msg = "Reference to " + name; @@ -1265,7 +1265,7 @@ void CheckStl::invalidContainerReferenceError(const Token* tok, const Token* con reportError(std::move(errorPath), Severity::error, "invalidContainerReference", msg + " that may be invalid.", CWE664, Certainty::normal); } -void CheckStl::stlOutOfBounds() +void CheckStlImpl::stlOutOfBounds() { logChecker("CheckStl::stlOutOfBounds"); @@ -1351,7 +1351,7 @@ void CheckStl::stlOutOfBounds() } } -void CheckStl::stlOutOfBoundsError(const Token *tok, const std::string &num, const std::string &var, bool at) +void CheckStlImpl::stlOutOfBoundsError(const Token *tok, const std::string &num, const std::string &var, bool at) { if (at) reportError(tok, Severity::error, "stlOutOfBounds", "$symbol:" + var + "\nWhen " + num + "==$symbol.size(), $symbol.at(" + num + ") is out of bounds.", CWE788, Certainty::normal); @@ -1359,7 +1359,7 @@ void CheckStl::stlOutOfBoundsError(const Token *tok, const std::string &num, con reportError(tok, Severity::error, "stlOutOfBounds", "$symbol:" + var + "\nWhen " + num + "==$symbol.size(), $symbol[" + num + "] is out of bounds.", CWE788, Certainty::normal); } -void CheckStl::negativeIndex() +void CheckStlImpl::negativeIndex() { logChecker("CheckStl::negativeIndex"); @@ -1383,7 +1383,7 @@ void CheckStl::negativeIndex() } } -void CheckStl::negativeIndexError(const Token *tok, const ValueFlow::Value &index) +void CheckStlImpl::negativeIndexError(const Token *tok, const ValueFlow::Value &index) { ErrorPath errorPath = getErrorPath(tok, &index, "Negative array index"); std::ostringstream errmsg; @@ -1397,7 +1397,7 @@ void CheckStl::negativeIndexError(const Token *tok, const ValueFlow::Value &inde reportError(std::move(errorPath), severity, "negativeContainerIndex", errmsg.str(), CWE786, certainty); } -void CheckStl::erase() +void CheckStlImpl::erase() { logChecker("CheckStl::erase"); @@ -1418,7 +1418,7 @@ void CheckStl::erase() } } -void CheckStl::eraseCheckLoopVar(const Scope &scope, const Variable *var) +void CheckStlImpl::eraseCheckLoopVar(const Scope &scope, const Variable *var) { bool inconclusiveType=false; if (!isIterator(var, inconclusiveType)) @@ -1462,7 +1462,7 @@ void CheckStl::eraseCheckLoopVar(const Scope &scope, const Variable *var) } } -void CheckStl::stlBoundaries() +void CheckStlImpl::stlBoundaries() { logChecker("CheckStl::stlBoundaries"); @@ -1487,7 +1487,7 @@ void CheckStl::stlBoundaries() } // Error message for bad boundary usage.. -void CheckStl::stlBoundariesError(const Token *tok) +void CheckStlImpl::stlBoundariesError(const Token *tok) { reportError(tok, Severity::error, "stlBoundaries", "Dangerous comparison using operator< on iterator.\n" @@ -1516,7 +1516,7 @@ static bool if_findCompare(const Token * const tokBack, bool stdStringLike) return false; } -void CheckStl::if_find() +void CheckStlImpl::if_find() { const bool printWarning = mSettings->severity.isEnabled(Severity::warning); const bool printPerformance = mSettings->severity.isEnabled(Severity::performance); @@ -1593,7 +1593,7 @@ void CheckStl::if_find() } -void CheckStl::if_findError(const Token *tok, bool str) +void CheckStlImpl::if_findError(const Token *tok, bool str) { if (str && mSettings->standards.cpp >= Standards::CPP20) reportError(tok, Severity::performance, "stlIfStrFind", @@ -1684,7 +1684,7 @@ static const Token *findInsertValue(const Token *tok, const Token *containerTok, return nullptr; } -void CheckStl::checkFindInsert() +void CheckStlImpl::checkFindInsert() { if (!mSettings->severity.isEnabled(Severity::performance)) return; @@ -1730,7 +1730,7 @@ void CheckStl::checkFindInsert() } } -void CheckStl::checkFindInsertError(const Token *tok) +void CheckStlImpl::checkFindInsertError(const Token *tok) { std::string replaceExpr; if (tok && Token::simpleMatch(tok->astParent(), "=") && tok == tok->astParent()->astOperand2() && Token::simpleMatch(tok->astParent()->astOperand1(), "[")) { @@ -1762,7 +1762,7 @@ static bool isCpp03ContainerSizeSlow(const Token *tok) return var && var->isStlType("list"); } -void CheckStl::size() +void CheckStlImpl::size() { if (!mSettings->severity.isEnabled(Severity::performance)) return; @@ -1811,7 +1811,7 @@ void CheckStl::size() } } -void CheckStl::sizeError(const Token *tok) +void CheckStlImpl::sizeError(const Token *tok) { const std::string varname = tok ? tok->str() : std::string("list"); reportError(tok, Severity::performance, "stlSize", @@ -1823,7 +1823,7 @@ void CheckStl::sizeError(const Token *tok) "guaranteed to take constant time.", CWE398, Certainty::normal); } -void CheckStl::redundantCondition() +void CheckStlImpl::redundantCondition() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("redundantIfRemove")) return; @@ -1856,7 +1856,7 @@ void CheckStl::redundantCondition() } } -void CheckStl::redundantIfRemoveError(const Token *tok) +void CheckStlImpl::redundantIfRemoveError(const Token *tok) { reportError(tok, Severity::style, "redundantIfRemove", "Redundant checking of STL container element existence before removing it.\n" @@ -1864,7 +1864,7 @@ void CheckStl::redundantIfRemoveError(const Token *tok) "It is safe to call the remove method on a non-existing element.", CWE398, Certainty::normal); } -void CheckStl::missingComparison() +void CheckStlImpl::missingComparison() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -1928,7 +1928,7 @@ void CheckStl::missingComparison() } } -void CheckStl::missingComparisonError(const Token *incrementToken1, const Token *incrementToken2) +void CheckStlImpl::missingComparisonError(const Token *incrementToken1, const Token *incrementToken2) { std::list callstack = { incrementToken1,incrementToken2 }; @@ -2024,7 +2024,7 @@ namespace { }; } -void CheckStl::string_c_str() +void CheckStlImpl::string_c_str() { const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); const bool printPerformance = mSettings->severity.isEnabled(Severity::performance); @@ -2220,25 +2220,25 @@ void CheckStl::string_c_str() } } -void CheckStl::string_c_strThrowError(const Token* tok) +void CheckStlImpl::string_c_strThrowError(const Token* tok) { reportError(tok, Severity::error, "stlcstrthrow", "Dangerous usage of c_str(). The value returned by c_str() is invalid after throwing exception.\n" "Dangerous usage of c_str(). The string is destroyed after the c_str() call so the thrown pointer is invalid."); } -void CheckStl::string_c_strError(const Token* tok) +void CheckStlImpl::string_c_strError(const Token* tok) { reportError(tok, Severity::error, "stlcstr", "Dangerous usage of c_str(). The value returned by c_str() is invalid after this call.\n" "Dangerous usage of c_str(). The c_str() return value is only valid until its string is deleted.", CWE664, Certainty::normal); } -void CheckStl::string_c_strReturn(const Token* tok) +void CheckStlImpl::string_c_strReturn(const Token* tok) { reportError(tok, Severity::performance, "stlcstrReturn", "Returning the result of c_str() in a function that returns std::string is slow and redundant.\n" "The conversion from const char* as returned by c_str() to std::string creates an unnecessary string copy. Solve that by directly returning the string.", CWE704, Certainty::normal); } -void CheckStl::string_c_strParam(const Token* tok, nonneg int number, const std::string& argtype) +void CheckStlImpl::string_c_strParam(const Token* tok, nonneg int number, const std::string& argtype) { std::ostringstream oss; oss << "Passing the result of c_str() to a function that takes " << argtype << " as argument no. " << number << " is slow and redundant.\n" @@ -2246,28 +2246,28 @@ void CheckStl::string_c_strParam(const Token* tok, nonneg int number, const std: reportError(tok, Severity::performance, "stlcstrParam", oss.str(), CWE704, Certainty::normal); } -void CheckStl::string_c_strConstructor(const Token* tok, const std::string& argtype) +void CheckStlImpl::string_c_strConstructor(const Token* tok, const std::string& argtype) { std::string msg = "Constructing a " + argtype + " from the result of c_str() is slow and redundant.\n" "Constructing a " + argtype + " from const char* requires a call to strlen(). Solve that by directly passing the string."; reportError(tok, Severity::performance, "stlcstrConstructor", msg, CWE704, Certainty::normal); } -void CheckStl::string_c_strAssignment(const Token* tok, const std::string& argtype) +void CheckStlImpl::string_c_strAssignment(const Token* tok, const std::string& argtype) { std::string msg = "Assigning the result of c_str() to a " + argtype + " is slow and redundant.\n" "Assigning a const char* to a " + argtype + " requires a call to strlen(). Solve that by directly assigning the string."; reportError(tok, Severity::performance, "stlcstrAssignment", msg, CWE704, Certainty::normal); } -void CheckStl::string_c_strConcat(const Token* tok) +void CheckStlImpl::string_c_strConcat(const Token* tok) { std::string msg = "Concatenating the result of c_str() and a std::string is slow and redundant.\n" "Concatenating a const char* with a std::string requires a call to strlen(). Solve that by directly concatenating the strings."; reportError(tok, Severity::performance, "stlcstrConcat", msg, CWE704, Certainty::normal); } -void CheckStl::string_c_strStream(const Token* tok) +void CheckStlImpl::string_c_strStream(const Token* tok) { std::string msg = "Passing the result of c_str() to a stream is slow and redundant.\n" "Passing a const char* to a stream requires a call to strlen(). Solve that by directly passing the string."; @@ -2288,7 +2288,7 @@ namespace { } -void CheckStl::uselessCalls() +void CheckStlImpl::uselessCalls() { const bool printPerformance = mSettings->severity.isEnabled(Severity::performance); const bool printWarning = mSettings->severity.isEnabled(Severity::warning); @@ -2349,7 +2349,7 @@ void CheckStl::uselessCalls() } -void CheckStl::uselessCallsReturnValueError(const Token *tok, const std::string &varname, const std::string &function) +void CheckStlImpl::uselessCallsReturnValueError(const Token *tok, const std::string &varname, const std::string &function) { std::ostringstream errmsg; errmsg << "$symbol:" << varname << '\n'; @@ -2362,7 +2362,7 @@ void CheckStl::uselessCallsReturnValueError(const Token *tok, const std::string reportError(tok, Severity::warning, "uselessCallsCompare", errmsg.str(), CWE628, Certainty::normal); } -void CheckStl::uselessCallsSwapError(const Token *tok, const std::string &varname) +void CheckStlImpl::uselessCallsSwapError(const Token *tok, const std::string &varname) { reportError(tok, Severity::performance, "uselessCallsSwap", "$symbol:" + varname + "\n" @@ -2372,7 +2372,7 @@ void CheckStl::uselessCallsSwapError(const Token *tok, const std::string &varnam "code is inefficient. Is the object or the parameter wrong here?", CWE628, Certainty::normal); } -void CheckStl::uselessCallsSubstrError(const Token *tok, SubstrErrorType type) +void CheckStlImpl::uselessCallsSubstrError(const Token *tok, SubstrErrorType type) { std::string msg = "Ineffective call of function 'substr' because "; switch (type) { @@ -2392,19 +2392,19 @@ void CheckStl::uselessCallsSubstrError(const Token *tok, SubstrErrorType type) reportError(tok, Severity::performance, "uselessCallsSubstr", msg, CWE398, Certainty::normal); } -void CheckStl::uselessCallsConstructorError(const Token *tok) +void CheckStlImpl::uselessCallsConstructorError(const Token *tok) { const std::string container = tok ? tok->str() : ""; const std::string msg = "Inefficient constructor call: container '" + container + "' is assigned a partial copy of itself. Use erase() or resize() instead."; reportError(tok, Severity::performance, "uselessCallsConstructor", msg, CWE398, Certainty::normal); } -void CheckStl::uselessCallsEmptyError(const Token *tok) +void CheckStlImpl::uselessCallsEmptyError(const Token *tok) { reportError(tok, Severity::warning, "uselessCallsEmpty", "Ineffective call of function 'empty()'. Did you intend to call 'clear()' instead?", CWE398, Certainty::normal); } -void CheckStl::uselessCallsRemoveError(const Token *tok, const std::string& function) +void CheckStlImpl::uselessCallsRemoveError(const Token *tok, const std::string& function) { reportError(tok, Severity::warning, "uselessCallsRemove", "$symbol:" + function + "\n" @@ -2415,7 +2415,7 @@ void CheckStl::uselessCallsRemoveError(const Token *tok, const std::string& func // Check for iterators being dereferenced before being checked for validity. // E.g. if (*i && i != str.end()) { } -void CheckStl::checkDereferenceInvalidIterator() +void CheckStlImpl::checkDereferenceInvalidIterator() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -2479,7 +2479,7 @@ void CheckStl::checkDereferenceInvalidIterator() } -void CheckStl::checkDereferenceInvalidIterator2() +void CheckStlImpl::checkDereferenceInvalidIterator2() { const bool printInconclusive = (mSettings->certainty.isEnabled(Certainty::inconclusive)); @@ -2575,7 +2575,7 @@ void CheckStl::checkDereferenceInvalidIterator2() } } -void CheckStl::dereferenceInvalidIteratorError(const Token* tok, const ValueFlow::Value *value, bool inconclusive) +void CheckStlImpl::dereferenceInvalidIteratorError(const Token* tok, const ValueFlow::Value *value, bool inconclusive) { const std::string& varname = tok ? tok->expressionString() : "var"; const std::string errmsgcond("$symbol:" + varname + '\n' + ValueFlow::eitherTheConditionIsRedundant(value ? value->condition : nullptr) + " or there is possible dereference of an invalid iterator: $symbol."); @@ -2604,7 +2604,7 @@ void CheckStl::dereferenceInvalidIteratorError(const Token* tok, const ValueFlow } } -void CheckStl::dereferenceInvalidIteratorError(const Token* deref, const std::string &iterName) +void CheckStlImpl::dereferenceInvalidIteratorError(const Token* deref, const std::string &iterName) { reportError(deref, Severity::warning, "derefInvalidIterator", @@ -2613,7 +2613,7 @@ void CheckStl::dereferenceInvalidIteratorError(const Token* deref, const std::st "Possible dereference of an invalid iterator: $symbol. Make sure to check that the iterator is valid before dereferencing it - not after.", CWE825, Certainty::normal); } -void CheckStl::useStlAlgorithmError(const Token *tok, const std::string &algoName) +void CheckStlImpl::useStlAlgorithmError(const Token *tok, const std::string &algoName) { reportError(tok, Severity::style, "useStlAlgorithm", "Consider using " + algoName + " algorithm instead of a raw loop.", CWE398, Certainty::normal); @@ -3001,7 +3001,7 @@ namespace { }; } // namespace -void CheckStl::useStlAlgorithm() +void CheckStlImpl::useStlAlgorithm() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("useStlAlgorithm")) return; @@ -3237,7 +3237,7 @@ void CheckStl::useStlAlgorithm() } } -void CheckStl::knownEmptyContainerError(const Token *tok, const std::string& algo) +void CheckStlImpl::knownEmptyContainerError(const Token *tok, const std::string& algo) { const std::string var = tok ? tok->expressionString() : std::string("var"); @@ -3268,7 +3268,7 @@ static bool isKnownEmptyContainer(const Token* tok) }); } -void CheckStl::knownEmptyContainer() +void CheckStlImpl::knownEmptyContainer() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("knownEmptyContainer")) return; @@ -3311,7 +3311,7 @@ void CheckStl::knownEmptyContainer() } } -void CheckStl::eraseIteratorOutOfBoundsError(const Token *ftok, const Token* itertok, const ValueFlow::Value* val) +void CheckStlImpl::eraseIteratorOutOfBoundsError(const Token *ftok, const Token* itertok, const ValueFlow::Value* val) { if (!ftok || !itertok || !val) { reportError(ftok, Severity::error, "eraseIteratorOutOfBounds", @@ -3356,7 +3356,7 @@ static const ValueFlow::Value* getOOBIterValue(const Token* tok, const ValueFlow return it != tok->values().end() ? &*it : nullptr; } -void CheckStl::eraseIteratorOutOfBounds() +void CheckStlImpl::eraseIteratorOutOfBounds() { logChecker("CheckStl::eraseIteratorOutOfBounds"); for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) { @@ -3403,21 +3403,21 @@ static bool isLocalMutex(const Variable* var, const Scope* scope) return !var->isReference() && !var->isRValueReference() && !var->isStatic() && var->scope() == scope; } -void CheckStl::globalLockGuardError(const Token* tok) +void CheckStlImpl::globalLockGuardError(const Token* tok) { reportError(tok, Severity::warning, "globalLockGuard", "Lock guard is defined globally. Lock guards are intended to be local. A global lock guard could lead to a deadlock since it won't unlock until the end of the program.", CWE833, Certainty::normal); } -void CheckStl::localMutexError(const Token* tok) +void CheckStlImpl::localMutexError(const Token* tok) { reportError(tok, Severity::warning, "localMutex", "The lock is ineffective because the mutex is locked at the same scope as the mutex itself.", CWE667, Certainty::normal); } -void CheckStl::checkMutexes() +void CheckStlImpl::checkMutexes() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -3460,7 +3460,7 @@ void CheckStl::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) return; } - CheckStl checkStl(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckStlImpl checkStl(&tokenizer, &tokenizer.getSettings(), errorLogger); checkStl.erase(); checkStl.if_find(); checkStl.checkFindInsert(); @@ -3493,7 +3493,7 @@ void CheckStl::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) void CheckStl::getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const { - CheckStl c(nullptr, settings, errorLogger); + CheckStlImpl c(nullptr, settings, errorLogger); c.outOfBoundsError(nullptr, "container", nullptr, "x", nullptr); c.invalidIteratorError(nullptr, "iterator"); c.iteratorsError(nullptr, "container1", "container2"); @@ -3525,7 +3525,7 @@ void CheckStl::getErrorMessages(ErrorLogger* errorLogger, const Settings* settin c.redundantIfRemoveError(nullptr); c.uselessCallsReturnValueError(nullptr, "str", "find"); c.uselessCallsSwapError(nullptr, "str"); - c.uselessCallsSubstrError(nullptr, SubstrErrorType::COPY); + c.uselessCallsSubstrError(nullptr, CheckStlImpl::SubstrErrorType::COPY); c.uselessCallsConstructorError(nullptr); c.uselessCallsEmptyError(nullptr); c.uselessCallsRemoveError(nullptr, "remove"); diff --git a/lib/checkstl.h b/lib/checkstl.h index 03a634f1ed1..eea42f145f5 100644 --- a/lib/checkstl.h +++ b/lib/checkstl.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include "errortypes.h" @@ -48,16 +49,43 @@ namespace ValueFlow class CPPCHECKLIB CheckStl : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckStl() : Check(myName()) {} + CheckStl() : Check("STL usage") {} private: - /** This constructor is used when running checks. */ - CheckStl(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - /** run checks, the token list is not simplified */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const override; + + std::string classInfo() const override { + return "Check for invalid usage of STL:\n" + "- out of bounds errors\n" + "- misuse of iterators when iterating through a container\n" + "- mismatching containers in calls\n" + "- same iterators in calls\n" + "- dereferencing an erased iterator\n" + "- for vectors: using iterator/pointer after push_back has been used\n" + "- optimisation: use empty() instead of size() to guarantee fast code\n" + "- suspicious condition when using find\n" + "- unnecessary searching in associative containers\n" + "- redundant condition\n" + "- common mistakes when using string::c_str()\n" + "- useless calls of string and STL functions\n" + "- dereferencing an invalid iterator\n" + "- erasing an iterator that is out of bounds\n" + "- reading from empty STL container\n" + "- iterating over an empty STL container\n" + "- consider using an STL algorithm instead of raw loop\n" + "- incorrect locking with mutex\n"; + } +}; + +class CheckStlImpl : public CheckImpl { +public: + /** This constructor is used when running checks. */ + CheckStlImpl(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** Accessing container out of bounds using ValueFlow */ void outOfBounds(); @@ -209,34 +237,6 @@ class CPPCHECKLIB CheckStl : public Check { void globalLockGuardError(const Token *tok); void localMutexError(const Token *tok); - - void getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const override; - - static std::string myName() { - return "STL usage"; - } - - std::string classInfo() const override { - return "Check for invalid usage of STL:\n" - "- out of bounds errors\n" - "- misuse of iterators when iterating through a container\n" - "- mismatching containers in calls\n" - "- same iterators in calls\n" - "- dereferencing an erased iterator\n" - "- for vectors: using iterator/pointer after push_back has been used\n" - "- optimisation: use empty() instead of size() to guarantee fast code\n" - "- suspicious condition when using find\n" - "- unnecessary searching in associative containers\n" - "- redundant condition\n" - "- common mistakes when using string::c_str()\n" - "- useless calls of string and STL functions\n" - "- dereferencing an invalid iterator\n" - "- erasing an iterator that is out of bounds\n" - "- reading from empty STL container\n" - "- iterating over an empty STL container\n" - "- consider using an STL algorithm instead of raw loop\n" - "- incorrect locking with mutex\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkstring.cpp b/lib/checkstring.cpp index 580597bb10d..916885e094a 100644 --- a/lib/checkstring.cpp +++ b/lib/checkstring.cpp @@ -47,7 +47,7 @@ static const CWE CWE758(758U); // Reliance on Undefined, Unspecified, or Imple //--------------------------------------------------------------------------- // Writing string literal is UB //--------------------------------------------------------------------------- -void CheckString::stringLiteralWrite() +void CheckStringImpl::stringLiteralWrite() { logChecker("CheckString::stringLiteralWrite"); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -66,7 +66,7 @@ void CheckString::stringLiteralWrite() } } -void CheckString::stringLiteralWriteError(const Token *tok, const Token *strValue) +void CheckStringImpl::stringLiteralWriteError(const Token *tok, const Token *strValue) { std::list callstack{ tok }; if (strValue) @@ -89,7 +89,7 @@ void CheckString::stringLiteralWriteError(const Token *tok, const Token *strValu // Check for string comparison involving two static strings. // if(strcmp("00FF00","00FF00")==0) // <- statement is always true //--------------------------------------------------------------------------- -void CheckString::checkAlwaysTrueOrFalseStringCompare() +void CheckStringImpl::checkAlwaysTrueOrFalseStringCompare() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -133,7 +133,7 @@ void CheckString::checkAlwaysTrueOrFalseStringCompare() } } -void CheckString::alwaysTrueFalseStringCompareError(const Token *tok, const std::string& str1, const std::string& str2) +void CheckStringImpl::alwaysTrueFalseStringCompareError(const Token *tok, const std::string& str1, const std::string& str2) { constexpr std::size_t stringLen = 10; const std::string string1 = (str1.size() < stringLen) ? str1 : (str1.substr(0, stringLen-2) + ".."); @@ -145,7 +145,7 @@ void CheckString::alwaysTrueFalseStringCompareError(const Token *tok, const std: "Therefore the comparison is unnecessary and looks suspicious.", (str1==str2)?CWE571:CWE570, Certainty::normal); } -void CheckString::alwaysTrueStringVariableCompareError(const Token *tok, const std::string& str1, const std::string& str2) +void CheckStringImpl::alwaysTrueStringVariableCompareError(const Token *tok, const std::string& str1, const std::string& str2) { reportError(tok, Severity::warning, "stringCompare", "Comparison of identical string variables.\n" @@ -158,7 +158,7 @@ void CheckString::alwaysTrueStringVariableCompareError(const Token *tok, const s // Detect "str == '\0'" where "*str == '\0'" is correct. // Comparing char* with each other instead of using strcmp() //----------------------------------------------------------------------------- -void CheckString::checkSuspiciousStringCompare() +void CheckStringImpl::checkSuspiciousStringCompare() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -197,14 +197,14 @@ void CheckString::checkSuspiciousStringCompare() } } -void CheckString::suspiciousStringCompareError(const Token* tok, const std::string& var, bool isLong) +void CheckStringImpl::suspiciousStringCompareError(const Token* tok, const std::string& var, bool isLong) { const std::string cmpFunc = isLong ? "wcscmp" : "strcmp"; reportError(tok, Severity::warning, "literalWithCharPtrCompare", "$symbol:" + var + "\nString literal compared with variable '$symbol'. Did you intend to use " + cmpFunc + "() instead?", CWE595, Certainty::normal); } -void CheckString::suspiciousStringCompareError_char(const Token* tok, const std::string& var) +void CheckStringImpl::suspiciousStringCompareError_char(const Token* tok, const std::string& var) { reportError(tok, Severity::warning, "charLiteralWithCharPtrCompare", "$symbol:" + var + "\nChar literal compared with pointer '$symbol'. Did you intend to dereference it?", CWE595, Certainty::normal); @@ -220,7 +220,7 @@ static bool isChar(const Variable* var) return (var && !var->isPointer() && !var->isArray() && (var->typeStartToken()->str() == "char" || var->typeStartToken()->str() == "wchar_t")); } -void CheckString::strPlusChar() +void CheckStringImpl::strPlusChar() { logChecker("CheckString::strPlusChar"); const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -236,7 +236,7 @@ void CheckString::strPlusChar() } } -void CheckString::strPlusCharError(const Token *tok) +void CheckStringImpl::strPlusCharError(const Token *tok) { std::string charType = "char"; if (tok && tok->astOperand2() && tok->astOperand2()->variable()) @@ -272,7 +272,7 @@ static bool isMacroUsage(const Token* tok) // Implicit casts of string literals to bool // Comparing string literal with strlen() with wrong length //--------------------------------------------------------------------------- -void CheckString::checkIncorrectStringCompare() +void CheckStringImpl::checkIncorrectStringCompare() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -321,12 +321,12 @@ void CheckString::checkIncorrectStringCompare() } } -void CheckString::incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string) +void CheckStringImpl::incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string) { reportError(tok, Severity::warning, "incorrectStringCompare", "$symbol:" + func + "\nString literal " + string + " doesn't match length argument for $symbol().", CWE570, Certainty::normal); } -void CheckString::incorrectStringBooleanError(const Token *tok, const std::string& string) +void CheckStringImpl::incorrectStringBooleanError(const Token *tok, const std::string& string) { const bool charLiteral = isCharLiteral(string); const std::string literalType = charLiteral ? "char" : "string"; @@ -341,7 +341,7 @@ void CheckString::incorrectStringBooleanError(const Token *tok, const std::strin // always true: strcmp(str,"a")==0 || strcmp(str,"b") // TODO: Library configuration for string comparison functions //--------------------------------------------------------------------------- -void CheckString::overlappingStrcmp() +void CheckStringImpl::overlappingStrcmp() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -403,7 +403,7 @@ void CheckString::overlappingStrcmp() } } -void CheckString::overlappingStrcmpError(const Token *eq0, const Token *ne0) +void CheckStringImpl::overlappingStrcmpError(const Token *eq0, const Token *ne0) { std::string eq0Expr(eq0 ? eq0->expressionString() : std::string("strcmp(x,\"abc\")")); if (eq0 && eq0->astParent()->str() == "!") @@ -420,7 +420,7 @@ void CheckString::overlappingStrcmpError(const Token *eq0, const Token *ne0) // Overlapping source and destination passed to sprintf(). // TODO: Library configuration for overlapping arguments //--------------------------------------------------------------------------- -void CheckString::sprintfOverlappingData() +void CheckStringImpl::sprintfOverlappingData() { logChecker("CheckString::sprintfOverlappingData"); @@ -457,7 +457,7 @@ void CheckString::sprintfOverlappingData() } } -void CheckString::sprintfOverlappingDataError(const Token *funcTok, const Token *tok, const std::string &varname) +void CheckStringImpl::sprintfOverlappingDataError(const Token *funcTok, const Token *tok, const std::string &varname) { const std::string func = funcTok ? funcTok->str() : "s[n]printf"; @@ -473,7 +473,7 @@ void CheckString::sprintfOverlappingDataError(const Token *funcTok, const Token void CheckString::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckString checkString(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckStringImpl checkString(&tokenizer, &tokenizer.getSettings(), errorLogger); // Checks checkString.strPlusChar(); @@ -487,7 +487,7 @@ void CheckString::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger void CheckString::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckString c(nullptr, settings, errorLogger); + CheckStringImpl c(nullptr, settings, errorLogger); c.stringLiteralWriteError(nullptr, nullptr); c.sprintfOverlappingDataError(nullptr, nullptr, "varname"); c.strPlusCharError(nullptr); diff --git a/lib/checkstring.h b/lib/checkstring.h index 76002f8ed3d..799c5daa589 100644 --- a/lib/checkstring.h +++ b/lib/checkstring.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -41,16 +42,32 @@ class Tokenizer; class CPPCHECKLIB CheckString : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckString() : Check(myName()) {} + CheckString() : Check("String") {} private: - /** @brief This constructor is used when running checks. */ - CheckString(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + return "Detect misusage of C-style strings:\n" + "- overlapping buffers passed to sprintf as source and destination\n" + "- incorrect length arguments for 'substr' and 'strncmp'\n" + "- suspicious condition (runtime comparison of string literals)\n" + "- suspicious condition (string/char literals as boolean)\n" + "- suspicious comparison of a string literal with a char\\* variable\n" + "- suspicious comparison of '\\0' with a char\\* variable\n" + "- overlapping strcmp() expression\n"; + } +}; + +class CheckStringImpl : public CheckImpl { +public: + /** @brief This constructor is used when running checks. */ + CheckStringImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** @brief undefined behaviour, writing string literal */ void stringLiteralWrite(); @@ -82,23 +99,6 @@ class CPPCHECKLIB CheckString : public Check { void suspiciousStringCompareError(const Token* tok, const std::string& var, bool isLong); void suspiciousStringCompareError_char(const Token* tok, const std::string& var); void overlappingStrcmpError(const Token* eq0, const Token *ne0); - - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "String"; - } - - std::string classInfo() const override { - return "Detect misusage of C-style strings:\n" - "- overlapping buffers passed to sprintf as source and destination\n" - "- incorrect length arguments for 'substr' and 'strncmp'\n" - "- suspicious condition (runtime comparison of string literals)\n" - "- suspicious condition (string/char literals as boolean)\n" - "- suspicious comparison of a string literal with a char\\* variable\n" - "- suspicious comparison of '\\0' with a char\\* variable\n" - "- overlapping strcmp() expression\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checktype.cpp b/lib/checktype.cpp index eb222fbe6f5..1679d98e80f 100644 --- a/lib/checktype.cpp +++ b/lib/checktype.cpp @@ -56,7 +56,7 @@ static const CWE CWE758(758U); // Reliance on Undefined, Unspecified, or Imple static const CWE CWE190(190U); // Integer Overflow or Wraparound -void CheckType::checkTooBigBitwiseShift() +void CheckTypeImpl::checkTooBigBitwiseShift() { // unknown sizeof(int) => can't run this checker if (mSettings->platform.type == Platform::Type::Unspecified) @@ -110,7 +110,7 @@ void CheckType::checkTooBigBitwiseShift() } } -void CheckType::tooBigBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits) +void CheckTypeImpl::tooBigBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits) { constexpr char id[] = "shiftTooManyBits"; @@ -129,7 +129,7 @@ void CheckType::tooBigBitwiseShiftError(const Token *tok, int lhsbits, const Val reportError(std::move(errorPath), rhsbits.errorSeverity() ? Severity::error : Severity::warning, id, errmsg.str(), CWE758, rhsbits.isInconclusive() ? Certainty::inconclusive : Certainty::normal); } -void CheckType::tooBigSignedBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits) +void CheckTypeImpl::tooBigSignedBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits) { constexpr char id[] = "shiftTooManyBitsSigned"; @@ -164,7 +164,7 @@ void CheckType::tooBigSignedBitwiseShiftError(const Token *tok, int lhsbits, con // Checking for integer overflow //--------------------------------------------------------------------------- -void CheckType::checkIntegerOverflow() +void CheckTypeImpl::checkIntegerOverflow() { // unknown sizeof(int) => can't run this checker if (mSettings->platform.type == Platform::Type::Unspecified || mSettings->platform.int_bit >= MathLib::bigint_bits) @@ -215,7 +215,16 @@ void CheckType::checkIntegerOverflow() } } -void CheckType::integerOverflowError(const Token *tok, const ValueFlow::Value &value, bool isOverflow) +static std::string getMessageId(const ValueFlow::Value &value, const char id[]) +{ + if (value.condition != nullptr) + return id + std::string("Cond"); + if (value.safe) + return std::string("safe") + static_cast(std::toupper(id[0])) + (id + 1); + return id; +} + +void CheckTypeImpl::integerOverflowError(const Token *tok, const ValueFlow::Value &value, bool isOverflow) { const std::string expr(tok ? tok->expressionString() : ""); const std::string type = isOverflow ? "overflow" : "underflow"; @@ -242,7 +251,7 @@ void CheckType::integerOverflowError(const Token *tok, const ValueFlow::Value &v // Checking for sign conversion when operand can be negative //--------------------------------------------------------------------------- -void CheckType::checkSignConversion() +void CheckTypeImpl::checkSignConversion() { if (!mSettings->severity.isEnabled(Severity::warning)) return; @@ -274,7 +283,7 @@ void CheckType::checkSignConversion() } } -void CheckType::signConversionError(const Token *tok, const ValueFlow::Value *negativeValue, const bool constvalue) +void CheckTypeImpl::signConversionError(const Token *tok, const ValueFlow::Value *negativeValue, const bool constvalue) { const std::string expr(tok ? tok->expressionString() : "var"); @@ -292,7 +301,7 @@ void CheckType::signConversionError(const Token *tok, const ValueFlow::Value *ne ErrorPath errorPath = getErrorPath(tok,negativeValue,"Negative value is converted to an unsigned value"); reportError(std::move(errorPath), Severity::warning, - Check::getMessageId(*negativeValue, "signConversion").c_str(), + getMessageId(*negativeValue, "signConversion").c_str(), msg.str(), CWE195, negativeValue->isInconclusive() ? Certainty::inconclusive : Certainty::normal); @@ -327,7 +336,7 @@ static bool checkTypeCombination(ValueType src, ValueType tgt, const Settings& s }); } -void CheckType::checkLongCast() +void CheckTypeImpl::checkLongCast() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("truncLongCastAssignment")) return; @@ -405,7 +414,7 @@ static void makeBaseTypeString(std::string& typeStr) typeStr.erase(typeStr.begin(), typeStr.begin() + pos + 6 + 1); } -void CheckType::longCastAssignError(const Token *tok, const ValueType* src, const ValueType* tgt) +void CheckTypeImpl::longCastAssignError(const Token *tok, const ValueType* src, const ValueType* tgt) { std::string srcStr = src ? src->str() : "int"; makeBaseTypeString(srcStr); @@ -418,7 +427,7 @@ void CheckType::longCastAssignError(const Token *tok, const ValueType* src, cons srcStr + " result is assigned to " + tgtStr + " variable. If the variable is " + tgtStr + " to avoid loss of information, then there is loss of information. To avoid loss of information you must cast a calculation operand to " + tgtStr + ", for example 'l = a * b;' => 'l = (" + tgtStr + ")a * b;'.", CWE197, Certainty::normal); } -void CheckType::longCastReturnError(const Token *tok, const ValueType* src, const ValueType* tgt) +void CheckTypeImpl::longCastReturnError(const Token *tok, const ValueType* src, const ValueType* tgt) { std::string srcStr = src ? src->str() : "int"; makeBaseTypeString(srcStr); @@ -435,7 +444,7 @@ void CheckType::longCastReturnError(const Token *tok, const ValueType* src, cons // Checking for float to integer overflow //--------------------------------------------------------------------------- -void CheckType::checkFloatToIntegerOverflow() +void CheckTypeImpl::checkFloatToIntegerOverflow() { logChecker("CheckType::checkFloatToIntegerOverflow"); @@ -475,7 +484,7 @@ void CheckType::checkFloatToIntegerOverflow() } } -void CheckType::checkFloatToIntegerOverflow(const Token *tok, const ValueType *vtint, const ValueType *vtfloat, const std::list &floatValues) +void CheckTypeImpl::checkFloatToIntegerOverflow(const Token *tok, const ValueType *vtint, const ValueType *vtfloat, const std::list &floatValues) { // Conversion of float to integer? if (!vtint || !vtint->isIntegral()) @@ -512,7 +521,7 @@ void CheckType::checkFloatToIntegerOverflow(const Token *tok, const ValueType *v } } -void CheckType::floatToIntegerOverflowError(const Token *tok, const ValueFlow::Value &value) +void CheckTypeImpl::floatToIntegerOverflowError(const Token *tok, const ValueFlow::Value &value) { std::ostringstream errmsg; errmsg << "Undefined behaviour: float (" << value.floatValue << ") to integer conversion overflow."; @@ -525,7 +534,7 @@ void CheckType::floatToIntegerOverflowError(const Token *tok, const ValueFlow::V void CheckType::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { // These are not "simplified" because casts can't be ignored - CheckType checkType(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckTypeImpl checkType(&tokenizer, &tokenizer.getSettings(), errorLogger); checkType.checkTooBigBitwiseShift(); checkType.checkIntegerOverflow(); checkType.checkSignConversion(); @@ -535,7 +544,7 @@ void CheckType::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) void CheckType::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckType c(nullptr, settings, errorLogger); + CheckTypeImpl c(nullptr, settings, errorLogger); c.tooBigBitwiseShiftError(nullptr, 32, ValueFlow::Value(64)); c.tooBigSignedBitwiseShiftError(nullptr, 31, ValueFlow::Value(31)); c.integerOverflowError(nullptr, ValueFlow::Value(1LL<<32)); diff --git a/lib/checktype.h b/lib/checktype.h index d90e11f6fd1..e13bf644de6 100644 --- a/lib/checktype.h +++ b/lib/checktype.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -47,16 +48,31 @@ namespace ValueFlow class CPPCHECKLIB CheckType : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckType() : Check(myName()) {} + CheckType() : Check("Type") {} private: - /** @brief This constructor is used when running checks. */ - CheckType(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + return "Type checks\n" + "- bitwise shift by too many bits (only enabled when --platform is used)\n" + "- signed integer overflow (only enabled when --platform is used)\n" + "- dangerous sign conversion, when signed value can be negative\n" + "- possible loss of information when assigning int result to long variable\n" + "- possible loss of information when returning int result as long return value\n" + "- float conversion overflow\n"; + } +}; + +class CheckTypeImpl : public CheckImpl { +public: + /** @brief This constructor is used when running checks. */ + CheckTypeImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** @brief %Check for bitwise shift with too big right operand */ void checkTooBigBitwiseShift(); @@ -81,22 +97,6 @@ class CPPCHECKLIB CheckType : public Check { void longCastAssignError(const Token *tok, const ValueType* src = nullptr, const ValueType* tgt = nullptr); void longCastReturnError(const Token *tok, const ValueType* src = nullptr, const ValueType* tgt = nullptr); void floatToIntegerOverflowError(const Token *tok, const ValueFlow::Value &value); - - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "Type"; - } - - std::string classInfo() const override { - return "Type checks\n" - "- bitwise shift by too many bits (only enabled when --platform is used)\n" - "- signed integer overflow (only enabled when --platform is used)\n" - "- dangerous sign conversion, when signed value can be negative\n" - "- possible loss of information when assigning int result to long variable\n" - "- possible loss of information when returning int result as long return value\n" - "- float conversion overflow\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index b88debda6f8..f1d71a92f35 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -21,6 +21,7 @@ #include "checkuninitvar.h" #include "astutils.h" +#include "checkimpl.h" #include "ctu.h" #include "errorlogger.h" #include "library.h" @@ -97,7 +98,7 @@ static std::map getVariableValues(const Token* tok) { return ret; } -bool CheckUninitVar::diag(const Token* tok) +bool CheckUninitVarImpl::diag(const Token* tok) { if (!tok) return true; @@ -106,7 +107,7 @@ bool CheckUninitVar::diag(const Token* tok) return !mUninitDiags.insert(tok).second; } -void CheckUninitVar::check() +void CheckUninitVarImpl::check() { logChecker("CheckUninitVar::check"); @@ -126,7 +127,7 @@ void CheckUninitVar::check() } } -void CheckUninitVar::checkScope(const Scope* scope, const std::set &arrayTypeDefs) +void CheckUninitVarImpl::checkScope(const Scope* scope, const std::set &arrayTypeDefs) { for (const Variable &var : scope->varlist) { if ((mTokenizer->isCPP() && var.type() && !var.isPointer() && var.type()->needInitialization != Type::NeedInitialization::True) || @@ -231,7 +232,7 @@ void CheckUninitVar::checkScope(const Scope* scope, const std::set } } -void CheckUninitVar::checkStruct(const Token *tok, const Variable &structvar) +void CheckUninitVarImpl::checkStruct(const Token *tok, const Variable &structvar) { const Token *typeToken = structvar.typeStartToken(); while (Token::Match(typeToken, "%name% ::")) @@ -392,7 +393,7 @@ static bool isVariableUsed(const Token *tok, const Variable& var) return !parent2 || parent2->isConstOp() || (parent2->str() == "=" && parent2->astOperand2() == parent); } -bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var, bool * const possibleInit, bool * const noreturn, Alloc* const alloc, const std::string &membervar, std::map& variableValue) +bool CheckUninitVarImpl::checkScopeForVariable(const Token *tok, const Variable& var, bool * const possibleInit, bool * const noreturn, Alloc* const alloc, const std::string &membervar, std::map& variableValue) { const bool suppressErrors(possibleInit && *possibleInit); // Assume that this is a variable declaration, rather than a fundef const bool printDebug = mSettings->debugwarnings; @@ -728,7 +729,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var } // Use variable - else if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) + else if (!suppressErrors && isVariableUsage(tok, mSettings->library, var.isPointer(), *alloc)) uninitvarError(tok, tok->str(), *alloc); return true; @@ -817,7 +818,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var } else { // Use variable - if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) { + if (!suppressErrors && isVariableUsage(tok, mSettings->library, var.isPointer(), *alloc)) { uninitvarError(tok, tok->str(), *alloc); return true; } @@ -852,7 +853,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var return false; } -const Token* CheckUninitVar::checkExpr(const Token* tok, const Variable& var, const Alloc alloc, bool known, bool* bailout) const +const Token* CheckUninitVarImpl::checkExpr(const Token* tok, const Variable& var, const Alloc alloc, bool known, bool* bailout) const { if (!tok) return nullptr; @@ -872,7 +873,7 @@ const Token* CheckUninitVar::checkExpr(const Token* tok, const Variable& var, co if (tok->astOperand2()) return checkExpr(tok->astOperand2(), var, alloc, known, bailout); if (tok->varId() == var.declarationId()) { - const Token *errorToken = isVariableUsage(tok, var.isPointer(), alloc); + const Token *errorToken = isVariableUsage(tok, mSettings->library, var.isPointer(), alloc); if (errorToken) return errorToken; if (bailout) @@ -881,7 +882,7 @@ const Token* CheckUninitVar::checkExpr(const Token* tok, const Variable& var, co return nullptr; } -bool CheckUninitVar::checkIfForWhileHead(const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, Alloc alloc, const std::string &membervar) +bool CheckUninitVarImpl::checkIfForWhileHead(const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, Alloc alloc, const std::string &membervar) { const Token * const endpar = startparentheses->link(); if (Token::Match(startparentheses, "( ! %name% %oror%") && startparentheses->tokAt(2)->getValue(0)) @@ -901,7 +902,7 @@ bool CheckUninitVar::checkIfForWhileHead(const Token *startparentheses, const Va continue; } - if (const Token *errorToken = isVariableUsage(tok, var.isPointer(), alloc)) { + if (const Token *errorToken = isVariableUsage(tok, mSettings->library, var.isPointer(), alloc)) { if (suppressErrors) continue; uninitvarError(errorToken, errorToken->expressionString(), alloc); @@ -918,7 +919,7 @@ bool CheckUninitVar::checkIfForWhileHead(const Token *startparentheses, const Va } /** recursively check loop, return error token */ -const Token* CheckUninitVar::checkLoopBodyRecursive(const Token *start, const Variable& var, const Alloc alloc, const std::string &membervar, bool &bailout, bool &alwaysReturns) const +const Token* CheckUninitVarImpl::checkLoopBodyRecursive(const Token *start, const Variable& var, const Alloc alloc, const std::string &membervar, bool &bailout, bool &alwaysReturns) const { assert(start->str() == "{"); @@ -1054,7 +1055,7 @@ const Token* CheckUninitVar::checkLoopBodyRecursive(const Token *start, const Va return nullptr; } } else { - if (const Token *errtok = isVariableUsage(tok, var.isPointer(), alloc)) { + if (const Token *errtok = isVariableUsage(tok, mSettings->library, var.isPointer(), alloc)) { if (!conditionalUsage) return errtok; if (!errorToken) @@ -1086,7 +1087,7 @@ const Token* CheckUninitVar::checkLoopBodyRecursive(const Token *start, const Va return errorToken; } -bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const Alloc alloc, const std::string &membervar, const bool suppressErrors) +bool CheckUninitVarImpl::checkLoopBody(const Token *tok, const Variable& var, const Alloc alloc, const std::string &membervar, const bool suppressErrors) { bool bailout = false; bool alwaysReturns = false; @@ -1103,7 +1104,7 @@ bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const return bailout || alwaysReturns; } -void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc, nonneg int number_of_if, const std::string &membervar) +void CheckUninitVarImpl::checkRhs(const Token *tok, const Variable &var, Alloc alloc, nonneg int number_of_if, const std::string &membervar) { bool rhs = false; int indent = 0; @@ -1111,7 +1112,7 @@ void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc if (tok->str() == "=") rhs = true; else if (rhs && tok->varId() == var.declarationId()) { - if (membervar.empty() && isVariableUsage(tok, var.isPointer(), alloc)) + if (membervar.empty() && isVariableUsage(tok, mSettings->library, var.isPointer(), alloc)) uninitvarError(tok, tok->str(), alloc); else if (!membervar.empty() && isMemberVariableUsage(tok, var.isPointer(), alloc, membervar)) uninitStructMemberError(tok, tok->str() + "." + membervar); @@ -1150,7 +1151,7 @@ static bool astIsRhs(const Token *tok) return tok && tok->astParent() && tok == tok->astParent()->astOperand2(); } -const Token* CheckUninitVar::isVariableUsage(const Token *vartok, const Library& library, bool pointer, Alloc alloc, int indirect) +const Token* CheckUninitVarImpl::isVariableUsage(const Token *vartok, const Library& library, bool pointer, Alloc alloc, int indirect) { const bool cpp = vartok->isCpp(); const Token *valueExpr = vartok; // non-dereferenced , no address of value as variable @@ -1257,17 +1258,17 @@ const Token* CheckUninitVar::isVariableUsage(const Token *vartok, const Library& const Token *parent = valueExpr->astParent(); while (Token::simpleMatch(parent, ",")) parent = parent->astParent(); - const int use = isFunctionParUsage(valueExpr, library, pointer, alloc, indirect); + const int use = CheckUninitVarImpl::isFunctionParUsage(valueExpr, library, pointer, alloc, indirect); return (use>0) ? valueExpr : nullptr; } if (derefValue && Token::Match(derefValue->astParent(), "[(,]") && (derefValue->astParent()->str() == "," || astIsRhs(derefValue))) { - const int use = isFunctionParUsage(derefValue, library, false, NO_ALLOC, indirect); + const int use = CheckUninitVarImpl::isFunctionParUsage(derefValue, library, false, NO_ALLOC, indirect); return (use>0) ? derefValue : nullptr; } if (valueExpr->astParent()->isUnaryOp("&")) { const Token *parent = valueExpr->astParent(); if (Token::Match(parent->astParent(), "[(,]") && (parent->astParent()->str() == "," || astIsRhs(parent))) { - const int use = isFunctionParUsage(valueExpr, library, pointer, alloc, indirect); + const int use = CheckUninitVarImpl::isFunctionParUsage(valueExpr, library, pointer, alloc, indirect); return (use>0) ? valueExpr : nullptr; } return nullptr; @@ -1352,18 +1353,13 @@ const Token* CheckUninitVar::isVariableUsage(const Token *vartok, const Library& return derefValue ? derefValue : valueExpr; } -const Token* CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, Alloc alloc, int indirect) const -{ - return isVariableUsage(vartok, mSettings->library, pointer, alloc, indirect); -} - /*** * Is function parameter "used" so a "usage of uninitialized variable" can * be written? If parameter is passed "by value" then it is "used". If it * is passed "by reference" then it is not necessarily "used". * @return -1 => unknown 0 => not used 1 => used */ -int CheckUninitVar::isFunctionParUsage(const Token *vartok, const Library& library, bool pointer, Alloc alloc, int indirect) +int CheckUninitVarImpl::isFunctionParUsage(const Token *vartok, const Library& library, bool pointer, Alloc alloc, int indirect) { bool unknown = false; const Token *parent = getAstParentSkipPossibleCastAndAddressOf(vartok, &unknown); @@ -1433,12 +1429,12 @@ int CheckUninitVar::isFunctionParUsage(const Token *vartok, const Library& libra return -1; } -int CheckUninitVar::isFunctionParUsage(const Token *vartok, bool pointer, Alloc alloc, int indirect) const +int CheckUninitVarImpl::isFunctionParUsage(const Token *vartok, bool pointer, Alloc alloc, int indirect) const { - return CheckUninitVar::isFunctionParUsage(vartok, mSettings->library, pointer, alloc, indirect); + return isFunctionParUsage(vartok, mSettings->library, pointer, alloc, indirect); } -bool CheckUninitVar::isMemberVariableAssignment(const Token *tok, const std::string &membervar) const +bool CheckUninitVarImpl::isMemberVariableAssignment(const Token *tok, const std::string &membervar) const { if (Token::Match(tok, "%name% . %name%") && tok->strAt(2) == membervar) { if (Token::Match(tok->tokAt(3), "[=.[]")) @@ -1507,7 +1503,7 @@ bool CheckUninitVar::isMemberVariableAssignment(const Token *tok, const std::str return false; } -bool CheckUninitVar::isMemberVariableUsage(const Token *tok, bool isPointer, Alloc alloc, const std::string &membervar) const +bool CheckUninitVarImpl::isMemberVariableUsage(const Token *tok, bool isPointer, Alloc alloc, const std::string &membervar) const { if (Token::Match(tok->previous(), "[(,] %name% . %name% [,)]") && tok->strAt(2) == membervar) { @@ -1523,7 +1519,7 @@ bool CheckUninitVar::isMemberVariableUsage(const Token *tok, bool isPointer, All const Token *parent = tok->next()->astParent(); return !parent || !parent->isUnaryOp("&"); } - if (!isPointer && !Token::simpleMatch(tok->astParent(), ".") && Token::Match(tok->previous(), "[(,] %name% [,)]") && isVariableUsage(tok, isPointer, alloc)) + if (!isPointer && !Token::simpleMatch(tok->astParent(), ".") && Token::Match(tok->previous(), "[(,] %name% [,)]") && isVariableUsage(tok, mSettings->library, isPointer, alloc)) return true; if (!isPointer && Token::Match(tok->previous(), "= %name% ;")) { @@ -1543,18 +1539,18 @@ bool CheckUninitVar::isMemberVariableUsage(const Token *tok, bool isPointer, All if ((false) && // NOLINT(readability-simplify-boolean-expr,readability-redundant-parentheses) !isPointer && Token::Match(tok->tokAt(-2), "[(,] & %name% [,)]") && - isVariableUsage(tok, isPointer, alloc)) + isVariableUsage(tok, mSettings->library,isPointer, alloc)) return true; return false; } -void CheckUninitVar::uninitdataError(const Token *tok, const std::string &varname) +void CheckUninitVarImpl::uninitdataError(const Token *tok, const std::string &varname) { reportError(tok, Severity::error, "uninitdata", "$symbol:" + varname + "\nMemory is allocated but not initialized: $symbol", CWE_USE_OF_UNINITIALIZED_VARIABLE, Certainty::normal); } -void CheckUninitVar::uninitvarError(const Token *tok, const std::string &varname, ErrorPath errorPath) +void CheckUninitVarImpl::uninitvarError(const Token *tok, const std::string &varname, ErrorPath errorPath) { if (diag(tok)) return; @@ -1567,7 +1563,7 @@ void CheckUninitVar::uninitvarError(const Token *tok, const std::string &varname Certainty::normal); } -void CheckUninitVar::uninitvarError(const Token* tok, const ValueFlow::Value& v) +void CheckUninitVarImpl::uninitvarError(const Token* tok, const ValueFlow::Value& v) { if (!mSettings->isEnabled(&v)) return; @@ -1604,7 +1600,7 @@ void CheckUninitVar::uninitvarError(const Token* tok, const ValueFlow::Value& v) certainty); } -void CheckUninitVar::uninitStructMemberError(const Token *tok, const std::string &membername) +void CheckUninitVarImpl::uninitStructMemberError(const Token *tok, const std::string &membername) { reportError(tok, Severity::error, @@ -1612,7 +1608,7 @@ void CheckUninitVar::uninitStructMemberError(const Token *tok, const std::string "$symbol:" + membername + "\nUninitialized struct member: $symbol", CWE_USE_OF_UNINITIALIZED_VARIABLE, Certainty::normal); } -void CheckUninitVar::valueFlowUninit() +void CheckUninitVarImpl::valueFlowUninit() { logChecker("CheckUninitVar::valueFlowUninit"); @@ -1696,7 +1692,7 @@ void CheckUninitVar::valueFlowUninit() static bool isVariableUsage(const Settings &settings, const Token *vartok, MathLib::bigint *value) { (void)value; - return CheckUninitVar::isVariableUsage(vartok, settings.library, true, CheckUninitVar::Alloc::ARRAY); + return CheckUninitVarImpl::isVariableUsage(vartok, settings.library, true, CheckUninitVarImpl::Alloc::ARRAY); } // a Clang-built executable will crash when using the anonymous MyFileInfo later on - so put it in a unique namespace for now @@ -1752,7 +1748,7 @@ bool CheckUninitVar::analyseWholeProgram(const CTU::FileInfo &ctu, const std::li { (void)settings; - CheckUninitVar dummy(nullptr, &settings, &errorLogger); + CheckUninitVarImpl dummy(nullptr, &settings, &errorLogger); dummy. logChecker("CheckUninitVar::analyseWholeProgram"); @@ -1798,14 +1794,14 @@ bool CheckUninitVar::analyseWholeProgram(const CTU::FileInfo &ctu, const std::li void CheckUninitVar::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckUninitVar checkUninitVar(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckUninitVarImpl checkUninitVar(&tokenizer, &tokenizer.getSettings(), errorLogger); checkUninitVar.valueFlowUninit(); checkUninitVar.check(); } void CheckUninitVar::getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const { - CheckUninitVar c(nullptr, settings, errorLogger); + CheckUninitVarImpl c(nullptr, settings, errorLogger); ValueFlow::Value v{}; diff --git a/lib/checkuninitvar.h b/lib/checkuninitvar.h index b79e9c22be0..2bdac498ea0 100644 --- a/lib/checkuninitvar.h +++ b/lib/checkuninitvar.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include "mathlib.h" #include "errortypes.h" @@ -61,20 +62,36 @@ class CPPCHECKLIB CheckUninitVar : public Check { public: /** @brief This constructor is used when registering the CheckUninitVar */ - CheckUninitVar() : Check(myName()) {} + CheckUninitVar() : Check("Uninitialized variables") {} - enum Alloc : std::uint8_t { NO_ALLOC, NO_CTOR_CALL, CTOR_CALL, ARRAY }; +private: + /** @brief Run checks against the normal token list */ + void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; - static const Token *isVariableUsage(const Token *vartok, const Library &library, bool pointer, Alloc alloc, int indirect = 0); - const Token *isVariableUsage(const Token *vartok, bool pointer, Alloc alloc, int indirect = 0) const; + /** @brief Parse current TU and extract file info */ + Check::FileInfo *getFileInfo(const Tokenizer &tokenizer, const Settings &settings, const std::string& /*currentConfig*/) const override; -private: + Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const override; + + /** @brief Analyse all file infos for all TU */ + bool analyseWholeProgram(const CTU::FileInfo &ctu, const std::list &fileInfo, const Settings& settings, ErrorLogger &errorLogger) override; + + void getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const override; + + std::string classInfo() const override { + return "Uninitialized variables\n" + "- using uninitialized local variables\n" + "- using allocated data before it has been initialized\n"; + } +}; + +class CheckUninitVarImpl : public CheckImpl { +public: /** @brief This constructor is used when running checks. */ - CheckUninitVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} + CheckUninitVarImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} - /** @brief Run checks against the normal token list */ - void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + enum Alloc : std::uint8_t { NO_ALLOC, NO_CTOR_CALL, CTOR_CALL, ARRAY }; bool diag(const Token* tok); /** Check for uninitialized variables */ @@ -92,17 +109,11 @@ class CPPCHECKLIB CheckUninitVar : public Check { bool isMemberVariableAssignment(const Token *tok, const std::string &membervar) const; bool isMemberVariableUsage(const Token *tok, bool isPointer, Alloc alloc, const std::string &membervar) const; + static const Token *isVariableUsage(const Token *vartok, const Library &library, bool pointer, Alloc alloc, int indirect = 0); + /** ValueFlow-based checking for uninitialized variables */ void valueFlowUninit(); - /** @brief Parse current TU and extract file info */ - Check::FileInfo *getFileInfo(const Tokenizer &tokenizer, const Settings &settings, const std::string& /*currentConfig*/) const override; - - Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const override; - - /** @brief Analyse all file infos for all TU */ - bool analyseWholeProgram(const CTU::FileInfo &ctu, const std::list &fileInfo, const Settings& settings, ErrorLogger &errorLogger) override; - void uninitvarError(const Token* tok, const ValueFlow::Value& v); void uninitdataError(const Token *tok, const std::string &varname); void uninitvarError(const Token *tok, const std::string &varname, ErrorPath errorPath); @@ -118,18 +129,6 @@ class CPPCHECKLIB CheckUninitVar : public Check { void uninitStructMemberError(const Token *tok, const std::string &membername); std::set mUninitDiags; - - void getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const override; - - static std::string myName() { - return "Uninitialized variables"; - } - - std::string classInfo() const override { - return "Uninitialized variables\n" - "- using uninitialized local variables\n" - "- using allocated data before it has been initialized\n"; - } }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 9531237a208..4d8415e9793 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -699,7 +699,7 @@ static void useFunctionArgs(const Token *tok, Variables& variables) //--------------------------------------------------------------------------- // Usage of function variables //--------------------------------------------------------------------------- -void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const scope, Variables& variables) const +void CheckUnusedVarImpl::checkFunctionVariableUsage_iterateScopes(const Scope* const scope, Variables& variables) const { // Find declarations if the scope is executable.. if (scope->isExecutable()) { @@ -1173,7 +1173,7 @@ static bool isReturnedByRef(const Variable* var, const Function* func) }); } -void CheckUnusedVar::checkFunctionVariableUsage() +void CheckUnusedVarImpl::checkFunctionVariableUsage() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->checkLibrary && !mSettings->isPremiumEnabled("unusedVariable")) return; @@ -1479,7 +1479,7 @@ void CheckUnusedVar::checkFunctionVariableUsage() } } -void CheckUnusedVar::unusedVariableError(const Token *tok, const std::string &varname) +void CheckUnusedVarImpl::unusedVariableError(const Token *tok, const std::string &varname) { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("unusedVariable")) return; @@ -1487,7 +1487,7 @@ void CheckUnusedVar::unusedVariableError(const Token *tok, const std::string &va reportError(tok, Severity::style, "unusedVariable", "$symbol:" + varname + "\nUnused variable: $symbol", CWE563, Certainty::normal); } -void CheckUnusedVar::allocatedButUnusedVariableError(const Token *tok, const std::string &varname) +void CheckUnusedVarImpl::allocatedButUnusedVariableError(const Token *tok, const std::string &varname) { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("unusedVariable")) return; @@ -1495,7 +1495,7 @@ void CheckUnusedVar::allocatedButUnusedVariableError(const Token *tok, const std reportError(tok, Severity::style, "unusedAllocatedMemory", "$symbol:" + varname + "\nVariable '$symbol' is allocated memory that is never used.", CWE563, Certainty::normal); } -void CheckUnusedVar::unreadVariableError(const Token *tok, const std::string &varname, bool modified) +void CheckUnusedVarImpl::unreadVariableError(const Token *tok, const std::string &varname, bool modified) { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("unusedVariable")) return; @@ -1506,7 +1506,7 @@ void CheckUnusedVar::unreadVariableError(const Token *tok, const std::string &va reportError(tok, Severity::style, "unreadVariable", "$symbol:" + varname + "\nVariable '$symbol' is assigned a value that is never used.", CWE563, Certainty::normal); } -void CheckUnusedVar::unassignedVariableError(const Token *tok, const std::string &varname) +void CheckUnusedVarImpl::unassignedVariableError(const Token *tok, const std::string &varname) { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("unusedVariable")) return; @@ -1517,7 +1517,7 @@ void CheckUnusedVar::unassignedVariableError(const Token *tok, const std::string //--------------------------------------------------------------------------- // Check that all struct members are used //--------------------------------------------------------------------------- -void CheckUnusedVar::checkStructMemberUsage() +void CheckUnusedVarImpl::checkStructMemberUsage() { if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("unusedStructMember") && !mSettings->isPremiumEnabled("unusedVariable")) return; @@ -1698,12 +1698,12 @@ void CheckUnusedVar::checkStructMemberUsage() } } -void CheckUnusedVar::unusedStructMemberError(const Token* tok, const std::string& structname, const std::string& varname, const std::string& prefix) +void CheckUnusedVarImpl::unusedStructMemberError(const Token* tok, const std::string& structname, const std::string& varname, const std::string& prefix) { reportError(tok, Severity::style, "unusedStructMember", "$symbol:" + structname + "::" + varname + '\n' + prefix + " member '$symbol' is never used.", CWE563, Certainty::normal); } -bool CheckUnusedVar::isEmptyType(const Type* type) +bool CheckUnusedVarImpl::isEmptyType(const Type* type) { // a type that has no variables and no constructor @@ -1724,21 +1724,20 @@ bool CheckUnusedVar::isEmptyType(const Type* type) return (emptyType = false); } -void CheckUnusedVar::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) -{ - CheckUnusedVar checkUnusedVar(&tokenizer, &tokenizer.getSettings(), errorLogger); +void CheckUnusedVar::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { + CheckUnusedVarImpl checkUnusedVar(&tokenizer, &tokenizer.getSettings(), errorLogger); // Coding style checks checkUnusedVar.checkStructMemberUsage(); checkUnusedVar.checkFunctionVariableUsage(); } -void CheckUnusedVar::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const -{ - CheckUnusedVar c(nullptr, settings, errorLogger); +void CheckUnusedVar::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { + CheckUnusedVarImpl c(nullptr, settings, errorLogger); c.unusedVariableError(nullptr, "varname"); c.allocatedButUnusedVariableError(nullptr, "varname"); c.unreadVariableError(nullptr, "varname", false); c.unassignedVariableError(nullptr, "varname"); c.unusedStructMemberError(nullptr, "structname", "variable"); } + diff --git a/lib/checkunusedvar.h b/lib/checkunusedvar.h index 5ab79514cf9..1e8d7480539 100644 --- a/lib/checkunusedvar.h +++ b/lib/checkunusedvar.h @@ -22,6 +22,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -46,16 +47,32 @@ class CPPCHECKLIB CheckUnusedVar : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckUnusedVar() : Check(myName()) {} + CheckUnusedVar() : Check("UnusedVar") {} private: - /** @brief This constructor is used when running checks. */ - CheckUnusedVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} - /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; + void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; + + std::string classInfo() const override { + return "UnusedVar checks\n" + + // style + "- unused variable\n" + "- allocated but unused variable\n" + "- unread variable\n" + "- unassigned variable\n" + "- unused struct member\n"; + } +}; + +class CheckUnusedVarImpl : public CheckImpl { +public: + /** @brief This constructor is used when running checks. */ + CheckUnusedVarImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + /** @brief %Check for unused function variables */ void checkFunctionVariableUsage_iterateScopes(const Scope* scope, Variables& variables) const; void checkFunctionVariableUsage(); @@ -72,25 +89,7 @@ class CPPCHECKLIB CheckUnusedVar : public Check { void unreadVariableError(const Token *tok, const std::string &varname, bool modified); void unassignedVariableError(const Token *tok, const std::string &varname); - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - - static std::string myName() { - return "UnusedVar"; - } - - std::string classInfo() const override { - return "UnusedVar checks\n" - - // style - "- unused variable\n" - "- allocated but unused variable\n" - "- unread variable\n" - "- unassigned variable\n" - "- unused struct member\n"; - } - std::map mIsEmptyTypeMap; - }; /// @} //--------------------------------------------------------------------------- diff --git a/lib/checkvaarg.cpp b/lib/checkvaarg.cpp index e6efc8f5ed9..18eb246e0e7 100644 --- a/lib/checkvaarg.cpp +++ b/lib/checkvaarg.cpp @@ -39,7 +39,7 @@ static const CWE CWE664(664U); // Improper Control of a Resource Through its L static const CWE CWE688(688U); // Function Call With Incorrect Variable or Reference as Argument static const CWE CWE758(758U); // Reliance on Undefined, Unspecified, or Implementation-Defined Behavior -void CheckVaarg::va_start_argument() +void CheckVaargImpl::va_start_argument() { const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); const std::size_t functions = symbolDatabase->functionScopes.size(); @@ -73,13 +73,13 @@ void CheckVaarg::va_start_argument() } } -void CheckVaarg::wrongParameterTo_va_start_error(const Token *tok, const std::string& paramIsName, const std::string& paramShouldName) +void CheckVaargImpl::wrongParameterTo_va_start_error(const Token *tok, const std::string& paramIsName, const std::string& paramShouldName) { reportError(tok, Severity::warning, "va_start_wrongParameter", "'" + paramIsName + "' given to va_start() is not last named argument of the function. Did you intend to pass '" + paramShouldName + "'?", CWE688, Certainty::normal); } -void CheckVaarg::referenceAs_va_start_error(const Token *tok, const std::string& paramName) +void CheckVaargImpl::referenceAs_va_start_error(const Token *tok, const std::string& paramName) { reportError(tok, Severity::error, "va_start_referencePassed", "Using reference '" + paramName + "' as parameter for va_start() results in undefined behaviour.", CWE758, Certainty::normal); @@ -90,7 +90,7 @@ void CheckVaarg::referenceAs_va_start_error(const Token *tok, const std::string& // Detect va_list usage after va_end() //--------------------------------------------------------------------------- -void CheckVaarg::va_list_usage() +void CheckVaargImpl::va_list_usage() { if (mSettings->clang) return; @@ -155,19 +155,19 @@ void CheckVaarg::va_list_usage() } } -void CheckVaarg::va_end_missingError(const Token *tok, const std::string& varname) +void CheckVaargImpl::va_end_missingError(const Token *tok, const std::string& varname) { reportError(tok, Severity::error, "va_end_missing", "va_list '" + varname + "' was opened but not closed by va_end().", CWE664, Certainty::normal); } -void CheckVaarg::va_list_usedBeforeStartedError(const Token *tok, const std::string& varname) +void CheckVaargImpl::va_list_usedBeforeStartedError(const Token *tok, const std::string& varname) { reportError(tok, Severity::error, "va_list_usedBeforeStarted", "va_list '" + varname + "' used before va_start() was called.", CWE664, Certainty::normal); } -void CheckVaarg::va_start_subsequentCallsError(const Token *tok, const std::string& varname) +void CheckVaargImpl::va_start_subsequentCallsError(const Token *tok, const std::string& varname) { reportError(tok, Severity::error, "va_start_subsequentCalls", "va_start() or va_copy() called subsequently on '" + varname + "' without va_end() in between.", CWE664, Certainty::normal); @@ -175,14 +175,14 @@ void CheckVaarg::va_start_subsequentCallsError(const Token *tok, const std::stri void CheckVaarg::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) { - CheckVaarg check(&tokenizer, &tokenizer.getSettings(), errorLogger); + CheckVaargImpl check(&tokenizer, &tokenizer.getSettings(), errorLogger); check.va_start_argument(); check.va_list_usage(); } void CheckVaarg::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { - CheckVaarg c(nullptr, settings, errorLogger); + CheckVaargImpl c(nullptr, settings, errorLogger); c.wrongParameterTo_va_start_error(nullptr, "arg1", "arg2"); c.referenceAs_va_start_error(nullptr, "arg1"); c.va_end_missingError(nullptr, "vl"); diff --git a/lib/checkvaarg.h b/lib/checkvaarg.h index 7af5d98d66f..a0c1a7c997b 100644 --- a/lib/checkvaarg.h +++ b/lib/checkvaarg.h @@ -23,6 +23,7 @@ //--------------------------------------------------------------------------- #include "check.h" +#include "checkimpl.h" #include "config.h" #include @@ -41,29 +42,13 @@ class Tokenizer; class CPPCHECKLIB CheckVaarg : public Check { public: - CheckVaarg() : Check(myName()) {} - -private: - CheckVaarg(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) {} + CheckVaarg() : Check("Vaarg") {} void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override; - void va_start_argument(); - void va_list_usage(); - - void wrongParameterTo_va_start_error(const Token *tok, const std::string& paramIsName, const std::string& paramShouldName); - void referenceAs_va_start_error(const Token *tok, const std::string& paramName); - void va_end_missingError(const Token *tok, const std::string& varname); - void va_list_usedBeforeStartedError(const Token *tok, const std::string& varname); - void va_start_subsequentCallsError(const Token *tok, const std::string& varname); - +private: void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override; - static std::string myName() { - return "Vaarg"; - } - std::string classInfo() const override { return "Check for misusage of variable argument lists:\n" "- Wrong parameter passed to va_start()\n" @@ -74,6 +59,22 @@ class CPPCHECKLIB CheckVaarg : public Check { } }; +class CheckVaargImpl: public CheckImpl +{ +public: + CheckVaargImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : CheckImpl(tokenizer, settings, errorLogger) {} + + void va_start_argument(); + void va_list_usage(); + + void wrongParameterTo_va_start_error(const Token *tok, const std::string& paramIsName, const std::string& paramShouldName); + void referenceAs_va_start_error(const Token *tok, const std::string& paramName); + void va_end_missingError(const Token *tok, const std::string& varname); + void va_list_usedBeforeStartedError(const Token *tok, const std::string& varname); + void va_start_subsequentCallsError(const Token *tok, const std::string& varname); +}; + /// @} //--------------------------------------------------------------------------- diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index 12bd4898d4a..5e5b9ae743a 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -32,12 +32,6 @@ - - Create - Create - Create - Create - @@ -50,6 +44,12 @@ + + Create + Create + Create + Create + @@ -124,6 +124,7 @@ + diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 3819bfc4b41..246bd9eaf40 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -5697,7 +5697,7 @@ static void valueFlowSubFunction(const TokenList& tokenlist, // Remove uninit values if argument is passed by value if (argtok->variable() && !argtok->variable()->isPointer() && argvalues.size() == 1 && argvalues.front().isUninitValue()) { - if (CheckUninitVar::isVariableUsage(argtok, settings.library, false, CheckUninitVar::Alloc::NO_ALLOC, 0)) + if (CheckUninitVarImpl::isVariableUsage(argtok, settings.library, false, CheckUninitVarImpl::Alloc::NO_ALLOC, 0)) continue; } diff --git a/oss-fuzz/Makefile b/oss-fuzz/Makefile index c93b8694065..bf40964b338 100644 --- a/oss-fuzz/Makefile +++ b/oss-fuzz/Makefile @@ -45,7 +45,6 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/addoninfo.o \ $(libcppdir)/analyzerinfo.o \ $(libcppdir)/astutils.o \ - $(libcppdir)/check.o \ $(libcppdir)/check64bit.o \ $(libcppdir)/checkassert.o \ $(libcppdir)/checkautovariables.o \ @@ -58,6 +57,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/checkersreport.o \ $(libcppdir)/checkexceptionsafety.o \ $(libcppdir)/checkfunctions.o \ + $(libcppdir)/checkimpl.o \ $(libcppdir)/checkinternal.o \ $(libcppdir)/checkio.o \ $(libcppdir)/checkleakautovar.o \ @@ -153,7 +153,7 @@ simplecpp.o: ../externals/simplecpp/simplecpp.cpp ../externals/simplecpp/simplec tinyxml2.o: ../externals/tinyxml2/tinyxml2.cpp ../externals/tinyxml2/tinyxml2.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -w -D_LARGEFILE_SOURCE -c -o $@ ../externals/tinyxml2/tinyxml2.cpp -$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkers.h ../lib/checkuninitvar.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/regex.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyzers.h ../lib/vf_common.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h +$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checkuninitvar.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/regex.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyzers.h ../lib/vf_common.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: ../lib/tokenize.cpp ../externals/simplecpp/simplecpp.h ../lib/addoninfo.h ../lib/astutils.h ../lib/checkers.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/summaries.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 ../lib/vfvalue.h @@ -168,31 +168,28 @@ $(libcppdir)/addoninfo.o: ../lib/addoninfo.cpp ../externals/picojson/picojson.h $(libcppdir)/analyzerinfo.o: ../lib/analyzerinfo.cpp ../externals/tinyxml2/tinyxml2.h ../lib/analyzerinfo.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/filesettings.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/standards.h ../lib/utils.h ../lib/xml.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/analyzerinfo.cpp -$(libcppdir)/astutils.o: ../lib/astutils.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkclass.h ../lib/checkers.h ../lib/config.h ../lib/errortypes.h ../lib/findtoken.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vfvalue.h +$(libcppdir)/astutils.o: ../lib/astutils.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkclass.h ../lib/checkers.h ../lib/checkimpl.h ../lib/config.h ../lib/errortypes.h ../lib/findtoken.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/astutils.cpp -$(libcppdir)/check.o: ../lib/check.cpp ../lib/addoninfo.h ../lib/check.h ../lib/checkers.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/standards.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h - $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/check.cpp - -$(libcppdir)/check64bit.o: ../lib/check64bit.cpp ../lib/addoninfo.h ../lib/check.h ../lib/check64bit.h ../lib/checkers.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/check64bit.o: ../lib/check64bit.cpp ../lib/addoninfo.h ../lib/check.h ../lib/check64bit.h ../lib/checkers.h ../lib/checkimpl.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/check64bit.cpp -$(libcppdir)/checkassert.o: ../lib/checkassert.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkassert.h ../lib/checkers.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checkassert.o: ../lib/checkassert.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkassert.h ../lib/checkers.h ../lib/checkimpl.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkassert.cpp -$(libcppdir)/checkautovariables.o: ../lib/checkautovariables.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkautovariables.h ../lib/checkers.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h +$(libcppdir)/checkautovariables.o: ../lib/checkautovariables.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkautovariables.h ../lib/checkers.h ../lib/checkimpl.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkautovariables.cpp -$(libcppdir)/checkbool.o: ../lib/checkbool.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkbool.h ../lib/checkers.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checkbool.o: ../lib/checkbool.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkbool.h ../lib/checkers.h ../lib/checkimpl.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkbool.cpp -$(libcppdir)/checkbufferoverrun.o: ../lib/checkbufferoverrun.cpp ../externals/tinyxml2/tinyxml2.h ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkbufferoverrun.h ../lib/checkers.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vf_common.h ../lib/vfvalue.h ../lib/xml.h +$(libcppdir)/checkbufferoverrun.o: ../lib/checkbufferoverrun.cpp ../externals/tinyxml2/tinyxml2.h ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkbufferoverrun.h ../lib/checkers.h ../lib/checkimpl.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vf_common.h ../lib/vfvalue.h ../lib/xml.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkbufferoverrun.cpp -$(libcppdir)/checkclass.o: ../lib/checkclass.cpp ../externals/tinyxml2/tinyxml2.h ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkclass.h ../lib/checkers.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h ../lib/xml.h +$(libcppdir)/checkclass.o: ../lib/checkclass.cpp ../externals/tinyxml2/tinyxml2.h ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkclass.h ../lib/checkers.h ../lib/checkimpl.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h ../lib/xml.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkclass.cpp -$(libcppdir)/checkcondition.o: ../lib/checkcondition.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkcondition.h ../lib/checkers.h ../lib/checkother.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checkcondition.o: ../lib/checkcondition.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkcondition.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checkother.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkcondition.cpp $(libcppdir)/checkers.o: ../lib/checkers.cpp ../lib/checkers.h ../lib/config.h @@ -204,58 +201,61 @@ $(libcppdir)/checkersidmapping.o: ../lib/checkersidmapping.cpp ../lib/checkers.h $(libcppdir)/checkersreport.o: ../lib/checkersreport.cpp ../lib/addoninfo.h ../lib/checkers.h ../lib/checkersreport.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/standards.h ../lib/utils.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkersreport.cpp -$(libcppdir)/checkexceptionsafety.o: ../lib/checkexceptionsafety.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkexceptionsafety.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checkexceptionsafety.o: ../lib/checkexceptionsafety.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkexceptionsafety.h ../lib/checkimpl.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkexceptionsafety.cpp -$(libcppdir)/checkfunctions.o: ../lib/checkfunctions.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkfunctions.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h +$(libcppdir)/checkfunctions.o: ../lib/checkfunctions.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkfunctions.h ../lib/checkimpl.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkfunctions.cpp -$(libcppdir)/checkinternal.o: ../lib/checkinternal.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkinternal.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checkimpl.o: ../lib/checkimpl.cpp ../lib/addoninfo.h ../lib/checkers.h ../lib/checkimpl.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/standards.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h + $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkimpl.cpp + +$(libcppdir)/checkinternal.o: ../lib/checkinternal.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checkinternal.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkinternal.cpp -$(libcppdir)/checkio.o: ../lib/checkio.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkio.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checkio.o: ../lib/checkio.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checkio.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkio.cpp -$(libcppdir)/checkleakautovar.o: ../lib/checkleakautovar.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkleakautovar.h ../lib/checkmemoryleak.h ../lib/checknullpointer.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checkleakautovar.o: ../lib/checkleakautovar.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checkleakautovar.h ../lib/checkmemoryleak.h ../lib/checknullpointer.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkleakautovar.cpp -$(libcppdir)/checkmemoryleak.o: ../lib/checkmemoryleak.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkmemoryleak.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checkmemoryleak.o: ../lib/checkmemoryleak.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checkmemoryleak.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkmemoryleak.cpp -$(libcppdir)/checknullpointer.o: ../lib/checknullpointer.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checknullpointer.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h +$(libcppdir)/checknullpointer.o: ../lib/checknullpointer.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checknullpointer.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checknullpointer.cpp -$(libcppdir)/checkother.o: ../lib/checkother.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkother.h ../lib/config.h ../lib/errortypes.h ../lib/fwdanalysis.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h +$(libcppdir)/checkother.o: ../lib/checkother.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checkother.h ../lib/config.h ../lib/errortypes.h ../lib/fwdanalysis.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkother.cpp -$(libcppdir)/checkpostfixoperator.o: ../lib/checkpostfixoperator.cpp ../lib/addoninfo.h ../lib/check.h ../lib/checkers.h ../lib/checkpostfixoperator.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checkpostfixoperator.o: ../lib/checkpostfixoperator.cpp ../lib/addoninfo.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checkpostfixoperator.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkpostfixoperator.cpp -$(libcppdir)/checks.o: ../lib/checks.cpp ../lib/check.h ../lib/check64bit.h ../lib/checkassert.h ../lib/checkautovariables.h ../lib/checkbool.h ../lib/checkbufferoverrun.h ../lib/checkclass.h ../lib/checkcondition.h ../lib/checkexceptionsafety.h ../lib/checkfunctions.h ../lib/checkinternal.h ../lib/checkio.h ../lib/checkleakautovar.h ../lib/checkmemoryleak.h ../lib/checknullpointer.h ../lib/checkother.h ../lib/checkpostfixoperator.h ../lib/checks.h ../lib/checksizeof.h ../lib/checkstl.h ../lib/checkstring.h ../lib/checktype.h ../lib/checkuninitvar.h ../lib/checkunusedvar.h ../lib/checkvaarg.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/standards.h ../lib/vfvalue.h +$(libcppdir)/checks.o: ../lib/checks.cpp ../lib/check.h ../lib/check64bit.h ../lib/checkassert.h ../lib/checkautovariables.h ../lib/checkbool.h ../lib/checkbufferoverrun.h ../lib/checkclass.h ../lib/checkcondition.h ../lib/checkexceptionsafety.h ../lib/checkfunctions.h ../lib/checkimpl.h ../lib/checkinternal.h ../lib/checkio.h ../lib/checkleakautovar.h ../lib/checkmemoryleak.h ../lib/checknullpointer.h ../lib/checkother.h ../lib/checkpostfixoperator.h ../lib/checks.h ../lib/checksizeof.h ../lib/checkstl.h ../lib/checkstring.h ../lib/checktype.h ../lib/checkuninitvar.h ../lib/checkunusedvar.h ../lib/checkvaarg.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/standards.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checks.cpp -$(libcppdir)/checksizeof.o: ../lib/checksizeof.cpp ../lib/addoninfo.h ../lib/check.h ../lib/checkers.h ../lib/checksizeof.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checksizeof.o: ../lib/checksizeof.cpp ../lib/addoninfo.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checksizeof.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checksizeof.cpp -$(libcppdir)/checkstl.o: ../lib/checkstl.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checknullpointer.h ../lib/checkstl.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/pathanalysis.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h +$(libcppdir)/checkstl.o: ../lib/checkstl.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checknullpointer.h ../lib/checkstl.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/pathanalysis.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkstl.cpp -$(libcppdir)/checkstring.o: ../lib/checkstring.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkstring.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checkstring.o: ../lib/checkstring.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checkstring.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkstring.cpp -$(libcppdir)/checktype.o: ../lib/checktype.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checktype.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h +$(libcppdir)/checktype.o: ../lib/checktype.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checktype.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checktype.cpp -$(libcppdir)/checkuninitvar.o: ../lib/checkuninitvar.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checknullpointer.h ../lib/checkuninitvar.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checkuninitvar.o: ../lib/checkuninitvar.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checknullpointer.h ../lib/checkuninitvar.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkuninitvar.cpp $(libcppdir)/checkunusedfunctions.o: ../lib/checkunusedfunctions.cpp ../externals/tinyxml2/tinyxml2.h ../lib/addoninfo.h ../lib/analyzerinfo.h ../lib/astutils.h ../lib/checkers.h ../lib/checkunusedfunctions.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h ../lib/xml.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkunusedfunctions.cpp -$(libcppdir)/checkunusedvar.o: ../lib/checkunusedvar.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkunusedvar.h ../lib/config.h ../lib/errortypes.h ../lib/fwdanalysis.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h +$(libcppdir)/checkunusedvar.o: ../lib/checkunusedvar.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checkunusedvar.h ../lib/config.h ../lib/errortypes.h ../lib/fwdanalysis.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkunusedvar.cpp -$(libcppdir)/checkvaarg.o: ../lib/checkvaarg.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkvaarg.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h +$(libcppdir)/checkvaarg.o: ../lib/checkvaarg.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkimpl.h ../lib/checkvaarg.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkvaarg.cpp $(libcppdir)/clangimport.o: ../lib/clangimport.cpp ../lib/clangimport.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h diff --git a/test/test64bit.cpp b/test/test64bit.cpp index 6f9a5fbda2f..da837fd9a96 100644 --- a/test/test64bit.cpp +++ b/test/test64bit.cpp @@ -49,8 +49,7 @@ class Test64BitPortability : public TestFixture { SimpleTokenizer tokenizer(settings, *this, cpp); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check char variable usage.. - Check64BitPortability check64BitPortability(&tokenizer, &settings, this); + Check64BitPortabilityImpl check64BitPortability(&tokenizer, &settings, this); check64BitPortability.pointerassignment(); } diff --git a/test/testcharvar.cpp b/test/testcharvar.cpp index 624efcff539..bb98dfad48d 100644 --- a/test/testcharvar.cpp +++ b/test/testcharvar.cpp @@ -47,7 +47,7 @@ class TestCharVar : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check char variable usage.. - CheckOther checkOther(&tokenizer, &settings, this); + CheckOtherImpl checkOther(&tokenizer, &settings, this); checkOther.checkCharVariable(); } diff --git a/test/testclass.cpp b/test/testclass.cpp index c1b801c208b..35994e98cf4 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -270,7 +270,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); (checkClass.checkCopyCtorAndEqOperator)(); } @@ -371,7 +371,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings0, this); + CheckClassImpl checkClass(&tokenizer, &settings0, this); (checkClass.checkExplicitConstructors)(); } @@ -528,7 +528,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings1, this); + CheckClassImpl checkClass(&tokenizer, &settings1, this); (checkClass.checkDuplInheritedMembers)(); } @@ -752,7 +752,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings3, this); + CheckClassImpl checkClass(&tokenizer, &settings3, this); checkClass.copyconstructors(); } @@ -1223,7 +1223,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings0, this); + CheckClassImpl checkClass(&tokenizer, &settings0, this); checkClass.operatorEqRetRefThis(); } @@ -1694,7 +1694,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings1, this); + CheckClassImpl checkClass(&tokenizer, &settings1, this); checkClass.operatorEqToSelf(); } @@ -2657,7 +2657,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &s, this); + CheckClassImpl checkClass(&tokenizer, &s, this); checkClass.virtualDestructor(); } @@ -2994,7 +2994,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); checkClass.checkMemset(); } @@ -3640,7 +3640,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings1, this); + CheckClassImpl checkClass(&tokenizer, &settings1, this); checkClass.thisSubtraction(); } @@ -3680,7 +3680,7 @@ class TestClass : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); (checkClass.checkConst)(); } @@ -7863,7 +7863,7 @@ class TestClass : public TestFixture { SimpleTokenizer tokenizer(settings2, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - CheckClass checkClass(&tokenizer, &settings2, this); + CheckClassImpl checkClass(&tokenizer, &settings2, this); checkClass.initializerListOrder(); } @@ -8017,7 +8017,7 @@ class TestClass : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); checkClass.initializationListUsage(); } @@ -8241,7 +8241,7 @@ class TestClass : public TestFixture { SimpleTokenizer tokenizer(settings0, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - CheckClass checkClass(&tokenizer, &settings0, this); + CheckClassImpl checkClass(&tokenizer, &settings0, this); (checkClass.checkSelfInitialization)(); } @@ -8351,7 +8351,7 @@ class TestClass : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); checkClass.checkVirtualFunctionCallInConstructor(); } @@ -8696,7 +8696,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); (checkClass.checkOverride)(); } @@ -8908,7 +8908,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); (checkClass.checkUselessOverride)(); } @@ -9098,7 +9098,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); (checkClass.checkUnsafeClassRefMember)(); } @@ -9116,7 +9116,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings1, this); + CheckClassImpl checkClass(&tokenizer, &settings1, this); (checkClass.checkThisUseAfterFree)(); } @@ -9353,7 +9353,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); (checkClass.checkReturnByReference)(); } diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp index 0eb91ba8cca..8bec74529b6 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -52,7 +52,7 @@ class TestConstructors : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check class constructors.. - CheckClass checkClass(&tokenizer, &settings1, this); + CheckClassImpl checkClass(&tokenizer, &settings1, this); checkClass.constructors(); } diff --git a/test/testincompletestatement.cpp b/test/testincompletestatement.cpp index 3d8f5d4d713..bd94b52af0e 100644 --- a/test/testincompletestatement.cpp +++ b/test/testincompletestatement.cpp @@ -50,7 +50,7 @@ class TestIncompleteStatement : public TestFixture { ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); // Check for incomplete statements.. - CheckOther checkOther(&tokenizer, &settings1, this); + CheckOtherImpl checkOther(&tokenizer, &settings1, this); checkOther.checkIncompleteStatement(); } diff --git a/test/testio.cpp b/test/testio.cpp index d3344f76b8d..bc6e40034f6 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -109,7 +109,7 @@ class TestIO : public TestFixture { // Check.. if (options.onlyFormatStr) { - CheckIO checkIO(&tokenizer, &settings1, this); + CheckIOImpl checkIO(&tokenizer, &settings1, this); checkIO.checkWrongPrintfScanfArguments(); return; } diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 1ed88120886..8982215d8e3 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -39,13 +39,12 @@ class TestMemleak : public TestFixture { #define functionReturnType(...) functionReturnType_(__FILE__, __LINE__, __VA_ARGS__) template - CheckMemoryLeak::AllocType functionReturnType_(const char* file, int line, const char (&code)[size]) { + CheckMemoryLeakImpl::AllocType functionReturnType_(const char* file, int line, const char (&code)[size]) { // Tokenize.. SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - const CheckMemoryLeak c(&tokenizer, this, &settingsDefault); - + const CheckMemoryLeakImpl c(&tokenizer, &settingsDefault, this); return (c.functionReturnType)(&tokenizer.getSymbolDatabase()->scopeList.front().functionList.front()); } @@ -53,19 +52,19 @@ class TestMemleak : public TestFixture { { const char code[] = "const char *foo()\n" "{ return 0; }"; - ASSERT_EQUALS(CheckMemoryLeak::No, functionReturnType(code)); + ASSERT_EQUALS(CheckMemoryLeakImpl::No, functionReturnType(code)); } { const char code[] = "Fred *newFred()\n" "{ return new Fred; }"; - ASSERT_EQUALS(CheckMemoryLeak::New, functionReturnType(code)); + ASSERT_EQUALS(CheckMemoryLeakImpl::New, functionReturnType(code)); } { const char code[] = "char *foo()\n" "{ return new char[100]; }"; - ASSERT_EQUALS(CheckMemoryLeak::NewArray, functionReturnType(code)); + ASSERT_EQUALS(CheckMemoryLeakImpl::NewArray, functionReturnType(code)); } { @@ -74,7 +73,7 @@ class TestMemleak : public TestFixture { " char *p = new char[100];\n" " return p;\n" "}"; - ASSERT_EQUALS(CheckMemoryLeak::NewArray, functionReturnType(code)); + ASSERT_EQUALS(CheckMemoryLeakImpl::NewArray, functionReturnType(code)); } } @@ -94,8 +93,8 @@ class TestMemleak : public TestFixture { // there is no allocation const Token *tok = Token::findsimplematch(tokenizer.tokens(), "ret ="); - const CheckMemoryLeak check(&tokenizer, nullptr, &settingsDefault); - ASSERT_EQUALS(CheckMemoryLeak::No, check.getAllocationType(tok->tokAt(2), 1)); + const CheckMemoryLeakImpl check(&tokenizer, &settingsDefault, nullptr); + ASSERT_EQUALS(CheckMemoryLeakImpl::No, check.getAllocationType(tok->tokAt(2), 1)); } }; @@ -120,7 +119,7 @@ class TestMemleakInFunction : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for memory leaks.. - CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &settings, this); + CheckMemoryLeakInFunctionImpl checkMemoryLeak(&tokenizer, &settings, this); checkMemoryLeak.checkReallocUsage(); } @@ -502,7 +501,7 @@ class TestMemleakInClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for memory leaks.. - CheckMemoryLeakInClass checkMemoryLeak(&tokenizer, &settings, this); + CheckMemoryLeakInClassImpl checkMemoryLeak(&tokenizer, &settings, this); (checkMemoryLeak.check)(); } @@ -1707,7 +1706,7 @@ class TestMemleakStructMember : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for memory leaks.. - CheckMemoryLeakStructMember checkMemoryLeakStructMember(&tokenizer, &settings, this); + CheckMemoryLeakStructMemberImpl checkMemoryLeakStructMember(&tokenizer, &settings, this); (checkMemoryLeakStructMember.check)(); } @@ -2389,7 +2388,7 @@ class TestMemleakNoVar : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for memory leaks.. - CheckMemoryLeakNoVar checkMemoryLeakNoVar(&tokenizer, &settings, this); + CheckMemoryLeakNoVarImpl checkMemoryLeakNoVar(&tokenizer, &settings, this); (checkMemoryLeakNoVar.check)(); } diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index a154bd0d9c2..3e9d4011500 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -4351,7 +4351,7 @@ class TestNullPointer : public TestFixture { Library library; ASSERT(LibraryHelper::loadxmldata(library, xmldata, sizeof(xmldata))); - const std::list null = CheckNullPointer::parseFunctionCall(*xtok, library); + const std::list null = CheckNullPointerImpl::parseFunctionCall(*xtok, library); ASSERT_EQUALS(0U, null.size()); } @@ -4369,7 +4369,7 @@ class TestNullPointer : public TestFixture { Library library; ASSERT(LibraryHelper::loadxmldata(library, xmldata, sizeof(xmldata))); - const std::list null = CheckNullPointer::parseFunctionCall(*xtok, library); + const std::list null = CheckNullPointerImpl::parseFunctionCall(*xtok, library); ASSERT_EQUALS(1U, null.size()); ASSERT_EQUALS("a", null.front()->str()); } diff --git a/test/testother.cpp b/test/testother.cpp index 9a18a067231..321657c668f 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2055,7 +2055,7 @@ class TestOther : public TestFixture { SimpleTokenizer tokenizerCpp(settings, *this); ASSERT_LOC(tokenizerCpp.tokenize(code), file, line); - CheckOther checkOtherCpp(&tokenizerCpp, &settings, this); + CheckOtherImpl checkOtherCpp(&tokenizerCpp, &settings, this); checkOtherCpp.warningOldStylePointerCast(); checkOtherCpp.warningDangerousTypeCast(); } @@ -2341,7 +2341,7 @@ class TestOther : public TestFixture { SimpleTokenizer tokenizerCpp(settings, *this); ASSERT_LOC(tokenizerCpp.tokenize(code), file, line); - CheckOther checkOtherCpp(&tokenizerCpp, &settings, this); + CheckOtherImpl checkOtherCpp(&tokenizerCpp, &settings, this); checkOtherCpp.warningIntToPointerCast(); } @@ -2380,7 +2380,7 @@ class TestOther : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - CheckOther checkOtherCpp(&tokenizer, &settings, this); + CheckOtherImpl checkOtherCpp(&tokenizer, &settings, this); checkOtherCpp.invalidPointerCast(); } diff --git a/test/testpostfixoperator.cpp b/test/testpostfixoperator.cpp index 9e95fabc949..1d01217231a 100644 --- a/test/testpostfixoperator.cpp +++ b/test/testpostfixoperator.cpp @@ -38,8 +38,7 @@ class TestPostfixOperator : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check for postfix operators.. - CheckPostfixOperator checkPostfixOperator(&tokenizer, &settings, this); + CheckPostfixOperatorImpl checkPostfixOperator(&tokenizer, &settings, this); checkPostfixOperator.postfixOperator(); } diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 6fe563a57ca..6ad2047ddd7 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -127,7 +127,7 @@ class TestUninitVar : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for redundant code.. - CheckUninitVar checkuninitvar(&tokenizer, &settings1, this); + CheckUninitVarImpl checkuninitvar(&tokenizer, &settings1, this); checkuninitvar.check(); } @@ -137,7 +137,7 @@ class TestUninitVar : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for redundant code.. - CheckUninitVar checkuninitvar(&tokenizer, &settings, this); + CheckUninitVarImpl checkuninitvar(&tokenizer, &settings, this); checkuninitvar.check(); } @@ -3673,7 +3673,7 @@ class TestUninitVar : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for redundant code.. - CheckUninitVar checkuninitvar(&tokenizer, &settings, this); + CheckUninitVarImpl checkuninitvar(&tokenizer, &settings, this); (checkuninitvar.valueFlowUninit)(); } diff --git a/test/testunusedprivfunc.cpp b/test/testunusedprivfunc.cpp index 5a364347163..3b419814dca 100644 --- a/test/testunusedprivfunc.cpp +++ b/test/testunusedprivfunc.cpp @@ -104,7 +104,7 @@ class TestUnusedPrivateFunction : public TestFixture { ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); // Check for unused private functions.. - CheckClass checkClass(&tokenizer, &settings1, this); + CheckClassImpl checkClass(&tokenizer, &settings1, this); checkClass.privateFunctions(); } diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 13d288a3fdd..d0ad22b004d 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -290,7 +290,7 @@ class TestUnusedVar : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for unused variables.. - CheckUnusedVar checkUnusedVar(&tokenizer, &settings, this); + CheckUnusedVarImpl checkUnusedVar(&tokenizer, &settings, this); checkUnusedVar.checkFunctionVariableUsage(); } @@ -310,7 +310,7 @@ class TestUnusedVar : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for unused variables.. - CheckUnusedVar checkUnusedVar(&tokenizer, &settings, this); + CheckUnusedVarImpl checkUnusedVar(&tokenizer, &settings, this); (checkUnusedVar.checkStructMemberUsage)(); } @@ -323,7 +323,7 @@ class TestUnusedVar : public TestFixture { ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); // Check for unused variables.. - CheckUnusedVar checkUnusedVar(&tokenizer, &settings, this); + CheckUnusedVarImpl checkUnusedVar(&tokenizer, &settings, this); (checkUnusedVar.checkStructMemberUsage)(); } @@ -336,7 +336,7 @@ class TestUnusedVar : public TestFixture { ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); // Check for unused variables.. - CheckUnusedVar checkUnusedVar(&tokenizer, &settings, this); + CheckUnusedVarImpl checkUnusedVar(&tokenizer, &settings, this); (checkUnusedVar.checkFunctionVariableUsage)(); } diff --git a/tools/dmake/dmake.cpp b/tools/dmake/dmake.cpp index 80f3aa35b83..3d08943f5ba 100644 --- a/tools/dmake/dmake.cpp +++ b/tools/dmake/dmake.cpp @@ -495,6 +495,7 @@ int main(int argc, char **argv) } libfiles_h.emplace("analyzer.h"); libfiles_h.emplace("calculate.h"); + libfiles_h.emplace("check.h"); libfiles_h.emplace("config.h"); libfiles_h.emplace("filesettings.h"); libfiles_h.emplace("findtoken.h"); @@ -559,7 +560,7 @@ int main(int argc, char **argv) for (const std::string &libfile: libfiles_prio) { const std::string l = libfile.substr(4); - outstr += make_vcxproj_cl_entry(l, l == "check.cpp" ? Precompile : Compile); + outstr += make_vcxproj_cl_entry(l, l == "checkimpl.cpp" ? Precompile : Compile); } }, [&](std::string &outstr){ outstr += make_vcxproj_cl_entry(R"(..\externals\simplecpp\simplecpp.h)", Include);