如何通过clang-3.9获得objective-c的Return Stmt?

时间:2016-07-07 09:06:45

标签: objective-c macos clang llvm static-analysis

我现在是通过clang对objective-c进行静态分析的新手。 我遇到一个问题,当我通过RecursiveASTVisitor找到ReturnStmt时,clang有时无法找到ReturnStmt。 RecursiveASTVisitor代码如下:

    class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor> {
public:
    MyASTVisitor(Rewriter &R) : TheRewriter(R) {}
    .........
        else if(isa<ReturnStmt>(s)){
            //The Return Stmt find block
            ReturnStmt *returnStat = cast<ReturnStmt>(s);
            TheRewriter.InsertText(returnStat->getLocStart(),"//the return stmt\n",true,true); 
        }
        return true;
    }}

这就是结果 第一个结果可以找到return stmt

int main (int argc, const char* argv[])  {  
@autoreleasepool {  
    //the func--->NSLog() begin called!
    NSLog (@"Programming is fun!");  
}  
//the return stmt
return 0; }

但第二个找不到它

int main(int argc, char * argv[]) {
@autoreleasepool {
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}}

1 个答案:

答案 0 :(得分:0)

让我解释一下clang AST如何使用一个小例子。假设此代码存在于temp.cpp

int b()
{
    return 0;
}

int main()
{
    return b();
}

现在让我们看看上面代码的clang的AST表示是什么:(顺便说一句,这是你可以在任何时候看到你的代码不应该做它应该做的事情。看看原始的AST看看是什么是错的。要从clang获取原始AST转储,我们将运行它。

clang -Xclang -ast-dump -fsyntax-only temp.cpp 

这给了我们这个输出:

|-FunctionDecl 0x5f952e0 <t.cpp:2:1, line:5:1> line:2:5 used b 'int (void)'
| `-CompoundStmt 0x5f95400 <line:3:1, line:5:1>
|   `-ReturnStmt 0x5f953e8 <line:4:2, col:9>
|     `-IntegerLiteral 0x5f953c8 <col:9> 'int' 0
`-FunctionDecl 0x5f95440 <line:7:1, line:10:1> line:7:5 main 'int (void)'
  `-CompoundStmt 0x5f95620 <line:8:1, line:10:1>
    `-ReturnStmt 0x5f95608 <line:9:2, col:11>
      `-CallExpr 0x5f955e0 <col:9, col:11> 'int'
        `-ImplicitCastExpr 0x5f955c8 <col:9> 'int (*)(void)' <FunctionToPointerDecay>
          `-DeclRefExpr 0x5f95570 <col:9> 'int (void)' lvalue Function 0x5f952e0 'b' 'int (void)'

如果你看一下函数b的第一个FunctionDecl,它是一个返回整数值0的简单return语句。但是,现在如果你看一下main的FunctionDecl,你可以看到returnStmt调用CallExpr然后得到返回来自功能b。这正是您的案例中发生的事情。一个返回语句被检测到,一个不被检测到。

在这种情况下,您可以执行ReturnStmt的{​​{3}}调用,它会为您提供Expr类型,您需要针对不同的可能返回案例解决这个问题。