0

libclang ライブラリに関するチュートリアルを開始しようとしていますが、関数を呼び出すとアクセス違反が発生しますclang_getSpellingLocation()。エラーに関するその他の情報は、エラー数、行、および列で正しく報告されます。

私の環境:C++Builder XE pro、Windows 7 32bit、LLVM 3.4、coff2omfで変換したlibCLang.lib、libCLang.dll。

Visual C++ 2010 で同じコードをテストしたところ、正しく動作しました。

この問題について誰か助けてくれませんか?

私の簡単なコード

//---------------------------------------------------------------------------
void __fastcall TForm8::Button1Click(TObject *Sender)
{

    unsigned line, column;
    CXIndex index = clang_createIndex(0, 0);

    const  char  * args []  =  {
    "-I/usr/include" ,
    "-I."
    };

    int  numArgs  =  sizeof ( args )  /  sizeof ( * args );

  CXTranslationUnit tu = clang_parseTranslationUnit(index, "G:\\projects\\LibCLang  \\File2.cpp", args, numArgs, NULL, 0, CXTranslationUnit_None);

  unsigned  diagnosticCount  =  clang_getNumDiagnostics ( tu );

  for ( unsigned  i  =  0 ;  i  <  diagnosticCount ;  i++ )
  {
      CXDiagnostic  diagnostic   =  clang_getDiagnostic ( tu ,  i );
      CXSourceLocation location = clang_getDiagnosticLocation(diagnostic);
      clang_getSpellingLocation(location, NULL, &line, &column, NULL);
      CXString text = clang_getDiagnosticSpelling(diagnostic);
      UnicodeString s = clang_getCString(text);
  }
}
4

1 に答える 1

2

AVがオンになっていてclang_getSpellingLocation()、そうでないのは確かclang_getDiagnosticSpelling()ですか?

呼び出し規約を使用する__cdecl場合、構造体のサイズが 8 バイト以下の場合に値によって構造体を返す場合、さまざまなベンダーのコンパイラーが好きなことを行うことができます。の場合clang_getDiagnosticSpelling()CXString32bit環境で8バイトです。Visual C++ などの一部のコンパイラは、8 バイト構造体の内容をEAX:EDXCPU レジスタに直接返しますが、C++Builder などの他のコンパイラは、一時構造体への参照を渡す非表示の出力パラメーターを使用します。

clang_getDiagnosticSpelling()(および他の同様の関数) はCXStringusing を返しEAX:EDXますが、C++Builder は代わりに隠しパラメーターを使用します。そのための簡単な回避策があります。C++Builder は、関数がusingを__cdecl返すことを想定しています。とは 32 ビットで同じサイズであるため、次のことができます。__int64EAX:EDXCXString__int64

typedef __int64 __cdecl (*clang_getDiagnosticSpellingHack)(CXDiagnostic);

//CXString text = clang_getDiagnosticSpelling(diagnostic);
clang_getDiagnosticSpellingHack func = reinterpret_cast<clang_getDiagnosticSpellingHack>(&clang_getDiagnosticSpelling);
__int64 tmp = func(diagnostic);
CXString text = reinterpret_cast<CXString&>(tmp);

または、C++Builder_EAX_EDX組み込み関数を利用できます。

typedef void __cdecl (*clang_getDiagnosticSpellingHack)(CXDiagnostic);

//CXString text = clang_getDiagnosticSpelling(diagnostic);
clang_getDiagnosticSpellingHack func = reinterpret_cast<clang_getDiagnosticSpellingHack>(&clang_getDiagnosticSpelling);
CXString text;
func(diagnostic);
text.ptr_data = (void*) _EAX;
text.int_data = _EDX;

については、 C++Builder がパラメーターを渡す方法とは異なる方法でパラメーターを受け入れるようにコンパイルされていclang_getSpellingLocation()ない限り、戻り値がないため、規則にこのような不一致があるとは思いません。C++Builder は、3 つのデータ値すべてをコール スタックから直接プッシュします。の逆アセンブリを調べて、実際にパラメータの値にアクセスする方法を確認し、必要に応じて C++Builder コードを調整する必要があります。clang_getSpellingLocation()CXSourceLocationCXSourceLocationclang_getSpellingLocation()CXSourceLocation

また、 がどのようにそれをclang_getDiagnosticLocation()返すかを再CXSourceLocation確認して、C++Builder がそれを返す方法と一致することを確認する必要があります (参照による非表示の出力パラメーターを介して) clang_getSpellingLocation()。したがって、clang_getSpellingLocation()それ自体が原因ではない可能性があります。clang_getDiagnosticLocation()との両方の逆アセンブリを見ずに言うのは難しいです(私clang_getSpellingLocation()は を返す関数の逆アセンブリを見てきました。CXStringEAX:EDX

于 2014-03-07T22:43:20.560 に答える