Skip to content

Commit 8ffa917

Browse files
committed
Fixed cppcheck-opensource#6863 (AST: wrong handling of assignment between ? and :)
1 parent 234669b commit 8ffa917

2 files changed

Lines changed: 19 additions & 3 deletions

File tree

lib/tokenlist.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,8 @@ struct AST_state {
427427
unsigned int depth;
428428
unsigned int inArrayAssignment;
429429
bool cpp;
430-
explicit AST_state(bool cpp_) : depth(0), inArrayAssignment(0), cpp(cpp_) {}
430+
unsigned int assign;
431+
explicit AST_state(bool cpp_) : depth(0), inArrayAssignment(0), cpp(cpp_), assign(0U) {}
431432
};
432433

433434
static bool iscast(const Token *tok)
@@ -847,10 +848,22 @@ static void compileAssignTernary(Token *&tok, AST_state& state)
847848
while (tok) {
848849
// TODO: http://en.cppreference.com/w/cpp/language/operator_precedence says:
849850
// "The expression in the middle of the conditional operator (between ? and :) is parsed as if parenthesized: its precedence relative to ?: is ignored."
850-
if (tok->isAssignmentOp() || Token::Match(tok, "[?:]")) {
851-
if (tok->str() == "?" && tok->strAt(1) == ":") {
851+
if (tok->isAssignmentOp()) {
852+
state.assign++;
853+
compileBinOp(tok, state, compileAssignTernary);
854+
if (state.assign > 0U)
855+
state.assign--;
856+
} else if (tok->str() == "?") {
857+
if (tok->strAt(1) == ":") {
852858
state.op.push(0);
853859
}
860+
const unsigned int assign = state.assign;
861+
state.assign = 0U;
862+
compileBinOp(tok, state, compileAssignTernary);
863+
state.assign = assign;
864+
} else if (tok->str() == ":") {
865+
if (state.assign > 0U)
866+
break;
854867
compileBinOp(tok, state, compileAssignTernary);
855868
} else break;
856869
}

test/testtokenize.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8413,6 +8413,9 @@ class TestTokenizer : public TestFixture {
84138413
// assignments are executed from right to left
84148414
ASSERT_EQUALS("abc==", testAst("a=b=c;"));
84158415

8416+
// assignment in ternary operator
8417+
ASSERT_EQUALS("ab0=c1=:?", testAst("a?b=0:c=1;"));
8418+
84168419
ASSERT_EQUALS("a\"\"=", testAst("a=\"\""));
84178420
ASSERT_EQUALS("a\'\'=", testAst("a=\'\'"));
84188421
ASSERT_EQUALS("a1[\"\"=", testAst("char a[1]=\"\";"));

0 commit comments

Comments
 (0)