@@ -64,6 +64,15 @@ abstract class AttrRef extends Node {
6464abstract class AttrWrite extends AttrRef {
6565 /** Gets the data flow node corresponding to the value that is written to the attribute. */
6666 abstract Node getValue ( ) ;
67+
68+ /**
69+ * Holds if this attribute write writes the attribute named `attrName` on object `object` with
70+ * value `value`.
71+ */
72+ predicate writes ( Node object , string attrName , Node value ) {
73+ this .accesses ( object , attrName ) and
74+ this .getValue ( ) = value
75+ }
6776}
6877
6978/**
@@ -225,7 +234,14 @@ private class ClassDefinitionAsAttrWrite extends AttrWrite, CfgNode {
225234 * - Dynamic attribute reads using `getattr`: `getattr(object, attr)`
226235 * - Qualified imports: `from module import attr as name`
227236 */
228- abstract class AttrRead extends AttrRef , Node , LocalSourceNode { }
237+ abstract class AttrRead extends AttrRef , Node , LocalSourceNode {
238+
239+ /** Holds if this attribute read reads the attribute named `attrName` on the object `object`. */
240+ predicate reads ( Node object , string attrName ) {
241+ this .accesses ( object , attrName )
242+ }
243+
244+ }
229245
230246/** A simple attribute read, e.g. `object.attr` */
231247private class AttributeReadAsAttrRead extends AttrRead , CfgNode {
0 commit comments