refs #11928 / refs #10045 / fixes #11794 - generate `limits.h`/`climits` defines from platform (#5414)
This commit is contained in:
parent
09785a4eb8
commit
3103736c51
6
Makefile
6
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
|
||||
|
|
150
lib/platform.cpp
150
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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>"
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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.
|
|
@ -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 "$@"
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue