Log On
Embarcadero Home
Watch, Follow, &
Connect with Us
Share This
QualityCentral
Communities
Articles
Blogs
Resources
Downloads
Help
QualityCentral
Delphi-BCB
IDE
Structure Pane
Error Insight
You are not logged in.
Help
Print
Public Report
Report From:
Delphi-BCB/IDE/Structure Pane/Error Insight
[ Add a report in this area ]
Report #:
101168
Status:
Open
Syntax parser gets broken after "absolute" keyword
Project:
Delphi
Build #:
16.0.4316.44803
Version:
16.2
Submitted By:
Dmitry Burov
Report Type:
Basic functionality failure
Date Reported:
11/20/2011 10:46:30 AM
Severity:
Commonly encountered problem
Last Updated:
3/20/2012 2:24:39 AM
Platform:
All versions
Internal Tracking #:
288930
Resolution:
None
(Resolution Comments)
Resolved in Build:
:
None
Duplicate of:
None
Voting and Rating
Overall Rating:
No Ratings Yet
0.00 out of 5
Total Votes:
None
Description
see screenshot.
Not only locally broken - but even unusable to the end of the unit file !
Steps to Reproduce:
see screenshot
-------------------------
unit Unit1;
interface
implementation
uses System.Classes;
type
TPtr = record
someData: Boolean;
x:Pointer;
someMoreData: string;
end;
procedure BugTest(const pt: TPtr; const sl:TStrings);
var
x_as_obj: TObject absolute pt.X;
begin
// such variable definitions come handy
// when need to work with TList.AddObject
// or TStrings.AddObject and such
sl.AddObject('bug test', x_as_obj);
end;
end.
-------------------------
Workarounds
One may ask how is at better than direct typecast used many time within VCL code or any code floating over the internets.
Why not this way?
procedure BugTest(const pt: TPtr; const sl:TStrings);
begin
sl.AddObject('bug test', TObject(pt.X));
end;
Let's make the procedure a bit more complex and use the variable more than once.
There is a common pattern, frequently used in Windows GDI API for example. And in TurboPascal ExitProc chain, if i remeber good old DOS times.
We change some value using provided function, and all value is returmned by function, so caller can save it for laiter chaining or gracefully dispose of.
Code is schematic, slow but easy.
procedure UpdateCache(const pt: TPtr; const sl:TStrings; const value: string);
var idx: integer; temp: TObject;
begin
idx := sl.IndexOf(value);
if idx >=0 then begin
temp := sl.Objects[idx];
sl.Objects[idx] := TObject(pt.X);
TObject(pt.X) := temp;
end els begin
sl.AddObject('bug test', TObject(pt.X));
TObject(pt.X) := nil;
end;
end;
procedure UpdateCache(const pt: TPtr; const sl:TStrings; const value: string);
var idx: integer; temp: TObject; pt_obj: TObject absolute pt.X;
begin
idx := sl.IndexOf(value);
if idx >=0 then begin
temp := sl.Objects[idx];
sl.Objects[idx] := pt_obj;
pt_obj := temp;
end els begin
sl.AddObject('bug test', pt_obj);
pt_obj := nil;
end;
end;
So we used that variable more than once.
1. Type Safety. None in both cases. Compiler protection fully overriden.
2. Coding speed - we have to key in reasonable less code.
3. Future changes: if we change container type from TStrings so some another, and it will have other type than TObject for by-side values, we only would need change type in one easy to find declaration, rather than peek through the whole procedure body. Given that we overriden type safety, if we would forget to change some place, compiler would not be able to warn us with error.
4. Mistyping: There are frequently smilar-named types, like TColor and TColors. Single mis-typed letter may change the meaning. When we have one type definition it is easier to key it in with attention and check it rigidly, than when intermixed through all the body.
5. Side Effects: providing all this, absolute-using pattern make code looks like regular variable used. This may lead unattentive programmer to wrong things like re-using variable for temporary values and such. Direct typecast way frankly marks tricky place and alerts any later reader.
Given this, i consider 2-4 more important than 5, though of cause mileage varies.
Attachment
absolute_record_bug.zip
Comments
Tomohiro Takahashi at 11/20/2011 4:36:34 PM
-
Could you please provide simple sample code to reproduce/verify your issue?
Dmitry Burov at 11/22/2011 2:21:23 AM
-
unit Unit1;
interface
implementation
uses System.Classes;
type TPtr = record someData: Boolean; x:Pointer; someMoreData: string; end;
procedure BugTest(const pt: TPtr; const sl:TStrings);
var x_as_obj: TObject absolute pt.X;
begin
// such variable definitions come handy
// when need to work with TList.AddObject
// or TStrings.AddObject and such
sl.AddObject('bug test', x_as_obj);
end;
end.
Dmitry Burov at 11/25/2011 1:54:37 AM
-
ok, since u updated sample i'd add workaround and few arguments against it.
Dmitry Burov at 11/25/2011 1:58:59 AM
-
And speaking nostalgically, TurboPAscal mad e it all wrong.
Soviet PDP-11 Pascal had address specification bound to var, rather than to type. MAybe they taken it from some other Western implementation of Pascal, dunno.
"var Name origin Adress: Type;" instead of Borland's "var Name: Type absolute Address;"
What's the differnce ? Simple. It eliminated overlook errors, like when hastily adding two counter variables.
Var SomeData: integer absolute DataStructure.Member;
Now coder has few seconds to add looping into procedure, He hastily inserts loop counter vars and if overlook he gets...
Var i,j,SomeData: integer absolute DataStructure.Member;
He messed things up :-)
View Your Reports
Search
Server Response from: ETNACODE01
Developer Tools
Blackfish SQL
C++Builder
Delphi
FireMonkey
Prism
InterBase
JBuilder
J Optimizer
HTML5 Builder
3rdRail & TurboRuby
Database Tools
Change Manager
DBArtisan
DB Optimizer
ER/Studio
Performance Center
Rapid SQL
Technical Articles
Tutorials
White Papers
Press Releases
Newsletters
Add Content (GetPublished)
Audio
Audio & Video
Video
Bugs & Suggestions (QualityCentral)
Discussion Forums
Examples (CodeCentral)
Tags
Technology Partners
Downloads
Free Trials
Registered User Downloads
Beta Programs
Add Content (GetPublished)
Articles
Blogs
Bugs & Suggestions (QualityCentral)
Discussion Forums
Examples (CodeCentral)
Member Services
About
Connect with Us