diff --git a/simplecpp.cpp b/simplecpp.cpp index 9fa548a3..1d6298ce 100644 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -2824,10 +2824,18 @@ static void simplifyHasInclude(simplecpp::TokenList &expr, const simplecpp::DUI /** Evaluate name * @throws std::runtime_error thrown on undefined function-like macro */ -static void simplifyName(simplecpp::TokenList &expr) +static void simplifyName(simplecpp::TokenList &expr, const simplecpp::DUI &dui) { + // In C++ and C23 the keywords true/false are 1/0 in #if expressions + const simplecpp::cstd_t cstd = simplecpp::getCStd(dui.std); + const bool hasTrueFalse = (cstd == simplecpp::CUnknown || cstd >= simplecpp::C23); + for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) { if (tok->name) { + if (hasTrueFalse && (tok->str() == "true" || tok->str() == "false")) { + tok->setstr(tok->str() == "true" ? "1" : "0"); + continue; + } static const std::set altop{"and","or","bitand","bitor","compl","not","not_eq","xor"}; if (altop.find(tok->str()) != altop.end()) { bool alt; @@ -3101,7 +3109,7 @@ static long long evaluate(simplecpp::TokenList &expr, const simplecpp::DUI &dui, simplifyComments(expr); simplifySizeof(expr, sizeOfType); simplifyHasInclude(expr, dui); - simplifyName(expr); + simplifyName(expr, dui); simplifyNumbers(expr); expr.constFold(); // TODO: handle invalid expressions diff --git a/test.cpp b/test.cpp index 3574563a..940a3207 100644 --- a/test.cpp +++ b/test.cpp @@ -2609,6 +2609,24 @@ static void ifdiv0() ASSERT_EQUALS("", preprocess(code)); } +static void ifTrueFalse() +{ + const char code[] = "#if true && !false\n" + "1\n" + "#else\n" + "2\n" + "#endif\n"; + simplecpp::DUI dui; + ASSERT_EQUALS("\n1", preprocess(code, dui, nullptr)); + dui.std = "c++11"; + ASSERT_EQUALS("\n1", preprocess(code, dui, nullptr)); + dui.std = "c23"; + ASSERT_EQUALS("\n1", preprocess(code, dui, nullptr)); + // before C23, true and false are ordinary identifiers that evaluate to 0 + dui.std = "c17"; + ASSERT_EQUALS("\n\n\n2", preprocess(code, dui, nullptr)); +} + static void ifalt() // using "and", "or", etc { const char *code; @@ -4794,6 +4812,7 @@ static void runTests(int argc, char **argv, Input input) TEST_CASE(ifif); TEST_CASE(ifoverflow); TEST_CASE(ifdiv0); + TEST_CASE(ifTrueFalse); TEST_CASE(ifalt); // using "and", "or", etc TEST_CASE(ifexpr); TEST_CASE(ifUndefFuncStyleMacro);