From 9be339fd19344644e34c42fb75c8771a90d1f374 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 15 Dec 2025 15:40:18 +0100 Subject: [PATCH 1/2] fixed #1059 - extract configurations for compound preprocessor checks with operators [skip ci] --- lib/preprocessor.cpp | 39 ++++++++++++++++++++++++++++++-------- test/testpreprocessor.cpp | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index c395bf07e8b..ca25bf464ae 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -437,15 +437,38 @@ 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()) - 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()) { + int v = strToInt(cond->next->str()); + if (cond->op == '<') + v -= 1; + else + v += 1; + configset.insert(dtok->str() + '=' + std::to_string(v)); + } + } + 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()) + configset.insert(dtok->str()); + continue; + } } std::string cfgStr; for (const std::string &s : configset) { diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index e97b49196cb..e92389156be 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -322,6 +322,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); @@ -2321,6 +2326,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 1d43e4d6c829f76089abbc5d8a2fd60ef64994c8 Mon Sep 17 00:00:00 2001 From: firewave Date: Wed, 31 Dec 2025 14:58:24 +0100 Subject: [PATCH 2/2] fixed #14357 - properly handle "!defined" in compound preprocessor checks [skip ci] --- lib/preprocessor.cpp | 4 +++- test/testpreprocessor.cpp | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index ca25bf464ae..0043461cda2 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -432,8 +432,10 @@ static std::string readcondition(const simplecpp::Token *iftok, const std::setop == '!') { if (!sameline(iftok,cond->next) || !cond->next->name) break; - if (cond->next->str() == "defined") + if (cond->next->str() == "defined") { + cond = cond->next; continue; + } configset.insert(cond->next->str() + "=0"); continue; } diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index e92389156be..ceca114c7db 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -327,6 +327,11 @@ class TestPreprocessor : public TestFixture { TEST_CASE(getConfigs20); // #1059 TEST_CASE(getConfigs21); // #1059 TEST_CASE(getConfigs22); // #1059 + TEST_CASE(getConfigs23); // #1059 + TEST_CASE(getConfigs24); // #1059 + TEST_CASE(getConfigs25); // #1059 + TEST_CASE(getConfigs26); // #1059 + TEST_CASE(getConfigs27); // #1059 TEST_CASE(getConfigsError); TEST_CASE(getConfigsD1); @@ -2361,6 +2366,41 @@ class TestPreprocessor : public TestFixture { ASSERT_EQUALS("\nA=0;B\n", getConfigsStr(filedata)); } + void getConfigs23() { // #1059 + const char filedata[] = "#if defined(A) && !defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA\n", getConfigsStr(filedata)); + } + + void getConfigs24() { // #1059 + const char filedata[] = "#if !defined(A) && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nB\n", getConfigsStr(filedata)); + } + + void getConfigs25() { // #1059 + const char filedata[] = "#if A == 1 && !defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1\n", getConfigsStr(filedata)); + } + + void getConfigs26() { // #1059 + const char filedata[] = "#if A <= 1 && !defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1\n", getConfigsStr(filedata)); + } + + void getConfigs27() { // #1059 + const char filedata[] = "#if A < 1 && !defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + void getConfigsError() { const char filedata1[] = "#ifndef X\n" "#error \"!X\"\n"