refs #11928 / refs #10045 / fixes #11794 - generate `limits.h`/`climits` defines from platform (#5414)

This commit is contained in:
Oliver Stöneberg 2023-10-21 17:21:12 +02:00 committed by GitHub
parent 09785a4eb8
commit 3103736c51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 472 additions and 6 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -22,6 +22,7 @@
//---------------------------------------------------------------------------
#include "config.h"
#include "standards.h"
#include <climits>
#include <stdexcept>
@ -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;
};
/// @}

View File

@ -700,6 +700,7 @@ static void splitcfg(const std::string &cfg, std::list<std::string> &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;
}

View File

@ -154,6 +154,11 @@ void PreprocessorHelper::preprocess(const char code[], std::vector<std::string>
}
void PreprocessorHelper::preprocess(Preprocessor &preprocessor, const char code[], std::vector<std::string> &files, Tokenizer& tokenizer)
{
preprocess(preprocessor, code, files, tokenizer, simplecpp::DUI());
}
void PreprocessorHelper::preprocess(Preprocessor &preprocessor, const char code[], std::vector<std::string> &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<std::string, simplecpp::TokenList*> filedata;
simplecpp::preprocess(tokens2, tokens1, files, filedata, simplecpp::DUI());
simplecpp::preprocess(tokens2, tokens1, files, filedata, dui);
// Tokenizer..
tokenizer.createTokens(std::move(tokens2));

View File

@ -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<std::string> &files, Tokenizer& tokenizer);
static void preprocess(Preprocessor &preprocessor, const char code[], std::vector<std::string> &files, Tokenizer& tokenizer);
static void preprocess(Preprocessor &preprocessor, const char code[], std::vector<std::string> &files, Tokenizer& tokenizer, const simplecpp::DUI& dui);
};
namespace cppcheck {

View File

@ -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)

View File

@ -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)

View File

@ -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 <sstream> // IWYU pragma: keep
#include <string>
#include <simplecpp.h>
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<CheckType>(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<std::string> files(1, filename);
Tokenizer tokenizer(&settings1, this, &preprocessor);
PreprocessorHelper::preprocess(preprocessor, code, files, tokenizer, dui);
// Tokenizer..
ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line);
// Check..
runChecks<CheckType>(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)

View File

@ -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 "<?xml version=\"1.0\"?>
<platform>
<char_bit>$char_bit</char_bit>
<default-sign>$default_sign</default-sign>
<sizeof>
<bool>$size_of_bool</bool>
<short>$size_of_short</short>
<int>$size_of_int</int>
<long>$size_of_long</long>
<long-long>$size_of_long_long</long-long>
<float>$size_of_float</float>
<double>$size_of_double</double>
<long-double>$size_of_long_double</long-double>
<pointer>$size_of_pointer</pointer>
<size_t>$size_of_size_t</size_t>
<wchar_t>$size_of_wchar_t</wchar_t>
</sizeof>
</platform>"

15
tools/defines/defines.sh Executable file
View File

@ -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

43
tools/defines/float.c Normal file
View File

@ -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;
}

32
tools/defines/limits.c Normal file
View File

@ -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;
}

22
tools/defines/readme.md Normal file
View File

@ -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.

View File

@ -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 "$@"

44
tools/defines/stdint.c Normal file
View File

@ -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;
}