The Delphi Bug List

Compiler

Hints and Warnings


The color codes indicate in which version(s) of Delphi the bug occurs and what its status is.
Latest update: 12 July 1998
Bug # Delphi versions Description
113 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Compiler accepts bad type casts without warnings
142 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Constants that are not used but defined, do not get flagged by the compiler as "Defined but never used"
Some people think this is not so bad, because they wouldn't like to have this flag repeated many times because they have units with global constants.
147 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
There is a very serious bug in Delphi 3.0 related to the hint feature of the compiler
148 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
There are bugs in Delphi 2.0 and Delphi 3.0 that relate to the "localness" of the $HINTS and $WARNINGS directives. These directives do not have the same scope as other local directives like the $ALIGN directive.

Bug #113; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha
Hints and Warnings

Compiler accepts bad type casts without warnings

Description
Reported by Roumen Roupski
The compiler generates 'unwanted' code for the following statements:
var
  i: Integer;
  s: Single;
begin
  i := 1;
  s := Single(i);
end;
This results in s getting the value
1.4012984643E-45
This is not a bug! Because Integer and Single both occupy four bytes in memory, a type cast is allowed. But in most cases this is rather meaningless, since a Single is coded very differently (with mantissa and exponent) from an Integer.
Thanks for pointing this out, Duncan Murdoch

Bug #147; last modified: 12-Jul-98
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Unknown Unknown Exists Unknown Unknown Fixed Fixed Fixed
Hints and Warnings

There is a very serious bug in Delphi 3.0 related to the hint feature of the compiler

Description
Reported by Hallvard Vassbotn
Try to compile the following simple project consisting of three files:
T1.DPR:
program t1;
uses t1u;
end.
T1U.PAS:
{$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 t1u;
interface
{$I SIMPLE.INC}
type
  TSimpleClass = class
  private
    Unused1: integer;
    Unused2: integer;
  end;
implementation
end.
SIMPLE.INC:
{1
2
3
4
5
6
7
8
9}
You will get two hint messages saying

"Hint: D:\SRC\t1u.pas(-2): Private symbol 'Unused1' declared but never used."
"Hint: D:\SRC\t1u.pas(-1): Private symbol 'Unused2' declared but never used."

Notice that the line-numbers for the messages are all wrong (negative). It seems that the hint messages get confused because of the included file.
If you now try to re-compile, Delphi 3.0 will give an access violation
("Access violation at address 004E4688 in module 'delphi32.exe'. Read of address 00000060" on my system).
You can now no longer compile anything, you will have to restart Delphi. Usually you will be able to do File|Save all. If you try File|Close all you will get the same access violation and it will be impossible to close down Delphi politely (Task Manager's End Task command will still work). Trying to work in the IDE gives lots of access violations again.
("Access violation at address 4130479C in module 'VCL30.dpl'. Read of address 65695653" on my system).
When you close down Delphi you will get a set of errors: "Access violation at address 004E4688 in module 'delphi32.exe'. Read of address 00000048"
"Exception EAccessViolation in module VCL30.dpl at FFFFF074. Access violation at address 00000074. Read of address 00000074." "Database Engine Error: delphi 32.exe - Application Error. The instruction at "0x41306fcc" referenced memory at "0x01480848". the memory could not be "read". Click on OK to terminate the application"
before it finally dies and you can restart it.

I'm using Delphi 3.0 Client/Server build 5.53 on Windows NT 4.0 sp3 (build 1381) on a Pentium Pro 200 MHz with 64 MB RAM and 1.6 Gb disk. This behaviour has been re-created on two different machines.

Solution / workaround
There seem to be four work-arounds:
  1. Don't use include files.
  2. Don't ever declare private fields or methods that are actually not used
  3. Turn off hints
  4. Compile using DCC32.EXE instead of the IDE (see also the next bug report)
I hope Borland will release a 3.01 version ASAP... The irony of all this is that I reported this exact same bug during beta testing of Delphi 3.0 - guess Borland has a hard time listening...
Bug #148; last modified: 12-Jul-98
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Unknown Exists Exists Exists Exists Exists Unknown Unknown
Hints and Warnings

There are bugs in Delphi 2.0 and Delphi 3.0 that relate to the "localness" of the $HINTS and $WARNINGS directives. These directives do not have the same scope as other local directives like the $ALIGN directive.

Description
Reported by Hallvard Vassbotn; checked by Rune Moberg
The following three files demonstrate the problem:
LOCBUG.DPR:
program LocBug;
uses
  LocBugA;
begin
end.
LOCBUGA.PAS:
unit LocBugA;
interface
{$HINTS OFF} {$WARNINGS OFF} {$ALIGN OFF}
type
  TObjectA = class
  private
    UnusedA: integer;  // Should not get hint, and we don't
  public
    procedure Destroy; // Should not get warning, and we don't
  end;
  TRecA = record       // SizeOf(TRecA) should be 5, and it is
    A: char;
    L: longint;
  end;

implementation

uses
  LocBugB;
{.$HINTS OFF}      // Remove dots to work around the buggy behavior
{.$WARNINGS OFF}
type
  TObjectB = class
  private
    UnusedB: integer;  // Should not get hint, but we do in D3 (sometimes)
  public
    procedure Destroy; // Should not get warning, but we do (sometimes)
  end;
  {.$ALIGN ON}    // If you remove the dot, you will get an invalid typecast below
  TRecB = record  // SizeOf(TRecA) should be 5, and it is
    A: char;
    L: longint;
  end;
procedure TObjectA.Destroy; begin end;
procedure TObjectB.Destroy;
var
  A: TRecA;
begin
  TRecB(A).L := 123; // This is Ok because SizeOf(TRecA) = SizeOf(TRecB)
end;
end.
LOCBUGB.PAS:
unit LocBugB;
interface
implementation
{$HINTS ON} {$WARNINGS ON} {$ALIGN ON}
end.
The problem is that whenever the compiler re-compiles the LocBugB unit, the HINTS and WARNINGS are turned on and kept on from the point the unit is used in other units. The same does not happen with the ALIGN directive. So the "(sometimes)" in the comments above refers to whenever the LocBugB unit is re-compiled.

This means that to make sure HINTS and WARNINGS are turned off in a given unit you have to include {$HINTS OFF} and {$WARNINGS OFF} directives after the uses clause in the interface section _and_ after the uses clause in the implementation section.

This bug might seem innocent, but in combination with the very dangerous hints-bug I've written about before (it causes an access violation that forces you to close down D3), this new bug is very annoying. One of the suggested work-arounds for the first bug was to turn off hints for all code. This new bug means that this is not a simple task.

Solution / workaround
To make sure HINTS and WARNINGS are turned off in a given unit you have to include {$HINTS OFF} and {$WARNINGS OFF} directives after the uses clause in the interface section _and_ after the uses clause in the implementation section.

A related "bug" or short-coming

Often a unit needs to turn off hints and/or warnings for a small section of code. In the ideal case, this should be done without affecting the initial state of the HINTS directive. You would think that the $IFOPT directive could be used to achieve this, but that is not so. The $IFOPT directive only supports testing single-letter directives and there are no single letter variant of the HINTS and WARNINGS directives.

This means that you cannot write:

{$IFDEF _HINTS_ON_} Error: Define name clash! {$ENDIF}
{$IFOPT HINTS ON} {$HINTS OFF} {$DEFINE _HINTS_ON_} {$ENDIF}
...
{Hint-disabled code here}
{$IFDEF _HINTS_ON_} {$HINTS ON} {$UNDEF _HINTS_ON_} {$ENDIF}
This is admittedly ugly looking code, but it is the way we have handled local directives back to the TP/BP days. It would be very handy if Borland could add a pair of {$PUSHOPT} {$POPOPT} directives to help in this situations.

Another major shortcoming

The other work-around I suggested for the initial AV-generating hints bug was to use DCC32.EXE to compile the project. This is indeed possible, but it is an incredibly complicated, error-prone and manual process to get it working.

First of all, the Delphi IDE manages the project quite nicely and keeps all the options in the separate .DOF file. Why on earth can't DCC32 recognize and use this? Instead it insists on duplicating all the information in a DCC32.CFG file in the project directory (this makes it impossible to have more than one project in the same directory) or to give them all on the command line.

Secondly, it is awkward to start DCC32 from the Tools menu. To be able to see any error messages etc. you have to run it from a batch file. To run a batch file you have to run cmd/command and add /C DCC32.BAT to the parameters. Then you have to add $NAME($EXENAME) to give the name of the project file.


Index page
The Delphi Bug Lists are maintained by Reinier Sterkenburg, with help from the DeBug Team.
All feedback is appreciated. See also the feedback section of the Delphi Bug List home page.