如何确定我是否将消息发送给自己?在 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".