Borland®
Shop
Products Downloads Services Support Partners News & Events Company Community
Delphi
Documentation
Support

Additional Resources
Technology Partners
Books
Community

 DELPHI DEVELOPER SUPPORT

Delphi 4 fixes and known issues
COMPILER SECTION

Areas of concentration under: compiler


Area: compiler\delphi

Reference Number: 1460 (Published: 10/28/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 9/30/98
Severity: Serious
Type: Basic Functionality Failure

Problem:

In investigating the previous problem I caused an 
interal compiler error E4129.

Steps:


1) The code
interface

 procedure AProcedure(const IA: array of integer; 
const IB: array of integer;  SA: array of string; B: 
integer);overload;
implementation

procedure AProcedure(const IA: array of integer; 
const IB: array of integer;  SA: array of string; B: 
integer);
  begin
  { body of procedure }
  end;

procedure TForm1.Button1Click(Sender: TObject);

begin
    AProcedure([1, 2],['One', 'Two'], 3);   // Kills 
compiler here
end;

2) the error.
[Fatal Error] Unit1.pas(45): Internal error: E4129

Area: compiler\delphi

Reference Number: 1089 (Published: 12/16/98)
Status: Deferred to Next Rel
Date Reported: 8/6/98
Severity: Commonly Encountered
Type: Basic Functionality Failure

Problem:

Type information is generated in illogical manner for 
Cardinals.

Cardinals are now true unsigned 32-bit numnbers 
with a range from 0 to 4G-1

However the compiler still generates type 
information for them as if they were implemented as 
signed longs

Area: compiler\delphi

Reference Number: 1459 (Published: 10/28/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 9/30/98
Severity: Commonly Encountered
Type: Basic Functionality Failure

Problem:

The follow code gives an incorrect compiler error.

When a procedure is  declare as overloaded and it 
is declared as taking two const arrays the 1st  of 
integer and the second of type string and an 
integer. If no other procedure is supplied with a 
similar partial parameter list you get an erroneous 
error message

Steps:

1) Add the following code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
procedure AProcedure(const IA: array of integer;   
SA: array of string; B: integer);overload;

var
  Form1: TForm1;

implementation

{$R *.DFM}


procedure AProcedure(const IA: array of integer; 
{const IB: array of integer;}  SA: array of string; B: 
integer);
  begin
  {Nothing needed here }
  end;

procedure TForm1.Button1Click(Sender: TObject);
  var StrArray: Array[0..1] of string;
begin
    AProcedure([1, 2],['One', 'Two'], 3);   // Call 1 
This causes the  error 
    StrArray[0] := 'One';
    StrArray[1] := 'Two';
    AProcedure([1, 2], StrArray, 3);         // Call 2 
NOTE the compiler does not barf on this???
end;

2) 
the error messages:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~
[Error] Unit1.pas(45): Ordinal type required
[Error] Unit1.pas(45): There is no overloaded 
version of 'AProcedure' that can be called with 
these arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~
the > > Ordinal type required < < < Messages 
is the wierd one??

Comments:
1) adding another procedure:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~
procedure AProcedure(const A: string; SA: array of 
string); overload; // Dummy procedure
procedure AProcedure(const A: string; SA: array of 
string);
begin
  { nothing }
end;

Area: compiler\delphi

Reference Number: 1506 (Published: 12/17/98)
Status: Deferred to Next Rel
Date Reported: 10/5/98
Severity: Commonly Encountered
Type: Documentation Problem

Problem:

Compiler allows double hash-sign within string 
constant.

eg.   S := ##13;

is equivalent to

S := #0#13;

I found this accidentally.
I was intending to write #13 and typed ##13 
instead.
It compiled, but didn't give the result I expected.

Steps:



procedure TForm1.Button1Click(Sender: TObject);
var
  S : string;
begin
  S := ##13;

  if S = #0#13 then    // condition is true
    Caption := 'Same';

end;

Area: compiler\delphi

Reference Number: 1017 (Published: 10/27/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 7/23/98
Severity: Infrequently Encountered
Type: Basic Functionality Failure

Problem:

Result fails to return string value assigned to it when 
it's a record type

Steps:

1.  Create a new application.
2.  Paste the GetMyRecord function below into the 
implementation section of the unit.
3.  Paste the following declaration for TMyRecord 
into the type clause of the unit.
4.  Drop a button on the form apply button click 
code below to the onclick event.
5.  Run and click the button, the string being 
returned is blank.

type
  TMyRecord = record
    MyString : Ansistring;
  end;

function GetMyRecord : TMyRecord;
begin
  Result.MyString := 'You will not see this';
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Showmessage(GetMyRecord.MyString);
end;

The compiler seems to be applying the rule for 
functions returning 4-byte sized records, i.e., 
function result is returned in EAX.  However, it 
should be applying the rule for AnsiStrings, 
WideStrings, etc.: the result is returned in an implicit 
var param passed to the function.  If you change 
MyString's type to be ShortString everything works 
fine.

Area: compiler\delphi

Reference Number: 1075 (Published: 12/16/98)
Status: Deferred to Next Rel
Date Reported: 8/4/98
Severity: Infrequently Encountered
Type: New Feature

Problem:

Add a keyword SHAREDVAR to declare shared 
variables. Similar in spirit to THREADVAR, 
SHAREDVAR declarations can be at the unit level 
only. Variables that are declared with SHAREDVAR 
instead of VAR are shared across all applications 
and DLLs that use the enclosing unit.

Area: compiler\delphi\basm

Reference Number: 998 (Published: 10/27/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 7/18/98
Severity: Serious
Type: Basic Functionality Failure

Problem:

Note that this is a change in behavior from Delphi 3.

Certain arithmetic combinations seem to produce 
unexpected results in code.

Area: compiler\delphi\basm

Reference Number: 437 (Published: 12/15/98)
Status: Deferred to Next Rel
Date Reported: 4/15/98
Severity: Commonly Encountered
Type: New Feature

Problem:

BASM doesn't appear to support MMX extensions.


Area: compiler\delphi\basm

Reference Number: 434 (Published: 12/15/98)
Status: Deferred to Next Rel
Date Reported: 4/15/98
Severity: Infrequently Encountered
Type: Basic Functionality Failure

Problem:


The instruction

asm
  jcxz @1
@1:

has bad encoding. An address size override ($67) is 
emitted before the instruction. It appears to be 
harmless but shouldn't be there.


Area: compiler\delphi\basm

Reference Number: 901 (Published: 12/18/98)
Status: Deferred to Next Rel
Date Reported: 7/7/98
Severity: Infrequently Encountered
Type: Basic Functionality Failure

Problem:

BASM parser accepts syntax that must cause an 
error.

Steps:

Encode the following in a Delphi program.

asm
  lea ecx,[eax + ebx + ecx + edx + esi + edi]
end;

Once compiled, you will see that the code for the 
following instruction is generated.

lea ecx, [eax + edi]

Area: compiler\delphi\basm

Reference Number: 433 (Published: 12/15/98)
Status: Deferred to Next Rel
Date Reported: 4/15/98
Severity: Infrequently Encountered
Type: Minor Functionality Failure

Problem:

The compiler accepts

asm
  imul bl,cl

which is not a valid instruction

Note from edj:  If this is as-designed, it seems that if 
the compiler is going to do magic, it should do it a 
little smarter.  It would be safer to translate to:
660FAFD9       imul   bx,cx

Steps:

dcc32 -cc dcc31400.pas
td32 dcc31400.exe
View|CPU

Notice that:
asm imul bl, cl end;

Has been translated (magically) to:
0FAFD9         imul   ebx,ecx

Area: compiler\delphi\basm

Reference Number: 902 (Published: 12/18/98)
Status: Deferred to Next Rel
Date Reported: 7/7/98
Severity: Extremely Rare Case
Type: Basic Functionality Failure

Problem:

BASM supports incorrect coding for SLDT and 
SMSW.

Steps:

begin
  asm
     SLDT ecx
  end;
end;

generates the code for SLDT CX which the 
disassembler displays as expected.

This is a corner case as these instructions are of no 
practical use to applications programmers.

And from reading the newsgroups encoding for 
INVLPG is also suspect though also equally not 
useful.

Area: compiler\delphi\code generation\optimization

Reference Number: 1113 (Published: 10/28/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 8/14/98
Severity: Critical
Type: Basic Functionality Failure

Problem:

Guid constants assigned an empty string, as in

const
  IID : TIID = '';

are not initialized to all zeros (not equal to 
GUID_NULL).

Steps:

uses
  ActiveX;

procedure Form1.FormCreate(Sender: TObject);
const
  IID : TIID = '';
begin
  if not IsEqualIID(IID, GUID_NULL) then
    Beep
end;

Area: compiler\delphi\code generation\optimization

Reference Number: 243 (Published: 7/17/98)
Status: Fixed in Version 4.0
Date Reported: 4/23/97
Severity: Serious
Type: Crash

Problem:

Having the following in the implementation of Form1 
crashes the compiler (AV in DCC.DLL):

var
  i : (i1, i2) = i1;

A workaround is of course to have a type (ti = (i1, 
i2)).

Area: compiler\delphi\code generation\optimization

Reference Number: 263 (Published: 7/17/98)
Status: Fixed in Version 4.0
Date Reported: 9/30/97
Severity: Serious
Type: Crash

Problem:

This program and unit, when compiled with Delphi 3 
will cause an internal URW376 error followed by an 
AV in DFWEDIT.DLL.

{URW376.DPR}
program URW376;

uses
  URW376U;

begin
  InterfacedRoutine;
end.

{URW376U.PAS}
unit URW376U;

{With these compiler options turned off (ie, set to -), 
compiling with
 Delphi 3 causes a fatal error ("Internal error 
URW376"). Turning them
 on (ie, set to +) the unit will compile perfectly}
{$D-,L-}

interface

procedure InterfacedRoutine;

implementation

procedure LocalRoutine;
type
  TMyEnum = (Zero, One, Two);
const
  MyEnumArray : array [TMyEnum] of char = ('0', '1', 
'2');
begin
end;

procedure InterfacedRoutine;
begin
  LocalRoutine;
end;

end.

Area: compiler\delphi\code generation\optimization

Reference Number: 269 (Published: 7/17/98)
Status: Fixed in Version 4.0
Date Reported: 12/5/97
Severity: Serious
Type: Crash

Problem:

If an application declares a typed constant that is a 
wide string,
the application does terminate correctly.

This occurs NT4. 

Steps:

Declare a constant like:
const
   wtext : widestring = '123';

Area: compiler\delphi\code generation\optimization

Reference Number: 787 (Published: 8/4/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 6/17/98
Severity: Serious
Type: Crash

Problem:

With a default parameter of set type, compilation 
causes internal error URW527 (syntax check works 
fine, instead). After this error loading and compiling 
other projects results in memory errors in Delphi 
packages, and eventually a system crash.

Steps:

1. Add the following to a unit:

function MyMsg (const Msg: string;
  AButtons: TMsgDlgButtons = [mbOK]): Word;
begin
  Result := MessageDlg (Msg, mtInformation,
    AButtons, 0);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  MyMsg ('Hello');
end;

2. Compile: gives error
3. load and run another project: bad error!

Area: compiler\delphi\code generation\optimization

Reference Number: 1364 (Published: 10/28/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 9/18/98
Severity: Serious
Type: Crash

Problem:

The attached project causes Internal Error L511 
upon compile.  The problem appears to stem from 
the fact that the two units within the project 
reference each other in the implementation section.

Steps:

1. Compile the attached project.
// Internal Error L511 occurs

Area: compiler\delphi\code generation\optimization

Reference Number: 1060 (Published: 10/27/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 7/31/98
Severity: Serious
Type: Basic Functionality Failure

Problem:

In Delphi, this causes the dataset designer to AV 
when when creating persistent fields.

Steps:

Build or install the 4.01 inline.
Make sure the DB dictionary/repository is setup.
Drop a TTable and connect it to customer.db.
Bring up the fields editor.
Add all fields.
// Note the AV.

Area: compiler\delphi\code generation\optimization

Reference Number: 1321 (Published: 12/17/98)
Status: Deferred to Next Rel
Date Reported: 9/11/98
Severity: Serious
Type: Basic Functionality Failure

Problem:

The compiler generates initialization and finalization 
code for units where it is not required.  This tends to 
cause the OS to page fault when loading a Delphi 
application thus causing lots of 4kb pages to be 
loaded making the footprint of the application very 
large.

There has been an extensive thread on the private 
newsgroup concerning this issue.  The following 
code was posted in response to this issue to help 
reduce the working set size of any Delphi 
application:

procedure TrimWorkingSet;
var
  MainHandle : THandle;
begin
MainHandle := 
OpenProcess(PROCESS_ALL_ACCESS, false, 
GetCurrentProcessID);
SetProcessWorkingSetSize(MainHandle,-1,-1);
CloseHandle(MainHandle);
end;

Steps:

The code mentioned in Description can reduce the 
memory footprint of the IDE by 40%.

Area: compiler\delphi\code generation\optimization

Reference Number: 913 (Published: 10/22/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 7/7/98
Severity: Serious
Type: Minor Functionality Failure

Problem:

A C788 internal error.


Area: compiler\delphi\code generation\optimization

Reference Number: 1135 (Published: 10/28/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 8/18/98
Severity: Commonly Encountered
Type: Crash

Problem:

The Delphi 3.02 linker is a bit too clever when 
removing symbols.

It also has a severe code generation bug (the 
compiler may be involved
too - I just don't care, since the net effect is the 
same)

In a nutshell, if one tries to FLD (BASM) data that 
has been declared
using the absolute directive, then bad code is 
generated. This will
make the application crash at runtime with access 
violations.

You will get an access violation (in this case a 
Runtime Error 216,
otherwise an exception EAccessViolation) on 
execution of 

    fld test1

This is because the first few lines of assembler code 
look like this


  fld test1
0052768C:  DD0502504A30 FLD QWORD PTR 
[+02504A30]

  fld test2

00527692:  DD0500528884 FLD QWORD PTR 
[+00528884]


[my applications are always based at $500000]
 

First result:
-------------
  Clearly [+02504A30] looks a bit like garbage (and 
it is plain 
  wrong, of course)... This explains the crash, since 
$2504A30 
  is way beyond reach for this application.


Second result:
--------------
   Run the code as shown above up to the first FLD 
(breakpoint
   or single-step).

   Have tooltip expression or "Evaluate" tell you 
that:
      test1  -- > "Symbol was eliminated by linker"
 
  

"Touching" the Constant variable, e.g. Constant[1] 
:= 0;, does
apparently make the linker sort of include "test1", 
but does _NOT_
remove the crash (!).

Even worse, touching the Test1 variable, e.g. 
Test1 := 0;, does not
change this behaviour, either.

The only solution to this problem is to have the 
absolute declaration
turned around, e.g.

  Test3: double = 0;
  Constant2: array[1..8] of byte absolute Test3;

Steps:

Found on the delphi.basm newsgroup:

{$A+,B-,C+,D+,E-,F-,G+,H+,I+,J+,K-,L+,M-,N+,O+,P
+,Q+,R+,S-,T+,U-,V+,W-,X+,Y+,Z1}
unit TestMe;

interface

implementation

var
  Constant: array[1..8] of byte;

  Test1: double absolute Constant;
  Test2: double = 0;

procedure RunMe;
asm
  fld test1
  fld test2

  fstp st(0)
  fstp st(0)
end;

initialization

  RunMe;

end.

Area: compiler\delphi\code generation\optimization

Reference Number: 349 (Published: 8/12/98)
Status: Deferred to Next Rel
Date Reported: 2/25/98
Severity: Infrequently Encountered
Type: Crash

Problem:

The compiler currently allows declaration of class 
properties, i.e. properties where both the read and 
write methods are class methods.

However, there is no straigtforward way to access 
such a property. It is possible, but you have to do 
weird type casts (see the example code). Also 
accessing such a property in the natural way (with 
Instance.Property) will cause Access Violations if 
the class methods access the VMT in anyway (i.e. 
use the implied Self: TClass parameter).

Steps:

1. Create a new application project
2. Drop a button on the form
3. Double-click the button to add an event handler
4. Add the following code:


type
  TClassProp = class(TObject)
  private
    FValue: integer;
    class function GetValue: integer;
    class procedure SetValue(Value: integer);
  public
    // D3 and Allegro actually supports declaring 
class properties..
    property Value: integer read GetValue write 
SetValue;  // This compiles, but no easy way to 
access it
    property Value1: integer read FValue write 
SetValue;  // This compiles, but does not make 
much sense!?
    property Value2: integer read GetValue write 
FValue;  // This compiles, but does not make much 
sense!?
  end;

var
  TClassProp_Value: integer;

implementation

class function TClassProp.GetValue: integer;
begin
  // Self could be a VMT or a object instance ptr 
here
  Result := TClassProp_Value;
  // Try to use the VMT, this will crash when Self is 
an object
  // instance instead of a class reference
  ShowMessage(Format('%s.GetValue = %d', 
[Self.Classname, Result]));
end;

class procedure TClassProp.SetValue(Value: 
integer);
begin
  TClassProp_Value := Value;
  // Try to use the VMT, this will crash when Self is 
an object
  // instance instead of a class reference
  ShowMessage(Format('%s.SetValue(%d)', 
[Self.Classname, Value]));
end;

procedure TForm4.Button1Click(Sender: TObject);
var
  CP: TClassProp;
begin
  // But D3/Allegro does not support accessing 
them directly through a class-reference

  // This does not compile
//  TClassProp.Value := 3;     // Method identifier 
expected
//  writeln(TClassProp.Value); // Method identifier 
expected

  // This compiles and runs as expected!! - Special 
syntax for accessing class properties through a 
class reference
  TClassProp(TClassProp).Value := 1;
  
ShowMessage(Format('TClassProp(TClassProp).Val
ue = %d', [TClassProp(TClassProp).Value]));

  // This compiles and runs ok
  CP := TClassProp.Create;
  TClassProp(CP.ClassType).Value := 2;
  
ShowMessage(Format('TClassProp(CP.ClassType).
Value = %d', [TClassProp(CP.ClassType).Value]));

  // Compiles, but crashes with an AV if methods 
access the VMT
  // This is caused by Self being an object instance, 
not a class reference
  // To work around this the compiler should 
convert Self from a TObject to a TClass!
  CP.Value := 3;
  ShowMessage(Format('CP.Value = %d', 
[CP.Value]));
end;

Area: compiler\delphi\code generation\optimization

Reference Number: 369 (Published: 7/17/98)
Status: Fixed in Version 4.0
Date Reported: 3/9/98
Severity: Infrequently Encountered
Type: Crash

Problem:

The following code makes the compiler AV in 
DCC.DLL:

var
  V : array [0..1] of Variant;

begin
  Initialize(V);
end.

Area: compiler\delphi\code generation\optimization

Reference Number: 1345 (Published: 10/28/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 9/16/98
Severity: Infrequently Encountered
Type: Crash

Problem:

The following inline assembly will cause an AV in 
DCC40.DLL during compile time:

  asm
    mov ebx,[ClientWidth]
  end;

Steps:

1. File | New App
2. In the OnCreate for instance, put this code:

  asm
    mov ebx,[ClientWidth]
  end;

3. Compile, and BOOM!

Area: compiler\delphi\code generation\optimization

Reference Number: 694 (Published: 12/15/98)
Status: Deferred to Next Rel
Date Reported: 6/10/98
Severity: Infrequently Encountered
Type: Basic Functionality Failure

Problem:

A writeln after an exception causes an unexpected 
access violation in the IDE.

Steps:

the following code in Unit1.pas.

constructor TFoo.CreateNew;
begin
  Writeln('In TFoo.CreateNew');  // Set Breakpoint 
here
  raise EMyException.Create('Will this be seen?');
  Writeln('Out Foo.CreateNew'); //Statement causes 
an Access Violation
end;

Set the breakpoint where specified, run and click 
the button.

Step past the first WRITELN and RAISE 
statements and then step through the second 
WRITELN.

See the Access Violation appear.

Area: compiler\delphi\code generation\optimization

Reference Number: 1239 (Published: 10/24/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 8/27/98
Severity: Infrequently Encountered
Type: Basic Functionality Failure

Problem:

When using packed records and optimizations, the 
code gen fails. AV in run-time.

The following is a small snippet that shows the 
problem.

type
  TMyRecord = packed record
    C : Char;
    w : Word;
  end;

  PTab = ^TTab;
  TTab = array [1..10] of TMyRecord;

var
  Tab1, Tab2 : PTab;

procedure TForm1.Button1Click(Sender: TObject);
var
  i : Integer;
begin
  New(Tab1);
  New(Tab2);
  for i:=1 to 10 do
    Tab2^[i]:=Tab1^[i];  { This AVs }
end;

Steps:

1. File | New app
2. Drop a button down, and add an event handler 
for OnClick
3. Cut and paste the code from the description into 
your app.
4. Run and hit the button

Area: compiler\delphi\code generation\optimization

Reference Number: 1477 (Published: 12/17/98)
Status: Deferred to Next Rel
Date Reported: 10/1/98
Severity: Extremely Rare Case
Type: Crash

Problem:

Sorry, this is hard core assembler programming, but 
nevertheless a code generation bug:

Both D2 and D3 (and probably D4, too) generate 
wrong code for this instruction:

asm
  mov es, word ptr es:[$2c]
end;

The binary code generated is:

   66 26 8E     05   2C 00 E8 D5

which the built-in CPU window (correctly!) 
disassembles to

   mov es, es:[$D5E8002C]  ; the "word ptr" is 
implicit

[ The "D5 E8" comes from an immediately following 
relative jump (E8
 < offset > ). ]



TASM 5.2b on the other hand assembles the above 
instruction to:

   67 26 8E     06   00 2C ; shouldn't that be "2C 
00"?

which (surprisingly < g > ) translates to "MOV ES, 
ES:[+002C]"

Obviously, Delphi 2/3 incorrectly generate an 
_operand size_ prefix ($66 - documented to be 
optional, BTW) instead of an _address size_ prefix 
($67) for this instruction. 

Steps:

Assemble with BASM

asm
  mov es, word ptr es:[$2c]
end;

and disassemble it again with any working 
disassembler (the CPU window, TD32, anything)

Area: compiler\delphi\error recovery

Reference Number: 392 (Published: 7/17/98)
Status: Fixed in Version 4.0
Date Reported: 3/24/98
Severity: Critical
Type: Crash

Problem:

Internal error URW882 is reported when compiling a 
unit which defines a constant using SizeOf.  See 
the test unit below for a simple example.

unit Test;
interface
uses Sysutils;
function PtrNew(Size: longint; ZeroIt: boolean): 
pointer;
implementation

const
  MemSizeSize = sizeof(integer);  //  < -- This line 
causes the error

function PtrNew(Size: longint; ZeroIt: boolean): 
pointer;
begin
  Inc(PChar(Result), MemSizeSize);
end;

end.

Area: compiler\delphi\error recovery

Reference Number: 495 (Published: 11/12/98)
Status: Deferred to Next Rel
Date Reported: 5/11/98
Severity: Infrequently Encountered
Type: Minor Functionality Failure

Problem:

Duplicating the uses keyword causes the compiler 
to report that it could not compile the unit it says just 
compiled.  (not a typo)

Steps:

dcc32 -cc a.pas
Result:
A.PAS(2) Error: Identifier expected but 'USES' 
found
B.PAS(5)
A.PAS(3) Fatal: Could not compile used unit 'b.pas'

Expected result:  If the compiler shows that it got to 
B.PAS(5) (the last line of B.PAS) with no errors, it 
should not say it couldn't compile the unit

Area: compiler\delphi\errors and warnings

Reference Number: 252 (Published: 7/17/98)
Status: Fixed in Version 4.0
Date Reported: 8/12/97
Severity: Serious
Type: Crash

Problem:

Internal Compiler error L1086 on line:
  TInternalError = type TObject;


Area: compiler\delphi\errors and warnings

Reference Number: 686 (Published: 10/16/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 6/10/98
Severity: Serious
Type: Minor Functionality Failure

Problem:

The hint "Overriding virtual method 'b.y' has a lower 
visibility than base class 'b'" is ambiguous.  Can we 
improve it to include which sections the two 
methods are declared in?

Steps:


Example:
Method 'descendant.foo', declared as 'private' 
lowers the visibility of 'ancestor.foo' which is 
declared 'public'

Area: compiler\delphi\errors and warnings

Reference Number: 1462 (Published: 10/28/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 9/30/98
Severity: Serious
Type: Minor Functionality Failure

Problem:

When the compiler encounters the error 
"Unsatisfied forward or external declaration" it can 
cause a bogus file open error message if the file 
with the error is not in the directory of the currently 
open project.

Area: compiler\delphi\errors and warnings

Reference Number: 1115 (Published: 8/26/98)
Status: Fixed
Date Reported: 8/14/98
Severity: Infrequently Encountered
Type: Crash

Problem:

Code generates internal compiler error C1127

Steps:

compile the console applicaion code below:
(delphi 4, newest patch applied)
===================================
{$A+,B-,C+,D+,E-,F-,G+,H+,I+,J+,K-,L+,M-,N+,O+,P
+,Q+,R+,S-,T+,U-,V+,W-,X+,Y+,Z1}
{$MINSTACKSIZE $00004000}
{$MAXSTACKSIZE $00100000}
{$IMAGEBASE $00500000}
{$APPTYPE CONSOLE}

program Project1;

uses
  Windows;

procedure BugMe;
  asm int 3 end;
  asm aas  end;  // error here

begin
  BugMe;
end.

Area: compiler\delphi\errors and warnings

Reference Number: 367 (Published: 11/20/98)
Status: Deferred to Next Rel
Date Reported: 3/8/98
Severity: Infrequently Encountered
Type: Minor Functionality Failure

Problem:

Invalid procedure or function declaration produces 
compiler error rather than diagnostic.

Steps:

Start with a new project.

Define a procedure within Fom1, private section 
(really doesn't matter):

   procedure test(x: integer; y:integer;);

Compile

The incorrect ';' causes a compiler termination with 
message 'Error, expected an identifier' rather than 
an error diagnostic.

Area: compiler\delphi\errors and warnings

Reference Number: 1572 (Published: 12/21/98)
Status: Deferred to Next Rel
Date Reported: 10/15/98
Severity: Infrequently Encountered
Type: Minor Functionality Failure

Problem:

Casting an integer to string doesn't cause compiler 
error. User may expect it to work like IntToStr, but it 
causes a AV at runtime.

Area: compiler\delphi\execution

Reference Number: 246 (Published: 7/17/98)
Status: Fixed in Version 4.0
Date Reported: 7/3/97
Severity: Serious
Type: Crash

Problem:

Putting Strings inside plain objects fail inside  of Init 
Constructors causing Av's at runtime.

Steps:

unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, 
Controls, Forms, Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  pListNode = ^ListNode;
  ListNode = object
  public
    Foo: string;
    Bar: string[20];
    constructor Init;
  end;

var
  Form1: TForm1;
implementation
{$R *.DFM}

constructor ListNode.Init;
begin
  foo := 'one';       {This is the offending line - causes 
A.V.}
 //  foo := Form1.Name;     {This also fails}
  Bar := 'eye';
end;

procedure TForm1.FormCreate(Sender: TObject);
var
 ln: ListNode;
begin
  //ln.Foo := 'foo';   {This does not fail}
  New(pListNode, Init);
end;

end.

Area: compiler\delphi\execution

Reference Number: 259 (Published: 7/17/98)
Status: Fixed in Version 4.0
Date Reported: 9/13/97
Severity: Serious
Type: Crash

Problem:

A class with a dynamic constructor created through 
a class reference variable will cause an access 
violation.

The problem is that the compiler is generating a call 
to CallDynaInst (you can find this routine in the 
System.pas file, called _CallDynaInst). The code 
should be generated as CallDynaClass, which 
assumes that the EAX register then contains the 
VMT address instead of a pointer to the VMT 
address (as would be the first pointer in an 
instantiated class).

Area: compiler\delphi\execution

Reference Number: 257 (Published: 7/17/98)
Status: Fixed in Version 4.0
Date Reported: 9/13/97
Severity: Commonly Encountered
Type: Crash

Problem:

The following project crashes the compiler 
DCC.DLL at address 00831F2D for read of 
FFFFFFFF. 

UNIT1.PAS and DFM
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, 
Controls,
  Forms, Dialogs,
  Unit3, Unit2;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
  AOBject: TObject;
begin
  AObject := TUnary.Create(utMinus);
end;

end.
object Form1: TForm1
  Left = 418
  Top = 159
  Width = 696
  Height = 480
  Caption = 'Form1'
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
end

========================================
============

UNIT2.PAS
unit Unit2;

interface

uses Unit3;

type
  TUnary = class(TObject)
  private
    FTest : TUnary;
  public
    constructor Create(UT : TUnary);
  end;

implementation

constructor TUnary.Create(UT : TUnary);
begin
  FTest := UT;
end;

end.

========================================
=============unit Unit3;

interface

type
 TUnary = (utPlus, utMinus, utInvert);

implementation

end.



Area: compiler\delphi\interaction with ui

Reference Number: 733 (Published: 10/16/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 6/14/98
Severity: Serious
Type: Minor Functionality Failure

Problem:

When you save a project in the IDE, a CFG file is 
generated to facilitate command-line compilation 
with the same compiler/linker options

This file is not generated very reliably, so causing 
potential compilation failures

To rememdy the problem, the programmer may have 
to go and edit the CFG file manually which is a bit of 
a chore since this file presumably gets regenerated 
by the IDE whenever the project is saved

Steps:

Create a pair of directories on your C: drive called 
"C:\EXE Bin" and "C:\DCU Bin"
Make a new project in Allegro
Choose Project | Options... | 
Directories\Conditionals
Set the Output directory to be C:\Exe Bin
Set the Unit output directory to be C:\DCU Bin
Set the BPL output directory to be C:\Exe Bin
Set the DCP output directory to be C:\DCU Bin
Save the project as DCC32Test

This causes these command-line switches (amongst 
others) to be stored in DCC32Test.CFG:

-Ec:\Temp\Exe Bin
-Nc:\Temp\DCU Bin
-LEc:\Temp\Exe Bin
-LNc:\Temp\DCU Bin

Notice the lack of quotes around the long directory 
names?

Bring up a command prompt & navigate to where 
you saved the project

Execute DCC32 DCC32Test.Dpr

Four warnings are generated followed by a 
compilation failure error, due to long file names 
(without surrounding quotes) being misinterpreted:

Warning: Invalid compiler directive: 'Bin'
Warning: Invalid compiler directive: 'Bin'
Warning: Invalid compiler directive: 'Bin'
Warning: Invalid compiler directive: 'Bin'
Unit1.pas(24)
Unit1.pas(25) Error: Could not create output file 
'c:\Temp\DCU\Unit1.dcu'
DCC32Test.dpr(14)

Area: compiler\delphi\interaction with ui

Reference Number: 1560 (Published: 12/21/98)
Status: Deferred to Next Rel
Date Reported: 10/13/98
Severity: Commonly Encountered
Type: Basic Functionality Failure

Problem:

The package project option to generate 
namespaces is ignored

Steps:

-Create a project with a component source module 
(or see attached)
-Options | Linker | Generate C++ Object files ON
  -Include namespaces ON
-Compile

Area: compiler\delphi\interfaces

Reference Number: 1087 (Published: 10/28/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 8/6/98
Severity: Critical
Type: Basic Functionality Failure

Problem:

Using the Implements property on a class results in 
an additional AddRef in either the delegating or 
delegated object.

Area: compiler\delphi\interfaces

Reference Number: 346 (Published: 11/13/98)
Status: Deferred to Next Rel
Date Reported: 2/23/98
Severity: Infrequently Encountered
Type: Minor Functionality Failure

Problem:

An automation interface will not compile when the 
interface in the TLB is the same name as the unit 
which implements it.  Also occures in D3.

This probably should be allowed, but if it can't be 
then at lease give a compiler message that means 
something...

Steps:

Create a project. Save all.

AddAutomation object to project.  Name automation 
object Unit2 in the expert.  Save as iUnit2.

Compile.  

Receive error:  "(PascalError) iUnit2.pas(9): '.' 
expected but ')' found."

and so on....


Area: compiler\delphi\language

Reference Number: 982 (Published: 12/18/98)
Status: Deferred to Next Rel
Date Reported: 7/16/98
Severity: Commonly Encountered
Type: Minor Functionality Failure

Problem:

On Dcc32.exe Command line online info layout is 
off.

Steps:

- type dcc32 on dos prompt.
- You will see online info in French wich is off layout

Area: compiler\delphi\language

Reference Number: 344 (Published: 11/13/98)
Status: Deferred to Next Rel
Date Reported: 2/23/98
Severity: Commonly Encountered
Type: Unknown

Problem:

Generally, the compiler error for overloaded 
methods should be made stricter. It should give 
more errors at the declaration level for classes that 
contain overloaded methods that can never be 
called because of 'Ambiguous overloaded call' 
errors.

These errors should be caugth at declaration level 
rather than at call-level.

Some calls that really are ambiguous from the 
programmers perspective should also not be 
allowed.

The following bug reports will contain examples of 
this. For all of these examples, the following steps 
should be performed before entering the supplied 
code:

Steps:

1. Create a new Application project
2. Drop a button on the form
3. Double click the button and enter the following 
code in the event handler:

procedure TForm1.Button1Click(Sender: TObject);
var
  A: TFoo;
begin
  A:= TFoo.Create;
  try
    A.Test;
  finally
    A.Free;
  end;
end;

4. The follwing bug-reports will give the code 
examples that define the TFoo class.

Area: compiler\delphi\language

Reference Number: 776 (Published: 12/7/98)
Status: Deferred to Next Rel
Date Reported: 6/16/98
Severity: Infrequently Encountered
Type: Basic Functionality Failure

Problem:

The compiler allows FUNCTION in interface but 
PROCEDURE in implementation.

I know that I don't need to fully define a routine in 
the implementation section, i.e. I don't have to list 
parameters and function return type. But certainly 
function/procedure should be kept distrinct.

[This is new to Delphi 4 - MD]

Area: compiler\delphi\language

Reference Number: 351 (Published: 11/13/98)
Status: Deferred to Next Rel
Date Reported: 2/26/98
Severity: Extremely Rare Case
Type: Basic Functionality Failure

Problem:

The compiler does not allow a class parent type to 
be prefixed by a unit name. 

This makes it impossible to declare two classes in 
the same unit inheriting from two different classes 
with the same name in two different units.

Steps:

1. Create a new form
2. Modify the class declaration so that it looks like 
the one below
3. Note the usage of unit qualification in the class 
inhertance 
4. Try to compile
5. You don't get a normal compiler-error message in 
the error log, but rather a modal dialog saying:
 > Error
 > Expected ")".

unit Unit15;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, 
Controls, Forms, Dialogs;

type
  TForm15 = class(Forms.TForm)  // Note: Forms. 
syntax
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form15: TForm15;

implementation

{$R *.DFM}

end.

Area: compiler\delphi\language\dynamic arrays

Reference Number: 653 (Published: 11/19/98)
Status: Deferred to Next Rel
Date Reported: 6/8/98
Severity: Serious
Type: Basic Functionality Failure

Problem:

If an attempt to allocate a 2 dimensional dynamic 
array raises an out of memory exception, the 
memory that has been allocted so far is not freed.  It 
will not be freed until the program is exited, making it 
impossible to allocate any more memory.

Steps:


1) Create a form with three buttons and the 
following private declaration and event handlers:

type
  TForm1 = class(TForm)
 { ... }
  private
    { Private declarations }
    FArray : array of array of double;
  public
    { Public declarations }
  end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetLength(Farray,1500,1500); { allocate 18 Mb 
array }
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  SetLength(Farray,8000,8000); {allocate 512 Mb 
array }
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
{  FArray := nil;}
  Finalize(Farray);
end;

2) Run the program alongside some utility that will 
show the amount of memory allocated (the NT4 
Task Manager is ideal as it can show the memory 
usage and VM size of each process).

3) Press the second button to allocate a 5000x5000 
array of doubles (512 Mb in size). It will allocate 
memory for a few seconds, then fail with a 
EOutOfMemory exception (unless you've got a lot of 
RAM and swap file space!).

4) Note the memory allocated as shown in the Task 
Manager. The memory allocated for a portion of the 
2d array so far has not been freed.

5) Click the third button, which should deallocate 
the array. This has no effect and the memory isn't 
deallocated until the program is exited. Any further 
attempts to allocate memory, even small amounts, 
will fail.

6) For comparison, click the first button which 
allocates an 18Mb array. This should work OK and 
the allocation will show up on the Task Manager. 
Clicking the deallocate button will free the memory 
and the Task Manager will show the reduced 
memory allocation.

Area: compiler\delphi\language\overloading\method

Reference Number: 1153 (Published: 10/22/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 8/20/98
Severity: Critical
Type: Crash

Problem:

Combining Overloading with Default parameters can 
cause stack to corrupt with invalid data passed, but 
only when overloaded methods are declared in a 
specific order.

Area: compiler\delphi\language\overloading\method

Reference Number: 857 (Published: 10/21/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 6/30/98
Severity: Serious
Type: Basic Functionality Failure

Problem:

If you have overloaded routines in a DLL, you seem 
only to be able to export the first one

Steps:

Make a DLL like the one below. When you compile 
it, the blue bullet markers, idicating code generated 
appear by the first version of Foo. If you swap the 
two overloaded routines around, so that they are in 
the opposite order, the same occurs, in that code is 
generated for the first one.

We need a mechanism to specify which one is 
being exported, which is more scientific than code 
positioning.

library Project1;

uses
  SysUtils,
  Dialogs,
  Classes;

procedure Foo(A: AnsiChar); overload;
begin
  ShowMessage('FooA')
end;

procedure Foo(I: Integer); overload;
begin
  ShowMessage('FooI')
end;

exports
  Foo;

begin
end.

Area: compiler\delphi\language\overloading\method

Reference Number: 837 (Published: 10/21/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 6/23/98
Severity: Commonly Encountered
Type: Basic Functionality Failure

Problem:

Method overloading goes bad when Booleans are 
used as parameter types

Steps:

Try compiling this unit. Even though the overloaded 
methods are declared fine, the compiler rejects the 
second call.

Changing the 40.0 to 40 makes the code compile 
just fine

unit MethodOverloadUnit2;

interface

implementation

type
  TFoo = class(TObject)
  public
    procedure Bar(B: Boolean); overload;
    procedure Bar(D: Double); overload;
  end; { TFoo }

procedure TFoo.Bar(B: Boolean);
begin
end;

procedure TFoo.Bar(D: Double);
begin
end;

var
  Foo: TFoo;
begin
  Foo := TFoo.Create;
  Foo.Bar(40.0); //Compiler complains: 
"Incompatible types: 'Boolean' and 'Real'"
  Foo.Free
end.

Area: compiler\delphi\language\overloading\method

Reference Number: 973 (Published: 10/22/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 7/15/98
Severity: Commonly Encountered
Type: Basic Functionality Failure

Problem:

Cannot override an overloaded method when the 
immediate ancestor does not also override ALL 
overloaded methods.

Steps:

Try to compile the following code, not the error 
compiling class C.  However, if you change class C 
to inherit from class B2, then it works.

type
  A = class
  protected
    procedure Foo(X: integer); overload; virtual;
    procedure Foo(const S: string); overload; virtual;
  end;

  B = class(A)
  protected
    procedure Foo(X: integer); override;
  end;

  B2 = class(A)
  protected
    procedure Foo(X: integer); overload; override;
    procedure Foo(const S: string); overload; 
override;
  end;

  C = class(B)
  protected
    procedure Foo(const S: string); override;
  end;

Area: compiler\delphi\language\overloading\method

Reference Number: 345 (Published: 11/13/98)
Status: Deferred to Next Rel
Date Reported: 2/23/98
Severity: Commonly Encountered
Type: Unknown

Problem:

tighten up overloading rules, and introduce a new 
compiler error with the message:

"Method < identifier > with ambiguous 
parameters already exists)"

Replaceing 
"Ambiguous overload call to ..."

Steps:

You should define very clearly what parameter 
types are considered unique with respect to define 
new signatures for overloaded methods.

These rules should be based on single, simple goal:

"There should be no possible ambiguity when 
calling overloaded methods with constant 
expressiosn".

With this in mind, there should be only a few groups 
of parameter types that will be considered unique. 
For instance all integer-types would map to the 
same group, so that even declaring two methods 
with integer-type parameter at the same position 
would be illegal. For instance, currently this 
compiles:

type
  TFoo = class
  public
    procedure Bar(A: integer); overload;
    procedure Bar(A: byte); overload;
  end;

Calling Bar with a constant expression, as in :

  Foo.Bar(1);

is clearly ambiguous, so these declaration should be 
disallowed altogether.
Introduce a new compiler error with the message:
"Method < identifier > with ambiguous 
parameters already exists)"
This message should apply to by aliasing the 
following types:

All string/char types:
char, string, AnsiString, shortstring, type 
TString10=string[10], array of char, PChar

All integer numeric types:
byte, shortint, smallint, integer, word, cardinal, 
longint, int64...

All floating-point numeric types:
comp, double, single, real...

Area: compiler\delphi\language\variants

Reference Number: 301 (Published: 11/11/98)
Status: Deferred to Next Rel
Date Reported: 2/6/98
Severity: Serious
Type: Basic Functionality Failure

Problem:

Comparing any variant whose type is varString to 
any other variant with type less than varByte 
causes an invalid variant operation. Yet all these 
variants can be converted to varString types.

Steps:


procedure Comp(V1, V2: Variant);
begin
  try
    if V1 = V2 then Writeln('Equal');
  except
    Writeln(Format('Exception V1: %x V2: %x', 
[VarType(V1), VarType(V2)]));
  end;
end;

procedure Comp2(V1, V2: Variant);
var S1, S2: string;
begin
  S1 := V1;
  S2 := V2;
  if S1 = S2 then Writeln('Equal');  
end;

var
  V1, V2, V3, V4, V5: Variant;
begin
  V1 := 3333333;
  V2 := 1.234;
  V3 := '12/12/98 1:23:34 AM';
  V3 := VarAsType(V3, VarDate);
  V4 := 4;
  V4 := VarAsType(V4, varByte);
  V5 := 'aaaaa';

  Comp(V1, V5);
  Comp(V2, V5);
  Comp(V3, V5);
  Comp(V4, V5);

  Comp2(V1, V5);
  Comp2(V2, V5);
  Comp2(V3, V5);
  Comp2(V4, V5);
  Readln;
end.

Area: compiler\delphi\linker

Reference Number: 258 (Published: 7/17/98)
Status: Fixed in Version 4.0
Date Reported: 9/13/97
Severity: Serious
Type: Crash

Problem:

Internal error L1086 caused by type declaration

Steps:

unit TypeBugU;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, 
Controls, Forms, Dialogs;

type
  TForm1 = class(TForm)
  end;
  TInternalError = type TObject;  { < < This is the 
line which crashes  }

var
  Form1: TForm1;

implementation
{$R *.DFM}
end.


The first attempt to compile this gives:
"Fatal Error: (0): Internal error: L1086."
On subsequent compilations I get:
"Fatal Error: ...: Unit SysUtils was compiled with a 
different version of System"} 

Area: compiler\delphi\linker

Reference Number: 1573 (Published: 10/28/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 10/15/98
Severity: Serious
Type: Crash

Problem:

RES files with large string tables can cause an AV 
in RLINK32.DLL

Area: compiler\delphi\make logic

Reference Number: 861 (Published: 8/4/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 7/1/98
Severity: Critical
Type: Crash

Problem:

Compiling direct40.dpk causes internal error in the 
linker.

This is because the version for resource strings was 
not initialized in CalcSymbolVersions().

Area: compiler\delphi\other compiler

Reference Number: 245 (Published: 7/17/98)
Status: Fixed in Version 4.0
Date Reported: 7/2/97
Severity: Infrequently Encountered
Type: Crash

Problem:

An Include file that includes itself will cause Delphi 
to hang (i.e. it is self referential)

Steps:

1) Create a text file called CIRCLE.INC
2) Put the following line in it:
      {$I CIRCLE.INC}
3) Put the ablove line in a Delphi applicaiton.

Area: compiler\delphi\other compiler

Reference Number: 870 (Published: 10/21/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 7/6/98
Severity: Infrequently Encountered
Type: Minor Functionality Failure

Problem:

In the PACKAGEINFO resource of an EXE  bits 
30-31 of the first four bytes are not correctly set to 0 
- EXE, instead they are set to 3 which is undefined.

Steps:

1) File | New Application
2) Save the project and MAKE it.
3) At a DOS prompt in the directory the project 
resides type in "tdump -v project1.exe 
project1.dmp" using the BCB tdump.
4) look at text file project1.dmp, at the end of the file 
at the binary resource PACKAGEINFO.  The first 
four bytes should be 01 00 00 0C.

Area: compiler\delphi\thread local storage

Reference Number: 1053 (Published: 10/27/98)
Status: Fixed in Version 4 Update Pack 2
Date Reported: 7/31/98
Severity: Serious
Type: Crash

Problem:

setting a boolean threadvar to an expression 
including another threadvar yields incorrect results.

Steps:

{$A+,B-,C+,D+,E-,F-,G+,H+,I+,J+,K-,L+,M-,N+,O+,P
+,Q+,R+,S-,T+,U-,V+,W-,X+,Y+
,Z1}
{$MINSTACKSIZE $00004000}
{$MAXSTACKSIZE $00100000}
{$IMAGEBASE $00400000}
{$APPTYPE CONSOLE}

program Project1;

uses
  SysUtils;

const
  BoolText: array[boolean] of string = ('false', 'true');

threadvar
  BytesRemaining: integer;
  FetchFailure: boolean;

  procedure TestMe;
  begin
    WriteLn('Remaining = 0? - >  ' + 
BoolText[BytesRemaining = 0]);

    FetchFailure := BytesRemaining = 0;  // gets set 
incorrectly

    WriteLn('Remaining = 0? - >  ' + 
BoolText[FetchFailure]);
  end;

begin
  BytesRemaining := 200;
  TestMe;

  ReadLn;
end.

// the program outputs 'false true' instead of 'false 
false'



NOTE: These listings are for informational use only. It is not intended for use when calling Borland's Developer Support Department.
If you have any suggestions or complaints about these 'Delphi Enhancements and Fixes' pages, please contact the Delphi Administrator. This e-mail address is not intended for support issues.
 
Site Map Search Contact