summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface
diff options
context:
space:
mode:
authorArseniy Zaostrovnykh <necto.ne@gmail.com>2024-07-29 08:12:22 +0200
committerGitHub <noreply@github.com>2024-07-29 08:12:22 +0200
commit73c72f2c6505d5bc8b47bb0420f6cba5b24270fe (patch)
treeaac2aed26a5ff22ac7166bbbd3a86b5a2ae08623 /lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface
parent034d01422b5fd8f502ccb45ce95da108415a39a6 (diff)
[analyzer] Keep alive short-circuiting condition subexpressions in a conditional (#100745)
Fix the false negative caused by state merging in the evaluation of a short-circuiting expression inside the condition of a ternary operator. The fixed symptom is that CSA always evaluates `(x || x) ? n : m` to `m`. This change forces the analyzer to consider all logical expressions prone to short-circuiting alive until the entire conditional expression is evaluated. Here is why. By default, LiveVariables analysis marks only direct subexpressions as live relative to any expression. So for `a ? b : c` it will consider `a`, `b`, and `c` alive when evaluating the ternary operator expression. To explore both possibilities opened by a ternary operator, it is important to keep something different about the exploded nodes created after the evaluation of its branches. These two nodes come to the same location, so they must have different states. Otherwise, they will be considered identical and can engender only one outcome. `ExprEngine::visitGuardedExpr` chooses the first predecessor exploded node to carry the value of the conditional expression. It works well in the case of a simple condition, because when `a ? b : c` is evaluated, `a` is kept alive, so the two branches differ in the value of `a`. However, before this patch is applied, this strategy breaks for `(x || x) ? n : m`. `x` is not a direct child of the ternary expression. Due to short-circuiting, once `x` is assumed to be `true`, evaluation jumps directly to `n` and then to the result of the entire ternary expression. Given that the result of the entire condition `(x || x)` is not constructed, and `x` is not kept alive, the difference between the path coming through `n` and through `m` disappears. As a result, exploded nodes coming from the "true expression" and the "false expression" engender identical successors and merge the execution paths.
Diffstat (limited to 'lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface')
0 files changed, 0 insertions, 0 deletions