@@ -887,13 +887,96 @@ module Decls {
887
887
}
888
888
889
889
module 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 ;
892
900
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 }
897
980
}
898
981
}
899
982
@@ -1122,15 +1205,139 @@ module Exprs {
1122
1205
}
1123
1206
}
1124
1207
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
+ }
1127
1252
}
1128
1253
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 ) }
1131
1279
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
+ }
1134
1341
}
1135
1342
}
1136
1343
0 commit comments