我正在尝试启动有关libclang库的教程,但在调用函数clang_getSpellingLocation()
时出现访问冲突。正确报告有关错误的其他信息,包括错误计数,行和列。
我的环境:C ++ Builder XE pro,Windows 7 32位,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);
}
}
答案 0 :(得分:2)
您确定AV是clang_getSpellingLocation()
而不是clang_getDiagnosticSpelling()
吗?
当使用__cdecl
调用约定时,允许来自不同供应商的编译器在结构的大小为&lt; = 8字节时按值返回结构时做任何他们想做的事情。在clang_getDiagnosticSpelling()
的情况下,CXString
在32位环境中是8个字节。某些编译器(如Visual C ++)直接在EAX:EDX
CPU寄存器中返回8字节结构的内容,而其他编译器(如C ++ Builder)使用隐藏的输出参数将参考传递给临时结构
clang_getDiagnosticSpelling()
(以及其他类似函数)使用CXString
返回EAX:EDX
,但C ++ Builder使用隐藏参数。有一个简单的解决方法。 C ++ Builder期望__cdecl
函数使用__int64
返回EAX:EDX
,并且由于CXString
和__int64
在32位中的大小相同,您可以执行以下内容:
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使用{{1}的方式为了那个)。