diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp --- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -1126,7 +1126,7 @@ SymbolManager &SymMgr = State->getSymbolManager(); - int UnknownStates = 0; + llvm::SmallSet QueriedToUnknown; // Loop goes through all of the columns exept the last one ('UnknownX2'). // We treat `UnknownX2` column separately at the end of the loop body. @@ -1163,7 +1163,8 @@ CmpOpTable.getCmpOpState(CurrentOP, QueriedOP); if (BranchState == OperatorRelationsTable::Unknown) { - if (++UnknownStates == 2) + QueriedToUnknown.insert(QueriedOP); + if (QueriedToUnknown.size() == 2) // If we met both Unknown states. // if (x <= y) // assume true // if (x != y) // assume true diff --git a/clang/test/Analysis/constraint_manager_conditions.cpp b/clang/test/Analysis/constraint_manager_conditions.cpp --- a/clang/test/Analysis/constraint_manager_conditions.cpp +++ b/clang/test/Analysis/constraint_manager_conditions.cpp @@ -211,3 +211,17 @@ clang_analyzer_eval(y != x); // expected-warning{{FALSE}} } } + +// Test the logic of reaching the `Unknonw` tristate in CmpOpTable. +void cmp_op_table_unknownX2(int x, int y, int z) { + if (x >= y) { + // x >= y [1, 1] + if (x + z < y) + return; + // x + z < y [0, 0] + if (z != 0) + return; + // x < y [0, 0] + clang_analyzer_eval(x > y); // expected-warning{{TRUE}} expected-warning{{FALSE}} + } +}