4

私は現在、C++ で libclang を使用して単純なクローン検出器を作成しています。

このプログラムは、構造体を使用してカーソルを格納します。この構造体には、翻訳単位へのポインターと、clang_getCursorLocation(cursor) の呼び出しから取得した 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();
    };
}

ただし、出力は一貫しており、これは特定のカーソルの種類でのみ発生することを示唆しています。

これはバグですか、それとも私が見逃している、または間違っていることがありますか?

前もって感謝します、ジェイコブ

4

1 に答える 1

2

私はあなたの要点を完全に見逃しているかclang_equalCursors、間違った方法を使用しています:両方のカーソルが等しい場合、clang_equalCursorsゼロ以外の値を返します。つまり、等式ではなくカーソルの不等式をテストしていると思います。

ここで、特定のカーソルが他のカーソルとは明らかに異なる動作をする理由を説明してみましょう。各カーソルのソース位置は 1 つだけです。ただし、同じソース位置に複数のカーソルがある場合があります。たとえば、次の行について考えてみます。

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

上記のマークされた位置に少なくとも 2 つのカーソルがあるはずです。

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

ソースの場所をカーソルに戻すとclang_getCursor、最も具体的な場所 (この場合は変数宣言) が返されます。この場合、これがあなたに起こることだとgetCursor(loc)思います。その場所で最も具体的な場合にのみ、アクセスしているカーソルを返します。

何が起こるかを理解するために、各カーソルの物理的なソースの場所を出力してみてください (たとえば、clang_getCursorExtentおよびclang_getExpansionLocationを使用)。

于 2013-03-11T20:12:58.303 に答える