2013-03-11 75 views
4

我目前正在用C++编写一个使用libclang的简单克隆检测器。C++ libclang:从CXSourceLocation检索游标返回错误的游标?

程序使用结构存储游标,包含指向翻译单元的指针和从调用clang_getCursorLocation(游标)获得的CXSourceLocation。

typedef struct { 
    CXTranslationUnit* tu; 
    CXSourceLocation srcLoc; 
} t_cursorLocation; 

为了这个错误,子访问者函数访问每个节点并从每个游标创建一个结构体。随着类型t_cursorLocation的结构,我写了这个函数来获取相应的光标:

CXCursor getCursor(t_cursorLocation *loc1) { 
    return clang_getCursor(*loc1->tu, loc1->srcLoc); 
} 

然而,一些光标,当我创建了t_cursorLocation结构,并用它来检索从中创建光标时,检索到的游标不等于它所源自的游标。作为一个例子,看到孩子访客功能:

CXChildVisitResult traverseAST(CXCursor cursor, CXCursor parent, 
               CXClientData client_data) { 
    CXTranslationUnit tu = clang_Cursor_getTranslationUnit(cursor); 
    CXTranslationUnit tu2 = *((CXTranslationUnit *) client_data); 

    t_cursorLocation *loc = new t_cursorLocation(); 
    loc->tu = &tu; 
    loc->srcLoc = clang_getCursorLocation(cursor); 

    CXCursor c2 = getCursor(loc); 
    printf("CursorKind\t%s\n", 
      clang_getCString(clang_getCursorKindSpelling(cursor.kind))); 
    if (clang_equalCursors(cursor, c2)) { 
     printf("Noooo - the cursors do not match! Next test....."); 
     // use translation unit passed as client_data to see if 
     // there's a difference 
     loc->tu = &tu2; 
     c2 = getCursor(loc); 
     if (clang_equalCursors(cursor, c2)) { 
      printf("FAILED ALSO!\n"); 
     } else { 
      printf("PASSED???\n"); 
     } 
    } else { 
     printf("We have a match!\n"); 
    } 
    return CXChildVisit_Recurse; 
} 

我的主要功能如下:

int main(int argc, char **argv) { 
    CXIndex index = clang_createIndex(0, 0); 
    // initialise the translation unit 
    CXTranslationUnit tu = clang_parseTranslationUnit(index, 0, 
     argv, argc, 0, 0, CXTranslationUnit_None); 

    // set the client data in traverseAST 
    CXClientData data = &tu;// NULL; 
    // get the root cursor for the translation unit 
    CXCursor rootCursor = clang_getTranslationUnitCursor(tu); 
    clang_visitChildren(rootCursor, traverseAST, data); 

    clang_disposeTranslationUnit(tu); 
    clang_disposeIndex(index); 

    return 0; 
} 

我跑这在伪源代码如下:

void goo() { 
    // nothing here 
} 

void foo() { 
    // do something 
    int a; 
    switch (a) { 
     case 0: 
      goo(); 
    }; 
} 

但是输出是一致的,这表明这只在某些游标类型中才会发生。

这是一个错误还是有东西我失踪或做错了?

由于提前, 雅各

回答

2

要么我失去了你的观点完全,或者您正在使用clang_equalCursors错误的方式:当两个光标是平等的,clang_equalCursors返回一个非零值。这意味着我认为你正在测试游标不等式而不是平等。

现在,让我试着解释为什么某些游标显然表现出与其他游戏不同的行为。每个游标只有一个源位置。但是,在同一个源位置可能会有多个游标。认为例如约下面的行:

CXIndex index = clang_createIndex(0, 0); 
// ^

应该有至少两个光标在上述标记的位置:

  1. VarDecl:index
  2. DeclRefExpr:index = clang_createIndex(0,0)

当您将源位置转换回光标,clang_getCursor给出了最具体的一个(t中的变量声明他的情况)。我怀疑这是你在这种情况下发生的事情:getCursor(loc)只会返回你访问的游标,如果它是最具体的位置。

尝试打印每个光标的物理源位置(例如使用clang_getCursorExtentclang_getExpansionLocation)以了解发生了什么。

+0

嗨弗朗切斯科。感谢您的快速响应和澄清!这是一个很好的帮助 – 2013-03-12 18:05:51

+0

没问题。还有一件事:你不应该忘记使用'clang_disposeString'释放'CXString'分配的内存 – Francesco 2013-03-12 18:30:50