首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >libclang clang_getSpellingLocation访问冲突

libclang clang_getSpellingLocation访问冲突
EN

Stack Overflow用户
提问于 2014-03-01 11:23:59
回答 1查看 359关注 0票数 0

我试图开始一个关于libclang库的教程,但是在调用函数clang_getSpellingLocation()时,我会遇到访问冲突。有关此错误的其他信息通过错误计数、行和列正确地报告。

我的环境: C++Builder XE,Windows732bit,LLVM3.4,libCLang.lib转换使用coff2omf,libCLang.dll。

我在visual C++ 2010上测试了相同的代码,它工作正常。

在这个问题上你能帮我一个人吗?

我的简单代码

代码语言:javascript
复制
//---------------------------------------------------------------------------
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);
  }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-07 22:43:20

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

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

clang_getDiagnosticSpelling() (和其他类似函数)使用EAX:EDX返回CXString,但C++Builder使用隐藏参数。有一个简单的解决办法。C++Builder期望一个__cdecl函数使用EAX:EDX返回一个__int64,而且由于CXString__int64在32位中大小相同,所以可以执行以下操作:

代码语言:javascript
复制
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的本质:

代码语言:javascript
复制
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 )。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22113717

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档