27

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.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • In case anyone is interested, I'm looking at XE7 and giving it a run out on my codebase which currently builds on XE3. Things are not going as smoothly as one might hope. http://stackoverflow.com/questions/25815970/why-does-format-reject-procedure-address-arguments-starting-with-xe4 – David Heffernan Sep 12 '14 at 21:48
  • Is DWORD still an alias to LongWord? – Sertac Akyuz Sep 12 '14 at 21:55
  • @Sertac Ah, switched off computer. Late here now. Can't check now. `CppULongInt = type LongWord` defines new type rather than alias. – David Heffernan Sep 12 '14 at 21:58
  • 1
    I noticed. Pretty weird to define a pointer of a type to a type other than its own. – Sertac Akyuz Sep 12 '14 at 21:59
  • 1
    @Sertac The very name CppULongInt gives me the fear. It's as if they forgot that Delphi exists. Which is I suppose a change from the normal state of affairs when it goes in the other direction. – David Heffernan Sep 12 '14 at 22:02
  • 1
    In XE6 System.Types: `//NOTE: DWORD should really be CppULongInt DWORD = LongWord;`. – LU RD Sep 12 '14 at 22:21
  • 1
    IOW, "I know a PDWORD does not point to a DWORD, but I don't care". – Sertac Akyuz Sep 12 '14 at 22:24
  • 13
    [QC Report #: 115307](http://qc.embarcadero.com/wc/qcmain.aspx/qcmain.aspx?d=115307) – bummi Sep 12 '14 at 22:25
  • Another thing that makes me not want our company to migrate from XE2 to XE6. – Jerry Dodge Sep 13 '14 at 02:12
  • 1
    @Sertac *I know a PDWORD does not point to a DWORD, but I don't care, because I use $TYPEDADDRESS OFF!* – David Heffernan Sep 13 '14 at 05:38
  • The documentation says it's should be an alias to LongWord (aka Cardinal) heck even the wrong code is statet there... So it's clearly something that at Embarcadero someone didn't notice the difference between an alias and a new type... – mrabat Sep 13 '14 at 06:15
  • @mrabat `DWORD` is an alias to `LongWord`. See LURD's comment above. – David Heffernan Sep 13 '14 at 08:36
  • @mrabat probably meant CppULongint, which is [documented](http://docwiki.embarcadero.com/Libraries/en/System.CppULongInt) to be an alias. – Sertac Akyuz Sep 13 '14 at 09:57
  • 3
    I could not resist :) - http://sergworks.wordpress.com/2014/09/13/why-pdword-is-not-a-pointer-to-dword/ – kludg Sep 13 '14 at 10:41
  • 2
    So, possible answers to *"Why is PDWord not ^DWORD?"* - There's a developer who cannot tell a type from an alias. - There's a developer who doesn't have the slightest idea about the relation between `PDWORD` and `DWORD`. - @Serge's theory involving more developers, which amounts to "there's a development team who doesn't give a f..". – Sertac Akyuz Sep 13 '14 at 10:46
  • To me, it looks a like a simple oversight. – Rudy Velthuis Sep 14 '14 at 17:56
  • 1
    @Rudy *Note: Not ^DWORD yet* seems quite intentional – David Heffernan Sep 15 '14 at 07:21
  • The use of "yet" seems to indicate that was supposed to become `^DWORD` (again), but was typedef-ed as `^CppULongint` for some reason, and that this was simply not changed back to the original – Rudy Velthuis Sep 15 '14 at 10:22
  • 1
    This is fixed in XE8. http://qc.embarcadero.com/wc/qcmain.aspx?d=115307. – LU RD Apr 08 '15 at 21:02

1 Answers1

5

(Refering to Why PDWORD is not a pointer to DWORD.) It looks someone at Embarcadero didn't read the relevant Windows documentation:

  • DWORD is explicitly defined as a 32 bit unsigned integer, thereby in Delphi it should be an UInt32.
  • PDWORD is defined as a pointer to a DWORD, thereby in Delphi it should be PDWORD = ^DWORD.
  • It's DWORD_PTR (which is not a PDWORD!) that is defined as an ULONG_PTR, and the latter changes in size depending on the platform (32 or 64 bit), not the compiler definition of an unsigned long.

One reason may be they are attempting to use DWORD and other Windows datatypes on non Windows platforms, and are trying to keep them compatible. If so, in this case they failed and introduced a bug, because the definitions used won't work properly in Windows.

AmigoJack
  • 5,234
  • 1
  • 15
  • 31
LDS
  • 59
  • 1
  • 2
    You are referring to Serg's blog article here. Certainly C++ `long` is platform dependent. I'm asking why `PDWORD` isn't `^DWORD`, and also what `CppULongInt` is. Emba certainly aren't trying to use `DWORD` away from Windows. – David Heffernan Sep 15 '14 at 07:21
  • Actually the Windows header file defines DWORD as an alias to unsigned long. The Windows data model in turn says that long is 32 bits. C++ long is implementation defined. For any implementation on Windows this all mandates 32 bit long on that platform. – David Heffernan Sep 15 '14 at 07:55
  • Why Embarcardero defined it that way only Embarcadero knows. My guess is that it attampted to keep it compatible with different platforms/architectures, or the translation was made directly from the header files without taking into account the documentation. – LDS Sep 15 '14 at 08:17
  • Actually, I take back what I said in my first comment. The `DWORD` type is declared in `System.Types` which is x-plat. Quite how `DWORD` could have meaning away from Windows is beyond me though. – David Heffernan Sep 15 '14 at 08:18