This program
{$APPTYPE CONSOLE}
{$TYPEDADDRESS ON}
uses
Winapi.Windows;
procedure Foo(P: PDWORD);
begin
end;
procedure Bar;
var
dw: DWORD;
begin
Foo(@dw);
end;
begin
end.
compiles in XE3, but does not in XE4, XE5, XE6 and XE7. The error is at
Foo(@dw);
[dcc32 Error] E2010 Incompatible types: 'PDWORD' and 'Pointer'
This feels odd. So, after a bit of digging it seems that the issue is down to the definition of PDWORD
. One might naturally think that it would be:
PDWORD = ^DWORD;
and indeed that is the case in XE3. In later versions we find this:
// Note: Not ^DWORD yet
PDWORD = ^CppULongInt;
Odd. So, what is CppULongInt
?
CppULongInt = type LongWord;
{$EXTERNALSYM CppULongInt 'unsigned long'}
{$OBJTYPENAME CppULongInt 'Bul' 'Gm'}
Then looking at the declaration for DWORD
we find:
//NOTE: DWORD should really be CppULongInt
DWORD = LongWord;
So, CppULongInt
and DWORD
are different types. Hence the compilation error.
What's going on here? What is the purpose of CppULongInt
? Why do the RTL designers appear to want to alias DWORD
to CppULongInt
. Is this change related to the x64 Windows C++ compiler based on LLVM? Am I the only person in the world that uses {$TYPEDADDRESS ON}
?
Note, that last question is rhetorical.