Are you sure the AV is on clang_getSpellingLocation()
and not clang_getDiagnosticSpelling()
?
When using the __cdecl
calling convention, compilers from different vendors are allowed to do whatever they want when it comes to returning a structure by value when the size of the structure is <= 8 bytes. In the case of clang_getDiagnosticSpelling()
, CXString
is 8 bytes in a 32bit environment. Some compilers, like Visual C++, return the contents of an 8-byte structure directly in the EAX:EDX
CPU registers, whereas other compilers, like C++Builder, use a hidden output parameter that passes a reference to a temp structure.
clang_getDiagnosticSpelling()
(and other similar functions) return a CXString
using EAX:EDX
, but C++Builder uses a hidden parameter instead. There is a simple workaround for that. C++Builder expects a __cdecl
function to return an __int64
using EAX:EDX
, and since CXString
and __int64
are the same size in 32bit, you can do the following:
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);
Alternatively, you can utilize C++Builder's _EAX
and _EDX
intrinsics:
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;
As for clang_getSpellingLocation()
, I would not expect there to be such a mismatch in conventions since it has no return value, unless clang_getSpellingLocation()
were compiled to accept its CXSourceLocation
parameter differently than how C++Builder is passing it. C++Builder pushes all three data values from CXSourceLocation
directly on the call stack. You would have to look at the disassembly of clang_getSpellingLocation()
to see how it is actually accessing the values of its CXSourceLocation
parameter, and then adjust your C++Builder code accordingly if needed.
You should also double-check how clang_getDiagnosticLocation()
is returning its CXSourceLocation
to make sure that it matches how C++Builder expects it to be returned (via a hidden output parameter by reference) to ensure that memory is not being corrupted before clang_getSpellingLocation()
is being called. So it is possible that clang_getSpellingLocation()
itself might not be the culprit. Hard to say without seeing the disassembly for both clang_getDiagnosticLocation()
and clang_getSpellingLocation()
(I have seen the disassembly for functions that return CXString
, that is how I know for sure that clang uses EAX:EDX
for that).