@@ -887,13 +887,96 @@ module Decls {
887887}
888888
889889module Exprs {
890- private class AssignExprTree extends AstStandardPostOrderTree {
891- override AssignExpr ast ;
890+ module AssignExprs {
891+ /**
892+ * The control-flow of an assignment operation.
893+ *
894+ * There are two implementation of this base class:
895+ * - One where the left-hand side has direct-to-storage-access semantics
896+ * - One where the left-hand side has direct-to-implementation-access semantics
897+ */
898+ abstract private class AssignExprTree extends AstControlFlowTree {
899+ override AssignExpr ast ;
892900
893- final override ControlFlowTree getChildElement ( int i ) {
894- result .asAstNode ( ) = ast .getDest ( ) .getFullyConverted ( ) and i = 0
895- or
896- result .asAstNode ( ) = ast .getSource ( ) .getFullyConverted ( ) and i = 1
901+ final override predicate first ( ControlFlowElement first ) {
902+ astFirst ( ast .getDest ( ) .getFullyConverted ( ) , first )
903+ }
904+
905+ abstract predicate isSet ( ControlFlowElement n ) ;
906+
907+ abstract predicate isLast ( ControlFlowElement n , Completion c ) ;
908+
909+ final override predicate propagatesAbnormal ( ControlFlowElement child ) {
910+ child .asAstNode ( ) = ast .getDest ( ) .getFullyConverted ( ) or
911+ child .asAstNode ( ) = ast .getSource ( ) .getFullyConverted ( )
912+ }
913+
914+ predicate hasWillSetObserver ( ) { isPropertyObserverElement ( any ( WillSetObserver obs ) , ast ) }
915+
916+ predicate hasDidSetObserver ( ) { isPropertyObserverElement ( any ( WillSetObserver obs ) , ast ) }
917+
918+ final override predicate last ( ControlFlowElement last , Completion c ) {
919+ isPropertyObserverElement ( last , any ( DidSetObserver obs ) , ast ) and
920+ completionIsValidFor ( c , last )
921+ or
922+ not this .hasDidSetObserver ( ) and
923+ this .isLast ( last , c )
924+ }
925+
926+ final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
927+ // Flow from the destination to the source
928+ astLast ( ast .getDest ( ) .getFullyConverted ( ) , pred , c ) and
929+ c instanceof NormalCompletion and
930+ astFirst ( ast .getSource ( ) .getFullyConverted ( ) , succ )
931+ or
932+ // Flow from the source to the `willSet` observer, if any. Otherwise, flow to the set operation
933+ astLast ( ast .getSource ( ) .getFullyConverted ( ) , pred , c ) and
934+ c instanceof NormalCompletion and
935+ (
936+ if this .hasWillSetObserver ( )
937+ then isPropertyObserverElement ( succ , any ( WillSetObserver obs ) , ast )
938+ else this .isSet ( succ )
939+ )
940+ or
941+ // Flow from the set operation to the `didSet` observer, if any
942+ this .isSet ( pred ) and
943+ completionIsValidFor ( c , pred ) and
944+ isPropertyObserverElement ( succ , any ( DidSetObserver obs ) , ast )
945+ }
946+ }
947+
948+ /**
949+ * The control-flow for assignments where the left-hand side has
950+ * direct-to-implmentation-access semantics.
951+ */
952+ class PropertyAssignExpr extends AssignExprTree {
953+ AccessorDecl accessorDecl ;
954+
955+ PropertyAssignExpr ( ) { isPropertySetterElement ( accessorDecl , ast ) }
956+
957+ final override predicate isLast ( ControlFlowElement last , Completion c ) {
958+ isPropertySetterElement ( last , accessorDecl , ast ) and
959+ completionIsValidFor ( c , last )
960+ }
961+
962+ final override predicate isSet ( ControlFlowElement node ) {
963+ isPropertySetterElement ( node , _, ast )
964+ }
965+ }
966+
967+ /**
968+ * The control-flow for assignments where the left-hand side has
969+ * direct-to-storage-access semantics.
970+ */
971+ class DirectAssignExpr extends AssignExprTree {
972+ DirectAssignExpr ( ) { not this instanceof PropertyAssignExpr }
973+
974+ final override predicate isLast ( ControlFlowElement last , Completion c ) {
975+ last .asAstNode ( ) = ast and
976+ completionIsValidFor ( c , last )
977+ }
978+
979+ final override predicate isSet ( ControlFlowElement node ) { node .asAstNode ( ) = ast }
897980 }
898981 }
899982
@@ -1122,15 +1205,139 @@ module Exprs {
11221205 }
11231206 }
11241207
1125- private class DeclRefExprTree extends AstLeafTree {
1126- override DeclRefExpr ast ;
1208+ module DeclRefExprs {
1209+ class DeclRefExprLValueTree extends AstLeafTree {
1210+ override DeclRefExpr ast ;
1211+
1212+ DeclRefExprLValueTree ( ) { isLValue ( ast ) }
1213+ }
1214+
1215+ abstract class DeclRefExprRValueTree extends AstControlFlowTree {
1216+ override DeclRefExpr ast ;
1217+
1218+ DeclRefExprRValueTree ( ) { isRValue ( ast ) }
1219+
1220+ override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
1221+ none ( )
1222+ }
1223+
1224+ override predicate propagatesAbnormal ( ControlFlowElement child ) { none ( ) }
1225+ }
1226+
1227+ private class PropertyDeclRefRValueTree extends DeclRefExprRValueTree {
1228+ AccessorDecl accessor ;
1229+
1230+ PropertyDeclRefRValueTree ( ) { isPropertyGetterElement ( accessor , ast ) }
1231+
1232+ final override predicate first ( ControlFlowElement first ) {
1233+ isPropertyGetterElement ( first , accessor , ast )
1234+ }
1235+
1236+ final override predicate last ( ControlFlowElement last , Completion c ) {
1237+ isPropertyGetterElement ( last , accessor , ast ) and
1238+ completionIsValidFor ( c , last )
1239+ }
1240+ }
1241+
1242+ private class DirectDeclRefRValueTree extends DeclRefExprRValueTree {
1243+ DirectDeclRefRValueTree ( ) { not this instanceof PropertyDeclRefRValueTree }
1244+
1245+ final override predicate first ( ControlFlowElement first ) { first .asAstNode ( ) = ast }
1246+
1247+ final override predicate last ( ControlFlowElement last , Completion c ) {
1248+ last .asAstNode ( ) = ast and
1249+ completionIsValidFor ( c , last )
1250+ }
1251+ }
11271252 }
11281253
1129- private class MemberRefTree extends AstStandardPostOrderTree {
1130- override MemberRefExpr ast ;
1254+ module MemberRefs {
1255+ /**
1256+ * The control-flow of a member reference expression.
1257+ *
1258+ * There are two implementation of this base class:
1259+ * - One for lvalues
1260+ * - One for rvalues
1261+ */
1262+ abstract private class MemberRefTreeBase extends AstControlFlowTree {
1263+ override MemberRefExpr ast ;
1264+
1265+ final override predicate propagatesAbnormal ( ControlFlowElement child ) {
1266+ child .asAstNode ( ) = ast .getBaseExpr ( ) .getFullyConverted ( )
1267+ }
1268+
1269+ final override predicate first ( ControlFlowElement first ) {
1270+ astFirst ( ast .getBaseExpr ( ) .getFullyConverted ( ) , first )
1271+ }
1272+ }
1273+
1274+ /**
1275+ * The lvalue implementation of `MemberRefTreeBase`
1276+ */
1277+ private class MemberRefLValueTree extends MemberRefTreeBase {
1278+ MemberRefLValueTree ( ) { isLValue ( ast ) }
11311279
1132- final override AstNode getChildElement ( int i ) {
1133- result = ast .getBaseExpr ( ) .getFullyConverted ( ) and i = 0
1280+ final override predicate last ( ControlFlowElement last , Completion c ) {
1281+ last .asAstNode ( ) = ast and
1282+ completionIsValidFor ( c , last )
1283+ }
1284+
1285+ override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
1286+ astLast ( ast .getBaseExpr ( ) .getFullyConverted ( ) , pred , c ) and
1287+ c instanceof NormalCompletion and
1288+ succ .asAstNode ( ) = ast
1289+ }
1290+ }
1291+
1292+ /**
1293+ * The rvalue base implementation of `MemberRefTreeBase`.
1294+ *
1295+ * There are two implementations of this class:
1296+ * - One for direct-storage semantics
1297+ * - One for calls to getters
1298+ */
1299+ abstract private class MemberRefRValueTree extends MemberRefTreeBase {
1300+ MemberRefRValueTree ( ) { isRValue ( ast ) }
1301+ }
1302+
1303+ /**
1304+ * Control-flow for rvalue member accesses with direct-to-storage semantics
1305+ * or ordinary semantics without a getter.
1306+ */
1307+ private class DirectMemberRefRValue extends MemberRefRValueTree {
1308+ DirectMemberRefRValue ( ) { not this instanceof PropertyMemberRefRValue }
1309+
1310+ final override predicate last ( ControlFlowElement last , Completion c ) {
1311+ last .asAstNode ( ) = ast and
1312+ completionIsValidFor ( c , last )
1313+ }
1314+
1315+ override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
1316+ astLast ( ast .getBaseExpr ( ) .getFullyConverted ( ) , pred , c ) and
1317+ c instanceof NormalCompletion and
1318+ succ .asAstNode ( ) = ast
1319+ }
1320+ }
1321+
1322+ /**
1323+ * Control-flow for rvalue member accesses with direct-to-implementation semantics
1324+ * or ordinary semantics that includes a getter.
1325+ */
1326+ private class PropertyMemberRefRValue extends MemberRefRValueTree {
1327+ AccessorDecl accessor ;
1328+
1329+ PropertyMemberRefRValue ( ) { isPropertyGetterElement ( accessor , ast ) }
1330+
1331+ final override predicate last ( ControlFlowElement last , Completion c ) {
1332+ isPropertyGetterElement ( last , accessor , ast ) and
1333+ completionIsValidFor ( c , last )
1334+ }
1335+
1336+ override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
1337+ astLast ( ast .getBaseExpr ( ) .getFullyConverted ( ) , pred , c ) and
1338+ c instanceof NormalCompletion and
1339+ isPropertyGetterElement ( succ , accessor , ast )
1340+ }
11341341 }
11351342 }
11361343
0 commit comments