@@ -11,7 +11,54 @@ private newtype TNode =
1111 MkSsaNode ( SsaDefinition ssa ) or
1212 MkGlobalFunctionNode ( Function f ) or
1313 MkImplicitVarargsSlice ( CallExpr c ) { c .hasImplicitVarargs ( ) } or
14- MkFlowSummaryNode ( FlowSummaryImpl:: Private:: SummaryNode sn )
14+ MkFlowSummaryNode ( FlowSummaryImpl:: Private:: SummaryNode sn ) or
15+ MkPostUpdateNode ( IR:: Instruction insn ) { insn = updatedInstruction ( ) }
16+
17+ private IR:: Instruction getADirectlyWrittenInstruction ( ) {
18+ exists ( IR:: WriteTarget target , IR:: Instruction base |
19+ target = any ( IR:: WriteInstruction w ) .getLhs ( ) and
20+ ( base = result or base = IR:: implicitDerefInstruction ( result .( IR:: EvalInstruction ) .getExpr ( ) ) )
21+ |
22+ target .( IR:: FieldTarget ) .getBase ( ) = base or
23+ target .( IR:: ElementTarget ) .getBase ( ) = base
24+ )
25+ or
26+ result = IR:: evalExprInstruction ( any ( SendStmt s ) .getChannel ( ) )
27+ }
28+
29+ private IR:: Instruction getAccessPathPredecessor2 ( IR:: Instruction insn ) {
30+ exists ( Expr e | result = IR:: evalExprInstruction ( e ) |
31+ e = insn .( IR:: EvalInstruction ) .getExpr ( ) .( UnaryExpr ) .getOperand ( )
32+ or
33+ e = insn .( IR:: EvalInstruction ) .getExpr ( ) .( StarExpr ) .getBase ( )
34+ or
35+ e = insn .( IR:: EvalImplicitDerefInstruction ) .getOperand ( )
36+ )
37+ or
38+ result = insn .( IR:: ComponentReadInstruction ) .getBase ( )
39+ }
40+
41+ private IR:: Instruction getAWrittenInstruction ( ) {
42+ result = getAccessPathPredecessor2 * ( getADirectlyWrittenInstruction ( ) )
43+ }
44+
45+ private IR:: Instruction updatedInstruction ( ) {
46+ result = IR:: evalExprInstruction ( updatedExpr ( ) ) or
47+ result instanceof IR:: EvalImplicitDerefInstruction or
48+ result = getAWrittenInstruction ( )
49+ }
50+
51+ private Expr updatedExpr ( ) {
52+ result instanceof AddressExpr
53+ or
54+ result = any ( AddressExpr e ) .getOperand ( )
55+ or
56+ result instanceof StarExpr
57+ or
58+ result instanceof DerefExpr
59+ or
60+ result = any ( CallExpr ce ) .getAnArgument ( ) and mutableType ( result .getType ( ) )
61+ }
1562
1663/** Nodes intended for only use inside the data-flow libraries. */
1764module Private {
@@ -706,19 +753,6 @@ module Public {
706753 predicate isReceiverOf ( MethodDecl m ) { parm .isReceiverOf ( m ) }
707754 }
708755
709- private Node getADirectlyWrittenNode ( ) {
710- exists ( Write w | w .writesComponent ( result , _) ) or
711- result = DataFlow:: exprNode ( any ( SendStmt s ) .getChannel ( ) )
712- }
713-
714- private DataFlow:: Node getAccessPathPredecessor ( DataFlow:: Node node ) {
715- result = node .( PointerDereferenceNode ) .getOperand ( )
716- or
717- result = node .( ComponentReadNode ) .getBase ( )
718- }
719-
720- private Node getAWrittenNode ( ) { result = getAccessPathPredecessor * ( getADirectlyWrittenNode ( ) ) }
721-
722756 /**
723757 * Holds if `tp` is a type that may (directly or indirectly) reference a memory location.
724758 *
@@ -734,6 +768,10 @@ module Public {
734768 )
735769 }
736770
771+ private class UpdateNode extends InstructionNode {
772+ UpdateNode ( ) { insn = updatedInstruction ( ) }
773+ }
774+
737775 /**
738776 * A node associated with an object after an operation that might have
739777 * changed its state.
@@ -753,35 +791,37 @@ module Public {
753791 abstract Node getPreUpdateNode ( ) ;
754792 }
755793
756- private class DefaultPostUpdateNode extends PostUpdateNode {
757- Node preupd ;
794+ /** A post-update node for an instruction that updates a value. */
795+ class DefaultPostUpdateNode extends PostUpdateNode {
796+ UpdateNode preupd ;
758797
759- DefaultPostUpdateNode ( ) {
760- (
761- preupd instanceof AddressOperationNode
762- or
763- preupd = any ( AddressOperationNode addr ) .getOperand ( )
764- or
765- preupd = any ( PointerDereferenceNode deref ) .getOperand ( )
766- or
767- preupd = getAWrittenNode ( )
768- or
769- (
770- preupd instanceof ArgumentNode and not preupd instanceof ImplicitVarargsSlice
771- or
772- preupd = any ( CallNode c ) .getAnImplicitVarargsArgument ( )
773- ) and
774- mutableType ( preupd .getType ( ) )
775- ) and
776- (
777- preupd = this .( SsaNode ) .getAUse ( )
778- or
779- preupd = this and
780- not basicLocalFlowStep ( _, this )
781- )
782- }
798+ DefaultPostUpdateNode ( ) { this = MkPostUpdateNode ( preupd .asInstruction ( ) ) }
783799
784800 override Node getPreUpdateNode ( ) { result = preupd }
801+
802+ /** Gets the node that data will flow to from this node. */
803+ Node getSuccessor ( ) {
804+ preupd = result .( SsaNode ) .getAUse ( )
805+ or
806+ preupd = result and
807+ not basicLocalFlowStep0 ( _, preupd )
808+ }
809+
810+ override ControlFlow:: Root getRoot ( ) { result = preupd .asInstruction ( ) .getRoot ( ) }
811+
812+ override Type getType ( ) { result = preupd .asInstruction ( ) .getResultType ( ) }
813+
814+ override string getNodeKind ( ) { result = "post-update node" }
815+
816+ override string toString ( ) {
817+ result = "post-update node for " + preupd .asInstruction ( ) .toString ( )
818+ }
819+
820+ override predicate hasLocationInfo (
821+ string filepath , int startline , int startcolumn , int endline , int endcolumn
822+ ) {
823+ preupd .asInstruction ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn )
824+ }
785825 }
786826
787827 /**
0 commit comments