Overload resolution error using DrawText

When porting code from D2007 to XE2, I received a compiler error that I cannot understand. See the following example:

procedure TForm1.FormPaint(Sender: TObject); var c: Char; pc: PChar; r: TRect; begin c := '1'; pc := @c; r := Bounds(100, 100, 100, 100); DrawText(Canvas.Handle, pc, 1, r, DT_SINGLELINE or DT_NOCLIP); //1 {$TYPEDADDRESS OFF} DrawText(Canvas.Handle, @c, 1, r, DT_SINGLELINE or DT_NOCLIP); //2 {$TYPEDADDRESS ON} DrawText(Canvas.Handle, @c, 1, r, DT_SINGLELINE or DT_NOCLIP); //3 DrawText(Canvas.Handle, PChar(@c), 1, r, DT_SINGLELINE or DT_NOCLIP); //4 end; 

D2007 compiles this without a problem. The XE2 compiler rejects the line marked //3 with

[DCC Fehler] Unit1.pas (38): E2010 Inkompatible Typen: 'string' und 'Pointer'

I assume this is due to the recently added DrawText overloads accepting Delphi strings.

Can you explain this error? This is not a problem since I have a workaround (explicit casting), but I'm curious. Is the error still present in later versions of Delphi?

Edit: I ask if there is an error in the compiler, and not an explanation of why it is. It is possible that I overlooked the real reason the compiler refused my code.

+8
delphi overload-resolution delphi-xe2
source share
1 answer

This is not like the normal situation with overload resolution. DrawText defined twice:

 function DrawText(hDC: HDC; lpString: PWideChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; external user32 name 'DrawTextW'; function DrawText(hDC: HDC; const lpString: UnicodeString; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; begin Result := Winapi.Windows.DrawText(hDC, PWideChar(lpString), nCount, lpRect, uFormat); end; 

With {$TYPEDADDRESS OFF} it seems that ^Char interpreted by the compiler as an untyped pointer that is never compatible with the declared type of PChar , while @c seems to allow PChar OK. This seems to contradict the notion that {$TYPEDADDRESS OFF} means that all pointers are agnostic type. It seems that PChar and ^Char somehow handled differently in the compiler than other pointers.

With {$TYPEDADDRESS ON} both @c and ^Char become equivalent, but are curiously accepted as arguments until overload resolution exists for sorting.

In both cases, it seems that overload permissions are completed before type compatibility is fully established. I'm not sure what I would call this a mistake, though ... it seems like behavior that would be difficult to change without causing problems.

Sscce

 program Project1; {$APPTYPE CONSOLE} {$R *.res} {$DEFINE OVLD} {$IFDEF OVLD} procedure Test(s:string); overload; begin end; {$ENDIF} procedure Test(x:PChar); {$IFDEF OVLD}overload; {$ENDIF} begin end; var c : Char; pc : ^Char; begin {$TYPEDADDRESS OFF} Test(@c); Test(pc); //OVLD - Incompatible types : 'string'-'pointer' //No OVLD - Incompat. types : 'PWideChar'-'pointer' {$TYPEDADDRESS ON} Test(@c); //OVLD - Incompatible types : 'string'-'pointer' //No OVLD - OK Test(pc); //OVLD - Incompatible types : 'string'-'pointer' //No OVLD - OK end. 
+7
source share

All Articles