C++: Refactor `PartialDefinition` charpred

This class used `newtype` for seemingly no reason. The new code is
shorter and should be faster as well.
This commit is contained in:
Jonas Jensen 2020-04-28 16:52:32 +02:00
Родитель bc7163aa68
Коммит 796041af72
3 изменённых файлов: 35 добавлений и 43 удалений

Просмотреть файл

@ -299,7 +299,7 @@ private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNo
override Node getPreUpdateNode() { result.asExpr() = pd.getDefinedExpr() }
override Location getLocation() { result = pd.getLocation() }
override Location getLocation() { result = pd.getActualLocation() }
PartialDefinition getPartialDefinition() { result = pd }

Просмотреть файл

@ -113,44 +113,39 @@ class FlowVar extends TFlowVar {
* ```
*/
private module PartialDefinitions {
private newtype TPartialDefinition =
TExplicitFieldStoreQualifier(Expr qualifier, ControlFlowNode node) {
exists(FieldAccess fa | qualifier = fa.getQualifier() |
private predicate isInstanceFieldWrite(FieldAccess fa, ControlFlowNode node) {
assignmentLikeOperation(node, _, fa, _)
}
class PartialDefinition extends Expr {
ControlFlowNode node;
PartialDefinition() {
exists(FieldAccess fa | this = fa.getQualifier() |
// `fa = ...`, `fa += ...`, etc.
isInstanceFieldWrite(fa, node)
or
// `fa.a = ...`, `f(&fa)`, etc.
exists(PartialDefinition pd |
node = pd.getSubBasicBlockStart() and
fa = pd.getDefinedExpr()
)
)
} or
TExplicitCallQualifier(Expr qualifier) {
or
// `e.f(...)`
exists(Call call |
qualifier = call.getQualifier() and
this = call.getQualifier() and
not call.getTarget().hasSpecifier("const")
)
} or
TReferenceArgument(Expr arg, VariableAccess va) { referenceArgument(va, arg) }
private predicate isInstanceFieldWrite(FieldAccess fa, ControlFlowNode node) {
assignmentLikeOperation(node, _, fa, _)
}
class PartialDefinition extends TPartialDefinition {
Expr definedExpr;
ControlFlowNode node;
PartialDefinition() {
this = TExplicitFieldStoreQualifier(definedExpr, node)
) and
node = this
or
this = TExplicitCallQualifier(definedExpr) and node = definedExpr
or
this = TReferenceArgument(definedExpr, node)
// `f(e)`, `f(&e)`, etc.
referenceArgument(node, this)
}
predicate partiallyDefines(Variable v) { definedExpr = v.getAnAccess() }
predicate partiallyDefines(Variable v) { this = v.getAnAccess() }
predicate partiallyDefinesThis(ThisExpr e) { definedExpr = e }
predicate partiallyDefinesThis(ThisExpr e) { this = e }
/**
* Gets the subBasicBlock where this `PartialDefinition` is defined.
@ -165,33 +160,29 @@ private module PartialDefinitions {
* ```
* The expression `x` is being partially defined.
*/
Expr getDefinedExpr() { result = definedExpr }
Expr getDefinedExpr() { result = this }
Location getLocation() {
not exists(definedExpr.getLocation()) and result = definedExpr.getParent().getLocation()
/**
* Gets the location of this element, adjusted to avoid unknown locations
* on compiler-generated `ThisExpr`s.
*/
Location getActualLocation() {
not exists(this.getLocation()) and result = this.getParent().getLocation()
or
definedExpr.getLocation() instanceof UnknownLocation and
result = definedExpr.getParent().getLocation()
this.getLocation() instanceof UnknownLocation and
result = this.getParent().getLocation()
or
result = definedExpr.getLocation() and not result instanceof UnknownLocation
result = this.getLocation() and not result instanceof UnknownLocation
}
string toString() { result = "partial def of " + definedExpr }
}
/**
* A partial definition that's a definition by reference.
*/
class DefinitionByReference extends PartialDefinition, TReferenceArgument {
class DefinitionByReference extends PartialDefinition {
VariableAccess va;
DefinitionByReference() {
// `this` is not restricted in this charpred. That's because the full
// extent of this class includes the charpred of the superclass, which
// relates `this` to `definedExpr`, and `va` is functionally determined
// by `definedExpr`.
referenceArgument(va, definedExpr)
}
DefinitionByReference() { referenceArgument(va, this) }
VariableAccess getVariableAccess() { result = va }

Просмотреть файл

@ -1,4 +1,5 @@
import semmle.code.cpp.dataflow.internal.FlowVar
from PartialDefinition def
select def, def.getDefinedExpr(), def.getSubBasicBlockStart()
select def.getActualLocation().toString(), "partial def of " + def.toString(), def.getDefinedExpr(),
def.getSubBasicBlockStart()