c++ - libclang clang_getSpellingLocation 访问冲突

标签 c++ clang c++builder libclang

我正在尝试开始有关 libclang 库的教程,但在调用函数 clang_getSpellingLocation() 时出现访问冲突。正确报告有关错误的其他信息,包括错误计数、行和列。

我的环境:C++Builder XE pro, Windows 7 32bit, LLVM 3.4, libCLang.lib 转换 使用 coff2omf、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);
  }
}

最佳答案

您确定 AV 在 clang_getSpellingLocation() 而不是 clang_getDiagnosticSpelling() 上吗?

当使用 __cdecl 调用约定时,当结构的大小为 <= 8 字节时,不同供应商的编译器可以在按值返回结构时做任何他们想做的事情。对于 clang_getDiagnosticSpelling()CXString 在 32 位环境中是 8 个字节。一些编译器,如 Visual C++,直接在 EAX:EDX CPU 寄存器中返回一个 8 字节结构的内容,而其他编译器,如 C++Builder,使用一个隐藏的输出参数传递一个对临时结构的引用。

clang_getDiagnosticSpelling()(和其他类似函数)使用 EAX:EDX 返回一个 CXString,但 C++Builder 使用隐藏参数反而。有一个简单的解决方法。 C++Builder 期望一个 __cdecl 函数使用 EAX:EDX 返回一个 __int64,因为 CXString__int64在32bit中大小相同,可以这样:

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;

至于 clang_getSpellingLocation(),我不认为约定会出现这样的不匹配,因为它没有返回值,除非 clang_getSpellingLocation() 被编译为接受它的 CXSourceLocation 参数与 C++Builder 传递它的方式不同。 C++Builder 将 CXSourceLocation 中的所有三个数据值直接推送到调用堆栈上。您必须查看 clang_getSpellingLocation() 的反汇编,以了解它实际上如何访问其 CXSourceLocation 参数的值,然后相应地调整您的 C++Builder 代码如果需要的话。

您还应该仔细检查 clang_getDiagnosticLocation() 返回其 CXSourceLocation 的方式,以确保它符合 C++Builder 期望返回的方式(通过通过引用隐藏输出参数)以确保在调用 clang_getSpellingLocation() 之前内存不会被破坏。因此,clang_getSpellingLocation() 本身可能不是罪魁祸首。很难说没有看到 clang_getDiagnosticLocation()clang_getSpellingLocation() 的反汇编(我已经看到返回 CXString 的函数的反汇编,那这就是我确定 clang 使用 EAX:EDX 的方式。

关于c++ - libclang clang_getSpellingLocation 访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22113717/

相关文章:

c++ - 在 C++ 迭代器问题中使用带有一对的映射作为键

c++ - 合并一个 vc++ 和一个 c++ 构建器项目

c++ - 如何从 char 数组中删除前 4 个字符

c++ - 如何制作一个 set<string> 支持通过 C 字符串进行查找,而无需 std::string 中介?

python - 获取 lib clang 游标/类型的实际拼写

c++ - 如何仅为源代码的特定部分打开 -mavx2?

c++ - Direct2D 仅在 C++ Builder 中部分链接

delphi - 如何确定给定字体的行间距(以像素为单位)(对于 TVirtualTreeView)

c++ - GD32VF103 龙眼纳米中断不起作用

iphone - CLANG 给出错误,提示头文件有缺陷 UILocalizedIndexedCollat​​ion.h