Skip to content

Commit

Permalink
refs #11928 / refs #10045 / fixes #11794 - generate limits.h/`climi…
Browse files Browse the repository at this point in the history
…ts` defines from platform (#5414)
  • Loading branch information
firewave committed Oct 21, 2023
1 parent 09785a4 commit 3103736
Show file tree
Hide file tree
Showing 16 changed files with 472 additions and 6 deletions.
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
150 changes: 150 additions & 0 deletions lib/platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));

This comment has been minimized.

Copy link
@danmar

danmar Feb 3, 2024

Owner

hmm.. I feel this is not 100% correct.

This replaces LLONG_MIN in the code with "-9223372036854775808".

That is a "unsigned long long" constant according to the language rules because 9223372036854775808 can't be stored in a signed long long.

example clang AST output:

    |     `-UnaryOperator 0x1ce07c8 <col:19, col:20> 'unsigned long long' prefix '-'
    |       `-IntegerLiteral 0x1ce07a8 <col:20> 'unsigned long long' 9223372036854775808
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);
}
9 changes: 9 additions & 0 deletions lib/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
//---------------------------------------------------------------------------

#include "config.h"
#include "standards.h"

#include <climits>
#include <stdexcept>
Expand Down Expand Up @@ -51,6 +52,9 @@ class CPPCHECKLIB Platform {
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();

Expand Down Expand Up @@ -178,6 +182,11 @@ class CPPCHECKLIB Platform {
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;
};

/// @}
Expand Down
9 changes: 7 additions & 2 deletions lib/preprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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;
}
Expand Down
7 changes: 6 additions & 1 deletion test/helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,19 @@ 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]);

// 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));
Expand Down
4 changes: 4 additions & 0 deletions test/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
class Token;
class Preprocessor;
class Suppressions;
namespace simplecpp {
struct DUI;
}

class givenACodeSampleToTokenize {
private:
Expand Down Expand Up @@ -95,6 +98,7 @@ class PreprocessorHelper

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 {
Expand Down
22 changes: 22 additions & 0 deletions test/testplatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class TestPlatform : public TestFixture {
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) {
Expand Down Expand Up @@ -392,6 +394,26 @@ class TestPlatform : public TestFixture {
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)
13 changes: 13 additions & 0 deletions test/testpreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ class TestPreprocessor : public TestFixture {
TEST_CASE(testMissingSystemInclude5);
TEST_CASE(testMissingIncludeMixed);
TEST_CASE(testMissingIncludeCheckConfig);

TEST_CASE(limitsDefines);
}

// TODO: merge with `PreprocessorHelper::getcode()`
Expand Down Expand Up @@ -2680,6 +2682,17 @@ class TestPreprocessor : public TestFixture {
"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)
Loading

0 comments on commit 3103736

Please sign in to comment.