如何判断我是否将消息发送给自己?在AST(clang,objective c)

时间:2018-03-10 12:44:17

标签: objective-c clang abstract-syntax-tree

假设我正在遍历抽象语法树并遇到方法调用 [self.view backgroundColor] = UIColor.redColor;

如何判断我是否向self或其他某个对象发送消息(可能是超类,某些属性,无关紧要)。

我找到了一种方法,根据其名称,将一个接收器返回给消息。

Expr * getInstanceReceiver ()它返回实例消息的对象表达式(接收者),或者对于不是实例消息的消息返回null。

现在从这个Expr *我​​需要了解它是否是自我。 有没有人有任何想法如何?

1 个答案:

答案 0 :(得分:0)

在文件中提供这个简单的程序" main.m":

--server.password "your-password-goes-here"

您可以使用以下命令打印出AST:

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

所以"自我"是"你好"的隐含的第一个参数。方法,它在方法调用中被解析为 DeclRefExpr - ObjCMessageExpr,但也包含在ImplicitCastExpr中。

对于属性访问,它看起来不同。 "模型"的AST部分;内部的财产访问" whoAmI"函数包含在 PseudoObjectExpr

| |-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"

对于&#34; self&#34;你也有相同的 DeclRefExpr 。这里包含在ObjCMessageExpr(或ObjCPropertyRefExpr)中,但现在还有一层额外的包装--OpaqueValueExpr。

对于&#34; setModelTest&#34;中的属性设置器调用方法更加复杂:

`-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 *'

最后一个ObjCMessageExpr的结构类似于getter case。

似乎如果你遍历树并找到所有引用名为self的ImplicitParam(ImplicitParamDecl)的 DeclRefExpr 节点,你就会发现&#34; self&#34的所有出现;