Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions simplecpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1291,9 +1291,16 @@ void simplecpp::TokenList::combineOperators()

static const std::string COMPL("compl");
static const std::string NOT("not");
void simplecpp::TokenList::constFoldUnaryNotPosNeg(simplecpp::Token *tok)
void simplecpp::TokenList::constFoldUnaryNotPosNeg(simplecpp::Token *tok1)
{
for (; tok && tok->op != ')'; tok = tok->next) {
if (!tok1 || tok1->op == ')')
return;
Token *last = tok1;
while (last->next && last->next->op != ')')
last = last->next;

// unary operators are right-associative, "!-0" means "!(-0)", so they are folded from right to left
for (Token *tok = last; tok; tok = (tok == tok1) ? nullptr : tok->previous) {
// "not" might be !
if (isAlternativeUnaryOp(tok, NOT))
tok->op = '!';
Expand Down Expand Up @@ -1328,7 +1335,10 @@ void simplecpp::TokenList::constFoldUnaryNotPosNeg(simplecpp::Token *tok)
deleteToken(tok->next);
break;
case '-':
tok->setstr(tok->op + tok->next->str());
if (tok->next->str()[0] == '-')
tok->setstr(tok->next->str().substr(1));
else
tok->setstr(tok->op + tok->next->str());
deleteToken(tok->next);
break;
}
Expand Down
30 changes: 30 additions & 0 deletions test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2913,6 +2913,35 @@ static void ifZeroCondition()
ASSERT_EQUALS("file0,1,syntax_error,failed to evaluate #if condition, division/modulo by zero\n", toString(outputList));
}

static void ifUnaryOperators()
{
// unary operators in a row
const char * const exprs[] = {
"!!1",
"!-0",
"!+0",
"!~-1",
"- -1",
"-!0",
"-~0",
"~!0",
"+-1 == -1",
"1 && !-0",
"!-X",
"-(-1) == 1",
"- - -1 == -1",
"1 - -1 == 2"
};
for (const char * const expr : exprs) {
const std::string code = std::string("#if ") + expr + "\n"
"1\n"
"#else\n"
"2\n"
"#endif\n";
ASSERT_EQUALS("\n1", preprocess(code.c_str()));
}
}

static void ifTrueFalse()
{
const char code[] = "#if true && !false\n"
Expand Down Expand Up @@ -5150,6 +5179,7 @@ static void runTests(int argc, char **argv, Input input)
TEST_CASE(ifdiv0);
TEST_CASE(ifShortCircuit);
TEST_CASE(ifZeroCondition);
TEST_CASE(ifUnaryOperators);
TEST_CASE(ifTrueFalse);
TEST_CASE(ifalt); // using "and", "or", etc
TEST_CASE(ifexpr);
Expand Down
Loading