Skip to content

Commit

Permalink
Swift: Adopt shared ConditionalCompletionSplitting implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
hvitved committed Oct 9, 2024
1 parent 47704e3 commit f73ce49
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ module CfgInput implements InputSig<Location> {

CfgScope getCfgScope(AstNode n) { result = scopeOfAst(n.asAstNode()) }

class SplitKindBase = Splitting::TSplitKind;

class Split = Splitting::Split;

class SuccessorType = Cfg::SuccessorType;

/** Gets a successor type that matches completion `c`. */
Expand Down Expand Up @@ -88,4 +84,19 @@ module CfgInput implements InputSig<Location> {
}
}

module CfgImpl = Make<Location, CfgInput>;
private module CfgSplittingInput implements SplittingInputSig<Location, CfgInput> {
private import Splitting as S

class SplitKindBase = S::TSplitKind;

class Split = S::Split;
}

private module ConditionalCompletionSplittingInput implements
ConditionalCompletionSplittingInputSig<Location, CfgInput, CfgSplittingInput>
{
import Splitting::ConditionalCompletionSplitting::ConditionalCompletionSplittingInput
}

module CfgImpl =
MakeWithSplitting<Location, CfgInput, CfgSplittingInput, ConditionalCompletionSplittingInput>;
72 changes: 31 additions & 41 deletions swift/ql/lib/codeql/swift/controlflow/internal/Splitting.qll
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Split extends TSplit {
string toString() { none() }
}

private module ConditionalCompletionSplitting {
module ConditionalCompletionSplitting {
/** A split for conditional completions. */
class ConditionalCompletionSplit extends Split, TConditionalCompletionSplit {
ConditionalCompletion completion;
Expand All @@ -38,62 +38,52 @@ private module ConditionalCompletionSplitting {
override string toString() { result = completion.toString() }
}

private class ConditionalCompletionSplitKind extends SplitKind, TConditionalCompletionSplitKind {
private class ConditionalCompletionSplitKind_ extends SplitKind, TConditionalCompletionSplitKind {
override int getListOrder() { result = 0 }

override predicate isEnabled(ControlFlowElement n) { this.appliesTo(n) }

override string toString() { result = "ConditionalCompletion" }
}

private class ConditionalCompletionSplitImpl extends SplitImpl instanceof ConditionalCompletionSplit
{
override ConditionalCompletionSplitKind getKind() { any() }
module ConditionalCompletionSplittingInput {
private import Completion as Comp

override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
succ(pred, succ, c) and
last(succ, _, super.getCompletion()) and
class ConditionalCompletion = Comp::ConditionalCompletion;

class ConditionalCompletionSplitKind extends ConditionalCompletionSplitKind_, TSplitKind { }

class ConditionalCompletionSplit = ConditionalCompletionSplitting::ConditionalCompletionSplit;

bindingset[parent, parentCompletion]
private predicate condPropagateAstExpr(
AstNode parent, ConditionalCompletion parentCompletion, AstNode child,
ConditionalCompletion childCompletion
) {
child = parent.(NotExpr).getOperand().getFullyConverted() and
childCompletion.(BooleanCompletion).getDual() = parentCompletion
or
childCompletion = parentCompletion and
(
astLast(succ.asAstNode().(NotExpr).getOperand().getFullyConverted(), pred, c) and
super.getCompletion().(BooleanCompletion).getDual() = c
child = parent.(LogicalAndExpr).getAnOperand().getFullyConverted()
or
astLast(succ.asAstNode().(LogicalAndExpr).getAnOperand().getFullyConverted(), pred, c) and
super.getCompletion() = c
child = parent.(LogicalOrExpr).getAnOperand().getFullyConverted()
or
astLast(succ.asAstNode().(LogicalOrExpr).getAnOperand().getFullyConverted(), pred, c) and
super.getCompletion() = c
child = parent.(IfExpr).getBranch(_).getFullyConverted()
or
succ.asAstNode() =
any(IfExpr ce |
astLast(ce.getBranch(_).getFullyConverted(), pred, c) and
super.getCompletion() = c
)
or
exists(Expr e, Exprs::Conversions::ConversionOrIdentityTree conv |
succ.asAstNode() = conv.getAst() and
conv.convertsFrom(e) and
astLast(e, pred, c) and
super.getCompletion() = c
exists(Exprs::Conversions::ConversionOrIdentityTree conv |
parent = conv.getAst() and
conv.convertsFrom(child)
)
)
}

override predicate hasEntryScope(CfgInput::CfgScope scope, ControlFlowElement succ) { none() }

override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
this.appliesTo(pred) and
succ(pred, succ, c) and
if c instanceof ConditionalCompletion then super.getCompletion() = c else any()
}

override predicate hasExitScope(CfgInput::CfgScope scope, ControlFlowElement last, Completion c) {
this.appliesTo(last) and
succExit(scope, last, c) and
if c instanceof ConditionalCompletion then super.getCompletion() = c else any()
}

override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
none()
bindingset[parent, parentCompletion]
predicate condPropagateExpr(
ControlFlowElement parent, ConditionalCompletion parentCompletion, ControlFlowElement child,
ConditionalCompletion childCompletion
) {
condPropagateAstExpr(parent.asAstNode(), parentCompletion, child.asAstNode(), childCompletion)
}
}
}

0 comments on commit f73ce49

Please sign in to comment.