Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/Compiler/Delphi/Language/Overloading    [ Add a report in this area ]  
Report #:  122191   Status: Closed
Mysterious errors when implementing cdecl overload methods of interface
Project:  Delphi Build #:  19.0.14356.6604
Version:    19.2 Submitted By:   Chee Wee Chua
Report Type:  Feature Specification issue Date Reported:  2/2/2014 5:31:51 PM
Severity:    Infrequently encountered problem Last Updated: 4/15/2014 6:32:26 PM
Platform:    All versions Internal Tracking #:   47958
Resolution: Fixed (Resolution Comments) Resolved in Build: : XE6
Duplicate of:  None
Voting and Rating
Overall Rating: No Ratings Yet
0.00 out of 5
Total Votes: 10
Description
If you declare an interface with several cdecl methods of the same name, then declare another interface inheriting from the first interface, then declare an implementation of the second interface, mysterious errors occur when you try to compile it.

Notice that while you can declare "cdecl; overload" in an interface method declaration, if you do so in a class, you get VERY mysterious errors.

This makes the Delphi language grammar inconsistent. Document this, or fix the compiler.
Steps to Reproduce:
1. New Delphi console project.

2. Replace generated code with below.
-----------
type
  IFather = interface
    procedure wait; cdecl; overload;
    procedure wait(millis: Int64); cdecl; overload;
    procedure wait(millis: Int64; nanos: Integer); cdecl; overload;
  end;

  ISon = interface(IFather)
  end;

  TSon = class(TInterfacedObject, ISon)
    procedure wait; cdecl; overload;  // line 17
    procedure wait(millis: Int64); cdecl; overload; // line 18
    procedure wait(millis: Int64; nanos: Integer); cdecl; overload;
  end;

{ TSon }

procedure TSon.wait;
begin

end;

procedure TSon.wait(millis: Int64);
begin

end;

procedure TSon.wait(millis: Int64; nanos: Integer);
begin

end;

begin
end.
-----------

3. Compile.

EXP: No errors
ACT:
[dcc32 Error] Project4.dpr(17): E2169 Field definition not allowed after methods or properties
[dcc32 Error] Project4.dpr(18): E2070 Unknown directive: 'wait'
[dcc32 Error] Project4.dpr(18): E2029 'END' expected but ')' found
[dcc32 Error] Project4.dpr(18): E2029 ',' or ':' expected but ';' found
[dcc32 Error] Project4.dpr(19): E2070 Unknown directive: 'wait'
[dcc32 Error] Project4.dpr(19): E2029 'END' expected but ')' found
[dcc32 Error] Project4.dpr(19): E2029 ',' or ':' expected but ';' found
[dcc32 Error] Project4.dpr(20): E2029 Type expected but 'END' found
[dcc32 Error] Project4.dpr(16): E2291 Missing implementation of interface method IFather.wait
[dcc32 Error] Project4.dpr(16): E2291 Missing implementation of interface method IFather.wait
[dcc32 Error] Project4.dpr(29): E2037 Declaration of 'wait' differs from previous declaration
[dcc32 Error] Project4.dpr(34): E2037 Declaration of 'wait' differs from previous declaration
Workarounds
Instead of cdecl; overload, use overload; cdecl; instead.
Alternatively, remove the semicolon between the directives, eg, procedure wait cdecl overload;
Attachment
None
Comments

Blaise Thorn at 2/2/2014 6:31:17 PM -
This has nothing to do with interfaces or implementing them. Or CDecl, for that matter.

For method declarations, DCC expects to find directives in a particular order.
It does not accept a calling convention directive (or the INLINE directive) /before/ the OVERLOAD directive:

type C = class


procedure Accepted; overload; stdcall;


procedure Rejected; stdcall; overload;

end;
There is nothing mysterious about the issued error either: DCC interprets the unreserved "overload" identifier as a field name.

Chee Wee Chua at 2/2/2014 8:24:56 PM -
If you look at the RTL source code, you'll find 3500+ cdecl; overload; in there.

Blaise Thorn at 2/2/2014 8:39:12 PM -
> If you look at the RTL source code, you'll find 3500+ cdecl; overload; in there.

I said "method declarations". As in CLASS, RECORD, and OBJECT (and HELPER).

If you look at TMacLocationSensorNotifHandler.locationManager in System.Mac.Sensors.pas, you will see that all of them have "overload; cdecl;", while only /the one commented out/ has "cdecl; overload;".

Chee Wee Chua at 2/2/2014 10:48:52 PM -
The following works:

  TSon = class(TInterfacedObject, ISon)
    procedure wait cdecl overload;
    procedure wait(millis: Int64) cdecl overload;
    procedure wait(millis: Int64; nanos: Integer) cdecl overload;
  end;

So your theory is incorrect.

Blaise Thorn at 2/2/2014 11:21:44 PM -
> The following works

Having worked myself around this particular DCC limitation for years, I am quite aware of that fact.

> So your theory is incorrect.

Above was not a theory, but merely an explanation, albeit not an all-embracing one. For example, I could have also noted that certain combinations of three or more directives are only accepted by DCC in /one/ fixed order, in which a semicolon is /mandatory/ in one position whereas it is rejected in another. But that was not my goal.


Overall, I am not quite sure why you would rather initiate a pissing contest instead of working on improving your report as suggested.
Of course, that this "report is inadequate" is only a matter of my personal opinion; but based on that opinion, I will not promote this report as it is now.
(Of course, this does not mean that someone else will not.)

Chee Wee Chua at 2/2/2014 11:27:12 PM -
Unlike you, I don't promote my own reports even though I have the ability to promote reports.
There is no inadequacy in this report.

Blaise Thorn at 2/3/2014 12:02:15 AM -
> Unlike you, I don't promote my own reports

Is this a personal attack?
If you have a problem with the way I sysop, you are free to take it up with EMBT, of course.

> There is no inadequacy in this report.

Like I said, this is a matter of opinion.
Mine can be easily found in the first paragraph of my first comment.

Chee Wee Chua at 2/2/2014 9:58:58 PM -
Also,

function fcntl(Handle: Integer; Command: Integer; var Lock: flock): Integer; cdecl; overload;
  external libc name _PU + 'fcntl';
function fcntl(Handle: Integer; Command: Integer; Arg: Longint): Integer; cdecl; overload;
  external libc name _PU + 'fcntl';
function fcntl(Handle: Integer; Command: Integer): Integer; cdecl; overload;
  external libc name _PU + 'fcntl';

Blaise Thorn at 2/2/2014 10:11:03 PM -
> function fcntl

For the third time: I said "method declarations".
Those are not methods.

Chee Wee Chua at 2/2/2014 9:57:35 PM -
So, one rule for class/record/object declaration, and another rule for interface declarations?
I don't think so.

It's clearly a bug.

Blaise Thorn at 2/2/2014 10:07:28 PM -
> So, one rule for class/record/object declaration, and another rule for interface declarations?

And routines. Essentially, yes.

> It's clearly a bug.

I never said that it is not a problem.

Thus far, I have only said that
1) Your report is inadequate because you have completely misunderstood the issue.
2) It is a long-standing problem that even the RTL maintainers choose/have to work around.

Blaise Thorn at 2/3/2014 1:50:09 AM -
FTR, I like the new additions you have made to the report. At least they now somehow explain the relevance of interfaces in your steps.

However, your title and the first paragraph of the description continue to /grossly/ misrepresent the issue. They make it sound like the interfaces, their inheritance and implementation in classes is the actual culprit of the problem; whereas the only real issue is the accepted order of directives for methods in classes and records. (The fact that such order is accepted in interfaces and for routines is still a very important point, but it is just a point, not the problem itself.)

(Not to mention that you still call the errors "mysterious", yet you have been given an explanation what they mean.)

Tomohiro Takahashi at 2/3/2014 6:23:52 PM -
Is this issue a regression in Delphi XE5? What about previous versions of Delphi?

Tomohiro Takahashi at 4/21/2014 5:57:09 AM -
Chua-san
I have deleted your comment. sorry...
Anyway, I will check the internal status of this report...

Chee Wee Chua at 2/3/2014 7:53:25 PM -
Same issue in Delphi 2007, Tomohiro.

Tomohiro Takahashi at 4/22/2014 5:53:22 PM -
Chua-san
This is a comment from internal tracking system.
<<<<<<
"Reintroduce", "overload", "override", "virtual", "dynamic", and "message" directives in the method declaration must be specified at specific position.

Compiler accepts only the order of "overload; cdecl; " for method list in class declaration. Interface method list of interface declaration and global procedure accept any order.

ClassMethodDecl -> ClassMethodHeading ';'
                   [ REINTRODUCE ';' ]
                   [ OVERLOAD ';' ]
                   [ ( OVERRIDE | VIRTUAL | DYNAMIC | ( MESSAGE ConstExpr ) ) ';' ]
                   [ MethodDirectives ]
                   [ ( ABSTRACT | FINAL ) ';' ]

ObjectMethodDecl -> ObjectMethodHeading ';'
                    [ REINTRODUCE ';' ]
                    [ OVERLOAD ';' ]
                    [ ( OVERRIDE | VIRTUAL | DYNAMIC | ( MESSAGE ConstExpr ) ) ';' ]
                    [ MethodDirectives ]

RecordMethodDecl -> RecordMethodHeading ';'
                   [ REINTRODUCE ';' ]
                   [ OVERLOAD ';' ]
                   [ MethodDirectives ]

InterfaceMethodDecl -> ProcedureHeading ';' [ MethodDirectives ]
                    -> FunctionHeading ';' [ MethodDirectives ]
>>>>>>

Chee Wee Chua at 4/22/2014 9:13:19 PM -
Thanks for following up, Tomohiro-san.

Server Response from: ETNACODE01