Skip to content

Commit 8a1d96b

Browse files
authored
Merge pull request github#3374 from jbj/PartialDefinition-refactor
C++: Refactor `PartialDefinition` charpred
2 parents de3fa8e + 796041a commit 8a1d96b

File tree

3 files changed

+35
-43
lines changed

3 files changed

+35
-43
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNo
299299

300300
override Node getPreUpdateNode() { result.asExpr() = pd.getDefinedExpr() }
301301

302-
override Location getLocation() { result = pd.getLocation() }
302+
override Location getLocation() { result = pd.getActualLocation() }
303303

304304
PartialDefinition getPartialDefinition() { result = pd }
305305

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

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -113,44 +113,39 @@ class FlowVar extends TFlowVar {
113113
* ```
114114
*/
115115
private module PartialDefinitions {
116-
private newtype TPartialDefinition =
117-
TExplicitFieldStoreQualifier(Expr qualifier, ControlFlowNode node) {
118-
exists(FieldAccess fa | qualifier = fa.getQualifier() |
116+
private predicate isInstanceFieldWrite(FieldAccess fa, ControlFlowNode node) {
117+
assignmentLikeOperation(node, _, fa, _)
118+
}
119+
120+
class PartialDefinition extends Expr {
121+
ControlFlowNode node;
122+
123+
PartialDefinition() {
124+
exists(FieldAccess fa | this = fa.getQualifier() |
125+
// `fa = ...`, `fa += ...`, etc.
119126
isInstanceFieldWrite(fa, node)
120127
or
128+
// `fa.a = ...`, `f(&fa)`, etc.
121129
exists(PartialDefinition pd |
122130
node = pd.getSubBasicBlockStart() and
123131
fa = pd.getDefinedExpr()
124132
)
125133
)
126-
} or
127-
TExplicitCallQualifier(Expr qualifier) {
134+
or
135+
// `e.f(...)`
128136
exists(Call call |
129-
qualifier = call.getQualifier() and
137+
this = call.getQualifier() and
130138
not call.getTarget().hasSpecifier("const")
131-
)
132-
} or
133-
TReferenceArgument(Expr arg, VariableAccess va) { referenceArgument(va, arg) }
134-
135-
private predicate isInstanceFieldWrite(FieldAccess fa, ControlFlowNode node) {
136-
assignmentLikeOperation(node, _, fa, _)
137-
}
138-
139-
class PartialDefinition extends TPartialDefinition {
140-
Expr definedExpr;
141-
ControlFlowNode node;
142-
143-
PartialDefinition() {
144-
this = TExplicitFieldStoreQualifier(definedExpr, node)
145-
or
146-
this = TExplicitCallQualifier(definedExpr) and node = definedExpr
139+
) and
140+
node = this
147141
or
148-
this = TReferenceArgument(definedExpr, node)
142+
// `f(e)`, `f(&e)`, etc.
143+
referenceArgument(node, this)
149144
}
150145

151-
predicate partiallyDefines(Variable v) { definedExpr = v.getAnAccess() }
146+
predicate partiallyDefines(Variable v) { this = v.getAnAccess() }
152147

153-
predicate partiallyDefinesThis(ThisExpr e) { definedExpr = e }
148+
predicate partiallyDefinesThis(ThisExpr e) { this = e }
154149

155150
/**
156151
* Gets the subBasicBlock where this `PartialDefinition` is defined.
@@ -165,33 +160,29 @@ private module PartialDefinitions {
165160
* ```
166161
* The expression `x` is being partially defined.
167162
*/
168-
Expr getDefinedExpr() { result = definedExpr }
163+
Expr getDefinedExpr() { result = this }
169164

170-
Location getLocation() {
171-
not exists(definedExpr.getLocation()) and result = definedExpr.getParent().getLocation()
165+
/**
166+
* Gets the location of this element, adjusted to avoid unknown locations
167+
* on compiler-generated `ThisExpr`s.
168+
*/
169+
Location getActualLocation() {
170+
not exists(this.getLocation()) and result = this.getParent().getLocation()
172171
or
173-
definedExpr.getLocation() instanceof UnknownLocation and
174-
result = definedExpr.getParent().getLocation()
172+
this.getLocation() instanceof UnknownLocation and
173+
result = this.getParent().getLocation()
175174
or
176-
result = definedExpr.getLocation() and not result instanceof UnknownLocation
175+
result = this.getLocation() and not result instanceof UnknownLocation
177176
}
178-
179-
string toString() { result = "partial def of " + definedExpr }
180177
}
181178

182179
/**
183180
* A partial definition that's a definition by reference.
184181
*/
185-
class DefinitionByReference extends PartialDefinition, TReferenceArgument {
182+
class DefinitionByReference extends PartialDefinition {
186183
VariableAccess va;
187184

188-
DefinitionByReference() {
189-
// `this` is not restricted in this charpred. That's because the full
190-
// extent of this class includes the charpred of the superclass, which
191-
// relates `this` to `definedExpr`, and `va` is functionally determined
192-
// by `definedExpr`.
193-
referenceArgument(va, definedExpr)
194-
}
185+
DefinitionByReference() { referenceArgument(va, this) }
195186

196187
VariableAccess getVariableAccess() { result = va }
197188

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import semmle.code.cpp.dataflow.internal.FlowVar
22

33
from PartialDefinition def
4-
select def, def.getDefinedExpr(), def.getSubBasicBlockStart()
4+
select def.getActualLocation().toString(), "partial def of " + def.toString(), def.getDefinedExpr(),
5+
def.getSubBasicBlockStart()

0 commit comments

Comments
 (0)