diff --git a/Makefile b/Makefile index 632837053..7ae63ab26 100644 --- a/Makefile +++ b/Makefile @@ -470,7 +470,7 @@ $(libcppdir)/symboldatabase.o: lib/symboldatabase.cpp lib/addoninfo.h lib/astuti $(libcppdir)/addoninfo.o: lib/addoninfo.cpp externals/picojson/picojson.h lib/addoninfo.h lib/config.h lib/json.h lib/path.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/addoninfo.cpp -$(libcppdir)/analyzerinfo.o: lib/analyzerinfo.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/path.h lib/platform.h lib/utils.h +$(libcppdir)/analyzerinfo.o: lib/analyzerinfo.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/path.h lib/platform.h lib/standards.h lib/utils.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/config.h lib/errortypes.h lib/findtoken.h lib/importproject.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vfvalue.h @@ -608,7 +608,7 @@ $(libcppdir)/pathanalysis.o: lib/pathanalysis.cpp lib/astutils.h lib/config.h li $(libcppdir)/pathmatch.o: lib/pathmatch.cpp lib/config.h lib/path.h lib/pathmatch.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/pathmatch.cpp -$(libcppdir)/platform.o: lib/platform.cpp externals/tinyxml2/tinyxml2.h lib/config.h lib/path.h lib/platform.h +$(libcppdir)/platform.o: lib/platform.cpp externals/tinyxml2/tinyxml2.h lib/config.h lib/path.h lib/platform.h lib/standards.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/platform.cpp $(libcppdir)/preprocessor.o: lib/preprocessor.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h @@ -863,7 +863,7 @@ test/testtokenlist.o: test/testtokenlist.cpp lib/addoninfo.h lib/check.h lib/col test/testtokenrange.o: test/testtokenrange.cpp lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/suppressions.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 $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtokenrange.cpp -test/testtype.o: test/testtype.cpp lib/addoninfo.h lib/check.h lib/checktype.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h +test/testtype.o: test/testtype.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checktype.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtype.cpp test/testuninitvar.o: test/testuninitvar.cpp lib/addoninfo.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h diff --git a/lib/platform.cpp b/lib/platform.cpp index 7d3802174..9d849072c 100644 --- a/lib/platform.cpp +++ b/lib/platform.cpp @@ -294,3 +294,153 @@ bool Platform::loadFromXmlDocument(const tinyxml2::XMLDocument *doc) type = Type::File; return !error; } + +std::string Platform::getLimitsDefines(bool c99) const +{ + std::string s; + + // climits / limits.h + s += "CHAR_BIT="; + s += std::to_string(char_bit); + s += ";SCHAR_MIN="; + s += std::to_string(min_value(char_bit)); + s += ";SCHAR_MAX="; + s += std::to_string(max_value(char_bit)); + s += ";UCHAR_MAX="; + s += std::to_string(max_value(char_bit+1)); + s += ";CHAR_MIN="; + if (defaultSign == 'u') + s += std::to_string(min_value(char_bit)); + else + s += std::to_string(0); + s += ";CHAR_MAX="; + if (defaultSign == 'u') + s += std::to_string(max_value(char_bit+1)); + else + s += std::to_string(max_value(char_bit)); + // TODO + //s += ";MB_LEN_MAX="; + s += ";SHRT_MIN="; + s += std::to_string(min_value(short_bit)); + s += ";SHRT_MAX="; + s += std::to_string(max_value(short_bit)); + s += ";USHRT_MAX="; + s += std::to_string(max_value(short_bit+1)); + s += ";INT_MIN="; + s += std::to_string(min_value(int_bit)); + s += ";INT_MAX="; + s += std::to_string(max_value(int_bit)); + s += ";UINT_MAX="; + s += std::to_string(max_value(int_bit+1)); + s += ";LONG_MIN="; + s += std::to_string(min_value(long_bit)); + s += ";LONG_MAX="; + s += std::to_string(max_value(long_bit)); + s += ";ULONG_MAX="; + s += std::to_string(max_value(long_bit+1)); + if (c99) { + s += ";LLONG_MIN="; + s += std::to_string(min_value(long_long_bit)); + s += ";LLONG_MAX="; + s += std::to_string(max_value(long_long_bit)); + s += ";ULLONG_MAX="; + s += std::to_string(max_value(long_long_bit + 1)); + } + + // cstdint / stdint.h + // FIXME: these are currently hard-coded in std.cfg + /* + INTMAX_MIN + INTMAX_MAX + UINTMAX_MAX + INTN_MIN + INTN_MAX + UINTN_MAX + INT_LEASTN_MIN + INT_LEASTN_MAX + UINT_LEASTN_MAX + INT_FASTN_MIN + INT_FASTN_MAX + UINT_FASTN_MAX + INTPTR_MIN + INTPTR_MAX + UINTPTR_MAX + SIZE_MAX + PTRDIFF_MIN + PTRDIFF_MAX + SIG_ATOMIC_MIN + SIG_ATOMIC_MAX + WCHAR_MIN + WCHAR_MAX + WINT_MIN + WINT_MAX + + // function-like macros + // implemented in std.cfg + INTMAX_C + UINTMAX_C + INTN_C + UINTN_C + */ + + // cfloat / float.h + /* + // TODO: implement + FLT_RADIX + + FLT_MANT_DIG + DBL_MANT_DIG + LDBL_MANT_DIG + + FLT_DIG + DBL_DIG + LDBL_DIG + + FLT_MIN_EXP + DBL_MIN_EXP + LDBL_MIN_EXP + + FLT_MIN_10_EXP + DBL_MIN_10_EXP + LDBL_MIN_10_EXP + + FLT_MAX_EXP + DBL_MAX_EXP + LDBL_MAX_EXP + + FLT_MAX_10_EXP + DBL_MAX_10_EXP + LDBL_MAX_10_EXP + + FLT_MAX + DBL_MAX + LDBL_MAX + + FLT_EPSILON + DBL_EPSILON + LDBL_EPSILON + + FLT_MIN + DBL_MIN + LDBL_MIN + + FLT_ROUNDS + + // C99 / C++11 only + FLT_EVAL_METHOD + + DECIMAL_DIG + */ + + return s; +} + +std::string Platform::getLimitsDefines(Standards::cstd_t cstd) const +{ + return getLimitsDefines(cstd >= Standards::cstd_t::C99); +} + +std::string Platform::getLimitsDefines(Standards::cppstd_t cppstd) const +{ + return getLimitsDefines(cppstd >= Standards::cppstd_t::CPP11); +} diff --git a/lib/platform.h b/lib/platform.h index 323be855a..5e4e51e71 100644 --- a/lib/platform.h +++ b/lib/platform.h @@ -22,6 +22,7 @@ //--------------------------------------------------------------------------- #include "config.h" +#include "standards.h" #include #include @@ -51,6 +52,9 @@ private: return (~0ULL) >> 1; return (1LL << (bit-1)) - 1LL; } + + /** provides list of defines specified by the limit.h/climits includes */ + std::string getLimitsDefines(bool c99) const; public: Platform(); @@ -178,6 +182,11 @@ public: long long signedCharMin() const { return min_value(char_bit); } + + /** provides list of defines specified by the limit.h/climits includes */ + std::string getLimitsDefines(Standards::cstd_t cstd) const; + /** provides list of defines specified by the limit.h/climits includes */ + std::string getLimitsDefines(Standards::cppstd_t cppstd) const; }; /// @} diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index d4c1804b8..4efba6d1e 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -700,6 +700,7 @@ static void splitcfg(const std::string &cfg, std::list &defines, co static simplecpp::DUI createDUI(const Settings &mSettings, const std::string &cfg, const std::string &filename) { + // TODO: make it possible to specify platform-dependent sizes simplecpp::DUI dui; splitcfg(mSettings.userDefines, dui.defines, "1"); @@ -725,10 +726,14 @@ static simplecpp::DUI createDUI(const Settings &mSettings, const std::string &cf dui.includePaths = mSettings.includePaths; // -I dui.includes = mSettings.userIncludes; // --include // TODO: use mSettings.standards.stdValue instead - if (Path::isCPP(filename)) + if (Path::isCPP(filename)) { dui.std = mSettings.standards.getCPP(); - else + splitcfg(mSettings.platform.getLimitsDefines(Standards::getCPP(dui.std)), dui.defines, ""); + } + else { dui.std = mSettings.standards.getC(); + splitcfg(mSettings.platform.getLimitsDefines(Standards::getC(dui.std)), dui.defines, ""); + } dui.clearIncludeCache = mSettings.clearIncludeCache; return dui; } diff --git a/test/helpers.cpp b/test/helpers.cpp index 8834870d7..1f58eeff8 100644 --- a/test/helpers.cpp +++ b/test/helpers.cpp @@ -154,6 +154,11 @@ void PreprocessorHelper::preprocess(const char code[], std::vector } void PreprocessorHelper::preprocess(Preprocessor &preprocessor, const char code[], std::vector &files, Tokenizer& tokenizer) +{ + preprocess(preprocessor, code, files, tokenizer, simplecpp::DUI()); +} + +void PreprocessorHelper::preprocess(Preprocessor &preprocessor, const char code[], std::vector &files, Tokenizer& tokenizer, const simplecpp::DUI& dui) { std::istringstream istr(code); const simplecpp::TokenList tokens1(istr, files, files[0]); @@ -161,7 +166,7 @@ void PreprocessorHelper::preprocess(Preprocessor &preprocessor, const char code[ // Preprocess.. simplecpp::TokenList tokens2(files); std::map filedata; - simplecpp::preprocess(tokens2, tokens1, files, filedata, simplecpp::DUI()); + simplecpp::preprocess(tokens2, tokens1, files, filedata, dui); // Tokenizer.. tokenizer.createTokens(std::move(tokens2)); diff --git a/test/helpers.h b/test/helpers.h index 65e9d4dfe..cc4634ea7 100644 --- a/test/helpers.h +++ b/test/helpers.h @@ -31,6 +31,9 @@ class Token; class Preprocessor; class Suppressions; +namespace simplecpp { + struct DUI; +} class givenACodeSampleToTokenize { private: @@ -95,6 +98,7 @@ public: static void preprocess(const char code[], std::vector &files, Tokenizer& tokenizer); static void preprocess(Preprocessor &preprocessor, const char code[], std::vector &files, Tokenizer& tokenizer); + static void preprocess(Preprocessor &preprocessor, const char code[], std::vector &files, Tokenizer& tokenizer, const simplecpp::DUI& dui); }; namespace cppcheck { diff --git a/test/testplatform.cpp b/test/testplatform.cpp index 06bce2138..41dccfe4a 100644 --- a/test/testplatform.cpp +++ b/test/testplatform.cpp @@ -41,6 +41,8 @@ private: TEST_CASE(invalid_config_file_1); TEST_CASE(empty_elements); TEST_CASE(default_platform); + TEST_CASE(limitsDefines); + TEST_CASE(charMinMax); } static bool readPlatform(Platform& platform, const char* xmldata) { @@ -392,6 +394,26 @@ private: Platform platform; ASSERT_EQUALS(Platform::Type::Native, platform.type); } + + void limitsDefines() const { + Platform platform; + platform.set(Platform::Unix64); + const std::string defs = "CHAR_BIT=8;SCHAR_MIN=-128;SCHAR_MAX=127;UCHAR_MAX=255;CHAR_MIN=0;CHAR_MAX=127;SHRT_MIN=-32768;SHRT_MAX=32767;USHRT_MAX=65535;INT_MIN=-2147483648;INT_MAX=2147483647;UINT_MAX=4294967295;LONG_MIN=-9223372036854775808;LONG_MAX=9223372036854775807;ULONG_MAX=9223372036854775807"; + const std::string defs_c99 = "CHAR_BIT=8;SCHAR_MIN=-128;SCHAR_MAX=127;UCHAR_MAX=255;CHAR_MIN=0;CHAR_MAX=127;SHRT_MIN=-32768;SHRT_MAX=32767;USHRT_MAX=65535;INT_MIN=-2147483648;INT_MAX=2147483647;UINT_MAX=4294967295;LONG_MIN=-9223372036854775808;LONG_MAX=9223372036854775807;ULONG_MAX=9223372036854775807;LLONG_MIN=-9223372036854775808;LLONG_MAX=9223372036854775807;ULLONG_MAX=9223372036854775807"; + ASSERT_EQUALS(defs, platform.getLimitsDefines(Standards::cstd_t::C89)); + ASSERT_EQUALS(defs_c99, platform.getLimitsDefines(Standards::cstd_t::C99)); + ASSERT_EQUALS(defs_c99, platform.getLimitsDefines(Standards::cstd_t::CLatest)); + ASSERT_EQUALS(defs, platform.getLimitsDefines(Standards::cppstd_t::CPP03)); + ASSERT_EQUALS(defs_c99, platform.getLimitsDefines(Standards::cppstd_t::CPP11)); + ASSERT_EQUALS(defs_c99, platform.getLimitsDefines(Standards::cppstd_t::CPPLatest)); + } + + void charMinMax() const { + Platform platform; + ASSERT_EQUALS(255, platform.unsignedCharMax()); + ASSERT_EQUALS(127, platform.signedCharMax()); + ASSERT_EQUALS(-128, platform.signedCharMin()); + } }; REGISTER_TEST(TestPlatform) diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 86effdcae..9d2bd010e 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -262,6 +262,8 @@ private: TEST_CASE(testMissingSystemInclude5); TEST_CASE(testMissingIncludeMixed); TEST_CASE(testMissingIncludeCheckConfig); + + TEST_CASE(limitsDefines); } // TODO: merge with `PreprocessorHelper::getcode()` @@ -2680,6 +2682,17 @@ private: "test.c:9:0: information: Include file: \"" + missing3 + "\" not found. [missingInclude]\n" "test.c:11:0: information: Include file: <" + missing4 + "> not found. Please note: Cppcheck does not need standard library headers to get proper results. [missingIncludeSystem]\n", errout.str()); } + + void limitsDefines() { + // #11928 / #10045 + const char code[] = "void f(long l) {\n" + " if (l > INT_MAX) {}\n" + "}"; + const std::string actual = PreprocessorHelper::getcode(preprocessor0, code, "", "test.c"); + ASSERT_EQUALS("void f ( long l ) {\n" + "if ( l > $2147483647 ) { }\n" + "}", actual); + } }; REGISTER_TEST(TestPreprocessor) diff --git a/test/testtype.cpp b/test/testtype.cpp index 1007e2b30..c2e436876 100644 --- a/test/testtype.cpp +++ b/test/testtype.cpp @@ -18,7 +18,9 @@ #include "checktype.h" #include "errortypes.h" +#include "helpers.h" #include "platform.h" +#include "preprocessor.h" #include "settings.h" #include "standards.h" #include "fixture.h" @@ -27,6 +29,8 @@ #include // IWYU pragma: keep #include +#include + class TestType : public TestFixture { public: TestType() : TestFixture("TestType") {} @@ -41,6 +45,7 @@ private: TEST_CASE(longCastAssign); TEST_CASE(longCastReturn); TEST_CASE(checkFloatToIntegerOverflow); + TEST_CASE(integerOverflow); // #11794 } #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__) @@ -59,6 +64,25 @@ private: runChecks(tokenizer, this); } +#define checkP(...) checkP_(__FILE__, __LINE__, __VA_ARGS__) + void checkP_(const char* file, int line, const char code[], const Settings& settings, const char filename[] = "test.cpp", const simplecpp::DUI& dui = simplecpp::DUI()) { + // Clear the error buffer.. + errout.str(""); + + const Settings settings1 = settingsBuilder(settings).severity(Severity::warning).severity(Severity::portability).build(); + + Preprocessor preprocessor(settings1); + std::vector files(1, filename); + Tokenizer tokenizer(&settings1, this, &preprocessor); + PreprocessorHelper::preprocess(preprocessor, code, files, tokenizer, dui); + + // Tokenizer.. + ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); + + // Check.. + runChecks(tokenizer, this); + } + void checkTooBigShift_Unix32() { const Settings settings0; const Settings settings = settingsBuilder().platform(Platform::Type::Unix32).build(); @@ -451,6 +475,26 @@ private: "}", settings); ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str())); } + + void integerOverflow() { // #11794 + const Settings settings; + // TODO: needs to use preprocessing production code + simplecpp::DUI dui; + dui.std = "c++11"; + // this is set by the production code via cppcheck::Platform::getLimitDefines() + dui.defines.emplace_back("INT_MIN=-2147483648"); + + checkP("int fun(int x)\n" + "{\n" + " if(x < 0) x = -x;\n" + " return x >= 0;\n" + "}\n" + "int f()\n" + "{\n" + " fun(INT_MIN);\n" + "}", settings, "test.cpp", dui); + ASSERT_EQUALS("[test.cpp:3]: (error) Signed integer overflow for expression '-x'.\n", errout.str()); + } }; REGISTER_TEST(TestType) diff --git a/tools/defines/create_platform_cfg.sh b/tools/defines/create_platform_cfg.sh new file mode 100755 index 000000000..1d9f23cd7 --- /dev/null +++ b/tools/defines/create_platform_cfg.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +if [ -n "$1" ]; then + compiler_cmd=$1 +else + compiler_cmd="gcc" +fi + +compiler_defs=$($compiler_cmd -dM -E - < /dev/null) + +char_bit=$(echo "$compiler_defs" | grep __CHAR_BIT__ | cut -d' ' -f3) +# only set by compiler if -funsigned-char is specified +char_unsigned=$(echo "$compiler_defs" | grep __CHAR_UNSIGNED__ | cut -d' ' -f3) +if [ -n "$char_unsigned" ] && [ "$char_unsigned" -eq 1 ]; then + default_sign="unsigned" +else + default_sign="signed" +fi +# TODO +size_of_bool= +size_of_short=$(echo "$compiler_defs" | grep __SIZEOF_SHORT__ | cut -d' ' -f3) +size_of_int=$(echo "$compiler_defs" | grep __SIZEOF_INT__ | cut -d' ' -f3) +size_of_long=$(echo "$compiler_defs" | grep __SIZEOF_LONG__ | cut -d' ' -f3) +size_of_long_long=$(echo "$compiler_defs" | grep __SIZEOF_LONG_LONG__ | cut -d' ' -f3) +size_of_float=$(echo "$compiler_defs" | grep __SIZEOF_FLOAT__ | cut -d' ' -f3) +size_of_double=$(echo "$compiler_defs" | grep __SIZEOF_DOUBLE__ | cut -d' ' -f3) +size_of_long_double=$(echo "$compiler_defs" | grep __SIZEOF_LONG_DOUBLE__ | cut -d' ' -f3) +size_of_pointer=$(echo "$compiler_defs" | grep __SIZEOF_POINTER__ | cut -d' ' -f3) +size_of_size_t=$(echo "$compiler_defs" | grep __SIZEOF_SIZE_T__ | cut -d' ' -f3) +size_of_wchar_t=$(echo "$compiler_defs" | grep __SIZEOF_WCHAR_T__ | cut -d' ' -f3) + +echo " + + $char_bit + $default_sign + + $size_of_bool + $size_of_short + $size_of_int + $size_of_long + $size_of_long_long + $size_of_float + $size_of_double + $size_of_long_double + $size_of_pointer + $size_of_size_t + $size_of_wchar_t + +" diff --git a/tools/defines/defines.sh b/tools/defines/defines.sh new file mode 100755 index 000000000..51696171c --- /dev/null +++ b/tools/defines/defines.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +gcc -Wall -Wextra limits.c +./a.out +gcc -Wall -Wextra float.c +./a.out +gcc -Wall -Wextra stdint.c +./a.out + +clang -Weverything limits.c +./a.out +clang -Weverything float.c +./a.out +clang -Weverything stdint.c +./a.out \ No newline at end of file diff --git a/tools/defines/float.c b/tools/defines/float.c new file mode 100644 index 000000000..1d53f8185 --- /dev/null +++ b/tools/defines/float.c @@ -0,0 +1,43 @@ +#include "float.h" +#include "stdio.h" + +#define PRINT_DEF(d, f) \ + fprintf(stdout, ";"#d"=%"#f, d) + +int main(void) +{ + PRINT_DEF(FLT_RADIX, d); + PRINT_DEF(FLT_MANT_DIG, d); + PRINT_DEF(DBL_MANT_DIG, d); + PRINT_DEF(LDBL_MANT_DIG, d); + PRINT_DEF(FLT_DIG, d); + PRINT_DEF(DBL_DIG, d); + PRINT_DEF(LDBL_DIG, d); + PRINT_DEF(FLT_MIN_EXP, d); + PRINT_DEF(DBL_MIN_EXP, d); + PRINT_DEF(LDBL_MIN_EXP, d); + PRINT_DEF(FLT_MIN_10_EXP, d); + PRINT_DEF(DBL_MIN_10_EXP, d); + PRINT_DEF(LDBL_MIN_10_EXP, d); + PRINT_DEF(FLT_MAX_EXP, d); + PRINT_DEF(DBL_MAX_EXP, d); + PRINT_DEF(LDBL_MAX_EXP, d); + PRINT_DEF(FLT_MAX_10_EXP, d); + PRINT_DEF(DBL_MAX_10_EXP, d); + PRINT_DEF(LDBL_MAX_10_EXP, d); + PRINT_DEF(FLT_MAX, f); // TODO: float-to-double + PRINT_DEF(DBL_MAX, f); + PRINT_DEF(LDBL_MAX, Lf); + PRINT_DEF(FLT_EPSILON, f); // TODO: float-to-double + PRINT_DEF(DBL_EPSILON, f); + PRINT_DEF(LDBL_EPSILON, Lf); + PRINT_DEF(FLT_MIN, f); // TODO: float-to-double + PRINT_DEF(DBL_MIN, f); + PRINT_DEF(LDBL_MIN, Lf); +#if (__STDC_VERSION__ >= 199901L) || (__cplusplus >= 201103L) + PRINT_DEF(FLT_EVAL_METHOD, d); + PRINT_DEF(DECIMAL_DIG, d); +#endif + + return 0; +} diff --git a/tools/defines/limits.c b/tools/defines/limits.c new file mode 100644 index 000000000..8f2d9c90a --- /dev/null +++ b/tools/defines/limits.c @@ -0,0 +1,32 @@ +#include "limits.h" +#include "stdio.h" + +#define PRINT_DEF(d, f) \ + fprintf(stdout, ";"#d"=%"#f, d) + +int main(void) +{ + PRINT_DEF(CHAR_BIT, d); + PRINT_DEF(SCHAR_MIN, d); + PRINT_DEF(SCHAR_MAX, d); + PRINT_DEF(UCHAR_MAX, d); + PRINT_DEF(CHAR_MIN, d); + PRINT_DEF(CHAR_MAX, d); + PRINT_DEF(MB_LEN_MAX, d); + PRINT_DEF(SHRT_MIN, d); + PRINT_DEF(SHRT_MAX, d); + PRINT_DEF(USHRT_MAX, d); + PRINT_DEF(INT_MIN, d); + PRINT_DEF(INT_MAX, d); + PRINT_DEF(UINT_MAX, u); + PRINT_DEF(LONG_MIN, ld); + PRINT_DEF(LONG_MAX, ld); + PRINT_DEF(ULONG_MAX, ld); +#if (__STDC_VERSION__ >= 199901L) || (__cplusplus >= 201103L) + PRINT_DEF(LLONG_MIN, lld); + PRINT_DEF(LLONG_MAX, lld); + PRINT_DEF(ULLONG_MAX, llu); +#endif + + return 0; +} diff --git a/tools/defines/readme.md b/tools/defines/readme.md new file mode 100644 index 000000000..ed9d372c0 --- /dev/null +++ b/tools/defines/readme.md @@ -0,0 +1,22 @@ +# Compiler defines + +NOTE: this is preliminary. + +This folder contains scripts to extract compiler-specific defines and definitions for use with a Cppcheck scan. + +Specifying these will get rid of `` warnings (which are reported when `--debug-warnings` is specified) which allows for increased coverage of the ValueFlow. + +## Files + +- `define.sh` +Invokes the compilation and execution of the various programs which output the compiler-specific defines. +- `float.c` +Outputs the defines provided by `float.h`/`cfloat`. +- `limits.c` +Outputs the defines provided by `limits.h`/`climits`. +- `stdint.c` +Outputs the defines provided by `stdint.h`/`cstdint`. +- `create_platform_cfg.sh` +Generates a platform file from the given compiler which can be given to Cppcheck via `--platform`. +- `run_cppcheck.sh` +Generates the compiler-specific configurations for the given compiler and runs Cppcheck with them. \ No newline at end of file diff --git a/tools/defines/run_cppcheck.sh b/tools/defines/run_cppcheck.sh new file mode 100644 index 000000000..af0567c58 --- /dev/null +++ b/tools/defines/run_cppcheck.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# TODO: use temporary filename +./create_platform_cfg.sh > platform.cfg + +# TODO: add option to pass define to cppcheck +./defines.sh > defines.txt + +./cppcheck --platform=platform.cfg "$@" \ No newline at end of file diff --git a/tools/defines/stdint.c b/tools/defines/stdint.c new file mode 100644 index 000000000..bd899140d --- /dev/null +++ b/tools/defines/stdint.c @@ -0,0 +1,44 @@ +#include "stdint.h" +#include "stdio.h" + +#define PRINT_DEF(d, f) \ + fprintf(stdout, ";"#d"=%"#f, d) + +#define PRINT_DEF_N(d1, d2, f) \ + do { \ + PRINT_DEF(d1 ## 8 ## d2, f); \ + PRINT_DEF(d1 ## 16 ## d2, f); \ + PRINT_DEF(d1 ## 32 ## d2, f); \ + PRINT_DEF(d1 ## 64 ## d2, l ## f); \ + } while (0) + +// TODO: fix all format specifiers +int main(void) +{ + PRINT_DEF(INTMAX_MIN, ld); + PRINT_DEF(INTMAX_MAX, ld); + PRINT_DEF(UINTMAX_MAX, lu); + PRINT_DEF_N(INT, _MIN, d); + PRINT_DEF_N(INT, _MAX, d); + PRINT_DEF_N(UINT, _MAX, u); + PRINT_DEF_N(INT_LEAST, _MIN, d); + PRINT_DEF_N(INT_LEAST, _MAX, d); + PRINT_DEF_N(UINT_LEAST, _MAX, u); + PRINT_DEF_N(INT_FAST, _MIN, d); + PRINT_DEF_N(INT_FAST, _MAX, d); + PRINT_DEF_N(UINT_FAST, _MAX, u); + PRINT_DEF(INTPTR_MIN, ld); + PRINT_DEF(INTPTR_MAX, ld); + PRINT_DEF(UINTPTR_MAX, lu); + PRINT_DEF(SIZE_MAX, lu); + PRINT_DEF(PTRDIFF_MIN, ld); + PRINT_DEF(PTRDIFF_MAX, ld); + PRINT_DEF(SIG_ATOMIC_MIN, d); + PRINT_DEF(SIG_ATOMIC_MAX, d); + PRINT_DEF(WCHAR_MIN, d); + PRINT_DEF(WCHAR_MAX, d); + PRINT_DEF(WINT_MIN, d); + PRINT_DEF(WINT_MAX, d); + + return 0; +}