如何确定我是否将消息发送给自己?在 AST 中(clang,objective c)
How to figure out if I'm the message is sent to self? in AST (clang, objective c)
假设我正在遍历抽象语法树并遇到方法调用
[self.view backgroundColor] = UIColor.redColor;
我如何确定我是在向 self
还是向其他对象发送消息(它可能超 class、一些 属性,无关紧要) .
我找到了一个方法,根据它的名字,return一个消息的接收者。
Expr * getInstanceReceiver ()
它return是实例消息的对象表达式(接收者),或者对于非实例消息的消息为空。
现在从这个 Expr* 我需要了解它是否是 self。
有人知道怎么做吗?
给定文件中的这个简单程序 "main.m":
int puts(const char *);
__attribute__((objc_root_class))
@interface Robot
@property char *model;
@end
@implementation Robot
- (void)say:(char *)x {
puts(x);
}
- (void)hello {
[self say:"hello"];
}
- (char *)model {
return "49209192";
}
- (void)whoAmI {
puts(self.model);
}
- (void)setModel:(char *)model {
puts("setModel test");
}
- (void)setModelTest {
self.model = "123";
}
@end
int main() {
return 0;
}
您可以使用以下命令打印出 AST:
clang -cc1 -ast-dump main.m
然后看到 "hello" 方法 AST 看起来像这样:
| |-ObjCMethodDecl 0x7fe1c905bdb0 <line:21:1, line:23:1> line:21:1 - hello 'void'
| | |-ImplicitParamDecl 0x7fe1c90806e8 <<invalid sloc>> <invalid sloc> implicit used self 'Robot *'
| | |-ImplicitParamDecl 0x7fe1c9080748 <<invalid sloc>> <invalid sloc> implicit _cmd 'SEL':'SEL *'
| | `-CompoundStmt 0x7fe1c90808a0 <col:15, line:23:1>
| | `-ObjCMessageExpr 0x7fe1c9080868 <line:22:5, col:22> 'void' selector=say:
| | |-ImplicitCastExpr 0x7fe1c9080838 <col:6> 'Robot *' <LValueToRValue>
| | | `-DeclRefExpr 0x7fe1c90807a8 <col:6> 'Robot *' lvalue ImplicitParam 0x7fe1c90806e8 'self' 'Robot *'
| | `-ImplicitCastExpr 0x7fe1c9080850 <col:15> 'char *' <ArrayToPointerDecay>
| | `-StringLiteral 0x7fe1c9080808 <col:15> 'char [6]' lvalue "hello"
所以 "self" 是 "hello" 方法的隐式第一个参数,它在方法调用 - ObjCMessageExpr 中被解析为 DeclRefExpr,但是也包含在 ImplicitCastExpr 中。
对于 属性 访问,它看起来不同。 "model" 属性 函数内部 "whoAmI" 访问的 AST 部分包含在 PseudoObjectExpr:
中
`-PseudoObjectExpr 0x7fe844080640 <col:10, col:15> 'char *'
|-ObjCPropertyRefExpr 0x7fe8440805e0 <col:10, col:15> '<pseudo-object type>' lvalue objcproperty Kind=PropertyRef Property="model" Messaging=Getter
| `-OpaqueValueExpr 0x7fe8440805c0 <col:10> 'Robot *'
| `-ImplicitCastExpr 0x7fe844080578 <col:10> 'Robot *' <LValueToRValue>
| `-DeclRefExpr 0x7fe844080550 <col:10> 'Robot *' lvalue ImplicitParam 0x7fe844080468 'self' 'Robot *'
|-OpaqueValueExpr 0x7fe8440805c0 <col:10> 'Robot *'
| `-ImplicitCastExpr 0x7fe844080578 <col:10> 'Robot *' <LValueToRValue>
| `-DeclRefExpr 0x7fe844080550 <col:10> 'Robot *' lvalue ImplicitParam 0x7fe844080468 'self' 'Robot *'
`-ObjCMessageExpr 0x7fe844080610 <col:15> 'char *' selector=model
`-OpaqueValueExpr 0x7fe8440805c0 <col:10> 'Robot *'
`-ImplicitCastExpr 0x7fe844080578 <col:10> 'Robot *' <LValueToRValue>
`-DeclRefExpr 0x7fe844080550 <col:10> 'Robot *' lvalue ImplicitParam 0x7fe844080468 'self' 'Robot *'
您也有相同的 DeclRefExpr for "self" 在这里包装在 ObjCMessageExpr(或 ObjCPropertyRefExpr)中,但现在有一个额外的包装层 - OpaqueValueExpr。
对于 属性 setter 在 "setModelTest" 方法中的调用,它更加复杂:
`-PseudoObjectExpr 0x7fe844080b80 <line:27:5, col:18> 'char *'
|-BinaryOperator 0x7fe844080ae8 <col:5, col:18> 'char [4]' lvalue '='
| |-ObjCPropertyRefExpr 0x7fe844080a98 <col:5, col:10> '<pseudo-object type>' lvalue objcproperty Kind=PropertyRef Property="model" Messaging=Setter
| | `-OpaqueValueExpr 0x7fe844080a78 <col:5> 'Robot *'
| | `-ImplicitCastExpr 0x7fe8440809c0 <col:5> 'Robot *' <LValueToRValue>
| | `-DeclRefExpr 0x7fe844080998 <col:5> 'Robot *' lvalue ImplicitParam 0x7fe8440808d8 'self' 'Robot *'
| `-OpaqueValueExpr 0x7fe844080ac8 <col:18> 'char [4]' lvalue
| `-StringLiteral 0x7fe844080a48 <col:18> 'char [4]' lvalue "123"
|-OpaqueValueExpr 0x7fe844080a78 <col:5> 'Robot *'
| `-ImplicitCastExpr 0x7fe8440809c0 <col:5> 'Robot *' <LValueToRValue>
| `-DeclRefExpr 0x7fe844080998 <col:5> 'Robot *' lvalue ImplicitParam 0x7fe8440808d8 'self' 'Robot *'
|-OpaqueValueExpr 0x7fe844080ac8 <col:18> 'char [4]' lvalue
| `-StringLiteral 0x7fe844080a48 <col:18> 'char [4]' lvalue "123"
|-OpaqueValueExpr 0x7fe844080b60 <col:18> 'char *'
| `-ImplicitCastExpr 0x7fe844080b10 <col:18> 'char *' <ArrayToPointerDecay>
| `-OpaqueValueExpr 0x7fe844080ac8 <col:18> 'char [4]' lvalue
| `-StringLiteral 0x7fe844080a48 <col:18> 'char [4]' lvalue "123"
`-ObjCMessageExpr 0x7fe844080b28 <col:10> 'void' selector=setModel:
|-OpaqueValueExpr 0x7fe844080a78 <col:5> 'Robot *'
| `-ImplicitCastExpr 0x7fe8440809c0 <col:5> 'Robot *' <LValueToRValue>
| `-DeclRefExpr 0x7fe844080998 <col:5> 'Robot *' lvalue ImplicitParam 0x7fe8440808d8 'self' 'Robot *'
`-OpaqueValueExpr 0x7fe844080b60 <col:18> 'char *'
`-ImplicitCastExpr 0x7fe844080b10 <col:18> 'char *' <ArrayToPointerDecay>
`-OpaqueValueExpr 0x7fe844080ac8 <col:18> 'char [4]' lvalue
`-StringLiteral 0x7fe844080a48 <col:18> 'char [4]' lvalue "123"
最后一个ObjCMessageExpr的结构与getter情况类似。
似乎如果你遍历树并找到所有引用名为 self 的 ImplicitParam (ImplicitParamDecl) 的 DeclRefExpr 节点,你会发现所有出现的 "self".
假设我正在遍历抽象语法树并遇到方法调用
[self.view backgroundColor] = UIColor.redColor;
我如何确定我是在向 self
还是向其他对象发送消息(它可能超 class、一些 属性,无关紧要) .
我找到了一个方法,根据它的名字,return一个消息的接收者。
Expr * getInstanceReceiver ()
它return是实例消息的对象表达式(接收者),或者对于非实例消息的消息为空。
现在从这个 Expr* 我需要了解它是否是 self。 有人知道怎么做吗?
给定文件中的这个简单程序 "main.m":
int puts(const char *);
__attribute__((objc_root_class))
@interface Robot
@property char *model;
@end
@implementation Robot
- (void)say:(char *)x {
puts(x);
}
- (void)hello {
[self say:"hello"];
}
- (char *)model {
return "49209192";
}
- (void)whoAmI {
puts(self.model);
}
- (void)setModel:(char *)model {
puts("setModel test");
}
- (void)setModelTest {
self.model = "123";
}
@end
int main() {
return 0;
}
您可以使用以下命令打印出 AST:
clang -cc1 -ast-dump main.m
然后看到 "hello" 方法 AST 看起来像这样:
| |-ObjCMethodDecl 0x7fe1c905bdb0 <line:21:1, line:23:1> line:21:1 - hello 'void'
| | |-ImplicitParamDecl 0x7fe1c90806e8 <<invalid sloc>> <invalid sloc> implicit used self 'Robot *'
| | |-ImplicitParamDecl 0x7fe1c9080748 <<invalid sloc>> <invalid sloc> implicit _cmd 'SEL':'SEL *'
| | `-CompoundStmt 0x7fe1c90808a0 <col:15, line:23:1>
| | `-ObjCMessageExpr 0x7fe1c9080868 <line:22:5, col:22> 'void' selector=say:
| | |-ImplicitCastExpr 0x7fe1c9080838 <col:6> 'Robot *' <LValueToRValue>
| | | `-DeclRefExpr 0x7fe1c90807a8 <col:6> 'Robot *' lvalue ImplicitParam 0x7fe1c90806e8 'self' 'Robot *'
| | `-ImplicitCastExpr 0x7fe1c9080850 <col:15> 'char *' <ArrayToPointerDecay>
| | `-StringLiteral 0x7fe1c9080808 <col:15> 'char [6]' lvalue "hello"
所以 "self" 是 "hello" 方法的隐式第一个参数,它在方法调用 - ObjCMessageExpr 中被解析为 DeclRefExpr,但是也包含在 ImplicitCastExpr 中。
对于 属性 访问,它看起来不同。 "model" 属性 函数内部 "whoAmI" 访问的 AST 部分包含在 PseudoObjectExpr:
中`-PseudoObjectExpr 0x7fe844080640 <col:10, col:15> 'char *'
|-ObjCPropertyRefExpr 0x7fe8440805e0 <col:10, col:15> '<pseudo-object type>' lvalue objcproperty Kind=PropertyRef Property="model" Messaging=Getter
| `-OpaqueValueExpr 0x7fe8440805c0 <col:10> 'Robot *'
| `-ImplicitCastExpr 0x7fe844080578 <col:10> 'Robot *' <LValueToRValue>
| `-DeclRefExpr 0x7fe844080550 <col:10> 'Robot *' lvalue ImplicitParam 0x7fe844080468 'self' 'Robot *'
|-OpaqueValueExpr 0x7fe8440805c0 <col:10> 'Robot *'
| `-ImplicitCastExpr 0x7fe844080578 <col:10> 'Robot *' <LValueToRValue>
| `-DeclRefExpr 0x7fe844080550 <col:10> 'Robot *' lvalue ImplicitParam 0x7fe844080468 'self' 'Robot *'
`-ObjCMessageExpr 0x7fe844080610 <col:15> 'char *' selector=model
`-OpaqueValueExpr 0x7fe8440805c0 <col:10> 'Robot *'
`-ImplicitCastExpr 0x7fe844080578 <col:10> 'Robot *' <LValueToRValue>
`-DeclRefExpr 0x7fe844080550 <col:10> 'Robot *' lvalue ImplicitParam 0x7fe844080468 'self' 'Robot *'
您也有相同的 DeclRefExpr for "self" 在这里包装在 ObjCMessageExpr(或 ObjCPropertyRefExpr)中,但现在有一个额外的包装层 - OpaqueValueExpr。
对于 属性 setter 在 "setModelTest" 方法中的调用,它更加复杂:
`-PseudoObjectExpr 0x7fe844080b80 <line:27:5, col:18> 'char *'
|-BinaryOperator 0x7fe844080ae8 <col:5, col:18> 'char [4]' lvalue '='
| |-ObjCPropertyRefExpr 0x7fe844080a98 <col:5, col:10> '<pseudo-object type>' lvalue objcproperty Kind=PropertyRef Property="model" Messaging=Setter
| | `-OpaqueValueExpr 0x7fe844080a78 <col:5> 'Robot *'
| | `-ImplicitCastExpr 0x7fe8440809c0 <col:5> 'Robot *' <LValueToRValue>
| | `-DeclRefExpr 0x7fe844080998 <col:5> 'Robot *' lvalue ImplicitParam 0x7fe8440808d8 'self' 'Robot *'
| `-OpaqueValueExpr 0x7fe844080ac8 <col:18> 'char [4]' lvalue
| `-StringLiteral 0x7fe844080a48 <col:18> 'char [4]' lvalue "123"
|-OpaqueValueExpr 0x7fe844080a78 <col:5> 'Robot *'
| `-ImplicitCastExpr 0x7fe8440809c0 <col:5> 'Robot *' <LValueToRValue>
| `-DeclRefExpr 0x7fe844080998 <col:5> 'Robot *' lvalue ImplicitParam 0x7fe8440808d8 'self' 'Robot *'
|-OpaqueValueExpr 0x7fe844080ac8 <col:18> 'char [4]' lvalue
| `-StringLiteral 0x7fe844080a48 <col:18> 'char [4]' lvalue "123"
|-OpaqueValueExpr 0x7fe844080b60 <col:18> 'char *'
| `-ImplicitCastExpr 0x7fe844080b10 <col:18> 'char *' <ArrayToPointerDecay>
| `-OpaqueValueExpr 0x7fe844080ac8 <col:18> 'char [4]' lvalue
| `-StringLiteral 0x7fe844080a48 <col:18> 'char [4]' lvalue "123"
`-ObjCMessageExpr 0x7fe844080b28 <col:10> 'void' selector=setModel:
|-OpaqueValueExpr 0x7fe844080a78 <col:5> 'Robot *'
| `-ImplicitCastExpr 0x7fe8440809c0 <col:5> 'Robot *' <LValueToRValue>
| `-DeclRefExpr 0x7fe844080998 <col:5> 'Robot *' lvalue ImplicitParam 0x7fe8440808d8 'self' 'Robot *'
`-OpaqueValueExpr 0x7fe844080b60 <col:18> 'char *'
`-ImplicitCastExpr 0x7fe844080b10 <col:18> 'char *' <ArrayToPointerDecay>
`-OpaqueValueExpr 0x7fe844080ac8 <col:18> 'char [4]' lvalue
`-StringLiteral 0x7fe844080a48 <col:18> 'char [4]' lvalue "123"
最后一个ObjCMessageExpr的结构与getter情况类似。
似乎如果你遍历树并找到所有引用名为 self 的 ImplicitParam (ImplicitParamDecl) 的 DeclRefExpr 节点,你会发现所有出现的 "self".