mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Python points-to: Handle varargs in caller
This commit is contained in:
@@ -168,12 +168,12 @@ class Call extends Call_ {
|
||||
|
||||
override CallNode getAFlowNode() { result = super.getAFlowNode() }
|
||||
|
||||
/** Gets a tuple (*) argument of this class definition. */
|
||||
/** Gets a tuple (*) argument of this call. */
|
||||
Expr getStarargs() {
|
||||
result = this.getAPositionalArg().(Starred).getValue()
|
||||
}
|
||||
|
||||
/** Gets a dictionary (**) argument of this class definition. */
|
||||
/** Gets a dictionary (**) argument of this call. */
|
||||
Expr getKwargs() {
|
||||
result = this.getANamedArg().(DictUnpacking).getValue()
|
||||
}
|
||||
@@ -227,10 +227,18 @@ class Call extends Call_ {
|
||||
result = this.getKwargs().(Dict).getAKey().(StrConst).getText()
|
||||
}
|
||||
|
||||
/** Gets the positional argument count of this call, provided there is no more than one tuple (*) argument. */
|
||||
int getPositionalArgumentCount() {
|
||||
count(this.getStarargs()) < 2 and
|
||||
result = count(this.getAPositionalArg())
|
||||
result = count(Expr arg | arg = this.getAPositionalArg() and not arg instanceof Starred)
|
||||
}
|
||||
|
||||
/** Gets the tuple (*) argument of this call, provided there is exactly one. */
|
||||
Expr getStarArg() {
|
||||
count(this.getStarargs()) < 2 and
|
||||
result = getStarargs()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A conditional expression such as, `body if test else orelse` */
|
||||
|
||||
@@ -481,6 +481,11 @@ class CallNode extends ControlFlowNode {
|
||||
)
|
||||
}
|
||||
|
||||
ControlFlowNode getStarArg() {
|
||||
result.getNode() = this.getNode().getStarArg() and
|
||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A control flow corresponding to an attribute expression, such as `value.attr` */
|
||||
|
||||
@@ -41,7 +41,7 @@ abstract class TupleObjectInternal extends SequenceObjectInternal {
|
||||
private string contents(int n) {
|
||||
n < 4 and n = this.length() and result = ""
|
||||
or
|
||||
n = 4 and n < this.length() and result = "... " + (this.length()-4).toString() + " more"
|
||||
n = 3 and this.length() > 3 and result = (this.length()-3).toString() + " more..."
|
||||
or
|
||||
result = this.getItem(n).toString() + ", " + this.contents(n+1)
|
||||
}
|
||||
@@ -165,7 +165,7 @@ class VarargsTupleObjectInternal extends TVarargsTuple, TupleObjectInternal {
|
||||
exists(CallNode call, PointsToContext context, int offset, int length |
|
||||
this = TVarargsTuple(call, context, offset, length) and
|
||||
n < length and
|
||||
PointsToInternal::pointsTo(call.getArg(offset+n), context, result, _)
|
||||
InterProceduralPointsTo::positional_argument_points_to(call, offset+n, context, result, _)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -844,11 +844,13 @@ module InterProceduralPointsTo {
|
||||
private predicate normal_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
|
||||
exists(PointsToContext caller, ControlFlowNode arg |
|
||||
PointsToInternal::pointsTo(arg, caller, value, origin) and
|
||||
callsite_argument_transfer(arg, caller, def, context)
|
||||
named_argument_transfer(arg, caller, def, context)
|
||||
)
|
||||
or
|
||||
not def.isSelf() and not def.isVarargs() and not def.isKwargs() and
|
||||
context.isRuntime() and value = ObjectInternal::unknown() and origin = def.getDefiningNode()
|
||||
or
|
||||
positional_parameter_points_to(def, context, value, origin)
|
||||
}
|
||||
|
||||
pragma [noinline]
|
||||
@@ -921,7 +923,7 @@ module InterProceduralPointsTo {
|
||||
exists(int parameter_offset |
|
||||
callsite_calls_function(call, caller, scope, callee, parameter_offset) and
|
||||
startOffset = scope.getPositionalParameterCount() - parameter_offset and
|
||||
length = call.getNode().getPositionalArgumentCount() - startOffset and
|
||||
length = positional_argument_count(call, caller) - startOffset and
|
||||
length > 0
|
||||
)
|
||||
}
|
||||
@@ -929,7 +931,7 @@ module InterProceduralPointsTo {
|
||||
predicate varargs_empty_tuple(Function scope, PointsToContext callee) {
|
||||
exists(CallNode call, PointsToContext caller, int parameter_offset |
|
||||
callsite_calls_function(call, caller, scope, callee, parameter_offset) and
|
||||
scope.getPositionalParameterCount() - parameter_offset >= call.getNode().getPositionalArgumentCount()
|
||||
scope.getPositionalParameterCount() - parameter_offset >= positional_argument_count(call, caller)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -940,16 +942,39 @@ module InterProceduralPointsTo {
|
||||
p.isKwargs() and value = TUnknownInstance(ObjectInternal::builtin("dict"))
|
||||
}
|
||||
|
||||
/** Holds if the `(argument, caller)` pair matches up with `(param, callee)` pair across call. */
|
||||
cached predicate callsite_argument_transfer(ControlFlowNode argument, PointsToContext caller, ParameterDefinition param, PointsToContext callee) {
|
||||
predicate positional_argument_points_to(CallNode call, int argument, PointsToContext caller, ObjectInternal value, ControlFlowNode origin) {
|
||||
PointsToInternal::pointsTo(call.getArg(argument), caller, value, origin)
|
||||
or
|
||||
exists(SequenceObjectInternal arg, int pos |
|
||||
pos = call.getNode().getPositionalArgumentCount() and
|
||||
PointsToInternal::pointsTo(origin, caller, arg, _) and
|
||||
value = arg.getItem(argument-pos) and
|
||||
origin = call.getStarArg()
|
||||
)
|
||||
}
|
||||
|
||||
private int positional_argument_count(CallNode call, PointsToContext caller) {
|
||||
result = call.getNode().getPositionalArgumentCount() and not exists(call.getStarArg()) and caller.appliesTo(call)
|
||||
or
|
||||
exists(SequenceObjectInternal arg, int pos |
|
||||
pos = call.getNode().getPositionalArgumentCount() and
|
||||
PointsToInternal::pointsTo(call.getStarArg(), caller, arg, _) and
|
||||
result = pos + arg.length()
|
||||
)
|
||||
}
|
||||
|
||||
predicate positional_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
|
||||
exists(CallNode call, int argument, PointsToContext caller, Function func, int offset |
|
||||
positional_argument_points_to(call, argument, caller, value, origin) and
|
||||
callsite_calls_function(call, caller, func, context, offset) and
|
||||
def.getParameter() = func.getArg(argument+offset)
|
||||
)
|
||||
}
|
||||
|
||||
cached predicate named_argument_transfer(ControlFlowNode argument, PointsToContext caller, ParameterDefinition param, PointsToContext callee) {
|
||||
exists(CallNode call, Function func, int offset |
|
||||
callsite_calls_function(call, caller, func, callee, offset)
|
||||
|
|
||||
exists(int n |
|
||||
argument = call.getArg(n) and
|
||||
param.getParameter() = func.getArg(n+offset)
|
||||
)
|
||||
or
|
||||
exists(string name |
|
||||
argument = call.getArgByName(name) and
|
||||
param.getParameter() = func.getArgByName(name)
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
| l_calls.py:37 | ControlFlowNode for f() | f |
|
||||
| l_calls.py:38 | ControlFlowNode for Attribute() | E.m |
|
||||
| l_calls.py:39 | ControlFlowNode for Attribute() | E.m |
|
||||
| l_calls.py:42 | ControlFlowNode for f() | f |
|
||||
| l_calls.py:51 | ControlFlowNode for g() | g |
|
||||
| l_calls.py:52 | ControlFlowNode for Attribute() | F.m |
|
||||
| l_calls.py:53 | ControlFlowNode for Attribute() | F.m |
|
||||
| q_super.py:4 | ControlFlowNode for Attribute() | object.__init__ |
|
||||
| q_super.py:12 | ControlFlowNode for Attribute() | Base2.__init__ |
|
||||
| q_super.py:22 | ControlFlowNode for Attribute() | Base1.meth |
|
||||
|
||||
@@ -113,14 +113,18 @@
|
||||
| k_getsetattr.py:4 | Class C | meth1 | Function meth1 |
|
||||
| k_getsetattr.py:4 | Class C | meth2 | Function meth2 |
|
||||
| l_calls.py:0 | Module code.l_calls | E | class E |
|
||||
| l_calls.py:0 | Module code.l_calls | F | class F |
|
||||
| l_calls.py:0 | Module code.l_calls | Owner | class Owner |
|
||||
| l_calls.py:0 | Module code.l_calls | bar | Function bar |
|
||||
| l_calls.py:0 | Module code.l_calls | f | Function f |
|
||||
| l_calls.py:0 | Module code.l_calls | foo | Function foo |
|
||||
| l_calls.py:0 | Module code.l_calls | g | Function g |
|
||||
| l_calls.py:0 | Module code.l_calls | t | Tuple |
|
||||
| l_calls.py:12 | Class Owner | cm | classmethod() |
|
||||
| l_calls.py:12 | Class Owner | cm2 | classmethod() |
|
||||
| l_calls.py:12 | Class Owner | m | Function m |
|
||||
| l_calls.py:32 | Class E | m | Function m |
|
||||
| l_calls.py:47 | Class F | m | Function m |
|
||||
| o_no_returns.py:0 | Module code.o_no_returns | bar | Function bar |
|
||||
| o_no_returns.py:0 | Module code.o_no_returns | fail | Function fail |
|
||||
| o_no_returns.py:0 | Module code.o_no_returns | foo | Function foo |
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
| k_getsetattr.py:15 | ControlFlowNode for Attribute() | 6 |
|
||||
| l_calls.py:4 | ControlFlowNode for Attribute() | 4 |
|
||||
| l_calls.py:9 | ControlFlowNode for foo() | 4 |
|
||||
| l_calls.py:48 | ControlFlowNode for None | 48 |
|
||||
| m_attributes.py:12 | ControlFlowNode for Attribute() | 8 |
|
||||
| m_attributes.py:13 | ControlFlowNode for Attribute() | 8 |
|
||||
| o_no_returns.py:7 | ControlFlowNode for fail() | 10 |
|
||||
|
||||
@@ -602,6 +602,7 @@ WARNING: Predicate points_to has been deprecated and may be removed in future (P
|
||||
| l_calls.py:29 | ControlFlowNode for args | args | builtin-class tuple | 29 | runtime |
|
||||
| l_calls.py:29 | ControlFlowNode for f | Function f | builtin-class function | 29 | import |
|
||||
| l_calls.py:30 | ControlFlowNode for args | args | builtin-class tuple | 29 | code/l_calls.py:37 from import |
|
||||
| l_calls.py:30 | ControlFlowNode for args | args | builtin-class tuple | 29 | code/l_calls.py:42 from import |
|
||||
| l_calls.py:30 | ControlFlowNode for args | args | builtin-class tuple | 29 | runtime |
|
||||
| l_calls.py:32 | ControlFlowNode for ClassExpr | class E | builtin-class type | 32 | import |
|
||||
| l_calls.py:32 | ControlFlowNode for E | class E | builtin-class type | 32 | import |
|
||||
@@ -635,6 +636,37 @@ WARNING: Predicate points_to has been deprecated and may be removed in future (P
|
||||
| l_calls.py:39 | ControlFlowNode for IntegerLiteral | int 3 | builtin-class int | 39 | import |
|
||||
| l_calls.py:39 | ControlFlowNode for IntegerLiteral | int 4 | builtin-class int | 39 | import |
|
||||
| l_calls.py:39 | ControlFlowNode for IntegerLiteral | int 5 | builtin-class int | 39 | import |
|
||||
| l_calls.py:41 | ControlFlowNode for Str | 'a' | builtin-class str | 41 | import |
|
||||
| l_calls.py:41 | ControlFlowNode for Str | 'b' | builtin-class str | 41 | import |
|
||||
| l_calls.py:41 | ControlFlowNode for Str | 'c' | builtin-class str | 41 | import |
|
||||
| l_calls.py:41 | ControlFlowNode for Tuple | Tuple | builtin-class tuple | 41 | import |
|
||||
| l_calls.py:41 | ControlFlowNode for t | Tuple | builtin-class tuple | 41 | import |
|
||||
| l_calls.py:42 | ControlFlowNode for f | Function f | builtin-class function | 29 | import |
|
||||
| l_calls.py:42 | ControlFlowNode for f() | args | builtin-class tuple | 29 | import |
|
||||
| l_calls.py:42 | ControlFlowNode for t | Tuple | builtin-class tuple | 41 | import |
|
||||
| l_calls.py:44 | ControlFlowNode for FunctionExpr | Function g | builtin-class function | 44 | import |
|
||||
| l_calls.py:44 | ControlFlowNode for g | Function g | builtin-class function | 44 | import |
|
||||
| l_calls.py:45 | ControlFlowNode for a | 'a' | builtin-class str | 51 | code/l_calls.py:51 from import |
|
||||
| l_calls.py:47 | ControlFlowNode for ClassExpr | class F | builtin-class type | 47 | import |
|
||||
| l_calls.py:47 | ControlFlowNode for F | class F | builtin-class type | 47 | import |
|
||||
| l_calls.py:47 | ControlFlowNode for object | builtin-class object | builtin-class type | 47 | import |
|
||||
| l_calls.py:48 | ControlFlowNode for FunctionExpr | Function m | builtin-class function | 48 | import |
|
||||
| l_calls.py:48 | ControlFlowNode for None | NoneType None | builtin-class NoneType | 48 | import |
|
||||
| l_calls.py:48 | ControlFlowNode for m | Function m | builtin-class function | 48 | import |
|
||||
| l_calls.py:49 | ControlFlowNode for x | 'a' | builtin-class str | 52 | code/l_calls.py:52 from import |
|
||||
| l_calls.py:49 | ControlFlowNode for x | 'b' | builtin-class str | 53 | code/l_calls.py:53 from import |
|
||||
| l_calls.py:51 | ControlFlowNode for g | Function g | builtin-class function | 44 | import |
|
||||
| l_calls.py:51 | ControlFlowNode for g() | 'a' | builtin-class str | 51 | import |
|
||||
| l_calls.py:51 | ControlFlowNode for t | Tuple | builtin-class tuple | 41 | import |
|
||||
| l_calls.py:52 | ControlFlowNode for Attribute | Attribute | builtin-class method | 52 | import |
|
||||
| l_calls.py:52 | ControlFlowNode for Attribute() | 'a' | builtin-class str | 52 | import |
|
||||
| l_calls.py:52 | ControlFlowNode for F | class F | builtin-class type | 47 | import |
|
||||
| l_calls.py:52 | ControlFlowNode for F() | F() | class F | 52 | import |
|
||||
| l_calls.py:52 | ControlFlowNode for t | Tuple | builtin-class tuple | 41 | import |
|
||||
| l_calls.py:53 | ControlFlowNode for Attribute | Function m | builtin-class function | 48 | import |
|
||||
| l_calls.py:53 | ControlFlowNode for Attribute() | 'b' | builtin-class str | 53 | import |
|
||||
| l_calls.py:53 | ControlFlowNode for F | class F | builtin-class type | 47 | import |
|
||||
| l_calls.py:53 | ControlFlowNode for t | Tuple | builtin-class tuple | 41 | import |
|
||||
| m_attributes.py:3 | ControlFlowNode for C | class C | builtin-class type | 3 | import |
|
||||
| m_attributes.py:3 | ControlFlowNode for ClassExpr | class C | builtin-class type | 3 | import |
|
||||
| m_attributes.py:3 | ControlFlowNode for object | builtin-class object | builtin-class type | 3 | import |
|
||||
|
||||
@@ -708,6 +708,37 @@ WARNING: Predicate points_to has been deprecated and may be removed in future (P
|
||||
| l_calls.py:39 | ControlFlowNode for IntegerLiteral | int 3 | builtin-class int | 39 |
|
||||
| l_calls.py:39 | ControlFlowNode for IntegerLiteral | int 4 | builtin-class int | 39 |
|
||||
| l_calls.py:39 | ControlFlowNode for IntegerLiteral | int 5 | builtin-class int | 39 |
|
||||
| l_calls.py:41 | ControlFlowNode for Str | 'a' | builtin-class str | 41 |
|
||||
| l_calls.py:41 | ControlFlowNode for Str | 'b' | builtin-class str | 41 |
|
||||
| l_calls.py:41 | ControlFlowNode for Str | 'c' | builtin-class str | 41 |
|
||||
| l_calls.py:41 | ControlFlowNode for Tuple | Tuple | builtin-class tuple | 41 |
|
||||
| l_calls.py:41 | ControlFlowNode for t | Tuple | builtin-class tuple | 41 |
|
||||
| l_calls.py:42 | ControlFlowNode for f | Function f | builtin-class function | 29 |
|
||||
| l_calls.py:42 | ControlFlowNode for f() | args | builtin-class tuple | 29 |
|
||||
| l_calls.py:42 | ControlFlowNode for t | Tuple | builtin-class tuple | 41 |
|
||||
| l_calls.py:44 | ControlFlowNode for FunctionExpr | Function g | builtin-class function | 44 |
|
||||
| l_calls.py:44 | ControlFlowNode for g | Function g | builtin-class function | 44 |
|
||||
| l_calls.py:45 | ControlFlowNode for a | 'a' | builtin-class str | 51 |
|
||||
| l_calls.py:47 | ControlFlowNode for ClassExpr | class F | builtin-class type | 47 |
|
||||
| l_calls.py:47 | ControlFlowNode for F | class F | builtin-class type | 47 |
|
||||
| l_calls.py:47 | ControlFlowNode for object | builtin-class object | builtin-class type | 47 |
|
||||
| l_calls.py:48 | ControlFlowNode for FunctionExpr | Function m | builtin-class function | 48 |
|
||||
| l_calls.py:48 | ControlFlowNode for None | NoneType None | builtin-class NoneType | 48 |
|
||||
| l_calls.py:48 | ControlFlowNode for m | Function m | builtin-class function | 48 |
|
||||
| l_calls.py:49 | ControlFlowNode for x | 'a' | builtin-class str | 52 |
|
||||
| l_calls.py:49 | ControlFlowNode for x | 'b' | builtin-class str | 53 |
|
||||
| l_calls.py:51 | ControlFlowNode for g | Function g | builtin-class function | 44 |
|
||||
| l_calls.py:51 | ControlFlowNode for g() | 'a' | builtin-class str | 51 |
|
||||
| l_calls.py:51 | ControlFlowNode for t | Tuple | builtin-class tuple | 41 |
|
||||
| l_calls.py:52 | ControlFlowNode for Attribute | Attribute | builtin-class method | 52 |
|
||||
| l_calls.py:52 | ControlFlowNode for Attribute() | 'a' | builtin-class str | 52 |
|
||||
| l_calls.py:52 | ControlFlowNode for F | class F | builtin-class type | 47 |
|
||||
| l_calls.py:52 | ControlFlowNode for F() | F() | class F | 52 |
|
||||
| l_calls.py:52 | ControlFlowNode for t | Tuple | builtin-class tuple | 41 |
|
||||
| l_calls.py:53 | ControlFlowNode for Attribute | Function m | builtin-class function | 48 |
|
||||
| l_calls.py:53 | ControlFlowNode for Attribute() | 'b' | builtin-class str | 53 |
|
||||
| l_calls.py:53 | ControlFlowNode for F | class F | builtin-class type | 47 |
|
||||
| l_calls.py:53 | ControlFlowNode for t | Tuple | builtin-class tuple | 41 |
|
||||
| s_scopes.py:4 | ControlFlowNode for True | bool True | builtin-class bool | 4 |
|
||||
| s_scopes.py:4 | ControlFlowNode for float | bool True | builtin-class bool | 4 |
|
||||
| s_scopes.py:7 | ControlFlowNode for C2 | class C2 | builtin-class type | 7 |
|
||||
|
||||
@@ -468,6 +468,7 @@
|
||||
| l_calls.py:25 | ControlFlowNode for a | runtime | class Owner | builtin-class type |
|
||||
| l_calls.py:29 | ControlFlowNode for FunctionExpr | import | Function f | builtin-class function |
|
||||
| l_calls.py:30 | ControlFlowNode for args | code/l_calls.py:37 from import | (int 1, int 2, int 3, ) | builtin-class tuple |
|
||||
| l_calls.py:30 | ControlFlowNode for args | code/l_calls.py:42 from import | ('a', 'b', 'c', ) | builtin-class tuple |
|
||||
| l_calls.py:30 | ControlFlowNode for args | runtime | instance of tuple | builtin-class tuple |
|
||||
| l_calls.py:32 | ControlFlowNode for ClassExpr | import | class E | builtin-class type |
|
||||
| l_calls.py:32 | ControlFlowNode for object | import | builtin-class object | builtin-class type |
|
||||
@@ -498,6 +499,33 @@
|
||||
| l_calls.py:39 | ControlFlowNode for IntegerLiteral | import | int 3 | builtin-class int |
|
||||
| l_calls.py:39 | ControlFlowNode for IntegerLiteral | import | int 4 | builtin-class int |
|
||||
| l_calls.py:39 | ControlFlowNode for IntegerLiteral | import | int 5 | builtin-class int |
|
||||
| l_calls.py:41 | ControlFlowNode for Str | import | 'a' | builtin-class str |
|
||||
| l_calls.py:41 | ControlFlowNode for Str | import | 'b' | builtin-class str |
|
||||
| l_calls.py:41 | ControlFlowNode for Str | import | 'c' | builtin-class str |
|
||||
| l_calls.py:41 | ControlFlowNode for Tuple | import | ('a', 'b', 'c', ) | builtin-class tuple |
|
||||
| l_calls.py:42 | ControlFlowNode for f | import | Function f | builtin-class function |
|
||||
| l_calls.py:42 | ControlFlowNode for f() | import | ('a', 'b', 'c', ) | builtin-class tuple |
|
||||
| l_calls.py:42 | ControlFlowNode for t | import | ('a', 'b', 'c', ) | builtin-class tuple |
|
||||
| l_calls.py:44 | ControlFlowNode for FunctionExpr | import | Function g | builtin-class function |
|
||||
| l_calls.py:45 | ControlFlowNode for a | code/l_calls.py:51 from import | 'a' | builtin-class str |
|
||||
| l_calls.py:47 | ControlFlowNode for ClassExpr | import | class F | builtin-class type |
|
||||
| l_calls.py:47 | ControlFlowNode for object | import | builtin-class object | builtin-class type |
|
||||
| l_calls.py:48 | ControlFlowNode for FunctionExpr | import | Function F.m | builtin-class function |
|
||||
| l_calls.py:48 | ControlFlowNode for None | import | None | builtin-class NoneType |
|
||||
| l_calls.py:49 | ControlFlowNode for x | code/l_calls.py:52 from import | 'a' | builtin-class str |
|
||||
| l_calls.py:49 | ControlFlowNode for x | code/l_calls.py:53 from import | 'b' | builtin-class str |
|
||||
| l_calls.py:51 | ControlFlowNode for g | import | Function g | builtin-class function |
|
||||
| l_calls.py:51 | ControlFlowNode for g() | import | 'a' | builtin-class str |
|
||||
| l_calls.py:51 | ControlFlowNode for t | import | ('a', 'b', 'c', ) | builtin-class tuple |
|
||||
| l_calls.py:52 | ControlFlowNode for Attribute | import | Method(Function F.m, F()) | builtin-class method |
|
||||
| l_calls.py:52 | ControlFlowNode for Attribute() | import | 'a' | builtin-class str |
|
||||
| l_calls.py:52 | ControlFlowNode for F | import | class F | builtin-class type |
|
||||
| l_calls.py:52 | ControlFlowNode for F() | import | F() | class F |
|
||||
| l_calls.py:52 | ControlFlowNode for t | import | ('a', 'b', 'c', ) | builtin-class tuple |
|
||||
| l_calls.py:53 | ControlFlowNode for Attribute | import | Function F.m | builtin-class function |
|
||||
| l_calls.py:53 | ControlFlowNode for Attribute() | import | 'b' | builtin-class str |
|
||||
| l_calls.py:53 | ControlFlowNode for F | import | class F | builtin-class type |
|
||||
| l_calls.py:53 | ControlFlowNode for t | import | ('a', 'b', 'c', ) | builtin-class tuple |
|
||||
| m_attributes.py:3 | ControlFlowNode for ClassExpr | import | class C | builtin-class type |
|
||||
| m_attributes.py:3 | ControlFlowNode for object | import | builtin-class object | builtin-class type |
|
||||
| m_attributes.py:5 | ControlFlowNode for FunctionExpr | import | Function C.__init__ | builtin-class function |
|
||||
|
||||
@@ -37,3 +37,18 @@ class E(object):
|
||||
f(1, 2, 3)
|
||||
E().m(2, 3, 4)
|
||||
E.m(3, 4, 5)
|
||||
|
||||
t = 'a', 'b', 'c'
|
||||
f(*t)
|
||||
|
||||
def g(a, b, c):
|
||||
return a
|
||||
|
||||
class F(object):
|
||||
def m(self, x, y, z=None):
|
||||
return x
|
||||
|
||||
g(*t)
|
||||
F().m(*t)
|
||||
F.m(*t)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user