diff --git a/simplecpp.cpp b/simplecpp.cpp index 3bae3d56..6fb28762 100644 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -1422,30 +1422,36 @@ void simplecpp::TokenList::constFoldBitwise(Token *tok) static const std::string OR("or"); void simplecpp::TokenList::constFoldLogicalOp(Token *tok) { - for (; tok && tok->op != ')'; tok = tok->next) { - if (tok->name) { - if (isAlternativeBinaryOp(tok,AND)) - tok->setstr("&&"); - else if (isAlternativeBinaryOp(tok,OR)) - tok->setstr("||"); + for (Token *t = tok; t && t->op != ')'; t = t->next) { + if (t->name) { + if (isAlternativeBinaryOp(t,AND)) + t->setstr("&&"); + else if (isAlternativeBinaryOp(t,OR)) + t->setstr("||"); } - if (tok->str() != "&&" && tok->str() != "||") - continue; - if (!tok->previous || !tok->previous->number) - continue; - if (!tok->next || !tok->next->number) - continue; + } - int result; - if (tok->str() == "||") - result = (stringToLL(tok->previous->str()) || stringToLL(tok->next->str())); - else /*if (tok->str() == "&&")*/ - result = (stringToLL(tok->previous->str()) && stringToLL(tok->next->str())); + // && has higher precedence than || + for (const char * const op : {"&&", "||"}) { + for (Token *t = tok; t && t->op != ')'; t = t->next) { + if (t->str() != op) + continue; + if (!t->previous || !t->previous->number) + continue; + if (!t->next || !t->next->number) + continue; - tok = tok->previous; - tok->setstr(toString(result)); - deleteToken(tok->next); - deleteToken(tok->next); + int result; + if (t->str() == "||") + result = (stringToLL(t->previous->str()) || stringToLL(t->next->str())); + else /*if (t->str() == "&&")*/ + result = (stringToLL(t->previous->str()) && stringToLL(t->next->str())); + + t = t->previous; + t->setstr(toString(result)); + deleteToken(t->next); + deleteToken(t->next); + } } } diff --git a/test.cpp b/test.cpp index 0f07aadb..00ebbf1e 100644 --- a/test.cpp +++ b/test.cpp @@ -2532,6 +2532,27 @@ static void ifLogical() ASSERT_EQUALS("\nX", preprocess(code, dui)); } +static void ifLogicalPrecedence() +{ + // && has higher precedence than || + const char code1[] = "#if 1 || 1 && 0\n" + "X\n" + "#endif"; + ASSERT_EQUALS("\nX", preprocess(code1)); + const char code2[] = "#if 1 or 1 and 0\n" + "X\n" + "#endif"; + ASSERT_EQUALS("\nX", preprocess(code2)); + const char code3[] = "#if 0 && 1 || 1\n" + "X\n" + "#endif"; + ASSERT_EQUALS("\nX", preprocess(code3)); + const char code4[] = "#if 0 || 1 && 0\n" + "X\n" + "#endif"; + ASSERT_EQUALS("", preprocess(code4)); +} + static void ifSizeof() { const char code[] = "#if sizeof(unsigned short)==2\n" @@ -4887,6 +4908,7 @@ static void runTests(int argc, char **argv, Input input) TEST_CASE(ifDefinedHashHash); TEST_CASE(ifDefinedHashHash2); TEST_CASE(ifLogical); + TEST_CASE(ifLogicalPrecedence); TEST_CASE(ifSizeof); TEST_CASE(elif); TEST_CASE(elifdef);