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
|
$(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
|
$(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
|
$(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
|
$(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
|
$(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
|
$(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
|
$(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
|
$(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
|
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
|
$(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
|
$(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
|
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;
|
type = Type::File;
|
||||||
return !error;
|
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 "config.h"
|
||||||
|
#include "standards.h"
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
@ -51,6 +52,9 @@ private:
|
||||||
return (~0ULL) >> 1;
|
return (~0ULL) >> 1;
|
||||||
return (1LL << (bit-1)) - 1LL;
|
return (1LL << (bit-1)) - 1LL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** provides list of defines specified by the limit.h/climits includes */
|
||||||
|
std::string getLimitsDefines(bool c99) const;
|
||||||
public:
|
public:
|
||||||
Platform();
|
Platform();
|
||||||
|
|
||||||
|
@ -178,6 +182,11 @@ public:
|
||||||
long long signedCharMin() const {
|
long long signedCharMin() const {
|
||||||
return min_value(char_bit);
|
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)
|
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;
|
simplecpp::DUI dui;
|
||||||
|
|
||||||
splitcfg(mSettings.userDefines, dui.defines, "1");
|
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.includePaths = mSettings.includePaths; // -I
|
||||||
dui.includes = mSettings.userIncludes; // --include
|
dui.includes = mSettings.userIncludes; // --include
|
||||||
// TODO: use mSettings.standards.stdValue instead
|
// TODO: use mSettings.standards.stdValue instead
|
||||||
if (Path::isCPP(filename))
|
if (Path::isCPP(filename)) {
|
||||||
dui.std = mSettings.standards.getCPP();
|
dui.std = mSettings.standards.getCPP();
|
||||||
else
|
splitcfg(mSettings.platform.getLimitsDefines(Standards::getCPP(dui.std)), dui.defines, "");
|
||||||
|
}
|
||||||
|
else {
|
||||||
dui.std = mSettings.standards.getC();
|
dui.std = mSettings.standards.getC();
|
||||||
|
splitcfg(mSettings.platform.getLimitsDefines(Standards::getC(dui.std)), dui.defines, "");
|
||||||
|
}
|
||||||
dui.clearIncludeCache = mSettings.clearIncludeCache;
|
dui.clearIncludeCache = mSettings.clearIncludeCache;
|
||||||
return dui;
|
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)
|
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);
|
std::istringstream istr(code);
|
||||||
const simplecpp::TokenList tokens1(istr, files, files[0]);
|
const simplecpp::TokenList tokens1(istr, files, files[0]);
|
||||||
|
@ -161,7 +166,7 @@ void PreprocessorHelper::preprocess(Preprocessor &preprocessor, const char code[
|
||||||
// Preprocess..
|
// Preprocess..
|
||||||
simplecpp::TokenList tokens2(files);
|
simplecpp::TokenList tokens2(files);
|
||||||
std::map<std::string, simplecpp::TokenList*> filedata;
|
std::map<std::string, simplecpp::TokenList*> filedata;
|
||||||
simplecpp::preprocess(tokens2, tokens1, files, filedata, simplecpp::DUI());
|
simplecpp::preprocess(tokens2, tokens1, files, filedata, dui);
|
||||||
|
|
||||||
// Tokenizer..
|
// Tokenizer..
|
||||||
tokenizer.createTokens(std::move(tokens2));
|
tokenizer.createTokens(std::move(tokens2));
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
class Token;
|
class Token;
|
||||||
class Preprocessor;
|
class Preprocessor;
|
||||||
class Suppressions;
|
class Suppressions;
|
||||||
|
namespace simplecpp {
|
||||||
|
struct DUI;
|
||||||
|
}
|
||||||
|
|
||||||
class givenACodeSampleToTokenize {
|
class givenACodeSampleToTokenize {
|
||||||
private:
|
private:
|
||||||
|
@ -95,6 +98,7 @@ public:
|
||||||
|
|
||||||
static void preprocess(const char code[], std::vector<std::string> &files, Tokenizer& tokenizer);
|
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);
|
||||||
|
static void preprocess(Preprocessor &preprocessor, const char code[], std::vector<std::string> &files, Tokenizer& tokenizer, const simplecpp::DUI& dui);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace cppcheck {
|
namespace cppcheck {
|
||||||
|
|
|
@ -41,6 +41,8 @@ private:
|
||||||
TEST_CASE(invalid_config_file_1);
|
TEST_CASE(invalid_config_file_1);
|
||||||
TEST_CASE(empty_elements);
|
TEST_CASE(empty_elements);
|
||||||
TEST_CASE(default_platform);
|
TEST_CASE(default_platform);
|
||||||
|
TEST_CASE(limitsDefines);
|
||||||
|
TEST_CASE(charMinMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool readPlatform(Platform& platform, const char* xmldata) {
|
static bool readPlatform(Platform& platform, const char* xmldata) {
|
||||||
|
@ -392,6 +394,26 @@ private:
|
||||||
Platform platform;
|
Platform platform;
|
||||||
ASSERT_EQUALS(Platform::Type::Native, platform.type);
|
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)
|
REGISTER_TEST(TestPlatform)
|
||||||
|
|
|
@ -262,6 +262,8 @@ private:
|
||||||
TEST_CASE(testMissingSystemInclude5);
|
TEST_CASE(testMissingSystemInclude5);
|
||||||
TEST_CASE(testMissingIncludeMixed);
|
TEST_CASE(testMissingIncludeMixed);
|
||||||
TEST_CASE(testMissingIncludeCheckConfig);
|
TEST_CASE(testMissingIncludeCheckConfig);
|
||||||
|
|
||||||
|
TEST_CASE(limitsDefines);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: merge with `PreprocessorHelper::getcode()`
|
// TODO: merge with `PreprocessorHelper::getcode()`
|
||||||
|
@ -2680,6 +2682,17 @@ private:
|
||||||
"test.c:9:0: information: Include file: \"" + missing3 + "\" not found. [missingInclude]\n"
|
"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());
|
"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)
|
REGISTER_TEST(TestPreprocessor)
|
||||||
|
|
|
@ -18,7 +18,9 @@
|
||||||
|
|
||||||
#include "checktype.h"
|
#include "checktype.h"
|
||||||
#include "errortypes.h"
|
#include "errortypes.h"
|
||||||
|
#include "helpers.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
#include "preprocessor.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "standards.h"
|
#include "standards.h"
|
||||||
#include "fixture.h"
|
#include "fixture.h"
|
||||||
|
@ -27,6 +29,8 @@
|
||||||
#include <sstream> // IWYU pragma: keep
|
#include <sstream> // IWYU pragma: keep
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <simplecpp.h>
|
||||||
|
|
||||||
class TestType : public TestFixture {
|
class TestType : public TestFixture {
|
||||||
public:
|
public:
|
||||||
TestType() : TestFixture("TestType") {}
|
TestType() : TestFixture("TestType") {}
|
||||||
|
@ -41,6 +45,7 @@ private:
|
||||||
TEST_CASE(longCastAssign);
|
TEST_CASE(longCastAssign);
|
||||||
TEST_CASE(longCastReturn);
|
TEST_CASE(longCastReturn);
|
||||||
TEST_CASE(checkFloatToIntegerOverflow);
|
TEST_CASE(checkFloatToIntegerOverflow);
|
||||||
|
TEST_CASE(integerOverflow); // #11794
|
||||||
}
|
}
|
||||||
|
|
||||||
#define check(...) check_(__FILE__, __LINE__, __VA_ARGS__)
|
#define check(...) check_(__FILE__, __LINE__, __VA_ARGS__)
|
||||||
|
@ -59,6 +64,25 @@ private:
|
||||||
runChecks<CheckType>(tokenizer, this);
|
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() {
|
void checkTooBigShift_Unix32() {
|
||||||
const Settings settings0;
|
const Settings settings0;
|
||||||
const Settings settings = settingsBuilder().platform(Platform::Type::Unix32).build();
|
const Settings settings = settingsBuilder().platform(Platform::Type::Unix32).build();
|
||||||
|
@ -451,6 +475,26 @@ private:
|
||||||
"}", settings);
|
"}", settings);
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str()));
|
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)
|
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