From bd2b38507287dd2288a45d77776946cfec9c2aa3 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 15 Dec 2025 15:40:18 +0100 Subject: [PATCH 1/3] fixed #1059 - extract configurations for compound preprocessor checks with operators --- lib/preprocessor.cpp | 63 ++++++++++++++++++++++++++------------- test/testpreprocessor.cpp | 40 +++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 20 deletions(-) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 01e3d6f5c74..84b7b6bdc63 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -22,6 +22,7 @@ #include "errorlogger.h" #include "errortypes.h" #include "library.h" +#include "mathlib.h" #include "path.h" #include "platform.h" #include "settings.h" @@ -420,17 +421,21 @@ static std::string readcondition(const simplecpp::Token *iftok, const std::setname && (next1->str() == "==" || next1->str() == "<=" || next1->str() == ">=") && next2->number) { if (defined.find(cond->str()) == defined.end()) - return cond->str() + '=' + cond->next->next->str(); + return cond->str() + '=' + next1->next->str(); } + const auto lessGreaterThanConfig = [](const simplecpp::Token* dtok, const simplecpp::Token* ctok) { + int v = MathLib::toBigNumber(ctok->next->str()); + if (ctok->op == '<') + v -= 1; + else + v += 1; + return dtok->str() + '=' + std::to_string(v); + }; + if (len == 3 && cond->name && (next1->op == '<' || next1->op == '>') && next2->number) { if (defined.find(cond->str()) == defined.end()) { - int v = strToInt(cond->next->next->str()); - if (next1->op == '<') - v -= 1; - else - v += 1; - return cond->str() + '=' + std::to_string(v); + return lessGreaterThanConfig(cond, next1); } } @@ -447,22 +452,40 @@ static std::string readcondition(const simplecpp::Token *iftok, const std::setnext->str() + "=0"); continue; } - if (cond->str() != "defined") + if (cond->str() == "==" || cond->str() == "<=" || cond->str() == ">=") { + if (cond->next->number) { + const simplecpp::Token *dtok = cond->previous; + if (sameline(iftok,dtok) && dtok->name && defined.find(dtok->str()) == defined.end() && undefined.find(dtok->str()) == undefined.end()) + configset.insert(dtok->str() + '=' + cond->next->str()); + } continue; - const simplecpp::Token *dtok = cond->next; - if (!dtok) - break; - if (dtok->op == '(') - dtok = dtok->next; - - if (sameline(iftok,dtok) && dtok->name && defined.find(dtok->str()) == defined.end() && undefined.find(dtok->str()) == undefined.end()) { - if (!isNotDefinedMacro) { - configset.insert(dtok->str() + "=" + dtok->str()); // if defined is set to itself. - } else { - configset.insert(dtok->str()); + } + if (cond->op == '<' || cond->op == '>') { + if (cond->next->number) { + const simplecpp::Token *dtok = cond->previous; + if (sameline(iftok,dtok) && dtok->name && defined.find(dtok->str()) == defined.end() && undefined.find(dtok->str()) == undefined.end()) { + configset.insert(lessGreaterThanConfig(dtok, cond)); + } } + continue; + } + if (cond->str() == "defined") { + const simplecpp::Token *dtok = cond->next; + if (!dtok) + break; + if (dtok->op == '(') + dtok = dtok->next; + + if (sameline(iftok,dtok) && dtok->name && defined.find(dtok->str()) == defined.end() && undefined.find(dtok->str()) == undefined.end()) { + if (!isNotDefinedMacro) { + configset.insert(dtok->str() + "=" + dtok->str()); // if defined is set to itself. + } else { + configset.insert(dtok->str()); + } + isNotDefinedMacro = false; + } + continue; } - isNotDefinedMacro = false; } std::string cfgStr; for (const std::string &s : configset) { diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index c53fed82e01..ffaf5e86ea6 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -323,6 +323,11 @@ class TestPreprocessor : public TestFixture { TEST_CASE(getConfigs15); // #1059 TEST_CASE(getConfigs16); // #1059 TEST_CASE(getConfigs17); // #1059 + TEST_CASE(getConfigs18); // #1059 + TEST_CASE(getConfigs19); // #1059 + TEST_CASE(getConfigs20); // #1059 + TEST_CASE(getConfigs21); // #1059 + TEST_CASE(getConfigs22); // #1059 TEST_CASE(getConfigsError); TEST_CASE(getConfigsD1); @@ -2359,6 +2364,41 @@ class TestPreprocessor : public TestFixture { ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); } + void getConfigs18() { // #1059 + const char filedata[] = "#if A == 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1;B\n", getConfigsStr(filedata)); + } + + void getConfigs19() { // #1059 + const char filedata[] = "#if A >= 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1;B\n", getConfigsStr(filedata)); + } + + void getConfigs20() { // #1059 + const char filedata[] = "#if A <= 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1;B\n", getConfigsStr(filedata)); + } + + void getConfigs21() { // #1059 + const char filedata[] = "#if A > 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2;B\n", getConfigsStr(filedata)); + } + + void getConfigs22() { // #1059 + const char filedata[] = "#if A < 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0;B\n", getConfigsStr(filedata)); + } + void getConfigsError() { const char filedata1[] = "#ifndef X\n" "#error \"!X\"\n" From 11c9eee93ea6e9b8dc2d73e0f0073ebc0e66d42a Mon Sep 17 00:00:00 2001 From: firewave Date: Sat, 3 Jan 2026 18:58:43 +0100 Subject: [PATCH 2/3] TestPreprocessor: re-grouped and extended some tests --- lib/preprocessor.cpp | 2 +- test/testpreprocessor.cpp | 300 +++++++++++++++++++++++++++++++------- 2 files changed, 247 insertions(+), 55 deletions(-) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 84b7b6bdc63..a028fc5b864 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -425,7 +425,7 @@ static std::string readcondition(const simplecpp::Token *iftok, const std::setnext->str()); + auto v = MathLib::toBigNumber(ctok->next->str()); if (ctok->op == '<') v -= 1; else diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index ffaf5e86ea6..0f22a1fbca7 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -319,15 +319,15 @@ class TestPreprocessor : public TestFixture { TEST_CASE(getConfigs11); // #9832 - include guards TEST_CASE(getConfigs12); // #14222 TEST_CASE(getConfigs13); // #14222 - TEST_CASE(getConfigs14); // #1059 - TEST_CASE(getConfigs15); // #1059 - TEST_CASE(getConfigs16); // #1059 - TEST_CASE(getConfigs17); // #1059 - TEST_CASE(getConfigs18); // #1059 - TEST_CASE(getConfigs19); // #1059 - TEST_CASE(getConfigs20); // #1059 - TEST_CASE(getConfigs21); // #1059 - TEST_CASE(getConfigs22); // #1059 + TEST_CASE(getConfigs_gte); // #1059 + TEST_CASE(getConfigs_lte); // #1059 + TEST_CASE(getConfigs_gt); // #1059 + TEST_CASE(getConfigs_lt); // #1059 + TEST_CASE(getConfigs_eq_compound); // #1059 + TEST_CASE(getConfigs_gte_compound); // #1059 + TEST_CASE(getConfigs_lte_compound); // #1059 + TEST_CASE(getConfigs_gt_compound); // #1059 + TEST_CASE(getConfigs_lt_compound); // #1059 TEST_CASE(getConfigsError); TEST_CASE(getConfigsD1); @@ -2336,67 +2336,259 @@ class TestPreprocessor : public TestFixture { ASSERT_EQUALS("\n", getConfigsStr(filedata, nullptr, "gnu.cfg")); } - void getConfigs14() { // #1059 - const char filedata[] = "#if A >= 1\n" - "1\n" - "#endif\n"; - ASSERT_EQUALS("\nA=1\n", getConfigsStr(filedata)); + void getConfigs_gte() { // #1059 + { + const char filedata[] = "#if A >= 1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A >= 201112L\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201112L\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A >= 12147483647\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=12147483647\n", getConfigsStr(filedata)); + } } - void getConfigs15() { // #1059 - const char filedata[] = "#if A <= 1\n" - "1\n" - "#endif\n"; - ASSERT_EQUALS("\nA=1\n", getConfigsStr(filedata)); + void getConfigs_lte() { // #1059 + { + const char filedata[] = "#if A <= 1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A <= 201112L\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201112L\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A <= 12147483647\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=12147483647\n", getConfigsStr(filedata)); + } } - void getConfigs16() { // #1059 - const char filedata[] = "#if A > 1\n" - "1\n" - "#endif\n"; - ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + void getConfigs_gt() { // #1059 + { + const char filedata[] = "#if A > 1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 1L\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 1U\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 1UL\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 1Z\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 0x1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 01\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 0b1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 1t\n" + "1\n" + "#endif\n"; + ASSERT_THROW_INTERNAL_EQUALS(getConfigsStr(filedata), INTERNAL, "Internal Error. MathLib::toBigNumber: input was not completely consumed: 1t"); + } + { + const char filedata[] = "#if A > 1.0\n" + "1\n" + "#endif\n"; + TODO_ASSERT_THROW(getConfigsStr(filedata), InternalError); // floating point literals are not allowed + } + { + const char filedata[] = "#if A > 12147483647\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=12147483648\n", getConfigsStr(filedata)); + } } - void getConfigs17() { // #1059 - const char filedata[] = "#if A < 1\n" - "1\n" - "#endif\n"; - ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + void getConfigs_lt() { // #1059 + { + const char filedata[] = "#if A < 1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 1L\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 1U\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 1UL\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 1Z\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 0x1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 01\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 0b1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 1t\n" + "1\n" + "#endif\n"; + ASSERT_THROW_INTERNAL_EQUALS(getConfigsStr(filedata), INTERNAL, "Internal Error. MathLib::toBigNumber: input was not completely consumed: 1t"); + } + { + const char filedata[] = "#if A < 1.0\n" + "1\n" + "#endif\n"; + TODO_ASSERT_THROW(getConfigsStr(filedata), InternalError); // floating point literals are not allowed + } + { + const char filedata[] = "#if A < 12147483647\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=12147483646\n", getConfigsStr(filedata)); + } } - void getConfigs18() { // #1059 - const char filedata[] = "#if A == 1 && defined(B)\n" - "1\n" - "#endif\n"; - ASSERT_EQUALS("\nA=1;B\n", getConfigsStr(filedata)); + void getConfigs_eq_compound() { // #1059 + { + const char filedata[] = "#if A == 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1;B=B\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A == 201112L && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201112L;B=B\n", getConfigsStr(filedata)); + } } - void getConfigs19() { // #1059 - const char filedata[] = "#if A >= 1 && defined(B)\n" - "1\n" - "#endif\n"; - ASSERT_EQUALS("\nA=1;B\n", getConfigsStr(filedata)); + void getConfigs_gte_compound() { // #1059 + { + const char filedata[] = "#if A >= 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1;B=B\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A >= 201112L && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201112L;B=B\n", getConfigsStr(filedata)); + } } - void getConfigs20() { // #1059 - const char filedata[] = "#if A <= 1 && defined(B)\n" - "1\n" - "#endif\n"; - ASSERT_EQUALS("\nA=1;B\n", getConfigsStr(filedata)); + void getConfigs_lte_compound() { // #1059 + { + const char filedata[] = "#if A <= 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1;B=B\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A <= 201112L && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201112L;B=B\n", getConfigsStr(filedata)); + } } - void getConfigs21() { // #1059 - const char filedata[] = "#if A > 1 && defined(B)\n" - "1\n" - "#endif\n"; - ASSERT_EQUALS("\nA=2;B\n", getConfigsStr(filedata)); + void getConfigs_gt_compound() { // #1059 + { + const char filedata[] = "#if A > 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2;B=B\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 201112L && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201113;B=B\n", getConfigsStr(filedata)); + } } - void getConfigs22() { // #1059 - const char filedata[] = "#if A < 1 && defined(B)\n" - "1\n" - "#endif\n"; - ASSERT_EQUALS("\nA=0;B\n", getConfigsStr(filedata)); + void getConfigs_lt_compound() { // #1059 + { + const char filedata[] = "#if A < 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0;B=B\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 201112L && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201111;B=B\n", getConfigsStr(filedata)); + } } void getConfigsError() { From 254ca43a0b971e7bead083a8eae501ad2b3b7f3b Mon Sep 17 00:00:00 2001 From: firewave Date: Wed, 25 Feb 2026 14:07:31 +0100 Subject: [PATCH 3/3] test/cfg/std.c: suppressed `purgedConfiguration` --- test/cfg/std.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cfg/std.c b/test/cfg/std.c index adc147c2333..af0b30e03b2 100644 --- a/test/cfg/std.c +++ b/test/cfg/std.c @@ -7,7 +7,7 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // -// cppcheck-suppress-file valueFlowBailout +// cppcheck-suppress-file [valueFlowBailout,purgedConfiguration] #include #include