Skip to content

Commit 8e8c65a

Browse files
authored
Merge pull request #4146 from jbj/partiallyDefinesVariableAt
C++: Fix two join orders in FlowVar.qll
2 parents c9e22ab + e949c16 commit 8e8c65a

File tree

1 file changed

+24
-9
lines changed
  • cpp/ql/src/semmle/code/cpp/dataflow/internal

1 file changed

+24
-9
lines changed

cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,25 @@ private module PartialDefinitions {
120120
)
121121
}
122122

123-
predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() }
123+
deprecated predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() }
124124

125-
predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
125+
deprecated predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
126126

127127
/**
128128
* Gets the subBasicBlock where this `PartialDefinition` is defined.
129129
*/
130130
ControlFlowNode getSubBasicBlockStart() { result = node }
131131

132+
/**
133+
* Holds if this `PartialDefinition` defines variable `v` at control-flow
134+
* node `cfn`.
135+
*/
136+
pragma[noinline]
137+
predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) {
138+
innerDefinedExpr = v.getAnAccess() and
139+
cfn = node
140+
}
141+
132142
/**
133143
* Holds if this partial definition may modify `inner` (or what it points
134144
* to) through `outer`. These expressions will never be `Conversion`s.
@@ -188,7 +198,7 @@ module FlowVar_internal {
188198
predicate fullySupportedSsaVariable(Variable v) {
189199
v = any(SsaDefinition def).getAVariable() and
190200
// A partially-defined variable is handled using the partial definitions logic.
191-
not any(PartialDefinition p).partiallyDefines(v) and
201+
not any(PartialDefinition p).partiallyDefinesVariableAt(v, _) and
192202
// SSA variables do not exist before their first assignment, but one
193203
// feature of this data flow library is to track where uninitialized data
194204
// ends up.
@@ -232,7 +242,7 @@ module FlowVar_internal {
232242
or
233243
assignmentLikeOperation(sbb, v, _, _)
234244
or
235-
sbb = any(PartialDefinition p | p.partiallyDefines(v)).getSubBasicBlockStart()
245+
exists(PartialDefinition p | p.partiallyDefinesVariableAt(v, sbb))
236246
or
237247
blockVarDefinedByVariable(sbb, v)
238248
)
@@ -363,8 +373,7 @@ module FlowVar_internal {
363373

364374
override predicate definedPartiallyAt(Expr e) {
365375
exists(PartialDefinition p |
366-
p.partiallyDefines(v) and
367-
sbb = p.getSubBasicBlockStart() and
376+
p.partiallyDefinesVariableAt(v, sbb) and
368377
p.definesExpressions(_, e)
369378
)
370379
}
@@ -427,7 +436,7 @@ module FlowVar_internal {
427436
/**
428437
* Gets a variable that is assigned in this loop and read outside the loop.
429438
*/
430-
private Variable getARelevantVariable() {
439+
Variable getARelevantVariable() {
431440
result = this.getAVariableAssignedInLoop() and
432441
exists(VariableAccess va |
433442
va.getTarget() = result and
@@ -472,10 +481,16 @@ module FlowVar_internal {
472481
reachesWithoutAssignment(bb.getAPredecessor(), v) and
473482
this.bbInLoop(bb)
474483
) and
475-
not assignmentLikeOperation(bb.getANode(), v, _, _)
484+
not assignsToVar(bb, v)
476485
}
477486
}
478487

488+
pragma[noinline]
489+
private predicate assignsToVar(BasicBlock bb, Variable v) {
490+
assignmentLikeOperation(bb.getANode(), v, _, _) and
491+
exists(AlwaysTrueUponEntryLoop loop | v = loop.getARelevantVariable())
492+
}
493+
479494
/**
480495
* Holds if `loop` always assigns to `v` before leaving through an edge
481496
* from `bbInside` in its condition to `bbOutside` outside the loop. Also,
@@ -736,7 +751,7 @@ module FlowVar_internal {
736751
exists(Variable v | not fullySupportedSsaVariable(v) |
737752
assignmentLikeOperation(this, v, _, _)
738753
or
739-
this = any(PartialDefinition p | p.partiallyDefines(v)).getSubBasicBlockStart()
754+
exists(PartialDefinition p | p.partiallyDefinesVariableAt(v, this))
740755
// It is not necessary to cut the basic blocks at `Initializer` nodes
741756
// because the affected variable can have no _other_ value before its
742757
// initializer. It is not necessary to cut basic blocks at procedure

0 commit comments

Comments
 (0)