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
98 changes: 64 additions & 34 deletions simplecpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -954,7 +954,7 @@ void simplecpp::TokenList::constFold()
constFoldQuestionOp(&tok);

// If there is no '(' we are done with the constant folding
if (tok->op != '(')
if (!tok || tok->op != '(')
break;

if (!tok->next || !tok->next->next || tok->next->next->op != ')')
Expand Down Expand Up @@ -1164,10 +1164,7 @@ void simplecpp::TokenList::constFoldMulDivRem(Token *tok)
} else
continue;

tok = tok->previous;
tok->setstr(toString(result));
deleteToken(tok->next);
deleteToken(tok->next);
simpleSquash(tok, toString(result));
}
}

Expand All @@ -1187,10 +1184,7 @@ void simplecpp::TokenList::constFoldAddSub(Token *tok)
else
continue;

tok = tok->previous;
tok->setstr(toString(result));
deleteToken(tok->next);
deleteToken(tok->next);
simpleSquash(tok, toString(result));
}
}

Expand All @@ -1210,10 +1204,7 @@ void simplecpp::TokenList::constFoldShift(Token *tok)
else
continue;

tok = tok->previous;
tok->setstr(toString(result));
deleteToken(tok->next);
deleteToken(tok->next);
simpleSquash(tok, toString(result));
}
}

Expand Down Expand Up @@ -1247,10 +1238,7 @@ void simplecpp::TokenList::constFoldComparison(Token *tok)
else
continue;

tok = tok->previous;
tok->setstr(toString(result));
deleteToken(tok->next);
deleteToken(tok->next);
simpleSquash(tok, toString(result));
}
}

Expand Down Expand Up @@ -1282,12 +1270,51 @@ void simplecpp::TokenList::constFoldBitwise(Token *tok)
result = (stringToLL(tok->previous->str()) ^ stringToLL(tok->next->str()));
else /*if (*op == '|')*/
result = (stringToLL(tok->previous->str()) | stringToLL(tok->next->str()));
tok = tok->previous;
tok->setstr(toString(result));
deleteToken(tok->next);
deleteToken(tok->next);
simpleSquash(tok, toString(result));
}
}
}

void simplecpp::TokenList::simpleSquash(Token *&tok, const std::string & result)
{
tok = tok->previous;
tok->setstr(result);
deleteToken(tok->next);
deleteToken(tok->next);
}

void simplecpp::TokenList::squashTokens(Token *&tok, const std::set<std::string> & breakPoints, bool forwardDirection, const std::string & result)
{
const char * const brackets = forwardDirection ? "()" : ")(";
Token* Token::* const step = forwardDirection ? &Token::next : &Token::previous;
int skip = 0;
const Token * const tok1 = tok->*step;
while (tok1 && tok1->*step) {
if ((tok1->*step)->op == brackets[1]){
if (skip) {
--skip;
deleteToken(tok1->*step);
} else
break;
} else if ((tok1->*step)->op == brackets[0]) {
++skip;
deleteToken(tok1->*step);
} else if (skip) {
deleteToken(tok1->*step);
} else if (breakPoints.count((tok1->*step)->str()) != 0) {
break;
} else {
deleteToken(tok1->*step);
}
}
simpleSquash(tok, result);
}

static simplecpp::Token * constFoldGetOperand(simplecpp::Token * tok, bool forwardDirection)
{
simplecpp::Token* simplecpp::Token::* const step = forwardDirection ? &simplecpp::Token::next : &simplecpp::Token::previous;
const char bracket = forwardDirection ? ')' : '(';
return tok->*step && (tok->*step)->number && (!((tok->*step)->*step) || (((tok->*step)->*step)->op == bracket)) ? tok->*step : nullptr;
}

static const std::string AND("and");
Expand All @@ -1303,21 +1330,24 @@ void simplecpp::TokenList::constFoldLogicalOp(Token *tok)
}
if (tok->str() != "&&" && tok->str() != "||")
continue;
if (!tok->previous || !tok->previous->number)
continue;
if (!tok->next || !tok->next->number)
const Token* const lhs = constFoldGetOperand(tok, false);
const Token* const rhs = constFoldGetOperand(tok, true);
if (!lhs) // if lhs is not a single number we don't need to fold
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()));

tok = tok->previous;
tok->setstr(toString(result));
deleteToken(tok->next);
deleteToken(tok->next);
std::set<std::string> breakPoints;
breakPoints.insert(":");
breakPoints.insert("?");
if (tok->str() == "||"){
if (stringToLL(lhs->str()) != 0LL || (rhs && stringToLL(rhs->str()) != 0LL))
squashTokens(tok, breakPoints, stringToLL(lhs->str()) != 0LL, toString(1));
} else /*if (tok->str() == "&&")*/ {
breakPoints.insert("||");
if (stringToLL(lhs->str()) == 0LL || (rhs && stringToLL(rhs->str()) == 0LL))
squashTokens(tok, breakPoints, stringToLL(lhs->str()) == 0LL, toString(0));
else if (rhs && stringToLL(lhs->str()) && stringToLL(rhs->str()))
simpleSquash(tok, "1");
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions simplecpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@ namespace simplecpp {
void constFoldLogicalOp(Token *tok);
void constFoldQuestionOp(Token **tok1);

void simpleSquash(Token *&tok, const std::string & result);
void squashTokens(Token *&tok, const std::set<std::string> & breakPoints, bool forwardDirection, const std::string & result);
std::string readUntil(Stream &stream, const Location &location, char start, char end, OutputList *outputList);
void lineDirective(unsigned int fileIndex, unsigned int line, Location *location);

Expand Down
26 changes: 26 additions & 0 deletions test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,15 @@ static void constFold()
ASSERT_EQUALS("1", testConstFold("010==8"));
ASSERT_EQUALS("exception", testConstFold("!1 ? 2 :"));
ASSERT_EQUALS("exception", testConstFold("?2:3"));
ASSERT_EQUALS("0", testConstFold("( 0 ) && 10 < X"));
ASSERT_EQUALS("0", testConstFold("1+2*(3+4) && 7 - 7"));
ASSERT_EQUALS("1", testConstFold("( 1 ) || 10 < X"));
ASSERT_EQUALS("1", testConstFold("1+2*(3+4) || 8 - 7"));
ASSERT_EQUALS("X && 0", testConstFold("X && 0"));
ASSERT_EQUALS("X >= 0 || 0 < Y", testConstFold("X >= 0 || 0 < Y"));
ASSERT_EQUALS("X && 1 && Z", testConstFold("X && (1 || Y) && Z"));
ASSERT_EQUALS("0 || Y", testConstFold("0 && X || Y"));
ASSERT_EQUALS("X > 0 && Y", testConstFold("X > 0 && Y"));
}

#ifdef __CYGWIN__
Expand Down Expand Up @@ -1598,6 +1607,22 @@ static void ifA()
ASSERT_EQUALS("\nX", preprocess(code, dui));
}

static void ifXorY()
{
const char code[] = "#if Z > 0 || 0 < Y\n"
"X\n"
"#endif";
ASSERT_EQUALS("", preprocess(code));

simplecpp::DUI dui;
dui.defines.push_back("Z=1");
ASSERT_EQUALS("\nX", preprocess(code, dui));

dui.defines.clear();
dui.defines.push_back("Y=15");
ASSERT_EQUALS("\nX", preprocess(code, dui));
}

static void ifCharLiteral()
{
const char code[] = "#if ('A'==0x41)\n"
Expand Down Expand Up @@ -3104,6 +3129,7 @@ int main(int argc, char **argv)
TEST_CASE(ifdef2);
TEST_CASE(ifndef);
TEST_CASE(ifA);
TEST_CASE(ifXorY);
TEST_CASE(ifCharLiteral);
TEST_CASE(ifDefined);
TEST_CASE(ifDefinedNoPar);
Expand Down
Loading